mirror of https://github.com/YosysHQ/yosys.git
Merge 52b828e725 into 4821ed17b4
This commit is contained in:
commit
a26e2adfe6
|
|
@ -172,7 +172,10 @@ Verilog Attributes and non-standard features
|
||||||
- The frontend sets attributes ``always_comb``, ``always_latch`` and
|
- The frontend sets attributes ``always_comb``, ``always_latch`` and
|
||||||
``always_ff`` on processes derived from SystemVerilog style always blocks
|
``always_ff`` on processes derived from SystemVerilog style always blocks
|
||||||
according to the type of the always. These are checked for correctness in
|
according to the type of the always. These are checked for correctness in
|
||||||
``proc_dlatch``.
|
``proc_dlatch``. Latches inferred from ``always_latch`` processes are exempt
|
||||||
|
from the ``proc -latches <info|warn|error>`` reporting policy, and the
|
||||||
|
generated latch cells carry the ``always_latch`` attribute, which also
|
||||||
|
exempts them from `check` ``-nolatches``.
|
||||||
|
|
||||||
- The cell attribute ``wildcard_port_conns`` represents wildcard port
|
- The cell attribute ``wildcard_port_conns`` represents wildcard port
|
||||||
connections (SystemVerilog ``.*``). These are resolved to concrete connections
|
connections (SystemVerilog ``.*``). These are resolved to concrete connections
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,8 @@ struct CheckPass : public Pass {
|
||||||
log(" -nolatches\n");
|
log(" -nolatches\n");
|
||||||
log(" also check for latch cells ($dlatch, $adlatch, $dlatchsr and their\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(" $_DLATCH_*/$_DLATCHSR_* mappings) remaining in the design. Use this\n");
|
||||||
log(" before techmapping in flows that must not emit latches.\n");
|
log(" before techmapping in flows that must not emit latches. Cells marked\n");
|
||||||
|
log(" with the 'always_latch' attribute are not reported.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -latchonly\n");
|
log(" -latchonly\n");
|
||||||
log(" check only for latch cells (as listed under -nolatches), skipping all\n");
|
log(" check only for latch cells (as listed under -nolatches), skipping all\n");
|
||||||
|
|
@ -142,10 +143,9 @@ struct CheckPass : public Pass {
|
||||||
// latch-only mode only flags latches, skipping the (potentially false-positive mid-flow) undriven/driver/loop checks below
|
// latch-only mode only flags latches, skipping the (potentially false-positive mid-flow) undriven/driver/loop checks below
|
||||||
if (latchonly) {
|
if (latchonly) {
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
if (
|
if (!cell->get_bool_attribute(ID::always_latch) && (
|
||||||
cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) ||
|
cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) ||
|
||||||
cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_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());
|
log_warning("Cell %s.%s is a latch of type %s.\n", module, cell, cell->type.unescape());
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +298,7 @@ struct CheckPass : public Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
nolatches && (
|
nolatches && !cell->get_bool_attribute(ID::always_latch) && (
|
||||||
cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) ||
|
cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) ||
|
||||||
cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_"))
|
cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_"))
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ struct ProcPass : public Pass {
|
||||||
log(" -noopt\n");
|
log(" -noopt\n");
|
||||||
log(" Will omit the opt_expr pass.\n");
|
log(" Will omit the opt_expr pass.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -latches <auto|warn|error>\n");
|
log(" -latches <info|warn|error>\n");
|
||||||
log(" controls how the inference of a latch is reported.\n");
|
log(" controls how the inference of a latch is reported.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -546,11 +546,16 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc, LatchPolicy policy)
|
||||||
else
|
else
|
||||||
cell = db.module->addDlatch(NEW_ID, en, rhs, lhs);
|
cell = db.module->addDlatch(NEW_ID, en, rhs, lhs);
|
||||||
cell->set_src_attribute(src);
|
cell->set_src_attribute(src);
|
||||||
|
if (proc->get_bool_attribute(ID::always_latch))
|
||||||
|
cell->set_bool_attribute(ID::always_latch);
|
||||||
db.generated_dlatches.insert(cell);
|
db.generated_dlatches.insert(cell);
|
||||||
|
|
||||||
if (proc->get_bool_attribute(ID::always_comb))
|
if (proc->get_bool_attribute(ID::always_comb))
|
||||||
log_error("Latch inferred for signal `%s.%s' from always_comb process `%s.%s'.\n",
|
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());
|
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
|
||||||
|
else if (proc->get_bool_attribute(ID::always_latch))
|
||||||
|
log("Latch inferred for signal `%s.%s' from always_latch 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_ERROR)
|
else if (policy == POLICY_ERROR)
|
||||||
log_error("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n",
|
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);
|
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), cell);
|
||||||
|
|
@ -580,6 +585,9 @@ struct ProcDlatchPass : public Pass {
|
||||||
log(" -latches <info|warn|error>\n");
|
log(" -latches <info|warn|error>\n");
|
||||||
log(" controls how the inference of a latch is reported. Alternatively, one\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(" can use the 'proc.latches' scratchpad variable. Defaults to 'warn'.\n");
|
||||||
|
log(" Latches requested explicitly with 'always_latch' processes are exempt\n");
|
||||||
|
log(" from this policy and always reported at info level. The generated\n");
|
||||||
|
log(" latch cells carry the 'always_latch' attribute.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
|
|
||||||
|
|
@ -108,13 +108,20 @@ struct SynthAnalogDevicesPass : public ScriptPass
|
||||||
log(" -noabc9\n");
|
log(" -noabc9\n");
|
||||||
log(" disable use of new ABC9 flow\n");
|
log(" disable use of new ABC9 flow\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -latches <info|warn|error>\n");
|
||||||
|
log(" select the behaviour for latches that cannot be mapped to a\n");
|
||||||
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
help_script();
|
help_script();
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string top_opt, edif_file, json_file, tech, tech_param;
|
std::string top_opt, edif_file, json_file, tech, tech_param, latches;
|
||||||
bool flatten, retime, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp;
|
bool flatten, retime, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp;
|
||||||
bool abc9, dff;
|
bool abc9, dff;
|
||||||
bool flatten_before_abc;
|
bool flatten_before_abc;
|
||||||
|
|
@ -127,6 +134,7 @@ struct SynthAnalogDevicesPass : public ScriptPass
|
||||||
edif_file.clear();
|
edif_file.clear();
|
||||||
tech = "t16ffc";
|
tech = "t16ffc";
|
||||||
tech_param = " -D IS_T16FFC";
|
tech_param = " -D IS_T16FFC";
|
||||||
|
latches = "error";
|
||||||
flatten = true;
|
flatten = true;
|
||||||
retime = false;
|
retime = false;
|
||||||
noiopad = false;
|
noiopad = false;
|
||||||
|
|
@ -244,10 +252,17 @@ struct SynthAnalogDevicesPass : public ScriptPass
|
||||||
json_file = args[++argidx];
|
json_file = args[++argidx];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-latches" && argidx+1 < args.size()) {
|
||||||
|
latches = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
if (latches != "info" && latches != "warn" && latches != "error")
|
||||||
|
log_cmd_error("Invalid value '%s' for -latches (expected info, warn or error)\n", latches.c_str());
|
||||||
|
|
||||||
if (!(tech == "t16ffc" || tech == "t40lp"))
|
if (!(tech == "t16ffc" || tech == "t40lp"))
|
||||||
log_cmd_error("Invalid ADI -tech setting: '%s'.\n", tech);
|
log_cmd_error("Invalid ADI -tech setting: '%s'.\n", tech);
|
||||||
|
|
||||||
|
|
@ -276,7 +291,7 @@ struct SynthAnalogDevicesPass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("prepare")) {
|
if (check_label("prepare")) {
|
||||||
run("proc");
|
run("proc -latches " + latches);
|
||||||
if (flatten || help_mode) {
|
if (flatten || help_mode) {
|
||||||
run("check");
|
run("check");
|
||||||
run("flatten", "(with '-flatten')");
|
run("flatten", "(with '-flatten')");
|
||||||
|
|
@ -439,6 +454,8 @@ struct SynthAnalogDevicesPass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_ffs")) {
|
if (check_label("map_ffs")) {
|
||||||
|
if (latches == "error" || help_mode)
|
||||||
|
run("check -latchonly -assert", "(only if -latches error, the default)");
|
||||||
run("dfflegalize -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r");
|
run("dfflegalize -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r");
|
||||||
if (abc9 || help_mode) {
|
if (abc9 || help_mode) {
|
||||||
if (dff || help_mode)
|
if (dff || help_mode)
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ struct SynthPass : public ScriptPass {
|
||||||
log(" -nordff\n");
|
log(" -nordff\n");
|
||||||
log(" passed to 'memory'. prohibits merging of FFs into memory read ports\n");
|
log(" passed to 'memory'. prohibits merging of FFs into memory read ports\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -latches <auto|warn|error>\n");
|
log(" -latches <info|warn|error>\n");
|
||||||
log(" controls how the inference of a latch is reported.\n");
|
log(" controls how the inference of a latch is reported.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -noshare\n");
|
log(" -noshare\n");
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ struct SynthEfinixPass : public ScriptPass
|
||||||
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
|
@ -160,7 +161,7 @@ struct SynthEfinixPass : public ScriptPass
|
||||||
|
|
||||||
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
||||||
{
|
{
|
||||||
run("proc -latches " + (latches == "info" ? std::string("info") : std::string("warn")));
|
run("proc -latches " + latches);
|
||||||
run("check");
|
run("check");
|
||||||
run("flatten");
|
run("flatten");
|
||||||
run("tribuf -logic");
|
run("tribuf -logic");
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ struct SynthPass : public ScriptPass {
|
||||||
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
|
@ -289,7 +290,7 @@ struct SynthPass : public ScriptPass {
|
||||||
run("hierarchy -check");
|
run("hierarchy -check");
|
||||||
} else
|
} else
|
||||||
run(stringf("hierarchy -check -top %s", top_module));
|
run(stringf("hierarchy -check -top %s", top_module));
|
||||||
run("proc -latches " + (latches == "info" ? std::string("info") : std::string("warn")));
|
run("proc -latches " + latches);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("flatten", "(unless -noflatten)")) {
|
if (check_label("flatten", "(unless -noflatten)")) {
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
|
@ -304,7 +305,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("read_verilog " + define + " -lib -specify +/ice40/cells_sim.v");
|
run("read_verilog " + define + " -lib -specify +/ice40/cells_sim.v");
|
||||||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt));
|
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt));
|
||||||
run("proc -latches " + (latches == "info" ? std::string("info") : std::string("warn")));
|
run("proc -latches " + latches);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("flatten", "(unless -noflatten)"))
|
if (check_label("flatten", "(unless -noflatten)"))
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,19 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
log(" -noclkbuf\n");
|
log(" -noclkbuf\n");
|
||||||
log(" do not insert global clock buffers\n");
|
log(" do not insert global clock buffers\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -latches <info|warn|error>\n");
|
||||||
|
log(" select the behaviour for latches that cannot be mapped to a\n");
|
||||||
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
help_script();
|
help_script();
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, family_opt, bram_type;
|
string top_opt, family_opt, bram_type, latches;
|
||||||
bool flatten, nolutram, nobram, dff, nodsp, noiopad, noclkbuf;
|
bool flatten, nolutram, nobram, dff, nodsp, noiopad, noclkbuf;
|
||||||
|
|
||||||
void clear_flags() override
|
void clear_flags() override
|
||||||
|
|
@ -85,6 +92,7 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
top_opt = "-auto-top";
|
top_opt = "-auto-top";
|
||||||
family_opt = "cyclonev";
|
family_opt = "cyclonev";
|
||||||
bram_type = "m10k";
|
bram_type = "m10k";
|
||||||
|
latches = "error";
|
||||||
flatten = true;
|
flatten = true;
|
||||||
nolutram = false;
|
nolutram = false;
|
||||||
nobram = false;
|
nobram = false;
|
||||||
|
|
@ -145,10 +153,17 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
noclkbuf = true;
|
noclkbuf = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-latches" && argidx + 1 < args.size()) {
|
||||||
|
latches = args[++argidx];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
if (latches != "info" && latches != "warn" && latches != "error")
|
||||||
|
log_cmd_error("Invalid value '%s' for -latches (expected info, warn or error)\n", latches.c_str());
|
||||||
|
|
||||||
if (!design->full_selection())
|
if (!design->full_selection())
|
||||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||||
|
|
||||||
|
|
@ -183,7 +198,7 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("coarse")) {
|
if (check_label("coarse")) {
|
||||||
run("proc");
|
run("proc -latches " + latches);
|
||||||
if (flatten || help_mode) {
|
if (flatten || help_mode) {
|
||||||
run("check");
|
run("check");
|
||||||
run("flatten", "(skip if -noflatten)");
|
run("flatten", "(skip if -noflatten)");
|
||||||
|
|
@ -241,6 +256,8 @@ struct SynthIntelALMPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_ffs")) {
|
if (check_label("map_ffs")) {
|
||||||
|
if (latches == "error" || help_mode)
|
||||||
|
run("check -latchonly -assert", "(only if -latches error, the default)");
|
||||||
run("techmap");
|
run("techmap");
|
||||||
run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0");
|
run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0");
|
||||||
run("techmap -map +/intel_alm/common/dff_map.v");
|
run("techmap -map +/intel_alm/common/dff_map.v");
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ struct SynthLatticePass : public ScriptPass
|
||||||
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
log(" (ignored with -asyncprld, which has a latch primitive)\n");
|
log(" (ignored with -asyncprld, which has a latch primitive)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
|
@ -416,7 +417,7 @@ struct SynthLatticePass : public ScriptPass
|
||||||
|
|
||||||
if (check_label("coarse"))
|
if (check_label("coarse"))
|
||||||
{
|
{
|
||||||
run("proc -latches " + ((asyncprld || latches == "info") ? std::string("info") : std::string("warn")));
|
run("proc -latches " + (asyncprld ? std::string("info") : latches));
|
||||||
if (flatten || help_mode) {
|
if (flatten || help_mode) {
|
||||||
run("check");
|
run("check");
|
||||||
run("flatten");
|
run("flatten");
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ struct SynthNanoXplorePass : public ScriptPass
|
||||||
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
|
@ -263,7 +264,7 @@ struct SynthNanoXplorePass : public ScriptPass
|
||||||
|
|
||||||
if (check_label("coarse"))
|
if (check_label("coarse"))
|
||||||
{
|
{
|
||||||
run("proc -latches " + (latches == "info" ? std::string("info") : std::string("warn")));
|
run("proc -latches " + latches);
|
||||||
if (flatten || help_mode) {
|
if (flatten || help_mode) {
|
||||||
run("check");
|
run("check");
|
||||||
run("flatten", "(skip if -noflatten)");
|
run("flatten", "(skip if -noflatten)");
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
log(" dedicated hardware primitive and are implemented using LUTs\n");
|
||||||
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n");
|
||||||
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
log(" prints a warning, and 'info' permits them with an info-level message.\n");
|
||||||
|
log(" Latches explicitly requested with 'always_latch' are always permitted.\n");
|
||||||
log(" (only applies to the pp3 family)\n");
|
log(" (only applies to the pp3 family)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The following commands are executed by this synthesis command:\n");
|
log("The following commands are executed by this synthesis command:\n");
|
||||||
|
|
@ -226,7 +227,7 @@ struct SynthQuickLogicPass : public ScriptPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("prepare")) {
|
if (check_label("prepare")) {
|
||||||
run("proc -latches " + ((family == "pp3" && latches != "info") ? std::string("warn") : std::string("info")));
|
run("proc -latches " + (family == "pp3" ? latches : std::string("info")));
|
||||||
if (flatten) {
|
if (flatten) {
|
||||||
run("check");
|
run("check");
|
||||||
run("flatten", "(unless -noflatten)");
|
run("flatten", "(unless -noflatten)");
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,20 @@ logger -check-expected
|
||||||
|
|
||||||
design -reset
|
design -reset
|
||||||
|
|
||||||
|
# always_latch is exempt
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top(input g, d, output reg q);
|
||||||
|
always_latch if (g) q <= d;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
logger -expect-no-warnings
|
||||||
|
logger -expect log "Latch inferred for signal .* from always_latch process" 1
|
||||||
|
proc -latches error
|
||||||
|
logger -check-expected
|
||||||
|
select -assert-count 1 t:$dlatch a:always_latch %i
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
|
||||||
# error
|
# error
|
||||||
read_verilog <<EOT
|
read_verilog <<EOT
|
||||||
module top(input g, rn, d, output reg q);
|
module top(input g, rn, d, output reg q);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,18 @@ hierarchy -top top
|
||||||
proc
|
proc
|
||||||
check -nolatches -assert
|
check -nolatches -assert
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog -sv <<EOT
|
||||||
|
module top(input g, d, output reg q);
|
||||||
|
always_latch if (g) q <= d;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
hierarchy -top top
|
||||||
|
proc
|
||||||
|
select -assert-count 1 t:$dlatch a:always_latch %i
|
||||||
|
check -nolatches -assert
|
||||||
|
check -latchonly -assert
|
||||||
|
|
||||||
design -reset
|
design -reset
|
||||||
read_verilog <<EOT
|
read_verilog <<EOT
|
||||||
module top(input g, d, output reg q, output y);
|
module top(input g, d, output reg q, output y);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,18 @@ design -load read
|
||||||
synth_ice40 -latches info
|
synth_ice40 -latches info
|
||||||
select -assert-count 1 t:SB_LUT4
|
select -assert-count 1 t:SB_LUT4
|
||||||
|
|
||||||
design -load read
|
# always_latch
|
||||||
logger -expect warning "Latch inferred for signal" 1
|
design -reset
|
||||||
logger -expect error "Found 1 problems in 'check -assert'" 1
|
read_verilog -sv <<EOT
|
||||||
|
module top(input d, en, output reg q);
|
||||||
|
always_latch if (en) q = d;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
logger -expect-no-warnings
|
||||||
|
synth_ice40
|
||||||
|
logger -check-expected
|
||||||
|
select -assert-count 1 t:SB_LUT4
|
||||||
|
|
||||||
|
design -load read
|
||||||
|
logger -expect error "Latch inferred for signal" 1
|
||||||
synth_ice40
|
synth_ice40
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue