diff --git a/src/include/simeng/pipeline/LoadStoreQueue.hh b/src/include/simeng/pipeline/LoadStoreQueue.hh index a1cad904ee..d51aec5b9a 100644 --- a/src/include/simeng/pipeline/LoadStoreQueue.hh +++ b/src/include/simeng/pipeline/LoadStoreQueue.hh @@ -35,6 +35,7 @@ class LoadStoreQueue { unsigned int maxCombinedSpace, MemoryInterface& memory, span>> completionSlots, std::function, span)> forwardOperands, + std::function&)> raiseException, bool exclusive = false, uint16_t loadBandwidth = UINT16_MAX, uint16_t storeBandwidth = UINT16_MAX, uint16_t permittedRequests = UINT16_MAX, @@ -49,6 +50,7 @@ class LoadStoreQueue { MemoryInterface& memory, span>> completionSlots, std::function, span)> forwardOperands, + std::function&)> raiseException, bool exclusive = false, uint16_t loadBandwidth = UINT16_MAX, uint16_t storeBandwidth = UINT16_MAX, uint16_t permittedRequests = UINT16_MAX, @@ -119,6 +121,9 @@ class LoadStoreQueue { /** A function handler to call to forward the results of a completed load. */ std::function, span)> forwardOperands_; + /** A function handle called upon exception generation. */ + std::function&)> raiseException_; + /** The maximum number of loads that can be in-flight. Undefined if this * is a combined queue. */ unsigned int maxLoadQueueSpace_; diff --git a/src/lib/models/outoforder/Core.cc b/src/lib/models/outoforder/Core.cc index df2237cfe8..9a626a5eb2 100644 --- a/src/lib/models/outoforder/Core.cc +++ b/src/lib/models/outoforder/Core.cc @@ -46,6 +46,7 @@ Core::Core(MemoryInterface& instructionMemory, MemoryInterface& dataMemory, [this](auto regs, auto values) { dispatchIssueUnit_.forwardOperands(regs, values); }, + [](auto uop) { uop->setCommitReady(); }, config["LSQ-L1-Interface"]["Exclusive"].as(), config["LSQ-L1-Interface"]["Load-Bandwidth"].as(), config["LSQ-L1-Interface"]["Store-Bandwidth"].as(), diff --git a/src/lib/pipeline/FetchUnit.cc b/src/lib/pipeline/FetchUnit.cc index 0cb9d33104..a0855aeee6 100644 --- a/src/lib/pipeline/FetchUnit.cc +++ b/src/lib/pipeline/FetchUnit.cc @@ -222,6 +222,9 @@ void FetchUnit::updatePC(uint64_t address) { } void FetchUnit::requestFromPC() { + // Do nothing if supplying fetch stream from loop buffer + if (loopBufferState_ == LoopBufferState::SUPPLYING) return; + // Do nothing if buffer already contains enough data if (bufferedBytes_ >= isa_.getMaxInstructionSize()) return; diff --git a/src/lib/pipeline/LoadStoreQueue.cc b/src/lib/pipeline/LoadStoreQueue.cc index 2189e6feca..7844e465cd 100644 --- a/src/lib/pipeline/LoadStoreQueue.cc +++ b/src/lib/pipeline/LoadStoreQueue.cc @@ -20,11 +20,13 @@ LoadStoreQueue::LoadStoreQueue( unsigned int maxCombinedSpace, MemoryInterface& memory, span>> completionSlots, std::function, span)> forwardOperands, + std::function&)> raiseException, bool exclusive, uint16_t loadBandwidth, uint16_t storeBandwidth, uint16_t permittedRequests, uint16_t permittedLoads, uint16_t permittedStores) : completionSlots_(completionSlots), forwardOperands_(forwardOperands), + raiseException_(raiseException), maxCombinedSpace_(maxCombinedSpace), combined_(true), memory_(memory), @@ -40,11 +42,13 @@ LoadStoreQueue::LoadStoreQueue( MemoryInterface& memory, span>> completionSlots, std::function, span)> forwardOperands, + std::function&)> raiseException, bool exclusive, uint16_t loadBandwidth, uint16_t storeBandwidth, uint16_t permittedRequests, uint16_t permittedLoads, uint16_t permittedStores) : completionSlots_(completionSlots), forwardOperands_(forwardOperands), + raiseException_(raiseException), maxLoadQueueSpace_(maxLoadQueueSpace), maxStoreQueueSpace_(maxStoreQueueSpace), combined_(false), @@ -100,6 +104,13 @@ void LoadStoreQueue::startLoad(const std::shared_ptr& insn) { if (ld_addresses.size() == 0) { // Early execution if not addresses need to be accessed insn->execute(); + + if (insn->exceptionEncountered()) { + // Exception; don't pass insn to completedLoads_ + raiseException_(insn); + return; + } + completedLoads_.push(insn); } else { // Create a speculative entry for the load @@ -507,6 +518,13 @@ void LoadStoreQueue::tick() { if (load->hasAllData()) { // This load has completed load->execute(); + + if (load->exceptionEncountered()) { + // Exception; don't pass load to completedLoads_ + raiseException_(load); + continue; + } + if (load->isStoreData()) { supplyStoreData(load); } diff --git a/sst/SimEngMemInterface.cc b/sst/SimEngMemInterface.cc index 4e07801f21..f805b30d5d 100644 --- a/sst/SimEngMemInterface.cc +++ b/sst/SimEngMemInterface.cc @@ -196,6 +196,7 @@ void SimEngMemInterface::requestWrite(const MemoryAccessTarget& target, for (StandardMem::Request* req : requests) { sstMem_->send(req); } + delete aggrReq; } void SimEngMemInterface::tick() { tickCounter_++; } diff --git a/test/unit/pipeline/LoadStoreQueueTest.cc b/test/unit/pipeline/LoadStoreQueueTest.cc index a6519d6632..414363352c 100644 --- a/test/unit/pipeline/LoadStoreQueueTest.cc +++ b/test/unit/pipeline/LoadStoreQueueTest.cc @@ -57,20 +57,22 @@ class LoadStoreQueueTest : public ::testing::TestWithParam { LoadStoreQueue getQueue() { if (GetParam()) { // Combined queue - return LoadStoreQueue(MAX_COMBINED, dataMemory, - {completionSlots.data(), completionSlots.size()}, - [this](auto registers, auto values) { - forwardOperandsHandler.forwardOperands(registers, - values); - }); + return LoadStoreQueue( + MAX_COMBINED, dataMemory, + {completionSlots.data(), completionSlots.size()}, + [this](auto registers, auto values) { + forwardOperandsHandler.forwardOperands(registers, values); + }, + [](auto uop) {}); } else { // Split queue - return LoadStoreQueue(MAX_LOADS, MAX_STORES, dataMemory, - {completionSlots.data(), completionSlots.size()}, - [this](auto registers, auto values) { - forwardOperandsHandler.forwardOperands(registers, - values); - }); + return LoadStoreQueue( + MAX_LOADS, MAX_STORES, dataMemory, + {completionSlots.data(), completionSlots.size()}, + [this](auto registers, auto values) { + forwardOperandsHandler.forwardOperands(registers, values); + }, + [](auto uop) {}); } } @@ -133,9 +135,9 @@ class LoadStoreQueueTest : public ::testing::TestWithParam { // Test that a split queue can be constructed correctly TEST_F(LoadStoreQueueTest, SplitQueue) { - LoadStoreQueue queue = - LoadStoreQueue(MAX_LOADS, MAX_STORES, dataMemory, {nullptr, 0}, - [](auto registers, auto values) {}); + LoadStoreQueue queue = LoadStoreQueue( + MAX_LOADS, MAX_STORES, dataMemory, {nullptr, 0}, + [](auto registers, auto values) {}, [](auto uop) {}); EXPECT_EQ(queue.isCombined(), false); EXPECT_EQ(queue.getLoadQueueSpace(), MAX_LOADS); @@ -145,8 +147,9 @@ TEST_F(LoadStoreQueueTest, SplitQueue) { // Test that a combined queue can be constructed correctly TEST_F(LoadStoreQueueTest, CombinedQueue) { - LoadStoreQueue queue = LoadStoreQueue(MAX_COMBINED, dataMemory, {nullptr, 0}, - [](auto registers, auto values) {}); + LoadStoreQueue queue = LoadStoreQueue( + MAX_COMBINED, dataMemory, {nullptr, 0}, + [](auto registers, auto values) {}, [](auto uop) {}); EXPECT_EQ(queue.isCombined(), true); EXPECT_EQ(queue.getLoadQueueSpace(), MAX_COMBINED); diff --git a/test/unit/pipeline/ReorderBufferTest.cc b/test/unit/pipeline/ReorderBufferTest.cc index 66b8f93dc4..df217968e3 100644 --- a/test/unit/pipeline/ReorderBufferTest.cc +++ b/test/unit/pipeline/ReorderBufferTest.cc @@ -26,8 +26,9 @@ class ReorderBufferTest : public testing::Test { ReorderBufferTest() : memory{}, rat({{8, 32}}, {64}), - lsq(maxLSQLoads, maxLSQStores, dataMemory, {nullptr, 0}, - [](auto registers, auto values) {}), + lsq( + maxLSQLoads, maxLSQStores, dataMemory, {nullptr, 0}, + [](auto registers, auto values) {}, [](auto uop) {}), uop(new MockInstruction), uop2(new MockInstruction), uopPtr(uop),