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
00013
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
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
00044 #endif //DEBUG_IDEAL_INTERCONNECT
00045
00046
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
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
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
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
00099 grantQueue.push_back(new InterconnectDelivery(time,
00100 fromID,
00101 req->fromInterfaceID,
00102 req));
00103 }
00104
00105 #ifdef DEBUG_IDEAL_INTERCONNECT
00106
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
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
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
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
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
00254 delete tempGrant;
00255
00256
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
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
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