split_trans_bus.cc

00001 
00002 #include "sim/builder.hh"
00003 #include "split_trans_bus.hh"
00004 
00005 using namespace std;
00006 
00007 void
00008 SplitTransBus::request(Tick time, int fromID){
00009     
00010     requests++;
00011     
00012     assert(fromID >= 0);
00013     
00014     // keep linked list of requests sorted at all times
00015     // first request takes priority over later requests at same cycle
00016     InterconnectRequest* newReq = new InterconnectRequest(time, fromID);
00017     if(pipelined){
00018         if(allInterfaces[fromID]->isMaster()){
00019             addToList(&requestQueue, newReq);
00020         }
00021         else{
00022             addToList(slaveRequestQueue, newReq);
00023         }
00024     }
00025     else{
00026         addToList(&requestQueue, newReq);
00027     }
00028 
00029     
00030 #ifdef DEBUG_SPLIT_TRANS_BUS
00031     checkIfSorted(&requestQueue);
00032     if(pipelined) checkIfSorted(slaveRequestQueue);
00033 #endif //DEBUG_SPLIT_TRANS_BUS
00034     
00035     if(!blocked){
00036         
00037         if(!pipelined){
00038             if(arbitrationEvents.empty()){
00039                 scheduleArbitrationEvent(time + arbitrationDelay);
00040             }
00041             else{
00042                 Tick nextArbCycle = TICK_T_MAX;
00043                 int hitIndex = -1;
00044                 for(int i=0;i<arbitrationEvents.size();i++){
00045                     if(arbitrationEvents[i]->when() < nextArbCycle){
00046                         nextArbCycle = arbitrationEvents[i]->when();
00047                         hitIndex = i;
00048                     }
00049                 }
00050                 assert(nextArbCycle < TICK_T_MAX);
00051                 
00052                 if(nextArbCycle > (time + arbitrationDelay)){
00053                     /* the arbitration events are out of synch */
00054                     for(int i=0;i<arbitrationEvents.size();i++){
00055                         if(arbitrationEvents[i]->scheduled()){
00056                             arbitrationEvents[i]->deschedule();
00057                         }
00058                         delete arbitrationEvents[i];
00059                     }
00060                     arbitrationEvents.clear();
00061                     
00062                     scheduleArbitrationEvent(time + arbitrationDelay);
00063                 }
00064     
00065             }
00066         }
00067         else{
00068             scheduleArbitrationEvent(time + arbitrationDelay);
00069         }
00070     }
00071 }
00072 
00073 void
00074 SplitTransBus::addToList(std::list<InterconnectRequest*>* inList,
00075                          InterconnectRequest* icReq){
00076     
00077     list<InterconnectRequest*>::iterator findPos;
00078     for(findPos=inList->begin();
00079         findPos!=inList->end();
00080         findPos++){
00081             InterconnectRequest* tempReq = *findPos;
00082             if(icReq->time < tempReq->time) break;
00083         }
00084 
00085     inList->insert(findPos, icReq);
00086 }
00087 
00088 void
00089 SplitTransBus::scheduleArbitrationEvent(Tick possibleArbCycle){
00090     
00091     assert(!blocked);
00092     
00093     bool addArbCycle = true;
00094     for(int i=0;i<arbitrationEvents.size();++i){
00095         if(arbitrationEvents[i]->when() == possibleArbCycle){
00096             addArbCycle = false;
00097         }
00098     }
00099     
00100     if(addArbCycle){
00101         InterconnectArbitrationEvent* event = 
00102                 new InterconnectArbitrationEvent(this);
00103         event->schedule(possibleArbCycle);
00104         arbitrationEvents.push_back(event);
00105     }
00106 }
00107 
00108 void
00109 SplitTransBus::arbitrate(Tick cycle){
00110     
00111     assert(!blocked);
00112     if(pipelined) assert(!requestQueue.empty() || !slaveRequestQueue->empty());
00113     else assert(!requestQueue.empty());
00114     
00115     if(pipelined){
00116         grantInterface(STB_SLAVE, cycle);
00117         grantInterface(STB_MASTER, cycle);
00118     }
00119     else{
00120         grantInterface(STB_NOT_PIPELINED, cycle);
00121     }
00122     
00123     
00124     if(!requestQueue.empty()){
00125         Tick nextReqTime = requestQueue.front()->time;
00126     
00127         if(pipelined){
00128             if(nextReqTime <= (cycle - arbitrationDelay)){
00129                 scheduleArbitrationEvent(cycle + 1);
00130             }
00131             else{
00132                 scheduleArbitrationEvent(nextReqTime + arbitrationDelay);
00133             }
00134         }
00135         else{
00136             if(nextReqTime <= cycle){
00137                 scheduleArbitrationEvent(cycle + arbitrationDelay);
00138             }
00139             else{
00140                 scheduleArbitrationEvent(nextReqTime + arbitrationDelay);
00141             }
00142         }
00143     }
00144     
00145     if(pipelined){
00146         if(!slaveRequestQueue->empty()){
00147             Tick nextReqTime = slaveRequestQueue->front()->time;
00148         
00149             if(nextReqTime <= (cycle - arbitrationDelay)){
00150                 scheduleArbitrationEvent(cycle + 1);
00151             }
00152             else{
00153                 scheduleArbitrationEvent(nextReqTime + arbitrationDelay);
00154             }
00155         }
00156     }
00157 }
00158 
00159 void
00160 SplitTransBus::grantInterface(grant_type gt, Tick cycle){
00161     
00162     Tick goodReqTime = cycle - arbitrationDelay;
00163     InterconnectRequest* grantReq;
00164     
00165     /* remove the request from the correct queue */
00166     switch(gt){
00167         case STB_NOT_PIPELINED:
00168             grantReq = requestQueue.front();
00169             requestQueue.pop_front();
00170             break;
00171         
00172         case STB_MASTER:
00173             if(requestQueue.empty()) return;
00174             grantReq = requestQueue.front();
00175             
00176             /* check if requests are available */
00177             if(grantReq->time > goodReqTime) return;
00178             requestQueue.pop_front();
00179             break;
00180             
00181         case STB_SLAVE:
00182             if(slaveRequestQueue->empty()) return;
00183             grantReq = slaveRequestQueue->front();
00184             
00185             /* check if requests are available */
00186             if(grantReq->time > goodReqTime) return;
00187             slaveRequestQueue->pop_front();
00188             break;
00189             
00190         default:
00191             fatal("Unknown grant_type encountered");
00192             
00193     }
00194     
00195     /* grant access */
00196     allInterfaces[grantReq->fromID]->grantData();
00197     
00198     /* update statistics */
00199     arbitratedRequests++;
00200     totalArbQueueCycles += ((cycle - grantReq->time) - arbitrationDelay);
00201     totalArbitrationCycles += arbitrationDelay;
00202     
00203     delete grantReq;
00204 }
00205 
00206 
00207 void 
00208 SplitTransBus::send(MemReqPtr& req, Tick time, int fromID){
00209     
00210     assert(!blocked);
00211     assert((req->size / width) <= 1);
00212     
00213     bool isFromMaster = false;
00214     if(allInterfaces[fromID]->isMaster()) isFromMaster = true;
00215     
00216     if(req->toInterfaceID != -1){
00217         // L1 to L1 request
00218         deliverQueue.push_back(
00219                 new InterconnectDelivery(time, 
00220                                          fromID,
00221                                          req->toInterfaceID,
00222                                          req));
00223     }
00224     else if(isFromMaster){
00225         // Try all slaves and check if they can supply the needed data
00226         int successCount = 0;
00227         int toID = -1;
00228         for(int i=0;i<allInterfaces.size();++i){
00229 
00230             if(allInterfaces[i]->isMaster()) continue;
00231             
00232             if(allInterfaces[i]->inRange(req->paddr)){
00233                 successCount++;
00234                 toID = i;
00235             }
00236         }
00237         
00238         if(successCount == 0){
00239             fatal("No supplier for data on SplitTransBus");
00240         }
00241         if(successCount > 1){
00242             fatal("More than one supplier for data on SplitTransBus");
00243         }
00244         
00245         /* deliver to L2 cache */
00246         deliverQueue.push_back(
00247                 new InterconnectDelivery(time, fromID, toID, req));
00248     }
00249     else{
00250         /* deliver to L1 cache */
00251         deliverQueue.push_back(
00252                 new InterconnectDelivery(time,
00253                                          fromID,
00254                                          req->fromInterfaceID,
00255                                          req));
00256     }
00257     
00258 #ifdef DEBUG_SPLIT_TRANS_BUS
00259     /* check that the queue is sorted */
00260     InterconnectDelivery* prev = NULL;
00261     bool first = true;
00262     for(list<InterconnectDelivery*>::iterator i=deliverQueue.begin();
00263         i!=deliverQueue.end();
00264         i++){
00265             if(first){
00266                 first = false;
00267                 prev = *i;
00268                 continue;
00269             }
00270             
00271             assert(prev->grantTime <= (*i)->grantTime);
00272             prev = *i;
00273         }
00274 #endif //DEBUG_SPLIT_TRANS_BUS
00275     
00276     if(doProfile) useCycleSample += transferDelay;
00277         
00278     scheduleDeliverEvent(time + transferDelay);
00279 }
00280 
00281 void
00282 SplitTransBus::scheduleDeliverEvent(Tick possibleArbCycle){
00283     
00284     bool addEvent = true;
00285     for(int i=0;i < deliverEvents.size();i++){
00286         if(deliverEvents[i]->when() == possibleArbCycle){
00287             addEvent = false;
00288         }
00289     }
00290     
00291     if(addEvent){
00292         
00293         InterconnectDeliverQueueEvent* event = 
00294                 new InterconnectDeliverQueueEvent(this);
00295         event->schedule(possibleArbCycle);
00296         deliverEvents.push_back(event);
00297     }
00298 }
00299 
00300 
00301 void
00302 SplitTransBus::deliver(MemReqPtr& req, Tick cycle, int toID, int fromID){
00303 
00304     assert(!blocked);
00305     assert(!deliverQueue.empty());
00306     
00307     InterconnectDelivery* delivery = deliverQueue.front();
00308     deliverQueue.pop_front();
00309     
00310     /* update statistics */
00311     sentRequests++;
00312     int queueTime = (cycle - delivery->grantTime) - transferDelay;
00313     totalTransQueueCycles += queueTime;
00314     totalTransferCycles += transferDelay;
00315     
00316     int curCpuId = delivery->req->xc->cpu->params->cpu_id;
00317     perCpuTotalTransQueueCycles[curCpuId] += queueTime;
00318     perCpuTotalTransferCycles[curCpuId] += transferDelay;
00319     
00320     int retval = BA_NO_RESULT;
00321     assert(delivery->toID > -1);
00322     if(allInterfaces[delivery->toID]->isMaster()){
00323         allInterfaces[delivery->toID]->deliver(delivery->req);
00324     }
00325     else{
00326         retval = allInterfaces[delivery->toID]->access(delivery->req);
00327     }
00328     
00329     delete delivery;
00330     
00331     if(retval != BA_BLOCKED){
00332         /* see if we need to schedule another delivery */
00333         if(!deliverQueue.empty()){
00334             InterconnectDelivery* nextDelivery = deliverQueue.front();
00335             if(nextDelivery->grantTime <= (cycle - transferDelay)){
00336                 if(pipelined) scheduleDeliverEvent(cycle + 1); 
00337                 else scheduleDeliverEvent(cycle + transferDelay);
00338             }
00339             else{
00340                 scheduleDeliverEvent(nextDelivery->grantTime + transferDelay);
00341             }
00342         }
00343     }
00344 }
00345 
00346 void
00347 SplitTransBus::setBlocked(int fromInterface){
00348     
00349     if(blocked) warn("SplitTransBus blocking on a second cause");
00350     
00351     blocked = true;
00352     numSetBlocked++;
00353     waitingFor = fromInterface;
00354     
00355     /* remove all scheduled arbitration events */
00356     for(int i=0;i<arbitrationEvents.size();++i){
00357         if (arbitrationEvents[i]->scheduled()) {
00358             arbitrationEvents[i]->deschedule();
00359         }
00360         delete arbitrationEvents[i];
00361     }
00362     arbitrationEvents.clear();
00363     
00364     /* remove all deliver events */
00365     for(int i=0;i<deliverEvents.size();i++){
00366         if(deliverEvents[i]->scheduled()){
00367             deliverEvents[i]->deschedule();
00368         }
00369         delete deliverEvents[i];
00370     }
00371     deliverEvents.clear();
00372     
00373     blockedAt = curTick;
00374 }
00375 
00376 void
00377 SplitTransBus::clearBlocked(int fromInterface){
00378     
00379     assert(blocked);
00380     assert(blockedAt >= 0);
00381     if (blocked && waitingFor == fromInterface) {
00382         blocked = false;
00383         
00384         if(!requestQueue.empty()){
00385             Tick min = requestQueue.front()->time;
00386             
00387             if(min >= curTick){
00388                 scheduleArbitrationEvent(min + arbitrationDelay);
00389             }
00390             else{
00391                 scheduleArbitrationEvent(curTick + arbitrationDelay);
00392             }
00393             
00394         }
00395         
00396         if(pipelined){
00397             if(!slaveRequestQueue->empty()){
00398                 Tick min = slaveRequestQueue->front()->time;
00399                 if(min >= curTick){
00400                     scheduleArbitrationEvent(min + arbitrationDelay);
00401                 }
00402                 else{
00403                     scheduleArbitrationEvent(curTick + arbitrationDelay);
00404                 }
00405             }
00406         }
00407         
00408         if(!deliverQueue.empty()){
00409             Tick min = deliverQueue.front()->grantTime;
00410             if(min >= curTick){
00411                 scheduleDeliverEvent(min + transferDelay);
00412             }
00413             else{
00414                 scheduleDeliverEvent(curTick + transferDelay);
00415             }
00416         }
00417         
00418         numClearBlocked++;
00419         
00420         blockedAt = -1;
00421     }
00422 }
00423 
00424 vector<int>
00425 SplitTransBus::getChannelSample(){
00426     
00427     if(!doProfile) doProfile = true;
00428     
00429     std::vector<int> retval(1, 0);
00430     retval[0] = useCycleSample;
00431     useCycleSample = 0;
00432     
00433     return retval;
00434 }
00435 
00436 #ifdef DEBUG_SPLIT_TRANS_BUS
00437 
00438 void
00439 SplitTransBus::checkIfSorted(std::list<InterconnectRequest* >* inList){
00440     /* check that the queue is sorted */
00441     InterconnectRequest* prev = NULL;
00442     bool first = true;
00443     for(list<InterconnectRequest*>::iterator i=inList->begin();
00444         i!=inList->end();
00445         i++){
00446             if(first){
00447                 first = false;
00448                 prev = *i;
00449                 continue;
00450             }
00451             
00452             assert(prev->time <= (*i)->time);
00453             prev = *i;
00454     }
00455 }
00456 
00457 void
00458 SplitTransBus::printRequestQueue(){
00459     cout << "Request queue: ";
00460     for(list<InterconnectRequest*>::iterator i = requestQueue.begin();
00461         i != requestQueue.end();
00462         i++){
00463         cout << "(" 
00464                 << (*i)->fromID 
00465                 << ", " 
00466                 << (*i)->time 
00467                 << ") ";
00468     }
00469     cout << "\n";
00470     
00471     if(pipelined){
00472         cout << "Slave request queue: ";
00473         for(list<InterconnectRequest*>::iterator i = slaveRequestQueue->begin();
00474             i != slaveRequestQueue->end();
00475             i++){
00476                 cout << "(" 
00477                         << (*i)->fromID 
00478                         << ", " 
00479                         << (*i)->time 
00480                         << ") ";
00481         }
00482         cout << "\n";
00483     }
00484 }
00485 
00486 void
00487 SplitTransBus::printDeliverQueue(){
00488     cout << "Deliver queue: ";
00489     for(list<InterconnectDelivery*>::iterator i = deliverQueue.begin();
00490         i != deliverQueue.end();
00491         i++){
00492             cout << "(" 
00493                     << (*i)->fromID 
00494                     << ", " 
00495                     << (*i)->toID 
00496                     << ", " 
00497                     << (*i)->grantTime 
00498                     << ") ";
00499     }
00500     cout << "\n";
00501 }
00502 
00503 #endif //DEBUG_SPLIT_TRANS_BUS
00504 
00505 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00506 
00507 BEGIN_DECLARE_SIM_OBJECT_PARAMS(SplitTransBus)
00508         Param<int> width;
00509         Param<int> clock;
00510         Param<int> transferDelay;
00511         Param<int> arbitrationDelay;
00512         Param<int> cpu_count;
00513         Param<bool> pipelined;
00514         SimObjectParam<HierParams *> hier;
00515 END_DECLARE_SIM_OBJECT_PARAMS(SplitTransBus)
00516 
00517 BEGIN_INIT_SIM_OBJECT_PARAMS(SplitTransBus)
00518         INIT_PARAM(width, "bus width in bytes"),
00519         INIT_PARAM(clock, "bus clock"),
00520         INIT_PARAM(transferDelay, "bus transfer delay in CPU cycles"),
00521         INIT_PARAM(arbitrationDelay, "bus arbitration delay in CPU cycles"),
00522         INIT_PARAM(cpu_count, "the number of CPUs in the system"),
00523         INIT_PARAM(pipelined, "true if the bus has pipelined arbitration "
00524                               "and transmission"),
00525         INIT_PARAM_DFLT(hier,
00526                         "Hierarchy global variables",
00527                         &defaultHierParams)
00528 END_INIT_SIM_OBJECT_PARAMS(SplitTransBus)
00529 
00530 CREATE_SIM_OBJECT(SplitTransBus)
00531 {
00532     return new SplitTransBus(getInstanceName(),
00533                              width,
00534                              clock,
00535                              transferDelay,
00536                              arbitrationDelay,
00537                              cpu_count,
00538                              pipelined,
00539                              hier);
00540 }
00541 
00542 REGISTER_SIM_OBJECT("SplitTransBus", SplitTransBus)
00543 
00544 #endif //DOXYGEN_SHOULD_SKIP_THIS

Generated on Tue Jun 5 12:55:20 2007 for M5InterconnectExtensions by  doxygen 1.4.7