trace_cpu.cc (11249:0733a1c08600) | trace_cpu.cc (11252:18bb597fc40c) |
---|---|
1/* 2 * Copyright (c) 2013 - 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 439 unchanged lines hidden (view full) --- 448 if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) { 449 panic("Retry packet's seqence number does not match " 450 "the first node in the readyList.\n"); 451 } 452 if (port.sendTimingReq(retryPkt)) { 453 ++numRetrySucceeded; 454 retryPkt = nullptr; 455 } | 1/* 2 * Copyright (c) 2013 - 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 439 unchanged lines hidden (view full) --- 448 if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) { 449 panic("Retry packet's seqence number does not match " 450 "the first node in the readyList.\n"); 451 } 452 if (port.sendTimingReq(retryPkt)) { 453 ++numRetrySucceeded; 454 retryPkt = nullptr; 455 } |
456 } else if (node_ptr->isLoad || node_ptr->isStore) { | 456 } else if (node_ptr->isLoad() || node_ptr->isStore()) { |
457 // If there is no retryPkt, attempt to send a memory request in 458 // case of a load or store node. If the send fails, executeMemReq() 459 // returns a packet pointer, which we save in retryPkt. In case of 460 // a comp node we don't do anything and simply continue as if the 461 // execution of the comp node succedded. 462 retryPkt = executeMemReq(node_ptr); 463 } 464 // If the retryPkt or a new load/store node failed, we exit from here --- 4 unchanged lines hidden (view full) --- 469 } 470 471 // Proceed to remove dependencies for the successfully executed node. 472 // If it is a load which is not strictly ordered and we sent a 473 // request for it successfully, we do not yet mark any register 474 // dependencies complete. But as per dependency modelling we need 475 // to mark ROB dependencies of load and non load/store nodes which 476 // are based on successful sending of the load as complete. | 457 // If there is no retryPkt, attempt to send a memory request in 458 // case of a load or store node. If the send fails, executeMemReq() 459 // returns a packet pointer, which we save in retryPkt. In case of 460 // a comp node we don't do anything and simply continue as if the 461 // execution of the comp node succedded. 462 retryPkt = executeMemReq(node_ptr); 463 } 464 // If the retryPkt or a new load/store node failed, we exit from here --- 4 unchanged lines hidden (view full) --- 469 } 470 471 // Proceed to remove dependencies for the successfully executed node. 472 // If it is a load which is not strictly ordered and we sent a 473 // request for it successfully, we do not yet mark any register 474 // dependencies complete. But as per dependency modelling we need 475 // to mark ROB dependencies of load and non load/store nodes which 476 // are based on successful sending of the load as complete. |
477 if (node_ptr->isLoad && !node_ptr->isStrictlyOrdered()) { | 477 if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) { |
478 // If execute succeeded mark its dependents as complete 479 DPRINTF(TraceCPUData, "Node seq. num %lli sent. Waking up " 480 "dependents..\n", node_ptr->seqNum); 481 482 auto child_itr = (node_ptr->dependents).begin(); 483 while (child_itr != (node_ptr->dependents).end()) { 484 // ROB dependency of a store on a load must not be removed 485 // after load is sent but after response is received | 478 // If execute succeeded mark its dependents as complete 479 DPRINTF(TraceCPUData, "Node seq. num %lli sent. Waking up " 480 "dependents..\n", node_ptr->seqNum); 481 482 auto child_itr = (node_ptr->dependents).begin(); 483 while (child_itr != (node_ptr->dependents).end()) { 484 // ROB dependency of a store on a load must not be removed 485 // after load is sent but after response is received |
486 if (!(*child_itr)->isStore && | 486 if (!(*child_itr)->isStore() && |
487 (*child_itr)->removeRobDep(node_ptr->seqNum)) { 488 489 // Check if the child node has become dependency free 490 if ((*child_itr)->numRobDep == 0 && 491 (*child_itr)->numRegDep == 0) { 492 493 // Source dependencies are complete, check if 494 // resources are available and issue --- 30 unchanged lines hidden (view full) --- 525 readyList.erase(free_itr); 526 // If it is a cacheable load which was sent, don't delete 527 // just yet. Delete it in completeMemAccess() after the 528 // response is received. If it is an strictly ordered 529 // load, it was not sent and all dependencies were simply 530 // marked complete. Thus it is safe to delete it. For 531 // stores and non load/store nodes all dependencies were 532 // marked complete so it is safe to delete it. | 487 (*child_itr)->removeRobDep(node_ptr->seqNum)) { 488 489 // Check if the child node has become dependency free 490 if ((*child_itr)->numRobDep == 0 && 491 (*child_itr)->numRegDep == 0) { 492 493 // Source dependencies are complete, check if 494 // resources are available and issue --- 30 unchanged lines hidden (view full) --- 525 readyList.erase(free_itr); 526 // If it is a cacheable load which was sent, don't delete 527 // just yet. Delete it in completeMemAccess() after the 528 // response is received. If it is an strictly ordered 529 // load, it was not sent and all dependencies were simply 530 // marked complete. Thus it is safe to delete it. For 531 // stores and non load/store nodes all dependencies were 532 // marked complete so it is safe to delete it. |
533 if (!node_ptr->isLoad || node_ptr->isStrictlyOrdered()) { | 533 if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) { |
534 // Release all resources occupied by the completed node 535 hwResource.release(node_ptr); 536 // clear the dynamically allocated set of dependents 537 (node_ptr->dependents).clear(); 538 // delete node 539 delete node_ptr; 540 // remove from graph 541 depGraph.erase(graph_itr); --- 57 unchanged lines hidden (view full) --- 599 600 DPRINTF(TraceCPUData, "Executing memory request %lli (addr %d, pc %#x, " 601 "size %d, flags %d).\n", node_ptr->seqNum, node_ptr->addr, 602 node_ptr->pc, node_ptr->size, node_ptr->flags); 603 604 // If the request is strictly ordered, do not send it. Just return nullptr 605 // as if it was succesfully sent. 606 if (node_ptr->isStrictlyOrdered()) { | 534 // Release all resources occupied by the completed node 535 hwResource.release(node_ptr); 536 // clear the dynamically allocated set of dependents 537 (node_ptr->dependents).clear(); 538 // delete node 539 delete node_ptr; 540 // remove from graph 541 depGraph.erase(graph_itr); --- 57 unchanged lines hidden (view full) --- 599 600 DPRINTF(TraceCPUData, "Executing memory request %lli (addr %d, pc %#x, " 601 "size %d, flags %d).\n", node_ptr->seqNum, node_ptr->addr, 602 node_ptr->pc, node_ptr->size, node_ptr->flags); 603 604 // If the request is strictly ordered, do not send it. Just return nullptr 605 // as if it was succesfully sent. 606 if (node_ptr->isStrictlyOrdered()) { |
607 node_ptr->isLoad ? ++numSOLoads : ++numSOStores; | 607 node_ptr->isLoad() ? ++numSOLoads : ++numSOStores; |
608 DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n", 609 node_ptr->seqNum); 610 return nullptr; 611 } 612 613 // Check if the request spans two cache lines as this condition triggers 614 // an assert fail in the L1 cache. If it does then truncate the size to 615 // access only until the end of that line and ignore the remainder. The --- 9 unchanged lines hidden (view full) --- 625 626 // Create a request and the packet containing request 627 Request* req = new Request(node_ptr->addr, node_ptr->size, node_ptr->flags, 628 masterID, node_ptr->seqNum, 629 ContextID(0), ThreadID(0)); 630 req->setPC(node_ptr->pc); 631 PacketPtr pkt; 632 uint8_t* pkt_data = new uint8_t[req->getSize()]; | 608 DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n", 609 node_ptr->seqNum); 610 return nullptr; 611 } 612 613 // Check if the request spans two cache lines as this condition triggers 614 // an assert fail in the L1 cache. If it does then truncate the size to 615 // access only until the end of that line and ignore the remainder. The --- 9 unchanged lines hidden (view full) --- 625 626 // Create a request and the packet containing request 627 Request* req = new Request(node_ptr->addr, node_ptr->size, node_ptr->flags, 628 masterID, node_ptr->seqNum, 629 ContextID(0), ThreadID(0)); 630 req->setPC(node_ptr->pc); 631 PacketPtr pkt; 632 uint8_t* pkt_data = new uint8_t[req->getSize()]; |
633 if (node_ptr->isLoad) { | 633 if (node_ptr->isLoad()) { |
634 pkt = Packet::createRead(req); 635 } else { 636 pkt = Packet::createWrite(req); 637 memset(pkt_data, 0xA, req->getSize()); 638 } 639 pkt->dataDynamic(pkt_data); 640 641 // Call MasterPort method to send a timing request for this packet --- 17 unchanged lines hidden (view full) --- 659TraceCPU::ElasticDataGen::checkAndIssue(const GraphNode* node_ptr, bool first) 660{ 661 // Assert the node is dependency-free 662 assert(node_ptr->numRobDep == 0 && node_ptr->numRegDep == 0); 663 664 // If this is the first attempt, print a debug message to indicate this. 665 if (first) { 666 DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now" | 634 pkt = Packet::createRead(req); 635 } else { 636 pkt = Packet::createWrite(req); 637 memset(pkt_data, 0xA, req->getSize()); 638 } 639 pkt->dataDynamic(pkt_data); 640 641 // Call MasterPort method to send a timing request for this packet --- 17 unchanged lines hidden (view full) --- 659TraceCPU::ElasticDataGen::checkAndIssue(const GraphNode* node_ptr, bool first) 660{ 661 // Assert the node is dependency-free 662 assert(node_ptr->numRobDep == 0 && node_ptr->numRegDep == 0); 663 664 // If this is the first attempt, print a debug message to indicate this. 665 if (first) { 666 DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now" |
667 " dependency free.\n", node_ptr->seqNum, 668 node_ptr->isLoad ? "L" : (node_ptr->isStore ? "S" : "C"), | 667 " dependency free.\n", node_ptr->seqNum, node_ptr->typeToStr(), |
669 node_ptr->robNum); 670 } 671 672 // Check if resources are available to issue the specific node 673 if (hwResource.isAvailable(node_ptr)) { 674 // If resources are free only then add to readyList 675 DPRINTFR(TraceCPUData, "\t\tResources available for seq. num %lli. Adding" 676 " to readyList, occupying resources.\n", node_ptr->seqNum); --- 149 unchanged lines hidden (view full) --- 826 DPRINTF(TraceCPUData, "readyList is empty.\n"); 827 return; 828 } 829 DPRINTF(TraceCPUData, "Printing readyList:\n"); 830 while (itr != readyList.end()) { 831 auto graph_itr = depGraph.find(itr->seqNum); 832 GraphNode* node_ptr M5_VAR_USED = graph_itr->second; 833 DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum, | 668 node_ptr->robNum); 669 } 670 671 // Check if resources are available to issue the specific node 672 if (hwResource.isAvailable(node_ptr)) { 673 // If resources are free only then add to readyList 674 DPRINTFR(TraceCPUData, "\t\tResources available for seq. num %lli. Adding" 675 " to readyList, occupying resources.\n", node_ptr->seqNum); --- 149 unchanged lines hidden (view full) --- 825 DPRINTF(TraceCPUData, "readyList is empty.\n"); 826 return; 827 } 828 DPRINTF(TraceCPUData, "Printing readyList:\n"); 829 while (itr != readyList.end()) { 830 auto graph_itr = depGraph.find(itr->seqNum); 831 GraphNode* node_ptr M5_VAR_USED = graph_itr->second; 832 DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum, |
834 node_ptr->isLoad ? "L" : (node_ptr->isStore ? "S" : "C"), 835 itr->execTick); | 833 node_ptr->typeToStr(), itr->execTick); |
836 itr++; 837 } 838} 839 840TraceCPU::ElasticDataGen::HardwareResource::HardwareResource( 841 uint16_t max_rob, uint16_t max_stores, uint16_t max_loads) 842 : sizeROB(max_rob), 843 sizeStoreBuffer(max_stores), --- 8 unchanged lines hidden (view full) --- 852{ 853 // Occupy ROB entry for the issued node 854 // Merely maintain the oldest node, i.e. numerically least robNum by saving 855 // it in the variable oldestInFLightRobNum. 856 inFlightNodes[new_node->seqNum] = new_node->robNum; 857 oldestInFlightRobNum = inFlightNodes.begin()->second; 858 859 // Occupy Load/Store Buffer entry for the issued node if applicable | 834 itr++; 835 } 836} 837 838TraceCPU::ElasticDataGen::HardwareResource::HardwareResource( 839 uint16_t max_rob, uint16_t max_stores, uint16_t max_loads) 840 : sizeROB(max_rob), 841 sizeStoreBuffer(max_stores), --- 8 unchanged lines hidden (view full) --- 850{ 851 // Occupy ROB entry for the issued node 852 // Merely maintain the oldest node, i.e. numerically least robNum by saving 853 // it in the variable oldestInFLightRobNum. 854 inFlightNodes[new_node->seqNum] = new_node->robNum; 855 oldestInFlightRobNum = inFlightNodes.begin()->second; 856 857 // Occupy Load/Store Buffer entry for the issued node if applicable |
860 if (new_node->isLoad) { | 858 if (new_node->isLoad()) { |
861 ++numInFlightLoads; | 859 ++numInFlightLoads; |
862 } else if (new_node->isStore) { | 860 } else if (new_node->isStore()) { |
863 ++numInFlightStores; 864 } // else if it is a non load/store node, no buffer entry is occupied 865 866 printOccupancy(); 867} 868 869void 870TraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node) --- 18 unchanged lines hidden (view full) --- 889 DPRINTFR(TraceCPUData, "\tCleared. inFlightNodes.size() = %d, " 890 "oldestInFlightRobNum = %d\n", inFlightNodes.size(), 891 oldestInFlightRobNum); 892 893 // A store is considered complete when a request is sent, thus ROB entry is 894 // freed. But it occupies an entry in the Store Buffer until its response 895 // is received. A load is considered complete when a response is received, 896 // thus both ROB and Load Buffer entries can be released. | 861 ++numInFlightStores; 862 } // else if it is a non load/store node, no buffer entry is occupied 863 864 printOccupancy(); 865} 866 867void 868TraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node) --- 18 unchanged lines hidden (view full) --- 887 DPRINTFR(TraceCPUData, "\tCleared. inFlightNodes.size() = %d, " 888 "oldestInFlightRobNum = %d\n", inFlightNodes.size(), 889 oldestInFlightRobNum); 890 891 // A store is considered complete when a request is sent, thus ROB entry is 892 // freed. But it occupies an entry in the Store Buffer until its response 893 // is received. A load is considered complete when a response is received, 894 // thus both ROB and Load Buffer entries can be released. |
897 if (done_node->isLoad) { | 895 if (done_node->isLoad()) { |
898 assert(numInFlightLoads != 0); 899 --numInFlightLoads; 900 } 901 // For normal writes, we send the requests out and clear a store buffer 902 // entry on response. For writes which are strictly ordered, for e.g. 903 // writes to device registers, we do that within release() which is called 904 // when node is executed and taken off from readyList. | 896 assert(numInFlightLoads != 0); 897 --numInFlightLoads; 898 } 899 // For normal writes, we send the requests out and clear a store buffer 900 // entry on response. For writes which are strictly ordered, for e.g. 901 // writes to device registers, we do that within release() which is called 902 // when node is executed and taken off from readyList. |
905 if (done_node->isStore && done_node->isStrictlyOrdered()) { | 903 if (done_node->isStore() && done_node->isStrictlyOrdered()) { |
906 releaseStoreBuffer(); 907 } 908} 909 910void 911TraceCPU::ElasticDataGen::HardwareResource::releaseStoreBuffer() 912{ 913 assert(numInFlightStores != 0); --- 30 unchanged lines hidden (view full) --- 944 } 945 DPRINTFR(TraceCPUData, ", LQ = %d/%d, SQ = %d/%d.\n", 946 numInFlightLoads, sizeLoadBuffer, 947 numInFlightStores, sizeStoreBuffer); 948 // Check if resources are available to issue the specific node 949 if (num_in_flight_nodes >= sizeROB) { 950 return false; 951 } | 904 releaseStoreBuffer(); 905 } 906} 907 908void 909TraceCPU::ElasticDataGen::HardwareResource::releaseStoreBuffer() 910{ 911 assert(numInFlightStores != 0); --- 30 unchanged lines hidden (view full) --- 942 } 943 DPRINTFR(TraceCPUData, ", LQ = %d/%d, SQ = %d/%d.\n", 944 numInFlightLoads, sizeLoadBuffer, 945 numInFlightStores, sizeStoreBuffer); 946 // Check if resources are available to issue the specific node 947 if (num_in_flight_nodes >= sizeROB) { 948 return false; 949 } |
952 if (new_node->isLoad && numInFlightLoads >= sizeLoadBuffer) { | 950 if (new_node->isLoad() && numInFlightLoads >= sizeLoadBuffer) { |
953 return false; 954 } | 951 return false; 952 } |
955 if (new_node->isStore && numInFlightStores >= sizeStoreBuffer) { | 953 if (new_node->isStore() && numInFlightStores >= sizeStoreBuffer) { |
956 return false; 957 } 958 return true; 959} 960 961bool 962TraceCPU::ElasticDataGen::HardwareResource::awaitingResponse() const { 963 // Return true if there is at least one read or write request in flight --- 281 unchanged lines hidden (view full) --- 1245 1246bool 1247TraceCPU::ElasticDataGen::InputStream::read(GraphNode* element) 1248{ 1249 ProtoMessage::InstDepRecord pkt_msg; 1250 if (trace.read(pkt_msg)) { 1251 // Required fields 1252 element->seqNum = pkt_msg.seq_num(); | 954 return false; 955 } 956 return true; 957} 958 959bool 960TraceCPU::ElasticDataGen::HardwareResource::awaitingResponse() const { 961 // Return true if there is at least one read or write request in flight --- 281 unchanged lines hidden (view full) --- 1243 1244bool 1245TraceCPU::ElasticDataGen::InputStream::read(GraphNode* element) 1246{ 1247 ProtoMessage::InstDepRecord pkt_msg; 1248 if (trace.read(pkt_msg)) { 1249 // Required fields 1250 element->seqNum = pkt_msg.seq_num(); |
1253 element->isLoad = pkt_msg.load(); 1254 element->isStore = pkt_msg.store(); | 1251 element->type = pkt_msg.type(); |
1255 element->compDelay = pkt_msg.comp_delay(); 1256 1257 // Repeated field robDepList 1258 element->clearRobDep(); 1259 assert((pkt_msg.rob_dep()).size() <= element->maxRobDep); 1260 for (int i = 0; i < (pkt_msg.rob_dep()).size(); i++) { 1261 element->robDep[element->numRobDep] = pkt_msg.rob_dep(i); 1262 element->numRobDep += 1; --- 116 unchanged lines hidden (view full) --- 1379 // Return true if the node is dependency free 1380 return (numRobDep == 0 && numRegDep == 0); 1381} 1382 1383void 1384TraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const 1385{ 1386 DPRINTFR(TraceCPUData, "%lli", seqNum); | 1252 element->compDelay = pkt_msg.comp_delay(); 1253 1254 // Repeated field robDepList 1255 element->clearRobDep(); 1256 assert((pkt_msg.rob_dep()).size() <= element->maxRobDep); 1257 for (int i = 0; i < (pkt_msg.rob_dep()).size(); i++) { 1258 element->robDep[element->numRobDep] = pkt_msg.rob_dep(i); 1259 element->numRobDep += 1; --- 116 unchanged lines hidden (view full) --- 1376 // Return true if the node is dependency free 1377 return (numRobDep == 0 && numRegDep == 0); 1378} 1379 1380void 1381TraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const 1382{ 1383 DPRINTFR(TraceCPUData, "%lli", seqNum); |
1387 DPRINTFR(TraceCPUData, ",%s", (isLoad ? "True" : "False")); 1388 DPRINTFR(TraceCPUData, ",%s", (isStore ? "True" : "False")); 1389 if (isLoad || isStore) { | 1384 DPRINTFR(TraceCPUData, ",%s", typeToStr()); 1385 if (isLoad() || isStore()) { |
1390 DPRINTFR(TraceCPUData, ",%i", addr); 1391 DPRINTFR(TraceCPUData, ",%i", size); 1392 DPRINTFR(TraceCPUData, ",%i", flags); 1393 } 1394 DPRINTFR(TraceCPUData, ",%lli", compDelay); 1395 int i = 0; 1396 DPRINTFR(TraceCPUData, "robDep:"); 1397 while (robDep[i] != 0) { --- 11 unchanged lines hidden (view full) --- 1409 while (child_itr != dependents.end()) { 1410 DPRINTFR(TraceCPUData, ":%lli", (*child_itr)->seqNum); 1411 child_itr++; 1412 } 1413 1414 DPRINTFR(TraceCPUData, "\n"); 1415} 1416 | 1386 DPRINTFR(TraceCPUData, ",%i", addr); 1387 DPRINTFR(TraceCPUData, ",%i", size); 1388 DPRINTFR(TraceCPUData, ",%i", flags); 1389 } 1390 DPRINTFR(TraceCPUData, ",%lli", compDelay); 1391 int i = 0; 1392 DPRINTFR(TraceCPUData, "robDep:"); 1393 while (robDep[i] != 0) { --- 11 unchanged lines hidden (view full) --- 1405 while (child_itr != dependents.end()) { 1406 DPRINTFR(TraceCPUData, ":%lli", (*child_itr)->seqNum); 1407 child_itr++; 1408 } 1409 1410 DPRINTFR(TraceCPUData, "\n"); 1411} 1412 |
1413std::string 1414TraceCPU::ElasticDataGen::GraphNode::typeToStr() const 1415{ 1416 return Record::RecordType_Name(type); 1417} 1418 |
|
1417TraceCPU::FixedRetryGen::InputStream::InputStream(const std::string& filename) 1418 : trace(filename) 1419{ 1420 // Create a protobuf message for the header and read it from the stream 1421 ProtoMessage::PacketHeader header_msg; 1422 if (!trace.read(header_msg)) { 1423 panic("Failed to read packet header from %s\n", filename); 1424 --- 30 unchanged lines hidden --- | 1419TraceCPU::FixedRetryGen::InputStream::InputStream(const std::string& filename) 1420 : trace(filename) 1421{ 1422 // Create a protobuf message for the header and read it from the stream 1423 ProtoMessage::PacketHeader header_msg; 1424 if (!trace.read(header_msg)) { 1425 panic("Failed to read packet header from %s\n", filename); 1426 --- 30 unchanged lines hidden --- |