From 69cfa157bda596f2d037b433ae79545f295f7882 Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Thu, 2 Nov 2023 23:03:37 -0500 Subject: [PATCH 01/12] Unit : L2Cache - new sparta unit that receives reqs from IL1 and DCACHE and sends out miss requests to the BIU --- core/CPUFactories.hpp | 4 + core/CPUTopology.cpp | 28 +- core/DCache.cpp | 15 +- core/DCache.hpp | 15 +- core/LSU.hpp | 24 + core/MemoryAccessInfo.hpp | 26 +- mss/BIU.cpp | 11 +- mss/BIU.hpp | 11 +- mss/CMakeLists.txt | 1 + mss/L2Cache.cpp | 656 ++++++++++++++++++ mss/L2Cache.hpp | 374 ++++++++++ test/CMakeLists.txt | 1 + test/core/l2cache/BIUSinkUnit.hpp | 55 ++ test/core/l2cache/CMakeLists.txt | 14 + test/core/l2cache/L2Cache_test.cpp | 223 ++++++ test/core/l2cache/L2SourceUnit.hpp | 125 ++++ .../expected_output/hit_case.out.EXPECTED | 93 +++ .../single_access.out.EXPECTED | 63 ++ test/core/l2cache/hit_case.json | 14 + test/core/l2cache/single_access.json | 7 + .../l2cache/test_arches/2_src_L2Cache.yaml | 27 + 21 files changed, 1766 insertions(+), 21 deletions(-) create mode 100644 mss/L2Cache.cpp create mode 100644 mss/L2Cache.hpp create mode 100644 test/core/l2cache/BIUSinkUnit.hpp create mode 100644 test/core/l2cache/CMakeLists.txt create mode 100644 test/core/l2cache/L2Cache_test.cpp create mode 100644 test/core/l2cache/L2SourceUnit.hpp create mode 100644 test/core/l2cache/expected_output/hit_case.out.EXPECTED create mode 100644 test/core/l2cache/expected_output/single_access.out.EXPECTED create mode 100644 test/core/l2cache/hit_case.json create mode 100644 test/core/l2cache/single_access.json create mode 100644 test/core/l2cache/test_arches/2_src_L2Cache.yaml diff --git a/core/CPUFactories.hpp b/core/CPUFactories.hpp index 333b5931..82dbd1db 100644 --- a/core/CPUFactories.hpp +++ b/core/CPUFactories.hpp @@ -14,6 +14,7 @@ #include "MMU.hpp" #include "SimpleTLB.hpp" #include "BIU.hpp" +#include "L2Cache.hpp" #include "MSS.hpp" #include "ROB.hpp" #include "FlushManager.hpp" @@ -71,6 +72,9 @@ namespace olympia{ sparta::ResourceFactory lsu_rf; + //! \brief Resouce Factory to build a L2Cache Unit + sparta::ResourceFactory l2cache_rf; //! \brief Resouce Factory to build a BIU Unit sparta::ResourceFactorylsu_rf }, + { + "l2cache", + "cpu.core*", + "L2Cache Unit", + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + &factories->l2cache_rf + }, { "biu", "cpu.core*", @@ -202,12 +210,28 @@ olympia::CoreTopologySimple::CoreTopologySimple(){ "cpu.core*.lsu.ports.in_cache_free_req" }, { - "cpu.core*.dcache.ports.out_biu_req", + "cpu.core*.dcache.ports.out_l2cache_req", + "cpu.core*.l2cache.ports.in_dcache_l2cache_req" + }, + { + "cpu.core*.dcache.ports.in_l2cache_ack", + "cpu.core*.l2cache.ports.out_l2cache_dcache_ack" + }, + { + "cpu.core*.dcache.ports.in_l2cache_resp", + "cpu.core*.l2cache.ports.out_l2cache_dcache_resp" + }, + { + "cpu.core*.l2cache.ports.out_biu_req", "cpu.core*.biu.ports.in_biu_req" }, { "cpu.core*.biu.ports.out_biu_ack", - "cpu.core*.dcache.ports.in_biu_ack" + "cpu.core*.l2cache.ports.in_biu_ack" + }, + { + "cpu.core*.biu.ports.out_biu_resp", + "cpu.core*.l2cache.ports.in_biu_resp" }, { "cpu.core*.lsu.ports.out_mmu_lookup_req", diff --git a/core/DCache.cpp b/core/DCache.cpp index 4b022a0a..2764ba00 100644 --- a/core/DCache.cpp +++ b/core/DCache.cpp @@ -11,8 +11,11 @@ namespace olympia { in_lsu_lookup_req_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getInstsFromLSU_, MemoryAccessInfoPtr)); - in_biu_ack_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getAckFromBIU_, InstPtr)); + in_l2cache_ack_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getAckFromL2Cache_, bool)); + + in_l2cache_resp_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getRespFromL2Cache_, InstPtr)); // DL1 cache config const uint32_t l1_line_size = p->l1_line_size; @@ -78,17 +81,21 @@ namespace olympia { if(!busy_) { busy_ = true; cache_pending_inst_ = memory_access_info_ptr; - out_biu_req_.send(cache_pending_inst_->getInstPtr()); + out_l2cache_req_.send(cache_pending_inst_->getInstPtr()); } } out_lsu_lookup_ack_.send(memory_access_info_ptr); } - void DCache::getAckFromBIU_(const InstPtr &inst_ptr) { + void DCache::getRespFromL2Cache_(const InstPtr &inst_ptr) { out_lsu_lookup_req_.send(cache_pending_inst_); reloadCache_(inst_ptr->getRAdr()); cache_pending_inst_.reset(); busy_ = false; } + void DCache::getAckFromL2Cache_(const bool &ack) { + // Process ACK + } + } diff --git a/core/DCache.hpp b/core/DCache.hpp index 949397ed..ed1ecef6 100644 --- a/core/DCache.hpp +++ b/core/DCache.hpp @@ -35,7 +35,9 @@ namespace olympia { void getInstsFromLSU_(const MemoryAccessInfoPtr &memory_access_info_ptr); - void getAckFromBIU_(const InstPtr &inst_ptr); + void getAckFromL2Cache_(const bool &ack); + + void getRespFromL2Cache_(const InstPtr &inst_ptr); using L1Handle = SimpleDL1::Handle; L1Handle l1_cache_; @@ -51,8 +53,11 @@ namespace olympia { sparta::DataInPort in_lsu_lookup_req_ {&unit_port_set_, "in_lsu_lookup_req", 0}; - sparta::DataInPort in_biu_ack_ - {&unit_port_set_, "in_biu_ack", 1}; + sparta::DataInPort in_l2cache_ack_ + {&unit_port_set_, "in_l2cache_ack", 1}; + + sparta::DataInPort in_l2cache_resp_ + {&unit_port_set_, "in_l2cache_resp", 1}; //////////////////////////////////////////////////////////////////////////////// // Output Ports @@ -66,8 +71,8 @@ namespace olympia { sparta::DataOutPort out_lsu_lookup_req_ {&unit_port_set_, "out_lsu_lookup_req", 1}; - sparta::DataOutPort out_biu_req_ - {&unit_port_set_, "out_biu_req"}; + sparta::DataOutPort out_l2cache_req_ + {&unit_port_set_, "out_l2cache_req"}; //////////////////////////////////////////////////////////////////////////////// // Events diff --git a/core/LSU.hpp b/core/LSU.hpp index 81a94fa5..4bc5dc68 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -399,6 +399,30 @@ namespace olympia }; + inline std::ostream & operator<<(std::ostream & os, + const olympia::MemoryAccessInfo::UnitName & unit) { + switch(unit) { + case olympia::MemoryAccessInfo::UnitName::IL1: + os << "IL1"; + break; + case olympia::MemoryAccessInfo::UnitName::LSU: + os << "LSU"; + break; + case olympia::MemoryAccessInfo::UnitName::DCACHE: + os << "DCACHE"; + break; + case olympia::MemoryAccessInfo::UnitName::L2CACHE: + os << "L2CACHE"; + break; + case olympia::MemoryAccessInfo::UnitName::BIU: + os << "BIU"; + break; + default: + throw sparta::SpartaException("NUM_STATES cannot be a valid enum state."); + } + return os; + } + inline std::ostream & operator<<(std::ostream & os, const olympia::MemoryAccessInfo::MMUState & mmu_access_state){ switch(mmu_access_state){ diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index 28203d4d..c6f573a9 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -39,6 +39,18 @@ namespace olympia { __LAST = NUM_STATES }; + enum class UnitName : std::uint32_t { + NO_ACCESS = 0, + __FIRST = NO_ACCESS, + IL1, + LSU, + DCACHE, + L2CACHE, + BIU, + NUM_UNITS, + __LAST = NUM_UNITS + }; + MemoryAccessInfo() = delete; MemoryAccessInfo( @@ -48,7 +60,9 @@ namespace olympia { mmu_access_state_(MMUState::NO_ACCESS), // Construct the State object here - cache_access_state_(CacheState::NO_ACCESS) {} + cache_access_state_(CacheState::NO_ACCESS), + src_(UnitName::IL1), + dest_(UnitName::BIU) {} virtual ~MemoryAccessInfo() {} @@ -67,6 +81,12 @@ namespace olympia { bool getPhyAddrStatus() const { return phy_addr_ready_; } + void setSrcUnit(UnitName src_unit) { src_ = src_unit; } + const UnitName & getSrcUnit() const { return src_; } + + void setDestUnit(UnitName dest_unit) { dest_ = dest_unit; } + const UnitName & getDestUnit() const { return dest_; } + MMUState getMMUState() const { return mmu_access_state_; } @@ -100,6 +120,10 @@ namespace olympia { // DCache access status CacheState cache_access_state_; + // Src and destination unit name for the packet + UnitName src_; + UnitName dest_; + // Scoreboards using ScoreboardViews = std::array, core_types::N_REGFILES>; ScoreboardViews scoreboard_views_; diff --git a/mss/BIU.cpp b/mss/BIU.cpp index 7d0f1773..aa1a24fb 100644 --- a/mss/BIU.cpp +++ b/mss/BIU.cpp @@ -19,7 +19,7 @@ namespace olympia_mss biu_latency_(p->biu_latency) { in_biu_req_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, getReqFromLSU_, olympia::InstPtr)); + (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, getReqFromL2Cache_, olympia::InstPtr)); in_mss_ack_sync_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, getAckFromMSS_, bool)); @@ -34,8 +34,8 @@ namespace olympia_mss // Callbacks //////////////////////////////////////////////////////////////////////////////// - // Receive new BIU request from LSU - void BIU::getReqFromLSU_(const olympia::InstPtr & inst_ptr) + // Receive new BIU request from L2Cache + void BIU::getReqFromL2Cache_(const olympia::InstPtr & inst_ptr) { appendReqQueue_(inst_ptr); @@ -69,7 +69,9 @@ namespace olympia_mss // Handle MSS Ack void BIU::handle_MSS_Ack_() { - out_biu_ack_.send(biu_req_queue_.front()); + out_biu_resp_.send(biu_req_queue_.front(), biu_latency_); + out_biu_ack_.send(true); + biu_req_queue_.pop_front(); biu_busy_ = false; @@ -97,7 +99,6 @@ namespace olympia_mss sparta_assert(false, "MSS is NOT done!"); } - //////////////////////////////////////////////////////////////////////////////// // Regular Function/Subroutine Call //////////////////////////////////////////////////////////////////////////////// diff --git a/mss/BIU.hpp b/mss/BIU.hpp index 5798907e..63e12817 100644 --- a/mss/BIU.hpp +++ b/mss/BIU.hpp @@ -67,7 +67,10 @@ namespace olympia_mss // Output Ports //////////////////////////////////////////////////////////////////////////////// - sparta::DataOutPort out_biu_ack_ + sparta::DataOutPort out_biu_ack_ + {&unit_port_set_, "out_biu_ack"}; + + sparta::DataOutPort out_biu_resp_ {&unit_port_set_, "out_biu_ack"}; sparta::SyncOutPort out_mss_req_sync_ @@ -91,7 +94,7 @@ namespace olympia_mss // Event Handlers //////////////////////////////////////////////////////////////////////////////// - // Event to handle BIU request from LSU + // Event to handle BIU request from L2Cache sparta::UniqueEvent<> ev_handle_biu_req_ {&unit_event_set_, "handle_biu_req", CREATE_SPARTA_HANDLER(BIU, handle_BIU_Req_)}; @@ -104,8 +107,8 @@ namespace olympia_mss // Callbacks //////////////////////////////////////////////////////////////////////////////// - // Receive new BIU request from LSU - void getReqFromLSU_(const olympia::InstPtr &); + // Receive new BIU request from L2Cache + void getReqFromL2Cache_(const olympia::InstPtr &); // Handle BIU request void handle_BIU_Req_(); diff --git a/mss/CMakeLists.txt b/mss/CMakeLists.txt index 706261d4..1f2739e8 100644 --- a/mss/CMakeLists.txt +++ b/mss/CMakeLists.txt @@ -1,6 +1,7 @@ project (mss) add_library(mss BIU.cpp + L2Cache.cpp MSS.cpp ) get_property(SPARTA_INCLUDE_PROP TARGET SPARTA::sparta PROPERTY INTERFACE_INCLUDE_DIRECTORIES) diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp new file mode 100644 index 00000000..c1edf628 --- /dev/null +++ b/mss/L2Cache.cpp @@ -0,0 +1,656 @@ +// -*- C++ -*- + +#include "sparta/utils/SpartaAssert.hpp" +#include "sparta/utils/LogUtils.hpp" + +#include "L2Cache.hpp" + +namespace olympia_mss +{ + const char L2Cache::name[] = "l2cache"; + + //////////////////////////////////////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////////////////////////////////////// + + L2Cache::L2Cache(sparta::TreeNode *node, const L2CacheParameterSet *p) : + sparta::Unit(node), + num_reqs_from_dcache_(&unit_stat_set_, + "num_reqs_from_dcache", + "The total number of instructions received by L2Cache from DCache", + sparta::Counter::COUNT_NORMAL), + num_reqs_from_il1_(&unit_stat_set_, + "num_reqs_from_il1", + "The total number of instructions received by L2Cache from IL1", + sparta::Counter::COUNT_NORMAL), + num_reqs_to_biu_(&unit_stat_set_, + "num_reqs_to_biu", + "The total number of instructions forwarded from L2Cache to BIU", + sparta::Counter::COUNT_NORMAL), + num_acks_from_biu_(&unit_stat_set_, + "num_acks_from_biu", + "The total number of instructions received from BIU into L2Cache", + sparta::Counter::COUNT_NORMAL), + num_acks_to_il1_(&unit_stat_set_, + "num_acks_to_il1", + "The total number of instructions forwarded from L2Cache to IL1", + sparta::Counter::COUNT_NORMAL), + num_acks_to_dcache_(&unit_stat_set_, + "num_acks_to_dcache", + "The total number of instructions forwarded from L2Cache to DCache", + sparta::Counter::COUNT_NORMAL), + num_resps_from_biu_(&unit_stat_set_, + "num_resps_from_biu", + "The total number of instructions received from BIU into L2Cache", + sparta::Counter::COUNT_NORMAL), + num_resps_to_il1_(&unit_stat_set_, + "num_resps_to_il1", + "The total number of instructions forwarded from L2Cache to IL1", + sparta::Counter::COUNT_NORMAL), + num_resps_to_dcache_(&unit_stat_set_, + "num_resps_to_dcache", + "The total number of instructions forwarded from L2Cache to DCache", + sparta::Counter::COUNT_NORMAL), + l2_cache_hits_(&unit_stat_set_, + "l2_cache_hits", + "The total number L2 Cache Hits", + sparta::Counter::COUNT_NORMAL), + l2_cache_misses_(&unit_stat_set_, + "l2_cache_misses", + "The total number L2 Cache Misses", + sparta::Counter::COUNT_NORMAL), + dcache_req_queue_size_(p->dcache_req_queue_size), + il1_req_queue_size_(p->il1_req_queue_size), + biu_req_queue_size_(p->biu_req_queue_size), + biu_resp_queue_size_(p->biu_resp_queue_size), + dcache_resp_queue_size_(p->dcache_resp_queue_size), + il1_resp_queue_size_(p->il1_resp_queue_size), + stages_(p->l2cache_latency), + l2cache_pipeline_("L2CachePipeline", stages_.NUM_STAGES, getClock()), + pipeline_req_queue_("Pipeline_Request_Queue", + p->pipeline_req_queue_size, + node->getClock()), + pipeline_req_queue_size_(p->pipeline_req_queue_size), + miss_pending_buffer_("Miss_Pending_Buffer", + p->miss_pending_buffer_size, + node->getClock(), + &unit_stat_set_), + miss_pending_buffer_size_(p->miss_pending_buffer_size), + l2_always_hit_(p->l2_always_hit), + l2cache_biu_credits_(p->l2cache_biu_credits), + l2cache_latency_(p->l2cache_latency) { + + // In Port Handler registration + in_dcache_l2cache_req_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getReqFromDCache_, olympia::InstPtr)); + + in_il1_l2cache_req_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getReqFromIL1_, olympia::InstPtr)); + + in_biu_resp_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getRespFromBIU_, olympia::InstPtr)); + + in_biu_ack_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getAckFromBIU_, bool)); + + // Default channel selected for arbitration + channel_select_ = channel::IL1; + + // Pipeline collection config + l2cache_pipeline_.enableCollection(node); + // Allow the pipeline to create events and schedule work + l2cache_pipeline_.performOwnUpdates(); + + // There can be situations where NOTHING is going on in the + // simulator but forward progression of the pipeline elements. + // In this case, the internal event for the pipeline will + // be the only event keeping simulation alive. Sparta + // supports identifying non-essential events (by calling + // setContinuing to false on any event). + l2cache_pipeline_.setContinuing(true); + + l2cache_pipeline_.registerHandlerAtStage(stages_.CACHE_LOOKUP, CREATE_SPARTA_HANDLER(L2Cache, handleCacheAccessRequest_)); + + l2cache_pipeline_.registerHandlerAtStage(stages_.HIT_MISS_HANDLING, CREATE_SPARTA_HANDLER(L2Cache, handleCacheAccessResult_)); + + // L2 cache config + l2_lineSize_ = p->l2_line_size; + shiftBy_ = log2(l2_lineSize_); + const uint32_t l2_size_kb = p->l2_size_kb; + const uint32_t l2_associativity = p->l2_associativity; + std::unique_ptr repl(new sparta::cache::TreePLRUReplacement + (l2_associativity)); + l2_cache_.reset(new olympia::SimpleDL1( getContainer(), l2_size_kb, l2_lineSize_, *repl)); + + ILOG("L2Cache construct: #" << node->getGroupIdx()); + ILOG("Starting BIU credits = " << l2cache_biu_credits_); + } + + + //////////////////////////////////////////////////////////////////////////////// + // Callbacks + //////////////////////////////////////////////////////////////////////////////// + + // Receive new L2Cache request from DCache + void L2Cache::getReqFromDCache_(const olympia::InstPtr & inst_ptr) { + + ILOG("Request received from DCache on the port"); + + appendDCacheReqQueue_(inst_ptr); + + // Schedule L2Cache request handling event only when: + // Request queue is not empty + if (dcache_req_queue_.size() < dcache_req_queue_size_) { + ev_handle_dcache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); + num_reqs_from_dcache_++; + } + else { + ILOG("This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); + } + } + + // Receive new L2Cache request from IL1 + void L2Cache::getReqFromIL1_(const olympia::InstPtr & inst_ptr) { + + ILOG("Request received from IL1 on the port"); + + appendIL1ReqQueue_(inst_ptr); + + // Schedule L2Cache request handling event only when: + // (1)Request queue is not empty + if (il1_req_queue_.size() < il1_req_queue_size_) { + ev_handle_il1_l2cache_req_.schedule(sparta::Clock::Cycle(0)); + num_reqs_from_il1_++; + } + else { + ILOG("This request cannot be serviced right now, L2Cache input buffer from IL1 is already full!"); + } + } + + // Handle BIU resp + void L2Cache::getRespFromBIU_(const olympia::InstPtr & inst_ptr) { + + ILOG("Response received from BIU on the port"); + + appendBIURespQueue_(inst_ptr); + + // Schedule BIU resp handling event only when: + // Request queue is not empty + if (biu_resp_queue_.size() < biu_resp_queue_size_) { + ev_handle_biu_l2cache_resp_.schedule(sparta::Clock::Cycle(0)); + num_resps_from_biu_++; + } + else { + ILOG("This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); + } + } + + // Handle BIU ack + void L2Cache::getAckFromBIU_(const bool & ack) { + + // Update the biu credits + l2cache_biu_credits_++; + + // Kickstart the pipeline issueing + ev_issue_req_.schedule(sparta::Clock::Cycle(0)); + + ILOG("Ack received from BIU on the port : Current BIU credits = " << l2cache_biu_credits_); + } + + // Handle L2Cache request from DCache + void L2Cache::handle_DCache_L2Cache_Req_() { + if (!dcache_req_queue_.empty()) { + ev_create_req_.schedule(sparta::Clock::Cycle(0)); + } + } + + // Handle L2Cache request from IL1 + void L2Cache::handle_IL1_L2Cache_Req_() { + if (!il1_req_queue_.empty()) { + ev_create_req_.schedule(sparta::Clock::Cycle(0)); + } + } + + // Handle BIU->L2Cache response + void L2Cache::handle_BIU_L2Cache_Resp_() { + if (!biu_resp_queue_.empty()) { + ev_create_req_.schedule(sparta::Clock::Cycle(0)); + } + } + + // Handle L2Cache request to BIU + void L2Cache::handle_L2Cache_BIU_Req_() { + out_biu_req_.send(biu_req_queue_.front()); + biu_req_queue_.erase(biu_req_queue_.begin()); + + num_reqs_to_biu_++; + + ILOG("L2Cache Request sent to BIU!"); + } + + // Returning ack to DCache + void L2Cache::handle_L2Cache_DCache_Ack_() { + out_l2cache_dcache_ack_.send(true); + num_acks_to_dcache_++; + + ILOG("L2Cache Ack is sent to DCache!"); + } + + // Returning resp to IL1 + void L2Cache::handle_L2Cache_IL1_Ack_() { + out_l2cache_il1_ack_.send(true); + num_acks_to_il1_++; + + ILOG("L2Cache Ack is sent to IL1!"); + } + + // Returning resp to DCache + void L2Cache::handle_L2Cache_DCache_Resp_() { + out_l2cache_dcache_resp_.send(dcache_resp_queue_.front()); + dcache_resp_queue_.erase(dcache_resp_queue_.begin()); + + num_resps_to_dcache_++; + + ILOG("L2Cache Resp is sent to DCache!"); + } + + // Returning resp to IL1 + void L2Cache::handle_L2Cache_IL1_Resp_() { + out_l2cache_il1_resp_.send(il1_resp_queue_.front()); + il1_resp_queue_.erase(il1_resp_queue_.begin()); + + num_resps_to_il1_++; + + ILOG("L2Cache Resp is sent to IL1!"); + } + + // Handle arbitration and forward the req to pipeline_req_queue_ + void L2Cache::create_Req_() { + + channel arbitration_winner = arbitrateL2CacheAccessReqs_(); + uint32_t num_inst_found = 0; + + if (arbitration_winner == channel::BIU) { + + const olympia::InstPtr &instPtr = biu_resp_queue_.front(); + + // request in the miss_pending_buffer iterator + auto iter = miss_pending_buffer_.begin(); + auto req = iter; + + // Function to check if the request to the given cacheline is present in the miss_pending_buffer_ + auto getCacheLine = [this] (auto inst_ptr) { return inst_ptr->getRAdr() >> shiftBy_; }; + auto is_addr_present = [instPtr, getCacheLine] (auto reqPtr) + { return getCacheLine(reqPtr->getInstPtr()) == getCacheLine(instPtr); }; + + // Find the instructions from the miss_pending_buffer_ + while (iter != miss_pending_buffer_.end()) { + + req = std::find_if(iter, miss_pending_buffer_.end(), is_addr_present); + iter = req; + + // Set the original SrcUnit as the DestUnit because the resp will + // now be forwarded from BIU to the original SrcUnit + if (req != miss_pending_buffer_.end()) { + + ILOG("Request found in miss_pending_buffer_ with SrcUnit : " << (*req)->getSrcUnit()); + num_inst_found++; + + (*req)->setDestUnit((*req)->getSrcUnit()); + (*req)->setSrcUnit(L2UnitName::BIU); + + if (pipeline_req_queue_.size() < pipeline_req_queue_size_) { + pipeline_req_queue_.push(*req); + } + else { + sparta_assert("pipeline_req_queue_ is full. Check the sizing.") + } + + if (num_inst_found == 1) + ILOG("BIU cache reload request is sent to Pipeline_req_Q!"); + + iter++; + + miss_pending_buffer_.erase(req); + } + } + + if (num_inst_found == 0) + sparta_assert("No match found for the BIU resp in the miss_pending_buffer!!"); + + biu_resp_queue_.erase(biu_resp_queue_.begin()); + } + else if (arbitration_winner == channel::IL1) { + + const auto &reqPtr = std::make_shared(il1_req_queue_.front()); + + reqPtr->setSrcUnit(L2UnitName::IL1); + + pipeline_req_queue_.push(reqPtr); + ILOG("IL1 request is sent to Pipeline_req_Q!"); + + il1_req_queue_.erase(il1_req_queue_.begin()); + + // Send out the ack to IL1 for credit management + ev_handle_l2cache_il1_ack_.schedule(sparta::Clock::Cycle(0)); + } + else if (arbitration_winner == channel::DCACHE) { + + const auto &reqPtr = std::make_shared(dcache_req_queue_.front()); + + reqPtr->setSrcUnit(L2UnitName::DCACHE); + + pipeline_req_queue_.push(reqPtr); + ILOG("DCache request is sent to Pipeline_req_Q!"); + + dcache_req_queue_.erase(dcache_req_queue_.begin()); + + // Send out the ack to DCache for credit management + ev_handle_l2cache_dcache_ack_.schedule(sparta::Clock::Cycle(0)); + } + + ev_issue_req_.schedule(sparta::Clock::Cycle(0)); + + if ( (!biu_resp_queue_.empty() + || !il1_req_queue_.empty() + || !dcache_req_queue_.empty() ) + + && (pipeline_req_queue_.numFree() > 0)) + + ev_create_req_.schedule(sparta::Clock::Cycle(1)); + } + + void L2Cache::issue_Req_() { + + // Append the request to a pipeline if the pipeline_req_queue_ is not empty + // and l2cache_pipeline_ has credits available + if (hasCreditsForPipelineIssue_() && !pipeline_req_queue_.empty()) { + l2cache_pipeline_.append(pipeline_req_queue_.front()); + inFlight_reqs_++; + ILOG("Request is sent to Pipeline! SrcUnit : " << pipeline_req_queue_.front()->getSrcUnit()); + + pipeline_req_queue_.pop(); + } + + // Checking for the queue empty again before scheduling the event for the next clock cycle + if (!pipeline_req_queue_.empty()) + ev_issue_req_.schedule(sparta::Clock::Cycle(1)); + } + + // Pipeline Stage 1 + void L2Cache::handleCacheAccessRequest_() { + const auto req = l2cache_pipeline_[stages_.CACHE_LOOKUP]; + ILOG("Pipeline stage 1! - " << req->getInstPtr()); + + // Access cache, and check cache hit or miss + const L2CacheState cacheLookUpResult = cacheLookup_(req); + + // Update memory access info + req->setCacheState(cacheLookUpResult); + + if (cacheLookUpResult == L2CacheState::MISS) { + if (req->getSrcUnit() == L2UnitName::BIU) { + + // Reload cache line + reloadCache_(req->getInstPtr()->getRAdr()); + req->setCacheState(L2CacheState::HIT); + ILOG("Post-Reload State set to : Cache HIT: phyAddr=0x" << std::hex << req->getInstPtr()->getRAdr()); + } + } + else if (cacheLookUpResult == L2CacheState::HIT) { + if (req->getSrcUnit() != L2UnitName::BIU) { + + // Return the request back to where it came from + req->setDestUnit(req->getSrcUnit()); + } + } + } + + // Pipeline Stage 2 + void L2Cache::handleCacheAccessResult_() { + const auto req = l2cache_pipeline_[stages_.HIT_MISS_HANDLING]; + ILOG("Pipeline stage 2! " << req->getInstPtr()); + + inFlight_reqs_--; + + if (req->getCacheState() == L2CacheState::HIT) { + // If it was originally a miss in L2Cache, on return from BIU, it's SrcUnit is set to BIU + // and DestUnit to whatever the original SrcUnit was. + // + // If it was a hit in L2Cache, return the request back to where it originally came from. + // + // Send out the resp to the original SrcUnit -- which is now the DestUnit. + sendOutResp_(req->getDestUnit(), req->getInstPtr()); + } + else { // if (req->getCacheState() == L2CacheState::MISS) + // This request to access cache came from DCache or IL1 to do a cache lookup. + // It was either a miss or hit based on cacheLookup_() in the previous stage of the pipeline + + + // Set Destination for this request to BIU + req->setDestUnit(L2UnitName::BIU); + + // Handle the miss instruction by storing it aside while waiting + // for lower level memory to return + if (miss_pending_buffer_.size() < miss_pending_buffer_size_) { + ILOG("Storing the CACHE MISS in miss_pending_buffer_"); + miss_pending_buffer_.push_back(req); + } + else { + sparta_assert("No space in miss_pending_buffer_!"); + } + + // Function to check if the request to the given cacheline is present in the miss_pending_buffer_ + auto getCacheLine = [this] (auto reqPtr) { return reqPtr->getInstPtr()->getRAdr() >> shiftBy_; }; + auto is_addr_present = [req, getCacheLine] (auto reqPtr) + { return (req != reqPtr && getCacheLine(reqPtr) == getCacheLine(req));}; + + // Send out the request to BIU for a cache MISS if it is not sent out already + auto reqIter = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_addr_present); + + if (reqIter == miss_pending_buffer_.end()) + sendOutReq_(req->getDestUnit(), req->getInstPtr()); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // Regular Function/Subroutine Call + //////////////////////////////////////////////////////////////////////////////// + + // Append L2Cache request queue for reqs from DCache + void L2Cache::appendDCacheReqQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(dcache_req_queue_.size() <= dcache_req_queue_size_ ,"DCache request queue overflows!"); + + // Push new requests from back + dcache_req_queue_.emplace_back(inst_ptr); + + ILOG("Append DCache->L2Cache request queue!"); + } + + // Append L2Cache request queue for reqs from IL1 + void L2Cache::appendIL1ReqQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(il1_req_queue_.size() <= il1_req_queue_size_ ,"IL1 request queue overflows!"); + + // Push new requests from back + il1_req_queue_.emplace_back(inst_ptr); + + ILOG("Append IL1->L2Cache request queue!"); + } + + // Append BIU resp queue + void L2Cache::appendBIURespQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(biu_resp_queue_.size() <= biu_resp_queue_size_ ,"BIU resp queue overflows!"); + + // Push new requests from back + biu_resp_queue_.emplace_back(inst_ptr); + + ILOG("Append BIU->L2Cache resp queue!"); + } + + // Append DCache resp queue + void L2Cache::appendDCacheRespQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(dcache_resp_queue_.size() <= dcache_resp_queue_size_ ,"DCache resp queue overflows!"); + + // Push new resp to the dcache_resp_queue_ + dcache_resp_queue_.emplace_back(inst_ptr); + ev_handle_l2cache_dcache_resp_.schedule(sparta::Clock::Cycle(0)); + + ILOG("Append L2Cache->DCache resp queue!"); + } + + // Append IL1 resp queue + void L2Cache::appendIL1RespQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(il1_resp_queue_.size() <= il1_resp_queue_size_ ,"IL1 resp queue overflows!"); + + // Push new resp to the il1_resp_queue_ + il1_resp_queue_.emplace_back(inst_ptr); + ev_handle_l2cache_il1_resp_.schedule(sparta::Clock::Cycle(0)); + + ILOG("Append L2Cache->IL1 resp queue!"); + } + + // Append BIU req queue + void L2Cache::appendBIUReqQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(biu_req_queue_.size() <= biu_req_queue_size_ ,"BIU req queue overflows!"); + + // Push new request to the biu_req_queue_ if biu credits are available with the L2Cache + if (l2cache_biu_credits_ > 0) { + biu_req_queue_.emplace_back(inst_ptr); + l2cache_biu_credits_-- ; + + ev_handle_l2cache_biu_req_.schedule(sparta::Clock::Cycle(0)); + } + else { + sparta_assert("Can't send out this biu request :: OUT OF BIU CREDITS"); + } + + ILOG("Append L2Cache->BIU req queue : Remaining BIU credits = " << l2cache_biu_credits_); + } + + // Return the resp to the master units + void L2Cache::sendOutResp_(const L2UnitName &unit, const olympia::InstPtr& instPtr) { + // if (instPtr is originally from DCache) + if (unit == L2UnitName::DCACHE) { + appendDCacheRespQueue_(instPtr); + } + // if (instPtr is originally from IL1) + else if (unit == L2UnitName::IL1) { + appendIL1RespQueue_(instPtr); + } + else { + sparta_assert("Resp is being sent to a Unit that is not valid"); + } + } + + // Send the request to the slave units + void L2Cache::sendOutReq_(const L2UnitName &unit, const olympia::InstPtr& instPtr) { + // if (instPtr is destined for BIU on L2Cache miss) + if (unit == L2UnitName::BIU) { + appendBIUReqQueue_(instPtr); + } + else { + sparta_assert("Request is being sent to a Unit that is not valid"); + } + } + + // Select the channel to pick the request from + // Current options : + // BIU - P0 + // DCache - P1 - RoundRobin Candidate + // DL1 - P1 - RoundRobin Candidate + L2Cache::channel L2Cache::arbitrateL2CacheAccessReqs_() { + sparta_assert(il1_req_queue_.size() > 0 || dcache_req_queue_.size() > 0 || biu_resp_queue_.size() > 0, + "Arbitration failed: Reqest queues are empty!"); + + channel winner; + + // P0 priority to sevice the pending request in the buffer + if (!biu_resp_queue_.empty()) { + winner = channel::BIU; + ILOG("Arbitration winner - BIU"); + + return winner; + } + + // RoundRobin for P1 Priority + while (true) { + + if (channel_select_ == channel::IL1) { + channel_select_ = channel::DCACHE; + if (!il1_req_queue_.empty()) { + winner = channel::IL1; + ILOG("Arbitration winner - IL1"); + + return winner; + } + } + else if (channel_select_ == channel::DCACHE) { + channel_select_ = channel::IL1; + if (!dcache_req_queue_.empty()) { + winner = channel::DCACHE; + ILOG("Arbitration winner - DCache"); + + return winner; + } + } + } + } + + // Cache lookup for a HIT or MISS on a given request + L2Cache::L2CacheState L2Cache::cacheLookup_(L2MemoryAccessInfoPtr mem_access_info_ptr) { + const olympia::InstPtr & inst_ptr = mem_access_info_ptr->getInstPtr(); + uint64_t phyAddr = inst_ptr->getRAdr(); + + bool cache_hit = false; + + if (l2_always_hit_) { + cache_hit = true; + } + else { + auto cache_line = l2_cache_->peekLine(phyAddr); + cache_hit = (cache_line != nullptr) && cache_line->isValid(); + + // Update MRU replacement state if Cache HIT + if (cache_hit) { + l2_cache_->touchMRU(*cache_line); + } + } + + if (l2_always_hit_) { + ILOG("HIT all the time: phyAddr=0x" << std::hex << phyAddr); + l2_cache_hits_++; + } + else if (cache_hit) { + ILOG("Cache HIT: phyAddr=0x" << std::hex << phyAddr); + l2_cache_hits_++; + } + else { + ILOG("Cache MISS: phyAddr=0x" << std::hex << phyAddr); + l2_cache_misses_++; + } + + return (cache_hit ? + (L2CacheState::HIT) + : (L2CacheState::MISS)); + } + + // Allocating the cacheline in the L2 based on return from BIU/L3 + void L2Cache::reloadCache_(uint64_t phyAddr) { + auto l2_cache_line = &l2_cache_->getLineForReplacementWithInvalidCheck(phyAddr); + l2_cache_->allocateWithMRUUpdate(*l2_cache_line, phyAddr); + + ILOG("Cache reload complete!"); + } + + // Check if there are enough credits for the request to be issued to the l2cache_pipeline_ + bool L2Cache::hasCreditsForPipelineIssue_() { + + uint32_t num_free_biu_req_queue = biu_req_queue_size_ - biu_req_queue_.size(); + uint32_t num_free_miss_pending_buffer_ = miss_pending_buffer_.numFree(); + + uint32_t empty_slots = std::min(num_free_biu_req_queue, num_free_miss_pending_buffer_); + + DLOG("Inflight req : " << inFlight_reqs_ << " - Empty slots : " << empty_slots); + return (inFlight_reqs_ < empty_slots); + } +} diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp new file mode 100644 index 00000000..d7427b1e --- /dev/null +++ b/mss/L2Cache.hpp @@ -0,0 +1,374 @@ +// -*- C++ -*- + + + +#pragma once + +#include +#include + +#include "sparta/ports/PortSet.hpp" +#include "sparta/ports/SignalPort.hpp" +#include "sparta/ports/DataPort.hpp" +#include "sparta/events/EventSet.hpp" +#include "sparta/events/UniqueEvent.hpp" +#include "sparta/simulation/Unit.hpp" +#include "sparta/simulation/ParameterSet.hpp" +#include "sparta/simulation/TreeNode.hpp" +#include "sparta/collection/Collectable.hpp" +#include "sparta/events/StartupEvent.hpp" +#include "sparta/ports/SyncPort.hpp" +#include "sparta/resources/Pipe.hpp" +#include "sparta/resources/Pipeline.hpp" + +#include "Inst.hpp" +#include "CoreTypes.hpp" +#include "MemoryAccessInfo.hpp" + +#include "SimpleDL1.hpp" +#include "LSU.hpp" + +namespace olympia_mss +{ + class L2Cache : public sparta::Unit + { + public: + //! Parameters for L2Cache model + class L2CacheParameterSet : public sparta::ParameterSet { + public: + // Constructor for L2CacheParameterSet + L2CacheParameterSet(sparta::TreeNode* n): + sparta::ParameterSet(n) + { } + + PARAMETER(uint32_t, dcache_req_queue_size, 8, "DCache request queue size") + PARAMETER(uint32_t, dcache_resp_queue_size, 4, "DCache resp queue size") + PARAMETER(uint32_t, il1_req_queue_size, 8, "IL1 request queue size") + PARAMETER(uint32_t, il1_resp_queue_size, 4, "IL1 resp queue size") + PARAMETER(uint32_t, biu_req_queue_size, 4, "BIU request queue size") + PARAMETER(uint32_t, biu_resp_queue_size, 4, "BIU resp queue size") + PARAMETER(uint32_t, pipeline_req_queue_size, 64, "Pipeline request buffer size") + PARAMETER(uint32_t, miss_pending_buffer_size, 64, "Pipeline request buffer size") + + // Parameters for the L2 cache + PARAMETER(uint32_t, l2_line_size, 64, "L2 line size (power of 2)") + PARAMETER(uint32_t, l2_size_kb, 512, "Size of L2 in KB (power of 2)") + PARAMETER(uint32_t, l2_associativity, 16, "L2 associativity (power of 2)") + PARAMETER(bool, l2_always_hit, false, "L2 will always hit") + + PARAMETER(uint32_t, l2cache_biu_credits, 1, "Starting credits for BIU") + PARAMETER(uint32_t, l2cache_latency, 7, "Cache Lookup HIT latency") + }; + + // Constructor for L2Cache + // node parameter is the node that represent the L2Cache and p is the L2Cache parameter set + L2Cache(sparta::TreeNode* node, const L2CacheParameterSet* p); + + // name of this resource. + static const char name[]; + + //////////////////////////////////////////////////////////////////////////////// + // Type Name/Alias Declaration + //////////////////////////////////////////////////////////////////////////////// + + private: + + // Friend class used in rename testing + friend class L2CacheTester; + + //////////////////////////////////////////////////////////////////////////////// + // Statistics and Counters + //////////////////////////////////////////////////////////////////////////////// + // sparta::StatisticDef cycles_per_instr_; // A simple expression to calculate IPC + sparta::Counter num_reqs_from_dcache_; // Counter of number instructions received from DCache + sparta::Counter num_reqs_from_il1_; // Counter of number instructions received from IL1 + sparta::Counter num_reqs_to_biu_; // Counter of number instructions forwarded to BIU -- Totals misses + sparta::Counter num_acks_from_biu_; // Counter of number acks received from BIU + sparta::Counter num_acks_to_il1_; // Counter of number acks provided to IL1 + sparta::Counter num_acks_to_dcache_; // Counter of number acks provided to DCache + + sparta::Counter num_resps_from_biu_; // Counter of number responses received from BIU + sparta::Counter num_resps_to_il1_; // Counter of number responses provided to IL1 + sparta::Counter num_resps_to_dcache_; // Counter of number responses provided to DCache + + sparta::Counter l2_cache_hits_; // Counter of number L2 Cache Hits + sparta::Counter l2_cache_misses_; // Counter of number L2 Cache Misses + + //////////////////////////////////////////////////////////////////////////////// + // Input Ports + //////////////////////////////////////////////////////////////////////////////// + + sparta::DataInPort in_dcache_l2cache_req_ + {&unit_port_set_, "in_dcache_l2cache_req", 1}; + + sparta::DataInPort in_il1_l2cache_req_ + {&unit_port_set_, "in_il1_l2cache_req", 1}; + + sparta::DataInPort in_biu_resp_ + {&unit_port_set_, "in_biu_l2cache_resp", 1}; + + sparta::DataInPort in_biu_ack_ + {&unit_port_set_, "in_biu_l2cache_ack", 1}; + + + //////////////////////////////////////////////////////////////////////////////// + // Output Ports + //////////////////////////////////////////////////////////////////////////////// + + sparta::DataOutPort out_biu_req_ + {&unit_port_set_, "out_l2cache_biu_req"}; + + sparta::DataOutPort out_l2cache_il1_resp_ + {&unit_port_set_, "out_l2cache_il1_resp"}; + + sparta::DataOutPort out_l2cache_dcache_resp_ + {&unit_port_set_, "out_l2cache_dcache_resp"}; + + sparta::DataOutPort out_l2cache_il1_ack_ + {&unit_port_set_, "out_l2cache_il1_ack"}; + + sparta::DataOutPort out_l2cache_dcache_ack_ + {&unit_port_set_, "out_l2cache_dcache_ack"}; + + + //////////////////////////////////////////////////////////////////////////////// + // Internal States + //////////////////////////////////////////////////////////////////////////////// + + + using CacheRequestQueue = std::vector; + + // Buffers for the incoming requests from DCache and IL1 + CacheRequestQueue dcache_req_queue_; + CacheRequestQueue il1_req_queue_; + + const uint32_t dcache_req_queue_size_; + const uint32_t il1_req_queue_size_; + + // Buffers for the outgoing requests from L2Cache + CacheRequestQueue biu_req_queue_; + + const uint32_t biu_req_queue_size_; + + // Buffers for the incoming resps from BIU + CacheRequestQueue biu_resp_queue_; + + const uint32_t biu_resp_queue_size_; + + // Buffers for the outgoing resps to DCache and IL1 + CacheRequestQueue dcache_resp_queue_; + CacheRequestQueue il1_resp_queue_; + + const uint32_t dcache_resp_queue_size_; + const uint32_t il1_resp_queue_size_; + + // Channels enum + enum class channel { + NO_ACCESS = 0, + __FIRST = NO_ACCESS, + BIU, + IL1, + DCACHE, + NUM_CHANNELS, + __LAST = NUM_CHANNELS + } channel_select_; + + // Cache Pipeline + class PipelineStages { + public: + PipelineStages(uint32_t latency) { + NUM_STAGES = latency; + __LAST = NUM_STAGES; + HIT_MISS_HANDLING = NUM_STAGES - 1; + CACHE_LOOKUP = HIT_MISS_HANDLING - 1; + } + + uint32_t NO_ACCESS = 0; + uint32_t __FIRST = NO_ACCESS; + uint32_t CACHE_LOOKUP; + uint32_t HIT_MISS_HANDLING; + uint32_t NUM_STAGES; + uint32_t __LAST; + }; + + // Skipping the use of SpartaSharedPointer due to allocator bug + // Instead using std::shared_ptr. That works cleanly. + using L2MemoryAccessInfoPtr = std::shared_ptr; + using L2UnitName = olympia::MemoryAccessInfo::UnitName; + using L2CachePipeline = sparta::Pipeline; + + PipelineStages stages_; + L2CachePipeline l2cache_pipeline_; + + sparta::Queue pipeline_req_queue_; + const uint32_t pipeline_req_queue_size_; + uint32_t inFlight_reqs_ = 0; + + sparta::Clock::Cycle pipeline_req_issue_clock_ = 0; + sparta::Clock::Cycle pipeline_req_issue_delay_ = 0; + + sparta::Buffer> miss_pending_buffer_; + const uint32_t miss_pending_buffer_size_; + + + // L2 Cache + using L2CacheState = olympia::MemoryAccessInfo::CacheState; + using CacheHandle = olympia::SimpleDL1::Handle; + uint32_t l2_lineSize_; + uint8_t shiftBy_; + CacheHandle l2_cache_; + const bool l2_always_hit_; + + // Local state variables + uint32_t l2cache_biu_credits_; + const uint32_t l2cache_latency_; + + //////////////////////////////////////////////////////////////////////////////// + // Event Handlers + //////////////////////////////////////////////////////////////////////////////// + + // Event to handle L2Cache request from DCache + sparta::UniqueEvent<> ev_handle_dcache_l2cache_req_ + {&unit_event_set_, "ev_handle_dcache_l2cache_req", CREATE_SPARTA_HANDLER(L2Cache, handle_DCache_L2Cache_Req_)}; + + // Event to handle L2Cache request from IL1 + sparta::UniqueEvent<> ev_handle_il1_l2cache_req_ + {&unit_event_set_, "ev_handle_il1_l2cache_req", CREATE_SPARTA_HANDLER(L2Cache, handle_IL1_L2Cache_Req_)}; + + // Event to handle L2Cache resp for IL1 + sparta::UniqueEvent<> ev_handle_l2cache_il1_resp_ + {&unit_event_set_, "ev_handle_l2cache_il1_resp", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_IL1_Resp_)}; + + // Event to handle L2Cache resp for DCache + sparta::UniqueEvent<> ev_handle_l2cache_dcache_resp_ + {&unit_event_set_, "ev_handle_l2cache_dcache_resp", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_DCache_Resp_)}; + + // Event to handle L2Cache request to BIU + sparta::UniqueEvent<> ev_handle_l2cache_biu_req_ + {&unit_event_set_, "ev_handle_l2cache_biu_req", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_BIU_Req_)}; + + // Event to handle L2Cache request to BIU + sparta::UniqueEvent<> ev_handle_biu_l2cache_resp_ + {&unit_event_set_, "ev_handle_biu_l2cache_resp", CREATE_SPARTA_HANDLER(L2Cache, handle_BIU_L2Cache_Resp_)}; + + // Event to handle L2Cache ack for IL1 + sparta::UniqueEvent<> ev_handle_l2cache_il1_ack_ + {&unit_event_set_, "ev_handle_l2cache_il1_ack", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_IL1_Ack_)}; + + // Event to handle L2Cache ack for DCache + sparta::UniqueEvent<> ev_handle_l2cache_dcache_ack_ + {&unit_event_set_, "ev_handle_l2cache_dcache_ack", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_DCache_Ack_)}; + + // Event to create request for pipeline and feed it to the pipeline_req_queue_ + sparta::UniqueEvent<> ev_create_req_ + {&unit_event_set_, "create_req", CREATE_SPARTA_HANDLER(L2Cache, create_Req_)}; + + // Event to issue request to pipeline + sparta::UniqueEvent<> ev_issue_req_ + {&unit_event_set_, "issue_req", CREATE_SPARTA_HANDLER(L2Cache, issue_Req_)}; + + //////////////////////////////////////////////////////////////////////////////// + // Callbacks + //////////////////////////////////////////////////////////////////////////////// + + // Receive new L2Cache request from DCache + void getReqFromDCache_(const olympia::InstPtr &); + + // Receive new L2Cache request from IL1 + void getReqFromIL1_(const olympia::InstPtr &); + + // Receive BIU access Response + void getRespFromBIU_(const olympia::InstPtr &); + + // Receive BIU ack Response + void getAckFromBIU_(const bool &); + + // Handle L2Cache request from DCache + void handle_DCache_L2Cache_Req_(); + + // Handle L2Cache request from IL1 + void handle_IL1_L2Cache_Req_(); + + // Handle L2Cache request to BIU + void handle_L2Cache_BIU_Req_(); + + // Handle L2Cahe resp for IL1 + void handle_L2Cache_IL1_Resp_(); + + // Handle L2Cahe resp for DCache + void handle_L2Cache_DCache_Resp_(); + + // Handle L2Cahe ack for IL1 + void handle_L2Cache_IL1_Ack_(); + + // Handle L2Cahe ack for DCache + void handle_L2Cache_DCache_Ack_(); + + // Handle BIU resp to L2Cache + void handle_BIU_L2Cache_Resp_(); + + + // Pipeline request create callback + void create_Req_(); + + // Pipeline request issue callback + void issue_Req_(); + + + // Pipeline callbacks + // Stage 1 + void handleCacheAccessRequest_(); + + // Stage 2 + void handleCacheAccessResult_(); + + + //////////////////////////////////////////////////////////////////////////////// + // Regular Function/Subroutine Call + //////////////////////////////////////////////////////////////////////////////// + + // Append L2Cache request queue for reqs from DCache + void appendDCacheReqQueue_(const olympia::InstPtr &); + + // Append L2Cache request queue for reqs from IL1 + void appendIL1ReqQueue_(const olympia::InstPtr &); + + // Append L2Cache request queue for reqs to BIU + void appendBIUReqQueue_(const olympia::InstPtr &); + + // Append L2Cache resp queue for resps from BIU + void appendBIURespQueue_(const olympia::InstPtr &); + + // Append L2Cache resp queue for resps to DCache BIU + void appendDCacheRespQueue_(const olympia::InstPtr &); + + // Append L2Cache resp queue for resps to IL1 + void appendIL1RespQueue_(const olympia::InstPtr &); + + + + // Select the channel to pick the request from + // Current options : + // BIU - P0 + // DCache - P1 - RoundRobin Candidate + // DL1 - P1 - RoundRobin Candidate + channel arbitrateL2CacheAccessReqs_(); + + // Cache lookup for a HIT or MISS on a given request + L2CacheState cacheLookup_(std::shared_ptr); + + // Allocating the cacheline in the L2 bbased on return from BIU/L3 + void reloadCache_(uint64_t); + + // Return the resp to the master units + void sendOutResp_(const L2UnitName&, const olympia::InstPtr&); + + // Send the request to the slave units + void sendOutReq_(const L2UnitName&, const olympia::InstPtr&); + + // Check if there are enough credits for the request to be issued to the l2cache_pipeline_ + bool hasCreditsForPipelineIssue_(); + }; + + class L2CacheTester; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e812a002..291c8532 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,4 +30,5 @@ include_directories(${PROJECT_SOURCE_DIR}/..) add_subdirectory(sim) add_subdirectory(core/common) add_subdirectory(core/dispatch) +add_subdirectory(core/l2cache) add_subdirectory(core/rename) diff --git a/test/core/l2cache/BIUSinkUnit.hpp b/test/core/l2cache/BIUSinkUnit.hpp new file mode 100644 index 00000000..8a996a0f --- /dev/null +++ b/test/core/l2cache/BIUSinkUnit.hpp @@ -0,0 +1,55 @@ + +#pragma once + +#include "sparta/simulation/TreeNode.hpp" +#include "sparta/events/SingleCycleUniqueEvent.hpp" +#include "sparta/utils/SpartaSharedPointer.hpp" +#include "sparta/utils/LogUtils.hpp" + +#include + +namespace l2cache_test +{ + // //////////////////////////////////////////////////////////////////////////////// + // "Sink" unit, just sinks instructions sent to it. Sends credits + // back as directed by params/execution mode + class BIUSinkUnit : public sparta::Unit + { + public: + static constexpr char name[] = "BIUSinkUnit"; + + class BIUSinkUnitParameters : public sparta::ParameterSet + { + public: + explicit BIUSinkUnitParameters(sparta::TreeNode *n) : + sparta::ParameterSet(n) + { } + PARAMETER(std::string, purpose, "grp", "Purpose of this SinkUnit: grp, single") + PARAMETER(sparta::Clock::Cycle, sink_latency, 10, "Latency of this SinkUnit") + }; + + BIUSinkUnit(sparta::TreeNode * n, const BIUSinkUnitParameters * params) : sparta::Unit(n) { + + purpose_ = params->purpose; + sink_latency_ = params->sink_latency; + + in_biu_req_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(BIUSinkUnit, sinkInst_, olympia::InstPtr)); + } + private: + void sinkInst_(const olympia::InstPtr & instPtr) { + ILOG("Instruction: '" << instPtr << "' sinked"); + + out_biu_ack_.send(true, sink_latency_); + out_biu_resp_.send(instPtr, 2*sink_latency_); + } + + sparta::DataInPort in_biu_req_ {&unit_port_set_, "in_biu_req", + sparta::SchedulingPhase::Tick, 1}; + sparta::DataOutPort out_biu_resp_ {&unit_port_set_, "out_biu_resp"}; + sparta::DataOutPort out_biu_ack_ {&unit_port_set_, "out_biu_ack"}; + + std::string purpose_; + sparta::Clock::Cycle sink_latency_; + }; +} diff --git a/test/core/l2cache/CMakeLists.txt b/test/core/l2cache/CMakeLists.txt new file mode 100644 index 00000000..57e7b267 --- /dev/null +++ b/test/core/l2cache/CMakeLists.txt @@ -0,0 +1,14 @@ +project(L2Cache_test) + +add_executable(L2Cache_test L2Cache_test.cpp) + +target_link_libraries(L2Cache_test core common_test mss ${STF_LINK_LIBS} SPARTA::sparta) + +file(CREATE_LINK ${SIM_BASE}/mavis/json ${CMAKE_CURRENT_BINARY_DIR}/mavis_isa_files SYMBOLIC) +file(CREATE_LINK ${SIM_BASE}/arches ${CMAKE_CURRENT_BINARY_DIR}/arches SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/expected_output ${CMAKE_CURRENT_BINARY_DIR}/expected_output SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/single_access.json ${CMAKE_CURRENT_BINARY_DIR}/single_access.json SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/hit_case.json ${CMAKE_CURRENT_BINARY_DIR}/hit_case.json SYMBOLIC) + +sparta_named_test(L2Cache_test_single_access L2Cache_test single_access.out -c test_arches/2_src_L2Cache.yaml --input-file single_access.json) +sparta_named_test(L2Cache_test_hit_case L2Cache_test hit_case.out -c test_arches/2_src_L2Cache.yaml --input-file hit_case.json) diff --git a/test/core/l2cache/L2Cache_test.cpp b/test/core/l2cache/L2Cache_test.cpp new file mode 100644 index 00000000..a491e51b --- /dev/null +++ b/test/core/l2cache/L2Cache_test.cpp @@ -0,0 +1,223 @@ + +#include "L2Cache.hpp" +#include "MavisUnit.hpp" +#include "CoreUtils.hpp" + +#include "test/core/common/SourceUnit.hpp" +#include "test/core/common/SinkUnit.hpp" + +#include "test/core/l2cache/BIUSinkUnit.hpp" +#include "test/core/l2cache/L2SourceUnit.hpp" + +#include "sparta/app/CommandLineSimulator.hpp" +#include "sparta/utils/SpartaTester.hpp" +#include "sparta/resources/Buffer.hpp" +#include "sparta/sparta.hpp" +#include "sparta/simulation/ClockManager.hpp" +#include "sparta/kernel/Scheduler.hpp" +#include "sparta/utils/SpartaTester.hpp" +#include "sparta/statistics/StatisticSet.hpp" +#include "sparta/report/Report.hpp" +#include "sparta/events/UniqueEvent.hpp" +#include "sparta/app/Simulation.hpp" +#include "sparta/utils/SpartaSharedPointer.hpp" +#include "OlympiaAllocators.hpp" + +#include +#include +#include +#include +#include + +TEST_INIT + +// +// Simple L2Cache Simulator. +// +// SourceUnit 0 <-> L2Cache <-> BIUSinkUnit +// ^ +// | +// | +// SourceUnit 1 <--- +// +class L2CacheSim : public sparta::app::Simulation +{ +public: + + L2CacheSim(sparta::Scheduler * sched, + const std::string & mavis_isa_files, + const std::string & mavis_uarch_files, + const std::string & output_file, + const std::string & input_file) : + sparta::app::Simulation("L2CacheSim", sched), + input_file_(input_file), + test_tap_(getRoot(), "info", output_file) + { + } + + ~L2CacheSim() { + getRoot()->enterTeardown(); + } + + void runRaw(uint64_t run_time) override final + { + (void) run_time; // ignored + + sparta::app::Simulation::runRaw(run_time); + } + +private: + + void buildTree_() override + { + auto rtn = getRoot(); + + // Cerate the common Allocators + allocators_tn_.reset(new olympia::OlympiaAllocators(rtn)); + + // Create a Mavis Unit + sparta::ResourceTreeNode * mavis = new sparta::ResourceTreeNode(rtn, + olympia::MavisUnit::name, + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "Mavis Unit", + &mavis_fact); + tns_to_delete_.emplace_back(mavis); + + // Create a Source Units that represents DCache and IL1 + sparta::ResourceTreeNode * Test_DCache = new sparta::ResourceTreeNode(rtn, + "dcache", + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "dcache", + &dcache_fact); + Test_DCache->getParameterSet()->getParameter("input_file")->setValueFromString(input_file_); + tns_to_delete_.emplace_back(Test_DCache); + + sparta::ResourceTreeNode * Test_IL1 = new sparta::ResourceTreeNode(rtn, + "il1", + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "il1", + &il1_fact); + Test_IL1->getParameterSet()->getParameter("input_file")->setValueFromString(input_file_); + tns_to_delete_.emplace_back(Test_IL1); + + // Create L2Cache + sparta::ResourceTreeNode * L2CacheUnit = new sparta::ResourceTreeNode(rtn, + "l2cache", + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "l2cache", + &l2cache_fact); + tns_to_delete_.emplace_back(L2CacheUnit); + + // Create SinkUnit that represents the BIU + sparta::ResourceTreeNode * Test_BIU = new sparta::ResourceTreeNode(rtn, + "biu", + sparta::TreeNode::GROUP_NAME_NONE, + sparta::TreeNode::GROUP_IDX_NONE, + "biu", + &biu_fact); + tns_to_delete_.emplace_back(Test_BIU); + } + + void configureTree_() override { } + + void bindTree_() override + { + auto * root_node = getRoot(); + + // Bind the "ROB" (simple SinkUnit that accepts instruction + // groups) to Dispatch + sparta::bind(root_node->getChildAs("dcache.ports.out_source_req"), + root_node->getChildAs("l2cache.ports.in_dcache_l2cache_req")); + sparta::bind(root_node->getChildAs("dcache.ports.in_source_resp"), + root_node->getChildAs("l2cache.ports.out_l2cache_dcache_resp")); + sparta::bind(root_node->getChildAs("dcache.ports.in_source_ack"), + root_node->getChildAs("l2cache.ports.out_l2cache_dcache_ack")); + + sparta::bind(root_node->getChildAs("il1.ports.out_source_req"), + root_node->getChildAs("l2cache.ports.in_il1_l2cache_req")); + sparta::bind(root_node->getChildAs("il1.ports.in_source_resp"), + root_node->getChildAs("l2cache.ports.out_l2cache_il1_resp")); + sparta::bind(root_node->getChildAs("il1.ports.in_source_ack"), + root_node->getChildAs("l2cache.ports.out_l2cache_il1_ack")); + + sparta::bind(root_node->getChildAs("biu.ports.in_biu_req"), + root_node->getChildAs("l2cache.ports.out_l2cache_biu_req")); + sparta::bind(root_node->getChildAs("biu.ports.out_biu_resp"), + root_node->getChildAs("l2cache.ports.in_biu_l2cache_resp")); + sparta::bind(root_node->getChildAs("biu.ports.out_biu_ack"), + root_node->getChildAs("l2cache.ports.in_biu_l2cache_ack")); + } + // Allocators. Last thing to delete + std::unique_ptr allocators_tn_; + + sparta::ResourceFactory dcache_fact; + sparta::ResourceFactory il1_fact; + + sparta::ResourceFactory l2cache_fact; + + sparta::ResourceFactory biu_fact; + + olympia::MavisFactoy mavis_fact; + std::vector> tns_to_delete_; + + const std::string input_file_; + sparta::log::Tap test_tap_; +}; + +const char USAGE[] = + "Usage:\n" + " \n" + "\n"; + +sparta::app::DefaultValues DEFAULTS; + +// The main tester of L2Cache. The test is encapsulated in the +// parameter test_type of the Source unit. +void runTest(int argc, char **argv) +{ + DEFAULTS.auto_summary_default = "off"; + std::vector datafiles; + std::string input_file; + + sparta::app::CommandLineSimulator cls(USAGE, DEFAULTS); + auto & app_opts = cls.getApplicationOptions(); + app_opts.add_options() + ("output_file", + sparta::app::named_value>("output_file", &datafiles), + "Specifies the output file") + ("input-file", + sparta::app::named_value("INPUT_FILE", &input_file)->default_value(""), + "Provide a JSON instruction stream", + "Provide a JSON file with instructions to run through Execute"); + + po::positional_options_description& pos_opts = cls.getPositionalOptions(); + pos_opts.add("output_file", -1); // example, look for the at the end + + int err_code = 0; + if(!cls.parse(argc, argv, err_code)){ + sparta_assert(false, "Command line parsing failed"); // Any errors already printed to cerr + } + + sparta_assert(false == datafiles.empty(), "Need an output file as the last argument of the test"); + + sparta::Scheduler sched; + L2CacheSim l2cache_sim(&sched, "mavis_isa_files", "arches/isa_json", datafiles[0], input_file); + + cls.populateSimulation(&l2cache_sim); + + cls.runSimulator(&l2cache_sim); + + EXPECT_FILES_EQUAL(datafiles[0], "expected_output/" + datafiles[0] + ".EXPECTED"); +} + +int main(int argc, char **argv) +{ + runTest(argc, argv); + + REPORT_ERROR; + return (int)ERROR_CODE; +} diff --git a/test/core/l2cache/L2SourceUnit.hpp b/test/core/l2cache/L2SourceUnit.hpp new file mode 100644 index 00000000..86c93be1 --- /dev/null +++ b/test/core/l2cache/L2SourceUnit.hpp @@ -0,0 +1,125 @@ +#pragma once + + +#include "core/InstGenerator.hpp" +#include "core/MavisUnit.hpp" +#include "mavis/ExtractorDirectInfo.h" +#include "sparta/simulation/TreeNode.hpp" +#include "sparta/events/SingleCycleUniqueEvent.hpp" +#include "sparta/utils/SpartaSharedPointer.hpp" +#include "sparta/utils/LogUtils.hpp" + +#include + +namespace l2cache_test +{ + // //////////////////////////////////////////////////////////////////////////////// + // "Source" unit, just Sources instructions sent to it. Sends credits + // back as directed by params/execution mode + class L2SourceUnit : public sparta::Unit + { + public: + static constexpr char name[] = "L2SourceUnit"; + + class L2SourceUnitParameters : public sparta::ParameterSet + { + public: + explicit L2SourceUnitParameters(sparta::TreeNode *n) : + sparta::ParameterSet(n) + { } + PARAMETER(bool, unit_enable, true, "Is this unit enabled?") + PARAMETER(std::string, input_file, "", "Input file: STF or JSON") + PARAMETER(sparta::Clock::Cycle, delay_btwn_insts, 50, "Clock delay between instruction/requests to L2Cache") + }; + + L2SourceUnit(sparta::TreeNode * n, const L2SourceUnitParameters * params) + : sparta::Unit(n), + mavis_facade_(olympia::getMavis(n)), + delay_btwn_insts_(params->delay_btwn_insts), + unit_enable_(params->unit_enable) { + + sparta_assert(mavis_facade_ != nullptr, "Could not find the Mavis Unit"); + + in_source_resp_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2SourceUnit, ReceiveInst_, olympia::InstPtr)); + in_source_ack_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2SourceUnit, ReceiveAck_, bool)); + + if(params->input_file != "") { + inst_generator_ = olympia::InstGenerator::createGenerator(mavis_facade_, params->input_file, false); + } + + if (unit_enable_ == true) + sparta::StartupEvent(n, CREATE_SPARTA_HANDLER(L2SourceUnit, injectInsts_)); + } + + ~L2SourceUnit() { + sparta_assert(unit_enable_ == true && pending_reqs_ == 0, "pending_reqs remaining in the L2SourceUnit") + sparta_assert(unit_enable_ == true && pending_acks_ == 0, "pending_acks remaining in the L2SourceUnit") + } + + private: + + void injectInsts_() { + olympia::InstPtr dinst; + + if(inst_generator_) { + + while (!inst_generator_->isDone()) { + + dinst = inst_generator_->getNextInst(getClock()); + dinst->setUniqueID(unique_id_++); + + req_inst_queue_.emplace_back(dinst); + ev_req_inst_.schedule(schedule_time_); + + schedule_time_ += delay_btwn_insts_; + } + } + } + + void req_inst_() { + + ILOG("Instruction: '" << req_inst_queue_.front() << "' Requested"); + + pending_reqs_++; + pending_acks_++; + + out_source_req_.send(req_inst_queue_.front()); + req_inst_queue_.erase(req_inst_queue_.begin()); + } + + void ReceiveInst_(const olympia::InstPtr & instPtr) { + pending_reqs_--; + ILOG("Instruction: '" << instPtr << "' Received"); + } + + void ReceiveAck_(const bool & ack) { + pending_acks_--; + ILOG("Ack: '" << ack << "' Received"); + } + + sparta::DataInPort in_source_resp_ {&unit_port_set_, "in_source_resp", + sparta::SchedulingPhase::Tick, 1}; + sparta::DataInPort in_source_ack_ {&unit_port_set_, "in_source_ack"}; + + sparta::DataOutPort out_source_req_ {&unit_port_set_, "out_source_req"}; + + uint32_t pending_acks_ = 0; + uint32_t pending_reqs_ = 0; + + uint32_t unique_id_ = 0; + + olympia::MavisType * mavis_facade_ = nullptr; + std::unique_ptr inst_generator_; + + // Event to issue request to L2Cache + sparta::UniqueEvent<> ev_req_inst_ + {&unit_event_set_, "req_inst", CREATE_SPARTA_HANDLER(L2SourceUnit, req_inst_)}; + + std::vector req_inst_queue_; + sparta::Clock::Cycle schedule_time_ = 0; + sparta::Clock::Cycle delay_btwn_insts_ = 0; + bool unit_enable_; + }; +} \ No newline at end of file diff --git a/test/core/l2cache/expected_output/hit_case.out.EXPECTED b/test/core/l2cache/expected_output/hit_case.out.EXPECTED new file mode 100644 index 00000000..e54b5082 --- /dev/null +++ b/test/core/l2cache/expected_output/hit_case.out.EXPECTED @@ -0,0 +1,93 @@ +#Name: +#Cmdline: +#Exe: +#SimulatorVersion: +#Repro: +#Start: Thursday Thu Oct 26 12:21:09 2023 +#Elapsed: 0.134161s +{0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 +{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 +{0000000000 00000000 top.lsu info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000000 00000000 top.il1 info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000001 00000001 top.l2cache info} getReqFromLSU_: Request received from LSU on the port +{0000000001 00000001 top.l2cache info} appendLSUReqQueue_: Append LSU->L2Cache request queue! +{0000000001 00000001 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port +{0000000001 00000001 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! +{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 +{0000000001 00000001 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! +{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 11 +{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - LSU +{0000000001 00000001 top.l2cache info} create_Req_: LSU request is sent to Pipeline_req_Q! +{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 12 +{0000000001 00000001 top.il1 info} ReceiveAck_: Ack: '1' Received +{0000000001 00000001 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! +{0000000001 00000001 top.lsu info} ReceiveAck_: Ack: '1' Received +{0000000001 00000001 top.l2cache info} handle_L2Cache_LSU_Ack_: L2Cache Ack is sent to LSU! +{0000000011 00000011 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000012 00000012 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000013 00000013 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000013 00000013 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000014 00000014 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000014 00000014 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000014 00000014 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue : Remaining BIU credits = 3 +{0000000014 00000014 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU! +{0000000015 00000015 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000016 00000016 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 +{0000000026 00000026 top.l2cache info} getRespFromBIU_: Response received from BIU on the port +{0000000026 00000026 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! +{0000000026 00000026 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 +{0000000026 00000026 top.l2cache info} create_Req_: BIU cache reload request is sent to Pipeline_req_Q! +{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 37 +{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : LSU +{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 38 +{0000000037 00000037 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000038 00000038 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000039 00000039 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000039 00000039 top.l2cache info} reloadCache_: Cache reload complete! +{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Post-Reload State set to : Cache HIT: phyAddr=0xdeadbeef +{0000000040 00000040 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000040 00000040 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000040 00000040 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000040 00000040 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! +{0000000040 00000040 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! +{0000000041 00000041 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000041 00000041 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000041 00000041 top.l2cache info} appendLSURespQueue_: Append L2Cache->LSU resp queue! +{0000000041 00000041 top.l2cache info} handle_L2Cache_LSU_Resp_: L2Cache Resp is sent to LSU! +{0000000042 00000042 top.lsu info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000050 00000050 top.lsu info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested +{0000000050 00000050 top.il1 info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested +{0000000051 00000051 top.l2cache info} getReqFromLSU_: Request received from LSU on the port +{0000000051 00000051 top.l2cache info} appendLSUReqQueue_: Append LSU->L2Cache request queue! +{0000000051 00000051 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port +{0000000051 00000051 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! +{0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 +{0000000051 00000051 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! +{0000000051 00000051 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 61 +{0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - LSU +{0000000051 00000051 top.l2cache info} create_Req_: LSU request is sent to Pipeline_req_Q! +{0000000051 00000051 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 62 +{0000000051 00000051 top.il1 info} ReceiveAck_: Ack: '1' Received +{0000000051 00000051 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! +{0000000051 00000051 top.lsu info} ReceiveAck_: Ack: '1' Received +{0000000051 00000051 top.l2cache info} handle_L2Cache_LSU_Ack_: L2Cache Ack is sent to LSU! +{0000000061 00000061 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000062 00000062 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000063 00000063 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000063 00000063 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000064 00000064 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000064 00000064 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000064 00000064 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000064 00000064 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! +{0000000064 00000064 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! +{0000000065 00000065 top.il1 info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000065 00000065 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000065 00000065 top.l2cache info} appendLSURespQueue_: Append L2Cache->LSU resp queue! +{0000000065 00000065 top.l2cache info} handle_L2Cache_LSU_Resp_: L2Cache Resp is sent to LSU! +{0000000066 00000066 top.lsu info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received diff --git a/test/core/l2cache/expected_output/single_access.out.EXPECTED b/test/core/l2cache/expected_output/single_access.out.EXPECTED new file mode 100644 index 00000000..5b5b0b55 --- /dev/null +++ b/test/core/l2cache/expected_output/single_access.out.EXPECTED @@ -0,0 +1,63 @@ +#Name: +#Cmdline: +#Exe: +#SimulatorVersion: +#Repro: +#Start: Thursday Thu Oct 26 11:55:11 2023 +#Elapsed: 0.078725s +{0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 +{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 +{0000000000 00000000 top.lsu info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000000 00000000 top.il1 info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000001 00000001 top.l2cache info} getReqFromLSU_: Request received from LSU on the port +{0000000001 00000001 top.l2cache info} appendLSUReqQueue_: Append LSU->L2Cache request queue! +{0000000001 00000001 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port +{0000000001 00000001 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! +{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 +{0000000001 00000001 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! +{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 11 +{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - LSU +{0000000001 00000001 top.l2cache info} create_Req_: LSU request is sent to Pipeline_req_Q! +{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 12 +{0000000001 00000001 top.il1 info} ReceiveAck_: Ack: '1' Received +{0000000001 00000001 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! +{0000000001 00000001 top.lsu info} ReceiveAck_: Ack: '1' Received +{0000000001 00000001 top.l2cache info} handle_L2Cache_LSU_Ack_: L2Cache Ack is sent to LSU! +{0000000011 00000011 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000012 00000012 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000013 00000013 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000013 00000013 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000014 00000014 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000014 00000014 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000014 00000014 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue : Remaining BIU credits = 3 +{0000000014 00000014 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU! +{0000000015 00000015 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000016 00000016 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 +{0000000026 00000026 top.l2cache info} getRespFromBIU_: Response received from BIU on the port +{0000000026 00000026 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! +{0000000026 00000026 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 +{0000000026 00000026 top.l2cache info} create_Req_: BIU cache reload request is sent to Pipeline_req_Q! +{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 37 +{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : LSU +{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 38 +{0000000037 00000037 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000038 00000038 top.l2cache info} issue_Req_: Request is sent to Pipeline! +{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000039 00000039 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000039 00000039 top.l2cache info} reloadCache_: Cache reload complete! +{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Post-Reload State set to : Cache HIT: phyAddr=0xdeadbeef +{0000000040 00000040 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000040 00000040 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000040 00000040 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000040 00000040 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! +{0000000040 00000040 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! +{0000000041 00000041 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000041 00000041 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000041 00000041 top.l2cache info} appendLSURespQueue_: Append L2Cache->LSU resp queue! +{0000000041 00000041 top.l2cache info} handle_L2Cache_LSU_Resp_: L2Cache Resp is sent to LSU! +{0000000042 00000042 top.lsu info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received diff --git a/test/core/l2cache/hit_case.json b/test/core/l2cache/hit_case.json new file mode 100644 index 00000000..68cfe280 --- /dev/null +++ b/test/core/l2cache/hit_case.json @@ -0,0 +1,14 @@ +[ + { + "mnemonic": "sw", + "rs2": 3, + "vaddr" : "0xdeadbeef" + }, + { + "mnemonic": "lw", + "rs1": 3, + "rs2": 4, + "rd": 5, + "vaddr" : "0xdeadbeef" + } +] \ No newline at end of file diff --git a/test/core/l2cache/single_access.json b/test/core/l2cache/single_access.json new file mode 100644 index 00000000..46a55a69 --- /dev/null +++ b/test/core/l2cache/single_access.json @@ -0,0 +1,7 @@ +[ + { + "mnemonic": "sw", + "rs2": 3, + "vaddr" : "0xdeadbeef" + } +] \ No newline at end of file diff --git a/test/core/l2cache/test_arches/2_src_L2Cache.yaml b/test/core/l2cache/test_arches/2_src_L2Cache.yaml new file mode 100644 index 00000000..62b29d87 --- /dev/null +++ b/test/core/l2cache/test_arches/2_src_L2Cache.yaml @@ -0,0 +1,27 @@ +top: + il1: + params: + unit_enable: true + delay_btwn_insts: 50 + dcache: + params: + unit_enable: true + delay_btwn_insts: 50 + l2cache: + params: + dcache_req_queue_size: 8 + dcache_resp_queue_size: 4 + il1_req_queue_size: 8 + il1_resp_queue_size: 4 + biu_req_queue_size: 8 + biu_resp_queue_size: 4 + miss_pending_buffer_size : 2 + l2_line_size : 64 + l2_size_kb : 512 + l2_associativity : 16 + l2_always_hit : false + l2cache_biu_credits: 4 + l2cache_latency: 10 + biu: + params: + sink_latency: 10 From 3da049640c43566fc3129b2718f1a0d299644e8d Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Mon, 6 Nov 2023 15:57:30 -0600 Subject: [PATCH 02/12] Unit : L2Cache - backpressure for biu credits and l2cache_pipeline_ - make regress clean --- core/CPUTopology.cpp | 6 +- core/LSU.hpp | 3 + core/MemoryAccessInfo.hpp | 1 + mss/BIU.hpp | 2 +- mss/L2Cache.cpp | 154 +++++++++--------- mss/L2Cache.hpp | 2 +- test/core/l2cache/CMakeLists.txt | 2 +- .../expected_output/hit_case.out.EXPECTED | 137 ++++++++-------- .../single_access.out.EXPECTED | 93 +++++------ 9 files changed, 198 insertions(+), 202 deletions(-) diff --git a/core/CPUTopology.cpp b/core/CPUTopology.cpp index 75f3beca..4788af5f 100644 --- a/core/CPUTopology.cpp +++ b/core/CPUTopology.cpp @@ -222,16 +222,16 @@ olympia::CoreTopologySimple::CoreTopologySimple(){ "cpu.core*.l2cache.ports.out_l2cache_dcache_resp" }, { - "cpu.core*.l2cache.ports.out_biu_req", + "cpu.core*.l2cache.ports.out_l2cache_biu_req", "cpu.core*.biu.ports.in_biu_req" }, { "cpu.core*.biu.ports.out_biu_ack", - "cpu.core*.l2cache.ports.in_biu_ack" + "cpu.core*.l2cache.ports.in_biu_l2cache_ack" }, { "cpu.core*.biu.ports.out_biu_resp", - "cpu.core*.l2cache.ports.in_biu_resp" + "cpu.core*.l2cache.ports.in_biu_l2cache_resp" }, { "cpu.core*.lsu.ports.out_mmu_lookup_req", diff --git a/core/LSU.hpp b/core/LSU.hpp index 4bc5dc68..e121dc86 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -447,6 +447,9 @@ namespace olympia case olympia::MemoryAccessInfo::CacheState::NO_ACCESS: os << "no_access"; break; + case olympia::MemoryAccessInfo::CacheState::RELOAD: + os << "reload"; + break; case olympia::MemoryAccessInfo::CacheState::MISS: os << "miss"; break; diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index c6f573a9..469b1089 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -33,6 +33,7 @@ namespace olympia { enum class CacheState : std::uint64_t { NO_ACCESS = 0, __FIRST = NO_ACCESS, + RELOAD, MISS, HIT, NUM_STATES, diff --git a/mss/BIU.hpp b/mss/BIU.hpp index 63e12817..09a3dfe6 100644 --- a/mss/BIU.hpp +++ b/mss/BIU.hpp @@ -71,7 +71,7 @@ namespace olympia_mss {&unit_port_set_, "out_biu_ack"}; sparta::DataOutPort out_biu_resp_ - {&unit_port_set_, "out_biu_ack"}; + {&unit_port_set_, "out_biu_resp"}; sparta::SyncOutPort out_mss_req_sync_ {&unit_port_set_, "out_mss_req_sync", getClock()}; diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index c1edf628..2c5dbc67 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -220,12 +220,21 @@ namespace olympia_mss // Handle L2Cache request to BIU void L2Cache::handle_L2Cache_BIU_Req_() { - out_biu_req_.send(biu_req_queue_.front()); - biu_req_queue_.erase(biu_req_queue_.begin()); + + if (l2cache_biu_credits_ > 0 && !biu_req_queue_.empty()) { + out_biu_req_.send(biu_req_queue_.front()); + l2cache_biu_credits_--; + + biu_req_queue_.erase(biu_req_queue_.begin()); - num_reqs_to_biu_++; + num_reqs_to_biu_++; - ILOG("L2Cache Request sent to BIU!"); + ILOG("L2Cache Request sent to BIU : Current BIU credits = " << l2cache_biu_credits_); + } + else { + // Loop on biu_req_queue_ if the requests are present + ev_handle_l2cache_biu_req_.schedule(sparta::Clock::Cycle(1)); + } } // Returning ack to DCache @@ -268,63 +277,55 @@ namespace olympia_mss void L2Cache::create_Req_() { channel arbitration_winner = arbitrateL2CacheAccessReqs_(); - uint32_t num_inst_found = 0; if (arbitration_winner == channel::BIU) { const olympia::InstPtr &instPtr = biu_resp_queue_.front(); - // request in the miss_pending_buffer iterator - auto iter = miss_pending_buffer_.begin(); - auto req = iter; - // Function to check if the request to the given cacheline is present in the miss_pending_buffer_ auto getCacheLine = [this] (auto inst_ptr) { return inst_ptr->getRAdr() >> shiftBy_; }; auto is_addr_present = [instPtr, getCacheLine] (auto reqPtr) { return getCacheLine(reqPtr->getInstPtr()) == getCacheLine(instPtr); }; - // Find the instructions from the miss_pending_buffer_ - while (iter != miss_pending_buffer_.end()) { + auto req = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_addr_present); - req = std::find_if(iter, miss_pending_buffer_.end(), is_addr_present); - iter = req; + // Set the original SrcUnit as the DestUnit because the resp will + // now be forwarded from BIU to the original SrcUnit + if (req != miss_pending_buffer_.end()) { - // Set the original SrcUnit as the DestUnit because the resp will - // now be forwarded from BIU to the original SrcUnit - if (req != miss_pending_buffer_.end()) { + ILOG("Request found in miss_pending_buffer_ with SrcUnit : " << (*req)->getSrcUnit()); - ILOG("Request found in miss_pending_buffer_ with SrcUnit : " << (*req)->getSrcUnit()); - num_inst_found++; + (*req)->setDestUnit((*req)->getSrcUnit()); + (*req)->setSrcUnit(L2UnitName::BIU); + (*req)->setCacheState(L2CacheState::RELOAD); - (*req)->setDestUnit((*req)->getSrcUnit()); - (*req)->setSrcUnit(L2UnitName::BIU); - - if (pipeline_req_queue_.size() < pipeline_req_queue_size_) { - pipeline_req_queue_.push(*req); - } - else { - sparta_assert("pipeline_req_queue_ is full. Check the sizing.") - } - - if (num_inst_found == 1) - ILOG("BIU cache reload request is sent to Pipeline_req_Q!"); - - iter++; + if (pipeline_req_queue_.numFree() > 0) { + pipeline_req_queue_.push(*req); + } + else { + sparta_assert("pipeline_req_queue_ is full. Check the sizing.") + } + + // Check if this was the last occuring + auto iter = req; iter++; + auto next_req = std::find_if(iter, miss_pending_buffer_.end(), is_addr_present); + + if (next_req == miss_pending_buffer_.end()) { - miss_pending_buffer_.erase(req); + // When the find_if() returns .end(), free the entry in the biu_resp_queue_ + biu_resp_queue_.erase(biu_resp_queue_.begin()); } - } - - if (num_inst_found == 0) - sparta_assert("No match found for the BIU resp in the miss_pending_buffer!!"); - biu_resp_queue_.erase(biu_resp_queue_.begin()); + // Free the entry in the miss_pending_buffer_ + miss_pending_buffer_.erase(req); + } } else if (arbitration_winner == channel::IL1) { const auto &reqPtr = std::make_shared(il1_req_queue_.front()); reqPtr->setSrcUnit(L2UnitName::IL1); + reqPtr->setDestUnit(L2UnitName::IL1); pipeline_req_queue_.push(reqPtr); ILOG("IL1 request is sent to Pipeline_req_Q!"); @@ -339,6 +340,7 @@ namespace olympia_mss const auto &reqPtr = std::make_shared(dcache_req_queue_.front()); reqPtr->setSrcUnit(L2UnitName::DCACHE); + reqPtr->setDestUnit(L2UnitName::DCACHE); pipeline_req_queue_.push(reqPtr); ILOG("DCache request is sent to Pipeline_req_Q!"); @@ -349,13 +351,14 @@ namespace olympia_mss ev_handle_l2cache_dcache_ack_.schedule(sparta::Clock::Cycle(0)); } + // Try to issue a request to l2cache_pipeline_ ev_issue_req_.schedule(sparta::Clock::Cycle(0)); - if ( (!biu_resp_queue_.empty() - || !il1_req_queue_.empty() - || !dcache_req_queue_.empty() ) - - && (pipeline_req_queue_.numFree() > 0)) + // Schedule a ev_create_req_ event again to see if the the new request + // from any of the requestors can be put into pipeline_req_queue_ + if ( !biu_resp_queue_.empty() + || !il1_req_queue_.empty() + || !dcache_req_queue_.empty() ) ev_create_req_.schedule(sparta::Clock::Cycle(1)); } @@ -377,55 +380,52 @@ namespace olympia_mss ev_issue_req_.schedule(sparta::Clock::Cycle(1)); } - // Pipeline Stage 1 + // Pipeline Stage CACHE_LOOKUP void L2Cache::handleCacheAccessRequest_() { const auto req = l2cache_pipeline_[stages_.CACHE_LOOKUP]; - ILOG("Pipeline stage 1! - " << req->getInstPtr()); + ILOG("Pipeline stage CACHE_LOOKUP : " << req->getInstPtr()); - // Access cache, and check cache hit or miss const L2CacheState cacheLookUpResult = cacheLookup_(req); - - // Update memory access info - req->setCacheState(cacheLookUpResult); - - if (cacheLookUpResult == L2CacheState::MISS) { - if (req->getSrcUnit() == L2UnitName::BIU) { + + // Access cache, and check cache hit or miss + if (req->getCacheState() == L2CacheState::RELOAD) { + if (cacheLookUpResult == L2CacheState::MISS) { + // Reload cache line reloadCache_(req->getInstPtr()->getRAdr()); - req->setCacheState(L2CacheState::HIT); - ILOG("Post-Reload State set to : Cache HIT: phyAddr=0x" << std::hex << req->getInstPtr()->getRAdr()); + + ILOG("Reload Complete: phyAddr=0x" << std::hex << req->getInstPtr()->getRAdr()); } + + req->setCacheState(L2CacheState::HIT); } - else if (cacheLookUpResult == L2CacheState::HIT) { - if (req->getSrcUnit() != L2UnitName::BIU) { - - // Return the request back to where it came from - req->setDestUnit(req->getSrcUnit()); - } + else { + + // Update memory access info + req->setCacheState(cacheLookUpResult); } } - // Pipeline Stage 2 + // Pipeline Stage HIT_MISS_HANDLING void L2Cache::handleCacheAccessResult_() { const auto req = l2cache_pipeline_[stages_.HIT_MISS_HANDLING]; - ILOG("Pipeline stage 2! " << req->getInstPtr()); + ILOG("Pipeline stage HIT_MISS_HANDLING : " << req->getInstPtr()); inFlight_reqs_--; - + + // This request to access cache came from DCache or IL1 to do a cache lookup. + // It was either a miss or hit based on cacheLookup_() in the previous stage of the pipeline if (req->getCacheState() == L2CacheState::HIT) { // If it was originally a miss in L2Cache, on return from BIU, it's SrcUnit is set to BIU // and DestUnit to whatever the original SrcUnit was. // // If it was a hit in L2Cache, return the request back to where it originally came from. // - // Send out the resp to the original SrcUnit -- which is now the DestUnit. + // Send out the resp to the original SrcUnit -- which is now the DestUnit. sendOutResp_(req->getDestUnit(), req->getInstPtr()); } - else { // if (req->getCacheState() == L2CacheState::MISS) - // This request to access cache came from DCache or IL1 to do a cache lookup. - // It was either a miss or hit based on cacheLookup_() in the previous stage of the pipeline - + else { // if (req->getCacheState() == L2CacheState::MISS) // Set Destination for this request to BIU req->setDestUnit(L2UnitName::BIU); @@ -433,11 +433,12 @@ namespace olympia_mss // Handle the miss instruction by storing it aside while waiting // for lower level memory to return if (miss_pending_buffer_.size() < miss_pending_buffer_size_) { + ILOG("Storing the CACHE MISS in miss_pending_buffer_"); miss_pending_buffer_.push_back(req); } else { - sparta_assert("No space in miss_pending_buffer_!"); + sparta_assert("No space in miss_pending_buffer_! Why did the frontend issue push the request onto l2cache_pipeline_?"); } // Function to check if the request to the given cacheline is present in the miss_pending_buffer_ @@ -514,17 +515,16 @@ namespace olympia_mss sparta_assert(biu_req_queue_.size() <= biu_req_queue_size_ ,"BIU req queue overflows!"); // Push new request to the biu_req_queue_ if biu credits are available with the L2Cache - if (l2cache_biu_credits_ > 0) { + if (biu_req_queue_.size() < biu_req_queue_size_) { biu_req_queue_.emplace_back(inst_ptr); - l2cache_biu_credits_-- ; ev_handle_l2cache_biu_req_.schedule(sparta::Clock::Cycle(0)); } else { - sparta_assert("Can't send out this biu request :: OUT OF BIU CREDITS"); + sparta_assert("No space in biu_req_queue_! Why did the frontend issue push the request onto l2cache_pipeline_?"); } - ILOG("Append L2Cache->BIU req queue : Remaining BIU credits = " << l2cache_biu_credits_); + ILOG("Append L2Cache->BIU req queue"); } // Return the resp to the master units @@ -564,6 +564,12 @@ namespace olympia_mss channel winner; + if (pipeline_req_queue_.numFree() == 0) { + + // pipeline_req_queue_ is full + return channel::NO_ACCESS; + } + // P0 priority to sevice the pending request in the buffer if (!biu_resp_queue_.empty()) { winner = channel::BIU; @@ -638,8 +644,6 @@ namespace olympia_mss void L2Cache::reloadCache_(uint64_t phyAddr) { auto l2_cache_line = &l2_cache_->getLineForReplacementWithInvalidCheck(phyAddr); l2_cache_->allocateWithMRUUpdate(*l2_cache_line, phyAddr); - - ILOG("Cache reload complete!"); } // Check if there are enough credits for the request to be issued to the l2cache_pipeline_ diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index d7427b1e..52cff534 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -195,6 +195,7 @@ namespace olympia_mss // Instead using std::shared_ptr. That works cleanly. using L2MemoryAccessInfoPtr = std::shared_ptr; using L2UnitName = olympia::MemoryAccessInfo::UnitName; + using L2CacheState = olympia::MemoryAccessInfo::CacheState; using L2CachePipeline = sparta::Pipeline; PipelineStages stages_; @@ -212,7 +213,6 @@ namespace olympia_mss // L2 Cache - using L2CacheState = olympia::MemoryAccessInfo::CacheState; using CacheHandle = olympia::SimpleDL1::Handle; uint32_t l2_lineSize_; uint8_t shiftBy_; diff --git a/test/core/l2cache/CMakeLists.txt b/test/core/l2cache/CMakeLists.txt index 57e7b267..809b5a5c 100644 --- a/test/core/l2cache/CMakeLists.txt +++ b/test/core/l2cache/CMakeLists.txt @@ -5,7 +5,7 @@ add_executable(L2Cache_test L2Cache_test.cpp) target_link_libraries(L2Cache_test core common_test mss ${STF_LINK_LIBS} SPARTA::sparta) file(CREATE_LINK ${SIM_BASE}/mavis/json ${CMAKE_CURRENT_BINARY_DIR}/mavis_isa_files SYMBOLIC) -file(CREATE_LINK ${SIM_BASE}/arches ${CMAKE_CURRENT_BINARY_DIR}/arches SYMBOLIC) +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/test_arches ${CMAKE_CURRENT_BINARY_DIR}/test_arches SYMBOLIC) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/expected_output ${CMAKE_CURRENT_BINARY_DIR}/expected_output SYMBOLIC) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/single_access.json ${CMAKE_CURRENT_BINARY_DIR}/single_access.json SYMBOLIC) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/hit_case.json ${CMAKE_CURRENT_BINARY_DIR}/hit_case.json SYMBOLIC) diff --git a/test/core/l2cache/expected_output/hit_case.out.EXPECTED b/test/core/l2cache/expected_output/hit_case.out.EXPECTED index e54b5082..faa7c45e 100644 --- a/test/core/l2cache/expected_output/hit_case.out.EXPECTED +++ b/test/core/l2cache/expected_output/hit_case.out.EXPECTED @@ -3,91 +3,84 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Thursday Thu Oct 26 12:21:09 2023 -#Elapsed: 0.134161s +#Start: Monday Mon Nov 6 14:35:37 2023 +#Elapsed: 0.07909s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 {0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 -{0000000000 00000000 top.lsu info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000000 00000000 top.il1 info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested -{0000000001 00000001 top.l2cache info} getReqFromLSU_: Request received from LSU on the port -{0000000001 00000001 top.l2cache info} appendLSUReqQueue_: Append LSU->L2Cache request queue! +{0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port +{0000000001 00000001 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! {0000000001 00000001 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port {0000000001 00000001 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! {0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 {0000000001 00000001 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! -{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 11 -{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - LSU -{0000000001 00000001 top.l2cache info} create_Req_: LSU request is sent to Pipeline_req_Q! -{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 12 {0000000001 00000001 top.il1 info} ReceiveAck_: Ack: '1' Received {0000000001 00000001 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! -{0000000001 00000001 top.lsu info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_LSU_Ack_: L2Cache Ack is sent to LSU! -{0000000011 00000011 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000012 00000012 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000013 00000013 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000013 00000013 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000014 00000014 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000014 00000014 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000014 00000014 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue : Remaining BIU credits = 3 -{0000000014 00000014 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU! -{0000000015 00000015 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked -{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000016 00000016 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 -{0000000026 00000026 top.l2cache info} getRespFromBIU_: Response received from BIU on the port -{0000000026 00000026 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! -{0000000026 00000026 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 -{0000000026 00000026 top.l2cache info} create_Req_: BIU cache reload request is sent to Pipeline_req_Q! -{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 37 -{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : LSU -{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 38 -{0000000037 00000037 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000038 00000038 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000039 00000039 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000039 00000039 top.l2cache info} reloadCache_: Cache reload complete! -{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Post-Reload State set to : Cache HIT: phyAddr=0xdeadbeef -{0000000040 00000040 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000040 00000040 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000040 00000040 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000040 00000040 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! -{0000000040 00000040 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! -{0000000041 00000041 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received -{0000000041 00000041 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000041 00000041 top.l2cache info} appendLSURespQueue_: Append L2Cache->LSU resp queue! -{0000000041 00000041 top.l2cache info} handle_L2Cache_LSU_Resp_: L2Cache Resp is sent to LSU! -{0000000042 00000042 top.lsu info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received -{0000000050 00000050 top.lsu info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested +{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : IL1 +{0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache +{0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! +{0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received +{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache Ack is sent to DCache! +{0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE +{0000000010 00000010 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000010 00000010 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000011 00000011 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000011 00000011 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000011 00000011 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue +{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credits = 3 +{0000000012 00000012 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 +{0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port +{0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! +{0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 +{0000000033 00000033 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000034 00000034 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE +{0000000034 00000034 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000042 00000042 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Reload Complete: phyAddr=0xdeadbeef +{0000000043 00000043 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000043 00000043 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000043 00000043 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000043 00000043 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! +{0000000043 00000043 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! +{0000000044 00000044 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000044 00000044 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000044 00000044 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! +{0000000044 00000044 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! +{0000000045 00000045 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000050 00000050 top.dcache info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested {0000000050 00000050 top.il1 info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested -{0000000051 00000051 top.l2cache info} getReqFromLSU_: Request received from LSU on the port -{0000000051 00000051 top.l2cache info} appendLSUReqQueue_: Append LSU->L2Cache request queue! +{0000000051 00000051 top.l2cache info} getReqFromDCache_: Request received from DCache on the port +{0000000051 00000051 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! {0000000051 00000051 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port {0000000051 00000051 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! {0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 {0000000051 00000051 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! -{0000000051 00000051 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 61 -{0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - LSU -{0000000051 00000051 top.l2cache info} create_Req_: LSU request is sent to Pipeline_req_Q! -{0000000051 00000051 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 62 {0000000051 00000051 top.il1 info} ReceiveAck_: Ack: '1' Received {0000000051 00000051 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! -{0000000051 00000051 top.lsu info} ReceiveAck_: Ack: '1' Received -{0000000051 00000051 top.l2cache info} handle_L2Cache_LSU_Ack_: L2Cache Ack is sent to LSU! -{0000000061 00000061 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000062 00000062 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000063 00000063 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000063 00000063 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000064 00000064 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000064 00000064 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000064 00000064 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000064 00000064 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! -{0000000064 00000064 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! -{0000000065 00000065 top.il1 info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received -{0000000065 00000065 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000065 00000065 top.l2cache info} appendLSURespQueue_: Append L2Cache->LSU resp queue! -{0000000065 00000065 top.l2cache info} handle_L2Cache_LSU_Resp_: L2Cache Resp is sent to LSU! -{0000000066 00000066 top.lsu info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000051 00000051 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : IL1 +{0000000052 00000052 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache +{0000000052 00000052 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! +{0000000052 00000052 top.dcache info} ReceiveAck_: Ack: '1' Received +{0000000052 00000052 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache Ack is sent to DCache! +{0000000052 00000052 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE +{0000000060 00000060 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000060 00000060 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000061 00000061 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000061 00000061 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000061 00000061 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000061 00000061 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! +{0000000061 00000061 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! +{0000000062 00000062 top.il1 info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000062 00000062 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000062 00000062 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! +{0000000062 00000062 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! +{0000000063 00000063 top.dcache info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received diff --git a/test/core/l2cache/expected_output/single_access.out.EXPECTED b/test/core/l2cache/expected_output/single_access.out.EXPECTED index 5b5b0b55..b31cce68 100644 --- a/test/core/l2cache/expected_output/single_access.out.EXPECTED +++ b/test/core/l2cache/expected_output/single_access.out.EXPECTED @@ -3,61 +3,56 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Thursday Thu Oct 26 11:55:11 2023 -#Elapsed: 0.078725s +#Start: Monday Mon Nov 6 14:37:22 2023 +#Elapsed: 0.072407s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 {0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 -{0000000000 00000000 top.lsu info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000000 00000000 top.il1 info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested -{0000000001 00000001 top.l2cache info} getReqFromLSU_: Request received from LSU on the port -{0000000001 00000001 top.l2cache info} appendLSUReqQueue_: Append LSU->L2Cache request queue! +{0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port +{0000000001 00000001 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! {0000000001 00000001 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port {0000000001 00000001 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! {0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 {0000000001 00000001 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! -{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 11 -{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - LSU -{0000000001 00000001 top.l2cache info} create_Req_: LSU request is sent to Pipeline_req_Q! -{0000000001 00000001 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 12 {0000000001 00000001 top.il1 info} ReceiveAck_: Ack: '1' Received {0000000001 00000001 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! -{0000000001 00000001 top.lsu info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_LSU_Ack_: L2Cache Ack is sent to LSU! -{0000000011 00000011 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000012 00000012 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000013 00000013 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000013 00000013 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000014 00000014 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000014 00000014 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000014 00000014 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000014 00000014 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue : Remaining BIU credits = 3 -{0000000014 00000014 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU! -{0000000015 00000015 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked -{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000015 00000015 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000016 00000016 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 -{0000000026 00000026 top.l2cache info} getRespFromBIU_: Response received from BIU on the port -{0000000026 00000026 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! -{0000000026 00000026 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 -{0000000026 00000026 top.l2cache info} create_Req_: BIU cache reload request is sent to Pipeline_req_Q! -{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 37 -{0000000026 00000026 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : LSU -{0000000026 00000026 top.l2cache info} create_Req_: Scheduled issue_req to pipeline on clock: 38 -{0000000037 00000037 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000038 00000038 top.l2cache info} issue_Req_: Request is sent to Pipeline! -{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000039 00000039 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000039 00000039 top.l2cache info} reloadCache_: Cache reload complete! -{0000000039 00000039 top.l2cache info} handleCacheAccessRequest_: Post-Reload State set to : Cache HIT: phyAddr=0xdeadbeef -{0000000040 00000040 top.l2cache info} handleCacheAccessRequest_: Pipeline stage 1! - uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000040 00000040 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000040 00000040 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000040 00000040 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! -{0000000040 00000040 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! -{0000000041 00000041 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received -{0000000041 00000041 top.l2cache info} handleCacheAccessResult_: Pipeline stage 2! uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000041 00000041 top.l2cache info} appendLSURespQueue_: Append L2Cache->LSU resp queue! -{0000000041 00000041 top.l2cache info} handle_L2Cache_LSU_Resp_: L2Cache Resp is sent to LSU! -{0000000042 00000042 top.lsu info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : IL1 +{0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache +{0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! +{0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received +{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache Ack is sent to DCache! +{0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE +{0000000010 00000010 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000010 00000010 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000011 00000011 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000011 00000011 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000011 00000011 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue +{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credits = 3 +{0000000012 00000012 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 +{0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port +{0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! +{0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 +{0000000033 00000033 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000034 00000034 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE +{0000000034 00000034 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000042 00000042 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Reload Complete: phyAddr=0xdeadbeef +{0000000043 00000043 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000043 00000043 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000043 00000043 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000043 00000043 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! +{0000000043 00000043 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! +{0000000044 00000044 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000044 00000044 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000044 00000044 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! +{0000000044 00000044 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! +{0000000045 00000045 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received From 1e31d1c839988b1f0bdabfb00e3ecea217a3c0ed Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Wed, 8 Nov 2023 22:01:46 -0600 Subject: [PATCH 03/12] Unit : L2Cache - fix for comments on PR , V1.0 --- core/LSU.hpp | 18 ++++++++---------- core/MemoryAccessInfo.hpp | 8 ++++---- mss/BIU.cpp | 4 ++-- mss/BIU.hpp | 2 +- mss/L2Cache.cpp | 33 +++++++++++++++------------------ mss/L2Cache.hpp | 39 +++++++++++++++++---------------------- 6 files changed, 47 insertions(+), 57 deletions(-) diff --git a/core/LSU.hpp b/core/LSU.hpp index e121dc86..b272eaa8 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -399,8 +399,8 @@ namespace olympia }; - inline std::ostream & operator<<(std::ostream & os, - const olympia::MemoryAccessInfo::UnitName & unit) { + inline std::ostream& operator<<(std::ostream & os, + const olympia::MemoryAccessInfo::UnitName & unit) { switch(unit) { case olympia::MemoryAccessInfo::UnitName::IL1: os << "IL1"; @@ -417,14 +417,12 @@ namespace olympia case olympia::MemoryAccessInfo::UnitName::BIU: os << "BIU"; break; - default: - throw sparta::SpartaException("NUM_STATES cannot be a valid enum state."); } return os; } - inline std::ostream & operator<<(std::ostream & os, - const olympia::MemoryAccessInfo::MMUState & mmu_access_state){ + inline std::ostream& operator<<(std::ostream & os, + const olympia::MemoryAccessInfo::MMUState & mmu_access_state){ switch(mmu_access_state){ case olympia::MemoryAccessInfo::MMUState::NO_ACCESS: os << "no_access"; @@ -441,8 +439,8 @@ namespace olympia return os; } - inline std::ostream & operator<<(std::ostream & os, - const olympia::MemoryAccessInfo::CacheState & cache_access_state){ + inline std::ostream& operator<<(std::ostream & os, + const olympia::MemoryAccessInfo::CacheState & cache_access_state){ switch(cache_access_state){ case olympia::MemoryAccessInfo::CacheState::NO_ACCESS: os << "no_access"; @@ -463,7 +461,7 @@ namespace olympia } inline std::ostream& operator<<(std::ostream& os, - const olympia::LSU::LoadStoreInstInfo::IssuePriority& rank){ + const olympia::LSU::LoadStoreInstInfo::IssuePriority& rank){ switch(rank){ case LSU::LoadStoreInstInfo::IssuePriority::HIGHEST: os << "(highest)"; @@ -493,7 +491,7 @@ namespace olympia } inline std::ostream& operator<<(std::ostream& os, - const olympia::LSU::LoadStoreInstInfo::IssueState& state){ + const olympia::LSU::LoadStoreInstInfo::IssueState& state){ // Print instruction issue state switch(state){ case LSU::LoadStoreInstInfo::IssueState::READY: diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index 469b1089..5b1b8436 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -62,8 +62,8 @@ namespace olympia { // Construct the State object here cache_access_state_(CacheState::NO_ACCESS), - src_(UnitName::IL1), - dest_(UnitName::BIU) {} + src_(UnitName::NO_ACCESS), + dest_(UnitName::NO_ACCESS) {} virtual ~MemoryAccessInfo() {} @@ -82,10 +82,10 @@ namespace olympia { bool getPhyAddrStatus() const { return phy_addr_ready_; } - void setSrcUnit(UnitName src_unit) { src_ = src_unit; } + void setSrcUnit(const UnitName & src_unit) { src_ = src_unit; } const UnitName & getSrcUnit() const { return src_; } - void setDestUnit(UnitName dest_unit) { dest_ = dest_unit; } + void setDestUnit(const UnitName & dest_unit) { dest_ = dest_unit; } const UnitName & getDestUnit() const { return dest_; } MMUState getMMUState() const { diff --git a/mss/BIU.cpp b/mss/BIU.cpp index aa1a24fb..bbc25936 100644 --- a/mss/BIU.cpp +++ b/mss/BIU.cpp @@ -19,7 +19,7 @@ namespace olympia_mss biu_latency_(p->biu_latency) { in_biu_req_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, getReqFromL2Cache_, olympia::InstPtr)); + (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, receiveReqFromL2Cache_, olympia::InstPtr)); in_mss_ack_sync_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, getAckFromMSS_, bool)); @@ -35,7 +35,7 @@ namespace olympia_mss //////////////////////////////////////////////////////////////////////////////// // Receive new BIU request from L2Cache - void BIU::getReqFromL2Cache_(const olympia::InstPtr & inst_ptr) + void BIU::receiveReqFromL2Cache_(const olympia::InstPtr & inst_ptr) { appendReqQueue_(inst_ptr); diff --git a/mss/BIU.hpp b/mss/BIU.hpp index 09a3dfe6..0a2275b9 100644 --- a/mss/BIU.hpp +++ b/mss/BIU.hpp @@ -108,7 +108,7 @@ namespace olympia_mss //////////////////////////////////////////////////////////////////////////////// // Receive new BIU request from L2Cache - void getReqFromL2Cache_(const olympia::InstPtr &); + void receiveReqFromL2Cache_(const olympia::InstPtr &); // Handle BIU request void handle_BIU_Req_(); diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index 2c5dbc67..894934b4 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -93,9 +93,6 @@ namespace olympia_mss in_biu_ack_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getAckFromBIU_, bool)); - // Default channel selected for arbitration - channel_select_ = channel::IL1; - // Pipeline collection config l2cache_pipeline_.enableCollection(node); // Allow the pipeline to create events and schedule work @@ -276,9 +273,9 @@ namespace olympia_mss // Handle arbitration and forward the req to pipeline_req_queue_ void L2Cache::create_Req_() { - channel arbitration_winner = arbitrateL2CacheAccessReqs_(); + Channel arbitration_winner = arbitrateL2CacheAccessReqs_(); - if (arbitration_winner == channel::BIU) { + if (arbitration_winner == Channel::BIU) { const olympia::InstPtr &instPtr = biu_resp_queue_.front(); @@ -320,7 +317,7 @@ namespace olympia_mss miss_pending_buffer_.erase(req); } } - else if (arbitration_winner == channel::IL1) { + else if (arbitration_winner == Channel::IL1) { const auto &reqPtr = std::make_shared(il1_req_queue_.front()); @@ -335,7 +332,7 @@ namespace olympia_mss // Send out the ack to IL1 for credit management ev_handle_l2cache_il1_ack_.schedule(sparta::Clock::Cycle(0)); } - else if (arbitration_winner == channel::DCACHE) { + else if (arbitration_winner == Channel::DCACHE) { const auto &reqPtr = std::make_shared(dcache_req_queue_.front()); @@ -553,26 +550,26 @@ namespace olympia_mss } } - // Select the channel to pick the request from + // Select the Channel to pick the request from // Current options : // BIU - P0 // DCache - P1 - RoundRobin Candidate // DL1 - P1 - RoundRobin Candidate - L2Cache::channel L2Cache::arbitrateL2CacheAccessReqs_() { + L2Cache::Channel L2Cache::arbitrateL2CacheAccessReqs_() { sparta_assert(il1_req_queue_.size() > 0 || dcache_req_queue_.size() > 0 || biu_resp_queue_.size() > 0, "Arbitration failed: Reqest queues are empty!"); - channel winner; + Channel winner; if (pipeline_req_queue_.numFree() == 0) { // pipeline_req_queue_ is full - return channel::NO_ACCESS; + return Channel::NO_ACCESS; } // P0 priority to sevice the pending request in the buffer if (!biu_resp_queue_.empty()) { - winner = channel::BIU; + winner = Channel::BIU; ILOG("Arbitration winner - BIU"); return winner; @@ -581,19 +578,19 @@ namespace olympia_mss // RoundRobin for P1 Priority while (true) { - if (channel_select_ == channel::IL1) { - channel_select_ = channel::DCACHE; + if (channel_select_ == Channel::IL1) { + channel_select_ = Channel::DCACHE; if (!il1_req_queue_.empty()) { - winner = channel::IL1; + winner = Channel::IL1; ILOG("Arbitration winner - IL1"); return winner; } } - else if (channel_select_ == channel::DCACHE) { - channel_select_ = channel::IL1; + else if (channel_select_ == Channel::DCACHE) { + channel_select_ = Channel::IL1; if (!dcache_req_queue_.empty()) { - winner = channel::DCACHE; + winner = Channel::DCACHE; ILOG("Arbitration winner - DCache"); return winner; diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index 52cff534..246561d6 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -163,7 +163,8 @@ namespace olympia_mss const uint32_t il1_resp_queue_size_; // Channels enum - enum class channel { + enum class Channel : uint32_t + { NO_ACCESS = 0, __FIRST = NO_ACCESS, BIU, @@ -171,24 +172,20 @@ namespace olympia_mss DCACHE, NUM_CHANNELS, __LAST = NUM_CHANNELS - } channel_select_; + }; + // Cache Pipeline class PipelineStages { public: - PipelineStages(uint32_t latency) { - NUM_STAGES = latency; - __LAST = NUM_STAGES; - HIT_MISS_HANDLING = NUM_STAGES - 1; - CACHE_LOOKUP = HIT_MISS_HANDLING - 1; - } - - uint32_t NO_ACCESS = 0; - uint32_t __FIRST = NO_ACCESS; - uint32_t CACHE_LOOKUP; - uint32_t HIT_MISS_HANDLING; - uint32_t NUM_STAGES; - uint32_t __LAST; + PipelineStages(uint32_t latency) : NUM_STAGES(latency), + HIT_MISS_HANDLING(NUM_STAGES - 1), + CACHE_LOOKUP(HIT_MISS_HANDLING - 1) {} + + const uint32_t NO_ACCESS = 0; + const uint32_t CACHE_LOOKUP; + const uint32_t HIT_MISS_HANDLING; + const uint32_t NUM_STAGES; }; // Skipping the use of SpartaSharedPointer due to allocator bug @@ -204,9 +201,6 @@ namespace olympia_mss sparta::Queue pipeline_req_queue_; const uint32_t pipeline_req_queue_size_; uint32_t inFlight_reqs_ = 0; - - sparta::Clock::Cycle pipeline_req_issue_clock_ = 0; - sparta::Clock::Cycle pipeline_req_issue_delay_ = 0; sparta::Buffer> miss_pending_buffer_; const uint32_t miss_pending_buffer_size_; @@ -214,13 +208,14 @@ namespace olympia_mss // L2 Cache using CacheHandle = olympia::SimpleDL1::Handle; - uint32_t l2_lineSize_; - uint8_t shiftBy_; + const uint32_t l2_lineSize_; + const uint32_t shiftBy_; CacheHandle l2_cache_; const bool l2_always_hit_; // Local state variables - uint32_t l2cache_biu_credits_; + uint32_t l2cache_biu_credits_ = 0; + sparta::State channel_select_ = Channel::IL1; const uint32_t l2cache_latency_; //////////////////////////////////////////////////////////////////////////////// @@ -352,7 +347,7 @@ namespace olympia_mss // BIU - P0 // DCache - P1 - RoundRobin Candidate // DL1 - P1 - RoundRobin Candidate - channel arbitrateL2CacheAccessReqs_(); + Channel arbitrateL2CacheAccessReqs_(); // Cache lookup for a HIT or MISS on a given request L2CacheState cacheLookup_(std::shared_ptr); From 3ddda2f3cf66b77c0ae1ea43bd6231f349dbd88c Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Wed, 8 Nov 2023 22:39:12 -0600 Subject: [PATCH 04/12] Unit : L2Cache - V1.0 - comment fixes - make regress clean --- core/LSU.hpp | 6 ++++++ mss/L2Cache.cpp | 4 ++-- mss/L2Cache.hpp | 11 ++++++----- test/core/l2cache/CMakeLists.txt | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/core/LSU.hpp b/core/LSU.hpp index b272eaa8..f136d42d 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -402,6 +402,9 @@ namespace olympia inline std::ostream& operator<<(std::ostream & os, const olympia::MemoryAccessInfo::UnitName & unit) { switch(unit) { + case olympia::MemoryAccessInfo::UnitName::NO_ACCESS: + os << "NO_ACCESS"; + break; case olympia::MemoryAccessInfo::UnitName::IL1: os << "IL1"; break; @@ -417,6 +420,9 @@ namespace olympia case olympia::MemoryAccessInfo::UnitName::BIU: os << "BIU"; break; + case olympia::MemoryAccessInfo::UnitName::NUM_UNITS: + os << "NUM_UNITS"; + break; } return os; } diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index 894934b4..4cec103f 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -76,6 +76,8 @@ namespace olympia_mss node->getClock(), &unit_stat_set_), miss_pending_buffer_size_(p->miss_pending_buffer_size), + l2_lineSize_(p->l2_line_size), + shiftBy_(log2(l2_lineSize_)), l2_always_hit_(p->l2_always_hit), l2cache_biu_credits_(p->l2cache_biu_credits), l2cache_latency_(p->l2cache_latency) { @@ -111,8 +113,6 @@ namespace olympia_mss l2cache_pipeline_.registerHandlerAtStage(stages_.HIT_MISS_HANDLING, CREATE_SPARTA_HANDLER(L2Cache, handleCacheAccessResult_)); // L2 cache config - l2_lineSize_ = p->l2_line_size; - shiftBy_ = log2(l2_lineSize_); const uint32_t l2_size_kb = p->l2_size_kb; const uint32_t l2_associativity = p->l2_associativity; std::unique_ptr repl(new sparta::cache::TreePLRUReplacement diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index 246561d6..446ac4d8 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -182,10 +182,10 @@ namespace olympia_mss HIT_MISS_HANDLING(NUM_STAGES - 1), CACHE_LOOKUP(HIT_MISS_HANDLING - 1) {} - const uint32_t NO_ACCESS = 0; - const uint32_t CACHE_LOOKUP; - const uint32_t HIT_MISS_HANDLING; const uint32_t NUM_STAGES; + const uint32_t HIT_MISS_HANDLING; + const uint32_t CACHE_LOOKUP; + const uint32_t NO_ACCESS = 0; }; // Skipping the use of SpartaSharedPointer due to allocator bug @@ -208,14 +208,15 @@ namespace olympia_mss // L2 Cache using CacheHandle = olympia::SimpleDL1::Handle; + CacheHandle l2_cache_; + const uint32_t l2_lineSize_; const uint32_t shiftBy_; - CacheHandle l2_cache_; const bool l2_always_hit_; // Local state variables uint32_t l2cache_biu_credits_ = 0; - sparta::State channel_select_ = Channel::IL1; + Channel channel_select_ = Channel::IL1; const uint32_t l2cache_latency_; //////////////////////////////////////////////////////////////////////////////// diff --git a/test/core/l2cache/CMakeLists.txt b/test/core/l2cache/CMakeLists.txt index 809b5a5c..22aa7020 100644 --- a/test/core/l2cache/CMakeLists.txt +++ b/test/core/l2cache/CMakeLists.txt @@ -5,6 +5,7 @@ add_executable(L2Cache_test L2Cache_test.cpp) target_link_libraries(L2Cache_test core common_test mss ${STF_LINK_LIBS} SPARTA::sparta) file(CREATE_LINK ${SIM_BASE}/mavis/json ${CMAKE_CURRENT_BINARY_DIR}/mavis_isa_files SYMBOLIC) +file(CREATE_LINK ${SIM_BASE}/arches ${CMAKE_CURRENT_BINARY_DIR}/arches SYMBOLIC) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/test_arches ${CMAKE_CURRENT_BINARY_DIR}/test_arches SYMBOLIC) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/expected_output ${CMAKE_CURRENT_BINARY_DIR}/expected_output SYMBOLIC) file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/single_access.json ${CMAKE_CURRENT_BINARY_DIR}/single_access.json SYMBOLIC) From c194936a6e5fd9ea19145413a7467f162275d118 Mon Sep 17 00:00:00 2001 From: Kunal-Buch <145377279+Kunal-Buch@users.noreply.github.com> Date: Thu, 9 Nov 2023 14:59:18 -0500 Subject: [PATCH 05/12] initializing src_ and dest_ inline Co-authored-by: Knute <56927209+klingaard@users.noreply.github.com> Signed-off-by: Kunal-Buch <145377279+Kunal-Buch@users.noreply.github.com> --- core/MemoryAccessInfo.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index 5b1b8436..4d6b0ba3 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -122,8 +122,8 @@ namespace olympia { CacheState cache_access_state_; // Src and destination unit name for the packet - UnitName src_; - UnitName dest_; + UnitName src_ = UnitName::NO_ACCESS; + UnitName dest_ = UnitName::NO_ACCESS; // Scoreboards using ScoreboardViews = std::array, core_types::N_REGFILES>; From 9361306ed3df7168b8f108a777abd4483087784c Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Thu, 9 Nov 2023 15:07:32 -0600 Subject: [PATCH 06/12] Unit : L2Cache - V1.1 - comment fixes for IL1 changed to ICache, UnitName remanmed to ArchUnit, and pre-incremnt for counters. --- core/LSU.hpp | 18 +- core/MemoryAccessInfo.hpp | 20 +-- mss/L2Cache.cpp | 170 +++++++++--------- mss/L2Cache.hpp | 86 ++++----- test/core/l2cache/L2Cache_test.cpp | 28 +-- .../expected_output/hit_case.out.EXPECTED | 50 +++--- .../single_access.out.EXPECTED | 28 +-- .../l2cache/test_arches/2_src_L2Cache.yaml | 6 +- 8 files changed, 203 insertions(+), 203 deletions(-) diff --git a/core/LSU.hpp b/core/LSU.hpp index f136d42d..e7762dba 100644 --- a/core/LSU.hpp +++ b/core/LSU.hpp @@ -400,27 +400,27 @@ namespace olympia }; inline std::ostream& operator<<(std::ostream & os, - const olympia::MemoryAccessInfo::UnitName & unit) { + const olympia::MemoryAccessInfo::ArchUnit & unit) { switch(unit) { - case olympia::MemoryAccessInfo::UnitName::NO_ACCESS: + case olympia::MemoryAccessInfo::ArchUnit::NO_ACCESS: os << "NO_ACCESS"; break; - case olympia::MemoryAccessInfo::UnitName::IL1: - os << "IL1"; + case olympia::MemoryAccessInfo::ArchUnit::ICACHE: + os << "ICACHE"; break; - case olympia::MemoryAccessInfo::UnitName::LSU: + case olympia::MemoryAccessInfo::ArchUnit::LSU: os << "LSU"; break; - case olympia::MemoryAccessInfo::UnitName::DCACHE: + case olympia::MemoryAccessInfo::ArchUnit::DCACHE: os << "DCACHE"; break; - case olympia::MemoryAccessInfo::UnitName::L2CACHE: + case olympia::MemoryAccessInfo::ArchUnit::L2CACHE: os << "L2CACHE"; break; - case olympia::MemoryAccessInfo::UnitName::BIU: + case olympia::MemoryAccessInfo::ArchUnit::BIU: os << "BIU"; break; - case olympia::MemoryAccessInfo::UnitName::NUM_UNITS: + case olympia::MemoryAccessInfo::ArchUnit::NUM_UNITS: os << "NUM_UNITS"; break; } diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index 5b1b8436..63998ecf 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -40,10 +40,10 @@ namespace olympia { __LAST = NUM_STATES }; - enum class UnitName : std::uint32_t { + enum class ArchUnit : std::uint32_t { NO_ACCESS = 0, __FIRST = NO_ACCESS, - IL1, + ICACHE, LSU, DCACHE, L2CACHE, @@ -62,8 +62,8 @@ namespace olympia { // Construct the State object here cache_access_state_(CacheState::NO_ACCESS), - src_(UnitName::NO_ACCESS), - dest_(UnitName::NO_ACCESS) {} + src_(ArchUnit::NO_ACCESS), + dest_(ArchUnit::NO_ACCESS) {} virtual ~MemoryAccessInfo() {} @@ -82,11 +82,11 @@ namespace olympia { bool getPhyAddrStatus() const { return phy_addr_ready_; } - void setSrcUnit(const UnitName & src_unit) { src_ = src_unit; } - const UnitName & getSrcUnit() const { return src_; } + void setSrcUnit(const ArchUnit & src_unit) { src_ = src_unit; } + const ArchUnit & getSrcUnit() const { return src_; } - void setDestUnit(const UnitName & dest_unit) { dest_ = dest_unit; } - const UnitName & getDestUnit() const { return dest_; } + void setDestUnit(const ArchUnit & dest_unit) { dest_ = dest_unit; } + const ArchUnit & getDestUnit() const { return dest_; } MMUState getMMUState() const { return mmu_access_state_; @@ -122,8 +122,8 @@ namespace olympia { CacheState cache_access_state_; // Src and destination unit name for the packet - UnitName src_; - UnitName dest_; + ArchUnit src_; + ArchUnit dest_; // Scoreboards using ScoreboardViews = std::array, core_types::N_REGFILES>; diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index 4cec103f..791e6460 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -19,9 +19,9 @@ namespace olympia_mss "num_reqs_from_dcache", "The total number of instructions received by L2Cache from DCache", sparta::Counter::COUNT_NORMAL), - num_reqs_from_il1_(&unit_stat_set_, - "num_reqs_from_il1", - "The total number of instructions received by L2Cache from IL1", + num_reqs_from_icache_(&unit_stat_set_, + "num_reqs_from_icache", + "The total number of instructions received by L2Cache from ICache", sparta::Counter::COUNT_NORMAL), num_reqs_to_biu_(&unit_stat_set_, "num_reqs_to_biu", @@ -31,9 +31,9 @@ namespace olympia_mss "num_acks_from_biu", "The total number of instructions received from BIU into L2Cache", sparta::Counter::COUNT_NORMAL), - num_acks_to_il1_(&unit_stat_set_, - "num_acks_to_il1", - "The total number of instructions forwarded from L2Cache to IL1", + num_acks_to_icache_(&unit_stat_set_, + "num_acks_to_icache", + "The total number of instructions forwarded from L2Cache to ICache", sparta::Counter::COUNT_NORMAL), num_acks_to_dcache_(&unit_stat_set_, "num_acks_to_dcache", @@ -43,9 +43,9 @@ namespace olympia_mss "num_resps_from_biu", "The total number of instructions received from BIU into L2Cache", sparta::Counter::COUNT_NORMAL), - num_resps_to_il1_(&unit_stat_set_, - "num_resps_to_il1", - "The total number of instructions forwarded from L2Cache to IL1", + num_resps_to_icache_(&unit_stat_set_, + "num_resps_to_icache", + "The total number of instructions forwarded from L2Cache to ICache", sparta::Counter::COUNT_NORMAL), num_resps_to_dcache_(&unit_stat_set_, "num_resps_to_dcache", @@ -60,11 +60,11 @@ namespace olympia_mss "The total number L2 Cache Misses", sparta::Counter::COUNT_NORMAL), dcache_req_queue_size_(p->dcache_req_queue_size), - il1_req_queue_size_(p->il1_req_queue_size), + icache_req_queue_size_(p->icache_req_queue_size), biu_req_queue_size_(p->biu_req_queue_size), biu_resp_queue_size_(p->biu_resp_queue_size), dcache_resp_queue_size_(p->dcache_resp_queue_size), - il1_resp_queue_size_(p->il1_resp_queue_size), + icache_resp_queue_size_(p->icache_resp_queue_size), stages_(p->l2cache_latency), l2cache_pipeline_("L2CachePipeline", stages_.NUM_STAGES, getClock()), pipeline_req_queue_("Pipeline_Request_Queue", @@ -86,8 +86,8 @@ namespace olympia_mss in_dcache_l2cache_req_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getReqFromDCache_, olympia::InstPtr)); - in_il1_l2cache_req_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getReqFromIL1_, olympia::InstPtr)); + in_icache_l2cache_req_.registerConsumerHandler + (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getReqFromICache_, olympia::InstPtr)); in_biu_resp_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getRespFromBIU_, olympia::InstPtr)); @@ -139,28 +139,28 @@ namespace olympia_mss // Request queue is not empty if (dcache_req_queue_.size() < dcache_req_queue_size_) { ev_handle_dcache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); - num_reqs_from_dcache_++; + ++num_reqs_from_dcache_; } else { ILOG("This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); } } - // Receive new L2Cache request from IL1 - void L2Cache::getReqFromIL1_(const olympia::InstPtr & inst_ptr) { + // Receive new L2Cache request from ICache + void L2Cache::getReqFromICache_(const olympia::InstPtr & inst_ptr) { - ILOG("Request received from IL1 on the port"); + ILOG("Request received from ICache on the port"); - appendIL1ReqQueue_(inst_ptr); + appendICacheReqQueue_(inst_ptr); // Schedule L2Cache request handling event only when: // (1)Request queue is not empty - if (il1_req_queue_.size() < il1_req_queue_size_) { - ev_handle_il1_l2cache_req_.schedule(sparta::Clock::Cycle(0)); - num_reqs_from_il1_++; + if (icache_req_queue_.size() < icache_req_queue_size_) { + ev_handle_icache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); + ++num_reqs_from_icache_; } else { - ILOG("This request cannot be serviced right now, L2Cache input buffer from IL1 is already full!"); + ILOG("This request cannot be serviced right now, L2Cache input buffer from ICache is already full!"); } } @@ -175,7 +175,7 @@ namespace olympia_mss // Request queue is not empty if (biu_resp_queue_.size() < biu_resp_queue_size_) { ev_handle_biu_l2cache_resp_.schedule(sparta::Clock::Cycle(0)); - num_resps_from_biu_++; + ++num_resps_from_biu_; } else { ILOG("This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); @@ -186,7 +186,7 @@ namespace olympia_mss void L2Cache::getAckFromBIU_(const bool & ack) { // Update the biu credits - l2cache_biu_credits_++; + ++l2cache_biu_credits_; // Kickstart the pipeline issueing ev_issue_req_.schedule(sparta::Clock::Cycle(0)); @@ -201,9 +201,9 @@ namespace olympia_mss } } - // Handle L2Cache request from IL1 - void L2Cache::handle_IL1_L2Cache_Req_() { - if (!il1_req_queue_.empty()) { + // Handle L2Cache request from ICache + void L2Cache::handle_ICache_L2Cache_Req_() { + if (!icache_req_queue_.empty()) { ev_create_req_.schedule(sparta::Clock::Cycle(0)); } } @@ -224,7 +224,7 @@ namespace olympia_mss biu_req_queue_.erase(biu_req_queue_.begin()); - num_reqs_to_biu_++; + ++num_reqs_to_biu_; ILOG("L2Cache Request sent to BIU : Current BIU credits = " << l2cache_biu_credits_); } @@ -237,17 +237,17 @@ namespace olympia_mss // Returning ack to DCache void L2Cache::handle_L2Cache_DCache_Ack_() { out_l2cache_dcache_ack_.send(true); - num_acks_to_dcache_++; + ++num_acks_to_dcache_; ILOG("L2Cache Ack is sent to DCache!"); } - // Returning resp to IL1 - void L2Cache::handle_L2Cache_IL1_Ack_() { - out_l2cache_il1_ack_.send(true); - num_acks_to_il1_++; + // Returning resp to ICache + void L2Cache::handle_L2Cache_ICache_Ack_() { + out_l2cache_icache_ack_.send(true); + ++num_acks_to_icache_; - ILOG("L2Cache Ack is sent to IL1!"); + ILOG("L2Cache Ack is sent to ICache!"); } // Returning resp to DCache @@ -255,19 +255,19 @@ namespace olympia_mss out_l2cache_dcache_resp_.send(dcache_resp_queue_.front()); dcache_resp_queue_.erase(dcache_resp_queue_.begin()); - num_resps_to_dcache_++; + ++num_resps_to_dcache_; ILOG("L2Cache Resp is sent to DCache!"); } - // Returning resp to IL1 - void L2Cache::handle_L2Cache_IL1_Resp_() { - out_l2cache_il1_resp_.send(il1_resp_queue_.front()); - il1_resp_queue_.erase(il1_resp_queue_.begin()); + // Returning resp to ICache + void L2Cache::handle_L2Cache_ICache_Resp_() { + out_l2cache_icache_resp_.send(icache_resp_queue_.front()); + icache_resp_queue_.erase(icache_resp_queue_.begin()); - num_resps_to_il1_++; + ++num_resps_to_icache_; - ILOG("L2Cache Resp is sent to IL1!"); + ILOG("L2Cache Resp is sent to ICache!"); } // Handle arbitration and forward the req to pipeline_req_queue_ @@ -293,7 +293,7 @@ namespace olympia_mss ILOG("Request found in miss_pending_buffer_ with SrcUnit : " << (*req)->getSrcUnit()); (*req)->setDestUnit((*req)->getSrcUnit()); - (*req)->setSrcUnit(L2UnitName::BIU); + (*req)->setSrcUnit(L2ArchUnit::BIU); (*req)->setCacheState(L2CacheState::RELOAD); if (pipeline_req_queue_.numFree() > 0) { @@ -304,7 +304,7 @@ namespace olympia_mss } // Check if this was the last occuring - auto iter = req; iter++; + auto iter = req; ++iter; auto next_req = std::find_if(iter, miss_pending_buffer_.end(), is_addr_present); if (next_req == miss_pending_buffer_.end()) { @@ -317,27 +317,27 @@ namespace olympia_mss miss_pending_buffer_.erase(req); } } - else if (arbitration_winner == Channel::IL1) { + else if (arbitration_winner == Channel::ICACHE) { - const auto &reqPtr = std::make_shared(il1_req_queue_.front()); + const auto &reqPtr = std::make_shared(icache_req_queue_.front()); - reqPtr->setSrcUnit(L2UnitName::IL1); - reqPtr->setDestUnit(L2UnitName::IL1); + reqPtr->setSrcUnit(L2ArchUnit::ICACHE); + reqPtr->setDestUnit(L2ArchUnit::ICACHE); pipeline_req_queue_.push(reqPtr); - ILOG("IL1 request is sent to Pipeline_req_Q!"); + ILOG("ICache request is sent to Pipeline_req_Q!"); - il1_req_queue_.erase(il1_req_queue_.begin()); + icache_req_queue_.erase(icache_req_queue_.begin()); - // Send out the ack to IL1 for credit management - ev_handle_l2cache_il1_ack_.schedule(sparta::Clock::Cycle(0)); + // Send out the ack to ICache for credit management + ev_handle_l2cache_icache_ack_.schedule(sparta::Clock::Cycle(0)); } else if (arbitration_winner == Channel::DCACHE) { const auto &reqPtr = std::make_shared(dcache_req_queue_.front()); - reqPtr->setSrcUnit(L2UnitName::DCACHE); - reqPtr->setDestUnit(L2UnitName::DCACHE); + reqPtr->setSrcUnit(L2ArchUnit::DCACHE); + reqPtr->setDestUnit(L2ArchUnit::DCACHE); pipeline_req_queue_.push(reqPtr); ILOG("DCache request is sent to Pipeline_req_Q!"); @@ -354,7 +354,7 @@ namespace olympia_mss // Schedule a ev_create_req_ event again to see if the the new request // from any of the requestors can be put into pipeline_req_queue_ if ( !biu_resp_queue_.empty() - || !il1_req_queue_.empty() + || !icache_req_queue_.empty() || !dcache_req_queue_.empty() ) ev_create_req_.schedule(sparta::Clock::Cycle(1)); @@ -366,7 +366,7 @@ namespace olympia_mss // and l2cache_pipeline_ has credits available if (hasCreditsForPipelineIssue_() && !pipeline_req_queue_.empty()) { l2cache_pipeline_.append(pipeline_req_queue_.front()); - inFlight_reqs_++; + ++inFlight_reqs_; ILOG("Request is sent to Pipeline! SrcUnit : " << pipeline_req_queue_.front()->getSrcUnit()); pipeline_req_queue_.pop(); @@ -411,7 +411,7 @@ namespace olympia_mss inFlight_reqs_--; - // This request to access cache came from DCache or IL1 to do a cache lookup. + // This request to access cache came from DCache or ICache to do a cache lookup. // It was either a miss or hit based on cacheLookup_() in the previous stage of the pipeline if (req->getCacheState() == L2CacheState::HIT) { // If it was originally a miss in L2Cache, on return from BIU, it's SrcUnit is set to BIU @@ -425,7 +425,7 @@ namespace olympia_mss else { // if (req->getCacheState() == L2CacheState::MISS) // Set Destination for this request to BIU - req->setDestUnit(L2UnitName::BIU); + req->setDestUnit(L2ArchUnit::BIU); // Handle the miss instruction by storing it aside while waiting // for lower level memory to return @@ -465,14 +465,14 @@ namespace olympia_mss ILOG("Append DCache->L2Cache request queue!"); } - // Append L2Cache request queue for reqs from IL1 - void L2Cache::appendIL1ReqQueue_(const olympia::InstPtr& inst_ptr) { - sparta_assert(il1_req_queue_.size() <= il1_req_queue_size_ ,"IL1 request queue overflows!"); + // Append L2Cache request queue for reqs from ICache + void L2Cache::appendICacheReqQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(icache_req_queue_.size() <= icache_req_queue_size_ ,"ICache request queue overflows!"); // Push new requests from back - il1_req_queue_.emplace_back(inst_ptr); + icache_req_queue_.emplace_back(inst_ptr); - ILOG("Append IL1->L2Cache request queue!"); + ILOG("Append ICache->L2Cache request queue!"); } // Append BIU resp queue @@ -496,15 +496,15 @@ namespace olympia_mss ILOG("Append L2Cache->DCache resp queue!"); } - // Append IL1 resp queue - void L2Cache::appendIL1RespQueue_(const olympia::InstPtr& inst_ptr) { - sparta_assert(il1_resp_queue_.size() <= il1_resp_queue_size_ ,"IL1 resp queue overflows!"); + // Append ICache resp queue + void L2Cache::appendICacheRespQueue_(const olympia::InstPtr& inst_ptr) { + sparta_assert(icache_resp_queue_.size() <= icache_resp_queue_size_ ,"ICache resp queue overflows!"); - // Push new resp to the il1_resp_queue_ - il1_resp_queue_.emplace_back(inst_ptr); - ev_handle_l2cache_il1_resp_.schedule(sparta::Clock::Cycle(0)); + // Push new resp to the icache_resp_queue_ + icache_resp_queue_.emplace_back(inst_ptr); + ev_handle_l2cache_icache_resp_.schedule(sparta::Clock::Cycle(0)); - ILOG("Append L2Cache->IL1 resp queue!"); + ILOG("Append L2Cache->ICache resp queue!"); } // Append BIU req queue @@ -525,14 +525,14 @@ namespace olympia_mss } // Return the resp to the master units - void L2Cache::sendOutResp_(const L2UnitName &unit, const olympia::InstPtr& instPtr) { + void L2Cache::sendOutResp_(const L2ArchUnit &unit, const olympia::InstPtr& instPtr) { // if (instPtr is originally from DCache) - if (unit == L2UnitName::DCACHE) { + if (unit == L2ArchUnit::DCACHE) { appendDCacheRespQueue_(instPtr); } - // if (instPtr is originally from IL1) - else if (unit == L2UnitName::IL1) { - appendIL1RespQueue_(instPtr); + // if (instPtr is originally from ICache) + else if (unit == L2ArchUnit::ICACHE) { + appendICacheRespQueue_(instPtr); } else { sparta_assert("Resp is being sent to a Unit that is not valid"); @@ -540,9 +540,9 @@ namespace olympia_mss } // Send the request to the slave units - void L2Cache::sendOutReq_(const L2UnitName &unit, const olympia::InstPtr& instPtr) { + void L2Cache::sendOutReq_(const L2ArchUnit &unit, const olympia::InstPtr& instPtr) { // if (instPtr is destined for BIU on L2Cache miss) - if (unit == L2UnitName::BIU) { + if (unit == L2ArchUnit::BIU) { appendBIUReqQueue_(instPtr); } else { @@ -556,7 +556,7 @@ namespace olympia_mss // DCache - P1 - RoundRobin Candidate // DL1 - P1 - RoundRobin Candidate L2Cache::Channel L2Cache::arbitrateL2CacheAccessReqs_() { - sparta_assert(il1_req_queue_.size() > 0 || dcache_req_queue_.size() > 0 || biu_resp_queue_.size() > 0, + sparta_assert(icache_req_queue_.size() > 0 || dcache_req_queue_.size() > 0 || biu_resp_queue_.size() > 0, "Arbitration failed: Reqest queues are empty!"); Channel winner; @@ -578,17 +578,17 @@ namespace olympia_mss // RoundRobin for P1 Priority while (true) { - if (channel_select_ == Channel::IL1) { + if (channel_select_ == Channel::ICACHE) { channel_select_ = Channel::DCACHE; - if (!il1_req_queue_.empty()) { - winner = Channel::IL1; - ILOG("Arbitration winner - IL1"); + if (!icache_req_queue_.empty()) { + winner = Channel::ICACHE; + ILOG("Arbitration winner - ICache"); return winner; } } else if (channel_select_ == Channel::DCACHE) { - channel_select_ = Channel::IL1; + channel_select_ = Channel::ICACHE; if (!dcache_req_queue_.empty()) { winner = Channel::DCACHE; ILOG("Arbitration winner - DCache"); @@ -621,15 +621,15 @@ namespace olympia_mss if (l2_always_hit_) { ILOG("HIT all the time: phyAddr=0x" << std::hex << phyAddr); - l2_cache_hits_++; + ++l2_cache_hits_; } else if (cache_hit) { ILOG("Cache HIT: phyAddr=0x" << std::hex << phyAddr); - l2_cache_hits_++; + ++l2_cache_hits_; } else { ILOG("Cache MISS: phyAddr=0x" << std::hex << phyAddr); - l2_cache_misses_++; + ++l2_cache_misses_; } return (cache_hit ? diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index 446ac4d8..af234293 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -43,8 +43,8 @@ namespace olympia_mss PARAMETER(uint32_t, dcache_req_queue_size, 8, "DCache request queue size") PARAMETER(uint32_t, dcache_resp_queue_size, 4, "DCache resp queue size") - PARAMETER(uint32_t, il1_req_queue_size, 8, "IL1 request queue size") - PARAMETER(uint32_t, il1_resp_queue_size, 4, "IL1 resp queue size") + PARAMETER(uint32_t, icache_req_queue_size, 8, "ICache request queue size") + PARAMETER(uint32_t, icache_resp_queue_size, 4, "ICache resp queue size") PARAMETER(uint32_t, biu_req_queue_size, 4, "BIU request queue size") PARAMETER(uint32_t, biu_resp_queue_size, 4, "BIU resp queue size") PARAMETER(uint32_t, pipeline_req_queue_size, 64, "Pipeline request buffer size") @@ -81,14 +81,14 @@ namespace olympia_mss //////////////////////////////////////////////////////////////////////////////// // sparta::StatisticDef cycles_per_instr_; // A simple expression to calculate IPC sparta::Counter num_reqs_from_dcache_; // Counter of number instructions received from DCache - sparta::Counter num_reqs_from_il1_; // Counter of number instructions received from IL1 + sparta::Counter num_reqs_from_icache_; // Counter of number instructions received from ICache sparta::Counter num_reqs_to_biu_; // Counter of number instructions forwarded to BIU -- Totals misses sparta::Counter num_acks_from_biu_; // Counter of number acks received from BIU - sparta::Counter num_acks_to_il1_; // Counter of number acks provided to IL1 + sparta::Counter num_acks_to_icache_; // Counter of number acks provided to ICache sparta::Counter num_acks_to_dcache_; // Counter of number acks provided to DCache sparta::Counter num_resps_from_biu_; // Counter of number responses received from BIU - sparta::Counter num_resps_to_il1_; // Counter of number responses provided to IL1 + sparta::Counter num_resps_to_icache_; // Counter of number responses provided to ICache sparta::Counter num_resps_to_dcache_; // Counter of number responses provided to DCache sparta::Counter l2_cache_hits_; // Counter of number L2 Cache Hits @@ -101,8 +101,8 @@ namespace olympia_mss sparta::DataInPort in_dcache_l2cache_req_ {&unit_port_set_, "in_dcache_l2cache_req", 1}; - sparta::DataInPort in_il1_l2cache_req_ - {&unit_port_set_, "in_il1_l2cache_req", 1}; + sparta::DataInPort in_icache_l2cache_req_ + {&unit_port_set_, "in_icache_l2cache_req", 1}; sparta::DataInPort in_biu_resp_ {&unit_port_set_, "in_biu_l2cache_resp", 1}; @@ -118,14 +118,14 @@ namespace olympia_mss sparta::DataOutPort out_biu_req_ {&unit_port_set_, "out_l2cache_biu_req"}; - sparta::DataOutPort out_l2cache_il1_resp_ - {&unit_port_set_, "out_l2cache_il1_resp"}; + sparta::DataOutPort out_l2cache_icache_resp_ + {&unit_port_set_, "out_l2cache_icache_resp"}; sparta::DataOutPort out_l2cache_dcache_resp_ {&unit_port_set_, "out_l2cache_dcache_resp"}; - sparta::DataOutPort out_l2cache_il1_ack_ - {&unit_port_set_, "out_l2cache_il1_ack"}; + sparta::DataOutPort out_l2cache_icache_ack_ + {&unit_port_set_, "out_l2cache_icache_ack"}; sparta::DataOutPort out_l2cache_dcache_ack_ {&unit_port_set_, "out_l2cache_dcache_ack"}; @@ -138,12 +138,12 @@ namespace olympia_mss using CacheRequestQueue = std::vector; - // Buffers for the incoming requests from DCache and IL1 + // Buffers for the incoming requests from DCache and ICache CacheRequestQueue dcache_req_queue_; - CacheRequestQueue il1_req_queue_; + CacheRequestQueue icache_req_queue_; const uint32_t dcache_req_queue_size_; - const uint32_t il1_req_queue_size_; + const uint32_t icache_req_queue_size_; // Buffers for the outgoing requests from L2Cache CacheRequestQueue biu_req_queue_; @@ -155,12 +155,12 @@ namespace olympia_mss const uint32_t biu_resp_queue_size_; - // Buffers for the outgoing resps to DCache and IL1 + // Buffers for the outgoing resps to DCache and ICache CacheRequestQueue dcache_resp_queue_; - CacheRequestQueue il1_resp_queue_; + CacheRequestQueue icache_resp_queue_; const uint32_t dcache_resp_queue_size_; - const uint32_t il1_resp_queue_size_; + const uint32_t icache_resp_queue_size_; // Channels enum enum class Channel : uint32_t @@ -168,7 +168,7 @@ namespace olympia_mss NO_ACCESS = 0, __FIRST = NO_ACCESS, BIU, - IL1, + ICACHE, DCACHE, NUM_CHANNELS, __LAST = NUM_CHANNELS @@ -191,7 +191,7 @@ namespace olympia_mss // Skipping the use of SpartaSharedPointer due to allocator bug // Instead using std::shared_ptr. That works cleanly. using L2MemoryAccessInfoPtr = std::shared_ptr; - using L2UnitName = olympia::MemoryAccessInfo::UnitName; + using L2ArchUnit = olympia::MemoryAccessInfo::ArchUnit; using L2CacheState = olympia::MemoryAccessInfo::CacheState; using L2CachePipeline = sparta::Pipeline; @@ -216,7 +216,7 @@ namespace olympia_mss // Local state variables uint32_t l2cache_biu_credits_ = 0; - Channel channel_select_ = Channel::IL1; + Channel channel_select_ = Channel::ICACHE; const uint32_t l2cache_latency_; //////////////////////////////////////////////////////////////////////////////// @@ -227,13 +227,13 @@ namespace olympia_mss sparta::UniqueEvent<> ev_handle_dcache_l2cache_req_ {&unit_event_set_, "ev_handle_dcache_l2cache_req", CREATE_SPARTA_HANDLER(L2Cache, handle_DCache_L2Cache_Req_)}; - // Event to handle L2Cache request from IL1 - sparta::UniqueEvent<> ev_handle_il1_l2cache_req_ - {&unit_event_set_, "ev_handle_il1_l2cache_req", CREATE_SPARTA_HANDLER(L2Cache, handle_IL1_L2Cache_Req_)}; + // Event to handle L2Cache request from ICache + sparta::UniqueEvent<> ev_handle_icache_l2cache_req_ + {&unit_event_set_, "ev_handle_icache_l2cache_req", CREATE_SPARTA_HANDLER(L2Cache, handle_ICache_L2Cache_Req_)}; - // Event to handle L2Cache resp for IL1 - sparta::UniqueEvent<> ev_handle_l2cache_il1_resp_ - {&unit_event_set_, "ev_handle_l2cache_il1_resp", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_IL1_Resp_)}; + // Event to handle L2Cache resp for ICache + sparta::UniqueEvent<> ev_handle_l2cache_icache_resp_ + {&unit_event_set_, "ev_handle_l2cache_icache_resp", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_ICache_Resp_)}; // Event to handle L2Cache resp for DCache sparta::UniqueEvent<> ev_handle_l2cache_dcache_resp_ @@ -247,9 +247,9 @@ namespace olympia_mss sparta::UniqueEvent<> ev_handle_biu_l2cache_resp_ {&unit_event_set_, "ev_handle_biu_l2cache_resp", CREATE_SPARTA_HANDLER(L2Cache, handle_BIU_L2Cache_Resp_)}; - // Event to handle L2Cache ack for IL1 - sparta::UniqueEvent<> ev_handle_l2cache_il1_ack_ - {&unit_event_set_, "ev_handle_l2cache_il1_ack", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_IL1_Ack_)}; + // Event to handle L2Cache ack for ICache + sparta::UniqueEvent<> ev_handle_l2cache_icache_ack_ + {&unit_event_set_, "ev_handle_l2cache_icache_ack", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_ICache_Ack_)}; // Event to handle L2Cache ack for DCache sparta::UniqueEvent<> ev_handle_l2cache_dcache_ack_ @@ -270,8 +270,8 @@ namespace olympia_mss // Receive new L2Cache request from DCache void getReqFromDCache_(const olympia::InstPtr &); - // Receive new L2Cache request from IL1 - void getReqFromIL1_(const olympia::InstPtr &); + // Receive new L2Cache request from ICache + void getReqFromICache_(const olympia::InstPtr &); // Receive BIU access Response void getRespFromBIU_(const olympia::InstPtr &); @@ -282,20 +282,20 @@ namespace olympia_mss // Handle L2Cache request from DCache void handle_DCache_L2Cache_Req_(); - // Handle L2Cache request from IL1 - void handle_IL1_L2Cache_Req_(); + // Handle L2Cache request from ICache + void handle_ICache_L2Cache_Req_(); // Handle L2Cache request to BIU void handle_L2Cache_BIU_Req_(); - // Handle L2Cahe resp for IL1 - void handle_L2Cache_IL1_Resp_(); + // Handle L2Cahe resp for ICache + void handle_L2Cache_ICache_Resp_(); // Handle L2Cahe resp for DCache void handle_L2Cache_DCache_Resp_(); - // Handle L2Cahe ack for IL1 - void handle_L2Cache_IL1_Ack_(); + // Handle L2Cahe ack for ICache + void handle_L2Cache_ICache_Ack_(); // Handle L2Cahe ack for DCache void handle_L2Cache_DCache_Ack_(); @@ -326,8 +326,8 @@ namespace olympia_mss // Append L2Cache request queue for reqs from DCache void appendDCacheReqQueue_(const olympia::InstPtr &); - // Append L2Cache request queue for reqs from IL1 - void appendIL1ReqQueue_(const olympia::InstPtr &); + // Append L2Cache request queue for reqs from ICache + void appendICacheReqQueue_(const olympia::InstPtr &); // Append L2Cache request queue for reqs to BIU void appendBIUReqQueue_(const olympia::InstPtr &); @@ -338,8 +338,8 @@ namespace olympia_mss // Append L2Cache resp queue for resps to DCache BIU void appendDCacheRespQueue_(const olympia::InstPtr &); - // Append L2Cache resp queue for resps to IL1 - void appendIL1RespQueue_(const olympia::InstPtr &); + // Append L2Cache resp queue for resps to ICache + void appendICacheRespQueue_(const olympia::InstPtr &); @@ -357,10 +357,10 @@ namespace olympia_mss void reloadCache_(uint64_t); // Return the resp to the master units - void sendOutResp_(const L2UnitName&, const olympia::InstPtr&); + void sendOutResp_(const L2ArchUnit&, const olympia::InstPtr&); // Send the request to the slave units - void sendOutReq_(const L2UnitName&, const olympia::InstPtr&); + void sendOutReq_(const L2ArchUnit&, const olympia::InstPtr&); // Check if there are enough credits for the request to be issued to the l2cache_pipeline_ bool hasCreditsForPipelineIssue_(); diff --git a/test/core/l2cache/L2Cache_test.cpp b/test/core/l2cache/L2Cache_test.cpp index a491e51b..5028a7c8 100644 --- a/test/core/l2cache/L2Cache_test.cpp +++ b/test/core/l2cache/L2Cache_test.cpp @@ -84,7 +84,7 @@ class L2CacheSim : public sparta::app::Simulation &mavis_fact); tns_to_delete_.emplace_back(mavis); - // Create a Source Units that represents DCache and IL1 + // Create a Source Units that represents DCache and ICache sparta::ResourceTreeNode * Test_DCache = new sparta::ResourceTreeNode(rtn, "dcache", sparta::TreeNode::GROUP_NAME_NONE, @@ -94,14 +94,14 @@ class L2CacheSim : public sparta::app::Simulation Test_DCache->getParameterSet()->getParameter("input_file")->setValueFromString(input_file_); tns_to_delete_.emplace_back(Test_DCache); - sparta::ResourceTreeNode * Test_IL1 = new sparta::ResourceTreeNode(rtn, - "il1", + sparta::ResourceTreeNode * Test_ICache = new sparta::ResourceTreeNode(rtn, + "icache", sparta::TreeNode::GROUP_NAME_NONE, sparta::TreeNode::GROUP_IDX_NONE, - "il1", - &il1_fact); - Test_IL1->getParameterSet()->getParameter("input_file")->setValueFromString(input_file_); - tns_to_delete_.emplace_back(Test_IL1); + "icache", + &icache_fact); + Test_ICache->getParameterSet()->getParameter("input_file")->setValueFromString(input_file_); + tns_to_delete_.emplace_back(Test_ICache); // Create L2Cache sparta::ResourceTreeNode * L2CacheUnit = new sparta::ResourceTreeNode(rtn, @@ -137,12 +137,12 @@ class L2CacheSim : public sparta::app::Simulation sparta::bind(root_node->getChildAs("dcache.ports.in_source_ack"), root_node->getChildAs("l2cache.ports.out_l2cache_dcache_ack")); - sparta::bind(root_node->getChildAs("il1.ports.out_source_req"), - root_node->getChildAs("l2cache.ports.in_il1_l2cache_req")); - sparta::bind(root_node->getChildAs("il1.ports.in_source_resp"), - root_node->getChildAs("l2cache.ports.out_l2cache_il1_resp")); - sparta::bind(root_node->getChildAs("il1.ports.in_source_ack"), - root_node->getChildAs("l2cache.ports.out_l2cache_il1_ack")); + sparta::bind(root_node->getChildAs("icache.ports.out_source_req"), + root_node->getChildAs("l2cache.ports.in_icache_l2cache_req")); + sparta::bind(root_node->getChildAs("icache.ports.in_source_resp"), + root_node->getChildAs("l2cache.ports.out_l2cache_icache_resp")); + sparta::bind(root_node->getChildAs("icache.ports.in_source_ack"), + root_node->getChildAs("l2cache.ports.out_l2cache_icache_ack")); sparta::bind(root_node->getChildAs("biu.ports.in_biu_req"), root_node->getChildAs("l2cache.ports.out_l2cache_biu_req")); @@ -155,7 +155,7 @@ class L2CacheSim : public sparta::app::Simulation std::unique_ptr allocators_tn_; sparta::ResourceFactory dcache_fact; - sparta::ResourceFactory il1_fact; + sparta::ResourceFactory icache_fact; sparta::ResourceFactory l2cache_fact; diff --git a/test/core/l2cache/expected_output/hit_case.out.EXPECTED b/test/core/l2cache/expected_output/hit_case.out.EXPECTED index faa7c45e..8f3dd2a1 100644 --- a/test/core/l2cache/expected_output/hit_case.out.EXPECTED +++ b/test/core/l2cache/expected_output/hit_case.out.EXPECTED @@ -3,21 +3,21 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Monday Mon Nov 6 14:35:37 2023 -#Elapsed: 0.07909s +#Start: Thursday Thu Nov 9 14:55:52 2023 +#Elapsed: 0.076123s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 {0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 {0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested -{0000000000 00000000 top.il1 info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000000 00000000 top.icache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port {0000000001 00000001 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! -{0000000001 00000001 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port -{0000000001 00000001 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! -{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 -{0000000001 00000001 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! -{0000000001 00000001 top.il1 info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! -{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : IL1 +{0000000001 00000001 top.l2cache info} getReqFromICache_: Request received from ICache on the port +{0000000001 00000001 top.l2cache info} appendICacheReqQueue_: Append ICache->L2Cache request queue! +{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache +{0000000001 00000001 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! +{0000000001 00000001 top.icache info} ReceiveAck_: Ack: '1' Received +{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache Ack is sent to ICache! +{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! {0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received @@ -38,7 +38,7 @@ {0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port {0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! {0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 +{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : ICACHE {0000000033 00000033 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU {0000000034 00000034 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU {0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE @@ -49,24 +49,24 @@ {0000000043 00000043 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000043 00000043 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef {0000000043 00000043 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000043 00000043 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! -{0000000043 00000043 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! -{0000000044 00000044 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000043 00000043 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! +{0000000043 00000043 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! +{0000000044 00000044 top.icache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received {0000000044 00000044 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000044 00000044 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! {0000000044 00000044 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! {0000000045 00000045 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received {0000000050 00000050 top.dcache info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested -{0000000050 00000050 top.il1 info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested +{0000000050 00000050 top.icache info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested {0000000051 00000051 top.l2cache info} getReqFromDCache_: Request received from DCache on the port {0000000051 00000051 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! -{0000000051 00000051 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port -{0000000051 00000051 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! -{0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 -{0000000051 00000051 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! -{0000000051 00000051 top.il1 info} ReceiveAck_: Ack: '1' Received -{0000000051 00000051 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! -{0000000051 00000051 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : IL1 +{0000000051 00000051 top.l2cache info} getReqFromICache_: Request received from ICache on the port +{0000000051 00000051 top.l2cache info} appendICacheReqQueue_: Append ICache->L2Cache request queue! +{0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache +{0000000051 00000051 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! +{0000000051 00000051 top.icache info} ReceiveAck_: Ack: '1' Received +{0000000051 00000051 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache Ack is sent to ICache! +{0000000051 00000051 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000052 00000052 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000052 00000052 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! {0000000052 00000052 top.dcache info} ReceiveAck_: Ack: '1' Received @@ -77,9 +77,9 @@ {0000000061 00000061 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' {0000000061 00000061 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef {0000000061 00000061 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000061 00000061 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! -{0000000061 00000061 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! -{0000000062 00000062 top.il1 info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000061 00000061 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! +{0000000061 00000061 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! +{0000000062 00000062 top.icache info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received {0000000062 00000062 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' {0000000062 00000062 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! {0000000062 00000062 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! diff --git a/test/core/l2cache/expected_output/single_access.out.EXPECTED b/test/core/l2cache/expected_output/single_access.out.EXPECTED index b31cce68..1a12b399 100644 --- a/test/core/l2cache/expected_output/single_access.out.EXPECTED +++ b/test/core/l2cache/expected_output/single_access.out.EXPECTED @@ -3,21 +3,21 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Monday Mon Nov 6 14:37:22 2023 -#Elapsed: 0.072407s +#Start: Thursday Thu Nov 9 14:53:08 2023 +#Elapsed: 0.078586s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 {0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 {0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested -{0000000000 00000000 top.il1 info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000000 00000000 top.icache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port {0000000001 00000001 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! -{0000000001 00000001 top.l2cache info} getReqFromIL1_: Request received from IL1 on the port -{0000000001 00000001 top.l2cache info} appendIL1ReqQueue_: Append IL1->L2Cache request queue! -{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - IL1 -{0000000001 00000001 top.l2cache info} create_Req_: IL1 request is sent to Pipeline_req_Q! -{0000000001 00000001 top.il1 info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_IL1_Ack_: L2Cache Ack is sent to IL1! -{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : IL1 +{0000000001 00000001 top.l2cache info} getReqFromICache_: Request received from ICache on the port +{0000000001 00000001 top.l2cache info} appendICacheReqQueue_: Append ICache->L2Cache request queue! +{0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache +{0000000001 00000001 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! +{0000000001 00000001 top.icache info} ReceiveAck_: Ack: '1' Received +{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache Ack is sent to ICache! +{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! {0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received @@ -38,7 +38,7 @@ {0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port {0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! {0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : IL1 +{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : ICACHE {0000000033 00000033 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU {0000000034 00000034 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU {0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE @@ -49,9 +49,9 @@ {0000000043 00000043 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000043 00000043 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef {0000000043 00000043 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000043 00000043 top.l2cache info} appendIL1RespQueue_: Append L2Cache->IL1 resp queue! -{0000000043 00000043 top.l2cache info} handle_L2Cache_IL1_Resp_: L2Cache Resp is sent to IL1! -{0000000044 00000044 top.il1 info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000043 00000043 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! +{0000000043 00000043 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! +{0000000044 00000044 top.icache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received {0000000044 00000044 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000044 00000044 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! {0000000044 00000044 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! diff --git a/test/core/l2cache/test_arches/2_src_L2Cache.yaml b/test/core/l2cache/test_arches/2_src_L2Cache.yaml index 62b29d87..73e31d5c 100644 --- a/test/core/l2cache/test_arches/2_src_L2Cache.yaml +++ b/test/core/l2cache/test_arches/2_src_L2Cache.yaml @@ -1,5 +1,5 @@ top: - il1: + icache: params: unit_enable: true delay_btwn_insts: 50 @@ -11,8 +11,8 @@ top: params: dcache_req_queue_size: 8 dcache_resp_queue_size: 4 - il1_req_queue_size: 8 - il1_resp_queue_size: 4 + icache_req_queue_size: 8 + icache_resp_queue_size: 4 biu_req_queue_size: 8 biu_resp_queue_size: 4 miss_pending_buffer_size : 2 From d317cf142cf7f8185bf6db188e2411636adeded2 Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Thu, 9 Nov 2023 15:34:53 -0600 Subject: [PATCH 07/12] Unit : L2Cache - V1.1 - absorbing 'CacheFuncModel' name change --- core/MemoryAccessInfo.hpp | 4 ++-- mss/L2Cache.cpp | 2 +- mss/L2Cache.hpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index f13fed53..4debf30f 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -122,8 +122,8 @@ namespace olympia { CacheState cache_access_state_; // Src and destination unit name for the packet - ArchUnit src_ = UnitName::NO_ACCESS; - ArchUnit dest_ = UnitName::NO_ACCESS; + ArchUnit src_ = ArchUnit::NO_ACCESS; + ArchUnit dest_ = ArchUnit::NO_ACCESS; // Scoreboards using ScoreboardViews = std::array, core_types::N_REGFILES>; diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index 791e6460..bace2f3c 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -117,7 +117,7 @@ namespace olympia_mss const uint32_t l2_associativity = p->l2_associativity; std::unique_ptr repl(new sparta::cache::TreePLRUReplacement (l2_associativity)); - l2_cache_.reset(new olympia::SimpleDL1( getContainer(), l2_size_kb, l2_lineSize_, *repl)); + l2_cache_.reset(new olympia::CacheFuncModel( getContainer(), l2_size_kb, l2_lineSize_, *repl)); ILOG("L2Cache construct: #" << node->getGroupIdx()); ILOG("Starting BIU credits = " << l2cache_biu_credits_); diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index af234293..43815ce4 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -25,7 +25,7 @@ #include "CoreTypes.hpp" #include "MemoryAccessInfo.hpp" -#include "SimpleDL1.hpp" +#include "CacheFuncModel.hpp" #include "LSU.hpp" namespace olympia_mss @@ -207,7 +207,7 @@ namespace olympia_mss // L2 Cache - using CacheHandle = olympia::SimpleDL1::Handle; + using CacheHandle = olympia::CacheFuncModel::Handle; CacheHandle l2_cache_; const uint32_t l2_lineSize_; @@ -346,8 +346,8 @@ namespace olympia_mss // Select the channel to pick the request from // Current options : // BIU - P0 + // ICache - P1 - RoundRobin Candidate // DCache - P1 - RoundRobin Candidate - // DL1 - P1 - RoundRobin Candidate Channel arbitrateL2CacheAccessReqs_(); // Cache lookup for a HIT or MISS on a given request From 3b4a2f457d43d9707c2fd1669f7c52dd9b505ab5 Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Thu, 16 Nov 2023 05:25:38 -0600 Subject: [PATCH 08/12] Unit : L2Cache - credit management between DCACHE<->L2CACHE<->BIU with _ack port --- core/DCache.cpp | 15 +++++- core/DCache.hpp | 4 ++ mss/BIU.cpp | 16 ++++++- mss/BIU.hpp | 7 +++ mss/L2Cache.cpp | 46 ++++++------------- mss/L2Cache.hpp | 6 +-- .../expected_output/hit_case.out.EXPECTED | 18 ++++---- .../single_access.out.EXPECTED | 14 +++--- .../l2cache/test_arches/2_src_L2Cache.yaml | 4 +- 9 files changed, 75 insertions(+), 55 deletions(-) diff --git a/core/DCache.cpp b/core/DCache.cpp index 1f911946..f520d651 100644 --- a/core/DCache.cpp +++ b/core/DCache.cpp @@ -6,7 +6,8 @@ namespace olympia { DCache::DCache(sparta::TreeNode *n, const CacheParameterSet *p) : sparta::Unit(n), l1_always_hit_(p->l1_always_hit), - cache_latency_(p->cache_latency){ + cache_latency_(p->cache_latency), + dcache_l2cache_credit_available_(p->l1_l2cache_credit_available){ in_lsu_lookup_req_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getInstsFromLSU_, MemoryAccessInfoPtr)); @@ -78,10 +79,15 @@ namespace olympia { memory_access_info_ptr->setCacheState(MemoryAccessInfo::CacheState::HIT); }else{ memory_access_info_ptr->setCacheState(MemoryAccessInfo::CacheState::MISS); + // Poll on dcache_l2cache_credit_available_ == true which means + // that L2Cache can accept requests from DCache. + // Provide a corresponsing backpressure mechanism up the pipeline. if(!busy_) { busy_ = true; cache_pending_inst_ = memory_access_info_ptr; out_l2cache_req_.send(cache_pending_inst_->getInstPtr()); + + // Set the dcache_l2cache_credit_available_ = false here. } } out_lsu_lookup_ack_.send(memory_access_info_ptr); @@ -95,7 +101,12 @@ namespace olympia { } void DCache::getAckFromL2Cache_(const bool &ack) { - // Process ACK + // When DCache sends the request to L2Cache for a miss, + // This bool will be set to false, and Dcache should wait for ack from + // L2Cache notifying DCache that there is space in it's dcache request buffer + // + // Set it to true so that the following misses from DCache can be sent out to L2Cache. + dcache_l2cache_credit_available_ = ack; } } diff --git a/core/DCache.hpp b/core/DCache.hpp index 15e425c1..618e9f95 100644 --- a/core/DCache.hpp +++ b/core/DCache.hpp @@ -23,6 +23,7 @@ namespace olympia { PARAMETER(uint32_t, l1_associativity, 8, "DL1 associativity (power of 2)") PARAMETER(uint32_t, cache_latency, 1, "Assumed latency of the memory system") PARAMETER(bool, l1_always_hit, false, "DL1 will always hit") + PARAMETER(bool, l1_l2cache_credit_available, true, "Aloowing L1 cache to send the first miss request to L2Cache") }; static const char name[]; @@ -47,6 +48,9 @@ namespace olympia { // Keep track of the instruction that causes current outstanding cache miss MemoryAccessInfoPtr cache_pending_inst_ = nullptr; + // Credit bool for sending miss request to L2Cache + bool dcache_l2cache_credit_available_ = true; + //////////////////////////////////////////////////////////////////////////////// // Input Ports //////////////////////////////////////////////////////////////////////////////// diff --git a/mss/BIU.cpp b/mss/BIU.cpp index bbc25936..47fcc1de 100644 --- a/mss/BIU.cpp +++ b/mss/BIU.cpp @@ -63,6 +63,11 @@ namespace olympia_mss biu_busy_ = true; out_mss_req_sync_.send(biu_req_queue_.front(), biu_latency_); + if (biu_req_queue_.size() < biu_req_queue_size_) { + // Send out the ack to L2Cache if there is space in biu_req_queue_ + ev_handle_biu_l2cache_ack_.schedule(sparta::Clock::Cycle(0)); + } + ILOG("BIU request is sent to MSS!"); } @@ -70,9 +75,11 @@ namespace olympia_mss void BIU::handle_MSS_Ack_() { out_biu_resp_.send(biu_req_queue_.front(), biu_latency_); - out_biu_ack_.send(true); biu_req_queue_.pop_front(); + + // Send out the ack to L2Cache through , we just created space in biu_req_queue_ + ev_handle_biu_l2cache_ack_.schedule(sparta::Clock::Cycle(0)); biu_busy_ = false; // Schedule BIU request handling event only when: @@ -99,6 +106,13 @@ namespace olympia_mss sparta_assert(false, "MSS is NOT done!"); } + // Handle ack backto L2Cache + void BIU::handle_BIU_L2Cache_Ack_() { + out_biu_ack_.send(true); + + ILOG("BIU->L2Cache : Ack is sent."); + } + //////////////////////////////////////////////////////////////////////////////// // Regular Function/Subroutine Call //////////////////////////////////////////////////////////////////////////////// diff --git a/mss/BIU.hpp b/mss/BIU.hpp index 0a2275b9..9c2a4ec8 100644 --- a/mss/BIU.hpp +++ b/mss/BIU.hpp @@ -102,6 +102,10 @@ namespace olympia_mss sparta::UniqueEvent<> ev_handle_mss_ack_ {&unit_event_set_, "handle_mss_ack", CREATE_SPARTA_HANDLER(BIU, handle_MSS_Ack_)}; + // Event to handleBIU ack for L2Cache + sparta::UniqueEvent<> ev_handle_biu_l2cache_ack_ + {&unit_event_set_, "ev_handle_biu_l2cache_ack", CREATE_SPARTA_HANDLER(BIU, handle_BIU_L2Cache_Ack_)}; + //////////////////////////////////////////////////////////////////////////////// // Callbacks @@ -116,6 +120,9 @@ namespace olympia_mss // Handle MSS Ack void handle_MSS_Ack_(); + // Handle ack backto L2Cache + void handle_BIU_L2Cache_Ack_(); + // Receive MSS access acknowledge // Q: Does the argument list has to be "const DataType &" ? void getAckFromMSS_(const bool &); diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index bace2f3c..bed783f0 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -79,7 +79,7 @@ namespace olympia_mss l2_lineSize_(p->l2_line_size), shiftBy_(log2(l2_lineSize_)), l2_always_hit_(p->l2_always_hit), - l2cache_biu_credits_(p->l2cache_biu_credits), + l2cache_biu_credit_available_(p->l2cache_biu_credit_available), l2cache_latency_(p->l2cache_latency) { // In Port Handler registration @@ -118,9 +118,9 @@ namespace olympia_mss std::unique_ptr repl(new sparta::cache::TreePLRUReplacement (l2_associativity)); l2_cache_.reset(new olympia::CacheFuncModel( getContainer(), l2_size_kb, l2_lineSize_, *repl)); - + ILOG("L2Cache construct: #" << node->getGroupIdx()); - ILOG("Starting BIU credits = " << l2cache_biu_credits_); + ILOG("Starting BIU credits = " << std::boolalpha << l2cache_biu_credit_available_); } @@ -135,15 +135,8 @@ namespace olympia_mss appendDCacheReqQueue_(inst_ptr); - // Schedule L2Cache request handling event only when: - // Request queue is not empty - if (dcache_req_queue_.size() < dcache_req_queue_size_) { - ev_handle_dcache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); - ++num_reqs_from_dcache_; - } - else { - ILOG("This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); - } + ev_handle_dcache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); + ++num_reqs_from_dcache_; } // Receive new L2Cache request from ICache @@ -153,15 +146,8 @@ namespace olympia_mss appendICacheReqQueue_(inst_ptr); - // Schedule L2Cache request handling event only when: - // (1)Request queue is not empty - if (icache_req_queue_.size() < icache_req_queue_size_) { - ev_handle_icache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); - ++num_reqs_from_icache_; - } - else { - ILOG("This request cannot be serviced right now, L2Cache input buffer from ICache is already full!"); - } + ev_handle_icache_l2cache_req_.schedule(sparta::Clock::Cycle(0)); + ++num_reqs_from_icache_; } // Handle BIU resp @@ -186,12 +172,12 @@ namespace olympia_mss void L2Cache::getAckFromBIU_(const bool & ack) { // Update the biu credits - ++l2cache_biu_credits_; + l2cache_biu_credit_available_ = true; // Kickstart the pipeline issueing ev_issue_req_.schedule(sparta::Clock::Cycle(0)); - ILOG("Ack received from BIU on the port : Current BIU credits = " << l2cache_biu_credits_); + ILOG("Ack received from BIU on the port : Current BIU credit availability = " << std::boolalpha << l2cache_biu_credit_available_); } // Handle L2Cache request from DCache @@ -218,15 +204,15 @@ namespace olympia_mss // Handle L2Cache request to BIU void L2Cache::handle_L2Cache_BIU_Req_() { - if (l2cache_biu_credits_ > 0 && !biu_req_queue_.empty()) { + if (l2cache_biu_credit_available_ && !biu_req_queue_.empty()) { out_biu_req_.send(biu_req_queue_.front()); - l2cache_biu_credits_--; + l2cache_biu_credit_available_ = false; biu_req_queue_.erase(biu_req_queue_.begin()); ++num_reqs_to_biu_; - ILOG("L2Cache Request sent to BIU : Current BIU credits = " << l2cache_biu_credits_); + ILOG("L2Cache Request sent to BIU : Current BIU credit availability = " << std::boolalpha <DCache : Ack is sent."); } // Returning resp to ICache @@ -247,7 +233,7 @@ namespace olympia_mss out_l2cache_icache_ack_.send(true); ++num_acks_to_icache_; - ILOG("L2Cache Ack is sent to ICache!"); + ILOG("L2Cache->ICache : Ack is sent."); } // Returning resp to DCache @@ -461,8 +447,7 @@ namespace olympia_mss // Push new requests from back dcache_req_queue_.emplace_back(inst_ptr); - - ILOG("Append DCache->L2Cache request queue!"); + ILOG("Append DCache->L2Cache request queue!"); } // Append L2Cache request queue for reqs from ICache @@ -471,7 +456,6 @@ namespace olympia_mss // Push new requests from back icache_req_queue_.emplace_back(inst_ptr); - ILOG("Append ICache->L2Cache request queue!"); } diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index 43815ce4..531d046d 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -56,7 +56,7 @@ namespace olympia_mss PARAMETER(uint32_t, l2_associativity, 16, "L2 associativity (power of 2)") PARAMETER(bool, l2_always_hit, false, "L2 will always hit") - PARAMETER(uint32_t, l2cache_biu_credits, 1, "Starting credits for BIU") + PARAMETER(bool, l2cache_biu_credit_available, true, "Starting credit availability for BIU") PARAMETER(uint32_t, l2cache_latency, 7, "Cache Lookup HIT latency") }; @@ -215,7 +215,7 @@ namespace olympia_mss const bool l2_always_hit_; // Local state variables - uint32_t l2cache_biu_credits_ = 0; + bool l2cache_biu_credit_available_ = true; Channel channel_select_ = Channel::ICACHE; const uint32_t l2cache_latency_; @@ -254,7 +254,7 @@ namespace olympia_mss // Event to handle L2Cache ack for DCache sparta::UniqueEvent<> ev_handle_l2cache_dcache_ack_ {&unit_event_set_, "ev_handle_l2cache_dcache_ack", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_DCache_Ack_)}; - + // Event to create request for pipeline and feed it to the pipeline_req_queue_ sparta::UniqueEvent<> ev_create_req_ {&unit_event_set_, "create_req", CREATE_SPARTA_HANDLER(L2Cache, create_Req_)}; diff --git a/test/core/l2cache/expected_output/hit_case.out.EXPECTED b/test/core/l2cache/expected_output/hit_case.out.EXPECTED index 8f3dd2a1..630e389e 100644 --- a/test/core/l2cache/expected_output/hit_case.out.EXPECTED +++ b/test/core/l2cache/expected_output/hit_case.out.EXPECTED @@ -3,10 +3,10 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Thursday Thu Nov 9 14:55:52 2023 -#Elapsed: 0.076123s +#Start: Thursday Thu Nov 16 04:52:05 2023 +#Elapsed: 0.085713s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 -{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 +{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = true {0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000000 00000000 top.icache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port @@ -16,12 +16,12 @@ {0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache {0000000001 00000001 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! {0000000001 00000001 top.icache info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache Ack is sent to ICache! +{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. {0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! {0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received -{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache Ack is sent to DCache! +{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. {0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE {0000000010 00000010 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000010 00000010 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef @@ -30,11 +30,11 @@ {0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ {0000000011 00000011 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue -{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credits = 3 +{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credit availability = false {0000000012 00000012 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 +{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit availability = true {0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port {0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! {0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU @@ -65,12 +65,12 @@ {0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache {0000000051 00000051 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! {0000000051 00000051 top.icache info} ReceiveAck_: Ack: '1' Received -{0000000051 00000051 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache Ack is sent to ICache! +{0000000051 00000051 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. {0000000051 00000051 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000052 00000052 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000052 00000052 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! {0000000052 00000052 top.dcache info} ReceiveAck_: Ack: '1' Received -{0000000052 00000052 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache Ack is sent to DCache! +{0000000052 00000052 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. {0000000052 00000052 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE {0000000060 00000060 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' {0000000060 00000060 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef diff --git a/test/core/l2cache/expected_output/single_access.out.EXPECTED b/test/core/l2cache/expected_output/single_access.out.EXPECTED index 1a12b399..19ad6c54 100644 --- a/test/core/l2cache/expected_output/single_access.out.EXPECTED +++ b/test/core/l2cache/expected_output/single_access.out.EXPECTED @@ -3,10 +3,10 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Thursday Thu Nov 9 14:53:08 2023 -#Elapsed: 0.078586s +#Start: Thursday Thu Nov 16 04:45:10 2023 +#Elapsed: 0.080861s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 -{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = 4 +{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = true {0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000000 00000000 top.icache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port @@ -16,12 +16,12 @@ {0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache {0000000001 00000001 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! {0000000001 00000001 top.icache info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache Ack is sent to ICache! +{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. {0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! {0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received -{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache Ack is sent to DCache! +{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. {0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE {0000000010 00000010 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000010 00000010 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef @@ -30,11 +30,11 @@ {0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ {0000000011 00000011 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue -{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credits = 3 +{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credit availability = false {0000000012 00000012 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credits = 4 +{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit availability = true {0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port {0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! {0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU diff --git a/test/core/l2cache/test_arches/2_src_L2Cache.yaml b/test/core/l2cache/test_arches/2_src_L2Cache.yaml index 73e31d5c..eb2196b8 100644 --- a/test/core/l2cache/test_arches/2_src_L2Cache.yaml +++ b/test/core/l2cache/test_arches/2_src_L2Cache.yaml @@ -20,8 +20,8 @@ top: l2_size_kb : 512 l2_associativity : 16 l2_always_hit : false - l2cache_biu_credits: 4 - l2cache_latency: 10 + l2cache_biu_credit_available : true + l2cache_latency : 10 biu: params: sink_latency: 10 From 150b1c9670d25f611c7f767274f784452771160f Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Fri, 17 Nov 2023 14:01:50 -0600 Subject: [PATCH 09/12] Unit : L2Cache - ack protocol change to credits, interface type change from bool to uint32_t + PR comment fixes. make regress clean. --- core/DCache.cpp | 13 +- core/DCache.hpp | 9 +- mss/BIU.cpp | 14 +- mss/BIU.hpp | 6 +- mss/L2Cache.cpp | 159 ++++++++++-------- mss/L2Cache.hpp | 25 ++- test/core/l2cache/BIUSinkUnit.hpp | 16 +- test/core/l2cache/L2SourceUnit.hpp | 8 +- .../expected_output/hit_case.out.EXPECTED | 109 ++++++------ .../single_access.out.EXPECTED | 79 +++++---- .../l2cache/test_arches/2_src_L2Cache.yaml | 3 +- 11 files changed, 252 insertions(+), 189 deletions(-) diff --git a/core/DCache.cpp b/core/DCache.cpp index f520d651..70761c22 100644 --- a/core/DCache.cpp +++ b/core/DCache.cpp @@ -6,14 +6,13 @@ namespace olympia { DCache::DCache(sparta::TreeNode *n, const CacheParameterSet *p) : sparta::Unit(n), l1_always_hit_(p->l1_always_hit), - cache_latency_(p->cache_latency), - dcache_l2cache_credit_available_(p->l1_l2cache_credit_available){ + cache_latency_(p->cache_latency) { in_lsu_lookup_req_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getInstsFromLSU_, MemoryAccessInfoPtr)); in_l2cache_ack_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getAckFromL2Cache_, bool)); + (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getAckFromL2Cache_, uint32_t)); in_l2cache_resp_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(DCache, getRespFromL2Cache_, InstPtr)); @@ -79,7 +78,7 @@ namespace olympia { memory_access_info_ptr->setCacheState(MemoryAccessInfo::CacheState::HIT); }else{ memory_access_info_ptr->setCacheState(MemoryAccessInfo::CacheState::MISS); - // Poll on dcache_l2cache_credit_available_ == true which means + // Poll on dcache_l2cache_credits_ > 0 which means // that L2Cache can accept requests from DCache. // Provide a corresponsing backpressure mechanism up the pipeline. if(!busy_) { @@ -87,7 +86,7 @@ namespace olympia { cache_pending_inst_ = memory_access_info_ptr; out_l2cache_req_.send(cache_pending_inst_->getInstPtr()); - // Set the dcache_l2cache_credit_available_ = false here. + // Set the --dcache_l2cache_credits_ here. } } out_lsu_lookup_ack_.send(memory_access_info_ptr); @@ -100,13 +99,13 @@ namespace olympia { busy_ = false; } - void DCache::getAckFromL2Cache_(const bool &ack) { + void DCache::getAckFromL2Cache_(const uint32_t &ack) { // When DCache sends the request to L2Cache for a miss, // This bool will be set to false, and Dcache should wait for ack from // L2Cache notifying DCache that there is space in it's dcache request buffer // // Set it to true so that the following misses from DCache can be sent out to L2Cache. - dcache_l2cache_credit_available_ = ack; + dcache_l2cache_credits_ = ack; } } diff --git a/core/DCache.hpp b/core/DCache.hpp index 618e9f95..d0c9698d 100644 --- a/core/DCache.hpp +++ b/core/DCache.hpp @@ -23,7 +23,6 @@ namespace olympia { PARAMETER(uint32_t, l1_associativity, 8, "DL1 associativity (power of 2)") PARAMETER(uint32_t, cache_latency, 1, "Assumed latency of the memory system") PARAMETER(bool, l1_always_hit, false, "DL1 will always hit") - PARAMETER(bool, l1_l2cache_credit_available, true, "Aloowing L1 cache to send the first miss request to L2Cache") }; static const char name[]; @@ -36,7 +35,7 @@ namespace olympia { void getInstsFromLSU_(const MemoryAccessInfoPtr &memory_access_info_ptr); - void getAckFromL2Cache_(const bool &ack); + void getAckFromL2Cache_(const uint32_t &ack); void getRespFromL2Cache_(const InstPtr &inst_ptr); @@ -49,7 +48,7 @@ namespace olympia { MemoryAccessInfoPtr cache_pending_inst_ = nullptr; // Credit bool for sending miss request to L2Cache - bool dcache_l2cache_credit_available_ = true; + uint32_t dcache_l2cache_credits_ = 0; //////////////////////////////////////////////////////////////////////////////// // Input Ports @@ -57,7 +56,7 @@ namespace olympia { sparta::DataInPort in_lsu_lookup_req_ {&unit_port_set_, "in_lsu_lookup_req", 0}; - sparta::DataInPort in_l2cache_ack_ + sparta::DataInPort in_l2cache_ack_ {&unit_port_set_, "in_l2cache_ack", 1}; sparta::DataInPort in_l2cache_resp_ @@ -76,7 +75,7 @@ namespace olympia { {&unit_port_set_, "out_lsu_lookup_req", 1}; sparta::DataOutPort out_l2cache_req_ - {&unit_port_set_, "out_l2cache_req"}; + {&unit_port_set_, "out_l2cache_req", 0}; //////////////////////////////////////////////////////////////////////////////// // Events diff --git a/mss/BIU.cpp b/mss/BIU.cpp index 47fcc1de..bc0b1933 100644 --- a/mss/BIU.cpp +++ b/mss/BIU.cpp @@ -25,7 +25,7 @@ namespace olympia_mss (CREATE_SPARTA_HANDLER_WITH_DATA(BIU, getAckFromMSS_, bool)); in_mss_ack_sync_.setPortDelay(static_cast(1)); - + sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(BIU, sendInitialCredits_)); ILOG("BIU construct: #" << node->getGroupIdx()); } @@ -34,6 +34,12 @@ namespace olympia_mss // Callbacks //////////////////////////////////////////////////////////////////////////////// + // Sending Initial credits to L2Cache + void BIU::sendInitialCredits_() { + out_biu_ack_.send(biu_req_queue_size_); + ILOG("Sending initial credits to L2Cache : " << biu_req_queue_size_); + } + // Receive new BIU request from L2Cache void BIU::receiveReqFromL2Cache_(const olympia::InstPtr & inst_ptr) { @@ -107,8 +113,10 @@ namespace olympia_mss } // Handle ack backto L2Cache - void BIU::handle_BIU_L2Cache_Ack_() { - out_biu_ack_.send(true); + void BIU::handle_BIU_L2Cache_Ack_() + { + uint32_t available_slots = biu_req_queue_size_ - biu_req_queue_.size(); + out_biu_ack_.send(available_slots); ILOG("BIU->L2Cache : Ack is sent."); } diff --git a/mss/BIU.hpp b/mss/BIU.hpp index 9c2a4ec8..f494ff64 100644 --- a/mss/BIU.hpp +++ b/mss/BIU.hpp @@ -67,7 +67,7 @@ namespace olympia_mss // Output Ports //////////////////////////////////////////////////////////////////////////////// - sparta::DataOutPort out_biu_ack_ + sparta::DataOutPort out_biu_ack_ {&unit_port_set_, "out_biu_ack"}; sparta::DataOutPort out_biu_resp_ @@ -127,6 +127,8 @@ namespace olympia_mss // Q: Does the argument list has to be "const DataType &" ? void getAckFromMSS_(const bool &); + // Sending initial credits to L2Cache + void sendInitialCredits_(); //////////////////////////////////////////////////////////////////////////////// // Regular Function/Subroutine Call @@ -134,7 +136,5 @@ namespace olympia_mss // Append BIU request queue void appendReqQueue_(const olympia::InstPtr &); - - }; } diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index bed783f0..8bc3ae60 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -79,8 +79,9 @@ namespace olympia_mss l2_lineSize_(p->l2_line_size), shiftBy_(log2(l2_lineSize_)), l2_always_hit_(p->l2_always_hit), - l2cache_biu_credit_available_(p->l2cache_biu_credit_available), - l2cache_latency_(p->l2cache_latency) { + l2cache_latency_(p->l2cache_latency), + is_icache_connected_(p->is_icache_connected), + is_dcache_connected_(p->is_dcache_connected) { // In Port Handler registration in_dcache_l2cache_req_.registerConsumerHandler @@ -93,7 +94,7 @@ namespace olympia_mss (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getRespFromBIU_, olympia::InstPtr)); in_biu_ack_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getAckFromBIU_, bool)); + (CREATE_SPARTA_HANDLER_WITH_DATA(L2Cache, getAckFromBIU_, uint32_t)); // Pipeline collection config l2cache_pipeline_.enableCollection(node); @@ -119,14 +120,26 @@ namespace olympia_mss (l2_associativity)); l2_cache_.reset(new olympia::CacheFuncModel( getContainer(), l2_size_kb, l2_lineSize_, *repl)); + sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(L2Cache, sendInitialCredits_)); ILOG("L2Cache construct: #" << node->getGroupIdx()); - ILOG("Starting BIU credits = " << std::boolalpha << l2cache_biu_credit_available_); } //////////////////////////////////////////////////////////////////////////////// // Callbacks //////////////////////////////////////////////////////////////////////////////// + // Sending Initial credits to I/D-Cache + void L2Cache::sendInitialCredits_() { + if (is_icache_connected_) { + out_l2cache_icache_ack_.send(icache_req_queue_size_); + ILOG("Sending initial credits to ICache : " << icache_req_queue_size_); + } + + if (is_dcache_connected_) { + out_l2cache_dcache_ack_.send(dcache_req_queue_size_); + ILOG("Sending initial credits to DCache : " << dcache_req_queue_size_); + } + } // Receive new L2Cache request from DCache void L2Cache::getReqFromDCache_(const olympia::InstPtr & inst_ptr) { @@ -159,25 +172,25 @@ namespace olympia_mss // Schedule BIU resp handling event only when: // Request queue is not empty - if (biu_resp_queue_.size() < biu_resp_queue_size_) { + if (biu_resp_queue_.size() <= biu_resp_queue_size_) { ev_handle_biu_l2cache_resp_.schedule(sparta::Clock::Cycle(0)); ++num_resps_from_biu_; } else { - ILOG("This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); + sparta_assert(false, "This request cannot be serviced right now, L2Cache input buffer from DCache is already full!"); } } // Handle BIU ack - void L2Cache::getAckFromBIU_(const bool & ack) { + void L2Cache::getAckFromBIU_(const uint32_t & ack) { // Update the biu credits - l2cache_biu_credit_available_ = true; + l2cache_biu_credits_ = ack; // Kickstart the pipeline issueing - ev_issue_req_.schedule(sparta::Clock::Cycle(0)); + ev_issue_req_.schedule(1); - ILOG("Ack received from BIU on the port : Current BIU credit availability = " << std::boolalpha << l2cache_biu_credit_available_); + ILOG("Ack received from BIU on the port : Current BIU credit available = " << l2cache_biu_credits_); } // Handle L2Cache request from DCache @@ -204,15 +217,15 @@ namespace olympia_mss // Handle L2Cache request to BIU void L2Cache::handle_L2Cache_BIU_Req_() { - if (l2cache_biu_credit_available_ && !biu_req_queue_.empty()) { + if (l2cache_biu_credits_ > 0 && !biu_req_queue_.empty()) { out_biu_req_.send(biu_req_queue_.front()); - l2cache_biu_credit_available_ = false; + --l2cache_biu_credits_; biu_req_queue_.erase(biu_req_queue_.begin()); ++num_reqs_to_biu_; - ILOG("L2Cache Request sent to BIU : Current BIU credit availability = " << std::boolalpha <DCache : Ack is sent."); @@ -230,7 +244,8 @@ namespace olympia_mss // Returning resp to ICache void L2Cache::handle_L2Cache_ICache_Ack_() { - out_l2cache_icache_ack_.send(true); + uint32_t available_slots = icache_req_queue_size_ - icache_req_queue_.size(); + out_l2cache_icache_ack_.send(available_slots); ++num_acks_to_icache_; ILOG("L2Cache->ICache : Ack is sent."); @@ -267,10 +282,12 @@ namespace olympia_mss // Function to check if the request to the given cacheline is present in the miss_pending_buffer_ auto getCacheLine = [this] (auto inst_ptr) { return inst_ptr->getRAdr() >> shiftBy_; }; - auto is_addr_present = [instPtr, getCacheLine] (auto reqPtr) - { return getCacheLine(reqPtr->getInstPtr()) == getCacheLine(instPtr); }; + auto const inst_cl = getCacheLine(instPtr); + + auto is_cl_present = [&instPtr, inst_cl, getCacheLine] (auto reqPtr) + { return getCacheLine(reqPtr->getInstPtr()) == inst_cl; }; - auto req = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_addr_present); + auto req = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_cl_present); // Set the original SrcUnit as the DestUnit because the resp will // now be forwarded from BIU to the original SrcUnit @@ -291,7 +308,7 @@ namespace olympia_mss // Check if this was the last occuring auto iter = req; ++iter; - auto next_req = std::find_if(iter, miss_pending_buffer_.end(), is_addr_present); + auto next_req = std::find_if(iter, miss_pending_buffer_.end(), is_cl_present); if (next_req == miss_pending_buffer_.end()) { @@ -316,7 +333,7 @@ namespace olympia_mss icache_req_queue_.erase(icache_req_queue_.begin()); // Send out the ack to ICache for credit management - ev_handle_l2cache_icache_ack_.schedule(sparta::Clock::Cycle(0)); + ev_handle_l2cache_icache_ack_.schedule(sparta::Clock::Cycle(1)); } else if (arbitration_winner == Channel::DCACHE) { @@ -331,19 +348,27 @@ namespace olympia_mss dcache_req_queue_.erase(dcache_req_queue_.begin()); // Send out the ack to DCache for credit management - ev_handle_l2cache_dcache_ack_.schedule(sparta::Clock::Cycle(0)); + ev_handle_l2cache_dcache_ack_.schedule(sparta::Clock::Cycle(1)); + } + else if (arbitration_winner == Channel::NO_ACCESS) { + // Schedule a ev_create_req_ event again to see if the the new request + // from any of the requestors can be put into pipeline_req_queue_ + ev_create_req_.schedule(sparta::Clock::Cycle(1)); + } + else { + sparta_assert(false, "Invalid arbitration winner, What Channel is picked up?"); } // Try to issue a request to l2cache_pipeline_ - ev_issue_req_.schedule(sparta::Clock::Cycle(0)); + ev_issue_req_.schedule(1); // Schedule a ev_create_req_ event again to see if the the new request // from any of the requestors can be put into pipeline_req_queue_ if ( !biu_resp_queue_.empty() || !icache_req_queue_.empty() - || !dcache_req_queue_.empty() ) - + || !dcache_req_queue_.empty() ) { ev_create_req_.schedule(sparta::Clock::Cycle(1)); + } } void L2Cache::issue_Req_() { @@ -359,8 +384,9 @@ namespace olympia_mss } // Checking for the queue empty again before scheduling the event for the next clock cycle - if (!pipeline_req_queue_.empty()) - ev_issue_req_.schedule(sparta::Clock::Cycle(1)); + if (!pipeline_req_queue_.empty()) { + ev_issue_req_.schedule(1); + } } // Pipeline Stage CACHE_LOOKUP @@ -395,7 +421,7 @@ namespace olympia_mss const auto req = l2cache_pipeline_[stages_.HIT_MISS_HANDLING]; ILOG("Pipeline stage HIT_MISS_HANDLING : " << req->getInstPtr()); - inFlight_reqs_--; + --inFlight_reqs_; // This request to access cache came from DCache or ICache to do a cache lookup. // It was either a miss or hit based on cacheLookup_() in the previous stage of the pipeline @@ -421,19 +447,22 @@ namespace olympia_mss miss_pending_buffer_.push_back(req); } else { - sparta_assert("No space in miss_pending_buffer_! Why did the frontend issue push the request onto l2cache_pipeline_?"); + sparta_assert(false, "No space in miss_pending_buffer_! Why did the frontend issue push the request onto l2cache_pipeline_?"); } // Function to check if the request to the given cacheline is present in the miss_pending_buffer_ auto getCacheLine = [this] (auto reqPtr) { return reqPtr->getInstPtr()->getRAdr() >> shiftBy_; }; - auto is_addr_present = [req, getCacheLine] (auto reqPtr) - { return (req != reqPtr && getCacheLine(reqPtr) == getCacheLine(req));}; + const auto req_cl = getCacheLine(req); + + auto is_cl_present = [&req, req_cl, getCacheLine] (auto reqPtr) + { return (req != reqPtr && getCacheLine(reqPtr) == req_cl);}; // Send out the request to BIU for a cache MISS if it is not sent out already - auto reqIter = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_addr_present); + auto reqIter = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_cl_present); - if (reqIter == miss_pending_buffer_.end()) + if (reqIter == miss_pending_buffer_.end()) { sendOutReq_(req->getDestUnit(), req->getInstPtr()); + } } } @@ -496,14 +525,8 @@ namespace olympia_mss sparta_assert(biu_req_queue_.size() <= biu_req_queue_size_ ,"BIU req queue overflows!"); // Push new request to the biu_req_queue_ if biu credits are available with the L2Cache - if (biu_req_queue_.size() < biu_req_queue_size_) { - biu_req_queue_.emplace_back(inst_ptr); - - ev_handle_l2cache_biu_req_.schedule(sparta::Clock::Cycle(0)); - } - else { - sparta_assert("No space in biu_req_queue_! Why did the frontend issue push the request onto l2cache_pipeline_?"); - } + biu_req_queue_.emplace_back(inst_ptr); + ev_handle_l2cache_biu_req_.schedule(sparta::Clock::Cycle(0)); ILOG("Append L2Cache->BIU req queue"); } @@ -519,7 +542,7 @@ namespace olympia_mss appendICacheRespQueue_(instPtr); } else { - sparta_assert("Resp is being sent to a Unit that is not valid"); + sparta_assert(false, "Resp is being sent to a Unit that is not valid"); } } @@ -530,7 +553,7 @@ namespace olympia_mss appendBIUReqQueue_(instPtr); } else { - sparta_assert("Request is being sent to a Unit that is not valid"); + sparta_assert(false, "Request is being sent to a Unit that is not valid"); } } @@ -547,40 +570,44 @@ namespace olympia_mss if (pipeline_req_queue_.numFree() == 0) { - // pipeline_req_queue_ is full - return Channel::NO_ACCESS; + // pipeline_req_queue_ is full, try again next cycle + winner = Channel::NO_ACCESS; } - // P0 priority to sevice the pending request in the buffer - if (!biu_resp_queue_.empty()) { + else if (!biu_resp_queue_.empty()) { + winner = Channel::BIU; ILOG("Arbitration winner - BIU"); - - return winner; } - // RoundRobin for P1 Priority - while (true) { - - if (channel_select_ == Channel::ICACHE) { - channel_select_ = Channel::DCACHE; - if (!icache_req_queue_.empty()) { - winner = Channel::ICACHE; - ILOG("Arbitration winner - ICache"); - - return winner; - } + else if (channel_select_ == Channel::ICACHE) { + // Set it up for the following arbitration request + channel_select_ = Channel::DCACHE; + winner = Channel::NO_ACCESS; + + if (!icache_req_queue_.empty()) { + + winner = Channel::ICACHE; + ILOG("Arbitration winner - ICache"); } - else if (channel_select_ == Channel::DCACHE) { - channel_select_ = Channel::ICACHE; - if (!dcache_req_queue_.empty()) { - winner = Channel::DCACHE; - ILOG("Arbitration winner - DCache"); + } + else if (channel_select_ == Channel::DCACHE) { + + // Set it up for the following arbitration request + channel_select_ = Channel::ICACHE; + winner = Channel::NO_ACCESS; - return winner; - } + if (!dcache_req_queue_.empty()) { + + winner = Channel::DCACHE; + ILOG("Arbitration winner - DCache"); } } + else { + sparta_assert(false, "Illegal else : Why is channel_select_ incorrectly set?"); + } + + return winner; } // Cache lookup for a HIT or MISS on a given request diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index 531d046d..f14ab3ab 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -12,6 +12,7 @@ #include "sparta/ports/DataPort.hpp" #include "sparta/events/EventSet.hpp" #include "sparta/events/UniqueEvent.hpp" +#include "sparta/events/SingleCycleUniqueEvent.hpp" #include "sparta/simulation/Unit.hpp" #include "sparta/simulation/ParameterSet.hpp" #include "sparta/simulation/TreeNode.hpp" @@ -56,8 +57,9 @@ namespace olympia_mss PARAMETER(uint32_t, l2_associativity, 16, "L2 associativity (power of 2)") PARAMETER(bool, l2_always_hit, false, "L2 will always hit") - PARAMETER(bool, l2cache_biu_credit_available, true, "Starting credit availability for BIU") - PARAMETER(uint32_t, l2cache_latency, 7, "Cache Lookup HIT latency") + PARAMETER(uint32_t, l2cache_latency, 10, "Cache Lookup HIT latency") + PARAMETER(bool, is_icache_connected, false, "Does this unit have ICache connected to it") + PARAMETER(bool, is_dcache_connected, true, "Does this unit have DCache connected to it") }; // Constructor for L2Cache @@ -107,7 +109,7 @@ namespace olympia_mss sparta::DataInPort in_biu_resp_ {&unit_port_set_, "in_biu_l2cache_resp", 1}; - sparta::DataInPort in_biu_ack_ + sparta::DataInPort in_biu_ack_ {&unit_port_set_, "in_biu_l2cache_ack", 1}; @@ -124,10 +126,10 @@ namespace olympia_mss sparta::DataOutPort out_l2cache_dcache_resp_ {&unit_port_set_, "out_l2cache_dcache_resp"}; - sparta::DataOutPort out_l2cache_icache_ack_ + sparta::DataOutPort out_l2cache_icache_ack_ {&unit_port_set_, "out_l2cache_icache_ack"}; - sparta::DataOutPort out_l2cache_dcache_ack_ + sparta::DataOutPort out_l2cache_dcache_ack_ {&unit_port_set_, "out_l2cache_dcache_ack"}; @@ -215,10 +217,13 @@ namespace olympia_mss const bool l2_always_hit_; // Local state variables - bool l2cache_biu_credit_available_ = true; + uint32_t l2cache_biu_credits_ = 0; Channel channel_select_ = Channel::ICACHE; const uint32_t l2cache_latency_; + const bool is_icache_connected_ = false; + const bool is_dcache_connected_ = false; + //////////////////////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////////////////////// @@ -256,11 +261,11 @@ namespace olympia_mss {&unit_event_set_, "ev_handle_l2cache_dcache_ack", CREATE_SPARTA_HANDLER(L2Cache, handle_L2Cache_DCache_Ack_)}; // Event to create request for pipeline and feed it to the pipeline_req_queue_ - sparta::UniqueEvent<> ev_create_req_ + sparta::UniqueEvent ev_create_req_ {&unit_event_set_, "create_req", CREATE_SPARTA_HANDLER(L2Cache, create_Req_)}; // Event to issue request to pipeline - sparta::UniqueEvent<> ev_issue_req_ + sparta::UniqueEvent ev_issue_req_ {&unit_event_set_, "issue_req", CREATE_SPARTA_HANDLER(L2Cache, issue_Req_)}; //////////////////////////////////////////////////////////////////////////////// @@ -277,7 +282,7 @@ namespace olympia_mss void getRespFromBIU_(const olympia::InstPtr &); // Receive BIU ack Response - void getAckFromBIU_(const bool &); + void getAckFromBIU_(const uint32_t &); // Handle L2Cache request from DCache void handle_DCache_L2Cache_Req_(); @@ -318,6 +323,8 @@ namespace olympia_mss // Stage 2 void handleCacheAccessResult_(); + // Sending Initial credits to I/D-Cache + void sendInitialCredits_(); //////////////////////////////////////////////////////////////////////////////// // Regular Function/Subroutine Call diff --git a/test/core/l2cache/BIUSinkUnit.hpp b/test/core/l2cache/BIUSinkUnit.hpp index 8a996a0f..ed72857f 100644 --- a/test/core/l2cache/BIUSinkUnit.hpp +++ b/test/core/l2cache/BIUSinkUnit.hpp @@ -35,19 +35,31 @@ namespace l2cache_test in_biu_req_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(BIUSinkUnit, sinkInst_, olympia::InstPtr)); + + sparta::StartupEvent(n, CREATE_SPARTA_HANDLER(BIUSinkUnit, sendInitialCredits_)); } private: + + // Sending Initial credits to L2Cache + void sendInitialCredits_() { + uint32_t biu_req_queue_size_ = 32; + out_biu_ack_.send(biu_req_queue_size_); + ILOG("Sending initial credits to L2Cache : " << biu_req_queue_size_); + } + void sinkInst_(const olympia::InstPtr & instPtr) { ILOG("Instruction: '" << instPtr << "' sinked"); - out_biu_ack_.send(true, sink_latency_); + uint32_t biu_req_queue_size_ = 32; + + out_biu_ack_.send(biu_req_queue_size_, sink_latency_); out_biu_resp_.send(instPtr, 2*sink_latency_); } sparta::DataInPort in_biu_req_ {&unit_port_set_, "in_biu_req", sparta::SchedulingPhase::Tick, 1}; sparta::DataOutPort out_biu_resp_ {&unit_port_set_, "out_biu_resp"}; - sparta::DataOutPort out_biu_ack_ {&unit_port_set_, "out_biu_ack"}; + sparta::DataOutPort out_biu_ack_ {&unit_port_set_, "out_biu_ack"}; std::string purpose_; sparta::Clock::Cycle sink_latency_; diff --git a/test/core/l2cache/L2SourceUnit.hpp b/test/core/l2cache/L2SourceUnit.hpp index 86c93be1..f60f7ec1 100644 --- a/test/core/l2cache/L2SourceUnit.hpp +++ b/test/core/l2cache/L2SourceUnit.hpp @@ -43,7 +43,7 @@ namespace l2cache_test in_source_resp_.registerConsumerHandler (CREATE_SPARTA_HANDLER_WITH_DATA(L2SourceUnit, ReceiveInst_, olympia::InstPtr)); in_source_ack_.registerConsumerHandler - (CREATE_SPARTA_HANDLER_WITH_DATA(L2SourceUnit, ReceiveAck_, bool)); + (CREATE_SPARTA_HANDLER_WITH_DATA(L2SourceUnit, ReceiveAck_, uint32_t)); if(params->input_file != "") { inst_generator_ = olympia::InstGenerator::createGenerator(mavis_facade_, params->input_file, false); @@ -94,18 +94,18 @@ namespace l2cache_test ILOG("Instruction: '" << instPtr << "' Received"); } - void ReceiveAck_(const bool & ack) { + void ReceiveAck_(const uint32_t & ack) { pending_acks_--; ILOG("Ack: '" << ack << "' Received"); } sparta::DataInPort in_source_resp_ {&unit_port_set_, "in_source_resp", sparta::SchedulingPhase::Tick, 1}; - sparta::DataInPort in_source_ack_ {&unit_port_set_, "in_source_ack"}; + sparta::DataInPort in_source_ack_ {&unit_port_set_, "in_source_ack"}; sparta::DataOutPort out_source_req_ {&unit_port_set_, "out_source_req"}; - uint32_t pending_acks_ = 0; + uint32_t pending_acks_ = 1; uint32_t pending_reqs_ = 0; uint32_t unique_id_ = 0; diff --git a/test/core/l2cache/expected_output/hit_case.out.EXPECTED b/test/core/l2cache/expected_output/hit_case.out.EXPECTED index 630e389e..abf6f485 100644 --- a/test/core/l2cache/expected_output/hit_case.out.EXPECTED +++ b/test/core/l2cache/expected_output/hit_case.out.EXPECTED @@ -3,59 +3,64 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Thursday Thu Nov 16 04:52:05 2023 -#Elapsed: 0.085713s +#Start: Friday Fri Nov 17 11:05:39 2023 +#Elapsed: 0.074727s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 -{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = true +{0000000000 00000000 top.l2cache info} sendInitialCredits_: Sending initial credits to ICache : 8 +{0000000000 00000000 top.l2cache info} sendInitialCredits_: Sending initial credits to DCache : 8 +{0000000000 00000000 top.biu info} sendInitialCredits_: Sending initial credits to L2Cache : 32 +{0000000000 00000000 top.icache info} ReceiveAck_: Ack: '8' Received +{0000000000 00000000 top.dcache info} ReceiveAck_: Ack: '8' Received {0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000000 00000000 top.icache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000001 00000001 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit available = 32 {0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port {0000000001 00000001 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! {0000000001 00000001 top.l2cache info} getReqFromICache_: Request received from ICache on the port {0000000001 00000001 top.l2cache info} appendICacheReqQueue_: Append ICache->L2Cache request queue! {0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache {0000000001 00000001 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! -{0000000001 00000001 top.icache info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. -{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE +{0000000002 00000002 top.icache info} ReceiveAck_: Ack: '8' Received +{0000000002 00000002 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. +{0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! -{0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received -{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. -{0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE -{0000000010 00000010 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000010 00000010 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000003 00000003 top.dcache info} ReceiveAck_: Ack: '8' Received +{0000000003 00000003 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. +{0000000003 00000003 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE {0000000011 00000011 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000011 00000011 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000011 00000011 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue -{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credit availability = false -{0000000012 00000012 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000012 00000012 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000012 00000012 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit availability = true -{0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port -{0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! -{0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : ICACHE -{0000000033 00000033 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000012 00000012 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue +{0000000012 00000012 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credit available = 31 +{0000000013 00000013 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000013 00000013 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000013 00000013 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000024 00000024 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit available = 32 +{0000000034 00000034 top.l2cache info} getRespFromBIU_: Response received from BIU on the port +{0000000034 00000034 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! {0000000034 00000034 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE -{0000000034 00000034 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU -{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000042 00000042 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Reload Complete: phyAddr=0xdeadbeef -{0000000043 00000043 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000043 00000043 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000043 00000043 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000043 00000043 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! -{0000000043 00000043 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! -{0000000044 00000044 top.icache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received -{0000000044 00000044 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000044 00000044 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! -{0000000044 00000044 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! -{0000000045 00000045 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : ICACHE +{0000000035 00000035 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000035 00000035 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000035 00000035 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE +{0000000036 00000036 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000044 00000044 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000044 00000044 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000044 00000044 top.l2cache info} handleCacheAccessRequest_: Reload Complete: phyAddr=0xdeadbeef +{0000000045 00000045 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000045 00000045 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000045 00000045 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000045 00000045 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! +{0000000045 00000045 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! +{0000000046 00000046 top.icache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000046 00000046 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000046 00000046 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! +{0000000046 00000046 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! +{0000000047 00000047 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received {0000000050 00000050 top.dcache info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested {0000000050 00000050 top.icache info} req_inst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Requested {0000000051 00000051 top.l2cache info} getReqFromDCache_: Request received from DCache on the port @@ -64,23 +69,23 @@ {0000000051 00000051 top.l2cache info} appendICacheReqQueue_: Append ICache->L2Cache request queue! {0000000051 00000051 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache {0000000051 00000051 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! -{0000000051 00000051 top.icache info} ReceiveAck_: Ack: '1' Received -{0000000051 00000051 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. -{0000000051 00000051 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE +{0000000052 00000052 top.icache info} ReceiveAck_: Ack: '8' Received +{0000000052 00000052 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. +{0000000052 00000052 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000052 00000052 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000052 00000052 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! -{0000000052 00000052 top.dcache info} ReceiveAck_: Ack: '1' Received -{0000000052 00000052 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. -{0000000052 00000052 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE -{0000000060 00000060 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000060 00000060 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000053 00000053 top.dcache info} ReceiveAck_: Ack: '8' Received +{0000000053 00000053 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. +{0000000053 00000053 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE {0000000061 00000061 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' {0000000061 00000061 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000061 00000061 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000061 00000061 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! -{0000000061 00000061 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! -{0000000062 00000062 top.icache info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000062 00000062 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000062 00000062 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef {0000000062 00000062 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' -{0000000062 00000062 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! -{0000000062 00000062 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! -{0000000063 00000063 top.dcache info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000062 00000062 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! +{0000000062 00000062 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! +{0000000063 00000063 top.icache info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received +{0000000063 00000063 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' +{0000000063 00000063 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! +{0000000063 00000063 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! +{0000000064 00000064 top.dcache info} ReceiveInst_: Instruction: 'uid: 1 FETCHED 0 pid: 2 'lw 5,3,4' ' Received diff --git a/test/core/l2cache/expected_output/single_access.out.EXPECTED b/test/core/l2cache/expected_output/single_access.out.EXPECTED index 19ad6c54..0a296dc2 100644 --- a/test/core/l2cache/expected_output/single_access.out.EXPECTED +++ b/test/core/l2cache/expected_output/single_access.out.EXPECTED @@ -3,56 +3,61 @@ #Exe: #SimulatorVersion: #Repro: -#Start: Thursday Thu Nov 16 04:45:10 2023 -#Elapsed: 0.080861s +#Start: Friday Fri Nov 17 11:01:07 2023 +#Elapsed: 0.082742s {0000000000 00000000 top.l2cache info} L2Cache: L2Cache construct: #4294967295 -{0000000000 00000000 top.l2cache info} L2Cache: Starting BIU credits = true +{0000000000 00000000 top.l2cache info} sendInitialCredits_: Sending initial credits to ICache : 8 +{0000000000 00000000 top.l2cache info} sendInitialCredits_: Sending initial credits to DCache : 8 +{0000000000 00000000 top.biu info} sendInitialCredits_: Sending initial credits to L2Cache : 32 +{0000000000 00000000 top.icache info} ReceiveAck_: Ack: '8' Received +{0000000000 00000000 top.dcache info} ReceiveAck_: Ack: '8' Received {0000000000 00000000 top.dcache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested {0000000000 00000000 top.icache info} req_inst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Requested +{0000000001 00000001 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit available = 32 {0000000001 00000001 top.l2cache info} getReqFromDCache_: Request received from DCache on the port {0000000001 00000001 top.l2cache info} appendDCacheReqQueue_: Append DCache->L2Cache request queue! {0000000001 00000001 top.l2cache info} getReqFromICache_: Request received from ICache on the port {0000000001 00000001 top.l2cache info} appendICacheReqQueue_: Append ICache->L2Cache request queue! {0000000001 00000001 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - ICache {0000000001 00000001 top.l2cache info} create_Req_: ICache request is sent to Pipeline_req_Q! -{0000000001 00000001 top.icache info} ReceiveAck_: Ack: '1' Received -{0000000001 00000001 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. -{0000000001 00000001 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE +{0000000002 00000002 top.icache info} ReceiveAck_: Ack: '8' Received +{0000000002 00000002 top.l2cache info} handle_L2Cache_ICache_Ack_: L2Cache->ICache : Ack is sent. +{0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : ICACHE {0000000002 00000002 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - DCache {0000000002 00000002 top.l2cache info} create_Req_: DCache request is sent to Pipeline_req_Q! -{0000000002 00000002 top.dcache info} ReceiveAck_: Ack: '1' Received -{0000000002 00000002 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. -{0000000002 00000002 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE -{0000000010 00000010 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000010 00000010 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000003 00000003 top.dcache info} ReceiveAck_: Ack: '8' Received +{0000000003 00000003 top.l2cache info} handle_L2Cache_DCache_Ack_: L2Cache->DCache : Ack is sent. +{0000000003 00000003 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : DCACHE {0000000011 00000011 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000011 00000011 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000011 00000011 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000011 00000011 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue -{0000000011 00000011 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credit availability = false -{0000000012 00000012 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000012 00000012 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000012 00000012 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' {0000000012 00000012 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ -{0000000023 00000023 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit availability = true -{0000000033 00000033 top.l2cache info} getRespFromBIU_: Response received from BIU on the port -{0000000033 00000033 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! -{0000000033 00000033 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000033 00000033 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : ICACHE -{0000000033 00000033 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000012 00000012 top.l2cache info} appendBIUReqQueue_: Append L2Cache->BIU req queue +{0000000012 00000012 top.l2cache info} handle_L2Cache_BIU_Req_: L2Cache Request sent to BIU : Current BIU credit available = 31 +{0000000013 00000013 top.biu info} sinkInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' sinked +{0000000013 00000013 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000013 00000013 top.l2cache info} handleCacheAccessResult_: Storing the CACHE MISS in miss_pending_buffer_ +{0000000024 00000024 top.l2cache info} getAckFromBIU_: Ack received from BIU on the port : Current BIU credit available = 32 +{0000000034 00000034 top.l2cache info} getRespFromBIU_: Response received from BIU on the port +{0000000034 00000034 top.l2cache info} appendBIURespQueue_: Append BIU->L2Cache resp queue! {0000000034 00000034 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU -{0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE -{0000000034 00000034 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU -{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000042 00000042 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef -{0000000042 00000042 top.l2cache info} handleCacheAccessRequest_: Reload Complete: phyAddr=0xdeadbeef -{0000000043 00000043 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000043 00000043 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef -{0000000043 00000043 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000043 00000043 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! -{0000000043 00000043 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! -{0000000044 00000044 top.icache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received -{0000000044 00000044 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' -{0000000044 00000044 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! -{0000000044 00000044 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! -{0000000045 00000045 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000034 00000034 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : ICACHE +{0000000035 00000035 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000035 00000035 top.l2cache info} arbitrateL2CacheAccessReqs_: Arbitration winner - BIU +{0000000035 00000035 top.l2cache info} create_Req_: Request found in miss_pending_buffer_ with SrcUnit : DCACHE +{0000000036 00000036 top.l2cache info} issue_Req_: Request is sent to Pipeline! SrcUnit : BIU +{0000000044 00000044 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000044 00000044 top.l2cache info} cacheLookup_: Cache MISS: phyAddr=0xdeadbeef +{0000000044 00000044 top.l2cache info} handleCacheAccessRequest_: Reload Complete: phyAddr=0xdeadbeef +{0000000045 00000045 top.l2cache info} handleCacheAccessRequest_: Pipeline stage CACHE_LOOKUP : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000045 00000045 top.l2cache info} cacheLookup_: Cache HIT: phyAddr=0xdeadbeef +{0000000045 00000045 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000045 00000045 top.l2cache info} appendICacheRespQueue_: Append L2Cache->ICache resp queue! +{0000000045 00000045 top.l2cache info} handle_L2Cache_ICache_Resp_: L2Cache Resp is sent to ICache! +{0000000046 00000046 top.icache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received +{0000000046 00000046 top.l2cache info} handleCacheAccessResult_: Pipeline stage HIT_MISS_HANDLING : uid: 0 FETCHED 0 pid: 1 'sw 3' +{0000000046 00000046 top.l2cache info} appendDCacheRespQueue_: Append L2Cache->DCache resp queue! +{0000000046 00000046 top.l2cache info} handle_L2Cache_DCache_Resp_: L2Cache Resp is sent to DCache! +{0000000047 00000047 top.dcache info} ReceiveInst_: Instruction: 'uid: 0 FETCHED 0 pid: 1 'sw 3' ' Received diff --git a/test/core/l2cache/test_arches/2_src_L2Cache.yaml b/test/core/l2cache/test_arches/2_src_L2Cache.yaml index eb2196b8..0282ccd4 100644 --- a/test/core/l2cache/test_arches/2_src_L2Cache.yaml +++ b/test/core/l2cache/test_arches/2_src_L2Cache.yaml @@ -20,8 +20,9 @@ top: l2_size_kb : 512 l2_associativity : 16 l2_always_hit : false - l2cache_biu_credit_available : true l2cache_latency : 10 + is_icache_connected : true + is_dcache_connected : true biu: params: sink_latency: 10 From 3da074d85f74fb2e1467aa987a2b937288b7f007 Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Tue, 21 Nov 2023 06:44:13 -0600 Subject: [PATCH 10/12] Unit : L2Cache - using SSP instead of std::shared_ptr --- mss/L2Cache.cpp | 12 +++++++++--- mss/L2Cache.hpp | 10 +++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index 8bc3ae60..f071612f 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -5,6 +5,8 @@ #include "L2Cache.hpp" +#include "OlympiaAllocators.hpp" + namespace olympia_mss { const char L2Cache::name[] = "l2cache"; @@ -81,7 +83,9 @@ namespace olympia_mss l2_always_hit_(p->l2_always_hit), l2cache_latency_(p->l2cache_latency), is_icache_connected_(p->is_icache_connected), - is_dcache_connected_(p->is_dcache_connected) { + is_dcache_connected_(p->is_dcache_connected), + memory_access_allocator_(sparta::notNull(olympia::OlympiaAllocators::getOlympiaAllocators(node))-> + memory_access_allocator) { // In Port Handler registration in_dcache_l2cache_req_.registerConsumerHandler @@ -322,7 +326,8 @@ namespace olympia_mss } else if (arbitration_winner == Channel::ICACHE) { - const auto &reqPtr = std::make_shared(icache_req_queue_.front()); + const auto &reqPtr = sparta::allocate_sparta_shared_pointer(memory_access_allocator_, + icache_req_queue_.front()); reqPtr->setSrcUnit(L2ArchUnit::ICACHE); reqPtr->setDestUnit(L2ArchUnit::ICACHE); @@ -337,7 +342,8 @@ namespace olympia_mss } else if (arbitration_winner == Channel::DCACHE) { - const auto &reqPtr = std::make_shared(dcache_req_queue_.front()); + const auto &reqPtr = sparta::allocate_sparta_shared_pointer(memory_access_allocator_, + dcache_req_queue_.front()); reqPtr->setSrcUnit(L2ArchUnit::DCACHE); reqPtr->setDestUnit(L2ArchUnit::DCACHE); diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index f14ab3ab..df440cfb 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -190,9 +190,7 @@ namespace olympia_mss const uint32_t NO_ACCESS = 0; }; - // Skipping the use of SpartaSharedPointer due to allocator bug - // Instead using std::shared_ptr. That works cleanly. - using L2MemoryAccessInfoPtr = std::shared_ptr; + using L2MemoryAccessInfoPtr = sparta::SpartaSharedPointer; using L2ArchUnit = olympia::MemoryAccessInfo::ArchUnit; using L2CacheState = olympia::MemoryAccessInfo::CacheState; using L2CachePipeline = sparta::Pipeline; @@ -204,7 +202,7 @@ namespace olympia_mss const uint32_t pipeline_req_queue_size_; uint32_t inFlight_reqs_ = 0; - sparta::Buffer> miss_pending_buffer_; + sparta::Buffer miss_pending_buffer_; const uint32_t miss_pending_buffer_size_; @@ -224,6 +222,8 @@ namespace olympia_mss const bool is_icache_connected_ = false; const bool is_dcache_connected_ = false; + // allocator for this object type + sparta::SpartaSharedPointerAllocator & memory_access_allocator_; //////////////////////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////////////////////// @@ -358,7 +358,7 @@ namespace olympia_mss Channel arbitrateL2CacheAccessReqs_(); // Cache lookup for a HIT or MISS on a given request - L2CacheState cacheLookup_(std::shared_ptr); + L2CacheState cacheLookup_(sparta::SpartaSharedPointer); // Allocating the cacheline in the L2 bbased on return from BIU/L3 void reloadCache_(uint64_t); From d99f35b728e3bb539a75fe867d06f355e4edcaf3 Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Tue, 21 Nov 2023 11:30:53 -0600 Subject: [PATCH 11/12] Unit : L2Cache - linking misses to the same cacheline through next_req_ variable --- core/MemoryAccessInfo.hpp | 16 +++++++++++++--- mss/L2Cache.cpp | 13 +++++++++---- mss/L2Cache.hpp | 9 ++++----- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/core/MemoryAccessInfo.hpp b/core/MemoryAccessInfo.hpp index 4debf30f..f2416a09 100644 --- a/core/MemoryAccessInfo.hpp +++ b/core/MemoryAccessInfo.hpp @@ -13,6 +13,11 @@ namespace olympia { class MemoryAccessInfoPairDef; + class MemoryAccessInfo; + + using MemoryAccessInfoPtr = sparta::SpartaSharedPointer; + using MemoryAccessInfoAllocator = sparta::SpartaSharedPointerAllocator; + class MemoryAccessInfo { public: @@ -88,6 +93,9 @@ namespace olympia { void setDestUnit(const ArchUnit & dest_unit) { dest_ = dest_unit; } const ArchUnit & getDestUnit() const { return dest_; } + void setNextReq(const MemoryAccessInfoPtr & nextReq) { next_req_ = nextReq; } + const MemoryAccessInfoPtr & getNextReq() { return next_req_; } + MMUState getMMUState() const { return mmu_access_state_; } @@ -125,6 +133,11 @@ namespace olympia { ArchUnit src_ = ArchUnit::NO_ACCESS; ArchUnit dest_ = ArchUnit::NO_ACCESS; + // Pointer to next request for DEBUG/TRACK + // (Note : Currently used only to track request with same cacheline in L2Cache + // Not for functional/performance purpose) + MemoryAccessInfoPtr next_req_ = nullptr; + // Scoreboards using ScoreboardViews = std::array, core_types::N_REGFILES>; ScoreboardViews scoreboard_views_; @@ -153,7 +166,4 @@ namespace olympia { SPARTA_ADDPAIR("cache", &MemoryAccessInfo::getCacheState), SPARTA_FLATTEN(&MemoryAccessInfo::getInstPtr)) }; - - using MemoryAccessInfoPtr = sparta::SpartaSharedPointer; - using MemoryAccessInfoAllocator = sparta::SpartaSharedPointerAllocator; }; diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index f071612f..7925099f 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -461,14 +461,19 @@ namespace olympia_mss const auto req_cl = getCacheLine(req); auto is_cl_present = [&req, req_cl, getCacheLine] (auto reqPtr) - { return (req != reqPtr && getCacheLine(reqPtr) == req_cl);}; + { return (req != reqPtr && getCacheLine(reqPtr) == req_cl); }; // Send out the request to BIU for a cache MISS if it is not sent out already - auto reqIter = std::find_if(miss_pending_buffer_.begin(), miss_pending_buffer_.end(), is_cl_present); + auto reqIter = std::find_if(miss_pending_buffer_.rbegin(), miss_pending_buffer_.rend(), is_cl_present); - if (reqIter == miss_pending_buffer_.end()) { + if (reqIter == miss_pending_buffer_.rend()) { sendOutReq_(req->getDestUnit(), req->getInstPtr()); } + else { + // Found a request to same cacheLine. + // Link the current request to the last pending request + (*reqIter)->setNextReq(req); + } } } @@ -617,7 +622,7 @@ namespace olympia_mss } // Cache lookup for a HIT or MISS on a given request - L2Cache::L2CacheState L2Cache::cacheLookup_(L2MemoryAccessInfoPtr mem_access_info_ptr) { + L2Cache::L2CacheState L2Cache::cacheLookup_(olympia::MemoryAccessInfoPtr mem_access_info_ptr) { const olympia::InstPtr & inst_ptr = mem_access_info_ptr->getInstPtr(); uint64_t phyAddr = inst_ptr->getRAdr(); diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index df440cfb..275fd12c 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -190,19 +190,18 @@ namespace olympia_mss const uint32_t NO_ACCESS = 0; }; - using L2MemoryAccessInfoPtr = sparta::SpartaSharedPointer; using L2ArchUnit = olympia::MemoryAccessInfo::ArchUnit; using L2CacheState = olympia::MemoryAccessInfo::CacheState; - using L2CachePipeline = sparta::Pipeline; + using L2CachePipeline = sparta::Pipeline; PipelineStages stages_; L2CachePipeline l2cache_pipeline_; - sparta::Queue pipeline_req_queue_; + sparta::Queue pipeline_req_queue_; const uint32_t pipeline_req_queue_size_; uint32_t inFlight_reqs_ = 0; - sparta::Buffer miss_pending_buffer_; + sparta::Buffer miss_pending_buffer_; const uint32_t miss_pending_buffer_size_; @@ -223,7 +222,7 @@ namespace olympia_mss const bool is_dcache_connected_ = false; // allocator for this object type - sparta::SpartaSharedPointerAllocator & memory_access_allocator_; + olympia::MemoryAccessInfoAllocator & memory_access_allocator_; //////////////////////////////////////////////////////////////////////////////// // Event Handlers //////////////////////////////////////////////////////////////////////////////// From 44345e9dc1fd216dd096a375c26d56dac813415a Mon Sep 17 00:00:00 2001 From: Kunal-Buch Date: Mon, 4 Dec 2023 15:41:12 -0600 Subject: [PATCH 12/12] Unit : L2Cache - removing unsed variable --- mss/L2Cache.cpp | 1 - mss/L2Cache.hpp | 1 - 2 files changed, 2 deletions(-) diff --git a/mss/L2Cache.cpp b/mss/L2Cache.cpp index 7925099f..f5cb3efe 100644 --- a/mss/L2Cache.cpp +++ b/mss/L2Cache.cpp @@ -72,7 +72,6 @@ namespace olympia_mss pipeline_req_queue_("Pipeline_Request_Queue", p->pipeline_req_queue_size, node->getClock()), - pipeline_req_queue_size_(p->pipeline_req_queue_size), miss_pending_buffer_("Miss_Pending_Buffer", p->miss_pending_buffer_size, node->getClock(), diff --git a/mss/L2Cache.hpp b/mss/L2Cache.hpp index 275fd12c..9a999ebb 100644 --- a/mss/L2Cache.hpp +++ b/mss/L2Cache.hpp @@ -198,7 +198,6 @@ namespace olympia_mss L2CachePipeline l2cache_pipeline_; sparta::Queue pipeline_req_queue_; - const uint32_t pipeline_req_queue_size_; uint32_t inFlight_reqs_ = 0; sparta::Buffer miss_pending_buffer_;