Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise exception in LSU when ROB is drained #108

Merged
merged 15 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion core/Fetch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ namespace olympia
// Number of instructions to fetch
const uint32_t num_insts_to_fetch_;


// For traces with system instructions, skip them
const bool skip_nonuser_mode_;

Expand Down
10 changes: 8 additions & 2 deletions core/Inst.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,18 @@ namespace olympia
return inst_arch_info_->getTargetPipe();
}

// ROB handling -- mark this instruction as the oldest in the machine
void setOldest(bool oldest, sparta::Scheduleable * rob_retire_event) {
ev_retire_ = rob_retire_event;
is_oldest_ = oldest;
}

bool isMarkedOldest() const { return is_oldest_; }

// Instruction trace/JSON generation -- mark instruction as
// last in trace/JSON file.
void setLast() { is_last_ = true; }
bool getLast() const { return is_last_; }

// Set the instructions unique ID. This ID in constantly
// incremented and does not repeat. The same instruction in a
// trace can have different unique IDs (due to flushing)
Expand Down Expand Up @@ -217,7 +222,8 @@ namespace olympia

sparta::memory::addr_t inst_pc_ = 0; // Instruction's PC
sparta::memory::addr_t target_vaddr_ = 0; // Instruction's Target PC (for branches, loads/stores)
bool is_oldest_ = false;
bool is_oldest_ = false;
bool is_last_ = false; // Is last intruction of trace
uint64_t unique_id_ = 0; // Supplied by Fetch
uint64_t program_id_ = 0; // Supplied by a trace Reader or execution backend
bool is_speculative_ = false; // Is this instruction soon to be flushed?
Expand Down
10 changes: 7 additions & 3 deletions core/InstGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ namespace olympia
}

++curr_inst_index_;
if (inst != nullptr) {
inst->setUniqueID(++unique_id_);
inst->setProgramID(unique_id_);
inst->setUniqueID(++unique_id_);
inst->setProgramID(unique_id_);
if(isDone()) {
inst->setLast();
}
return inst;

Expand Down Expand Up @@ -176,6 +177,9 @@ namespace olympia
//inst->setVAddrVector(std::move(addrs));
}
++next_it_;
if(isDone()) {
inst->setLast();
}
return inst;
}
catch(std::exception & excpt) {
Expand Down
25 changes: 25 additions & 0 deletions core/LSU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ namespace olympia
ldst_pipeline_.registerHandlerAtStage(cache_lookup_stage_,
CREATE_SPARTA_HANDLER(LSU, handleCacheLookupReq_));

node->getParent()->registerForNotification<bool, LSU, &LSU::onRobDrained_>(
this, "rob_notif_channel", false /* ROB maybe not be constructed yet */);

ldst_pipeline_.registerHandlerAtStage(cache_read_stage_,
CREATE_SPARTA_HANDLER(LSU, handleCacheRead_));

Expand All @@ -108,6 +111,8 @@ namespace olympia
ILOG("LSU construct: #" << node->getGroupIdx());
}

void LSU::onRobDrained_(const bool & val) { retire_done_ = val; }

LSU::~LSU()
{
DLOG(getContainer()->getLocation() << ": " << load_store_info_allocator_.getNumAllocated()
Expand All @@ -116,6 +121,17 @@ namespace olympia
<< " MemoryAccessInfo objects allocated/created");
}

void LSU::onStartingTeardown_()
{
// If ROB has not stopped the simulation &
// the ldst has entries to process we should fail
if ((false == retire_done_) && (false == ldst_inst_queue_.empty()))
{
dumpDebugContent_(std::cerr);
sparta_assert(false, "Issue queue has pending instructions");
}
}

////////////////////////////////////////////////////////////////////////////////
// Callbacks
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -761,6 +777,15 @@ namespace olympia
// Otherwise, assertion error is fired inside arbitrateInstIssue_()
}

void LSU::dumpDebugContent_(std::ostream & output) const
{
output << "LSU Contents" << std::endl;
for (const auto & entry : ldst_inst_queue_)
{
output << '\t' << entry << std::endl;
}
}

