diff --git a/simulators/c++2/src_simulator/arch/CPU.cpp b/simulators/c++2/src_simulator/arch/CPU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9b01711a3476827671b5c24bfdf60702ee57aa9 --- /dev/null +++ b/simulators/c++2/src_simulator/arch/CPU.cpp @@ -0,0 +1,214 @@ +/*Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Daniel Knorreck, + Ludovic Apvrille, Renaud Pacalet + * + * ludovic.apvrille AT telecom-paristech.fr + * + * This software is a computer program whose purpose is to allow the + * edition of TURTLE analysis, design and deployment diagrams, to + * allow the generation of RT-LOTOS or Java code from this diagram, + * and at last to allow the analysis of formal validation traces + * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP + * from INRIA Rhone-Alpes. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + * + */ + +#include <CPU.h> +class TMLTask; +class TMLTransaction; + +double CPU::averageLoad (unsigned int n) const{ + double _averageLoad=0; + TMLTime _maxEndTime=0; + for( TransactionList::const_iterator i = _transactList.begin(); i != _transactList.end(); ++i ) { + if( (*i)->getTransactCoreNumber() == n ){ + TMLTime _endTime= (*i)->getEndTime(); + _maxEndTime=max(_maxEndTime,_endTime); + } + } + std::cout<<"max end time is "<<_maxEndTime<<std::endl; + for( TransactionList::const_iterator i = _transactList.begin(); i != _transactList.end(); ++i ) { + if( (*i)->getTransactCoreNumber() == n ){ + _averageLoad += (*i)->getEndTime() - (*i)->getStartTime(); + } + } + if(_maxEndTime == 0) + return 0; + else { + _averageLoad = (double)_averageLoad/_maxEndTime; + return _averageLoad; + } + /*if( _maxEndTime == 0 ) + myfile << "average load is 0" << "<br>"; + else + myfile<<" average load is "<<(double)_averageLoad/_maxEndTime<<"<br>";*/ + +} + + +void CPU::drawPieChart(std::ofstream& myfile) const { + + TMLTime _maxEndTime=0; + for(unsigned int j = 0; j < amountOfCore ; ++j){ + for( TransactionList::const_iterator i = _transactList.begin(); i != _transactList.end(); ++i ) { + if( (*i)->getTransactCoreNumber() == j ){ + TMLTime _endTime= (*i)->getEndTime(); + _maxEndTime=max(_maxEndTime,_endTime); + } + } + std::map <TMLTask*, double > transPercentage; + for( TransactionList::const_iterator i = _transactList.begin(); i!= _transactList.end(); ++i){ + if( (*i)->getTransactCoreNumber() == j ){ + transPercentage[(*i)-> getCommand()->getTask()]+=(double)((*i)->getEndTime()-(*i)->getStartTime())/_maxEndTime; + } + } + std::map <TMLTask*, double>::iterator iter = transPercentage.begin(); + myfile << " var chart" << _ID << "_" << j << "= new CanvasJS.Chart(\"chartContainer" << _ID << "_" << j <<"\"," << std::endl; + myfile << SCHED_HTML_JS_CONTENT2 << "Average load is " << averageLoad(j) << SCHED_HTML_JS_CONTENT3 << std::endl; + double idle=1; + while( iter != transPercentage.end()){ + myfile << " { y:" << (iter->second)*100 << ", indexLabel: \"" << iter->first->toString() << "\" }," << std::endl; + idle-=iter->second; + ++iter; + } + myfile << " { y:" << idle*100 << ", indexLabel: \"idle time\"" << " }" << std::endl; + myfile << std::endl; + myfile << SCHED_HTML_PIE_END; + myfile << "chart" << _ID << "_" << j << ".render();" << std::endl; + } + +} + +void CPU::showPieChart(std::ofstream& myfile) const{ + myfile << SCHED_HTML_JS_DIV_ID << _ID << "_" << this->_cycleTime << SCHED_HTML_JS_DIV_END << "<br>"; +} + + + +void CPU::schedule2HTML(std::ofstream& myfile) const { + myfile << "<h2><span>Scheduling for device: "<< _name <<"_core_"<<this->_cycleTime<< "</span></h2>" << std::endl; + + if ( _transactList.size() == 0 ) { + myfile << "<h4>Device never activated</h4>" << std::endl; + } + else { + myfile << "<table>" << std::endl << "<tr>"; + + std::map<TMLTask*, std::string> taskCellClasses; + unsigned int nextCellClassIndex = 0; + TMLTime aCurrTime = 0; + + for( TransactionList::const_iterator i = _transactList.begin(); i != _transactList.end(); ++i ) { + std::cout<<"get transaction core number is: "<<(*i)->getTransactCoreNumber()<<std::endl; + std::cout<<"time : "<<_cycleTime<<std::endl; + //std::cout << "CPU:calcSTL: html of CPU " << _name << ": " << (*i)->toString() << std::endl; + if( (*i)->getTransactCoreNumber() == this->_cycleTime ){ + TMLTransaction* aCurrTrans = *i; + unsigned int aBlanks = aCurrTrans->getStartTime() - aCurrTime; + + if ( aBlanks > 0 ) { + writeHTMLColumn( myfile, aBlanks, "not", "idle time" ); + } + + unsigned int aLength = aCurrTrans->getPenalties(); + + if ( aLength != 0 ) { + std::ostringstream title; + title << "idle:" << aCurrTrans->getIdlePenalty() << " switch:" << aCurrTrans->getTaskSwitchingPenalty(); + writeHTMLColumn( myfile, aLength, "not", title.str() ); + } + + aLength = aCurrTrans->getOperationLength(); + + // Issue #4 + TMLTask* task = aCurrTrans->getCommand()->getTask(); + const std::string cellClass = determineHTMLCellClass( taskCellClasses, task, nextCellClassIndex ); + + writeHTMLColumn( myfile, aLength, cellClass, aCurrTrans->toShortString() ); + + aCurrTime = aCurrTrans->getEndTime(); + } + } + + + myfile << "</tr>" << std::endl << "<tr>"; + + for ( unsigned int aLength = 0; aLength < aCurrTime; aLength++ ) { + myfile << "<th></th>"; + } + + myfile << "</tr>" << std::endl << "<tr>"; + + for ( unsigned int aLength = 0; aLength <= aCurrTime; aLength += 5 ) { + std::ostringstream spanVal; + spanVal << aLength; + writeHTMLColumn( myfile, 5, "sc", "", spanVal.str(), false ); + //myfile << "<td colspan=\"5\" class=\"sc\">" << aLength << "</td>"; + } + + myfile << "</tr>" << std::endl << "</table>" << std::endl << "<table>" << std::endl << "<tr>"; + + for( std::map<TMLTask*, std::string>::iterator taskColIt = taskCellClasses.begin(); taskColIt != taskCellClasses.end(); ++taskColIt ) { + TMLTask* task = (*taskColIt).first; + // Unset the default td max-width of 5px. For some reason setting the max-with on a specific t style does not work + myfile << "<td class=\"" << taskCellClasses[ task ] << "\"></td><td style=\"max-width: unset;\">" << task->toString() << "</td><td class=\"space\"></td>"; + } + + myfile << "</tr>" << std::endl; + +#ifdef ADD_COMMENTS + bool aMoreComments = true, aInit = true; + Comment* aComment; + + while ( aMoreComments ) { + aMoreComments = false; + myfile << "<tr>"; + + for( std::map<TMLTask*, std::string>::iterator taskColIt = taskCellClasses.begin(); taskColIt != taskCellClasses.end(); ++taskColIt ) { + //for(TaskList::const_iterator j=_taskList.begin(); j != _taskList.end(); ++j){ + TMLTask* task = (*taskColIt).first; + std::string aCommentString = task->getNextComment( aInit, aComment ); + + if ( aComment == 0 ) { + myfile << "<td></td><td></td><td class=\"space\"></td>"; + } + else { + replaceAll(aCommentString,"<","<"); + replaceAll(aCommentString,">",">"); + aMoreComments = true; + myfile << "<td style=\"max-width: unset;\">" << aComment->_time << "</td><td><pre>" << aCommentString << "</pre></td><td class=\"space\"></td>"; + } + } + + aInit = false; + myfile << "</tr>" << std::endl; + } +#endif + myfile << "</table>" << std::endl; + } +} diff --git a/simulators/c++2/src_simulator/arch/FPGA.cpp b/simulators/c++2/src_simulator/arch/FPGA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f37d5ffcb7258a6278c4b88912ee351338bded9a --- /dev/null +++ b/simulators/c++2/src_simulator/arch/FPGA.cpp @@ -0,0 +1,437 @@ +/*Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Niu Siyuan, + Ludovic Apvrille, Renaud Pacalet + * + * ludovic.apvrille AT telecom-paristech.fr + * + * This software is a computer program whose purpose is to allow the + * edition of TURTLE analysis, design and deployment diagrams, to + * allow the generation of RT-LOTOS or Java code from this diagram, + * and at last to allow the analysis of formal validation traces + * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP + * from INRIA Rhone-Alpes. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + * + */ + +#include <FPGA.h> +#include <TMLTask.h> +#include <TMLCommand.h> +#include <TMLTransaction.h> +#include <Bus.h> +#include <Slave.h> +#include <TMLChannel.h> + + +FPGA::FPGA( ID iID, + std::string iName, + WorkloadSource* iScheduler, + TMLTime iTimePerCycle, + TMLTime iReconfigTime, + unsigned int iChangeIdleModeCycles, + unsigned int iCyclesBeforeIdle, + unsigned int iCyclesPerExeci, + unsigned int iCyclesPerExecc ) : SchedulableDevice(iID, iName, iScheduler) + ,_timePerCycle(iTimePerCycle) + ,_reconfigTime(iReconfigTime) + ,_lastTransaction(0) +#ifdef PENALTIES_ENABLED + ,_changeIdleModeCycles(iChangeIdleModeCycles), _cyclesBeforeIdle(iCyclesBeforeIdle) +#endif +#ifdef PENALTIES_ENABLED + , _timePerExeci(_cyclesPerExeci * _timePerCycle /100.0) + , _timeBeforeIdle(_cyclesBeforeIdle*_timePerCycle) + , _changeIdleModeTime(_changeIdleModeCycles*_timePerCycle) +#else + , _timePerExeci(_cyclesPerExeci*_timePerCycle) +#endif +{} + +FPGA::~FPGA(){} + + +void FPGA::streamBenchmarks(std::ostream& s) const{ + std::cout<<"test fpga stramBenchmarks"<<std::endl; + s << TAG_FPGAo << " id=\"" << _ID << "\" name=\"" << _name << "\">" << std::endl; + if (_simulatedTime!=0) s << TAG_UTILo << (static_cast<float>(_busyCycles)/static_cast<float>(_simulatedTime)) << TAG_UTILc; + s << TAG_ENERGYo << ( (_simulatedTime/_timePerCycle)*_static_consumPerCycle) + ((_busyCycles/_timePerCycle)*_dynamic_consumPerCycle) << TAG_ENERGYc; + std::cout<< "power consumption "<< ((_simulatedTime/_timePerCycle)*_static_consumPerCycle) + ((_busyCycles/_timePerCycle)*_dynamic_consumPerCycle)<< std::endl; + for(BusMasterList::const_iterator i=_busMasterList.begin(); i != _busMasterList.end(); ++i) (*i)->streamBenchmarks(s); + s << TAG_FPGAc; +} + + + +TMLTransaction* FPGA::getNextTransaction(){ +std::cout<<"fpga getNextTransaction"<<std::endl; +#ifdef BUS_ENABLE + if(_masterNextTransaction==0 || _nextTransaction==0){ + return _nextTransaction; + } + else{ + BusMaster* aTempMaster = getMasterForBus(_nextTransaction->getChannel()->getFirstMaster(_nextTransaction)); + bool aResult = aTempMaster->accessGranted(); + + while (aResult && aTempMaster!=_masterNextTransaction){ + + aTempMaster =_nextTransaction->getChannel()->getNextMaster(_nextTransaction); + + aResult = aTempMaster->accessGranted(); + + } + return (aResult)?_nextTransaction:0; + } +#else + return _nextTransaction; +#endif + } + +void FPGA::calcStartTimeLength(TMLTime iTimeSlice){ +std::cout<<"fpga calStartTimeLength"<<std::endl; + +#ifdef BUS_ENABLED + + std::cout << "FPGA:calcSTL: scheduling decision of FPGA " << _name << ": " << _nextTransaction->toString() << std::endl; + std::cout << "get channel " << std::endl; + TMLChannel* aChannel=_nextTransaction->getCommand()->getChannel(0); + std::cout << "after get channel " << std::endl; + if (aChannel==0) { + std::cout<<"test111"<<std::endl; + //std::cout << "no channel " << std::endl; + _masterNextTransaction=0; + } else { + std::cout << "get bus " << std::endl; + _masterNextTransaction= getMasterForBus(aChannel->getFirstMaster(_nextTransaction)); + if (_masterNextTransaction!=0){ + std::cout << "before register transaction at bus " << _masterNextTransaction->toString() << std::endl; + _masterNextTransaction->registerTransaction(_nextTransaction); + std::cout << "Transaction registered at bus " << _masterNextTransaction->toString() << std::endl; + } else { + std::cout << " NO MASTER NEXT TRANSACTION " << std::endl; + } + } +#endif + std::cout<<"test222"<<std::endl; + //round to full cycles!!! + std::cout<<"time per cycle is "<<_timePerCycle<<std::endl; + std::cout<<"test333"<<std::endl; + TMLTime aStartTime = _nextTransaction->getRunnableTime(); + TMLTime aReminder = aStartTime % _timePerCycle; + if (aReminder!=0) aStartTime+=_timePerCycle - aReminder; + std::cout << "FPGA: set start time in FPGA=" << aStartTime << " Reminder=" << aReminder <<"\n"; + + _nextTransaction->setStartTime(aStartTime); + +#ifdef BUS_ENABLED + if (_masterNextTransaction==0){ +#endif + //calculate length of transaction + //if (_nextTransaction->getOperationLength()!=-1){ + std::cout<<"at first virtual length "<<_nextTransaction->getVirtualLength()<<std::endl; + std::cout<<"another "<<(TMLLength)(iTimeSlice /_timePerExeci)<<std::endl; + if (iTimeSlice!=0){ + _nextTransaction->setVirtualLength(max(min(_nextTransaction->getVirtualLength(), (TMLLength)(iTimeSlice /_timePerExeci)), (TMLTime)1)); + } + _nextTransaction->setLength(_nextTransaction->getVirtualLength()*_timePerExeci); + std::cout<<"!!!!!virtual length is "<<_nextTransaction->getVirtualLength()<<std::endl; +#ifdef BUS_ENABLED + } +#endif +#ifdef PENALTIES_ENABLED + //std::cout << "starttime=" << _nextTransaction->getStartTime() << "\n"; + if ((_nextTransaction->getStartTime()-_endSchedule) >=_timeBeforeIdle){ + _nextTransaction->setIdlePenalty(_changeIdleModeTime); + } +#endif +} + +void FPGA::truncateAndAddNextTransAt(TMLTime iTime){ +std::cout<<"fpga truncateAndAddNextTransAt"<<std::endl; + //std::cout << "CPU:schedule BEGIN " << _name << "+++++++++++++++++++++++++++++++++\n"; + //return truncateNextTransAt(iTime); + //not a problem if scheduling does not take place at time when transaction is actually truncated, tested + //std::cout << "CPU:truncateAndAddNextTransAt " << _name << "time: +++++++++++++++++++++" << iTime << "\n"; + TMLTime aTimeSlice = _scheduler->schedule(iTime); + //_schedulingNeeded=false; 05/05/11 + TMLTransaction* aNewTransaction =_scheduler->getNextTransaction(iTime); + //std::cout << "before if\n"; + + //_scheduler->transWasScheduled(this); //NEW was in if before 05/05/11 + + if (aNewTransaction!=_nextTransaction){ + //std::cout << "in if\n"; + if (truncateNextTransAt(iTime)!=0) addTransaction(0); + //if (_nextTransaction!=0 && truncateNextTransAt(iTime)!=0) addTransaction(); //NEW!!!! + if (_nextTransaction!=0 && _masterNextTransaction!=0) _masterNextTransaction->registerTransaction(0); + _nextTransaction = aNewTransaction; + if (_nextTransaction!=0) calcStartTimeLength(aTimeSlice); + } + //std::cout << "CPU:schedule END " << _name << "+++++++++++++++++++++++++++++++++\n"; +} + +TMLTime FPGA::truncateNextTransAt(TMLTime iTime){ +std::cout<<"fpga truncateNextTransAt"<<std::endl; + if (_masterNextTransaction==0){ +#ifdef PENALTIES_ENABLED + + //std::cout << "CPU:nt.startTime: " << _nextTransaction->getStartTime() << std::endl; + if (iTime < _nextTransaction->getStartTime()) { + return 0; + } + + TMLTime aNewDuration = iTime - _nextTransaction->getStartTime(); + TMLTime aStaticPenalty = _nextTransaction->getIdlePenalty() + _nextTransaction->getTaskSwitchingPenalty(); + if (aNewDuration<=aStaticPenalty){ + _nextTransaction->setLength(_timePerExeci); + _nextTransaction->setVirtualLength(1); + + } else{ + aNewDuration-=aStaticPenalty; + _nextTransaction->setVirtualLength(max((TMLTime)(aNewDuration /_timePerExeci),(TMLTime)1)); + _nextTransaction->setLength(_nextTransaction->getVirtualLength() *_timePerExeci); + } +#else + if (iTime <= _nextTransaction->getStartTime()) return 0; //before: <= + TMLTime aNewDuration = iTime - _nextTransaction->getStartTime(); + _nextTransaction->setVirtualLength(max((TMLTime)(aNewDuration /_timePerExeci), (TMLTime)1)); + _nextTransaction->setLength(_nextTransaction->getVirtualLength() *_timePerExeci); +#endif + } + return _nextTransaction->getOverallLength(); +} + + + +bool FPGA::addTransaction(TMLTransaction* iTransToBeAdded){ +std::cout<<"fpga addTransaction"<<std::endl; + bool aFinish; + std::cout << "*************** LOOKING for master of" << _nextTransaction->toString() << std::endl; + if (_masterNextTransaction==0){ + aFinish=true; + }else{ + BusMaster* aFollowingMaster =_nextTransaction->getChannel()->getNextMaster(_nextTransaction); + if (aFollowingMaster==0){ + std::cout << "1\n"; + aFinish=true; + BusMaster* aTempMaster = getMasterForBus(_nextTransaction->getChannel()->getFirstMaster(_nextTransaction)); + std::cout << "2\n"; + Slave* aTempSlave= _nextTransaction->getChannel()->getNextSlave(_nextTransaction); + std::cout << "3\n"; + aTempMaster->addBusContention(_nextTransaction->getStartTime()-max(_endSchedule,_nextTransaction->getRunnableTime())); + while (aTempMaster!=0){ + std::cout << "3a\n"; + aTempMaster->addTransaction(_nextTransaction); + std::cout << "3b\n"; + //if (aTempSlave!=0) aTempSlave->addTransaction(_nextTransaction); + if (aTempSlave!=0) aTempSlave->addTransaction(_nextTransaction); //NEW + std::cout << "4\n"; + aTempMaster =_nextTransaction->getChannel()->getNextMaster(_nextTransaction); + std::cout << "5\n"; + aTempSlave= _nextTransaction->getChannel()->getNextSlave(_nextTransaction); + } + std::cout << "6\n"; + } else { + std::cout << _name << " bus transaction next round" << std::endl; + _masterNextTransaction=aFollowingMaster; + std::cout << "7\n"; + _masterNextTransaction->registerTransaction(_nextTransaction); + aFinish=false; + } + //std::cout << "8\n"; + } + if (aFinish){ + _endSchedule=0; + _simulatedTime=max(_simulatedTime,_endSchedule); + _overallTransNo++; //NEW!!!!!!!! + _overallTransSize+=_nextTransaction->getOperationLength(); //NEW!!!!!!!! + //std::cout << "lets crash execute\n"; + _nextTransaction->getCommand()->execute(); //NEW!!!! + //std::cout << "not crashed\n"; +#ifdef TRANSLIST_ENABLED + _transactList.push_back(_nextTransaction); +#endif + _lastTransaction=_nextTransaction; + _busyCycles+=_nextTransaction->getOverallLength(); +#ifdef LISTENERS_ENABLED + NOTIFY_TRANS_EXECUTED(_nextTransaction); +#endif + _nextTransaction=0; + return true; + } else return false; +} + +void FPGA::schedule(){ + + std::cout << "fpga:schedule BEGIN " << _name << "+++++++++++++++++++++++++++++++++\n"; + + TMLTime aTimeSlice = _scheduler->schedule(_endSchedule); + + TMLTransaction* aOldTransaction = _nextTransaction; + _nextTransaction=_scheduler->getNextTransaction(_endSchedule); + + if (aOldTransaction!=0 && aOldTransaction!=_nextTransaction){ //NEW + + if (_masterNextTransaction!=0) { + _masterNextTransaction->registerTransaction(0); + + } + } + + if (_nextTransaction!=0 && aOldTransaction != _nextTransaction) calcStartTimeLength(aTimeSlice); + std::cout << "fpga:schedule END " << _name << "+++++++++++++++++++++++++++++++++\n"; +} + +void FPGA::getNextSignalChange(bool iInit, SignalChangeData* oSigData){ + if (iInit){ + + _posTrasactListVCD=_transactList.begin(); + std::cout<<"init "<<(*_posTrasactListVCD)->toShortString()<<std::endl; + _previousTransEndTime=0; + _vcdOutputState = END_IDLE_FPGA; + if (_posTrasactListVCD != _transactList.end() && (*_posTrasactListVCD)->getStartTime()!=0){ + new (oSigData) SignalChangeData(END_IDLE_FPGA, 0, this); + return; + } + } + + if (_posTrasactListVCD == _transactList.end()){ + std::cout<<"end trans"<<std::endl; + new (oSigData) SignalChangeData(END_IDLE_FPGA, _previousTransEndTime, this); + } + else{ + TMLTransaction* aCurrTrans=*_posTrasactListVCD; + std::cout<<"current trans is "<<aCurrTrans->toShortString()<<std::endl; + switch (_vcdOutputState){ + case END_TASK_FPGA: + std::cout<<"END_TASK_FPGA"<<std::endl; + do{ + _previousTransEndTime=(*_posTrasactListVCD)->getEndTime(); + _posTrasactListVCD++; + }while (_posTrasactListVCD != _transactList.end() && (*_posTrasactListVCD)->getStartTimeOperation()==_previousTransEndTime); + if (_posTrasactListVCD != _transactList.end() && (*_posTrasactListVCD)->getStartTime()==_previousTransEndTime){ + //outp << VCD_PREFIX << vcdValConvert(END_PENALTY_FPGA) << "FPGA" << _ID; + _vcdOutputState=END_PENALTY_FPGA; + std::cout<<"why???"<<std::endl; + new (oSigData) SignalChangeData(END_PENALTY_FPGA, _previousTransEndTime, this); + }else{ + //outp << VCD_PREFIX << vcdValConvert(END_IDLE_FPGA) << "FPGA" << _ID; + _vcdOutputState=END_IDLE_FPGA; + //if (_posTrasactListVCD == _transactList.end()) oNoMoreTrans=true; + new (oSigData) SignalChangeData(END_IDLE_FPGA, _previousTransEndTime, this); + } + //oSigChange=outp.str(); + //return _previousTransEndTime; + break; + case END_PENALTY_FPGA: + std::cout<<"END_PENALTY_FPGA"<<std::endl; + //outp << VCD_PREFIX << vcdValConvert(END_TASK_FPGA) << "FPGA" << _ID; + //oSigChange=outp.str(); + _vcdOutputState=END_TASK_FPGA; + //return aCurrTrans->getStartTimeOperation(); + new (oSigData) SignalChangeData(END_TASK_FPGA, aCurrTrans->getStartTimeOperation(), this); + break; + case END_IDLE_FPGA: + std::cout<<"END_IDLE_FPGA"<<std::endl; + if (aCurrTrans->getPenalties()==0){ + //outp << VCD_PREFIX << vcdValConvert(END_TASK_FPGA) << "FPGA" << _ID; + _vcdOutputState=END_TASK_FPGA; + new (oSigData) SignalChangeData(END_TASK_FPGA, aCurrTrans->getStartTime(), this); + }else{ + //outp << VCD_PREFIX << vcdValConvert(END_PENALTY_FPGA) << "FPGA" << _ID; + _vcdOutputState=END_PENALTY_FPGA; + new (oSigData) SignalChangeData(END_PENALTY_FPGA, aCurrTrans->getStartTime(), this); + } + //oSigChange=outp.str(); + //return aCurrTrans->getStartTime(); + break; + } + + } + //return 0; +} + + +std::string FPGA::toShortString() const{ + std::ostringstream outp; + outp << "fpga" << _ID; + return outp.str(); +} + +void FPGA::schedule2TXT(std::ofstream& myfile) const{ + myfile << "========= Scheduling for device: "<< _name << " =========\n" ; + for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){ + std::cout<<"my transaction================================="<<std::endl; + myfile << (*i)->toShortString() << std::endl; + } + std::cout<<"txt end========================"<<std::endl; +} + +BusMaster* FPGA::getMasterForBus(BusMaster* iDummy){ + if (iDummy!=0){ + SchedulableCommDevice* aBus = iDummy->getBus(); + for(BusMasterList::iterator i=_busMasterList.begin(); i != _busMasterList.end(); ++i){ + if ((*i)->getBus()==aBus) return *i; + } + std::cout << "cry!!!!!!!!!!!!! no bus master found\n"; + exit(1); + } + return 0; +} + +int FPGA::allTrans2XML(std::ostringstream& glob, int maxNbOfTrans) const { + int size = _transactList.size(); + int begining = size - maxNbOfTrans; + if (begining <0) { + begining = 0; + } + int cpt =0; + int total = 0; + for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){ + if (cpt >= begining) { + (*i)->toXML(glob, 0, _name); + total ++; + } + cpt ++; + } + return total; +} + + +void FPGA::latencies2XML(std::ostringstream& glob, unsigned int id1, unsigned int id2) { + for(TransactionList::const_iterator i=_transactList.begin(); i != _transactList.end(); ++i){ + if ((*i)->getCommand() !=NULL){ + if ((*i)->getCommand()->getID() == id1 || (*i)->getCommand()->getID() == id2){ + (*i)->toXML(glob, 0, _name); + } + } + } + + return; +} + + + diff --git a/simulators/c++2/src_simulator/arch/FPGA.h b/simulators/c++2/src_simulator/arch/FPGA.h new file mode 100644 index 0000000000000000000000000000000000000000..e7aa72e06db2c45d7bda7e23c44175855034460a --- /dev/null +++ b/simulators/c++2/src_simulator/arch/FPGA.h @@ -0,0 +1,204 @@ +/*Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Niu Siyuan, +Ludovic Apvrille, Renaud Pacalet + * + * ludovic.apvrille AT telecom-paristech.fr + * + * This software is a computer program whose purpose is to allow the + * edition of TURTLE analysis, design and deployment diagrams, to + * allow the generation of RT-LOTOS or Java code from this diagram, + * and at last to allow the analysis of formal validation traces + * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP + * from INRIA Rhone-Alpes. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + * + */ + +#ifndef FPGA_H +#define FPGA_H + + +#include <definitions.h> +#include <SchedulableDevice.h> +#include <SchedulableCommDevice.h> +#include <TraceableDevice.h> +#include <BusMaster.h> +#include <WorkloadSource.h> +#include <TMLTask.h> +#include <TMLCommand.h> + +class TMLTask; +class TMLTransaction; +class Bus; + +enum vcdFPGAVisState + { + END_IDLE_FPGA, + END_PENALTY_FPGA, + END_TASK_FPGA +}; + + +///Simulates the bahavior of a FPGA shared by several master devices +class FPGA: public SchedulableDevice, public TraceableDevice { +public: +///Constructor + /** + \param iID ID of the device + \param iName Name of the device + \param iScheduler Pointer to the scheduler object + \param iTimePerCycle 1/Processor frequency + \param iMapCapacity Pointer to the overall mapping capacity ???? + \param iMapPenalty Pointer to the mapping penalty ???? + \param iReconfigTime reconfiguration time + \param iChangeIdleModeCycles Cycles needed to switch into indle mode + \param iCyclesBeforeIdle Pointer to the max consecutive cycles before idle in cycle + \param iCyclesPerExeci Cycles needed to execute one EXECI unit + \param iCyclesPerExecc Cycles needed to execute one EXECC unit + */ + + FPGA(ID iID, std::string iName, WorkloadSource* iScheduler, TMLTime iTimePerCycle, TMLTime iReconfigTime, unsigned int iChangeIdleModeCycles, unsigned int iCyclesBeforeIdle,unsigned int iCyclesPerExeci, unsigned int iCyclesPerExecc); + ///Destructor + virtual ~FPGA(); + ///Determines the next FPGA transaction to be executed + virtual void schedule(); + ///Adds the transaction determined by the scheduling algorithm to the internal list of scheduled transactions + virtual bool addTransaction(TMLTransaction* iTransToBeAdded); + void truncateAndAddNextTransAt(TMLTime iTime); + ///Returns a pointer to the transaction determined by the scheduling algorithm + /** + \return Pointer to transaction + */ + TMLTransaction* getNextTransaction(); + void getNextSignalChange(bool iInit, SignalChangeData* oSigData); + ///Returns a short string representation of the transaction + /** + \return Short string representation + */ + std::string toShortString() const; + inline std::string toString() const {return _name;} + ///Writes a plain text representation of the schedule to an output file + /** + \param myfile Reference to the ofstream object representing the output file + */ + void schedule2TXT(std::ofstream& myfile) const; + + /** + \param glob refers to the output stream + */ + int allTrans2XML(std::ostringstream& glob, int maxNbOfTrans) const; + void latencies2XML(std::ostringstream& glob, unsigned int id1, unsigned int id2); + //virtual TMLTime truncateNextTransAt(TMLTime iTime)=0; + ///Adds a new bus master to the internal list + /** + \param iMaster Pointer to bus master + */ + virtual void streamBenchmarks(std::ostream& s) const; + inline void streamStateXML(std::ostream& s) const {streamBenchmarks(s);} + virtual void addBusMaster(BusMaster* iMaster){ + _busMasterList.push_back(iMaster); + } + ///Stores a new task in the internal task list + /** + \param iTask Pointer to the task to add + */ + virtual void registerTask(TMLTask* iTask){ + _taskList.push_back(iTask); + if (_scheduler!=0) _scheduler->addWorkloadSource(iTask); + } +protected: + ///List of all tasks running on the FPGA + TaskList _taskList; + + /** + \param iTime Indicates at what time the transaction should be truncated + */ + TMLTime truncateNextTransAt(TMLTime iTime); + ///Calculates the start time and the length of the next transaction + /** + \param iTimeSlice FPGA Time slice granted by the scheduler + */ + void calcStartTimeLength(TMLTime iTimeSlice); + ///1/Processor frequency + TMLTime _timePerCycle; + + TMLTime _reconfigTime; + + ///Determines the correct bus master of this CPU connected to the same bus as bus master iDummy + /** + \param iDummy Dummy Bus Master + */ + BusMaster* getMasterForBus(BusMaster* iDummy); + ///Pointer to the bus which will be accessed by the next transaction + BusMaster* _masterNextTransaction; + ///Pointer to the last transaction which has been executed + TMLTransaction* _lastTransaction; + ///List of bus masters + BusMasterList _busMasterList; +#ifdef PENALTIES_ENABLED + ///Cycles needed to switch to idle mode + unsigned int _changeIdleModeCycles; + ///Idle cycles which elapse before entering idle mode + unsigned int _cyclesBeforeIdle; +#endif + ///Cycles needed to execute one execi unit + unsigned int _cyclesPerExeci; + ///Time needed to execute one execi unit + float _timePerExeci; +#ifdef PENALTIES_ENABLED + ///Idle time which elapses before entering idle mode + TMLTime _timeBeforeIdle; + ///Time needed to switch into idle mode + TMLTime _changeIdleModeTime; +#endif + ///State variable for the VCD output + vcdFPGAVisState _vcdOutputState; +}; + +#endif + + + + + + + + + + + + + + + + + + + + + +