mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-02 13:36:08 +00:00
Merge b3b1394cf1 into c9805ceb33
This commit is contained in:
commit
16ed204d89
20 changed files with 354 additions and 36 deletions
|
|
@ -60,6 +60,11 @@ struct CheckPass : public Pass {
|
|||
log(" also check for internal cells that have not been mapped to cells of the\n");
|
||||
log(" target architecture\n");
|
||||
log("\n");
|
||||
log(" -nolatches\n");
|
||||
log(" also check for latch cells ($dlatch, $adlatch, $dlatchsr and their\n");
|
||||
log(" $_DLATCH_*/$_DLATCHSR_* mappings) remaining in the design. Use this\n");
|
||||
log(" before techmapping in flows that must not emit latches.\n");
|
||||
log("\n");
|
||||
log(" -allow-tbuf\n");
|
||||
log(" modify the -mapped behavior to still allow $_TBUF_ cells\n");
|
||||
log("\n");
|
||||
|
|
@ -79,6 +84,7 @@ struct CheckPass : public Pass {
|
|||
bool noinit = false;
|
||||
bool initdrv = false;
|
||||
bool mapped = false;
|
||||
bool nolatches = false;
|
||||
bool allow_tbuf = false;
|
||||
bool assert_mode = false;
|
||||
bool force_detailed_loop_check = false;
|
||||
|
|
@ -98,6 +104,10 @@ struct CheckPass : public Pass {
|
|||
mapped = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nolatches") {
|
||||
nolatches = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-allow-tbuf") {
|
||||
allow_tbuf = true;
|
||||
continue;
|
||||
|
|
@ -114,12 +124,27 @@ struct CheckPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
bool latchonly = design->scratchpad_get_bool("check.latchonly", false);
|
||||
|
||||
log_header(design, "Executing CHECK pass (checking for obvious problems).\n");
|
||||
|
||||
for (auto module : design->selected_whole_modules_warn())
|
||||
{
|
||||
log("Checking module %s...\n", module);
|
||||
|
||||
// latch-only mode only flags latches, skipping the (potentially false-positive mid-flow) undriven/driver/loop checks below
|
||||
if (latchonly) {
|
||||
for (auto cell : module->cells())
|
||||
if (
|
||||
cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) ||
|
||||
cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_")
|
||||
) {
|
||||
log_warning("Cell %s.%s is a latch of type %s.\n", module, cell, cell->type.unescape());
|
||||
counter++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
SigMap sigmap(module);
|
||||
dict<SigBit, vector<string>> wire_drivers;
|
||||
dict<SigBit, Cell *> driver_cells;
|
||||
|
|
@ -265,6 +290,15 @@ struct CheckPass : public Pass {
|
|||
cell_allowed:;
|
||||
}
|
||||
|
||||
if (
|
||||
nolatches && (
|
||||
cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) ||
|
||||
cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_"))
|
||||
) {
|
||||
log_warning("Cell %s.%s is a latch of type %s.\n", module, cell, cell->type.unescape());
|
||||
counter++;
|
||||
}
|
||||
|
||||
for (auto &conn : cell->connections()) {
|
||||
bool input = cell->input(conn.first);
|
||||
bool output = cell->output(conn.first);
|
||||
|
|
|
|||
|
|
@ -69,10 +69,14 @@ struct ProcPass : public Pass {
|
|||
log(" -noopt\n");
|
||||
log(" Will omit the opt_expr pass.\n");
|
||||
log("\n");
|
||||
log(" -latches <auto|warn|error>\n");
|
||||
log(" controls how the inference of a latch is reported.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
std::string global_arst;
|
||||
std::string latches;
|
||||
bool ifxmode = false;
|
||||
bool nomux = false;
|
||||
bool noopt = false;
|
||||
|
|
@ -104,6 +108,10 @@ struct ProcPass : public Pass {
|
|||
norom = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-latches" && argidx+1 < args.size()) {
|
||||
latches = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
|
@ -121,7 +129,10 @@ struct ProcPass : public Pass {
|
|||
Pass::call(design, "proc_rom");
|
||||
if (!nomux)
|
||||
Pass::call(design, ifxmode ? "proc_mux -ifx" : "proc_mux");
|
||||
Pass::call(design, "proc_dlatch");
|
||||
if (latches.empty())
|
||||
Pass::call(design, "proc_dlatch");
|
||||
else
|
||||
Pass::call(design, "proc_dlatch -latches " + latches);
|
||||
Pass::call(design, "proc_dff");
|
||||
Pass::call(design, "proc_memwr");
|
||||
Pass::call(design, "proc_clean");
|
||||
|
|
|
|||
|
|
@ -345,7 +345,13 @@ struct proc_dlatch_db_t
|
|||
}
|
||||
};
|
||||
|
||||
void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
|
||||
enum LatchPolicy {
|
||||
POLICY_INFO,
|
||||
POLICY_WARN,
|
||||
POLICY_ERROR
|
||||
};
|
||||
|
||||
void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc, LatchPolicy policy)
|
||||
{
|
||||
RTLIL::SigSig latches_bits, nolatches_bits;
|
||||
dict<SigBit, SigBit> latches_out_in;
|
||||
|
|
@ -443,6 +449,12 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
|
|||
if (proc->get_bool_attribute(ID::always_comb))
|
||||
log_error("Latch inferred for signal `%s.%s' from always_comb process `%s.%s'.\n",
|
||||
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
|
||||
else if (policy == POLICY_ERROR)
|
||||
log_error("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n",
|
||||
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), cell);
|
||||
else if (policy == POLICY_WARN)
|
||||
log_warning("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n",
|
||||
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), cell);
|
||||
else
|
||||
log("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n",
|
||||
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), cell);
|
||||
|
|
@ -458,22 +470,49 @@ struct ProcDlatchPass : public Pass {
|
|||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" proc_dlatch [selection]\n");
|
||||
log(" proc_dlatch [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This pass identifies latches in the processes and converts them to\n");
|
||||
log("d-type latches.\n");
|
||||
log("\n");
|
||||
log(" -latches <info|warn|error>\n");
|
||||
log(" controls how the inference of a latch is reported. Alternatively, one\n");
|
||||
log(" can use the 'proc.latches' scratchpad variable. Defaults to 'warn'.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
log_header(design, "Executing PROC_DLATCH pass (convert process syncs to latches).\n");
|
||||
|
||||
extra_args(args, 1, design);
|
||||
std::string policy_str;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-latches" && argidx+1 < args.size()) {
|
||||
policy_str = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (policy_str.empty())
|
||||
policy_str = design->scratchpad_get_string("proc.latches", "warn");
|
||||
|
||||
LatchPolicy policy;
|
||||
if (policy_str == "info")
|
||||
policy = POLICY_INFO;
|
||||
else if (policy_str == "warn")
|
||||
policy = POLICY_WARN;
|
||||
else if (policy_str == "error")
|
||||
policy = POLICY_ERROR;
|
||||
else
|
||||
log_cmd_error("Invalid value '%s' for -latches (expected info|warn|error).\n", policy_str.c_str());
|
||||
|
||||
for (auto mod : design->all_selected_modules()) {
|
||||
proc_dlatch_db_t db(mod);
|
||||
for (auto proc : mod->selected_processes())
|
||||
proc_dlatch(db, proc);
|
||||
proc_dlatch(db, proc, policy);
|
||||
db.fixup_muxes();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue