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 ---