From 5202fed69301b40e615c843ac9e48730d7bf6fd6 Mon Sep 17 00:00:00 2001 From: Aditya Badole Date: Mon, 7 Aug 2023 14:07:18 +0800 Subject: [PATCH] - Now commit is issuing any RC updates if Rd is overwritten Change-Id: Ie5ee07858d357b023d9c8b9ddc8636a710adbba3 --- src/arch/riscvcapstone/isa/decoder.isa | 10 ++-- src/arch/riscvcapstone/o3/commit.cc | 21 +++++++-- src/arch/riscvcapstone/o3/ncq_unit.cc | 54 ++++++++++++++++++---- src/arch/riscvcapstone/o3/node_commands.cc | 3 +- src/arch/riscvcapstone/o3/node_commands.hh | 2 + src/base/circular_queue.hh | 23 +++++++++ 6 files changed, 96 insertions(+), 17 deletions(-) diff --git a/src/arch/riscvcapstone/isa/decoder.isa b/src/arch/riscvcapstone/isa/decoder.isa index adcaf1c99c..d8c7913fee 100644 --- a/src/arch/riscvcapstone/isa/decoder.isa +++ b/src/arch/riscvcapstone/isa/decoder.isa @@ -951,7 +951,7 @@ decode QUADRANT default Unknown::unknown() { "Illegal write - out of capability bounds!", machInst); Mem_rv = Rs1_trv.getRegVal(); - + //if EA is not aligned, exception/fault Fault fault = dyn_inst->initiateGetTag(EA); if(fault != NoFault) return fault; @@ -1300,6 +1300,7 @@ decode QUADRANT default Unknown::unknown() { Rd_trv = Rd_trv; // just to make the dumb parser happy }}); 0x6: captype ({{ + assert(Rd_trv.getTag()); using CapType = gem5::RiscvcapstoneISA::o3::CapType; CapType temp = static_cast(Rs1); assert(temp >= CapType::LIN && temp <= CapType::SEALEDRET); @@ -1307,11 +1308,13 @@ decode QUADRANT default Unknown::unknown() { Rd_trv = Rd_trv; // just to make the dumb parser happy }}); 0x7: capnode ({{ + assert(Rd_trv.getTag()); using namespace gem5::RiscvcapstoneISA::o3; Rd_trv.getRegVal().val.cap.setNodeId(static_cast(Rs1)); Rd_trv = Rd_trv; // just to make the dumb parser happy }}); 0x8: capperm ({{ + assert(Rd_trv.getTag()); using CapPerm = gem5::RiscvcapstoneISA::o3::CapPerm; CapPerm temp = static_cast(Rs1); assert(temp >= CapPerm::NA && temp <= CapPerm::RWX); @@ -1319,6 +1322,7 @@ decode QUADRANT default Unknown::unknown() { Rd_trv = Rd_trv; // just to make the dumb parser happy }}); 0x9: capbound ({{ + assert(Rd_trv.getTag()); //DPRINTFN("Set capability bound to (%llx, %llx)\n", Rs1, Rs2); Rd_trv.getRegVal().val.cap.setAddresses(Rs1, Rs2, Rs1); Rd_trv = Rd_trv; // just to make the dumb parser happy @@ -1332,13 +1336,13 @@ decode QUADRANT default Unknown::unknown() { static_cast(reg_val.val.cap.perm()), static_cast(reg_val.val.cap.type()), reg_val.val.cap.nodeId()); - }}, IsSerializing, IsNonSpeculative); + }}, IsSerializing, IsNonSpeculative, IsSerializeAfter); 0xd: printregs ({{ using namespace gem5::RiscvcapstoneISA::o3; DynInst *dyn_inst = dynamic_cast(xc); assert(dyn_inst); dyn_inst->printRegs(); - }}, IsSerializing, IsNonSpeculative); + }}, IsSerializing, IsNonSpeculative, IsSerializeAfter); 0xe: getrand ({{ srand(time(NULL)); Rd = (rand() % (Rs2 - Rs1) + Rs1) & 0xFFFFFFFFFFFFFFF0; diff --git a/src/arch/riscvcapstone/o3/commit.cc b/src/arch/riscvcapstone/o3/commit.cc index bd107e0072..b24c7e3dbc 100644 --- a/src/arch/riscvcapstone/o3/commit.cc +++ b/src/arch/riscvcapstone/o3/commit.cc @@ -1225,10 +1225,25 @@ Commit::commitHead(const DynInstPtr &head_inst, unsigned inst_num) // } // } //very, very hacked together - if(head_inst->staticInst->opClass() != No_OpClass && head_inst->staticInst->getName() != "captype" - && head_inst->staticInst->getName() != "capperm" && head_inst->staticInst->getName() != "capnode") { + if(head_inst->staticInst->opClass() != No_OpClass && head_inst->staticInst->getName() != "capperm" && + head_inst->staticInst->getName() != "captype" && head_inst->staticInst->getName() != "capnode" && + head_inst->staticInst->getName() != "capbound" && head_inst->staticInst->getName() != "stc" && + head_inst->staticInst->getName() != "std" && head_inst->staticInst->getName() != "stb" && + head_inst->staticInst->getName() != "sth" && head_inst->staticInst->getName() != "stw" && + head_inst->staticInst->getName() != "capcreate" && head_inst->staticInst->getName() != "capprint" && + head_inst->numDestRegs() > 0) { + if(iewStage->ncQueue.isFull(tid)) { + DPRINTF(Commit, "[tid:%i] NCQ has become full.\n", tid); + //block(tid); + //send signals to previous stages to block + // toIEW->iewBlock[tid] = true; + return false; + // } else if(toIEW->iewBlock[tid]) { + // toIEW->iewBlock[tid] = false; + // toIEW->iewUnblock[tid] = true; + } CPU* cpu = dynamic_cast(head_inst->getCpuPtr()); - PhysRegIdPtr prev_reg = head_inst->prevDestIdx(0); + PhysRegIdPtr prev_reg = head_inst->prevDestIdx(0); //FIXME: this may be 0, may not be 0 if(!(prev_reg->classValue() == InvalidRegClass || prev_reg->classValue() == MiscRegClass)) { TaggedRegVal tagged_reg = cpu->getWritableTaggedReg(prev_reg); if(tagged_reg.getTag()) { diff --git a/src/arch/riscvcapstone/o3/ncq_unit.cc b/src/arch/riscvcapstone/o3/ncq_unit.cc index b9bafe768a..e705969919 100644 --- a/src/arch/riscvcapstone/o3/ncq_unit.cc +++ b/src/arch/riscvcapstone/o3/ncq_unit.cc @@ -45,6 +45,7 @@ NCQUnit::tick() { void NCQUnit::dumpNcQueue() { + DPRINTF(NCQ, "Dumping the NCQ\n"); for(size_t i = ncQueue.head(); i <= ncQueue.tail(); i++) { if(ncQueue[i].inst) DPRINTF(NCQ, "Instruction = %u\n", ncQueue[i].inst->seqNum); @@ -65,6 +66,8 @@ NCQUnit::pushCommand(const DynInstPtr& inst, NodeCommandPtr cmd) { ncq_entry.commands.push_back(cmd); + dumpNcQueue(); + return NoFault; } @@ -80,8 +83,7 @@ NCQUnit::pushCommand(NodeCommandPtr cmd) { ncq_entry.commands.push_back(cmd); ncq_entry.seqNum = cmd->seqNum; - - cmd->dump(); + cmd->ncq_ptr = &ncq_entry; dumpNcQueue(); @@ -90,6 +92,7 @@ NCQUnit::pushCommand(NodeCommandPtr cmd) { bool NCQUnit::isFull() { + dumpNcQueue(); return ncQueue.full(); } @@ -111,11 +114,20 @@ NCQUnit::commitBefore(InstSeqNum seq_num) { void NCQUnit::cleanupCommands(){ + DPRINTF(NCQ, "Cleaning up commands\n"); while(!ncQueue.empty()) { auto& front = ncQueue.front(); + if(front.inst) + DPRINTF(NCQ, "cleanupCommands: inst %u, canWB %u, completed() %u, commands size() %u", front.inst->seqNum, front.canWB, front.completed(), front.commands.size()); + else + DPRINTF(NCQ, "cleanupCommands: inst %u, canWB %u, completed() %u, commands size() %u from commit", front.seqNum, front.canWB, front.completed(), front.commands.size()); if(front.canWB && front.completed()) { - if(front.inst) + if(front.inst) { + DPRINTF(NCQ, "Removing NCQEntry for instruction %u\n", front.inst->seqNum); front.inst->ncqIdx = -1; + } + else + DPRINTF(NCQ, "Removing NCQEntry for instruction %u from commit\n", front.seqNum); front.clear(); ncQueue.pop_front(); } else{ @@ -139,7 +151,7 @@ NCQUnit::writebackCommands(){ DPRINTF(NCQ, "Instruction %u with %u commands (completed = %u)\n", it->inst->seqNum, commands.size(), it->completedCommands); else - DPRINTF(NCQ, "Inst is null. Command from commit.\n"); + DPRINTF(NCQ, "Instruction = %u. Command from commit.\n", it->seqNum); for(NodeCommandIterator nc_it = commands.begin(); nc_it != commands.end() && ncq->canSend(); ++ nc_it) { @@ -168,6 +180,13 @@ NCQUnit::writebackCommands(){ DPRINTF(NCQ, "Checking command dependencies\n"); + InstSeqNum sn, sn_o; + + if(it->inst) + sn = it->inst->seqNum; + else + sn = it->seqNum; + // check for dependencies // the naive way. Bruteforce bool dep_ready = true; @@ -180,14 +199,22 @@ NCQUnit::writebackCommands(){ ++ nc_it_o) { NodeCommandPtr nc_ptr_o = *nc_it_o; assert(nc_ptr_o); - if(nc_ptr_o->status != NodeCommand::COMPLETED && + if(it_o->inst) + sn_o = it_o->inst->seqNum; + else + sn_o = it_o->seqNum; + /** compare seqNum because commands from commit may be issued + * after commands from execute. + * there might be a better way to do it though + */ + if(nc_ptr_o->status != NodeCommand::COMPLETED && sn_o < sn && !ncOrder.reorderAllowed(nc_ptr_o, nc_ptr)){ dep_ready = false; break; } } - if(it_o == it) - break; + // if(it_o == it) + // break; } if(!dep_ready) @@ -196,6 +223,9 @@ NCQUnit::writebackCommands(){ if(it->inst) DPRINTF(NCQ, "Command ready to execute (instruction %u)\n", it->inst->seqNum); + else + DPRINTF(NCQ, "Command ready to execute (instruction %u)\n", + it->seqNum); // the command can be executed // one state transition in the state machine @@ -218,7 +248,6 @@ NCQUnit::writebackCommands(){ } } - void NCQUnit::completeCommand(NodeCommandPtr node_command){ DynInstPtr& inst = node_command->inst; @@ -236,6 +265,8 @@ NCQUnit::completeCommand(NodeCommandPtr node_command){ inst->setNodeExecuted(); iew->instToCommitIfExeced(inst); } + } else { + ++node_command->ncq_ptr->completedCommands; } } @@ -291,6 +322,8 @@ NCQUnit::passedQuery(const DynInstPtr& inst) const { void NCQUnit::squash(const InstSeqNum &squashed_num) { if(!ncQueue.empty()) { + DPRINTF(NCQ, "Squashing till seqNum = %u. NcQueue so far:\n", squashed_num); + dumpNcQueue(); NCQIterator temp = ncQueue.end() - 1; // while(!ncQueue.empty()) { // if(ncQueue.back().inst && ncQueue.back().inst->seqNum > squashed_num) { @@ -302,12 +335,13 @@ NCQUnit::squash(const InstSeqNum &squashed_num) { // } // } for( ;!ncQueue.empty() && temp != ncQueue.begin(); temp--) { - NCQEntry ncq = *temp; + NCQEntry &ncq = *temp; if(ncq.inst && ncq.inst->seqNum > squashed_num) { + DPRINTF(NCQ, "Squashing NCQ entry for seqNum = %u\n", ncq.inst->seqNum); ncq.inst->setSquashed(); ncq.inst->ncqIdx = -1; ncq.clear(); - ncQueue.pop_back(); + ncQueue.pop_i(temp.idx()); } } } diff --git a/src/arch/riscvcapstone/o3/node_commands.cc b/src/arch/riscvcapstone/o3/node_commands.cc index 02fe531464..0aa4311aeb 100644 --- a/src/arch/riscvcapstone/o3/node_commands.cc +++ b/src/arch/riscvcapstone/o3/node_commands.cc @@ -8,6 +8,7 @@ #include "arch/riscvcapstone/o3/node.hh" #include "arch/riscvcapstone/insts/amo.hh" #include "debug/NodeCmd.hh" +#include "arch/riscvcapstone/o3/ncq_unit.hh" namespace gem5 { namespace RiscvcapstoneISA { @@ -139,7 +140,7 @@ NodeAllocate::handleResp(PacketPtr pkt) { savedNode.depth = parentDepth + (asChild ? 1 : 0); savedNode.next = nextNodeId; savedNode.state = Node::VALID; - savedNode.counter = 0; // TODO: perhaps 1 + savedNode.counter = 1; // TODO: perhaps 1 state = NCAllocate_STORE; status = TO_RESUME; diff --git a/src/arch/riscvcapstone/o3/node_commands.hh b/src/arch/riscvcapstone/o3/node_commands.hh index 063ed4843e..071548e88d 100644 --- a/src/arch/riscvcapstone/o3/node_commands.hh +++ b/src/arch/riscvcapstone/o3/node_commands.hh @@ -15,6 +15,7 @@ namespace o3 { class NodeCommandCondition; class NCQ; +struct NCQEntry; /** * base class for all commands to node controller @@ -40,6 +41,7 @@ struct NodeCommand { DynInstPtr inst; InstSeqNum seqNum; CPU *cpu; + NCQEntry *ncq_ptr; bool canWB; std::unique_ptr condition; // the returned data and size diff --git a/src/base/circular_queue.hh b/src/base/circular_queue.hh index 63d60a55f5..ca791925d2 100644 --- a/src/base/circular_queue.hh +++ b/src/base/circular_queue.hh @@ -493,6 +493,29 @@ class CircularQueue --_size; } + /** + * @brief Pop ith element. Guess it's not a queue anymore + * + * @param idx index of the element to be popped + */ + void + pop_i(size_t idx) + { + assert(!empty() && idx <= tail()); + + if(idx == tail()) { + --_size; + return; + } + + for(size_t i = idx; i <= tail() - 1; i++) + { + data[i] = data[i+1]; + } + + --_size; + } + /** * Pushes an element at the end of the queue. *