diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 16fed54f203..e183cbf1007 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -465,6 +465,9 @@ struct LibertyFrontend : public Frontend { log(" -setattr \n"); log(" set the specified attribute (to the value 1) on all loaded modules\n"); log("\n"); + log(" -unit_delay\n"); + log(" import combinational timing arcs under the unit delay model\n"); + log("\n"); } void execute(std::istream *&f, std::string filename, std::vector args, RTLIL::Design *design) override { @@ -475,6 +478,7 @@ struct LibertyFrontend : public Frontend { bool flag_ignore_miss_func = false; bool flag_ignore_miss_dir = false; bool flag_ignore_miss_data_latch = false; + bool flag_unit_delay = false; std::vector attributes; size_t argidx; @@ -514,6 +518,10 @@ struct LibertyFrontend : public Frontend { attributes.push_back(RTLIL::escape_id(args[++argidx])); continue; } + if (arg == "-unit_delay") { + flag_unit_delay = true; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -652,6 +660,7 @@ struct LibertyFrontend : public Frontend { continue; RTLIL::Wire *wire = module->wires_.at(RTLIL::escape_id(node->args.at(0))); + log_assert(wire); if (dir && dir->value == "inout") { wire->port_input = true; @@ -690,6 +699,43 @@ struct LibertyFrontend : public Frontend { } module->connect(RTLIL::SigSig(wire, out_sig)); } + + if (flag_unit_delay) { + pool done; + + for (auto timing : node->children) + if (timing->id == "timing" && timing->args.empty()) { + auto type = timing->find("timing_type"); + auto related_pin = timing->find("related_pin"); + if (!type || type->value != "combinational" || !related_pin) + continue; + + Wire *related = module->wire(RTLIL::escape_id(related_pin->value)); + if (!related) + log_error("Failed to find related pin %s for timing of pin %s on %s\n", + related_pin->value.c_str(), log_id(wire), log_id(module)); + + if (done.count(related)) + continue; + + RTLIL::Cell *spec = module->addCell(NEW_ID, ID($specify2)); + spec->setParam(ID::SRC_WIDTH, 1); + spec->setParam(ID::DST_WIDTH, 1); + spec->setParam(ID::T_FALL_MAX, 1000); + spec->setParam(ID::T_FALL_TYP, 1000); + spec->setParam(ID::T_FALL_MIN, 1000); + spec->setParam(ID::T_RISE_MAX, 1000); + spec->setParam(ID::T_RISE_TYP, 1000); + spec->setParam(ID::T_RISE_MIN, 1000); + spec->setParam(ID::SRC_DST_POL, false); + spec->setParam(ID::SRC_DST_PEN, false); + spec->setParam(ID::FULL, false); + spec->setPort(ID::EN, Const(1, 1)); + spec->setPort(ID::SRC, related); + spec->setPort(ID::DST, wire); + done.insert(related); + } + } } } diff --git a/tests/liberty/.gitignore b/tests/liberty/.gitignore index bf5ba57dce0..8763aaac515 100644 --- a/tests/liberty/.gitignore +++ b/tests/liberty/.gitignore @@ -1,4 +1,3 @@ *.log -test.ys *.filtered *.verilogsim diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh index 07d2cce1cd5..ff5b20d74e5 100755 --- a/tests/liberty/run-test.sh +++ b/tests/liberty/run-test.sh @@ -3,11 +3,13 @@ set -e for x in *.lib; do echo "Testing on $x.." - echo "read_verilog small.v" > test.ys - echo "synth -top small" >> test.ys - echo "dfflibmap -info -liberty ${x}" >> test.ys - ../../yosys -ql ${x%.lib}.log -s test.ys + ../../yosys -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty ${x}" -ql ${x%.lib}.log ../../yosys-filterlib - $x 2>/dev/null > $x.filtered ../../yosys-filterlib -verilogsim $x > $x.verilogsim diff $x.filtered $x.filtered.ok && diff $x.verilogsim $x.verilogsim.ok done + +for x in *.ys; do + echo "Running $x.." + ../../yosys -q -s $x -l ${x%.ys}.log +done diff --git a/tests/liberty/unit_delay.ys b/tests/liberty/unit_delay.ys new file mode 100644 index 00000000000..8dd4091835a --- /dev/null +++ b/tests/liberty/unit_delay.ys @@ -0,0 +1,3 @@ +# Nothing gets imported: the file lacks timing data +read_liberty -wb -unit_delay normal.lib +select -assert-none =*/t:$specify*