From e7ffe7a7dfefd86233656c98574b2c8eea84c2a7 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Fri, 17 Apr 2026 10:27:45 -0700 Subject: [PATCH 1/4] override register states --- passes/sat/sim.cc | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index e445624ce..4da2b6e47 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -161,6 +161,9 @@ struct SimInstance pool dirty_memories; pool dirty_children; + // All wires that drive FF Q outputs + pool register_wires; + struct ff_state_t { Const past_d; @@ -1082,6 +1085,23 @@ struct SimInstance child.second->register_signals(id); } + void build_registers() + { + for (auto cell : module->cells()) + { + if (!cell->is_builtin_ff()) + continue; + FfData ff_data(nullptr, cell); + SigSpec q = sigmap(ff_data.sig_q); + for (auto bit : q) { + if (bit.wire != nullptr) + register_wires.insert(bit.wire); + } + } + for (auto child : children) + child.second->build_registers(); + } + void write_output_header(std::function enter_scope, std::function exit_scope, std::function register_signal) { int exit_scopes = 1; @@ -1255,6 +1275,50 @@ struct SimInstance return did_something; } + bool setRegisters(uint64_t time) + { + bool did_something = false; + for (auto &item : fst_handles) { + if (item.second == 0) continue; + if (register_wires.count(item.first) == 0) continue; + Wire *wire = item.first; + Const vcd_val = Const::from_string(shared->fst->valueOf(item.second)); + Const sim_val = get_state(wire); + if (sim_val != vcd_val) { + if (debug) + log_warning("Register mismatch at time %lu%s for %s.%s: " + "sim=%s vcd=%s, overwriting...\n", + (unsigned long)time, + shared->fst->getTimescaleString(), + scope.c_str(), log_id(wire->name), + log_signal(sim_val), log_signal(vcd_val)); + } + did_something |= set_state(wire, vcd_val); + } + for (auto &item : fst_array_handles) { + if (register_wires.count(item.first) == 0) continue; + did_something |= setStateFromArrayHandles(item.first, item.second); + } + for (auto child : children) + did_something |= child.second->setRegisters(time); + return did_something; + } + + // Useful for debug + void dumpRegisters(uint64_t time) + { + for (auto &item : fst_handles) { + if (item.second == 0) continue; + if (register_wires.count(item.first) == 0) continue; + log("Register %s.%s at time %lu%s: %s\n", + scope.c_str(), log_id(item.first->name), + (unsigned long)time, shared->fst->getTimescaleString(), + shared->fst->valueOf(item.second).c_str()); + } + for (auto child : children) + child.second->dumpRegisters(time); + } + void addAdditionalInputs() { for (auto cell : module->cells()) @@ -1385,6 +1449,7 @@ struct SimWorker : SimShared { next_output_id = 1; top->register_signals(top->shared->next_output_id); + top->build_registers(); } void register_output_step(int t) @@ -1676,6 +1741,11 @@ struct SimWorker : SimShared } if (did_something) update(true); + + // Override register state from VCD every cycle + if (top->setRegisters(time)) + update(true); + register_output_step(time); last_time = time; From 1298607d958c067d5e15165ef8578f8eb71c9432 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Fri, 17 Apr 2026 10:29:13 -0700 Subject: [PATCH 2/4] fix compilation err --- passes/sat/sim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 4da2b6e47..90ffc689f 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -1285,7 +1285,7 @@ struct SimInstance Const vcd_val = Const::from_string(shared->fst->valueOf(item.second)); Const sim_val = get_state(wire); if (sim_val != vcd_val) { - if (debug) + if (shared->debug) log_warning("Register mismatch at time %lu%s for %s.%s: " "sim=%s vcd=%s, overwriting...\n", (unsigned long)time, From 07ae46f1ea5d446c80325e375ec77d99e46a1d31 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Fri, 17 Apr 2026 11:31:25 -0700 Subject: [PATCH 3/4] comments and cleanup --- passes/sat/sim.cc | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 90ffc689f..a2cf8a5f8 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -1087,17 +1087,21 @@ struct SimInstance void build_registers() { + // Loop over all cells for (auto cell : module->cells()) { + // Skip non-flip-flops if (!cell->is_builtin_ff()) continue; FfData ff_data(nullptr, cell); SigSpec q = sigmap(ff_data.sig_q); + // Insert all wires from FF Q outputs for (auto bit : q) { if (bit.wire != nullptr) register_wires.insert(bit.wire); } } + // Recursively build registers for all child modules for (auto child : children) child.second->build_registers(); } @@ -1279,9 +1283,10 @@ struct SimInstance { bool did_something = false; for (auto &item : fst_handles) { - if (item.second == 0) continue; - if (register_wires.count(item.first) == 0) continue; + if (item.second == 0) continue; // skip signals that aren't found + if (register_wires.count(item.first) == 0) continue; // skip non-registers Wire *wire = item.first; + // Extract wire value from simulation and VCD ground truth Const vcd_val = Const::from_string(shared->fst->valueOf(item.second)); Const sim_val = get_state(wire); if (sim_val != vcd_val) { @@ -1293,32 +1298,20 @@ struct SimInstance scope.c_str(), log_id(wire->name), log_signal(sim_val), log_signal(vcd_val)); } + // Overwrite simulation register state with the ground truth did_something |= set_state(wire, vcd_val); } + // Handles multi-dimensional registers for (auto &item : fst_array_handles) { if (register_wires.count(item.first) == 0) continue; did_something |= setStateFromArrayHandles(item.first, item.second); } + // Apply to all child modules for (auto child : children) did_something |= child.second->setRegisters(time); return did_something; } - // Useful for debug - void dumpRegisters(uint64_t time) - { - for (auto &item : fst_handles) { - if (item.second == 0) continue; - if (register_wires.count(item.first) == 0) continue; - log("Register %s.%s at time %lu%s: %s\n", - scope.c_str(), log_id(item.first->name), - (unsigned long)time, shared->fst->getTimescaleString(), - shared->fst->valueOf(item.second).c_str()); - } - for (auto child : children) - child.second->dumpRegisters(time); - } - void addAdditionalInputs() { for (auto cell : module->cells()) From da1072d77d0fa042ca89ded2fc78d22e666be790 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Fri, 17 Apr 2026 15:10:40 -0700 Subject: [PATCH 4/4] add flag to toggle reg overwriting --- passes/sat/sim.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index a2cf8a5f8..7cc53ba7a 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -1431,6 +1431,7 @@ struct SimWorker : SimShared std::string map_filename; std::string summary_filename; std::string scope; + bool reg_overwrite = false; ~SimWorker() { @@ -1736,7 +1737,7 @@ struct SimWorker : SimShared update(true); // Override register state from VCD every cycle - if (top->setRegisters(time)) + if (reg_overwrite && top->setRegisters(time)) update(true); register_output_step(time); @@ -3097,6 +3098,9 @@ struct SimPass : public Pass { log(" -log-interval \n"); log(" log progress every N cycles (if clock is specified) or samples (otherwise). Defaults to 0 (no logging)\n"); log("\n"); + log(" -reg\n"); + log(" overwrite register state from VCD file every cycle\n"); + log("\n"); } @@ -3112,7 +3116,7 @@ struct SimPass : public Pass { int cycle_width = 10; int append = 0, log_interval = 0; bool start_set = false, stop_set = false, at_set = false; - + bool reg_overwrite = false; log_header(design, "Executing SIM pass (simulate the circuit).\n"); size_t argidx; @@ -3284,6 +3288,10 @@ struct SimPass : public Pass { worker.outputfiles.emplace_back(std::unique_ptr(new AnnotateActivity(&worker))); continue; } + if (args[argidx] == "-reg") { + reg_overwrite = true; + continue; + } break; } extra_args(args, argidx, design); @@ -3306,6 +3314,7 @@ struct SimPass : public Pass { top_mod = mods.front(); } + worker.reg_overwrite = reg_overwrite; if (worker.sim_filename.empty()) worker.run(top_mod, cycle_width, numcycles); else {