diff --git a/core/CPUTopology.cpp b/core/CPUTopology.cpp index b4260c67..67447e14 100644 --- a/core/CPUTopology.cpp +++ b/core/CPUTopology.cpp @@ -343,13 +343,6 @@ void olympia::CoreTopologySimple::bindTree(sparta::RootTreeNode* root_node) ; const std::string flush_manager = flushmanager_ports + ".out_flush_upper"; bind_ports(exe_flush_in, flush_manager); - - // Bind flush requests - const std::string exe_flush_out = - core_node + ".execute." + unit_name + ".ports.out_execute_flush"; - ; - const std::string flush_manager_in = flushmanager_ports + ".in_flush_request"; - bind_ports(exe_flush_out, flush_manager_in); } const auto issue_queue_to_pipe_map = olympia::coreutils::getPipeTopology( @@ -430,4 +423,4 @@ olympia::CPUTopology::allocateTopology(const std::string & topology) } sparta_assert(nullptr != new_topology); return new_topology; -} \ No newline at end of file +} diff --git a/core/ExecutePipe.cpp b/core/ExecutePipe.cpp index 7b794c4a..22d801eb 100644 --- a/core/ExecutePipe.cpp +++ b/core/ExecutePipe.cpp @@ -83,9 +83,7 @@ namespace olympia if (ex_inst->isBranch() && (std::rand() % 20) == 0) { ILOG("Randomly injecting a mispredicted branch: " << ex_inst); - FlushManager::FlushingCriteria criteria(FlushManager::FlushCause::MISPREDICTION, - ex_inst); - out_execute_flush_.send(criteria); + ex_inst->setMispredicted(); } } diff --git a/core/ExecutePipe.hpp b/core/ExecutePipe.hpp index 36d40352..5a2b95a3 100644 --- a/core/ExecutePipe.hpp +++ b/core/ExecutePipe.hpp @@ -84,8 +84,6 @@ namespace olympia sparta::DataOutPort out_execute_pipe_{&unit_port_set_, "out_execute_pipe"}; sparta::DataInPort in_reorder_flush_{ &unit_port_set_, "in_reorder_flush", sparta::SchedulingPhase::Flush, 1}; - sparta::DataOutPort out_execute_flush_{&unit_port_set_, - "out_execute_flush"}; // Scoreboards using ScoreboardViews = diff --git a/core/FlushManager.hpp b/core/FlushManager.hpp index a4ed855e..a6a35ae4 100644 --- a/core/FlushManager.hpp +++ b/core/FlushManager.hpp @@ -50,16 +50,35 @@ namespace olympia TARGET_MISPREDICTION, MISFETCH, POST_SYNC, - UKNOWN, + UNKNOWN, __LAST }; + static bool determineInclusive(FlushCause cause) + { + static const std::map inclusive_flush_map = { + {FlushCause::TRAP, true}, + {FlushCause::MISFETCH, true}, + {FlushCause::MISPREDICTION, false}, + {FlushCause::TARGET_MISPREDICTION, false}, + {FlushCause::POST_SYNC, false} + }; + + if(auto match = inclusive_flush_map.find(cause); match != inclusive_flush_map.end()) { + return match->second; + } + sparta_assert(false, "Unknown flush cause: " << static_cast(cause)); + return false; + } + class FlushingCriteria { public: - FlushingCriteria(FlushCause cause, InstPtr inst_ptr) : + FlushingCriteria(FlushCause cause, const InstPtr & inst_ptr) : cause_(cause), - inst_ptr_(inst_ptr) {} + is_inclusive_(determineInclusive(cause_)), + inst_ptr_(inst_ptr) + {} FlushingCriteria() = default; FlushingCriteria(const FlushingCriteria &rhs) = default; @@ -67,27 +86,8 @@ namespace olympia FlushCause getCause() const { return cause_; } const InstPtr & getInstPtr() const { return inst_ptr_; } - - bool isInclusiveFlush() const - { - static const std::map inclusive_flush_map = { - {FlushCause::TRAP, true}, - {FlushCause::MISFETCH, true}, - {FlushCause::MISPREDICTION, false}, - {FlushCause::TARGET_MISPREDICTION, false}, - {FlushCause::POST_SYNC, false} - }; - if(auto match = inclusive_flush_map.find(cause_); match != inclusive_flush_map.end()) { - return match->second; - } - sparta_assert(false, "Unknown flush cause: " << static_cast(cause_)); - return true; - } - - bool isLowerPipeFlush() const - { - return cause_ == FlushCause::MISFETCH; - } + bool isInclusiveFlush() const { return is_inclusive_; } + bool isLowerPipeFlush() const { return cause_ == FlushCause::MISFETCH; } bool includedInFlush(const InstPtr& other) const { @@ -97,11 +97,12 @@ namespace olympia } private: - FlushCause cause_ = FlushCause::UKNOWN; + // Cannot be const since these are copied into the PLE + FlushCause cause_ = FlushCause::UNKNOWN; + bool is_inclusive_ = false; InstPtr inst_ptr_; }; - static constexpr char name[] = "flushmanager"; class FlushManagerParameters : public sparta::ParameterSet @@ -202,8 +203,8 @@ namespace olympia case FlushManager::FlushCause::POST_SYNC: os << "POST_SYNC"; break; - case FlushManager::FlushCause::UKNOWN: - os << "UKNOWN"; + case FlushManager::FlushCause::UNKNOWN: + os << "UNKNOWN"; break; case FlushManager::FlushCause::__LAST: throw sparta::SpartaException("__LAST cannot be a valid enum state."); diff --git a/core/Inst.hpp b/core/Inst.hpp index 66e66ef1..3188f5ef 100644 --- a/core/Inst.hpp +++ b/core/Inst.hpp @@ -178,6 +178,10 @@ namespace olympia // Branch instruction was taken (always set for JAL/JALR) void setTakenBranch(bool taken) { is_taken_branch_ = taken; } + // Is this branch instruction mispredicted? + bool isMispredicted() const { return is_mispredicted_; } + void setMispredicted() { is_mispredicted_ = true; } + // TBD -- add branch prediction void setSpeculative(bool spec) { is_speculative_ = spec; } @@ -276,6 +280,9 @@ namespace olympia const bool is_condbranch_; const bool is_call_; const bool is_return_; + + // Did this instruction mispredict? + bool is_mispredicted_ = false; bool is_taken_branch_ = false; sparta::Scheduleable* ev_retire_ = nullptr; Status status_state_; diff --git a/core/ROB.cpp b/core/ROB.cpp index ab34832f..a757dbcc 100644 --- a/core/ROB.cpp +++ b/core/ROB.cpp @@ -76,10 +76,6 @@ namespace olympia ev_ensure_forward_progress_.schedule(retire_timeout_interval_); } - void ROB::retireEvent_() { - retireInstructions_(); - } - // An illustration of the use of the callback -- instead of // getting a reference, you can pull the data from the port // directly, albeit inefficient and superfluous here... @@ -94,6 +90,10 @@ namespace olympia void ROB::handleFlush_(const FlushManager::FlushingCriteria & criteria) { + sparta_assert(expect_flush_, "Received a flush, but didn't expect one"); + + expect_flush_ = false; + uint32_t credits_to_send = 0; // Clean up internals and send new credit count @@ -117,6 +117,11 @@ namespace olympia void ROB::retireInstructions_() { + // ROB is expecting a flush (back to itself) + if(expect_flush_) { + return; + } + const uint32_t num_to_retire = std::min(reorder_buffer_.size(), num_to_retire_); ILOG("num to retire: " << num_to_retire); @@ -171,6 +176,15 @@ namespace olympia break; } + // Is this a misprdicted branch requiring a refetch? + if(ex_inst.isMispredicted()) { + FlushManager::FlushingCriteria criteria + (FlushManager::FlushCause::MISPREDICTION, ex_inst_ptr); + out_retire_flush_.send(criteria); + expect_flush_ = true; + break; + } + // This is rare for the example if(SPARTA_EXPECT_FALSE(ex_inst.getPipe() == InstArchInfo::TargetPipe::SYS)) { diff --git a/core/ROB.hpp b/core/ROB.hpp index 2e09eebb..a024410f 100644 --- a/core/ROB.hpp +++ b/core/ROB.hpp @@ -108,9 +108,12 @@ namespace olympia sparta::DataInPort in_reorder_flush_ {&unit_port_set_, "in_reorder_flush", sparta::SchedulingPhase::Flush, 1}; + // Is the ROB expecting a flush? + bool expect_flush_ = false; + // Events used by the ROB sparta::UniqueEvent<> ev_retire_ {&unit_event_set_, "retire_insts", - CREATE_SPARTA_HANDLER(ROB, retireEvent_)}; + CREATE_SPARTA_HANDLER(ROB, retireInstructions_)}; // For correlation activities sparta::pevents::PeventCollector retire_event_{"RETIRE", getContainer(), getClock()}; @@ -124,7 +127,6 @@ namespace olympia std::unique_ptr> rob_stopped_notif_source_; void sendInitialCredits_(); - void retireEvent_(); void robAppended_(const InstGroup &); void retireInstructions_(); void checkForwardProgress_(); diff --git a/test/sim/CMakeLists.txt b/test/sim/CMakeLists.txt index 7a9a6683..1ac20e41 100644 --- a/test/sim/CMakeLists.txt +++ b/test/sim/CMakeLists.txt @@ -58,11 +58,11 @@ sparta_named_test(olympia_json_test_fp_transfers olympia # Test PEvent generation sparta_named_test(olympia_json_test_pevents olympia - --workload traces/dhry_riscv.zstf + --workload traces/dhry_riscv.zstf -i100k --pevents test_pevent.out RETIRE --pevents test_pevent.out COMPLETE) sparta_named_test(olympia_json_test_pevents_all olympia - --workload traces/dhry_riscv.zstf + --workload traces/dhry_riscv.zstf -i100k --pevents test_pevent.out all) ## Test the arches