From d0b9a0cb98f7e84c69a6cdd1f43205d6b9d61511 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Mon, 12 May 2025 12:48:01 +1200 Subject: [PATCH] sim.cc: Move cycle check Calling `throw dst_end_of_data_exception()` when the desired number of cycles has been reached means that the fst reader can't tidy up after itself and leads to memory leaks. This doesn't happen when the `-stop` flag is used because the `Yosys::FstData` struct tracks the end time and skips the outer callback if the simulation has gone past the desired end time. Move cycle checking into the inner callback along with the time checking means that the outer callback no longer needs to throw an exception in order to stop checking further values, while still allowing the fst reader to finish reading and deallocate memory. --- kernel/fstdata.cc | 17 +++++++-- kernel/fstdata.h | 4 +- passes/sat/sim.cc | 96 +++++++++++++++++++---------------------------- 3 files changed, 55 insertions(+), 62 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index a62691fa1..c127cdf83 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -206,6 +206,7 @@ static void reconstruct_clb_attimes(void *user_data, uint64_t pnt_time, fstHandl void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */) { if (pnt_time > end_time || !pnt_value) return; + if (curr_cycle > last_cycle) return; // if we are past the timestamp bool is_clock = false; if (!all_samples) { @@ -225,6 +226,7 @@ void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_faci if (pnt_time > last_time) { if (all_samples) { callback(last_time); + curr_cycle++; last_time = pnt_time; } else { if (is_clock) { @@ -232,6 +234,7 @@ void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_faci std::string prev = past_data[pnt_facidx]; if ((prev!="1" && val=="1") || (prev!="0" && val=="0")) { callback(last_time); + curr_cycle++; last_time = pnt_time; } } @@ -241,12 +244,14 @@ void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_faci last_data[pnt_facidx] = std::string((const char *)pnt_value); } -void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t start, uint64_t end, CallbackFunction cb) +void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t start, uint64_t end, unsigned int end_cycle, CallbackFunction cb) { clk_signals = signal; callback = cb; start_time = start; end_time = end; + curr_cycle = 0; + last_cycle = end_cycle; last_data.clear(); last_time = start_time; past_data.clear(); @@ -256,12 +261,16 @@ void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t sta fstReaderSetUnlimitedTimeRange(ctx); fstReaderSetFacProcessMaskAll(ctx); fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr); - if (last_time!=end_time) { + if (last_time!=end_time && curr_cycle < last_cycle) { past_data = last_data; callback(last_time); + curr_cycle++; + } + if (curr_cycle < last_cycle) { + past_data = last_data; + callback(end_time); + curr_cycle++; } - past_data = last_data; - callback(end_time); } std::string FstData::valueOf(fstHandle signal) diff --git a/kernel/fstdata.h b/kernel/fstdata.h index f5cf1d48d..a8ae40301 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -50,7 +50,7 @@ class FstData std::vector& getVars() { return vars; }; void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen); - void reconstructAllAtTimes(std::vector &signal, uint64_t start_time, uint64_t end_time, CallbackFunction cb); + void reconstructAllAtTimes(std::vector &signal, uint64_t start_time, uint64_t end_time, unsigned int end_cycle, CallbackFunction cb); std::string valueOf(fstHandle signal); fstHandle getHandle(std::string name); @@ -73,6 +73,8 @@ private: std::string timescale_str; uint64_t start_time; uint64_t end_time; + unsigned int last_cycle; + unsigned int curr_cycle; CallbackFunction callback; std::vector clk_signals; bool all_samples; diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index b250d23d8..e2b0022ff 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -1546,36 +1546,27 @@ struct SimWorker : SimShared log(" for %d clock cycle(s)",numcycles); log("\n"); bool all_samples = fst_clock.empty(); + unsigned int end_cycle = cycles_set ? numcycles*2 : INT_MAX; - try { - fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) { - if (verbose) - log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString()); - bool did_something = top->setInputs(); + fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, end_cycle, [&](uint64_t time) { + if (verbose) + log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString()); + bool did_something = top->setInputs(); - if (initial) { - if (!fst_noinit) did_something |= top->setInitState(); - initialize_stable_past(); - initial = false; - } - if (did_something) - update(true); - register_output_step(time); + if (initial) { + if (!fst_noinit) did_something |= top->setInitState(); + initialize_stable_past(); + initial = false; + } + if (did_something) + update(true); + register_output_step(time); - bool status = top->checkSignals(); - if (status) - log_error("Signal difference\n"); - cycle++; - - // Limit to number of cycles if provided - if (cycles_set && cycle > numcycles *2) - throw fst_end_of_data_exception(); - if (time==stopCount) - throw fst_end_of_data_exception(); - }); - } catch(fst_end_of_data_exception) { - // end of data detected - } + bool status = top->checkSignals(); + if (status) + log_error("Signal difference\n"); + cycle++; + }); write_output_files(); delete fst; @@ -2248,40 +2239,31 @@ struct SimWorker : SimShared log("Writing data to `%s`\n", (tb_filename+".txt").c_str()); std::ofstream data_file(tb_filename+".txt"); std::stringstream initstate; - try { - fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) { - for(auto &item : clocks) - data_file << stringf("%s",fst->valueOf(item.second).c_str()); - for(auto &item : inputs) - data_file << stringf("%s",fst->valueOf(item.second).c_str()); - for(auto &item : outputs) - data_file << stringf("%s",fst->valueOf(item.second).c_str()); - data_file << stringf("%s\n",Const(time-prev_time).as_string().c_str()); + unsigned int end_cycle = cycles_set ? numcycles*2 : INT_MAX; + fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, end_cycle, [&](uint64_t time) { + for(auto &item : clocks) + data_file << stringf("%s",fst->valueOf(item.second).c_str()); + for(auto &item : inputs) + data_file << stringf("%s",fst->valueOf(item.second).c_str()); + for(auto &item : outputs) + data_file << stringf("%s",fst->valueOf(item.second).c_str()); + data_file << stringf("%s\n",Const(time-prev_time).as_string().c_str()); - if (time==startCount) { - // initial state - for(auto var : fst->getVars()) { - if (var.is_reg && !Const::from_string(fst->valueOf(var.id).c_str()).is_fully_undef()) { - if (var.scope == scope) { - initstate << stringf("\t\tuut.%s = %d'b%s;\n", var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); - } else if (var.scope.find(scope+".")==0) { - initstate << stringf("\t\tuut.%s.%s = %d'b%s;\n",var.scope.substr(scope.size()+1).c_str(), var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); - } + if (time==startCount) { + // initial state + for(auto var : fst->getVars()) { + if (var.is_reg && !Const::from_string(fst->valueOf(var.id).c_str()).is_fully_undef()) { + if (var.scope == scope) { + initstate << stringf("\t\tuut.%s = %d'b%s;\n", var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); + } else if (var.scope.find(scope+".")==0) { + initstate << stringf("\t\tuut.%s.%s = %d'b%s;\n",var.scope.substr(scope.size()+1).c_str(), var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); } } } - cycle++; - prev_time = time; - - // Limit to number of cycles if provided - if (cycles_set && cycle > numcycles *2) - throw fst_end_of_data_exception(); - if (time==stopCount) - throw fst_end_of_data_exception(); - }); - } catch(fst_end_of_data_exception) { - // end of data detected - } + } + cycle++; + prev_time = time; + }); f << stringf("\treg [0:%d] data [0:%d];\n", data_len-1, cycle-1); f << "\tinitial begin;\n";