void LSU::replayReady_(const LoadStoreInstInfoPtr & replay_inst_ptr)
{
ILOG("Replay inst ready " << replay_inst_ptr);
Expand Down
10 changes: 7 additions & 3 deletions core/LSU.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,18 @@ namespace olympia
// Type Name/Alias Declaration
////////////////////////////////////////////////////////////////////////////////

bool retire_done_ = false;
using LoadStoreInstInfoPtr = sparta::SpartaSharedPointer<LoadStoreInstInfo>;
using LoadStoreInstIterator = sparta::Buffer<LoadStoreInstInfoPtr>::const_iterator;

using FlushCriteria = FlushManager::FlushingCriteria;

using LoadStoreInstIterator = sparta::Buffer<LoadStoreInstInfoPtr>::const_iterator;
void onRobDrained_(const bool & val);

private:
using ScoreboardViews =
std::array<std::unique_ptr<sparta::ScoreboardView>, core_types::N_REGFILES>;

ScoreboardViews scoreboard_views_;
////////////////////////////////////////////////////////////////////////////////
// Input Ports
Expand Down Expand Up @@ -190,7 +194,6 @@ namespace olympia
////////////////////////////////////////////////////////////////////////////////
// Callbacks
////////////////////////////////////////////////////////////////////////////////

// Send initial credits (ldst_inst_queue_size_) to Dispatch Unit
void sendInitialCredits_();

Expand Down Expand Up @@ -229,6 +232,7 @@ namespace olympia
// Handle instruction flush in LSU
void handleFlush_(const FlushCriteria &);

void dumpDebugContent_(std::ostream & output) const override final;
// Instructions in the replay ready to issue
void replayReady_(const LoadStoreInstInfoPtr &);

Expand Down Expand Up @@ -319,7 +323,7 @@ namespace olympia

// When simulation is ending (error or not), this function
// will be called
void onStartingTeardown_() override {}
void onStartingTeardown_() override;

bool olderStoresExists_(const InstPtr & inst_ptr);

Expand Down
19 changes: 17 additions & 2 deletions core/ROB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@ namespace olympia
registerConsumerHandler(CREATE_SPARTA_HANDLER_WITH_DATA(ROB, handleFlush_,
FlushManager::FlushingCriteria));

// This event is ALWAYS scheduled, but it should not keep
// simulation continuing on.
// Do not allow this event to keep simulation alive
ev_ensure_forward_progress_.setContinuing(false);

// Notify other components when ROB stops the simulation
rob_drained_notif_source_.reset(new sparta::NotificationSource<bool>(
this->getContainer(),
"rob_notif_channel",
"Notification channel for rob",
"rob_notif_channel"
));
// Send initial credits to anyone that cares. Probably Dispatch.
sparta::StartupEvent(node, CREATE_SPARTA_HANDLER(ROB, sendInitialCredits_));
}
Expand Down Expand Up @@ -133,6 +139,7 @@ namespace olympia
// Will be true if the user provides a -i option
if (SPARTA_EXPECT_FALSE((num_retired_ == num_insts_to_retire_))) {
rob_stopped_simulation_ = true;
rob_drained_notif_source_->postNotification(true);
getScheduler()->stopRunning();
break;
}
Expand All @@ -151,6 +158,14 @@ namespace olympia
break;
}

// Check to see if this is the last instruction of the
// trace
if(ex_inst.getLast()) {
rob_stopped_simulation_ = true;
rob_drained_notif_source_->postNotification(true);
// No need to stop the scheduler -- let simulation
// drain normally. Also, don't need to check forward progress
}
}
else {
break;
Expand Down
2 changes: 2 additions & 0 deletions core/ROB.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ namespace olympia
sparta::Event<> ev_ensure_forward_progress_{&unit_event_set_, "forward_progress_check",
CREATE_SPARTA_HANDLER(ROB, checkForwardProgress_)};

std::unique_ptr<sparta::NotificationSource<bool>> rob_drained_notif_source_;

void sendInitialCredits_();
void retireEvent_();
void robAppended_(const InstGroup &);
Expand Down
10 changes: 10 additions & 0 deletions test/core/rename/Rename_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ class olympia::LSUTester
// while the ADD instruction is running, the STORE instruction should NOT issue
EXPECT_TRUE(lsu.lsu_insts_issued_ == 0);
}

void clear_entries(olympia::LSU &lsu){
h0lyalg0rithm marked this conversation as resolved.
Show resolved Hide resolved
auto iter = lsu.ldst_inst_queue_.begin();
while(iter != lsu.ldst_inst_queue_.end()){
auto x(iter++);
lsu.ldst_inst_queue_.erase(x);
}
}
};

//
Expand Down Expand Up @@ -444,6 +452,7 @@ void runTest(int argc, char **argv)
cls.runSimulator(&sim, 6);
executepipe_tester.test_dependent_integer_first_instruction(*my_executepipe);
lsu_tester.test_dependent_lsu_instruction(*my_lsu);
lsu_tester.clear_entries(*my_lsu);
}
else if(input_file == "raw_float_lsu.json"){
// testing RAW dependency for data operand
Expand All @@ -457,6 +466,7 @@ void runTest(int argc, char **argv)
cls.runSimulator(&sim, 6);
executepipe_tester.test_dependent_integer_first_instruction(*my_executepipe);
lsu_tester.test_dependent_lsu_instruction(*my_lsu);
lsu_tester.clear_entries(*my_lsu);
}
else if(input_file == "amoadd.json"){
sparta::Scheduler sched;
Expand Down