mirror of
https://github.com/YosysHQ/yosys
synced 2026-03-01 19:26:55 +00:00
Detect undriven and error/warn
This commit is contained in:
parent
cdc728b6f0
commit
b454582f54
4 changed files with 108 additions and 5 deletions
|
|
@ -26,6 +26,7 @@
|
|||
#include "kernel/yw.h"
|
||||
#include "kernel/json.h"
|
||||
#include "kernel/fmt.h"
|
||||
#include "kernel/drivertools.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
|
|
@ -125,6 +126,8 @@ struct SimShared
|
|||
bool serious_asserts = false;
|
||||
bool fst_noinit = false;
|
||||
bool initstate = true;
|
||||
bool undriven_check = true;
|
||||
bool undriven_warning = false;
|
||||
};
|
||||
|
||||
void zinit(Const &v)
|
||||
|
|
@ -426,7 +429,7 @@ struct SimInstance
|
|||
|
||||
Const value = builder.build();
|
||||
if (shared->debug)
|
||||
log("[%s] get %s: %s\n", hiername(), log_signal(sig), log_signal(value));
|
||||
log("[%s] get %s: %s\n", hiername(), log_signal(sig, true), log_signal(value, true));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +448,7 @@ struct SimInstance
|
|||
}
|
||||
|
||||
if (shared->debug)
|
||||
log("[%s] set %s: %s\n", hiername(), log_signal(sig), log_signal(value));
|
||||
log("[%s] set %s: %s\n", hiername(), log_signal(sig, true), log_signal(value, true));
|
||||
return did_something;
|
||||
}
|
||||
|
||||
|
|
@ -1192,6 +1195,54 @@ struct SimInstance
|
|||
child.second->addAdditionalInputs();
|
||||
}
|
||||
|
||||
// Preconditions / assumptions:
|
||||
// 1) fst_handles is populated for this instance (0 handle means not in trace).
|
||||
// 2) fst_inputs is finalized (top-level inputs + addAdditionalInputs() for $anyseq).
|
||||
// 3) module has no processes (sim enforces proc-lowered input before this point).
|
||||
// 4) sigmap is valid for per-bit queries on this instance.
|
||||
// 5) shared->fst is active, i.e. this is called from FST/VCD replay flow.
|
||||
int checkUndrivenReplaySignals()
|
||||
{
|
||||
int issue_count = 0;
|
||||
bool has_replay_candidates = false;
|
||||
|
||||
for (auto &item : fst_handles)
|
||||
if (item.second != 0 && !fst_inputs.count(item.first)) {
|
||||
has_replay_candidates = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_replay_candidates) {
|
||||
DriverMap drivermap(module->design);
|
||||
drivermap.add(module);
|
||||
|
||||
for (auto &item : fst_handles) {
|
||||
Wire *wire = item.first;
|
||||
if (item.second == 0 || fst_inputs.count(wire))
|
||||
continue;
|
||||
|
||||
SigSpec undriven;
|
||||
for (auto bit : sigmap(wire))
|
||||
if (bit.wire != nullptr && drivermap(DriveBit(bit)).is_none())
|
||||
undriven.append(bit);
|
||||
|
||||
undriven.sort_and_unify();
|
||||
if (undriven.empty())
|
||||
continue;
|
||||
|
||||
issue_count++;
|
||||
std::string wire_name = scope + "." + RTLIL::unescape_id(wire->name);
|
||||
log_warning("Input trace contains undriven signal `%s` (%s); values for this signal are not replayed from FST/VCD input.\n",
|
||||
wire_name.c_str(), log_signal(undriven, true));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto child : children)
|
||||
issue_count += child.second->checkUndrivenReplaySignals();
|
||||
|
||||
return issue_count;
|
||||
}
|
||||
|
||||
bool setInputs()
|
||||
{
|
||||
bool did_something = false;
|
||||
|
|
@ -1248,7 +1299,7 @@ struct SimInstance
|
|||
} else if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X
|
||||
for(int i=0;i<fst_val.size();i++) {
|
||||
if (fst_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
|
||||
log_warning("Signal '%s.%s' in file %s in simulation %s\n", scope, log_id(item.first), log_signal(fst_val), log_signal(sim_val));
|
||||
log_warning("Signal '%s.%s' in file %s in simulation %s\n", scope, log_id(item.first), log_signal(fst_val, true), log_signal(sim_val, true));
|
||||
retVal = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1256,14 +1307,14 @@ struct SimInstance
|
|||
} else if (shared->sim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X
|
||||
for(int i=0;i<sim_val.size();i++) {
|
||||
if (sim_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
|
||||
log_warning("Signal '%s.%s' in file %s in simulation %s\n", scope, log_id(item.first), log_signal(fst_val), log_signal(sim_val));
|
||||
log_warning("Signal '%s.%s' in file %s in simulation %s\n", scope, log_id(item.first), log_signal(fst_val, true), log_signal(sim_val, true));
|
||||
retVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fst_val!=sim_val) {
|
||||
log_warning("Signal '%s.%s' in file %s in simulation '%s'\n", scope, log_id(item.first), log_signal(fst_val), log_signal(sim_val));
|
||||
log_warning("Signal '%s.%s' in file %s in simulation '%s'\n", scope, log_id(item.first), log_signal(fst_val, true), log_signal(sim_val, true));
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1498,6 +1549,12 @@ struct SimWorker : SimShared
|
|||
}
|
||||
|
||||
top->addAdditionalInputs();
|
||||
if (undriven_check) {
|
||||
int issue_count = top->checkUndrivenReplaySignals();
|
||||
if (issue_count > 0 && !undriven_warning)
|
||||
log_cmd_error("Found %d undriven signal%s in the replay trace. Use -undriven-warn to continue or -no-undriven-check to disable this check.\n",
|
||||
issue_count, issue_count == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
uint64_t startCount = 0;
|
||||
uint64_t stopCount = 0;
|
||||
|
|
@ -2627,6 +2684,12 @@ struct SimPass : public Pass {
|
|||
log(" Yosys witness (.yw) replay is preferred when possible.\n");
|
||||
log(" VCD support requires vcd2fst external tool to be present\n");
|
||||
log("\n");
|
||||
log(" -no-undriven-check\n");
|
||||
log(" skip undriven-signal checks for FST/VCD replay\n");
|
||||
log("\n");
|
||||
log(" -undriven-warn\n");
|
||||
log(" downgrade undriven-signal replay errors to warnings\n");
|
||||
log("\n");
|
||||
log(" -width <integer>\n");
|
||||
log(" cycle width in generated simulation output (must be divisible by 2).\n");
|
||||
log("\n");
|
||||
|
|
@ -2844,6 +2907,14 @@ struct SimPass : public Pass {
|
|||
worker.fst_noinit = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-no-undriven-check") {
|
||||
worker.undriven_check = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-undriven-warn") {
|
||||
worker.undriven_warning = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-x") {
|
||||
worker.ignore_x = true;
|
||||
continue;
|
||||
|
|
|
|||
7
tests/sim/undriven_replay.v
Normal file
7
tests/sim/undriven_replay.v
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
module undriven_replay (
|
||||
input wire in,
|
||||
output wire out,
|
||||
output wire undrv
|
||||
);
|
||||
assign out = in;
|
||||
endmodule
|
||||
15
tests/sim/undriven_replay.vcd
Normal file
15
tests/sim/undriven_replay.vcd
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
$version Yosys $end
|
||||
$scope module undriven_replay $end
|
||||
$var wire 1 ! in $end
|
||||
$var wire 1 " out $end
|
||||
$var wire 1 # undrv $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
#0
|
||||
b0 !
|
||||
b0 "
|
||||
b1 #
|
||||
#10
|
||||
b1 !
|
||||
b1 "
|
||||
b0 #
|
||||
10
tests/sim/undriven_replay.ys
Normal file
10
tests/sim/undriven_replay.ys
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
read_verilog undriven_replay.v
|
||||
prep -top undriven_replay
|
||||
|
||||
logger -expect error "Found 1 undriven signal in the replay trace" 1
|
||||
sim -r undriven_replay.vcd -scope undriven_replay -q
|
||||
|
||||
logger -expect warning "Input trace contains undriven signal" 1
|
||||
sim -r undriven_replay.vcd -scope undriven_replay -q -undriven-warn
|
||||
|
||||
sim -r undriven_replay.vcd -scope undriven_replay -q -no-undriven-check
|
||||
Loading…
Add table
Add a link
Reference in a new issue