ideal_interconnect.cc

00001 
00002 #include "sim/builder.hh"
00003 #include "ideal_interconnect.hh"
00004         
00005 using namespace std;
00006 
00007 void
00008 IdealInterconnect::request(Tick time, int fromID){
00009     
00010     requests++;
00011     
00012     // keep linked list of requests sorted at all times
00013     // first request takes priority over later requests at same cycle
00014     list<InterconnectRequest*>::iterator findPos;
00015     for(findPos=requestQueue.begin();
00016         findPos!=requestQueue.end();
00017         findPos++){
00018             
00019             InterconnectRequest* tempReq = *findPos;
00020             if(time < tempReq->time) break;
00021     }
00022     
00023     requestQueue.insert(findPos, new InterconnectRequest(time, fromID));
00024     
00025 #ifdef DEBUG_IDEAL_INTERCONNECT
00026     
00027     /* check that the queue is sorted */
00028     InterconnectRequest* prev = NULL;
00029     bool first = true;
00030     for(list<InterconnectRequest*>::iterator i=requestQueue.begin();
00031         i!=requestQueue.end();
00032         i++){
00033             if(first){
00034                 first = false;
00035                 prev = *i;
00036                 continue;
00037             }
00038             
00039             assert(prev->time <= (*i)->time);
00040             prev = *i;
00041     }
00042     
00043 //     printRequestQueue();
00044 #endif //DEBUG_IDEAL_INTERCONNECT
00045     
00046     /* add arbitration event if we are not blocked */
00047     if(!blocked){
00048         scheduleArbitrationEvent(time + arbitrationDelay);
00049     }
00050 }
00051 
00052 void
00053 IdealInterconnect::send(MemReqPtr& req, Tick time, int fromID){
00054     
00055     assert(!blocked);
00056     assert((req->size / width) <= 1);
00057     
00058     bool isFromMaster = allInterfaces[fromID]->isMaster();
00059     
00060     if(req->toInterfaceID != -1){
00061         /* cache-to-cache transfer */
00062         assert(req->toProcessorID != -1);
00063         assert(req->toInterfaceID == getInterconnectID(req->toProcessorID));
00064         grantQueue.push_back(new InterconnectDelivery(time, 
00065                                                       fromID, 
00066                                                       req->toInterfaceID,
00067                                                       req));
00068     }
00069     else if(isFromMaster){
00070         /* reciever is a slave interface */
00071         int recvCount = 0;
00072         int recvID = -1;
00073         
00074         for(int i=0;i<allInterfaces.size();++i){
00075             if(allInterfaces[i]->isMaster()) continue;
00076             
00077             if(allInterfaces[i]->inRange(req->paddr)){
00078                 recvCount++;
00079                 recvID = i;
00080             }
00081         }
00082         
00083         /* check for errors */
00084         if(recvCount > 1){
00085             fatal("More than one supplier for address in IdealInterconnect");
00086         }
00087         if(recvCount != 1){
00088             fatal("No supplier for address in IdealInterconnect");
00089         }
00090         assert(recvID >= 0);
00091         
00092         grantQueue.push_back(new InterconnectDelivery(time, 
00093                                                       fromID, 
00094                                                       recvID,
00095                                                       req));
00096     }
00097     else{
00098         /* reciever is a master interface*/
00099         grantQueue.push_back(new InterconnectDelivery(time,
00100                                                       fromID,
00101                                                       req->fromInterfaceID,
00102                                                       req));
00103     }
00104     
00105 #ifdef DEBUG_IDEAL_INTERCONNECT
00106     /* check that the queue is sorted */
00107     InterconnectDelivery* prev = NULL;
00108     bool first = true;
00109     for(list<InterconnectDelivery*>::iterator i=grantQueue.begin();
00110         i!=grantQueue.end();
00111         i++){
00112             if(first){
00113                 first = false;
00114                 prev = *i;
00115                 continue;
00116             }
00117             
00118             assert(prev->grantTime <= (*i)->grantTime);
00119             prev = *i;
00120         }
00121 #endif //DEBUG_IDEAL_INTERCONNECT
00122     
00123     bool found = false;
00124     for(int i=0;i<deliverEvents.size();i++){
00125         if(deliverEvents[i]->when() == (time + transferDelay)) found = true;
00126     }
00127     
00128     if(!found){
00129         InterconnectDeliverQueueEvent* event = 
00130                 new InterconnectDeliverQueueEvent(this);
00131         event->schedule(time + transferDelay);
00132         deliverEvents.push_back(event);
00133     }
00134 
00135 }
00136 
00137 void
00138 IdealInterconnect::arbitrate(Tick cycle){
00139     
00140     assert(!blocked);
00141     
00142     list<InterconnectRequest*> tempGrantQueue;
00143     
00144     InterconnectRequest* lastReq = requestQueue.back();
00145     if((lastReq->time + arbitrationDelay) <= cycle){
00146         //all requests can be issued
00147         tempGrantQueue.splice(tempGrantQueue.end(), requestQueue);
00148     }
00149     else{
00150         
00151         list<InterconnectRequest*>::iterator firstOldReq;
00152         for(firstOldReq = requestQueue.begin();
00153             firstOldReq != requestQueue.end();
00154             firstOldReq++){
00155                 if(((*firstOldReq)->time + arbitrationDelay) > cycle) break;
00156         }
00157         
00158         tempGrantQueue.splice(tempGrantQueue.end(),
00159                               requestQueue,
00160                               requestQueue.begin(),
00161                               firstOldReq);
00162     }
00163     
00164     for(list<InterconnectRequest*>::iterator i = tempGrantQueue.begin();
00165         i != tempGrantQueue.end();
00166         i++){
00167             
00168             /* update statistics */
00169             arbitratedRequests++;
00170             totalArbQueueCycles += (cycle - (*i)->time) - arbitrationDelay;
00171             totalArbitrationCycles += arbitrationDelay;
00172             
00173             allInterfaces[(*i)->fromID]->grantData();
00174             delete *i;
00175     }
00176     
00177     if(!requestQueue.empty()){
00178         InterconnectRequest* firstReq = requestQueue.front();
00179         scheduleArbitrationEvent(firstReq->time + arbitrationDelay);
00180     }
00181 }
00182 
00183 void
00184 IdealInterconnect::scheduleArbitrationEvent(Tick time){
00185     
00186     bool arbEventExists = false;
00187     for(int i=0;i<arbitrationEvents.size();++i){
00188         if(time == arbitrationEvents[i]->when()) arbEventExists = true;
00189     }
00190 
00191     if(!arbEventExists){
00192         InterconnectArbitrationEvent* event = 
00193                 new InterconnectArbitrationEvent(this);
00194         event->schedule(time);
00195         arbitrationEvents.push_back(event);
00196     }
00197     
00198 }
00199 
00200 void
00201 IdealInterconnect::deliver(MemReqPtr& req, Tick cycle, int toID, int fromID){
00202     
00203     assert(!blocked);
00204     
00205     assert(!req);
00206     assert(toID == -1);
00207     assert(fromID == -1);
00208     
00209     list<InterconnectDelivery* > grantsThisCycle;
00210     InterconnectDelivery* lastReq = grantQueue.back();
00211     if((lastReq->grantTime + transferDelay) <= cycle){
00212         //all requests can be issued
00213         grantsThisCycle.splice(grantsThisCycle.end(), grantQueue);
00214     }
00215     else{
00216         
00217         list<InterconnectDelivery*>::iterator firstOldReq;
00218         for(firstOldReq = grantQueue.begin();
00219             firstOldReq != grantQueue.end();
00220             firstOldReq++){
00221                 if(((*firstOldReq)->grantTime + transferDelay) > cycle) break;
00222             }
00223         
00224             grantsThisCycle.splice(grantsThisCycle.end(),
00225                                    grantQueue,
00226                                    grantQueue.begin(),
00227                                    firstOldReq);
00228     }
00229     
00230     
00231     while(!grantsThisCycle.empty()){
00232         InterconnectDelivery* tempGrant = grantsThisCycle.front();
00233         grantsThisCycle.pop_front();
00234         
00235         /* update statistics */
00236         sentRequests++;
00237         int queueCycles = (cycle - tempGrant->grantTime) - transferDelay;
00238         int curCpuId = tempGrant->req->xc->cpu->params->cpu_id;
00239         
00240         totalTransQueueCycles += queueCycles;
00241         totalTransferCycles += transferDelay;
00242         perCpuTotalTransQueueCycles[curCpuId] += queueCycles;
00243         perCpuTotalTransferCycles[curCpuId] += transferDelay;
00244         
00245         int retval = BA_NO_RESULT;
00246         if(allInterfaces[tempGrant->toID]->isMaster()){
00247             allInterfaces[tempGrant->toID]->deliver(tempGrant->req);
00248         }
00249         else{
00250             retval = allInterfaces[tempGrant->toID]->access(tempGrant->req);
00251         }
00252         
00253         /* this delivery got through, free memory */
00254         delete tempGrant;
00255         
00256         /* if the cache returns blocked we cannot deliver any more data */
00257         if(retval == BA_BLOCKED) break;
00258     }
00259 
00260     if(!grantsThisCycle.empty()){
00261         grantQueue.splice(grantQueue.begin(),
00262                           grantsThisCycle,
00263                           grantsThisCycle.begin(),
00264                           grantsThisCycle.end());
00265     }
00266 }
00267 
00268 void
00269 IdealInterconnect::setBlocked(int fromInterface){
00270     
00271     if(blocked) warn("blocking on a second cause");
00272     blocked = true;
00273     waitingFor = fromInterface;
00274     blockedAt = curTick;
00275     numSetBlocked++;
00276     
00277     blockedInterfaces.push_back(fromInterface);
00278     
00279     for(int i=0;i<arbitrationEvents.size();++i){
00280         if(arbitrationEvents[i]->scheduled()){
00281             arbitrationEvents[i]->deschedule();
00282         }
00283         delete arbitrationEvents[i];
00284     }
00285     arbitrationEvents.clear();
00286     
00287     for(int i=0;i<deliverEvents.size();++i){
00288         if(deliverEvents[i]->scheduled()){
00289             deliverEvents[i]->deschedule();
00290         }
00291         
00292         delete deliverEvents[i];
00293     }
00294     deliverEvents.clear();
00295     
00296 }
00297 
00298 void
00299 IdealInterconnect::clearBlocked(int fromInterface){
00300     
00301     assert(blocked);
00302     assert(blockedAt > -1);
00303     
00304     int hitIndex = -1;
00305     int hitCount = 0;
00306     for(int i=0;i<blockedInterfaces.size();i++){
00307         if(blockedInterfaces[i] == fromInterface){
00308             hitIndex = i;
00309             hitCount++;
00310         }
00311     }
00312     assert(hitCount == 1 && hitIndex > -1);
00313     blockedInterfaces.erase(blockedInterfaces.begin()+hitIndex);
00314     
00315     if(blockedInterfaces.empty()){
00316         
00317         blocked = false;
00318         numClearBlocked++;
00319         
00320         assert(arbitrationEvents.empty());
00321         if(!requestQueue.empty()){
00322             
00323             /* schedule new arbitration event */
00324             Tick firstReq = (requestQueue.front())->time;
00325             
00326             InterconnectArbitrationEvent* event = 
00327                     new InterconnectArbitrationEvent(this);
00328             arbitrationEvents.push_back(event);
00329             
00330             if((firstReq + arbitrationDelay) <= curTick){
00331                 event->schedule(curTick);
00332             }
00333             else{
00334                 event->schedule(firstReq + arbitrationDelay);
00335             }
00336         }
00337         
00338         assert(deliverEvents.empty());
00339         if(!grantQueue.empty()){
00340             
00341             /* schedule new deliver event */
00342             Tick firstGrant = (grantQueue.front())->grantTime;
00343             
00344             InterconnectDeliverQueueEvent* event = 
00345                     new InterconnectDeliverQueueEvent(this);
00346             deliverEvents.push_back(event);
00347             
00348             if((firstGrant + transferDelay) <= curTick){
00349                 event->schedule(curTick);
00350             }
00351             else{
00352                 event->schedule(firstGrant + transferDelay);
00353             }
00354         }
00355         
00356         blockedAt = -1;
00357     }
00358 }
00359 
00360 #ifdef DEBUG_IDEAL_INTERCONNECT
00361 
00362 void
00363 IdealInterconnect::printRequestQueue(){
00364     cout << "ReqQueue: ";
00365     for(list<InterconnectRequest*>::iterator i = requestQueue.begin();
00366         i != requestQueue.end();
00367         i++){
00368             cout << "(" << (*i)->time << ", " << (*i)->fromID << ") ";
00369     }
00370     cout << "\n";
00371 }
00372 
00373 void
00374 IdealInterconnect::printGrantQueue(){
00375     cout << "GrantQueue: ";
00376     for(list<InterconnectDelivery*>::iterator i = grantQueue.begin();
00377         i != grantQueue.end();
00378         i++){
00379             cout << "(" 
00380                     << (*i)->grantTime 
00381                     << ", " 
00382                     << (*i)->fromID 
00383                     << ", " 
00384                     << (*i)->toID 
00385                     << ") ";
00386     }
00387     cout << "\n";
00388 }
00389 
00390 #endif //DEBUG_IDEAL_INTERCONNECT
00391 
00392 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00393 
00394 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdealInterconnect)
00395     Param<int> width;
00396     Param<int> clock;
00397     Param<int> transferDelay;
00398     Param<int> arbitrationDelay;
00399     Param<int> cpu_count;
00400     SimObjectParam<HierParams *> hier;
00401 END_DECLARE_SIM_OBJECT_PARAMS(IdealInterconnect)
00402 
00403 BEGIN_INIT_SIM_OBJECT_PARAMS(IdealInterconnect)
00404     INIT_PARAM(width, "ideal interconnect width, set this to the cache line "
00405                       "width"),
00406     INIT_PARAM(clock, "ideal interconnect clock"),
00407     INIT_PARAM(transferDelay, "ideal interconnect transfer delay in CPU "
00408                               "cycles"),
00409     INIT_PARAM(arbitrationDelay, "ideal interconnect arbitration delay in CPU "
00410                                  "cycles"),
00411     INIT_PARAM(cpu_count, "the number of CPUs in the system"),
00412     INIT_PARAM_DFLT(hier,
00413                     "Hierarchy global variables",
00414                     &defaultHierParams)
00415 END_INIT_SIM_OBJECT_PARAMS(IdealInterconnect)
00416 
00417 CREATE_SIM_OBJECT(IdealInterconnect)
00418 {
00419     return new IdealInterconnect(getInstanceName(),
00420                                  width,
00421                                  clock,
00422                                  transferDelay,
00423                                  arbitrationDelay,
00424                                  cpu_count,
00425                                  hier);
00426 }
00427 
00428 REGISTER_SIM_OBJECT("IdealInterconnect", IdealInterconnect)
00429 
00430 #endif //DOXYGEN_SHOULD_SKIP_THIS

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