Merge branch 'main' of github.com:silimate/yosys into fork-scope

This commit is contained in:
Stan Lee 2026-04-20 15:21:20 -07:00
commit 38f97edb45
1 changed files with 73 additions and 1 deletions

View File

@ -161,6 +161,9 @@ struct SimInstance
pool<IdString> dirty_memories;
pool<SimInstance*> dirty_children;
// All wires that drive FF Q outputs
pool<Wire*> register_wires;
struct ff_state_t
{
Const past_d;
@ -1048,6 +1051,27 @@ struct SimInstance
child.second->register_signals(id);
}
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();
}
void write_output_header(std::function<void(IdString)> enter_scope, std::function<void()> exit_scope, std::function<void(const char*, int, Wire*, int, bool)> register_signal)
{
int exit_scopes = 1;
@ -1217,6 +1241,39 @@ struct SimInstance
return did_something;
}
bool setRegisters(uint64_t time)
{
bool did_something = false;
for (auto &item : fst_handles) {
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) {
if (shared->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));
}
// 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;
}
void addAdditionalInputs()
{
for (auto cell : module->cells())
@ -1332,6 +1389,7 @@ struct SimWorker : SimShared
std::string map_filename;
std::string summary_filename;
std::string scope;
bool reg_overwrite = false;
~SimWorker()
{
@ -1343,6 +1401,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)
@ -1628,6 +1687,11 @@ struct SimWorker : SimShared
}
if (did_something)
update(true);
// Override register state from VCD every cycle
if (reg_overwrite && top->setRegisters(time))
update(true);
register_output_step(time);
last_time = time;
@ -2986,6 +3050,9 @@ struct SimPass : public Pass {
log(" -log-interval <integer>\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");
}
@ -3001,7 +3068,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;
@ -3173,6 +3240,10 @@ struct SimPass : public Pass {
worker.outputfiles.emplace_back(std::unique_ptr<AnnotateActivity>(new AnnotateActivity(&worker)));
continue;
}
if (args[argidx] == "-reg") {
reg_overwrite = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -3195,6 +3266,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 {