From 648a31661e317c245deadae6ac2e29fd0bc063ef Mon Sep 17 00:00:00 2001 From: danbone Date: Mon, 8 Jan 2024 20:19:48 +0000 Subject: [PATCH] Fix end of simulation empty buffer checks in LSU (#138) I noticed that the buffer empty termination checks weren't working as intended. Co-authored-by: Daniel Bone --- core/Inst.hpp | 6 ------ core/InstGenerator.cpp | 6 ------ core/LSU.cpp | 11 +++++------ core/LSU.hpp | 26 ++++++++++++++++---------- core/ROB.cpp | 20 ++++++-------------- core/ROB.hpp | 2 +- 6 files changed, 28 insertions(+), 43 deletions(-) diff --git a/core/Inst.hpp b/core/Inst.hpp index 4fcd61aa..d18492cf 100644 --- a/core/Inst.hpp +++ b/core/Inst.hpp @@ -143,11 +143,6 @@ namespace olympia } bool isMarkedOldest() const { return is_oldest_; } - // Instruction trace/JSON generation -- mark instruction as - // last in trace/JSON file. - void setLast() { is_last_ = true; } - bool getLast() const { return is_last_; } - // Set the instructions unique ID. This ID in constantly // incremented and does not repeat. The same instruction in a // trace can have different unique IDs (due to flushing) @@ -223,7 +218,6 @@ namespace olympia sparta::memory::addr_t inst_pc_ = 0; // Instruction's PC sparta::memory::addr_t target_vaddr_ = 0; // Instruction's Target PC (for branches, loads/stores) bool is_oldest_ = false; - bool is_last_ = false; // Is last intruction of trace uint64_t unique_id_ = 0; // Supplied by Fetch uint64_t program_id_ = 0; // Supplied by a trace Reader or execution backend bool is_speculative_ = false; // Is this instruction soon to be flushed? diff --git a/core/InstGenerator.cpp b/core/InstGenerator.cpp index 2d5eaba7..1c90f4da 100644 --- a/core/InstGenerator.cpp +++ b/core/InstGenerator.cpp @@ -106,9 +106,6 @@ namespace olympia ++curr_inst_index_; inst->setUniqueID(++unique_id_); inst->setProgramID(unique_id_); - if(isDone()) { - inst->setLast(); - } return inst; } @@ -177,9 +174,6 @@ namespace olympia //inst->setVAddrVector(std::move(addrs)); } ++next_it_; - if(isDone()) { - inst->setLast(); - } return inst; } catch(std::exception & excpt) { diff --git a/core/LSU.cpp b/core/LSU.cpp index 630f89bd..ee5172d0 100644 --- a/core/LSU.cpp +++ b/core/LSU.cpp @@ -94,8 +94,8 @@ namespace olympia ldst_pipeline_.registerHandlerAtStage(cache_lookup_stage_, CREATE_SPARTA_HANDLER(LSU, handleCacheLookupReq_)); - node->getParent()->registerForNotification( - this, "rob_notif_channel", false /* ROB maybe not be constructed yet */); + node->getParent()->registerForNotification( + this, "rob_stopped_notif_channel", false /* ROB maybe not be constructed yet */); ldst_pipeline_.registerHandlerAtStage(cache_read_stage_, CREATE_SPARTA_HANDLER(LSU, handleCacheRead_)); @@ -111,8 +111,6 @@ namespace olympia ILOG("LSU construct: #" << node->getGroupIdx()); } - void LSU::onRobDrained_(const bool & val) { retire_done_ = val; } - LSU::~LSU() { DLOG(getContainer()->getLocation() << ": " << load_store_info_allocator_.getNumAllocated() @@ -121,11 +119,13 @@ namespace olympia << " MemoryAccessInfo objects allocated/created"); } + void LSU::onROBTerminate_(const bool & val) { rob_stopped_simulation_ = val; } + void LSU::onStartingTeardown_() { // If ROB has not stopped the simulation & // the ldst has entries to process we should fail - if ((false == retire_done_) && (false == ldst_inst_queue_.empty())) + if ((false == rob_stopped_simulation_) && (false == ldst_inst_queue_.empty())) { dumpDebugContent_(std::cerr); sparta_assert(false, "Issue queue has pending instructions"); @@ -992,7 +992,6 @@ namespace olympia void LSU::removeInstFromReplayQueue_(const InstPtr & inst_to_remove) { - // return; ILOG("Removing Inst from replay queue " << inst_to_remove); for (const auto & ldst_inst : ldst_inst_queue_) { diff --git a/core/LSU.hpp b/core/LSU.hpp index b73f6508..c68a2196 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -77,14 +77,11 @@ namespace olympia // Type Name/Alias Declaration //////////////////////////////////////////////////////////////////////////////// - bool retire_done_ = false; using LoadStoreInstInfoPtr = sparta::SpartaSharedPointer; using LoadStoreInstIterator = sparta::Buffer::const_iterator; using FlushCriteria = FlushManager::FlushingCriteria; - void onRobDrained_(const bool & val); - private: using ScoreboardViews = std::array, core_types::N_REGFILES>; @@ -175,6 +172,9 @@ namespace olympia // LSU Microarchitecture parameters const bool allow_speculative_load_exec_; + // ROB stopped simulation early, transactions could still be inflight. + bool rob_stopped_simulation_ = false; + //////////////////////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////////////////////// @@ -232,7 +232,6 @@ namespace olympia // Handle instruction flush in LSU void handleFlush_(const FlushCriteria &); - void dumpDebugContent_(std::ostream & output) const override final; // Instructions in the replay ready to issue void replayReady_(const LoadStoreInstInfoPtr &); @@ -242,6 +241,17 @@ namespace olympia // Instructions in the replay ready to issue void appendReady_(const LoadStoreInstInfoPtr &); + // Called when ROB terminates the simulation + void onROBTerminate_(const bool & val); + + // When simulation is ending (error or not), this function + // will be called + void onStartingTeardown_() override; + + // Typically called when the simulator is shutting down due to an exception + // writes out text to aid debug + void dumpDebugContent_(std::ostream & output) const override final; + //////////////////////////////////////////////////////////////////////////////// // Regular Function/Subroutine Call //////////////////////////////////////////////////////////////////////////////// @@ -250,6 +260,8 @@ namespace olympia void allocateInstToIssueQueue_(const InstPtr & inst_ptr); + bool olderStoresExists_(const InstPtr & inst_ptr); + bool allOlderStoresIssued_(const InstPtr & inst_ptr); void readyDependentLoads_(const LoadStoreInstInfoPtr &); @@ -321,12 +333,6 @@ namespace olympia sparta::Counter biu_reqs_{getStatisticSet(), "biu_reqs", "Number of BIU reqs", sparta::Counter::COUNT_NORMAL}; - // When simulation is ending (error or not), this function - // will be called - void onStartingTeardown_() override; - - bool olderStoresExists_(const InstPtr & inst_ptr); - friend class LSUTester; }; diff --git a/core/ROB.cpp b/core/ROB.cpp index ab9a5032..76e33bf0 100644 --- a/core/ROB.cpp +++ b/core/ROB.cpp @@ -53,12 +53,13 @@ namespace olympia ev_ensure_forward_progress_.setContinuing(false); // Notify other components when ROB stops the simulation - rob_drained_notif_source_.reset(new sparta::NotificationSource( + rob_stopped_notif_source_.reset(new sparta::NotificationSource( this->getContainer(), - "rob_notif_channel", - "Notification channel for rob", - "rob_notif_channel" + "rob_stopped_notif_channel", + "ROB terminated simulation channel", + "rob_stopped_notif_channel" )); + // Send initial credits to anyone that cares. Probably Dispatch. sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(ROB, sendInitialCredits_)); } @@ -139,7 +140,7 @@ namespace olympia // Will be true if the user provides a -i option if (SPARTA_EXPECT_FALSE((num_retired_ == num_insts_to_retire_))) { rob_stopped_simulation_ = true; - rob_drained_notif_source_->postNotification(true); + rob_stopped_notif_source_->postNotification(true); getScheduler()->stopRunning(); break; } @@ -157,15 +158,6 @@ namespace olympia ++num_flushes_; break; } - - // Check to see if this is the last instruction of the - // trace - if(ex_inst.getLast()) { - rob_stopped_simulation_ = true; - rob_drained_notif_source_->postNotification(true); - // No need to stop the scheduler -- let simulation - // drain normally. Also, don't need to check forward progress - } } else { break; diff --git a/core/ROB.hpp b/core/ROB.hpp index 89aa83d4..4458ec42 100644 --- a/core/ROB.hpp +++ b/core/ROB.hpp @@ -116,7 +116,7 @@ namespace olympia sparta::Event<> ev_ensure_forward_progress_{&unit_event_set_, "forward_progress_check", CREATE_SPARTA_HANDLER(ROB, checkForwardProgress_)}; - std::unique_ptr> rob_drained_notif_source_; + std::unique_ptr> rob_stopped_notif_source_; void sendInitialCredits_(); void retireEvent_();