53 instMasterID(params->
system->getMasterId(this,
"inst")),
54 dataMasterID(params->
system->getMasterId(this,
"data")),
55 instTraceFile(params->instTraceFile),
56 dataTraceFile(params->dataTraceFile),
57 icacheGen(*this,
".iside", icachePort, instMasterID, instTraceFile),
58 dcacheGen(*this,
".dside", dcachePort, dataMasterID, dataTraceFile,
74 fatal_if(
params->sizeROB > UINT16_MAX,
"ROB size set to %d exceeds the " 75 "max. value of %d.\n",
params->sizeROB, UINT16_MAX);
76 fatal_if(
params->sizeStoreBuffer > UINT16_MAX,
"ROB size set to %d " 77 "exceeds the max. value of %d.\n",
params->sizeROB,
79 fatal_if(
params->sizeLoadBuffer > UINT16_MAX,
"Load buffer size set to" 80 " %d exceeds the max. value of %d.\n",
81 params->sizeLoadBuffer, UINT16_MAX);
90 TraceCPUParams::create()
116 DPRINTF(TraceCPUInst,
"Instruction fetch request trace file is \"%s\"." 118 DPRINTF(TraceCPUData,
"Data memory request trace file is \"%s\".\n",
130 traceOffset = std::min(first_icache_tick, first_dcache_tick);
131 inform(
"%s: Time offset (tick) found as min of both traces is %lli.\n",
159 DPRINTF(TraceCPUInst,
"IcacheGen event.\n");
165 DPRINTF(TraceCPUInst,
"Scheduling next icacheGen event " 184 DPRINTF(TraceCPUData,
"DcacheGen event.\n");
223 .
name(
name() +
".numSchedDcacheEvent")
224 .
desc(
"Number of events scheduled to trigger data request generator")
228 .
name(
name() +
".numSchedIcacheEvent")
229 .
desc(
"Number of events scheduled to trigger instruction request generator")
234 .
desc(
"Number of micro-ops simulated by the Trace CPU")
239 .
desc(
"Cycles per micro-op used as a proxy for CPI")
251 using namespace Stats;
254 .name(
name() +
".maxDependents")
255 .desc(
"Max number of dependents observed on a node")
259 .name(
name() +
".maxReadyListSize")
260 .desc(
"Max size of the ready list observed")
264 .name(
name() +
".numSendAttempted")
265 .desc(
"Number of first attempts to send a request")
269 .name(
name() +
".numSendSucceeded")
270 .desc(
"Number of successful first attempts")
274 .name(
name() +
".numSendFailed")
275 .desc(
"Number of failed first attempts")
279 .name(
name() +
".numRetrySucceeded")
280 .desc(
"Number of successful retries")
284 .name(
name() +
".numSplitReqs")
285 .desc(
"Number of split requests")
289 .name(
name() +
".numSOLoads")
290 .desc(
"Number of strictly ordered loads")
294 .name(
name() +
".numSOStores")
295 .desc(
"Number of strictly ordered stores")
299 .name(
name() +
".dataLastTick")
300 .desc(
"Last tick simulated from the elastic data trace")
307 DPRINTF(TraceCPUData,
"Initializing data memory request generator " 308 "DcacheGen: elastic issue with retry.\n");
310 if (!readNextWindow())
311 panic(
"Trace has %d elements. It must have at least %d elements.\n",
312 depGraph.size(), 2 * windowSize);
313 DPRINTF(TraceCPUData,
"After 1st read, depGraph size:%d.\n",
316 if (!readNextWindow())
317 panic(
"Trace has %d elements. It must have at least %d elements.\n",
318 depGraph.size(), 2 * windowSize);
319 DPRINTF(TraceCPUData,
"After 2st read, depGraph size:%d.\n",
323 if (
DTRACE(TraceCPUData)) {
326 auto free_itr = readyList.begin();
327 DPRINTF(TraceCPUData,
"Execute tick of the first dependency free node %lli" 328 " is %d.\n", free_itr->seqNum, free_itr->execTick);
331 return (free_itr->execTick);
336 for (
auto& free_node : readyList) {
337 free_node.execTick -=
offset;
352 DPRINTF(TraceCPUData,
"Reading next window from file.\n");
360 DPRINTF(TraceCPUData,
"Start read: Size of depGraph is %d.\n",
363 uint32_t num_read = 0;
364 while (num_read != windowSize) {
372 if (!trace.read(new_node)) {
373 DPRINTF(TraceCPUData,
"\tTrace complete!\n");
374 traceComplete =
true;
386 depGraph[new_node->
seqNum] = new_node;
391 checkAndIssue(new_node);
395 DPRINTF(TraceCPUData,
"End read: Size of depGraph is %d.\n",
400 template<
typename T>
void 402 T& dep_array, uint8_t& num_dep)
404 for (
auto& a_dep : dep_array) {
412 auto parent_itr = depGraph.find(a_dep);
413 if (parent_itr != depGraph.end()) {
417 parent_itr->second->dependents.push_back(new_node);
418 auto num_depts = parent_itr->second->dependents.size();
419 maxDependents = std::max<double>(num_depts, maxDependents.value());
433 DPRINTF(TraceCPUData,
"Execute start occupancy:\n");
434 DPRINTFR(TraceCPUData,
"\tdepGraph = %d, readyList = %d, " 435 "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
436 depFreeQueue.size());
437 hwResource.printOccupancy();
449 while (!depFreeQueue.empty()) {
450 if (checkAndIssue(depFreeQueue.front(),
false)) {
451 DPRINTF(TraceCPUData,
"Removing from depFreeQueue: seq. num " 452 "%lli.\n", (depFreeQueue.front())->seqNum);
459 auto graph_itr = depGraph.begin();
460 auto free_itr = readyList.begin();
463 while (free_itr->execTick <=
curTick() && free_itr != readyList.end()) {
466 graph_itr = depGraph.find(free_itr->seqNum);
467 assert(graph_itr != depGraph.end());
474 if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) {
475 panic(
"Retry packet's seqence number does not match " 476 "the first node in the readyList.\n");
478 if (port.sendTimingReq(retryPkt)) {
482 }
else if (node_ptr->isLoad() || node_ptr->isStore()) {
488 retryPkt = executeMemReq(node_ptr);
503 if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) {
505 DPRINTF(TraceCPUData,
"Node seq. num %lli sent. Waking up " 506 "dependents..\n", node_ptr->seqNum);
508 auto child_itr = (node_ptr->dependents).begin();
509 while (child_itr != (node_ptr->dependents).end()) {
512 if (!(*child_itr)->isStore() &&
513 (*child_itr)->removeRobDep(node_ptr->seqNum)) {
516 if ((*child_itr)->numRobDep == 0 &&
517 (*child_itr)->numRegDep == 0) {
521 checkAndIssue(*child_itr);
525 child_itr = node_ptr->dependents.erase(child_itr);
536 DPRINTF(TraceCPUData,
"Node seq. num %lli done. Waking" 537 " up dependents..\n", node_ptr->seqNum);
539 for (
auto child : node_ptr->dependents) {
542 if (child->removeDepOnInst(node_ptr->seqNum)) {
545 checkAndIssue(child);
551 readyList.erase(free_itr);
559 if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) {
561 hwResource.release(node_ptr);
563 (node_ptr->dependents).clear();
565 owner.updateNumOps(node_ptr->robNum);
569 depGraph.erase(graph_itr);
572 free_itr = readyList.begin();
576 if (
DTRACE(TraceCPUData)) {
578 DPRINTF(TraceCPUData,
"Execute end occupancy:\n");
579 DPRINTFR(TraceCPUData,
"\tdepGraph = %d, readyList = %d, " 580 "depFreeQueue = %d ,", depGraph.size(), readyList.size(),
581 depFreeQueue.size());
582 hwResource.printOccupancy();
586 DPRINTF(TraceCPUData,
"Not scheduling an event as expecting a retry" 587 "event from the cache for seq. num %lli.\n",
588 retryPkt->req->getReqInstSeqNum());
594 if (depGraph.size() < windowSize && !traceComplete)
601 if (!readyList.empty()) {
602 Tick next_event_tick = std::max(readyList.begin()->execTick,
604 DPRINTF(TraceCPUData,
"Attempting to schedule @%lli.\n",
606 owner.schedDcacheNextEvent(next_event_tick);
607 }
else if (readyList.empty() && !depFreeQueue.empty() &&
608 hwResource.isAvailable(depFreeQueue.front())) {
609 DPRINTF(TraceCPUData,
"Attempting to schedule @%lli.\n",
610 owner.clockEdge(
Cycles(1)));
611 owner.schedDcacheNextEvent(owner.clockEdge(
Cycles(1)));
616 if (depGraph.empty() && readyList.empty() && traceComplete &&
617 !hwResource.awaitingResponse()) {
618 DPRINTF(TraceCPUData,
"\tExecution Complete!\n");
628 DPRINTF(TraceCPUData,
"Executing memory request %lli (phys addr %d, " 629 "virt addr %d, pc %#x, size %d, flags %d).\n",
636 node_ptr->
isLoad() ? ++numSOLoads : ++numSOStores;
637 DPRINTF(TraceCPUData,
"Skipping strictly ordered request %lli.\n",
648 unsigned blk_size = owner.cacheLineSize();
650 if (!(blk_offset + node_ptr->
size <= blk_size)) {
651 node_ptr->
size = blk_size - blk_offset;
656 auto req = std::make_shared<Request>(
661 req->setPC(node_ptr->
pc);
666 node_ptr->
flags, masterID, node_ptr->
pc);
668 req->setReqInstSeqNum(node_ptr->
seqNum);
672 uint8_t* pkt_data =
new uint8_t[req->getSize()];
677 memset(pkt_data, 0xA, req->getSize());
682 bool success = port.sendTimingReq(pkt);
689 DPRINTF(TraceCPUData,
"Send failed. Saving packet for retry.\n");
706 DPRINTFR(TraceCPUData,
"\t\tseq. num %lli(%s) with rob num %lli is now" 712 if (hwResource.isAvailable(node_ptr)) {
714 DPRINTFR(TraceCPUData,
"\t\tResources available for seq. num %lli. Adding" 715 " to readyList, occupying resources.\n", node_ptr->
seqNum);
718 addToSortedReadyList(node_ptr->
seqNum,
719 owner.clockEdge() + node_ptr->
compDelay);
721 hwResource.occupy(node_ptr);
727 DPRINTFR(TraceCPUData,
"\t\tResources unavailable for seq. num %lli." 728 " Adding to depFreeQueue.\n", node_ptr->
seqNum);
729 depFreeQueue.push(node_ptr);
731 DPRINTFR(TraceCPUData,
"\t\tResources unavailable for seq. num %lli. " 732 "Still pending issue.\n", node_ptr->
seqNum);
744 hwResource.releaseStoreBuffer();
752 auto graph_itr = depGraph.find(pkt->
req->getReqInstSeqNum());
753 assert(graph_itr != depGraph.end());
757 hwResource.release(node_ptr);
759 DPRINTF(TraceCPUData,
"Load seq. num %lli response received. Waking up" 760 " dependents..\n", node_ptr->seqNum);
762 for (
auto child : node_ptr->dependents) {
763 if (child->removeDepOnInst(node_ptr->seqNum)) {
764 checkAndIssue(child);
769 (node_ptr->dependents).clear();
771 owner.updateNumOps(node_ptr->robNum);
775 depGraph.erase(graph_itr);
778 if (
DTRACE(TraceCPUData)) {
785 if (depGraph.size() < windowSize && !traceComplete)
797 Tick next_event_tick = readyList.empty() ? owner.clockEdge(
Cycles(1)) :
798 std::max(readyList.begin()->execTick, owner.clockEdge(
Cycles(1)));
799 DPRINTF(TraceCPUData,
"Attempting to schedule @%lli.\n",
801 owner.schedDcacheNextEvent(next_event_tick);
810 ready_node.
seqNum = seq_num;
814 auto itr = readyList.begin();
818 if (itr == readyList.end()) {
819 readyList.insert(itr, ready_node);
820 maxReadyListSize = std::max<double>(readyList.size(),
821 maxReadyListSize.value());
829 if (retryPkt->req->getReqInstSeqNum() == itr->seqNum)
835 while (!found && itr != readyList.end()) {
838 if (exec_tick < itr->execTick)
842 else if (exec_tick == itr->execTick) {
845 if (seq_num < itr->seqNum)
856 readyList.insert(itr, ready_node);
858 maxReadyListSize = std::max<double>(readyList.size(),
859 maxReadyListSize.value());
865 auto itr = readyList.begin();
866 if (itr == readyList.end()) {
867 DPRINTF(TraceCPUData,
"readyList is empty.\n");
870 DPRINTF(TraceCPUData,
"Printing readyList:\n");
871 while (itr != readyList.end()) {
872 auto graph_itr = depGraph.find(itr->seqNum);
874 DPRINTFR(TraceCPUData,
"\t%lld(%s), %lld\n", itr->seqNum,
875 node_ptr->typeToStr(), itr->execTick);
881 uint16_t max_rob, uint16_t max_stores, uint16_t max_loads)
883 sizeStoreBuffer(max_stores),
884 sizeLoadBuffer(max_loads),
885 oldestInFlightRobNum(UINT64_MAX),
902 }
else if (new_node->
isStore()) {
913 DPRINTFR(TraceCPUData,
"\tClearing done seq. num %d from inFlightNodes..\n",
929 DPRINTFR(TraceCPUData,
"\tCleared. inFlightNodes.size() = %d, " 937 if (done_node->
isLoad()) {
961 uint16_t num_in_flight_nodes;
963 num_in_flight_nodes = 0;
964 DPRINTFR(TraceCPUData,
"\t\tChecking resources to issue seq. num %lli:" 965 " #in-flight nodes = 0", new_node->
seqNum);
971 DPRINTFR(TraceCPUData,
"\t\tChecking resources to issue seq. num %lli:" 972 " #in-flight nodes = %d - %d = %d", new_node->
seqNum,
980 num_in_flight_nodes = 0;
981 DPRINTFR(TraceCPUData,
"\t\tChecking resources to issue seq. num %lli:" 982 " new oldestInFlightRobNum = %d, #in-flight nodes ignored",
985 DPRINTFR(TraceCPUData,
", LQ = %d/%d, SQ = %d/%d.\n",
989 if (num_in_flight_nodes >=
sizeROB) {
1009 DPRINTFR(TraceCPUData,
"oldestInFlightRobNum = %d, " 1010 "LQ = %d/%d, SQ = %d/%d.\n",
1019 using namespace Stats;
1022 .
name(
name() +
".numSendAttempted")
1023 .
desc(
"Number of first attempts to send a request")
1027 .
name(
name() +
".numSendSucceeded")
1028 .
desc(
"Number of successful first attempts")
1033 .
desc(
"Number of failed first attempts")
1037 .
name(
name() +
".numRetrySucceeded")
1038 .
desc(
"Number of successful retries")
1043 .
desc(
"Last tick simulated from the fixed inst trace")
1050 DPRINTF(TraceCPUInst,
"Initializing instruction fetch request generator" 1051 " IcacheGen: fixed issue with retry.\n");
1053 if (nextExecute()) {
1054 DPRINTF(TraceCPUInst,
"\tFirst tick = %d.\n", currElement.tick);
1055 return currElement.tick;
1057 panic(
"Read of first message in the trace failed.\n");
1068 DPRINTF(TraceCPUInst,
"Trying to send retry packet.\n");
1072 DPRINTF(TraceCPUInst,
"Retry packet sending failed.\n");
1078 DPRINTF(TraceCPUInst,
"Trying to send packet for currElement.\n");
1081 assert(currElement.isValid());
1085 if (!send(currElement.addr, currElement.blocksize,
1086 currElement.cmd, currElement.flags, currElement.pc)) {
1087 DPRINTF(TraceCPUInst,
"currElement sending failed.\n");
1098 DPRINTF(TraceCPUInst,
"Packet sent successfully, trying to read next " 1103 Tick last_tick = currElement.tick;
1104 if (nextExecute()) {
1105 assert(currElement.tick >= last_tick);
1106 delta = currElement.tick - last_tick;
1127 currElement.clear();
1138 DPRINTF(TraceCPUInst,
"inst fetch: %c addr %d pc %#x size %d tick %d\n",
1139 currElement.cmd.isRead() ?
'r' :
'w',
1142 currElement.blocksize,
1154 auto req = std::make_shared<Request>(
addr, size, flags,
masterID);
1163 uint8_t* pkt_data =
new uint8_t[req->getSize()];
1167 memset(pkt_data, 0xA, req->getSize());
1185 DPRINTF(TraceCPUInst,
"Icache retry received. Scheduling next IcacheGen" 1186 " event @%lli.\n",
curTick());
1195 DPRINTF(TraceCPUData,
"Dcache retry received. Scheduling next DcacheGen" 1196 " event @%lli.\n",
curTick());
1204 DPRINTF(TraceCPUData,
"Scheduling next DcacheGen event at %lli.\n",
1209 DPRINTF(TraceCPUData,
"Re-scheduling next dcache event from %lli" 1235 DPRINTF(TraceCPUData,
"Received timing response from Dcache.\n");
1259 const std::string& filename,
1260 const double time_multiplier)
1262 timeMultiplier(time_multiplier),
1266 ProtoMessage::InstDepRecordHeader header_msg;
1268 panic(
"Failed to read packet header from %s\n", filename);
1271 panic(
"Trace %s was recorded with a different tick frequency %d\n",
1272 header_msg.tick_freq());
1290 ProtoMessage::InstDepRecord pkt_msg;
1293 element->
seqNum = pkt_msg.seq_num();
1294 element->
type = pkt_msg.type();
1300 assert((pkt_msg.rob_dep()).size() <= element->
maxRobDep);
1301 for (
int i = 0;
i < (pkt_msg.rob_dep()).size();
i++) {
1309 for (
int i = 0;
i < (pkt_msg.reg_dep()).size();
i++) {
1313 bool duplicate =
false;
1315 duplicate |= (pkt_msg.reg_dep(
i) == element->
robDep[
j]);
1324 if (pkt_msg.has_p_addr())
1325 element->
physAddr = pkt_msg.p_addr();
1329 if (pkt_msg.has_v_addr())
1330 element->
virtAddr = pkt_msg.v_addr();
1334 if (pkt_msg.has_asid())
1335 element->
asid = pkt_msg.asid();
1339 if (pkt_msg.has_size())
1340 element->
size = pkt_msg.size();
1344 if (pkt_msg.has_flags())
1345 element->
flags = pkt_msg.flags();
1349 if (pkt_msg.has_pc())
1350 element->
pc = pkt_msg.pc();
1356 if (pkt_msg.has_weight()) {
1370 for (
auto& own_reg_dep : regDep) {
1371 if (own_reg_dep == reg_dep) {
1374 assert(numRegDep > 0);
1376 DPRINTFR(TraceCPUData,
"\tFor %lli: Marking register dependency %lli " 1377 "done.\n", seqNum, reg_dep);
1389 for (
auto& own_rob_dep : robDep) {
1390 if (own_rob_dep == rob_dep) {
1393 assert(numRobDep > 0);
1395 DPRINTFR(TraceCPUData,
"\tFor %lli: Marking ROB dependency %lli " 1396 "done.\n", seqNum, rob_dep);
1405 for (
auto& own_reg_dep : regDep) {
1413 for (
auto& own_rob_dep : robDep) {
1423 if (!removeRobDep(done_seq_num)) {
1427 bool regdep_found
M5_VAR_USED = removeRegDep(done_seq_num);
1428 assert(regdep_found);
1431 return (numRobDep == 0 && numRegDep == 0);
1437 DPRINTFR(TraceCPUData,
"%lli", seqNum);
1438 DPRINTFR(TraceCPUData,
",%s", typeToStr());
1439 if (isLoad() || isStore()) {
1441 DPRINTFR(TraceCPUData,
",%i", size);
1442 DPRINTFR(TraceCPUData,
",%i", flags);
1444 DPRINTFR(TraceCPUData,
",%lli", compDelay);
1447 while (robDep[i] != 0) {
1448 DPRINTFR(TraceCPUData,
",%lli", robDep[i]);
1453 while (regDep[i] != 0) {
1454 DPRINTFR(TraceCPUData,
",%lli", regDep[i]);
1457 auto child_itr = dependents.begin();
1458 DPRINTFR(TraceCPUData,
"dependents:");
1459 while (child_itr != dependents.end()) {
1460 DPRINTFR(TraceCPUData,
":%lli", (*child_itr)->seqNum);
1470 return Record::RecordType_Name(
type);
1477 ProtoMessage::PacketHeader header_msg;
1479 panic(
"Failed to read packet header from %s\n", filename);
1482 panic(
"Trace %s was recorded with a different tick frequency %d\n",
1483 header_msg.tick_freq());
1499 element->
cmd = pkt_msg.
cmd();
1500 element->
addr = pkt_msg.addr();
1502 element->
tick = pkt_msg.tick();
1503 element->
flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0;
1504 element->
pc = pkt_msg.has_pc() ? pkt_msg.pc() : 0;
InputStream trace
Input stream used for reading the input trace file.
void execute()
This is the main execute function which consumes nodes from the sorted readyList. ...
#define panic(...)
This implements a cprintf based panic() function.
Struct to store a ready-to-execute node and its execution tick.
void schedDcacheNext()
This is the control flow that uses the functionality of the dcacheGen to replay the trace...
const uint16_t sizeStoreBuffer
The size of store buffer.
const uint64_t progressMsgInterval
Interval of committed instructions specified by the user at which a progress info message is printed...
bool send(Addr addr, unsigned size, const MemCmd &cmd, Request::FlagsType flags, Addr pc)
Creates a new request assigning the request parameters passed by the arguments.
bool isStore() const
Is the node a store.
Addr blocksize
The size of the access for the request.
TraceCPU & owner
Reference of the TraceCPU.
Cycles is a wrapper class for representing cycle counts, i.e.
NodeSeqNum seqNum
The sequence number of the ready node.
void exit()
Exit the FixedRetryGen.
void recvReqRetry()
Handle a retry signalled by the cache if data access failed in the first attempt. ...
bool isTraceComplete()
Returns the traceComplete variable which is set when end of the input trace file is reached...
EventFunctionWrapper dcacheNextEvent
Event for the control flow method schedDcacheNext()
bool removeRegDep(NodeSeqNum reg_dep)
Remove completed instruction from register dependency array.
Tick when() const
Get the time that the event is scheduled.
uint16_t numInFlightStores
Number of ready stores for which request may or may not be sent.
Request::Flags flags
Request flags if any.
RecordType type
Type of the node corresponding to the instruction modelled by it.
PacketPtr retryPkt
PacketPtr used to store the packet to retry.
Stats::Scalar numSchedIcacheEvent
bool nextExecute()
Reads a line of the trace file.
void updateNumOps(uint64_t rob_num)
HardwareResource(uint16_t max_rob, uint16_t max_stores, uint16_t max_loads)
Constructor that initializes the sizes of the structures.
PacketPtr executeMemReq(GraphNode *node_ptr)
Creates a new request for a load or store assigning the request parameters.
Request::FlagsType flags
Potential request flags to use.
void completeMemAccess(PacketPtr pkt)
When a load writeback is received, that is when the load completes, release the dependents on it...
static PacketPtr createWrite(const RequestPtr &req)
std::map< NodeSeqNum, NodeRobNum > inFlightNodes
A map from the sequence number to the ROB number of the in- flight nodes.
void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Tick traceOffset
This stores the time offset in the trace, which is taken away from the ready times of requests...
bool isExecComplete() const
Returns the execComplete variable which is set when the last node is executed.
Port & getInstPort()
Used to get a reference to the icache port.
std::string instTraceFile
File names for input instruction and data traces.
void exit()
Exit the ElasticDataGen.
void regStats()
Callback to set stat parameters.
uint32_t asid
The address space id which is set if the virtual address is set.
static const uint8_t maxRobDep
The maximum no.
bool recvTimingResp(PacketPtr pkt)
Receive the timing reponse and simply delete the packet since instruction fetch requests are issued a...
const uint16_t sizeROB
The size of the ROB used to throttle the max.
void checkAndSchedExitEvent()
This is called when either generator finishes executing from the trace.
bool oneTraceComplete
Set to true when one of the generators finishes replaying its trace.
void schedIcacheNext()
This is the control flow that uses the functionality of the icacheGen to replay the trace...
Stats::Scalar numSchedDcacheEvent
MemCmd cmd
Specifies if the request is to be a read or a write.
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
void clearRobDep()
Initialize register dependency array to all zeroes.
uint64_t NodeSeqNum
Node sequence number type.
bool readNextWindow()
Reads a line of the trace file.
uint8_t numRegDep
Number of register dependencies.
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
void addDepsOnParent(GraphNode *new_node, T &dep_array, uint8_t &num_dep)
Iterate over the dependencies of a new node and add the new node to the list of dependents of the par...
Stats::Scalar numSendSucceeded
bool traceComplete
Set to true when end of trace is reached.
Tick init()
Called from TraceCPU init().
void clearRegDep()
Initialize register dependency array to all zeroes.
RequestPtr req
A pointer to the original request.
void regStats() override
Callback to set stat parameters.
CountedExitEvent * execCompleteEvent
A CountedExitEvent which when serviced decrements the counter.
Tick curTick()
The current simulated tick.
bool awaitingResponse() const
Check if there are any outstanding requests, i.e.
virtual Port & getInstPort()=0
Purely virtual method that returns a reference to the instruction port.
bool isStrictlyOrdered() const
Return true if node has a request which is strictly ordered.
bool scheduled() const
Determine if the current event is scheduled.
The trace cpu replays traces generated using the elastic trace probe attached to the O3 CPU model...
uint64_t progressMsgThreshold
NodeRobNum robNum
ROB occupancy number.
TraceCPU(TraceCPUParams *params)
uint64_t Tick
Tick count type.
const bool enableEarlyExit
Exit when any one Trace CPU completes its execution.
EventFunctionWrapper icacheNextEvent
Event for the control flow method schedIcacheNext()
The struct GraphNode stores an instruction in the trace file.
This struct stores a line in the trace file.
void dcacheRetryRecvd()
When data cache port receives a retry, schedule event dcacheNextEvent.
FixedRetryGen icacheGen
Instance of FixedRetryGen to replay instruction read requests.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
void recvReqRetry()
Handle a retry signalled by the cache if instruction read failed in the first attempt.
bool isAvailable(const GraphNode *new_node) const
Check if structures required to issue a node are free.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void release(const GraphNode *done_node)
Release appropriate structures for a completed node.
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
uint16_t numInFlightLoads
Number of ready loads for which request may or may not be sent.
uint64_t compDelay
Computational delay.
MasterPort & port
Reference of the port to be used to issue memory requests.
virtual const std::string name() const
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
static int numTraceCPUs
Number of Trace CPUs in the system used as a shared variable and passed to the CountedExitEvent event...
Stats::Formula cpi
Stat for the CPI.
void dcacheRecvTimingResp(PacketPtr pkt)
When data cache port receives a response, this calls the dcache generator method handle to complete t...
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Tick execTick
The tick at which the ready node must be executed.
NodeRobNum oldestInFlightRobNum
The ROB number of the oldest in-flight node.
const uint16_t sizeLoadBuffer
The size of load buffer.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Stats::Scalar numOps
Stat for number of simulated micro-ops.
void reschedule(Event &event, Tick when, bool always=false)
bool checkAndIssue(const GraphNode *node_ptr, bool first=true)
Attempts to issue a node once the node's source dependencies are complete.
const MasterID masterID
MasterID used for the requests being sent.
Tick tick
The time at which the request should be sent.
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
bool recvTimingResp(PacketPtr pkt)
Receive the timing reponse and call dcacheRecvTimingResp() method of the dcacheGen to handle completi...
uint8_t numRobDep
Number of order dependencies.
Stats::Scalar numSendFailed
void schedDcacheNextEvent(Tick when)
Schedule event dcacheNextEvent at the given tick.
std::string dataTraceFile
Stats::Scalar numSendAttempted
ElasticDataGen dcacheGen
Instance of ElasticDataGen to replay data read and write requests.
Addr virtAddr
The virtual address for the request if any.
uint32_t size
Size of request if any.
void takeOverFrom(Port *old)
A utility function to make it easier to swap out ports.
void printReadyList()
Print readyList for debugging using debug flag TraceCPUData.
bool isLoad() const
Is the node a load.
void releaseStoreBuffer()
Release store buffer entry for a completed store.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void adjustInitTraceOffset(Tick &offset)
Adjust traceOffset based on what TraceCPU init() determines on comparing the offsets in the fetch req...
void occupy(const GraphNode *new_node)
Occupy appropriate structures for an issued node.
virtual Port & getDataPort()=0
Purely virtual method that returns a reference to the data port.
RegDepArray regDep
Array of register dependencies (incoming) if any.
Stats::Scalar numRetrySucceeded
void schedule(Event &event, Tick when)
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Addr addr
The address for the request.
Tick init()
Called from TraceCPU init().
Port & getDataPort()
Used to get a reference to the dcache port.
void icacheRetryRecvd()
When instruction cache port receives a retry, schedule event icacheNextEvent.
Addr physAddr
The address for the request if any.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
void printOccupancy()
Print resource occupancy for debugging.
void addToSortedReadyList(NodeSeqNum seq_num, Tick exec_tick)
Add a ready node to the readyList.
static const int NumArgumentRegs M5_VAR_USED
void writeElementAsTrace() const
Write out element in trace-compatible format using debug flag TraceCPUData.
RobDepArray robDep
Array of order dependencies.
const Params * params() const
std::string typeToStr() const
Return string specifying the type of the node.
void takeOverFrom(BaseCPU *oldCPU)
Load the state of a CPU from the previous CPU object, invoked on all new CPUs that are about to be sw...
Counter value() const
Return the current value of this stat as its base type.
int ContextID
Globally unique thread context ID.
const std::string & name() const
Returns name of the ElasticDataGen instance.
NodeSeqNum seqNum
Instruction sequence number.
bool removeRobDep(NodeSeqNum rob_dep)
Remove completed instruction from order dependency array.
bool removeDepOnInst(NodeSeqNum done_seq_num)
Check for all dependencies on completed inst.
ProbePointArg< PacketInfo > Packet
Packet probe point.
bool tryNext()
This tries to send current or retry packet and returns true if successfull.