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
00015
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
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
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
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
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
00196 allInterfaces[grantReq->fromID]->grantData();
00197
00198
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
00218 deliverQueue.push_back(
00219 new InterconnectDelivery(time,
00220 fromID,
00221 req->toInterfaceID,
00222 req));
00223 }
00224 else if(isFromMaster){
00225
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
00246 deliverQueue.push_back(
00247 new InterconnectDelivery(time, fromID, toID, req));
00248 }
00249 else{
00250
00251 deliverQueue.push_back(
00252 new InterconnectDelivery(time,
00253 fromID,
00254 req->fromInterfaceID,
00255 req));
00256 }
00257
00258 #ifdef DEBUG_SPLIT_TRANS_BUS
00259
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
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
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
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
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
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