From ffa52738fba1264ef2eb37d5333babfa0758fe48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Apr 2020 14:26:52 -0700 Subject: xaiger: output $_DFF_[NP]_ with mergeability if -dff option --- backends/aiger/xaiger.cc | 86 +++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1fb7210cb..d014c4ec6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module, bool dff_mode, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -212,10 +212,7 @@ struct XAigerWriter continue; } - if (cell->type == ID($__ABC9_FF_) && - // The presence of an abc9_mergeability attribute indicates - // that we do want to pass this flop to ABC - cell->attributes.count(ID::abc9_mergeability)) + if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { SigBit D = sigmap(cell->getPort(ID::D).as_bit()); SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); @@ -233,7 +230,11 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); if (inst_module) { - IdString derived_type = inst_module->derive(module->design, cell->parameters); + IdString derived_type; + if (cell->parameters.empty()) + derived_type = cell->type; + else + derived_type = inst_module->derive(module->design, cell->parameters); inst_module = module->design->module(derived_type); log_assert(inst_module); @@ -319,7 +320,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); log_assert(box_module); - log_assert(box_module->attributes.count(ID::abc9_box_id) || box_module->get_bool_attribute(ID::abc9_flop)); + log_assert(box_module->attributes.count(ID::abc9_box_id)); auto r = box_ports.insert(cell->type); if (r.second) { @@ -383,27 +384,6 @@ struct XAigerWriter undriven_bits.erase(O); } } - - // Connect .abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box - if (box_module->get_bool_attribute(ID::abc9_flop)) { - SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str())); - if (rhs.empty()) - log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); - - for (auto b : rhs) { - SigBit I = sigmap(b); - if (b == RTLIL::Sx) - b = State::S0; - else if (I != b) { - if (I == RTLIL::Sx) - alias_map[b] = State::S0; - else - alias_map[b] = I; - } - co_bits.emplace_back(b); - unused_bits.erase(I); - } - } } for (auto bit : input_bits) @@ -593,7 +573,11 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); log_assert(box_module); - IdString derived_type = box_module->derive(box_module->design, cell->parameters); + IdString derived_type; + if (cell->parameters.empty()) + derived_type = cell->type; + else + derived_type = box_module->derive(module->design, cell->parameters); box_module = box_module->design->module(derived_type); log_assert(box_module); @@ -610,11 +594,6 @@ struct XAigerWriter box_outputs += GetSize(w); } - // For flops only, create an extra 1-bit input that drives a new wire - // called ".abc9_ff.Q" that is used below - if (box_module->get_bool_attribute(ID::abc9_flop)) - box_inputs++; - std::get<0>(v) = box_inputs; std::get<1>(v) = box_outputs; std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int(); @@ -635,18 +614,34 @@ struct XAigerWriter auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); write_s_buffer(ff_bits.size()); + dict clk_to_mergeability; + + bool nonzero_warned = false; for (const auto &i : ff_bits) { const SigBit &d = i.first; const Cell *cell = i.second; - int mergeability = cell->attributes.at(ID::abc9_mergeability).as_int(); + log_assert(cell->type.in(ID($_DFF_N_), ID($_DFF_P_))); + + SigBit clock = sigmap(cell->getPort(ID::C)); + auto r = clk_to_mergeability.insert(std::make_pair(clock, clk_to_mergeability.size() + 1)); + int mergeability = r.first->second; log_assert(mergeability > 0); - write_r_buffer(mergeability); + if (cell->type == ID($_DFF_N_)) + write_r_buffer(-mergeability); + else if (cell->type == ID($_DFF_P_)) + write_r_buffer(mergeability); + else log_abort(); Const init = cell->attributes.at(ID::abc9_init, State::Sx); log_assert(GetSize(init) == 1); - if (init == State::S1) + if (init == State::S1) { + if (!nonzero_warned) { + log_warning("Module '%s' contains $_DFF_[NP]_ cell with non-zero initial state -- unsupported by ABC9.\n", log_id(module)); + nonzero_warned = true; + } write_s_buffer(1); + } else if (init == State::S0) write_s_buffer(0); else { @@ -674,7 +669,7 @@ struct XAigerWriter RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); if (holes_module) { std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module, false /* dff_mode */, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); f << "a"; @@ -761,8 +756,8 @@ struct XAigerBackend : public Backend { log(" write_xaiger [options] [filename]\n"); log("\n"); log("Write the top module (according to the (* top *) attribute or if only one module\n"); - log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or"); - log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); + log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_DFF_N_,\n"); + log(" $_DFF_P_, or non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); log("pseudo-outputs. Whitebox contents will be taken from the '$holes'\n"); log("module, if it exists.\n"); log("\n"); @@ -772,10 +767,13 @@ struct XAigerBackend : public Backend { log(" -map \n"); log(" write an extra file with port and box symbols\n"); log("\n"); + log(" -dff\n"); + log(" write $_DFF_[NP]_ cells\n"); + log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { - bool ascii_mode = false; + bool ascii_mode = false, dff_mode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -791,6 +789,10 @@ struct XAigerBackend : public Backend { map_filename = args[++argidx]; continue; } + if (args[argidx] == "-dff") { + dff_mode = true; + continue; + } break; } extra_args(f, filename, args, argidx, !ascii_mode); @@ -808,7 +810,7 @@ struct XAigerBackend : public Backend { if (!top_module->memories.empty()) log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); - XAigerWriter writer(top_module); + XAigerWriter writer(top_module, dff_mode); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From 53fc3ed64563045949bcd52a03d2af586605d523 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Apr 2020 14:31:14 -0700 Subject: aiger: -xaiger to read $_DFF_[NP]_ back with new clocks created according to mergeability class, and init state as cell attr --- frontends/aiger/aigerparse.cc | 25 +++++++++++++++++++++++-- frontends/aiger/aigerparse.h | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 6fda92d73..7e5e6dd2d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -454,6 +454,14 @@ void AigerReader::parse_xaiger() for (unsigned i = 0; i < flopNum; i++) mergeability.emplace_back(parse_xaiger_literal(f)); } + else if (c == 's') { + uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); + flopNum = parse_xaiger_literal(f); + log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); + initial_state.reserve(flopNum); + for (unsigned i = 0; i < flopNum; i++) + initial_state.emplace_back(parse_xaiger_literal(f)); + } else if (c == 'n') { parse_xaiger_literal(f); f >> s; @@ -767,6 +775,7 @@ void AigerReader::post_process() } } + dict mergeability_to_clock; for (uint32_t i = 0; i < flopNum; i++) { RTLIL::Wire *d = outputs[outputs.size() - flopNum + i]; log_assert(d); @@ -778,10 +787,22 @@ void AigerReader::post_process() log_assert(q->port_input); q->port_input = false; - auto ff = module->addCell(NEW_ID, ID($__ABC9_FF_)); + Cell* ff; + int clock_index = mergeability[i]; + if (clock_index < 0) { + ff = module->addCell(NEW_ID, ID($_DFF_N_)); + clock_index = -clock_index; + } + else if (clock_index > 0) + ff = module->addCell(NEW_ID, ID($_DFF_P_)); + else log_abort(); + auto r = mergeability_to_clock.insert(clock_index); + if (r.second) + r.first->second = module->addWire(NEW_ID); + ff->setPort(ID::C, r.first->second); ff->setPort(ID::D, d); ff->setPort(ID::Q, q); - ff->attributes[ID::abc9_mergeability] = mergeability[i]; + ff->attributes[ID::abc9_init] = initial_state[i]; } dict> wideports_cache; diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index 46ac81212..251a24977 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -45,7 +45,7 @@ struct AigerReader std::vector outputs; std::vector bad_properties; std::vector boxes; - std::vector mergeability; + std::vector mergeability, initial_state; AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); -- cgit v1.2.3 From accfc70fc2bcfaa5f9f58e8a113a32e506f5081d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Apr 2020 14:42:43 -0700 Subject: abc9: fix behaviour and help for -box option --- passes/techmap/abc9.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1b3d5ff06..d8f2f0357 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -303,7 +303,7 @@ struct Abc9Pass : public ScriptPass if (help_mode) { run("foreach module in selection"); run(" abc9_ops -write_lut /input.lut", "(skip if '-lut' or '-luts')"); - run(" abc9_ops -write_box /input.box"); + run(" abc9_ops -write_box /input.box", "(skip if '-box')"); run(" write_xaiger -map /input.sym /input.xaig"); run(" abc9_exe [options] -cwd [-lut /input.lut] -box /input.box"); run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); @@ -333,7 +333,8 @@ struct Abc9Pass : public ScriptPass if (!lut_mode) run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); - run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); + if (box_file.empty()) + run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); run_nocheck(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); @@ -349,7 +350,10 @@ struct Abc9Pass : public ScriptPass abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); if (!lut_mode) abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); - abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); + if (box_file.empty()) + abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); + else + abc9_exe_cmd += stringf(" -box %s", box_file.c_str()); run_nocheck(abc9_exe_cmd); run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); run_nocheck("abc9_ops -reintegrate"); -- cgit v1.2.3 From 95763c8d18eec49de3acff5d38a82f54cc25cb1b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 09:38:07 -0700 Subject: abc9_ops: add 'dff' label for auto handling of (* abc9_flop *) boxes --- backends/aiger/xaiger.cc | 10 +- passes/hierarchy/submod.cc | 2 +- passes/techmap/abc9.cc | 89 ++++++- passes/techmap/abc9_ops.cc | 558 +++++++++++++++++++++++----------------- techlibs/common/abc9_model.v | 3 - techlibs/xilinx/abc9_map.v | 354 ------------------------- techlibs/xilinx/abc9_unmap.v | 4 - techlibs/xilinx/cells_sim.v | 8 +- techlibs/xilinx/synth_xilinx.cc | 5 +- 9 files changed, 398 insertions(+), 635 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d014c4ec6..2e2ca7018 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -616,7 +616,6 @@ struct XAigerWriter dict clk_to_mergeability; - bool nonzero_warned = false; for (const auto &i : ff_bits) { const SigBit &d = i.first; const Cell *cell = i.second; @@ -633,15 +632,10 @@ struct XAigerWriter write_r_buffer(mergeability); else log_abort(); - Const init = cell->attributes.at(ID::abc9_init, State::Sx); + Const init = cell->attributes.at(ID::abc9_init); log_assert(GetSize(init) == 1); - if (init == State::S1) { - if (!nonzero_warned) { - log_warning("Module '%s' contains $_DFF_[NP]_ cell with non-zero initial state -- unsupported by ABC9.\n", log_id(module)); - nonzero_warned = true; - } + if (init == State::S1) write_s_buffer(1); - } else if (init == State::S0) write_s_buffer(0); else { diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 2db7cf26b..1f30a5160 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -389,7 +389,7 @@ struct SubmodPass : public Pass { while (did_something) { did_something = false; std::vector queued_modules; - for (auto mod : design->modules()) + for (auto mod : design->selected_modules()) if (handled_modules.count(mod->name) == 0 && design->selected_whole_module(mod->name)) queued_modules.push_back(mod->name); for (auto &modname : queued_modules) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index d8f2f0357..7f3e6abcc 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -151,8 +151,8 @@ struct Abc9Pass : public ScriptPass log(" specified).\n"); log("\n"); log(" -dff\n"); - log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n"); - log(" domains are marked as such and automatically partitioned by ABC.\n"); + log(" also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n"); + log(" domains are supported and automatically partitioned by ABC.\n"); log("\n"); log(" -nocleanup\n"); log(" when this option is used, the temporary files created by this pass\n"); @@ -274,26 +274,74 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { - if (check_label("pre")) { + if (check_label("check")) { run("abc9_ops -check"); + } + + if (check_label("dff", "(only if -dff)")) { + if (dff_mode || help_mode) { + run("abc9_ops -prep_dff_hier"); // derive all used (* abc9_flop *) modules + run("design -stash $abc9"); + run("design -copy-from $abc9 @$abc9_flops"); // copy derived modules in + run("proc"); + run("wbflip"); + run("techmap"); + run("opt"); + run("abc9_ops -prep_dff_map"); // rewrite specify + // TODO: Select fan-in cone $_DFF_[NP]_.Q + run("setattr -set submod \"$abc9_flop\" t:* t:$_DFF_N_ %d t:$_DFF_P_ %d"); + run("submod"); + run("design -copy-to $abc9 *_$abc9_flop"); // copy submod out + run("delete *_$abc9_flop"); + if (help_mode) { + run("foreach module in design"); + run(" cd "); + run(" rename _$abc9_flop _TECHMAP_REPLACE_"); + run(" cd"); + } + else { + // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs + for (auto module : active_design->selected_modules()) { + run(stringf("cd %s", log_id(module->name))); + run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); + run("cd"); + } + } + run("design -stash $abc9_map"); + run("design -load $abc9"); + run("abc9_ops -prep_dff_unmap"); // create $abc9_unmap design + run("techmap -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ + run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); + if (!help_mode) { + // TODO: Need a way to delete saved designs? + auto it = saved_designs.find("$abc9_map"); + delete it->second; + saved_designs.erase(it); + // TODO: Need a way to delete selections + active_design->selection_vars.erase(ID($abc9_flops)); + active_design->selection_vars.erase(ID($abc9_cells)); + } + } + } + + if (check_label("pre")) { run("scc -set_attr abc9_scc_id {}"); if (help_mode) run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); else - run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); + run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : "")); if (help_mode) run("abc9_ops -prep_lut ", "(skip if -lut or -luts)"); else if (!lut_mode) run(stringf("abc9_ops -prep_lut %d", maxlut)); if (help_mode) - run("abc9_ops -prep_box [-dff]", "(skip if -box)"); - else if (box_file.empty()) - run(stringf("abc9_ops -prep_box %s", dff_mode ? "-dff" : "")); + run("abc9_ops -prep_box", "(skip if -box)"); + else if (box_file.empty()) { + run("abc9_ops -prep_box"); + } run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); - if (dff_mode || help_mode) - run("abc9_ops -prep_dff", "(only if -dff)"); run("opt -purge @abc9_holes"); run("aigmap"); run("wbflip @abc9_holes"); @@ -304,10 +352,10 @@ struct Abc9Pass : public ScriptPass run("foreach module in selection"); run(" abc9_ops -write_lut /input.lut", "(skip if '-lut' or '-luts')"); run(" abc9_ops -write_box /input.box", "(skip if '-box')"); - run(" write_xaiger -map /input.sym /input.xaig"); - run(" abc9_exe [options] -cwd [-lut /input.lut] -box /input.box"); + run(" write_xaiger -map /input.sym [-dff] /input.xaig"); + run(" abc9_exe [options] -cwd -lut [/input.lut] -box [/input.box]"); run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); - run(" abc9_ops -reintegrate"); + run(" abc9_ops -reintegrate [-dff]"); } else { auto selected_modules = active_design->selected_modules(); @@ -335,7 +383,7 @@ struct Abc9Pass : public ScriptPass run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); if (box_file.empty()) run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); - run_nocheck(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); + run_nocheck(stringf("write_xaiger -map %s/input.sym %s %s/input.xaig", tempdir_name.c_str(), dff_mode ? "-dff" : "", tempdir_name.c_str())); int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); @@ -356,7 +404,7 @@ struct Abc9Pass : public ScriptPass abc9_exe_cmd += stringf(" -box %s", box_file.c_str()); run_nocheck(abc9_exe_cmd); run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); - run_nocheck("abc9_ops -reintegrate"); + run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : "")); } else log("Don't call ABC as there is nothing to map.\n"); @@ -373,6 +421,19 @@ struct Abc9Pass : public ScriptPass active_design->selection_stack.pop_back(); } } + + if (check_label("post")) { + if (dff_mode || help_mode) { + run("techmap -wb -map %$abc9_unmap", "(only if -dff)"); // techmap user design from submod back to original cell + // ($_DFF_[NP]_ already shorted by -reintegrate) + if (!help_mode) { + // TODO: Need a way to delete saved designs? + auto it = saved_designs.find("$abc9_unmap"); + delete it->second; + saved_designs.erase(it); + } + } + } } } Abc9Pass; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 1345188a4..fe2e5c3ac 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -119,81 +119,127 @@ void mark_scc(RTLIL::Module *module) } } -void prep_dff(RTLIL::Module *module) -{ - auto design = module->design; - log_assert(design); - SigMap assign_map(module); - - typedef SigSpec clkdomain_t; - dict clk_to_mergeability; +void prep_dff_hier(RTLIL::Design *design) +{ + pool seen; + dict selection_vars; + auto r YS_ATTRIBUTE(unused) = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); + log_assert(r.second); + auto r2 YS_ATTRIBUTE(unused) = design->selection_vars.insert(std::make_pair(ID($abc9_cells), RTLIL::Selection(false))); + log_assert(r2.second); + auto &modules_sel = design->selection_vars.at(ID($abc9_flops)); + auto &cells_sel = design->selection_vars.at(ID($abc9_cells)); + + for (auto module : design->selected_modules()) + for (auto cell : module->cells()) { + auto inst_module = design->module(cell->type); + if (inst_module && inst_module->get_bool_attribute(ID::abc9_flop)) { + modules_sel.select(inst_module); + // Derive modules for all instantiations of (* abc9_flop *) + auto derived_type = inst_module->derive(design, cell->parameters); + // And remember one representative cell (for its parameters) + if (modules_sel.selected_modules.insert(derived_type).second) + cells_sel.select(module, cell); + } + } +} - for (auto cell : module->cells()) { - if (cell->type != ID($__ABC9_FF_)) - continue; +void prep_dff_map(RTLIL::Design *design) +{ + for (auto module : design->modules()) { + vector specify_cells; + SigBit D, Q; + for (auto cell : module->cells()) + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { + if (D != SigBit()) + log_error("More than one $_DFF_[NP]_ cell found in module '%s' marked (* abc9_flop *)\n", log_id(module)); + D = cell->getPort(ID::D); + Q = cell->getPort(ID::Q); + + // TODO: Can we avoid doing this? + // Convert (* init *) on $_DFF_[NP]_.Q to (* abc9_init *) attr on cell + log_assert(GetSize(Q.wire) == 1); + auto it = Q.wire->attributes.find(ID::init); + Const init; + if (it != Q.wire->attributes.end()) { + log_assert(GetSize(it->second) == 1); + init = it->second; + Q.wire->attributes.erase(it); + } + else + init = State::Sx; + auto r YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID::abc9_init, init)); + log_assert(r.second); + if (init == State::S1) { + log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(module), log_id(cell->type)); - Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str())); - if (abc9_clock_wire == NULL) - log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module)); - SigSpec abc9_clock = assign_map(abc9_clock_wire); + module->makeblackbox(); - clkdomain_t key(abc9_clock); + auto wire = module->addWire(ID(_TECHMAP_FAIL_)); + wire->set_bool_attribute(ID::keep); + module->connect(wire, State::S1); - auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); - auto r2 = cell->attributes.insert(ID::abc9_mergeability); - log_assert(r2.second); - r2.first->second = r.first->second; + goto continue_outer_loop; + } + } + else if (cell->type.in(ID($specify2), ID($specify3), ID($specrule))) + specify_cells.emplace_back(cell); + if (D == SigBit()) + log_error("$_DFF_[NP]_ cell not found in module '%s' marked (* abc9_flop *)\n", log_id(module)); + + // Rewrite $specify cells that end with $_DFF_[NP]_.Q + // to $_DFF_[NP]_.D since it will be moved into + // the submodule + for (auto cell : specify_cells) { + auto DST = cell->getPort(ID::DST); + DST.replace(Q, D); + cell->setPort(ID::DST, DST); + } +continue_outer_loop: ; } +} - RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str())); - if (holes_module) { - SigMap sigmap(holes_module); - - dict replace; - for (auto cell : holes_module->cells().to_vector()) { - if (!cell->type.in(ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1), ID($_DFF_PP0_), ID($_DFF_PP1_))) - continue; - SigBit D = cell->getPort(ID::D); - SigBit Q = cell->getPort(ID::Q); - // Emulate async control embedded inside $_DFF_* cell with mux in front of D - if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_PN0_))) - D = holes_module->MuxGate(NEW_ID, State::S0, D, cell->getPort(ID::R)); - else if (cell->type.in(ID($_DFF_NN1_), ID($_DFF_PN1_))) - D = holes_module->MuxGate(NEW_ID, State::S1, D, cell->getPort(ID::R)); - else if (cell->type.in(ID($_DFF_NP0_), ID($_DFF_PP0_))) - D = holes_module->MuxGate(NEW_ID, D, State::S0, cell->getPort(ID::R)); - else if (cell->type.in(ID($_DFF_NP1_), ID($_DFF_PP1_))) - D = holes_module->MuxGate(NEW_ID, D, State::S1, cell->getPort(ID::R)); - // Remove the $_DFF_* cell from what needs to be a combinatorial box - holes_module->remove(cell); - Wire *port; - if (GetSize(Q.wire) == 1) - port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); - else - port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); - log_assert(port); - // Prepare to replace "assign = $_DFF_*.Q;" with "assign = $_DFF_*.D;" - // in order to extract just the combinatorial control logic that feeds the box - // (i.e. clock enable, synchronous reset, etc.) - replace.insert(std::make_pair(Q,D)); - // Since `flatten` above would have created wires named ".Q", - // extract the pre-techmap cell name - auto pos = Q.wire->name.str().rfind("."); - log_assert(pos != std::string::npos); - IdString driver = Q.wire->name.substr(0, pos); - // And drive the signal that was previously driven by "DFF.Q" (typically - // used to implement clock-enable functionality) with the ".$abc9_currQ" - // wire (which itself is driven an by input port) we inserted above - Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str())); - log_assert(currQ); - holes_module->connect(Q, currQ); +void prep_dff_unmap(RTLIL::Design *design) +{ + dict derived_to_cell; + const auto &cells_sel = design->selection_vars.at(ID($abc9_cells)); + for (auto &i : cells_sel.selected_members) { + auto module = design->module(i.first); + for (auto cell_name : i.second) { + auto cell = module->cell(cell_name); + log_assert(cell); + auto inst_module = design->module(cell->type); + log_assert(inst_module); + auto derived_type = inst_module->derive(design, cell->parameters); + derived_to_cell.insert(std::make_pair(derived_type, cell)); } + } - for (auto &conn : holes_module->connections_) - conn.second = replace.at(sigmap(conn.second), conn.second); + Design *unmap_design = new Design; + + // Create the reverse techmap rule -- (* abc9_box *) back to flop + for (const auto &i : derived_to_cell) { + auto module_name = i.first; + auto flop_module = design->module(module_name.str() + "_$abc9_flop"); + if (!flop_module) + continue; // May not exist if init = 1'b1 + + auto unmap_module = unmap_design->addModule(flop_module->name); + for (auto port : flop_module->ports) + unmap_module->addWire(port, flop_module->wire(port)); + unmap_module->ports = flop_module->ports; + unmap_module->check(); + + auto orig_cell = i.second; + auto unmap_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, orig_cell->type); + for (const auto &conn : orig_cell->connections()) + unmap_cell->setPort(conn.first, unmap_module->wire(conn.first)); + unmap_cell->parameters = orig_cell->parameters; } + + auto r YS_ATTRIBUTE(unused) = saved_designs.emplace("$abc9_unmap", unmap_design); + log_assert(r.second); } void prep_xaiger(RTLIL::Module *module, bool dff) @@ -208,17 +254,17 @@ void prep_xaiger(RTLIL::Module *module, bool dff) dict> box_ports; for (auto cell : module->cells()) { - if (cell->type == ID($__ABC9_FF_)) + if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) continue; if (cell->has_keep_attr()) continue; - auto inst_module = module->design->module(cell->type); + auto inst_module = design->module(cell->type); bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop); if (abc9_flop && !dff) continue; - if ((inst_module && inst_module->get_bool_attribute(ID::abc9_box)) || abc9_flop) { + if (inst_module && inst_module->get_bool_attribute(ID::abc9_box)) { auto r = box_ports.insert(cell->type); if (r.second) { // Make carry in the last PI, and carry out the last PO @@ -305,15 +351,16 @@ void prep_xaiger(RTLIL::Module *module, bool dff) cell->attributes[ID::abc9_box_seq] = box_count++; - IdString derived_type = box_module->derive(design, cell->parameters); + IdString derived_type; + if (cell->parameters.empty()) + derived_type = cell->type; + else + derived_type = box_module->derive(design, cell->parameters); box_module = design->module(derived_type); auto r = cell_cache.insert(derived_type); auto &holes_cell = r.first->second; if (r.second) { - if (box_module->has_processes()) - Pass::call_on_module(design, box_module, "proc"); - if (box_module->get_bool_attribute(ID::whitebox)) { holes_cell = holes_module->addCell(cell->name, derived_type); @@ -342,21 +389,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff) else if (w->port_output) conn = holes_module->addWire(stringf("%s.%s", derived_type.c_str(), log_id(port_name)), GetSize(w)); } - - // For flops only, create an extra 1-bit input that drives a new wire - // called ".abc9_ff.Q" that is used below - if (box_module->get_bool_attribute(ID::abc9_flop)) { - box_inputs++; - Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - holes_wire->port_id = port_id++; - holes_module->ports.push_back(holes_wire->name); - } - Wire *Q = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str())); - holes_module->connect(Q, holes_wire); - } } else // box_module is a blackbox log_assert(holes_cell == nullptr); @@ -394,7 +426,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) } for (auto cell : module->cells()) { - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY))) + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_), ID($__ABC9_DELAY))) continue; RTLIL::Module* inst_module = module->design->module(cell->type); @@ -540,7 +572,7 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { ofs.close(); } -void prep_box(RTLIL::Design *design, bool dff_mode) +void prep_box(RTLIL::Design *design) { TimingInfo timing; @@ -555,165 +587,153 @@ void prep_box(RTLIL::Design *design, bool dff_mode) dict> box_ports; for (auto module : design->modules()) { - auto abc9_flop = module->get_bool_attribute(ID::abc9_flop); - if (abc9_flop) { - auto r = module->attributes.insert(ID::abc9_box_id); - if (!r.second) - continue; - r.first->second = abc9_box_id++; - - if (dff_mode) { - int num_inputs = 0, num_outputs = 0; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - log_assert(GetSize(wire) == 1); - if (wire->port_input) num_inputs++; - if (wire->port_output) num_outputs++; - } - log_assert(num_outputs == 1); + if (!module->attributes.erase(ID::abc9_box)) + continue; - ss << log_id(module) << " " << r.first->second.as_int(); - ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); - ss << " " << num_inputs+1 << " " << num_outputs << std::endl; + auto r = module->attributes.insert(ID::abc9_box_id); + if (!r.second) + continue; + r.first->second = abc9_box_id++; + + if (module->get_bool_attribute(ID::abc9_flop)) { + int num_inputs = 0, num_outputs = 0; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + log_assert(GetSize(wire) == 1); + if (wire->port_input) num_inputs++; + if (wire->port_output) num_outputs++; + } + log_assert(num_outputs == 1); - ss << "#"; - bool first = true; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - ss << log_id(wire); - } - ss << " abc9_ff.Q" << std::endl; + ss << log_id(module) << " " << r.first->second.as_int(); + ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + ss << " " << num_inputs << " " << num_outputs << std::endl; - auto &t = timing.setup_module(module).required; - first = true; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - log_assert(GetSize(wire) == 1); - auto it = t.find(TimingInfo::NameBit(port_name,0)); - if (it == t.end()) - // Assume that no setup time means zero - ss << 0; - else { - ss << it->second; + ss << "#"; + bool first = true; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << log_id(wire); + } + ss << std::endl; + + auto &t = timing.setup_module(module).required; + first = true; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + log_assert(GetSize(wire) == 1); + auto it = t.find(TimingInfo::NameBit(port_name,0)); + if (it == t.end()) + // Assume that no setup time means zero + ss << 0; + else { + ss << it->second; #ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second); - } -#endif + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), + log_id(port_name), it->second); } - +#endif } - // Last input is 'abc9_ff.Q' - ss << " 0" << std::endl << std::endl; - continue; } + ss << " # $_DFF_[NP]_.D" << std::endl; + ss << std::endl; } else { - if (!module->attributes.erase(ID::abc9_box)) - continue; - - auto r = module->attributes.insert(ID::abc9_box_id); - if (!r.second) - continue; - r.first->second = abc9_box_id++; - } + auto r2 = box_ports.insert(module->name); + if (r2.second) { + // Make carry in the last PI, and carry out the last PO + // since ABC requires it this way + IdString carry_in, carry_out; + for (const auto &port_name : module->ports) { + auto w = module->wire(port_name); + log_assert(w); + if (w->get_bool_attribute(ID::abc9_carry)) { + log_assert(w->port_input != w->port_output); + if (w->port_input) + carry_in = port_name; + else if (w->port_output) + carry_out = port_name; + } + else + r2.first->second.push_back(port_name); + } - auto r = box_ports.insert(module->name); - if (r.second) { - // Make carry in the last PI, and carry out the last PO - // since ABC requires it this way - IdString carry_in, carry_out; - for (const auto &port_name : module->ports) { - auto w = module->wire(port_name); - log_assert(w); - if (w->get_bool_attribute(ID::abc9_carry)) { - log_assert(w->port_input != w->port_output); - if (w->port_input) - carry_in = port_name; - else if (w->port_output) - carry_out = port_name; + if (carry_in != IdString()) { + r2.first->second.push_back(carry_in); + r2.first->second.push_back(carry_out); } - else - r.first->second.push_back(port_name); } - if (carry_in != IdString()) { - r.first->second.push_back(carry_in); - r.first->second.push_back(carry_out); + std::vector inputs, outputs; + for (auto port_name : r2.first->second) { + auto wire = module->wire(port_name); + if (wire->port_input) + for (int i = 0; i < GetSize(wire); i++) + inputs.emplace_back(wire, i); + if (wire->port_output) + for (int i = 0; i < GetSize(wire); i++) + outputs.emplace_back(wire, i); } - } - - std::vector inputs; - std::vector outputs; - for (auto port_name : r.first->second) { - auto wire = module->wire(port_name); - if (wire->port_input) - for (int i = 0; i < GetSize(wire); i++) - inputs.emplace_back(wire, i); - if (wire->port_output) - for (int i = 0; i < GetSize(wire); i++) - outputs.emplace_back(wire, i); - } - - ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int(); - ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); - ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; - - bool first = true; - ss << "#"; - for (const auto &i : inputs) { - if (first) - first = false; - else - ss << " "; - if (GetSize(i.wire) == 1) - ss << log_id(i.wire); - else - ss << log_id(i.wire) << "[" << i.offset << "]"; - } - ss << std::endl; - auto &t = timing.setup_module(module).comb; - if (!abc9_flop && t.empty()) - log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module)); + ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int(); + ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; - for (const auto &o : outputs) { - first = true; + bool first = true; + ss << "#"; for (const auto &i : inputs) { if (first) first = false; else ss << " "; - auto jt = t.find(TimingInfo::BitBit(i,o)); - if (jt == t.end()) - ss << "-"; + if (GetSize(i.wire) == 1) + ss << log_id(i.wire); else - ss << jt->second; + ss << log_id(i.wire) << "[" << i.offset << "]"; } - ss << " # "; - if (GetSize(o.wire) == 1) - ss << log_id(o.wire); - else - ss << log_id(o.wire) << "[" << o.offset << "]"; ss << std::endl; + auto &t = timing.setup_module(module).comb; + if (t.empty()) + log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module)); + + for (const auto &o : outputs) { + first = true; + for (const auto &i : inputs) { + if (first) + first = false; + else + ss << " "; + auto jt = t.find(TimingInfo::BitBit(i,o)); + if (jt == t.end()) + ss << "-"; + else + ss << jt->second; + } + ss << " # "; + if (GetSize(o.wire) == 1) + ss << log_id(o.wire); + else + ss << log_id(o.wire) << "[" << o.offset << "]"; + ss << std::endl; + } + ss << std::endl; } - ss << std::endl; } // ABC expects at least one box @@ -730,7 +750,7 @@ void write_box(RTLIL::Module *module, const std::string &dst) { ofs.close(); } -void reintegrate(RTLIL::Module *module) +void reintegrate(RTLIL::Module *module, bool dff_mode) { auto design = module->design; log_assert(design); @@ -783,7 +803,12 @@ void reintegrate(RTLIL::Module *module) for (auto cell : module->cells().to_vector()) { if (cell->has_keep_attr()) continue; - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) + + if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { + module->connect(cell->getPort(ID::Q), cell->getPort(ID::D)); + module->remove(cell); + } + else if (cell->type.in(ID($_AND_), ID($_NOT_))) module->remove(cell); else if (cell->attributes.erase(ID::abc9_box_seq)) boxes.emplace_back(cell); @@ -797,6 +822,16 @@ void reintegrate(RTLIL::Module *module) std::map cell_stats; for (auto mapped_cell : mapped_mod->cells()) { + if (dff_mode && mapped_cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { + SigBit D = mapped_cell->getPort(ID::D); + SigBit Q = mapped_cell->getPort(ID::Q); + if (D.wire) + D.wire = module->wires_.at(remap_name(D.wire->name)); + Q.wire = module->wires_.at(remap_name(Q.wire->name)); + module->connect(Q, D); + continue; + } + // TODO: Speed up toposort -- we care about NOT ordering only toposort.node(mapped_cell->name); @@ -846,7 +881,7 @@ void reintegrate(RTLIL::Module *module) continue; } - if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) { + if (mapped_cell->type == ID($lut)) { RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); cell->parameters = mapped_cell->parameters; cell->attributes = mapped_cell->attributes; @@ -893,7 +928,11 @@ void reintegrate(RTLIL::Module *module) } RTLIL::Module* box_module = design->module(existing_cell->type); - IdString derived_type = box_module->derive(design, existing_cell->parameters); + IdString derived_type; + if (existing_cell->parameters.empty()) + derived_type = existing_cell->type; + else + derived_type = box_module->derive(design, existing_cell->parameters); RTLIL::Module* derived_module = design->module(derived_type); log_assert(derived_module); log_assert(mapped_cell->type == stringf("$__boxid%d", derived_module->attributes.at(ID::abc9_box_id).as_int())); @@ -1116,6 +1155,21 @@ struct Abc9OpsPass : public Pass { log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n"); log(" (* abc9_carry *) is only given for one input/output port, etc.\n"); log("\n"); + log(" -prep_dff_hier\n"); + log(" derive all cells with a type instantiating an (* abc9_flop *) module.\n"); + log(" store such modules in named selection '$abc9_flops'.\n"); + log("\n"); + log(" -prep_dff_map\n"); + log(" within (* abc9_flop *) modules, move all $specify{2,3}/$specrule cells\n"); + log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n"); + log(" the DFF's 'D' port. this is to prepare such specify cells to be moved into\n"); + log(" a submodule.\n"); + log("\n"); + log(" -prep_dff_unmap\n"); + log(" create a new design '$abc9_unmap' containing techmap rules that map\n"); + log(" *_$abc9_flop cells back into their original (* abc9_flop *) cells\n"); + log(" (including their original parameters).\n"); + log("\n"); log(" -prep_delays\n"); log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); log(" certain required times.\n"); @@ -1136,10 +1190,6 @@ struct Abc9OpsPass : public Pass { log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n"); log(" during -prep_{delays,xaiger,box}.\n"); log("\n"); - log(" -prep_dff\n"); - log(" compute the clock domain and initial value of each flop in the design.\n"); - log(" process the '$holes' module to support clock-enable functionality.\n"); - log("\n"); log(" -prep_lut \n"); log(" pre-compute the lut library by analysing all modules marked with\n"); log(" (* abc9_lut= *).\n"); @@ -1167,7 +1217,7 @@ struct Abc9OpsPass : public Pass { bool check_mode = false; bool prep_delays_mode = false; bool mark_scc_mode = false; - bool prep_dff_mode = false; + bool prep_dff_hier_mode = false, prep_dff_map_mode = false, prep_dff_unmap_mode = false; bool prep_xaiger_mode = false; bool prep_lut_mode = false; bool prep_box_mode = false; @@ -1177,53 +1227,71 @@ struct Abc9OpsPass : public Pass { int maxlut = 0; std::string write_box_dst; + bool valid = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; if (arg == "-check") { check_mode = true; + valid = true; continue; } if (arg == "-mark_scc") { mark_scc_mode = true; + valid = true; + continue; + } + if (arg == "-prep_dff_hier") { + prep_dff_hier_mode = true; + valid = true; continue; } - if (arg == "-prep_dff") { - prep_dff_mode = true; + if (arg == "-prep_dff_map") { + prep_dff_map_mode = true; + valid = true; + continue; + } + if (arg == "-prep_dff_unmap") { + prep_dff_unmap_mode = true; + valid = true; continue; } if (arg == "-prep_xaiger") { prep_xaiger_mode = true; + valid = true; continue; } if (arg == "-prep_delays") { prep_delays_mode = true; + valid = true; continue; } if (arg == "-prep_lut" && argidx+1 < args.size()) { prep_lut_mode = true; maxlut = atoi(args[++argidx].c_str()); - continue; - } - if (arg == "-maxlut" && argidx+1 < args.size()) { + valid = true; continue; } if (arg == "-write_lut" && argidx+1 < args.size()) { write_lut_dst = args[++argidx]; rewrite_filename(write_lut_dst); + valid = true; continue; } if (arg == "-prep_box") { prep_box_mode = true; + valid = true; continue; } if (arg == "-write_box" && argidx+1 < args.size()) { write_box_dst = args[++argidx]; rewrite_filename(write_box_dst); + valid = true; continue; } if (arg == "-reintegrate") { reintegrate_mode = true; + valid = true; continue; } if (arg == "-dff") { @@ -1234,20 +1302,26 @@ struct Abc9OpsPass : public Pass { } extra_args(args, argidx, design); - if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || prep_box_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) - log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); + if (!valid) + log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); - if (dff_mode && !prep_delays_mode && !prep_xaiger_mode && !prep_box_mode) - log_cmd_error("'-dff' option is only relevant for -prep_{delay,xaiger,box}.\n"); + if (dff_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode) + log_cmd_error("'-dff' option is only relevant for -prep_{delay,xaiger} or -reintegrate.\n"); if (check_mode) check(design); + if (prep_dff_hier_mode) + prep_dff_hier(design); + if (prep_dff_map_mode) + prep_dff_map(design); + if (prep_dff_unmap_mode) + prep_dff_unmap(design); if (prep_delays_mode) prep_delays(design, dff_mode); if (prep_lut_mode) prep_lut(design, maxlut); if (prep_box_mode) - prep_box(design, dff_mode); + prep_box(design); for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute(ID::abc9_holes)) @@ -1267,12 +1341,10 @@ struct Abc9OpsPass : public Pass { write_box(mod, write_box_dst); if (mark_scc_mode) mark_scc(mod); - if (prep_dff_mode) - prep_dff(mod); if (prep_xaiger_mode) prep_xaiger(mod, dff_mode); if (reintegrate_mode) - reintegrate(mod); + reintegrate(mod, dff_mode); } } } Abc9OpsPass; diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index c0c5dc2fd..9e8048faf 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -1,6 +1,3 @@ -module \$__ABC9_FF_ (input D, output Q); -endmodule - (* abc9_box *) module \$__ABC9_DELAY (input I, output O); parameter DELAY = 0; diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 81f8a1d42..1d733a650 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -22,360 +22,6 @@ // before invoking the `abc9` pass in order to transform the design into // a format that it understands. -`ifdef DFF_MODE -// For example, (complex) flip-flops are expected to be described as an -// combinatorial box (containing all control logic such as clock enable -// or synchronous resets) followed by a basic D-Q flop. -// Yosys will automatically analyse the simulation model (described in -// cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in -// order to extract the combinatorial control logic left behind. -// Specifically, a simulation model similar to the one below: -// -// ++===================================++ -// || Sim model || -// || /\/\/\/\ || -// D -->>-----< > +------+ || -// R -->>-----< Comb. > |$_DFF_| || -// CE -->>-----< logic >-----| [NP]_|---+---->>-- Q -// || +--< > +------+ | || -// || | \/\/\/\/ | || -// || | | || -// || +----------------------------+ || -// || || -// ++===================================++ -// -// is transformed into: -// -// ++==================++ -// || Comb box || -// || || -// || /\/\/\/\ || -// D -->>-----< > || -// R -->>-----< Comb. > || +-----------+ -// CE -->>-----< logic >--->>-- $Q --|$__ABC9_FF_|--+-->> Q -// abc9_ff.Q +-->>-----< > || +-----------+ | -// | || \/\/\/\/ || | -// | || || | -// | ++==================++ | -// | | -// +-----------------------------------------------+ -// -// The purpose of the following FD* rules are to wrap the flop with: -// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 -// the connectivity of its basic D-Q flop -// (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to -// capture asynchronous behaviour -// (c) a special abc9_ff.clock wire to capture its clock domain and polarity -// (indicated to `abc9' so that it only performs sequential synthesis -// (with reachability analysis) correctly on one domain at a time) -// (d) an (* abc9_init *) attribute on the $__ABC9_FF_ cell capturing its -// initial state -// NOTE: in order to perform sequential synthesis, `abc9' requires that -// the initial value of all flops be zero -// (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback -// into the (combinatorial) FD* cell to facilitate clock-enable behaviour - -module FDRE (output Q, (* techmap_autopurge *) input C, CE, D, R); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_R_INVERTED = 1'b0; - wire QQ, $Q; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDSE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_S_INVERTED(IS_R_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) - ); - end - else begin - assign Q = QQ; - FDRE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_R_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .R(R) - ); - end - endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; -endmodule -module FDRE_1 (output Q, (* techmap_autopurge *) input C, CE, D, R); - parameter [0:0] INIT = 1'b0; - wire QQ, $Q; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDSE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) - ); - end - else begin - assign Q = QQ; - FDRE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .R(R) - ); - end - endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; -endmodule - -module FDSE (output Q, (* techmap_autopurge *) input C, CE, D, S); - parameter [0:0] INIT = 1'b1; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_S_INVERTED = 1'b0; - wire QQ, $Q; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDRE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_R_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) - ); - end - else begin - assign Q = QQ; - FDSE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_S_INVERTED(IS_S_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .S(S) - ); - end endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; -endmodule -module FDSE_1 (output Q, (* techmap_autopurge *) input C, CE, D, S); - parameter [0:0] INIT = 1'b1; - wire QQ, $Q; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDRE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) - ); - end - else begin - assign Q = QQ; - FDSE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .S(S) - ); - end endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; -endmodule - -module FDCE (output Q, (* techmap_autopurge *) input C, CE, D, CLR); - parameter [0:0] INIT = 1'b0; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_CLR_INVERTED = 1'b0; - wire QQ, $Q, $QQ; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDPE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_PRE_INVERTED(IS_CLR_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below - ); - // Since this is an async flop, async behaviour is dealt with here - $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); - end - else begin - assign Q = QQ; - FDCE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_CLR_INVERTED(IS_CLR_INVERTED) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below - ); - // Since this is an async flop, async behaviour is dealt with here - $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); - end endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; -endmodule -module FDCE_1 (output Q, (* techmap_autopurge *) input C, CE, D, CLR); - parameter [0:0] INIT = 1'b0; - wire QQ, $Q, $QQ; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDPE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below - ); - $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ)); - end - else begin - assign Q = QQ; - FDCE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below - ); - $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ)); - end endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; -endmodule - -module FDPE (output Q, (* techmap_autopurge *) input C, CE, D, PRE); - parameter [0:0] INIT = 1'b1; - parameter [0:0] IS_C_INVERTED = 1'b0; - parameter [0:0] IS_D_INVERTED = 1'b0; - parameter [0:0] IS_PRE_INVERTED = 1'b0; - wire QQ, $Q, $QQ; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDCE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_CLR_INVERTED(IS_PRE_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below - ); - $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); - end - else begin - assign Q = QQ; - FDPE #( - .INIT(1'b0), - .IS_C_INVERTED(IS_C_INVERTED), - .IS_D_INVERTED(IS_D_INVERTED), - .IS_PRE_INVERTED(IS_PRE_INVERTED), - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below - ); - $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); - end endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; -endmodule -module FDPE_1 (output Q, (* techmap_autopurge *) input C, CE, D, PRE); - parameter [0:0] INIT = 1'b1; - wire QQ, $Q, $QQ; - generate if (INIT == 1'b1) begin - assign Q = ~QQ; - FDCE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below - ); - $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ)); - end - else begin - assign Q = QQ; - FDPE_1 #( - .INIT(1'b0) - ) _TECHMAP_REPLACE_ ( - .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below - ); - $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ)); - end endgenerate - (* abc9_init = 1'b0 *) - $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); - - // Special signals - wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; - wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; -endmodule -`endif - // Attach a (combinatorial) black-box onto the output // of thes LUTRAM primitives to capture their // asynchronous read behaviour diff --git a/techlibs/xilinx/abc9_unmap.v b/techlibs/xilinx/abc9_unmap.v index 5604ceb0a..49a7bd88c 100644 --- a/techlibs/xilinx/abc9_unmap.v +++ b/techlibs/xilinx/abc9_unmap.v @@ -25,10 +25,6 @@ module $__ABC9_ASYNC01(input A, S, output Y); assign Y = A; endmodule -module $__ABC9_FF_(input D, output Q); - assign Q = D; -endmodule - module $__ABC9_RAM6(input A, input [5:0] S, output Y); assign Y = A; endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 63223afbf..93d080ffd 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -640,7 +640,7 @@ module FDRSE ( Q <= d; endmodule -(* abc9_flop, lib_whitebox *) +(* lib_whitebox *) module FDCE ( output reg Q, (* clkbuf_sink *) @@ -683,7 +683,7 @@ module FDCE ( endspecify endmodule -(* abc9_flop, lib_whitebox *) +(* lib_whitebox *) module FDCE_1 ( output reg Q, (* clkbuf_sink *) @@ -708,7 +708,7 @@ module FDCE_1 ( endspecify endmodule -(* abc9_flop, lib_whitebox *) +(* lib_whitebox *) module FDPE ( output reg Q, (* clkbuf_sink *) @@ -750,7 +750,7 @@ module FDPE ( endspecify endmodule -(* abc9_flop, lib_whitebox *) +(* lib_whitebox *) module FDPE_1 ( output reg Q, (* clkbuf_sink *) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 229ffcb3d..173bdcb91 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -613,10 +613,7 @@ struct SynthXilinxPass : public ScriptPass if (family != "xc7") log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " "will use timing for 'xc7' instead.\n", family.c_str()); - std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1"; - if (dff_mode) - techmap_args += " -D DFF_MODE"; - run("techmap " + techmap_args); + run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); run("read_verilog -icells -lib -specify +/abc9_model.v +/xilinx/abc9_model.v"); std::string abc9_opts; std::string k = "synth_xilinx.abc9.W"; -- cgit v1.2.3 From 77f3abcdc30e21b4359c2b07c20b63bdac5993bf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 13:10:57 -0700 Subject: xaiger: when -dff use (* init *) for initial state --- backends/aiger/xaiger.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2e2ca7018..5d15df310 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -79,6 +79,7 @@ struct XAigerWriter Module *module; SigMap sigmap; + dict init_map; pool input_bits, output_bits; dict not_map, alias_map; dict> and_map; @@ -157,7 +158,8 @@ struct XAigerWriter if (wire->get_bool_attribute(ID::keep)) sigmap.add(wire); - for (auto wire : module->wires()) + for (auto wire : module->wires()) { + auto it = wire->attributes.find(ID::init); for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -184,7 +186,17 @@ struct XAigerWriter alias_map[wirebit] = bit; output_bits.insert(wirebit); } + + if (it != wire->attributes.end()) { + auto s = it->second[i]; + if (s != State::Sx) { + auto r = init_map.insert(std::make_pair(bit, it->second[i])); + if (!r.second && r.first->second != it->second[i]) + log_error("Bit '%s' has a conflicting (* init *) value.\n", log_signal(bit)); + } + } } + } TimingInfo timing; @@ -632,8 +644,8 @@ struct XAigerWriter write_r_buffer(mergeability); else log_abort(); - Const init = cell->attributes.at(ID::abc9_init); - log_assert(GetSize(init) == 1); + SigBit Q = sigmap(cell->getPort(ID::Q)); + State init = init_map.at(Q, State::Sx); if (init == State::S1) write_s_buffer(1); else if (init == State::S0) -- cgit v1.2.3 From 483a190c1b468b2a22fe7f2b92075953c6095f7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 13:11:25 -0700 Subject: aiger: -xaiger to parse initial state back into (* init *) on Q wire --- frontends/aiger/aigerparse.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 7e5e6dd2d..ed3a926c6 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -802,7 +802,8 @@ void AigerReader::post_process() ff->setPort(ID::C, r.first->second); ff->setPort(ID::D, d); ff->setPort(ID::Q, q); - ff->attributes[ID::abc9_init] = initial_state[i]; + log_assert(GetSize(q) == 1); + q->attributes[ID::init] = initial_state[i]; } dict> wideports_cache; -- cgit v1.2.3 From edacb8f437bd1d3c61a12dfa35214e3a1d47af99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 13:12:37 -0700 Subject: abc9_ops: do not use (* abc9_init *) --- passes/techmap/abc9_ops.cc | 47 ++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index fe2e5c3ac..2ad082d38 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -157,20 +157,11 @@ void prep_dff_map(RTLIL::Design *design) D = cell->getPort(ID::D); Q = cell->getPort(ID::Q); - // TODO: Can we avoid doing this? - // Convert (* init *) on $_DFF_[NP]_.Q to (* abc9_init *) attr on cell + // Block sequential synthesis on cells with (* init = 1 *) + // because ABC9 doesn't support them log_assert(GetSize(Q.wire) == 1); - auto it = Q.wire->attributes.find(ID::init); - Const init; - if (it != Q.wire->attributes.end()) { - log_assert(GetSize(it->second) == 1); - init = it->second; - Q.wire->attributes.erase(it); - } - else - init = State::Sx; - auto r YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID::abc9_init, init)); - log_assert(r.second); + Const init = Q.wire->attributes.at(ID::init, State::Sx); + log_assert(GetSize(init) == 1); if (init == State::S1) { log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(module), log_id(cell->type)); @@ -226,8 +217,10 @@ void prep_dff_unmap(RTLIL::Design *design) continue; // May not exist if init = 1'b1 auto unmap_module = unmap_design->addModule(flop_module->name); - for (auto port : flop_module->ports) - unmap_module->addWire(port, flop_module->wire(port)); + for (auto port : flop_module->ports) { + auto w = unmap_module->addWire(port, flop_module->wire(port)); + w->attributes.erase(ID::init); + } unmap_module->ports = flop_module->ports; unmap_module->check(); @@ -757,6 +750,17 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) map_autoidx = autoidx++; + // TODO: Get rid of this expensive lookup + dict> sig2inits; + SigMap sigmap(module); + for (auto w : module->wires()) { + auto it = w->attributes.find(ID::init); + if (it == w->attributes.end()) + continue; + for (const auto &b : SigSpec(w)) + sig2inits[sigmap(b)].emplace_back(b); + } + RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name.c_str())); if (mapped_mod == NULL) log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module)); @@ -764,6 +768,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) for (auto w : mapped_mod->wires()) { auto nw = module->addWire(remap_name(w->name), GetSize(w)); nw->start_offset = w->start_offset; + // Remove all (* init *) since they only existon $_DFF_[NP]_ + w->attributes.erase(ID::init); } dict> box_ports; @@ -804,8 +810,15 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) if (cell->has_keep_attr()) continue; + // Short out $_DFF_[NP]_ cells since the flop box already has + // all the information we need to reconstruct cell if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - module->connect(cell->getPort(ID::Q), cell->getPort(ID::D)); + SigBit Q = cell->getPort(ID::Q); + auto it = sig2inits.find(Q); + if (it != sig2inits.end()) + for (const auto &b : it->second) + b.wire->attributes.at(ID::init)[b.offset] = State::Sx; + module->connect(Q, cell->getPort(ID::D)); module->remove(cell); } else if (cell->type.in(ID($_AND_), ID($_NOT_))) @@ -822,6 +835,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) std::map cell_stats; for (auto mapped_cell : mapped_mod->cells()) { + // Short out $_DFF_[NP]_ cells since the flop box already has + // all the information we need to reconstruct cell if (dff_mode && mapped_cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { SigBit D = mapped_cell->getPort(ID::D); SigBit Q = mapped_cell->getPort(ID::Q); -- cgit v1.2.3 From 6b3aa91a2a1f717ebf4ce7155b134e9d556ac1ab Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 13:12:45 -0700 Subject: abc9: cleanup --- passes/techmap/abc9.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 7f3e6abcc..97ee57aaa 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -295,16 +295,13 @@ struct Abc9Pass : public ScriptPass run("delete *_$abc9_flop"); if (help_mode) { run("foreach module in design"); - run(" cd "); run(" rename _$abc9_flop _TECHMAP_REPLACE_"); - run(" cd"); } else { // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs for (auto module : active_design->selected_modules()) { - run(stringf("cd %s", log_id(module->name))); + active_design->selected_active_module = module->name.str(); run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); - run("cd"); } } run("design -stash $abc9_map"); -- cgit v1.2.3 From 90cd49995b9bf18c4b6e7e7bbea237617753b29b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 16:20:15 -0700 Subject: xaiger: do not treat (* init=1'bx *) as 1'b0 --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5d15df310..1006d56c6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -652,7 +652,7 @@ struct XAigerWriter write_s_buffer(0); else { log_assert(init == State::Sx); - write_s_buffer(0); + write_s_buffer(2); } // Use arrival time from output of flop box -- cgit v1.2.3 From c10757a8ea5d6052d7a06690fb7411b5e4c7d772 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 16:21:08 -0700 Subject: synth_xilinx: rename dff_mode -> dff --- techlibs/xilinx/synth_xilinx.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 173bdcb91..c45d389ef 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -143,7 +143,7 @@ struct SynthXilinxPass : public ScriptPass std::string top_opt, edif_file, blif_file, family; bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; - bool abc9, dff_mode; + bool abc9, dff; bool flatten_before_abc; int widemux; int lut_size; @@ -170,7 +170,7 @@ struct SynthXilinxPass : public ScriptPass nodsp = false; uram = false; abc9 = false; - dff_mode = false; + dff = false; flatten_before_abc = false; widemux = 0; lut_size = 6; @@ -217,7 +217,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-retime") { - dff_mode = true; + dff = true; retime = true; continue; } @@ -281,7 +281,7 @@ struct SynthXilinxPass : public ScriptPass continue; } if (args[argidx] == "-dff") { - dff_mode = true; + dff = true; continue; } break; @@ -595,9 +595,11 @@ struct SynthXilinxPass : public ScriptPass run("clean"); } - if (check_label("map_ffs")) { + if (check_label("map_ffs", "('-abc9' only)")) { if (abc9 || help_mode) { - run("techmap -map " + ff_map_file, "('-abc9' only)"); + if (dff || help_mode) + run("zinit -all", "('-dff' only)"); + run("techmap -map " + ff_map_file); } } @@ -625,7 +627,7 @@ struct SynthXilinxPass : public ScriptPass } if (nowidelut) abc9_opts += stringf(" -maxlut %d", lut_size); - if (dff_mode) + if (dff) abc9_opts += " -dff"; run("abc9" + abc9_opts); run("techmap -map +/xilinx/abc9_unmap.v"); @@ -645,7 +647,7 @@ struct SynthXilinxPass : public ScriptPass else abc_opts += " -luts 2:2,3,6:5,10,20,40"; } - if (dff_mode) + if (dff) abc_opts += " -dff"; if (retime) abc_opts += " -D 1"; -- cgit v1.2.3 From a1ae5845f83f12f2893c48c23c377aea25c1b280 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 17:30:29 -0700 Subject: abc9_ops: -prep_dff_map to cope with plain $_DFF_[NP]_ flops --- passes/techmap/abc9_ops.cc | 51 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 2ad082d38..cf3bd689e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -134,13 +134,22 @@ void prep_dff_hier(RTLIL::Design *design) for (auto module : design->selected_modules()) for (auto cell : module->cells()) { auto inst_module = design->module(cell->type); - if (inst_module && inst_module->get_bool_attribute(ID::abc9_flop)) { - modules_sel.select(inst_module); + if (inst_module && inst_module->attributes.count(ID::abc9_flop)) { + if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) + log_error("Module '%s' with (* abc9_flop *) is not a whitebox.\n", log_id(inst_module)); // Derive modules for all instantiations of (* abc9_flop *) auto derived_type = inst_module->derive(design, cell->parameters); + auto derived_module = design->module(derived_type); + if (!derived_module->get_bool_attribute(ID::abc9_flop)) + continue; // And remember one representative cell (for its parameters) - if (modules_sel.selected_modules.insert(derived_type).second) + if (!modules_sel.selected_whole_module(derived_type)) { + if (derived_type != cell->type) + modules_sel.select(inst_module); + + modules_sel.select(derived_module); cells_sel.select(module, cell); + } } } } @@ -150,19 +159,20 @@ void prep_dff_map(RTLIL::Design *design) for (auto module : design->modules()) { vector specify_cells; SigBit D, Q; + Cell* dff_cell = nullptr; for (auto cell : module->cells()) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - if (D != SigBit()) + if (dff_cell) log_error("More than one $_DFF_[NP]_ cell found in module '%s' marked (* abc9_flop *)\n", log_id(module)); - D = cell->getPort(ID::D); - Q = cell->getPort(ID::Q); + dff_cell = cell; - // Block sequential synthesis on cells with (* init = 1 *) + // Block sequential synthesis on cells with (* init *) != 1'b0 // because ABC9 doesn't support them + Q = cell->getPort(ID::Q); log_assert(GetSize(Q.wire) == 1); Const init = Q.wire->attributes.at(ID::init, State::Sx); log_assert(GetSize(init) == 1); - if (init == State::S1) { + if (init != State::S0) { log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(module), log_id(cell->type)); module->makeblackbox(); @@ -176,9 +186,26 @@ void prep_dff_map(RTLIL::Design *design) } else if (cell->type.in(ID($specify2), ID($specify3), ID($specrule))) specify_cells.emplace_back(cell); - if (D == SigBit()) + if (!dff_cell) log_error("$_DFF_[NP]_ cell not found in module '%s' marked (* abc9_flop *)\n", log_id(module)); + D = dff_cell->getPort(ID::D); + + // Add a dummy enable mux feeding DFF.D to ensure that: + // (i) a driving cell exists, so that 'submod' will have + // an output port + // (ii) DFF.Q will exist in this submodule + { + auto c = module->addCell(NEW_ID, ID($_MUX_)); + auto w = module->addWire(NEW_ID); + c->setPort(ID::A, D); + c->setPort(ID::B, Q); + c->setPort(ID::S, State::S0); + c->setPort(ID::Y, w); + dff_cell->setPort(ID::D, w); + D = w; + } + // Rewrite $specify cells that end with $_DFF_[NP]_.Q // to $_DFF_[NP]_.D since it will be moved into // the submodule @@ -253,7 +280,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) continue; auto inst_module = design->module(cell->type); - bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop); + bool abc9_flop = inst_module && inst_module->attributes.count(ID::abc9_flop); if (abc9_flop && !dff) continue; @@ -339,7 +366,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(cell); RTLIL::Module* box_module = design->module(cell->type); - if (!box_module || (!box_module->get_bool_attribute(ID::abc9_box) && !box_module->get_bool_attribute(ID::abc9_flop))) + if (!box_module || !box_module->get_bool_attribute(ID::abc9_box)) continue; cell->attributes[ID::abc9_box_seq] = box_count++; @@ -967,7 +994,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) SigSpec outputs = std::move(jt->second); mapped_cell->connections_.erase(jt); - auto abc9_flop = box_module->attributes.count(ID::abc9_flop); + auto abc9_flop = box_module->get_bool_attribute(ID::abc9_flop); if (!abc9_flop) { for (const auto &i : inputs) bit_users[i].insert(mapped_cell->name); -- cgit v1.2.3 From 4a10c87ae1916fb1d19b7bb0adebd54a5b15cf30 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 17:31:44 -0700 Subject: ice40: split out cells_map.v into ff_map.v --- techlibs/ice40/Makefile.inc | 1 + techlibs/ice40/cells_map.v | 31 ------------------------------- techlibs/ice40/ff_map.v | 28 ++++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 31 deletions(-) create mode 100644 techlibs/ice40/ff_map.v diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index b9e504a9d..1a8caf9a9 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -23,6 +23,7 @@ techlibs/ice40/brams_init3.vh: techlibs/ice40/brams_init.mk $(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v)) +$(eval $(call add_share_file,share/ice40,techlibs/ice40/ff_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v index d5362eb83..e9ccca239 100644 --- a/techlibs/ice40/cells_map.v +++ b/techlibs/ice40/cells_map.v @@ -1,33 +1,3 @@ -module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule -module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule - -module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule -module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule - -module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule -module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule - -module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule - -module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule - -module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule -module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule -module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule -module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule - -module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule -module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule -module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule -module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule - -`ifndef NO_LUT module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; @@ -59,4 +29,3 @@ module \$lut (A, Y); end endgenerate endmodule -`endif diff --git a/techlibs/ice40/ff_map.v b/techlibs/ice40/ff_map.v new file mode 100644 index 000000000..e8807e0bd --- /dev/null +++ b/techlibs/ice40/ff_map.v @@ -0,0 +1,28 @@ +module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule +module \$_DFF_P_ (input D, C, output Q); SB_DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule + +module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule +module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule + +module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule +module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule + +module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule +module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule +module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule + +module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule +module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule +module \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule -- cgit v1.2.3 From fe7965e0eeb7dacf1453ff6cfc1783c8c39c8201 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 17:32:21 -0700 Subject: ice40: add synth_ice40 -dff option, support with -abc9 --- techlibs/ice40/cells_sim.v | 13 +++++++++++++ techlibs/ice40/synth_ice40.cc | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 5d107989d..1b759a28f 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -245,6 +245,7 @@ endmodule // Positive Edge SiliconBlue FF Cells +(* abc9_flop, lib_whitebox *) module SB_DFF ( output `SB_DFF_REG, input C, D @@ -280,6 +281,7 @@ module SB_DFF ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFE ( output `SB_DFF_REG, input C, E, D @@ -322,6 +324,7 @@ module SB_DFFE ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFSR ( output `SB_DFF_REG, input C, R, D @@ -419,6 +422,7 @@ module SB_DFFR ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFSS ( output `SB_DFF_REG, input C, S, D @@ -516,6 +520,7 @@ module SB_DFFS ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFESR ( output `SB_DFF_REG, input C, E, R, D @@ -627,6 +632,7 @@ module SB_DFFER ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFESS ( output `SB_DFF_REG, input C, E, S, D @@ -740,6 +746,7 @@ endmodule // Negative Edge SiliconBlue FF Cells +(* abc9_flop, lib_whitebox *) module SB_DFFN ( output `SB_DFF_REG, input C, D @@ -775,6 +782,7 @@ module SB_DFFN ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFNE ( output `SB_DFF_REG, input C, E, D @@ -817,6 +825,7 @@ module SB_DFFNE ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFNSR ( output `SB_DFF_REG, input C, R, D @@ -864,6 +873,7 @@ module SB_DFFNSR ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFNR ( output `SB_DFF_REG, input C, R, D @@ -914,6 +924,7 @@ module SB_DFFNR ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFNSS ( output `SB_DFF_REG, input C, S, D @@ -1011,6 +1022,7 @@ module SB_DFFNS ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFNESR ( output `SB_DFF_REG, input C, E, R, D @@ -1122,6 +1134,7 @@ module SB_DFFNER ( `endif endmodule +(* abc9_flop, lib_whitebox *) module SB_DFFNESS ( output `SB_DFF_REG, input C, E, S, D diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 6e05ab0b2..a8bf93db5 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -71,6 +71,9 @@ struct SynthIce40Pass : public ScriptPass log(" -noflatten\n"); log(" do not flatten design before synthesis\n"); log("\n"); + log(" -dff\n"); + log(" run 'abc'/'abc9' with -dff option\n"); + log("\n"); log(" -retime\n"); log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); @@ -113,7 +116,7 @@ struct SynthIce40Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file, device_opt; - bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, flowmap; + bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap; int min_ce_use; void clear_flags() YS_OVERRIDE @@ -221,6 +224,10 @@ struct SynthIce40Pass : public ScriptPass abc9 = true; continue; } + if (args[argidx] == "-dff") { + dff = true; + continue; + } if (args[argidx] == "-device" && argidx+1 < args.size()) { device_opt = args[++argidx]; continue; @@ -354,7 +361,9 @@ struct SynthIce40Pass : public ScriptPass run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); run("simplemap t:$dff"); } - run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v"); + if ((abc9 && dff) || help_mode) + run("zinit -all", "(-abc9 and -dff only)"); + run("techmap -map +/ice40/ff_map.v"); run("opt_expr -mux_undef"); run("simplemap"); run("ice40_ffinit"); @@ -387,23 +396,34 @@ struct SynthIce40Pass : public ScriptPass k = stringf("synth_ice40.abc9.%s.W", device_opt.c_str()); abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); } + if (dff) + abc9_opts += " -dff"; run("abc9 " + abc9_opts); } else - run("abc -dress -lut 4", "(skip if -noabc)"); + run(stringf("abc -dress -lut 4 %s", dff ? "-dff" : ""), "(skip if -noabc)"); } run("ice40_wrapcarry -unwrap"); - run("techmap -D NO_LUT -map +/ice40/cells_map.v"); + run("techmap -map +/ice40/ff_map.v"); run("clean"); run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); } if (check_label("map_cells")) { - if (vpr) - run("techmap -D NO_LUT -map +/ice40/cells_map.v"); - else - run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)"); + if (help_mode) + run("techmap [-map +/ice40/ff_map.v] [-map +/ice40/cells_map.v]", "(skip if -abc9; skip if -vpr)"); + else if (vpr) + run("techmap -map +/ice40/ff_map.v"); + else { + std::string techmap_args; + if (!abc9) + techmap_args += " -map +/ice40/ff_map.v"; + if (!vpr) + techmap_args += " -map +/ice40/cells_map.v"; + if (!techmap_args.empty()) + run("techmap " + techmap_args); + } run("clean"); } -- cgit v1.2.3 From 039c3a59826de4410dd9257262430729fb0b4000 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 13 Apr 2020 19:08:46 -0700 Subject: kernel: Module::makeblackbox() to clear connections + delete wires last --- kernel/rtlil.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 196e301b6..3e5896813 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -776,6 +776,7 @@ void RTLIL::Module::makeblackbox() connections_.clear(); remove(delwires); + set_bool_attribute(ID::blackbox); } -- cgit v1.2.3 From 5d5029fa75b8cb37c07fc15a0429e28fe317b472 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 07:31:07 -0700 Subject: ecp5: replace ecp5_ffinit with techmap rules + dff2dffs -match-init --- techlibs/ecp5/Makefile.inc | 3 +- techlibs/ecp5/cells_map.v | 278 ++++++++++++++++++++++++++++++++++---------- techlibs/ecp5/synth_ecp5.cc | 3 +- 3 files changed, 220 insertions(+), 64 deletions(-) diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 217151e96..6bc9c854e 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -1,6 +1,5 @@ -OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \ - techlibs/ecp5/ecp5_gsr.o +OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_gsr.o GENFILES += techlibs/ecp5/bram_init_1_2_4.vh GENFILES += techlibs/ecp5/bram_init_9_18_36.vh diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index c031703a9..f8df08eab 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -1,65 +1,223 @@ -module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule -module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule - -module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule -module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule - -module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule -module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule - -module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule - -module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule - -module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule - -module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule - -module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) +module \$_DFF_x_ (input D, C, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + if (_TECHMAP_WIREINIT_Q_ === 1'b1) + localparam REGSET = "SET"; + else + localparam REGSET = "RESET"; + endgenerate + TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET)) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); +endmodule + +(* techmap_celltype = "$_DFFE_NN_ $_DFFE_PN_ $_DFFE_NP_ $_DFFE_PP_" *) +module \$_DFFE_xx_ (input D, C, E, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") + localparam CEMUX = "INV"; + else + localparam CEMUX = "CE"; + if (_TECHMAP_WIREINIT_Q_ === 1'b1) + localparam REGSET = "SET"; + else + localparam REGSET = "RESET"; + endgenerate + TRELLIS_FF #(.GSR("AUTO"), .CEMUX(CEMUX), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET)) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); +endmodule + +(* techmap_celltype = "$_DFF_NN0_ $_DFF_NN1_ $_DFF_PN0_ $_DFF_PN1_ $_DFF_NP0_ $_DFF_NP1_ $_DFF_PP0_ $_DFF_PP1_" *) +module \$_DFF_xxx_ (input D, C, R, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + // TODO: Why not use LSRMUX param? + if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") + wire LSR_ = !R; + else + wire LSR_ = R; + if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin + localparam REGSET = "SET"; + if (_TECHMAP_WIREINIT_Q_ === 1'b0) + $error("ECP5 doesn't support FFs with asynchronous set initialized to 0"); + end + else begin + localparam REGSET = "RESET"; + if (_TECHMAP_WIREINIT_Q_ === 1'b1) + $error("ECP5 doesn't support FFs with asynchronous reset initialized to 1"); + end + endgenerate + TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(LSR_), .DI(D), .Q(Q)); +endmodule + +(* techmap_celltype = "$__DFFS_NN0_ $__DFFS_NN1_ $__DFFS_PN0_ $__DFFS_PN1_ $__DFFS_NP0_ $__DFFS_NP1_ $__DFFS_PP0_ $__DFFS_PP1_" *) +module \$__DFFS_xxx_ (input D, C, R, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + // TODO: Why not use LSRMUX param? + if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") + wire LSR_ = !R; + else + wire LSR_ = R; + if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin + localparam REGSET = "SET"; + if (_TECHMAP_WIREINIT_Q_ === 1'b0) + // init is 0, reset to 1 + wire D_ = D || LSR_; + else + wire D_ = D; + end + else begin + localparam REGSET = "RESET"; + if (_TECHMAP_WIREINIT_Q_ === 1'b1) + // init is 1, reset to 0 + wire D_ = !(D && LSR_); + else + wire D_ = D; + end + endgenerate + TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(LSR_), .DI(D_), .Q(Q)); +endmodule + +(* techmap_celltype = "$__DFFE_NN0 $__DFFE_NN1 $__DFFE_PN0 $__DFFE_PN1 $__DFFE_NP0 $__DFFE_NP1 $__DFFE_PP0 $__DFFE_PP1" *) +module \$__DFFE_xxx_ (input D, C, E, R, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + // TODO: Why not use LSRMUX param? + if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") + wire LSR_ = !R; + else + wire LSR_ = R; + if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin + if (_TECHMAP_WIREINIT_Q_ === 1'b0) + $error("ECP5 doesn't support FFs with asynchronous set initialized to 0"); + else + localparam REGSET = "SET"; + end + else begin + if (_TECHMAP_WIREINIT_Q_ === 1'b1) + $error("ECP5 doesn't support FFs with asynchronous reset initialized to 1"); + else + localparam REGSET = "RESET"; + end + endgenerate + TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(LSR_), .DI(D), .Q(Q)); +endmodule + +(* techmap_celltype = "$__DFFSE_NN0 $__DFFSE_NN1 $__DFFSE_PN0 $__DFFSE_PN1 $__DFFSE_NP0 $__DFFSE_NP1 $__DFFSE_PP0 $__DFFSE_PP1" *) +module \$__DFFSE_xxx_ (input D, C, E, R, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + // TODO: Why not use LSRMUX param? + if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") + wire LSR_ = !R; + else + wire LSR_ = R; + if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin + localparam REGSET = "SET"; + if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin + // init is 0, reset to 1 + wire D_ = D || LSR_; + wire E_ = E || LSR_; + end + else begin + wire D_ = D; + wire E_ = E; + end + end + else begin + localparam REGSET = "RESET"; + if (_TECHMAP_WIREINIT_Q_ === 1'b1) begin + // init is 1, reset to 0 + wire D_ = !(D && LSR_); + wire E_ = !(E && LSR_); + end + else begin + wire D_ = D; + wire E_ = E; + end + end + endgenerate + TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E_), .LSR(LSR_), .DI(D_), .Q(Q)); +endmodule `ifdef ASYNC_PRLD -module \$_DLATCH_N_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(!E), .DI(1'b0), .M(D), .Q(Q)); endmodule -module \$_DLATCH_P_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(E), .DI(1'b0), .M(D), .Q(Q)); endmodule - -module \$_DFFSR_NNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_NNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule -module \$_DFFSR_NPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_NPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule - -module \$_DFFSR_PNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_PNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule -module \$_DFFSR_PPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule -module \$_DFFSR_PPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule +(* techmap_celltype = "$_DLATCH_N_ $_DLATCH_P_" *) +module \$_DLATCH_x_ (input E, input D, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + // TODO: Why not use LSRMUX param? + if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") + wire LSR_ = !E; + else + wire LSR_ = E; + if (_TECHMAP_WIREINIT_Q_ !== 1'bx) + $error("ECP5 doesn't support latches with initial values"); // TODO: Check + endgenerate + TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(LSR_), .DI(1'b0), .M(D), .Q(Q)); +endmodule + +(* techmap_celltype = "$_DFFSR_NNN_ $_DFFSR_NNP_ $_DFFSR_PNN_ $_DFFSR_PNP_ $_DFFSR_NPN_ $_DFFSR_NPP_ $_DFFSR_PPN_ $_DFFSR_PPP_" *) +module \$_DFFSR_xxx_ (input C, S, R, D, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; + generate + if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") + localparam CLKMUX = "INV"; + else + localparam CLKMUX = "CLK"; + if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") + wire S_ = !S; + else + wire S_ = S; + if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") + wire R_ = !R; + else + wire R_ = R; + if (_TECHMAP_WIREINIT_Q_ !== 1'bx) + $error("ECP5 doesn't support FFs with asynchronous set and reset with initial values"); + endgenerate + + TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX(CLKINV), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S_ || R_), .DI(D), .M(!R_), .Q(Q)); +endmodule `endif `include "cells_ff.vh" diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index b9b236a0c..5f00d3d4e 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -303,14 +303,13 @@ struct SynthEcp5Pass : public ScriptPass if (check_label("map_ffs")) { - run("dff2dffs"); + run("dff2dffs -match-init"); run("opt_clean"); if (!nodffe) run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); run("opt_expr -undriven -mux_undef"); run("simplemap"); - run("ecp5_ffinit"); run("ecp5_gsr"); run("attrmvcp -copy -attr syn_useioff"); run("opt_clean"); -- cgit v1.2.3 From 23c53a6bdde645ef475752e24e7751beb20a3121 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 07:48:37 -0700 Subject: ice40: synth_ice40 cleanup --- techlibs/ice40/synth_ice40.cc | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index a8bf93db5..376cb7dbd 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -412,19 +412,9 @@ struct SynthIce40Pass : public ScriptPass if (check_label("map_cells")) { if (help_mode) - run("techmap [-map +/ice40/ff_map.v] [-map +/ice40/cells_map.v]", "(skip if -abc9; skip if -vpr)"); - else if (vpr) - run("techmap -map +/ice40/ff_map.v"); - else { - std::string techmap_args; - if (!abc9) - techmap_args += " -map +/ice40/ff_map.v"; - if (!vpr) - techmap_args += " -map +/ice40/cells_map.v"; - if (!techmap_args.empty()) - run("techmap " + techmap_args); - } - + run("techmap -map +/ice40/cells_map.v", "(skip if -vpr)"); + else if (!vpr) + run("techmap -map +/ice40/cells_map.v"); run("clean"); } -- cgit v1.2.3 From e38b1280f9752d22c6d2a5803bec6a6cedf12a10 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 07:49:55 -0700 Subject: abc9_ops: -prep_dff_map to warn if no specify cells --- passes/techmap/abc9_ops.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index cf3bd689e..c640d06f8 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -206,13 +206,18 @@ void prep_dff_map(RTLIL::Design *design) D = w; } - // Rewrite $specify cells that end with $_DFF_[NP]_.Q - // to $_DFF_[NP]_.D since it will be moved into - // the submodule - for (auto cell : specify_cells) { - auto DST = cell->getPort(ID::DST); - DST.replace(Q, D); - cell->setPort(ID::DST, DST); + if (GetSize(specify_cells) == 0) { + log_warning("Module '%s' marked (* abc9_flop *) contains no specify timing information.\n", log_id(module)); + } + else { + // Rewrite $specify cells that end with $_DFF_[NP]_.Q + // to $_DFF_[NP]_.D since it will be moved into + // the submodule + for (auto cell : specify_cells) { + auto DST = cell->getPort(ID::DST); + DST.replace(Q, D); + cell->setPort(ID::DST, DST); + } } continue_outer_loop: ; } -- cgit v1.2.3 From 34c77326420e4f906544e26499683869c47d09aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 07:51:23 -0700 Subject: ecp5: add synth_ecp5 -dff to work with -abc9 --- techlibs/ecp5/cells_sim.v | 21 +++++++++++++++++++++ techlibs/ecp5/synth_ecp5.cc | 38 ++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 12b33e925..69685683f 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -294,6 +294,7 @@ endmodule // --------------------------------------- +(* abc9_flop=(SRMODE != "ASYNC"), lib_whitebox=(SRMODE != "ASYNC") *) module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); parameter GSR = "ENABLED"; parameter [127:0] CEMUX = "1"; @@ -340,6 +341,26 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); Q <= DI; end endgenerate + + generate + // TODO + if (CLKMUX == "INV") + specify + $setup(DI, negedge CLK, 0); + $setup(CE, negedge CLK, 0); + $setup(LSR, negedge CLK, 0); + if (muxlsr) (negedge CLK => (Q : DI)) = 0; + if (!muxlsr && muxce) (negedge CLK => (Q : srval)) = 0; + endspecify + else + specify + $setup(DI, posedge CLK, 0); + $setup(CE, posedge CLK, 0); + $setup(LSR, posedge CLK, 0); + if (muxlsr) (posedge CLK => (Q : srval)) = 0; + if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0; + endspecify + endgenerate endmodule // --------------------------------------- diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 5f00d3d4e..ecc5039e6 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -66,6 +66,9 @@ struct SynthEcp5Pass : public ScriptPass log(" -noflatten\n"); log(" do not flatten design before synthesis\n"); log("\n"); + log(" -dff\n"); + log(" run 'abc'/'abc9' with -dff option\n"); + log("\n"); log(" -retime\n"); log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); @@ -107,7 +110,7 @@ struct SynthEcp5Pass : public ScriptPass } string top_opt, blif_file, edif_file, json_file; - bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, retime, abc2, abc9, nodsp, vpr; + bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, nodsp, vpr; void clear_flags() YS_OVERRIDE { @@ -122,6 +125,7 @@ struct SynthEcp5Pass : public ScriptPass nowidelut = false; asyncprld = false; flatten = true; + dff = false; retime = false; abc2 = false; vpr = false; @@ -169,6 +173,10 @@ struct SynthEcp5Pass : public ScriptPass flatten = false; continue; } + if (args[argidx] == "-dff") { + dff = true; + continue; + } if (args[argidx] == "-retime") { retime = true; continue; @@ -307,6 +315,8 @@ struct SynthEcp5Pass : public ScriptPass run("opt_clean"); if (!nodffe) run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); + if ((abc9 && dff) || help_mode) + run("zinit -all", "(-abc9 and -dff only)"); run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); run("opt_expr -undriven -mux_undef"); run("simplemap"); @@ -323,7 +333,7 @@ struct SynthEcp5Pass : public ScriptPass std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v"; if (abc9) techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1"; - if (!asyncprld || abc9) + if (!techmap_args.empty()) run("techmap " + techmap_args); if (abc9) { @@ -337,26 +347,30 @@ struct SynthEcp5Pass : public ScriptPass else abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); if (nowidelut) - run("abc9 -maxlut 4 -W 200"); - else - run("abc9 -W 200"); + abc9_args += " -maxlut 4"; + if (dff) + abc9_args += " -dff"; + run("abc9" + abc9_args); run("techmap -map +/ecp5/abc9_unmap.v"); } else { + std::string abc_args = " -dress"; if (nowidelut) - run("abc -lut 4 -dress"); + abc_args += " -lut 4"; else - run("abc -lut 4:7 -dress"); + abc_args += " -lut 4:7"; + if (dff) + abc_args += " -dff"; + run("abc" + abc_args); } run("clean"); } if (check_label("map_cells")) { - if (vpr) - run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); - else - run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)"); - + if (help_mode) + run("techmap -map +/ecp5/cells_map.v", "(skip if -vpr)"); + else if (!vpr) + run("techmap -map +/ecp5/cells_map.v"); run("opt_lut_ins -tech ecp5"); run("clean"); } -- cgit v1.2.3 From f975cf39cbedbca0482109b7aa625570a3857ee6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 08:03:58 -0700 Subject: xaiger: update help text --- backends/aiger/xaiger.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1006d56c6..b8d65de4e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -762,10 +762,10 @@ struct XAigerBackend : public Backend { log(" write_xaiger [options] [filename]\n"); log("\n"); log("Write the top module (according to the (* top *) attribute or if only one module\n"); - log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_DFF_N_,\n"); - log(" $_DFF_P_, or non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); - log("pseudo-outputs. Whitebox contents will be taken from the '$holes'\n"); - log("module, if it exists.\n"); + log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally\n"); + log("$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-\n"); + log("inputs and pseudo-outputs. Whitebox contents will be taken from the\n"); + log("'$holes' module, if it exists.\n"); log("\n"); log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); -- cgit v1.2.3 From b66904e9cdef8cd0e0019f9a1a3a7a13abdcc10c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 08:18:04 -0700 Subject: Revert "Merge branch 'eddie/kernel_makeblackbox' into eddie/abc9_auto_dff" This reverts commit e08497c7c9d8a6f7a3eccddf2149c45d9ecff207, reversing changes made to e366fd55122236a21c6daee6765724add840a1f9. --- kernel/rtlil.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 3e5896813..196e301b6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -776,7 +776,6 @@ void RTLIL::Module::makeblackbox() connections_.clear(); remove(delwires); - set_bool_attribute(ID::blackbox); } -- cgit v1.2.3 From 509de98468973838aa3b3ff958084693434c8c83 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 08:53:07 -0700 Subject: submod: revert accidental change --- passes/hierarchy/submod.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 1f30a5160..2db7cf26b 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -389,7 +389,7 @@ struct SubmodPass : public Pass { while (did_something) { did_something = false; std::vector queued_modules; - for (auto mod : design->selected_modules()) + for (auto mod : design->modules()) if (handled_modules.count(mod->name) == 0 && design->selected_whole_module(mod->name)) queued_modules.push_back(mod->name); for (auto &modname : queued_modules) -- cgit v1.2.3 From a52f779ecae79be5ea79bd27f04837e7031f8415 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 10:36:07 -0700 Subject: ecp5: (* abc9_flop *) gated behind YOSYS --- techlibs/ecp5/cells_sim.v | 2 ++ 1 file changed, 2 insertions(+) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 69685683f..563592218 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -294,7 +294,9 @@ endmodule // --------------------------------------- +`ifdef YOSYS (* abc9_flop=(SRMODE != "ASYNC"), lib_whitebox=(SRMODE != "ASYNC") *) +`endif module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); parameter GSR = "ENABLED"; parameter [127:0] CEMUX = "1"; -- cgit v1.2.3 From 043ad8e76cd45bb573c804ffddb4a478cd4a99d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 11:10:48 -0700 Subject: abc9_ops: use new 'design -delete' and 'select -unset' --- passes/techmap/abc9.cc | 20 +++++--------------- passes/techmap/abc9_ops.cc | 3 ++- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 97ee57aaa..adb28189e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -309,15 +309,10 @@ struct Abc9Pass : public ScriptPass run("abc9_ops -prep_dff_unmap"); // create $abc9_unmap design run("techmap -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); - if (!help_mode) { - // TODO: Need a way to delete saved designs? - auto it = saved_designs.find("$abc9_map"); - delete it->second; - saved_designs.erase(it); - // TODO: Need a way to delete selections - active_design->selection_vars.erase(ID($abc9_flops)); - active_design->selection_vars.erase(ID($abc9_cells)); - } + run("design -delete $abc9"); + run("design -delete $abc9_map"); + run("select -unset $abc9_flops"); + run("select -unset $abc9_cells"); } } @@ -423,12 +418,7 @@ struct Abc9Pass : public ScriptPass if (dff_mode || help_mode) { run("techmap -wb -map %$abc9_unmap", "(only if -dff)"); // techmap user design from submod back to original cell // ($_DFF_[NP]_ already shorted by -reintegrate) - if (!help_mode) { - // TODO: Need a way to delete saved designs? - auto it = saved_designs.find("$abc9_unmap"); - delete it->second; - saved_designs.erase(it); - } + run("design -delete $abc9_unmap"); } } } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index c640d06f8..57f51503c 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1204,7 +1204,8 @@ struct Abc9OpsPass : public Pass { log("\n"); log(" -prep_dff_hier\n"); log(" derive all cells with a type instantiating an (* abc9_flop *) module.\n"); - log(" store such modules in named selection '$abc9_flops'.\n"); + log(" store such modules in named selection '$abc9_flops'. store one cell\n"); + log(" instantiating each derived module into named selection '$abc9_cells'.\n"); log("\n"); log(" -prep_dff_map\n"); log(" within (* abc9_flop *) modules, move all $specify{2,3}/$specrule cells\n"); -- cgit v1.2.3 From 489e83fc1ea7051cc400b043f75ce1ad359038f0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 11:38:44 -0700 Subject: abc9_ops: do away with '$abc9_cells' selection --- passes/techmap/abc9.cc | 1 - passes/techmap/abc9_ops.cc | 69 ++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index adb28189e..bddf9d2d9 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -312,7 +312,6 @@ struct Abc9Pass : public ScriptPass run("design -delete $abc9"); run("design -delete $abc9_map"); run("select -unset $abc9_flops"); - run("select -unset $abc9_cells"); } } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 57f51503c..d15da348a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -122,14 +122,11 @@ void mark_scc(RTLIL::Module *module) void prep_dff_hier(RTLIL::Design *design) { - pool seen; - dict selection_vars; auto r YS_ATTRIBUTE(unused) = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); log_assert(r.second); - auto r2 YS_ATTRIBUTE(unused) = design->selection_vars.insert(std::make_pair(ID($abc9_cells), RTLIL::Selection(false))); - log_assert(r2.second); auto &modules_sel = design->selection_vars.at(ID($abc9_flops)); - auto &cells_sel = design->selection_vars.at(ID($abc9_cells)); + + Design *unmap_design = new Design; for (auto module : design->selected_modules()) for (auto cell : module->cells()) { @@ -142,16 +139,24 @@ void prep_dff_hier(RTLIL::Design *design) auto derived_module = design->module(derived_type); if (!derived_module->get_bool_attribute(ID::abc9_flop)) continue; - // And remember one representative cell (for its parameters) + // And create the stub in the $abc9_unmap design if (!modules_sel.selected_whole_module(derived_type)) { if (derived_type != cell->type) modules_sel.select(inst_module); modules_sel.select(derived_module); - cells_sel.select(module, cell); + + auto unmap_module = unmap_design->addModule(derived_type.str() + "_$abc9_flop"); + auto unmap_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); + for (const auto &conn : cell->connections()) + unmap_cell->setPort(conn.first, SigSpec()); + unmap_cell->parameters = cell->parameters; } } } + + auto r2 YS_ATTRIBUTE(unused) = saved_designs.emplace("$abc9_unmap", unmap_design); + log_assert(r2.second); } void prep_dff_map(RTLIL::Design *design) @@ -225,46 +230,32 @@ continue_outer_loop: ; void prep_dff_unmap(RTLIL::Design *design) { - dict derived_to_cell; - const auto &cells_sel = design->selection_vars.at(ID($abc9_cells)); - for (auto &i : cells_sel.selected_members) { - auto module = design->module(i.first); - for (auto cell_name : i.second) { - auto cell = module->cell(cell_name); - log_assert(cell); - auto inst_module = design->module(cell->type); - log_assert(inst_module); - auto derived_type = inst_module->derive(design, cell->parameters); - derived_to_cell.insert(std::make_pair(derived_type, cell)); - } - } - - Design *unmap_design = new Design; + Design *unmap_design = saved_designs.at("$abc9_unmap"); // Create the reverse techmap rule -- (* abc9_box *) back to flop - for (const auto &i : derived_to_cell) { - auto module_name = i.first; - auto flop_module = design->module(module_name.str() + "_$abc9_flop"); + for (auto module : unmap_design->modules()) { + auto flop_module = design->module(module->name.str()); if (!flop_module) continue; // May not exist if init = 1'b1 - auto unmap_module = unmap_design->addModule(flop_module->name); + auto unmap_module = unmap_design->module(flop_module->name); + log_assert(unmap_module); for (auto port : flop_module->ports) { auto w = unmap_module->addWire(port, flop_module->wire(port)); + // Do not propagate (* init *) values inside the box w->attributes.erase(ID::init); } unmap_module->ports = flop_module->ports; unmap_module->check(); - auto orig_cell = i.second; - auto unmap_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, orig_cell->type); - for (const auto &conn : orig_cell->connections()) - unmap_cell->setPort(conn.first, unmap_module->wire(conn.first)); - unmap_cell->parameters = orig_cell->parameters; + auto unmap_cell = unmap_module->cell(ID::_TECHMAP_REPLACE_); + log_assert(unmap_cell); + for (const auto &conn : unmap_cell->connections()) { + auto rhs = unmap_module->wire(conn.first); + log_assert(rhs); + unmap_cell->setPort(conn.first, rhs); + } } - - auto r YS_ATTRIBUTE(unused) = saved_designs.emplace("$abc9_unmap", unmap_design); - log_assert(r.second); } void prep_xaiger(RTLIL::Module *module, bool dff) @@ -1204,8 +1195,8 @@ struct Abc9OpsPass : public Pass { log("\n"); log(" -prep_dff_hier\n"); log(" derive all cells with a type instantiating an (* abc9_flop *) module.\n"); - log(" store such modules in named selection '$abc9_flops'. store one cell\n"); - log(" instantiating each derived module into named selection '$abc9_cells'.\n"); + log(" store such modules in named selection '$abc9_flops'. create stubs within\n"); + log(" a new '$abc9_unmap' design to be used by -prep_dff_unmap.\n"); log("\n"); log(" -prep_dff_map\n"); log(" within (* abc9_flop *) modules, move all $specify{2,3}/$specrule cells\n"); @@ -1214,9 +1205,9 @@ struct Abc9OpsPass : public Pass { log(" a submodule.\n"); log("\n"); log(" -prep_dff_unmap\n"); - log(" create a new design '$abc9_unmap' containing techmap rules that map\n"); - log(" *_$abc9_flop cells back into their original (* abc9_flop *) cells\n"); - log(" (including their original parameters).\n"); + log(" fill in previously created '$abc9_unmap' design to contain techmap rules\n"); + log(" for mapping *_$abc9_flop cells back into their original (* abc9_flop *)\n"); + log(" cells(including their original parameters).\n"); log("\n"); log(" -prep_delays\n"); log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); -- cgit v1.2.3 From 8bad885e782181837c710f738f6184bd473d88ae Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 12:35:12 -0700 Subject: abc9_ops: -prep_dff_map to check $_DFF_[NP]_.Q drives module output --- passes/techmap/abc9_ops.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index d15da348a..2f1b531e2 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -175,6 +175,10 @@ void prep_dff_map(RTLIL::Design *design) // because ABC9 doesn't support them Q = cell->getPort(ID::Q); log_assert(GetSize(Q.wire) == 1); + + if (!Q.wire->port_output) + log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(module), log_id(cell->type)); + Const init = Q.wire->attributes.at(ID::init, State::Sx); log_assert(GetSize(init) == 1); if (init != State::S0) { @@ -1207,7 +1211,7 @@ struct Abc9OpsPass : public Pass { log(" -prep_dff_unmap\n"); log(" fill in previously created '$abc9_unmap' design to contain techmap rules\n"); log(" for mapping *_$abc9_flop cells back into their original (* abc9_flop *)\n"); - log(" cells(including their original parameters).\n"); + log(" cells (including their original parameters).\n"); log("\n"); log(" -prep_delays\n"); log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); -- cgit v1.2.3 From 0d84ff3fc47fbc17184e706ea3ef1ee801f19790 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 14 Apr 2020 12:56:28 -0700 Subject: Revert "ecp5: replace ecp5_ffinit with techmap rules + dff2dffs -match-init" This reverts commit 8c702b6cc0221a00021a3e4661c883bb591c924b. --- techlibs/ecp5/Makefile.inc | 3 +- techlibs/ecp5/cells_map.v | 278 ++++++++++---------------------------------- techlibs/ecp5/synth_ecp5.cc | 3 +- 3 files changed, 64 insertions(+), 220 deletions(-) diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 6bc9c854e..217151e96 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -1,5 +1,6 @@ -OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_gsr.o +OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o \ + techlibs/ecp5/ecp5_gsr.o GENFILES += techlibs/ecp5/bram_init_1_2_4.vh GENFILES += techlibs/ecp5/bram_init_9_18_36.vh diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index f8df08eab..c031703a9 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -1,223 +1,65 @@ -(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) -module \$_DFF_x_ (input D, C, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - if (_TECHMAP_WIREINIT_Q_ === 1'b1) - localparam REGSET = "SET"; - else - localparam REGSET = "RESET"; - endgenerate - TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET)) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); -endmodule - -(* techmap_celltype = "$_DFFE_NN_ $_DFFE_PN_ $_DFFE_NP_ $_DFFE_PP_" *) -module \$_DFFE_xx_ (input D, C, E, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") - localparam CEMUX = "INV"; - else - localparam CEMUX = "CE"; - if (_TECHMAP_WIREINIT_Q_ === 1'b1) - localparam REGSET = "SET"; - else - localparam REGSET = "RESET"; - endgenerate - TRELLIS_FF #(.GSR("AUTO"), .CEMUX(CEMUX), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET)) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); -endmodule - -(* techmap_celltype = "$_DFF_NN0_ $_DFF_NN1_ $_DFF_PN0_ $_DFF_PN1_ $_DFF_NP0_ $_DFF_NP1_ $_DFF_PP0_ $_DFF_PP1_" *) -module \$_DFF_xxx_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - // TODO: Why not use LSRMUX param? - if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") - wire LSR_ = !R; - else - wire LSR_ = R; - if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin - localparam REGSET = "SET"; - if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("ECP5 doesn't support FFs with asynchronous set initialized to 0"); - end - else begin - localparam REGSET = "RESET"; - if (_TECHMAP_WIREINIT_Q_ === 1'b1) - $error("ECP5 doesn't support FFs with asynchronous reset initialized to 1"); - end - endgenerate - TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(LSR_), .DI(D), .Q(Q)); -endmodule - -(* techmap_celltype = "$__DFFS_NN0_ $__DFFS_NN1_ $__DFFS_PN0_ $__DFFS_PN1_ $__DFFS_NP0_ $__DFFS_NP1_ $__DFFS_PP0_ $__DFFS_PP1_" *) -module \$__DFFS_xxx_ (input D, C, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - // TODO: Why not use LSRMUX param? - if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") - wire LSR_ = !R; - else - wire LSR_ = R; - if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin - localparam REGSET = "SET"; - if (_TECHMAP_WIREINIT_Q_ === 1'b0) - // init is 0, reset to 1 - wire D_ = D || LSR_; - else - wire D_ = D; - end - else begin - localparam REGSET = "RESET"; - if (_TECHMAP_WIREINIT_Q_ === 1'b1) - // init is 1, reset to 0 - wire D_ = !(D && LSR_); - else - wire D_ = D; - end - endgenerate - TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(LSR_), .DI(D_), .Q(Q)); -endmodule - -(* techmap_celltype = "$__DFFE_NN0 $__DFFE_NN1 $__DFFE_PN0 $__DFFE_PN1 $__DFFE_NP0 $__DFFE_NP1 $__DFFE_PP0 $__DFFE_PP1" *) -module \$__DFFE_xxx_ (input D, C, E, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - // TODO: Why not use LSRMUX param? - if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") - wire LSR_ = !R; - else - wire LSR_ = R; - if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin - if (_TECHMAP_WIREINIT_Q_ === 1'b0) - $error("ECP5 doesn't support FFs with asynchronous set initialized to 0"); - else - localparam REGSET = "SET"; - end - else begin - if (_TECHMAP_WIREINIT_Q_ === 1'b1) - $error("ECP5 doesn't support FFs with asynchronous reset initialized to 1"); - else - localparam REGSET = "RESET"; - end - endgenerate - TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(LSR_), .DI(D), .Q(Q)); -endmodule - -(* techmap_celltype = "$__DFFSE_NN0 $__DFFSE_NN1 $__DFFSE_PN0 $__DFFSE_PN1 $__DFFSE_NP0 $__DFFSE_NP1 $__DFFSE_PP0 $__DFFSE_PP1" *) -module \$__DFFSE_xxx_ (input D, C, E, R, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - // TODO: Why not use LSRMUX param? - if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") - wire LSR_ = !R; - else - wire LSR_ = R; - if (_TECHMAP_CELLTYPE_[1*8+:8] == "1") begin - localparam REGSET = "SET"; - if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - // init is 0, reset to 1 - wire D_ = D || LSR_; - wire E_ = E || LSR_; - end - else begin - wire D_ = D; - wire E_ = E; - end - end - else begin - localparam REGSET = "RESET"; - if (_TECHMAP_WIREINIT_Q_ === 1'b1) begin - // init is 1, reset to 0 - wire D_ = !(D && LSR_); - wire E_ = !(E && LSR_); - end - else begin - wire D_ = D; - wire E_ = E; - end - end - endgenerate - TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX(CLKMUX), .LSRMUX("LSR"), .REGSET(REGSET), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E_), .LSR(LSR_), .DI(D_), .Q(Q)); -endmodule +module \$_DFF_N_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule +module \$_DFF_P_ (input D, C, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q)); endmodule + +module \$_DFFE_NN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule +module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule + +module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule +module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule + +module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule + +module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule + +module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule + +module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule `ifdef ASYNC_PRLD -(* techmap_celltype = "$_DLATCH_N_ $_DLATCH_P_" *) -module \$_DLATCH_x_ (input E, input D, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - // TODO: Why not use LSRMUX param? - if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") - wire LSR_ = !E; - else - wire LSR_ = E; - if (_TECHMAP_WIREINIT_Q_ !== 1'bx) - $error("ECP5 doesn't support latches with initial values"); // TODO: Check - endgenerate - TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(LSR_), .DI(1'b0), .M(D), .Q(Q)); -endmodule - -(* techmap_celltype = "$_DFFSR_NNN_ $_DFFSR_NNP_ $_DFFSR_PNN_ $_DFFSR_PNP_ $_DFFSR_NPN_ $_DFFSR_NPP_ $_DFFSR_PPN_ $_DFFSR_PPP_" *) -module \$_DFFSR_xxx_ (input C, S, R, D, output Q); - parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; - parameter _TECHMAP_CELLTYPE_ = ""; - wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; - generate - if (_TECHMAP_CELLTYPE_[3*8+:8] == "N") - localparam CLKMUX = "INV"; - else - localparam CLKMUX = "CLK"; - if (_TECHMAP_CELLTYPE_[2*8+:8] == "N") - wire S_ = !S; - else - wire S_ = S; - if (_TECHMAP_CELLTYPE_[1*8+:8] == "N") - wire R_ = !R; - else - wire R_ = R; - if (_TECHMAP_WIREINIT_Q_ !== 1'bx) - $error("ECP5 doesn't support FFs with asynchronous set and reset with initial values"); - endgenerate - - TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX(CLKINV), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S_ || R_), .DI(D), .M(!R_), .Q(Q)); -endmodule +module \$_DLATCH_N_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(!E), .DI(1'b0), .M(D), .Q(Q)); endmodule +module \$_DLATCH_P_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(E), .DI(1'b0), .M(D), .Q(Q)); endmodule + +module \$_DFFSR_NNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule +module \$_DFFSR_NNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule +module \$_DFFSR_NPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule +module \$_DFFSR_NPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule + +module \$_DFFSR_PNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule +module \$_DFFSR_PNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule +module \$_DFFSR_PPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule +module \$_DFFSR_PPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule `endif `include "cells_ff.vh" diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index ecc5039e6..8039531ae 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -311,7 +311,7 @@ struct SynthEcp5Pass : public ScriptPass if (check_label("map_ffs")) { - run("dff2dffs -match-init"); + run("dff2dffs"); run("opt_clean"); if (!nodffe) run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); @@ -320,6 +320,7 @@ struct SynthEcp5Pass : public ScriptPass run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); run("opt_expr -undriven -mux_undef"); run("simplemap"); + run("ecp5_ffinit"); run("ecp5_gsr"); run("attrmvcp -copy -attr syn_useioff"); run("opt_clean"); -- cgit v1.2.3 From fb447951be5ac481106f06a911234614b576b40f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 09:38:29 -0700 Subject: abc9: cleanup --- passes/techmap/abc9.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index bddf9d2d9..b57ea3cf7 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -280,7 +280,8 @@ struct Abc9Pass : public ScriptPass if (check_label("dff", "(only if -dff)")) { if (dff_mode || help_mode) { - run("abc9_ops -prep_dff_hier"); // derive all used (* abc9_flop *) modules + run("abc9_ops -prep_dff_hier"); // derive all used (* abc9_flop *) modules, + // create stubs in $abc9_unmap design run("design -stash $abc9"); run("design -copy-from $abc9 @$abc9_flops"); // copy derived modules in run("proc"); @@ -288,8 +289,11 @@ struct Abc9Pass : public ScriptPass run("techmap"); run("opt"); run("abc9_ops -prep_dff_map"); // rewrite specify - // TODO: Select fan-in cone $_DFF_[NP]_.Q - run("setattr -set submod \"$abc9_flop\" t:* t:$_DFF_N_ %d t:$_DFF_P_ %d"); + // select all $_DFF_[NP]_ + // then select all its fanins + // then select all fanouts of all that + // lastly remove $_DFF_[NP]_ cells + run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d"); run("submod"); run("design -copy-to $abc9 *_$abc9_flop"); // copy submod out run("delete *_$abc9_flop"); @@ -306,12 +310,12 @@ struct Abc9Pass : public ScriptPass } run("design -stash $abc9_map"); run("design -load $abc9"); - run("abc9_ops -prep_dff_unmap"); // create $abc9_unmap design - run("techmap -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ - run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); run("design -delete $abc9"); - run("design -delete $abc9_map"); run("select -unset $abc9_flops"); + run("abc9_ops -prep_dff_unmap"); // implement $abc9_unmap design + run("techmap -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ + run("design -delete $abc9_map"); + run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); } } -- cgit v1.2.3 From 6f4f795953b2a38ec77984c7e1b50f579b59272e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 12:15:36 -0700 Subject: aiger/xaiger: use odd for negedge clk, even for posedge Since abc9 doesn't like negative mergeability values --- backends/aiger/xaiger.cc | 16 ++++++++++------ frontends/aiger/aigerparse.cc | 7 +++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b8d65de4e..e2d8e1e7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -627,21 +627,25 @@ struct XAigerWriter write_s_buffer(ff_bits.size()); dict clk_to_mergeability; + for (const auto &i : ff_bits) { + const Cell *cell = i.second; + log_assert(cell->type.in(ID($_DFF_N_), ID($_DFF_P_))); + + SigBit clock = sigmap(cell->getPort(ID::C)); + clk_to_mergeability.insert(std::make_pair(clock, clk_to_mergeability.size()*2+1)); + } for (const auto &i : ff_bits) { const SigBit &d = i.first; const Cell *cell = i.second; - log_assert(cell->type.in(ID($_DFF_N_), ID($_DFF_P_))); - SigBit clock = sigmap(cell->getPort(ID::C)); - auto r = clk_to_mergeability.insert(std::make_pair(clock, clk_to_mergeability.size() + 1)); - int mergeability = r.first->second; + int mergeability = clk_to_mergeability.at(clock); log_assert(mergeability > 0); if (cell->type == ID($_DFF_N_)) - write_r_buffer(-mergeability); - else if (cell->type == ID($_DFF_P_)) write_r_buffer(mergeability); + else if (cell->type == ID($_DFF_P_)) + write_r_buffer(mergeability+1); else log_abort(); SigBit Q = sigmap(cell->getPort(ID::Q)); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ed3a926c6..16e94c394 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -789,13 +789,12 @@ void AigerReader::post_process() Cell* ff; int clock_index = mergeability[i]; - if (clock_index < 0) { + if (clock_index & 1) { ff = module->addCell(NEW_ID, ID($_DFF_N_)); - clock_index = -clock_index; + clock_index--; } - else if (clock_index > 0) + else ff = module->addCell(NEW_ID, ID($_DFF_P_)); - else log_abort(); auto r = mergeability_to_clock.insert(clock_index); if (r.second) r.first->second = module->addWire(NEW_ID); -- cgit v1.2.3 From 762b6ad74a49f125ef1999794cba7ece9ca3839f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 12:27:26 -0700 Subject: xilinx: remove no-longer-relevant test --- tests/arch/xilinx/abc9_map.ys | 91 ------------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 tests/arch/xilinx/abc9_map.ys diff --git a/tests/arch/xilinx/abc9_map.ys b/tests/arch/xilinx/abc9_map.ys deleted file mode 100644 index 4a7b9384a..000000000 --- a/tests/arch/xilinx/abc9_map.ys +++ /dev/null @@ -1,91 +0,0 @@ -read_verilog < Date: Wed, 15 Apr 2020 12:28:03 -0700 Subject: xilinx: update abc9_dff tests --- tests/arch/xilinx/abc9_dff.ys | 63 ++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index b457cefce..abe597e2c 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -1,32 +1,59 @@ +logger -nowarn "Yosys has only limited support for tri-state logic at the moment\. .*" + +read_verilog < Date: Wed, 15 Apr 2020 15:41:55 -0700 Subject: abc9: suppress warnings when no compatible + used flop boxes formed --- passes/techmap/abc9.cc | 61 +++++++++++++++++++++++++------------------ passes/techmap/abc9_ops.cc | 39 ++++++++++++++++++--------- tests/arch/xilinx/abc9_dff.ys | 4 ++- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index b57ea3cf7..1a5604f7d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -281,41 +281,52 @@ struct Abc9Pass : public ScriptPass if (check_label("dff", "(only if -dff)")) { if (dff_mode || help_mode) { run("abc9_ops -prep_dff_hier"); // derive all used (* abc9_flop *) modules, - // create stubs in $abc9_unmap design + // create stubs in $abc9_unmap design run("design -stash $abc9"); run("design -copy-from $abc9 @$abc9_flops"); // copy derived modules in run("proc"); run("wbflip"); run("techmap"); run("opt"); + if (!help_mode) + active_design->scratchpad_unset("abc9_ops.prep_dff_map.did_something"); run("abc9_ops -prep_dff_map"); // rewrite specify - // select all $_DFF_[NP]_ - // then select all its fanins - // then select all fanouts of all that - // lastly remove $_DFF_[NP]_ cells - run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d"); - run("submod"); - run("design -copy-to $abc9 *_$abc9_flop"); // copy submod out - run("delete *_$abc9_flop"); - if (help_mode) { - run("foreach module in design"); - run(" rename _$abc9_flop _TECHMAP_REPLACE_"); + bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_map.did_something"); + if (did_something) { + // select all $_DFF_[NP]_ + // then select all its fanins + // then select all fanouts of all that + // lastly remove $_DFF_[NP]_ cells + run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d"); + run("submod"); + run("design -copy-to $abc9 *_$abc9_flop"); // copy submod out + run("delete *_$abc9_flop"); + if (help_mode) { + run("foreach module in design"); + run(" rename _$abc9_flop _TECHMAP_REPLACE_"); + } + else { + // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs + for (auto module : active_design->selected_modules()) { + active_design->selected_active_module = module->name.str(); + if (module->cell(stringf("%s_$abc9_flop", module->name.c_str()))) + run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); + } + } + run("design -stash $abc9_map"); + run("design -load $abc9"); + run("design -delete $abc9"); + run("select -unset $abc9_flops"); + run("techmap -wb -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ + run("design -delete $abc9_map"); + run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); + run("abc9_ops -prep_dff_unmap"); // implement $abc9_unmap design } else { - // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs - for (auto module : active_design->selected_modules()) { - active_design->selected_active_module = module->name.str(); - run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); - } + run("design -load $abc9"); + run("design -delete $abc9"); + run("select -unset $abc9_flops"); } - run("design -stash $abc9_map"); - run("design -load $abc9"); - run("design -delete $abc9"); - run("select -unset $abc9_flops"); - run("abc9_ops -prep_dff_unmap"); // implement $abc9_unmap design - run("techmap -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ - run("design -delete $abc9_map"); - run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); } } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 2f1b531e2..e00a4dc81 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -161,10 +161,23 @@ void prep_dff_hier(RTLIL::Design *design) void prep_dff_map(RTLIL::Design *design) { + Design *unmap_design = saved_designs.at("$abc9_unmap"); + for (auto module : design->modules()) { vector specify_cells; SigBit D, Q; Cell* dff_cell = nullptr; + + // If module has a public name (i.e. not $paramod) and it doesn't exist + // in the $abc9_unmap then it means only derived modules were + // instantiated, so make this a blackbox + if (module->name[0] == '\\' && !unmap_design->module(module->name.str() + "_$abc9_flop")) { + module->makeblackbox(); + module->set_bool_attribute(ID::blackbox, false); + module->set_bool_attribute(ID::whitebox, true); + continue; + } + for (auto cell : module->cells()) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { if (dff_cell) @@ -185,6 +198,7 @@ void prep_dff_map(RTLIL::Design *design) log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(module), log_id(cell->type)); module->makeblackbox(); + module->set_bool_attribute(ID::blackbox, false); auto wire = module->addWire(ID(_TECHMAP_FAIL_)); wire->set_bool_attribute(ID::keep); @@ -215,19 +229,20 @@ void prep_dff_map(RTLIL::Design *design) D = w; } - if (GetSize(specify_cells) == 0) { - log_warning("Module '%s' marked (* abc9_flop *) contains no specify timing information.\n", log_id(module)); - } - else { - // Rewrite $specify cells that end with $_DFF_[NP]_.Q - // to $_DFF_[NP]_.D since it will be moved into - // the submodule - for (auto cell : specify_cells) { - auto DST = cell->getPort(ID::DST); - DST.replace(Q, D); - cell->setPort(ID::DST, DST); - } + if (GetSize(specify_cells) == 0) + log_error("Module '%s' marked (* abc9_flop *) contains no specify timing information.\n", log_id(module)); + + // Rewrite $specify cells that end with $_DFF_[NP]_.Q + // to $_DFF_[NP]_.D since it will be moved into + // the submodule + for (auto cell : specify_cells) { + auto DST = cell->getPort(ID::DST); + DST.replace(Q, D); + cell->setPort(ID::DST, DST); } + + design->scratchpad_set_bool("abc9_ops.prep_dff_map.did_something", true); + continue_outer_loop: ; } } diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index abe597e2c..15343970f 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -14,6 +14,7 @@ endmodule EOT equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf design -load postopt +select -assert-count 6 t:FD* select -assert-count 6 c:fd2 c:fd3 c:fd4 c:fd6 c:fd7 c:fd8 @@ -32,6 +33,7 @@ endmodule EOT equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf design -load postopt +select -assert-count 4 t:FD* select -assert-count 4 c:fd3 c:fd4 c:fd7 c:fd8 @@ -54,6 +56,6 @@ logger -expect warning "Module 'FDSE' contains a \$_DFF_P_ cell .*" 1 logger -expect warning "Module '\$paramod\\FDSE_1\\INIT=1' contains a \$_DFF_N_ cell .*" 1 equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf design -load postopt -#select -assert-count 4 c:fd3 c:fd4 c:fd7 c:fd8 +select -assert-count 8 t:FD* logger -expect-no-warnings -- cgit v1.2.3 From c52bb11fb6a4a34ba702e35c2950efb978b953ad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 15:50:57 -0700 Subject: abc9_ops: more robust --- passes/techmap/abc9_ops.cc | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e00a4dc81..544fefdfb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -641,7 +641,8 @@ void prep_box(RTLIL::Design *design) log_assert(num_outputs == 1); ss << log_id(module) << " " << r.first->second.as_int(); - ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + log_assert(module->get_bool_attribute(ID::whitebox)); + ss << " " << "1"; ss << " " << num_inputs << " " << num_outputs << std::endl; ss << "#"; @@ -659,6 +660,9 @@ void prep_box(RTLIL::Design *design) ss << std::endl; auto &t = timing.setup_module(module).required; + if (t.empty()) + log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module)); + first = true; for (auto port_name : module->ports) { auto wire = module->wire(port_name); @@ -671,8 +675,8 @@ void prep_box(RTLIL::Design *design) log_assert(GetSize(wire) == 1); auto it = t.find(TimingInfo::NameBit(port_name,0)); if (it == t.end()) - // Assume that no setup time means zero - ss << 0; + // Assume no connectivity if no setup time + ss << "-"; else { ss << it->second; @@ -743,9 +747,11 @@ void prep_box(RTLIL::Design *design) } ss << std::endl; - auto &t = timing.setup_module(module).comb; - if (t.empty()) - log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module)); + auto &t = timing.setup_module(module); + if (t.comb.empty()) + log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module)); + if (!t.arrival.empty() || !t.required.empty()) + log_error("Module '%s' with (* abc9_box *) has setup and/or edge-sensitive timing information.\n", log_id(module)); for (const auto &o : outputs) { first = true; @@ -754,8 +760,8 @@ void prep_box(RTLIL::Design *design) first = false; else ss << " "; - auto jt = t.find(TimingInfo::BitBit(i,o)); - if (jt == t.end()) + auto jt = t.comb.find(TimingInfo::BitBit(i,o)); + if (jt == t.comb.end()) ss << "-"; else ss << jt->second; -- cgit v1.2.3 From ec4bbb1444b24d36c03a6635738e34b652e5aa1b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 16:13:57 -0700 Subject: abc9: generate $abc9_holes design instead of $holes --- backends/aiger/xaiger.cc | 12 +++++++++--- passes/techmap/abc9.cc | 18 +++++++++++------- passes/techmap/abc9_ops.cc | 16 ++++++++-------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e2d8e1e7f..17a2748dc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -676,7 +676,13 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); + RTLIL::Design *holes_design; + auto it = saved_designs.find("$abc9_holes"); + if (it != saved_designs.end()) + holes_design = it->second; + else + holes_design = nullptr; + RTLIL::Module *holes_module = holes_design ? holes_design->module(module->name) : nullptr; if (holes_module) { std::stringstream a_buffer; XAigerWriter writer(holes_module, false /* dff_mode */, true /* holes_mode */); @@ -768,8 +774,8 @@ struct XAigerBackend : public Backend { log("Write the top module (according to the (* top *) attribute or if only one module\n"); log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally\n"); log("$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-\n"); - log("inputs and pseudo-outputs. Whitebox contents will be taken from the\n"); - log("'$holes' module, if it exists.\n"); + log("inputs and pseudo-outputs. Whitebox contents will be taken from the equivalent\n"); + log("module in the '$abc9_holes' design, if it exists.\n"); log("\n"); log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1a5604f7d..dc96a765f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -345,15 +345,18 @@ struct Abc9Pass : public ScriptPass else if (box_file.empty()) { run("abc9_ops -prep_box"); } - run("select -set abc9_holes A:abc9_holes"); - run("flatten -wb @abc9_holes"); - run("techmap @abc9_holes"); - run("opt -purge @abc9_holes"); + run("design -stash $abc9"); + run("design -load $abc9_holes"); + run("techmap -wb -map %$abc9 -map +/techmap.v"); + run("opt -purge"); run("aigmap"); - run("wbflip @abc9_holes"); + run("wbflip"); + run("design -stash $abc9_holes"); + run("design -load $abc9"); } if (check_label("map")) { + run("aigmap"); if (help_mode) { run("foreach module in selection"); run(" abc9_ops -write_lut /input.lut", "(skip if '-lut' or '-luts')"); @@ -372,7 +375,6 @@ struct Abc9Pass : public ScriptPass log("Skipping module %s as it contains processes.\n", log_id(mod)); continue; } - log_assert(!mod->attributes.count(ID::abc9_box_id)); log_push(); active_design->selection().select(mod); @@ -432,8 +434,10 @@ struct Abc9Pass : public ScriptPass if (dff_mode || help_mode) { run("techmap -wb -map %$abc9_unmap", "(only if -dff)"); // techmap user design from submod back to original cell // ($_DFF_[NP]_ already shorted by -reintegrate) - run("design -delete $abc9_unmap"); + run("design -delete $abc9_unmap", " (only if -dff)"); } + if (saved_designs.count("$abc9_holes") || help_mode) + run("design -delete $abc9_holes"); } } } Abc9Pass; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 544fefdfb..ee25866c3 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -368,9 +368,13 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(no_loops); - RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str())); + auto r = saved_designs.emplace("$abc9_holes", nullptr); + if (r.second) + r.first->second = new Design; + RTLIL::Design *holes_design = r.first->second; + log_assert(holes_design); + RTLIL::Module *holes_module = holes_design->addModule(module->name); log_assert(holes_module); - holes_module->set_bool_attribute(ID::abc9_holes); dict cell_cache; TimingInfo timing; @@ -1246,9 +1250,8 @@ struct Abc9OpsPass : public Pass { log("\n"); log(" -prep_xaiger\n"); log(" prepare the design for XAIGER output. this includes computing the\n"); - log(" topological ordering of ABC9 boxes, as well as preparing the\n"); - log(" '$holes' module that contains the logic behaviour of ABC9\n"); - log(" whiteboxes.\n"); + log(" topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'\n"); + log(" design that contains the logic behaviour of ABC9 whiteboxes.\n"); log("\n"); log(" -dff\n"); log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n"); @@ -1388,9 +1391,6 @@ struct Abc9OpsPass : public Pass { prep_box(design); for (auto mod : design->selected_modules()) { - if (mod->get_bool_attribute(ID::abc9_holes)) - continue; - if (mod->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(mod)); continue; -- cgit v1.2.3 From 4c6647a4693838978354183d5553717fa2d97a48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 16:16:30 -0700 Subject: xaiger: always sort input/output bits by port id redundant for normal design, but necessary for holes --- backends/aiger/xaiger.cc | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 17a2748dc..6f0ed6e89 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -138,7 +138,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool dff_mode, bool holes_mode=false) : module(module), sigmap(module) + XAigerWriter(Module *module, bool dff_mode) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -411,16 +411,14 @@ struct XAigerWriter undriven_bits.erase(bit); } - if (holes_mode) { - struct sort_by_port_id { - bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { - return a.wire->port_id < b.wire->port_id || - (a.wire->port_id == b.wire->port_id && a.offset < b.offset); - } - }; - input_bits.sort(sort_by_port_id()); - output_bits.sort(sort_by_port_id()); - } + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id || + (a.wire->port_id == b.wire->port_id && a.offset < b.offset); + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); aig_map[State::S0] = 0; aig_map[State::S1] = 1; @@ -685,7 +683,7 @@ struct XAigerWriter RTLIL::Module *holes_module = holes_design ? holes_design->module(module->name) : nullptr; if (holes_module) { std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /* dff_mode */, true /* holes_mode */); + XAigerWriter writer(holes_module, false /* dff_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); f << "a"; -- cgit v1.2.3 From c41c180f68b161cfeb8b82efe06c56d02394a831 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 16:18:37 -0700 Subject: abc9: remove redundant wbflip --- passes/techmap/abc9.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index dc96a765f..fbb8356a5 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -350,7 +350,6 @@ struct Abc9Pass : public ScriptPass run("techmap -wb -map %$abc9 -map +/techmap.v"); run("opt -purge"); run("aigmap"); - run("wbflip"); run("design -stash $abc9_holes"); run("design -load $abc9"); } -- cgit v1.2.3 From 6c66030dfbcd93024f5f5bb602b9fcc58cb80a88 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Feb 2020 17:59:33 -0800 Subject: Uncomment negative setup times; clamp to zero for connectivity --- techlibs/xilinx/cells_sim.v | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 93d080ffd..5143f87da 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -36,6 +36,9 @@ module IBUF( parameter IOSTANDARD = "default"; parameter IBUF_LOW_PWR = 0; assign O = I; + specify + (I => O) = 0; + endspecify endmodule module IBUFG( @@ -57,6 +60,9 @@ module OBUF( parameter DRIVE = 12; parameter SLEW = "SLOW"; assign O = I; + specify + (I => O) = 0; + endspecify endmodule module IOBUF ( @@ -72,6 +78,10 @@ module IOBUF ( parameter SLEW = "SLOW"; assign IO = T ? 1'bz : I; assign O = IO; + specify + (I => IO) = 0; + (IO => O) = 0; + endspecify endmodule module OBUFT ( @@ -85,14 +95,20 @@ module OBUFT ( parameter IOSTANDARD = "DEFAULT"; parameter SLEW = "SLOW"; assign O = T ? 1'bz : I; + specify + (I => O) = 0; + endspecify endmodule module BUFG( (* clkbuf_driver *) output O, input I); - assign O = I; + specify + // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/CLK_BUFG_TOP_R.sdf#L11 + (I => O) = 96; + endspecify endmodule module BUFGCTRL( @@ -499,8 +515,8 @@ module FDRE ( endgenerate specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , posedge C &&& CE && !IS_C_INVERTED , -46); // Negative times not currently supported - //$setup(D , negedge C &&& CE && IS_C_INVERTED , -46); // Negative times not currently supported + $setup(D , posedge C &&& CE && !IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported + $setup(D , negedge C &&& CE && IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE, posedge C &&& !IS_C_INVERTED, 109); $setup(CE, negedge C &&& IS_C_INVERTED, 109); @@ -529,7 +545,7 @@ module FDRE_1 ( always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported + $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE, negedge C, 109); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 @@ -564,8 +580,8 @@ module FDSE ( endgenerate specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported - //$setup(D , negedge C &&& IS_C_INVERTED && CE, -46); // Negative times not currently supported + $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported + $setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE, posedge C &&& !IS_C_INVERTED, 109); $setup(CE, negedge C &&& IS_C_INVERTED, 109); @@ -594,7 +610,7 @@ module FDSE_1 ( always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported + $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE, negedge C, 109); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 @@ -667,8 +683,8 @@ module FDCE ( endgenerate specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported - //$setup(D , negedge C &&& IS_C_INVERTED && CE, -46); // Negative times not currently supported + $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported + $setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE , posedge C &&& !IS_C_INVERTED, 109); $setup(CE , negedge C &&& IS_C_INVERTED, 109); @@ -697,7 +713,7 @@ module FDCE_1 ( always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported + $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE , negedge C, 109); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 @@ -734,8 +750,8 @@ module FDPE ( endgenerate specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported - //$setup(D , negedge C &&& IS_C_INVERTED && CE, -46); // Negative times not currently supported + $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported + $setup(D , negedge C &&& IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE , posedge C &&& !IS_C_INVERTED, 109); $setup(CE , negedge C &&& IS_C_INVERTED, 109); @@ -764,7 +780,7 @@ module FDPE_1 ( always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; specify // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 - //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported + $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 $setup(CE , negedge C, 109); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 -- cgit v1.2.3 From 4cec21b93e62e9c43a0ab9618c0111ee65e520c1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 15 Apr 2020 16:29:11 -0700 Subject: abc9_ops: -prep_dff_map to error if async flop found --- passes/techmap/abc9_ops.cc | 12 +++++++----- techlibs/xilinx/cells_sim.v | 4 ---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index ee25866c3..62007c61e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -181,7 +181,7 @@ void prep_dff_map(RTLIL::Design *design) for (auto cell : module->cells()) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { if (dff_cell) - log_error("More than one $_DFF_[NP]_ cell found in module '%s' marked (* abc9_flop *)\n", log_id(module)); + log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(module)); dff_cell = cell; // Block sequential synthesis on cells with (* init *) != 1'b0 @@ -207,10 +207,15 @@ void prep_dff_map(RTLIL::Design *design) goto continue_outer_loop; } } + else if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), + ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1), + ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1))) + log_error("Module '%s' with (* abc9_flop *) contains an asynchronous $_DFFE?_[NP][NP][01]_? cell, which is not supported for sequential synthesis.\n", log_id(module)); else if (cell->type.in(ID($specify2), ID($specify3), ID($specrule))) specify_cells.emplace_back(cell); if (!dff_cell) - log_error("$_DFF_[NP]_ cell not found in module '%s' marked (* abc9_flop *)\n", log_id(module)); + log_error("Module '%s' with (* abc9_flop *) does not any contain $_DFF_[NP]_ cells.\n", log_id(module)); D = dff_cell->getPort(ID::D); @@ -229,9 +234,6 @@ void prep_dff_map(RTLIL::Design *design) D = w; } - if (GetSize(specify_cells) == 0) - log_error("Module '%s' marked (* abc9_flop *) contains no specify timing information.\n", log_id(module)); - // Rewrite $specify cells that end with $_DFF_[NP]_.Q // to $_DFF_[NP]_.D since it will be moved into // the submodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 5143f87da..25df3a865 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -656,7 +656,6 @@ module FDRSE ( Q <= d; endmodule -(* lib_whitebox *) module FDCE ( output reg Q, (* clkbuf_sink *) @@ -699,7 +698,6 @@ module FDCE ( endspecify endmodule -(* lib_whitebox *) module FDCE_1 ( output reg Q, (* clkbuf_sink *) @@ -724,7 +722,6 @@ module FDCE_1 ( endspecify endmodule -(* lib_whitebox *) module FDPE ( output reg Q, (* clkbuf_sink *) @@ -766,7 +763,6 @@ module FDPE ( endspecify endmodule -(* lib_whitebox *) module FDPE_1 ( output reg Q, (* clkbuf_sink *) -- cgit v1.2.3 From 7812a2959b9b23b44e8144f9edb139f282d623e1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:21:08 -0700 Subject: kernel: TimingInfo to clamp -ve setup/edge-sensitive delays to zero --- kernel/timinginfo.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index fb4e0930d..36908868c 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -128,11 +128,9 @@ struct TimingInfo int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &d : dst) { auto &v = t.arrival[NameBit(d)]; @@ -152,11 +150,9 @@ struct TimingInfo if (!c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + max = 0; } for (const auto &s : src) { auto &v = t.required[NameBit(s)]; -- cgit v1.2.3 From 48052ad813db3561a959a1921466d571bafa354c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:24:02 -0700 Subject: abc9: add flop boxes to basic $_DFF_P_ and $_DFF_N_ too --- passes/techmap/abc9.cc | 19 ++++++++++--------- passes/techmap/abc9_ops.cc | 26 ++++++++++++++++---------- techlibs/common/Makefile.inc | 2 ++ techlibs/common/abc9_map.v | 21 +++++++++++++++++++++ techlibs/common/abc9_model.v | 20 ++++++++++++++++++++ techlibs/common/abc9_unmap.v | 12 ++++++++++++ tests/various/abc9.ys | 12 +++++++----- 7 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 techlibs/common/abc9_map.v create mode 100644 techlibs/common/abc9_unmap.v diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fbb8356a5..911254aa6 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -314,23 +314,24 @@ struct Abc9Pass : public ScriptPass } } run("design -stash $abc9_map"); - run("design -load $abc9"); - run("design -delete $abc9"); - run("select -unset $abc9_flops"); - run("techmap -wb -map %$abc9_map"); // techmap user design into submod + $_DFF_[NP]_ + } + run("design -load $abc9"); + run("design -delete $abc9"); + run("select -unset $abc9_flops"); + if (did_something) { // techmap user design into submod + $_DFF_[NP]_ + run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v"); run("design -delete $abc9_map"); run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); run("abc9_ops -prep_dff_unmap"); // implement $abc9_unmap design } - else { - run("design -load $abc9"); - run("design -delete $abc9"); - run("select -unset $abc9_flops"); - } + else + run("techmap -wb -max_iter 1 -map +/abc9_map.v"); + } } if (check_label("pre")) { + run("read_verilog -icells -lib -specify +/abc9_model.v"); run("scc -set_attr abc9_scc_id {}"); if (help_mode) run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 62007c61e..976b6462e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -128,7 +128,7 @@ void prep_dff_hier(RTLIL::Design *design) Design *unmap_design = new Design; - for (auto module : design->selected_modules()) + for (auto module : design->modules()) for (auto cell : module->cells()) { auto inst_module = design->module(cell->type); if (inst_module && inst_module->attributes.count(ID::abc9_flop)) { @@ -219,17 +219,23 @@ void prep_dff_map(RTLIL::Design *design) D = dff_cell->getPort(ID::D); - // Add a dummy enable mux feeding DFF.D to ensure that: - // (i) a driving cell exists, so that 'submod' will have - // an output port - // (ii) DFF.Q will exist in this submodule { - auto c = module->addCell(NEW_ID, ID($_MUX_)); + // Add dummy buffers for all module inputs/outputs + // to ensure that these ports exists in the flop box + // created by later submod pass + for (auto port_name : module->ports) { + auto port = module->wire(port_name); + log_assert(GetSize(port) == 1); + auto c = module->addBufGate(NEW_ID, port, module->addWire(NEW_ID)); + // Need to set (* keep *) otherwise opt_clean + // inside submod will blow it away + c->set_bool_attribute(ID::keep); + } + // Add an additional buffer that drives $_DFF_[NP]_.D + // so that the flop box will have an output auto w = module->addWire(NEW_ID); - c->setPort(ID::A, D); - c->setPort(ID::B, Q); - c->setPort(ID::S, State::S0); - c->setPort(ID::Y, w); + auto c = module->addBufGate(NEW_ID, D, w); + c->set_bool_attribute(ID::keep); dff_cell->setPort(ID::D, w); D = w; } diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 7b1e4b430..607e772a2 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -30,4 +30,6 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) +$(eval $(call add_share_file,share,techlibs/common/abc9_map.v)) +$(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v)) $(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v new file mode 100644 index 000000000..b04a5b64f --- /dev/null +++ b/techlibs/common/abc9_map.v @@ -0,0 +1,21 @@ +(* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) +module $_DFF_x_(input C, D, output Q); + parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin + wire D_; + $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); + end + else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin + wire D_; + $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); + end + else if (_TECHMAP_CELLTYPE_ != "") + $error("Unrecognised _TECHMAP_CELLTYPE_"); + endgenerate + wire _TECHMAP_REMOVEINIT_Q_ = 1; +endmodule diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index 9e8048faf..41acf4d97 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -5,3 +5,23 @@ module \$__ABC9_DELAY (input I, output O); (I => O) = DELAY; endspecify endmodule + +(* abc9_flop, abc9_box, lib_whitebox *) +module $__DFF_N__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); + parameter [0:0] INIT = 1'bx; + assign n1 = D; + specify + $setup(D, posedge C, 0); + (posedge C => (n1:D)) = 0; + endspecify +endmodule + +(* abc9_flop, abc9_box, lib_whitebox *) +module $__DFF_P__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); + parameter [0:0] INIT = 1'bx; + assign n1 = D; + specify + $setup(D, posedge C, 0); + (posedge C => (n1:D)) = 0; + endspecify +endmodule diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v new file mode 100644 index 000000000..0fd07207d --- /dev/null +++ b/techlibs/common/abc9_unmap.v @@ -0,0 +1,12 @@ +(* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) +module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); + parameter [0:0] INIT = 1'bx; + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") + $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ == "$__DFF_P__$abc9_flop") + $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ != "") + $error("Unrecognised _TECHMAP_CELLTYPE_"); + endgenerate +endmodule diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 6e2415ad7..7a3a503e4 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -45,14 +45,16 @@ sat -seq 10 -verify -prove-asserts -show-ports miter design -reset read_verilog -icells < Date: Thu, 16 Apr 2020 10:25:22 -0700 Subject: Revert "Merge pull request #1917 from YosysHQ/eddie/abc9_delay_check" This reverts commit 759283fa65b1195ebe3a5bc6890ec622febca0eb, reversing changes made to f41c7ccfff4bf104c646ca4b85e079a0f91c9151. --- backends/aiger/xaiger.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6f0ed6e89..ddda1bd5a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -293,10 +293,6 @@ struct XAigerWriter if (abc9_flop) continue; } - else { - if (cell->type == ID($__ABC9_DELAY)) - log_error("Cell type '%s' not recognised. Check that '+/abc9_model.v' has been read.\n", cell->type.c_str()); - } bool cell_known = inst_module || cell->known(); for (const auto &c : cell->connections()) { -- cgit v1.2.3 From 8fbb55f4aba9ccb850680dc9c7ab582e8c964a4a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:25:41 -0700 Subject: synth_*: no need to explicitly read +/abc9_model.v --- techlibs/ecp5/synth_ecp5.cc | 2 +- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/intel_alm/synth_intel_alm.cc | 1 - techlibs/xilinx/synth_xilinx.cc | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 8039531ae..c1545cbb5 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -338,7 +338,7 @@ struct SynthEcp5Pass : public ScriptPass run("techmap " + techmap_args); if (abc9) { - run("read_verilog -icells -lib -specify +/abc9_model.v +/ecp5/abc9_model.v"); + run("read_verilog -icells -lib -specify +/ecp5/abc9_model.v"); std::string abc9_opts; if (nowidelut) abc9_opts += " -maxlut 4"; diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 376cb7dbd..f780832e6 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -387,7 +387,7 @@ struct SynthIce40Pass : public ScriptPass } if (!noabc) { if (abc9) { - run("read_verilog " + define + " -icells -lib -specify +/abc9_model.v +/ice40/abc9_model.v"); + run("read_verilog " + define + " -icells -lib -specify +/ice40/abc9_model.v"); std::string abc9_opts; std::string k = "synth_ice40.abc9.W"; if (active_design && active_design->scratchpad.count(k)) diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc index bf9e746b8..0f844961e 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -209,7 +209,6 @@ struct SynthIntelALMPass : public ScriptPass { } if (check_label("map_luts")) { - run("read_verilog -icells -specify -lib +/abc9_model.v"); run("abc9 -maxlut 6 -W 200"); run("techmap -map +/intel_alm/common/alm_map.v"); run("opt -fast"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c45d389ef..d6ca9e57e 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -616,7 +616,7 @@ struct SynthXilinxPass : public ScriptPass log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " "will use timing for 'xc7' instead.\n", family.c_str()); run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); - run("read_verilog -icells -lib -specify +/abc9_model.v +/xilinx/abc9_model.v"); + run("read_verilog -icells -lib -specify +/xilinx/abc9_model.v"); std::string abc9_opts; std::string k = "synth_xilinx.abc9.W"; if (active_design && active_design->scratchpad.count(k)) -- cgit v1.2.3 From c50601e35e9444e9fb77fd89622b3263d85d1fd0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:40:33 -0700 Subject: abc9: restore selected_modules() --- passes/techmap/abc9_ops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 976b6462e..4843200d8 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -128,7 +128,7 @@ void prep_dff_hier(RTLIL::Design *design) Design *unmap_design = new Design; - for (auto module : design->modules()) + for (auto module : design->selected_modules()) for (auto cell : module->cells()) { auto inst_module = design->module(cell->type); if (inst_module && inst_module->attributes.count(ID::abc9_flop)) { -- cgit v1.2.3 From 5ad3a8528896a2e2539f2de98194eb0a6cce36c9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 10:49:33 -0700 Subject: abc9: test to use box file instead of auto --- tests/simple_abc9/abc9.box | 3 +++ tests/simple_abc9/abc9.v | 2 +- tests/simple_abc9/run-test.sh | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 tests/simple_abc9/abc9.box diff --git a/tests/simple_abc9/abc9.box b/tests/simple_abc9/abc9.box new file mode 100644 index 000000000..b3c88437c --- /dev/null +++ b/tests/simple_abc9/abc9.box @@ -0,0 +1,3 @@ +MUXF8 1 0 3 1 +#I0 I1 S +0 0 0 # O diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v index 688b47586..5e969c614 100644 --- a/tests/simple_abc9/abc9.v +++ b/tests/simple_abc9/abc9.v @@ -213,7 +213,7 @@ module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encode input rst; endmodule -(* abc9_box, blackbox *) +(* abc9_box_id=1, blackbox *) module MUXF8(input I0, I1, S, output O); specify (I0 => O) = 0; diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh index 424d8f417..650e42fca 100755 --- a/tests/simple_abc9/run-test.sh +++ b/tests/simple_abc9/run-test.sh @@ -25,7 +25,7 @@ exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-n 300 -p synth -run coarse; \ opt -full; \ techmap; \ - abc9 -lut 4; \ + abc9 -lut 4 -box ../abc9.box; \ clean; \ check -assert; \ select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ -- cgit v1.2.3 From 722540dbf942d2b8acbaf7372001c7d982eb2845 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 12:08:59 -0700 Subject: abc9: not enough to techmap_fail on (* init=1 *), hide them using $__ --- backends/aiger/xaiger.cc | 1 + techlibs/common/abc9_map.v | 24 ++++++++++++++---------- techlibs/common/abc9_unmap.v | 12 ++++++++++++ tests/various/abc9.ys | 23 +++++++++++++++++++++-- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ddda1bd5a..abb9ae30f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -644,6 +644,7 @@ struct XAigerWriter SigBit Q = sigmap(cell->getPort(ID::Q)); State init = init_map.at(Q, State::Sx); + log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init)); if (init == State::S1) write_s_buffer(1); else if (init == State::S0) diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index b04a5b64f..5f1822485 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -2,20 +2,24 @@ module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; parameter _TECHMAP_CELLTYPE_ = ""; - generate if (_TECHMAP_WIREINIT_Q_ === 1'b1) - wire _TECHMAP_FAIL_ = 1; - else if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin - wire D_; - $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); - $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); + wire D_; + generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin + if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin + $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); + end + else + $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));// hide from abc9 using $__ prefix end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin - wire D_; - $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); - $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); + if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin + $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); + end + else + $__DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix end else if (_TECHMAP_CELLTYPE_ != "") $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate - wire _TECHMAP_REMOVEINIT_Q_ = 1; endmodule diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index 0fd07207d..4dfac0cbb 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -10,3 +10,15 @@ module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule + +(* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) +module $__DFF_N__$abc9_flop(input C, D, output Q); + parameter _TECHMAP_CELLTYPE_ = ""; + generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") + $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ == "$__DFF_P_") + $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); + else if (_TECHMAP_CELLTYPE_ != "") + $error("Unrecognised _TECHMAP_CELLTYPE_"); + endgenerate +endmodule diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 7a3a503e4..9586091c4 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -50,7 +50,7 @@ $_DFF_P_ ff(.C(clk), .D(d), .Q(w)); assign q = w; endmodule EOT -equiv_opt abc9 -lut 4 -dff +equiv_opt -assert abc9 -lut 4 -dff design -load postopt cd abc9_test036 select -assert-count 1 t:$_DFF_P_ @@ -69,8 +69,27 @@ specify endspecify endmodule -module top(input [1:0] i, output o); +module abc9_test037(input [1:0] i, output o); LUT2 #(.mask(4'b0)) lut (.i(i), .o(o)); endmodule EOT abc9 + + +design -reset +read_verilog -icells < Date: Thu, 16 Apr 2020 14:01:54 -0700 Subject: aiger: -xaiger to return $_FF_ flops --- frontends/aiger/aigerparse.cc | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 16e94c394..d25587e48 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -787,21 +787,8 @@ void AigerReader::post_process() log_assert(q->port_input); q->port_input = false; - Cell* ff; - int clock_index = mergeability[i]; - if (clock_index & 1) { - ff = module->addCell(NEW_ID, ID($_DFF_N_)); - clock_index--; - } - else - ff = module->addCell(NEW_ID, ID($_DFF_P_)); - auto r = mergeability_to_clock.insert(clock_index); - if (r.second) - r.first->second = module->addWire(NEW_ID); - ff->setPort(ID::C, r.first->second); - ff->setPort(ID::D, d); - ff->setPort(ID::Q, q); - log_assert(GetSize(q) == 1); + Cell* ff = module->addFfGate(NEW_ID, d, q); + ff->attributes[ID::abc9_mergeability] = mergeability[i]; q->attributes[ID::init] = initial_state[i]; } -- cgit v1.2.3 From e357b40e7ae8a907ef38b2d32c920aada3f1ed5a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 14:02:42 -0700 Subject: xaiger: no longer use nonstandard even/odd to designate +ve/-ve polarity --- backends/aiger/xaiger.cc | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index abb9ae30f..e1962119c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -620,27 +620,16 @@ struct XAigerWriter auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); write_s_buffer(ff_bits.size()); - dict clk_to_mergeability; - for (const auto &i : ff_bits) { - const Cell *cell = i.second; - log_assert(cell->type.in(ID($_DFF_N_), ID($_DFF_P_))); - - SigBit clock = sigmap(cell->getPort(ID::C)); - clk_to_mergeability.insert(std::make_pair(clock, clk_to_mergeability.size()*2+1)); - } - + dict clk_to_mergeability; for (const auto &i : ff_bits) { const SigBit &d = i.first; const Cell *cell = i.second; - SigBit clock = sigmap(cell->getPort(ID::C)); - int mergeability = clk_to_mergeability.at(clock); + SigSpec clk_and_pol{sigmap(cell->getPort(ID::C)), cell->type[6] == 'P' ? State::S1 : State::S0}; + auto r = clk_to_mergeability.insert(std::make_pair(clk_and_pol, clk_to_mergeability.size()+1)); + int mergeability = r.first->second; log_assert(mergeability > 0); - if (cell->type == ID($_DFF_N_)) - write_r_buffer(mergeability); - else if (cell->type == ID($_DFF_P_)) - write_r_buffer(mergeability+1); - else log_abort(); + write_r_buffer(mergeability); SigBit Q = sigmap(cell->getPort(ID::Q)); State init = init_map.at(Q, State::Sx); -- cgit v1.2.3 From bb840cca9cd62ad59b2054049e979263325ba664 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 16 Apr 2020 14:03:54 -0700 Subject: abc9_ops: -reintegrate to handle $_FF_; cleanup --- passes/techmap/abc9_ops.cc | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 4843200d8..8fc56b773 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -166,6 +166,7 @@ void prep_dff_map(RTLIL::Design *design) for (auto module : design->modules()) { vector specify_cells; SigBit D, Q; + Cell *c; Cell* dff_cell = nullptr; // If module has a public name (i.e. not $paramod) and it doesn't exist @@ -217,28 +218,23 @@ void prep_dff_map(RTLIL::Design *design) if (!dff_cell) log_error("Module '%s' with (* abc9_flop *) does not any contain $_DFF_[NP]_ cells.\n", log_id(module)); - D = dff_cell->getPort(ID::D); - - { - // Add dummy buffers for all module inputs/outputs - // to ensure that these ports exists in the flop box - // created by later submod pass - for (auto port_name : module->ports) { - auto port = module->wire(port_name); - log_assert(GetSize(port) == 1); - auto c = module->addBufGate(NEW_ID, port, module->addWire(NEW_ID)); - // Need to set (* keep *) otherwise opt_clean - // inside submod will blow it away - c->set_bool_attribute(ID::keep); - } - // Add an additional buffer that drives $_DFF_[NP]_.D - // so that the flop box will have an output - auto w = module->addWire(NEW_ID); - auto c = module->addBufGate(NEW_ID, D, w); + // Add dummy buffers for all module inputs/outputs + // to ensure that these ports exists in the flop box + // created by later submod pass + for (auto port_name : module->ports) { + auto port = module->wire(port_name); + log_assert(GetSize(port) == 1); + auto c = module->addBufGate(NEW_ID, port, module->addWire(NEW_ID)); + // Need to set (* keep *) otherwise opt_clean + // inside submod will blow it away c->set_bool_attribute(ID::keep); - dff_cell->setPort(ID::D, w); - D = w; } + // Add an additional buffer that drives $_DFF_[NP]_.D + // so that the flop box will have an output + D = module->addWire(NEW_ID); + c = module->addBufGate(NEW_ID, dff_cell->getPort(ID::D), D); + c->set_bool_attribute(ID::keep); + dff_cell->setPort(ID::D, D); // Rewrite $specify cells that end with $_DFF_[NP]_.Q // to $_DFF_[NP]_.D since it will be moved into @@ -895,9 +891,9 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) std::map cell_stats; for (auto mapped_cell : mapped_mod->cells()) { - // Short out $_DFF_[NP]_ cells since the flop box already has + // Short out $_FF_ cells since the flop box already has // all the information we need to reconstruct cell - if (dff_mode && mapped_cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { + if (dff_mode && mapped_cell->type == ID($_FF_)) { SigBit D = mapped_cell->getPort(ID::D); SigBit Q = mapped_cell->getPort(ID::Q); if (D.wire) -- cgit v1.2.3 From 7cd3f4a79bde6dbe2cd7f90d0a4996aebe70fd10 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 12:22:39 -0700 Subject: abc9_ops: add -prep_bypass for auto bypass boxes; refactor Eliminate need for abc9_{,un}map.v in xilinx -prep_dff_{hier,unmap} -> -prep_hier --- passes/techmap/abc9.cc | 64 +++-- passes/techmap/abc9_ops.cc | 618 +++++++++++++++++++++++++++++++--------- techlibs/ecp5/synth_ecp5.cc | 2 +- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/xilinx/Makefile.inc | 2 - techlibs/xilinx/abc9_map.v | 432 ---------------------------- techlibs/xilinx/abc9_model.v | 171 ----------- techlibs/xilinx/abc9_unmap.v | 57 ---- techlibs/xilinx/cells_sim.v | 222 ++++++++------- techlibs/xilinx/synth_xilinx.cc | 4 +- tests/arch/xilinx/abc9_dff.ys | 34 ++- 11 files changed, 667 insertions(+), 941 deletions(-) delete mode 100644 techlibs/xilinx/abc9_map.v delete mode 100644 techlibs/xilinx/abc9_unmap.v diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 911254aa6..ff9b46b5f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -275,22 +275,31 @@ struct Abc9Pass : public ScriptPass void script() YS_OVERRIDE { if (check_label("check")) { - run("abc9_ops -check"); + if (help_mode) + run("abc9_ops -check [-dff]", "(option if -dff)"); + else + run(stringf("abc9_ops -check %s", dff_mode ? "-dff" : "")); } - if (check_label("dff", "(only if -dff)")) { - if (dff_mode || help_mode) { - run("abc9_ops -prep_dff_hier"); // derive all used (* abc9_flop *) modules, - // create stubs in $abc9_unmap design - run("design -stash $abc9"); - run("design -copy-from $abc9 @$abc9_flops"); // copy derived modules in - run("proc"); - run("wbflip"); - run("techmap"); - run("opt"); + if (check_label("map")) { + if (help_mode) + run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)"); + else + run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : "")); + if (dff_mode) { + run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)"); + run("select -unset $abc9_flops", " (only if -dff)"); + } + run("design -stash $abc9"); + run("design -load $abc9_map"); + run("proc"); + run("wbflip"); + run("techmap"); + run("opt"); + if (dff_mode) { if (!help_mode) active_design->scratchpad_unset("abc9_ops.prep_dff_map.did_something"); - run("abc9_ops -prep_dff_map"); // rewrite specify + run("abc9_ops -prep_dff_map", "(only if -dff)"); // rewrite specify bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_map.did_something"); if (did_something) { // select all $_DFF_[NP]_ @@ -299,6 +308,8 @@ struct Abc9Pass : public ScriptPass // lastly remove $_DFF_[NP]_ cells run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d"); run("submod"); + run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); + run("abc9_ops -prep_dff_unmap"); run("design -copy-to $abc9 *_$abc9_flop"); // copy submod out run("delete *_$abc9_flop"); if (help_mode) { @@ -313,21 +324,13 @@ struct Abc9Pass : public ScriptPass run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); } } - run("design -stash $abc9_map"); - } - run("design -load $abc9"); - run("design -delete $abc9"); - run("select -unset $abc9_flops"); - if (did_something) { // techmap user design into submod + $_DFF_[NP]_ - run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v"); - run("design -delete $abc9_map"); - run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); - run("abc9_ops -prep_dff_unmap"); // implement $abc9_unmap design } - else - run("techmap -wb -max_iter 1 -map +/abc9_map.v"); - } + run("design -stash $abc9_map"); + run("design -load $abc9"); + run("design -delete $abc9"); + run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v"); + run("design -delete $abc9_map"); } if (check_label("pre")) { @@ -353,9 +356,10 @@ struct Abc9Pass : public ScriptPass run("aigmap"); run("design -stash $abc9_holes"); run("design -load $abc9"); + run("design -delete $abc9"); } - if (check_label("map")) { + if (check_label("exe")) { run("aigmap"); if (help_mode) { run("foreach module in selection"); @@ -430,12 +434,10 @@ struct Abc9Pass : public ScriptPass } } - if (check_label("post")) { - if (dff_mode || help_mode) { - run("techmap -wb -map %$abc9_unmap", "(only if -dff)"); // techmap user design from submod back to original cell + if (check_label("unmap")) { + run("techmap -wb -map %$abc9_unmap -map +/abc9_unmap.v"); // techmap user design from submod back to original cell // ($_DFF_[NP]_ already shorted by -reintegrate) - run("design -delete $abc9_unmap", " (only if -dff)"); - } + run("design -delete $abc9_unmap"); if (saved_designs.count("$abc9_holes") || help_mode) run("design -delete $abc9_holes"); } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 8fc56b773..25ac5c340 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -34,13 +34,10 @@ inline std::string remap_name(RTLIL::IdString abc9_name) return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); } -void check(RTLIL::Design *design) +void check(RTLIL::Design *design, bool dff_mode) { dict box_lookup; for (auto m : design->modules()) { - if (m->name.begins_with("$paramod")) - continue; - auto flop = m->get_bool_attribute(ID::abc9_flop); auto it = m->attributes.find(ID::abc9_box_id); if (!flop) { @@ -88,135 +85,405 @@ void check(RTLIL::Design *design) log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); } } + + if (dff_mode) { + pool unsupported{ + ID($adff), ID($dlatch), ID($dlatchsr), ID($sr), + ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), + ID($_DLATCH_N_), ID($_DLATCH_P_), + ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), + ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), + ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_) + }; + pool processed; + for (auto module : design->selected_modules()) + for (auto cell : module->cells()) { + auto inst_module = design->module(cell->type); + if (!inst_module) + continue; + if (!inst_module->attributes.count(ID::abc9_flop)) + continue; + auto derived_type = inst_module->derive(design, cell->parameters); + if (!processed.insert(derived_type).second) + continue; + if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) + log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type)); + + auto derived_module = design->module(derived_type); + if (derived_module->has_processes()) + Pass::call_on_module(design, derived_module, "proc"); + + if (derived_module->get_bool_attribute(ID::abc9_flop)) { + bool found = false; + for (auto derived_cell : derived_module->cells()) + if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { + if (found) + log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); + found = true; + + SigBit Q = derived_cell->getPort(ID::Q); + log_assert(GetSize(Q.wire) == 1); + + if (!Q.wire->port_output) + log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(derived_module), log_id(derived_cell->type)); + + Const init = Q.wire->attributes.at(ID::init, State::Sx); + log_assert(GetSize(init) == 1); + } + else if (unsupported.count(derived_cell->type)) { + log_error("Module '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); + } + } + } + } } -void mark_scc(RTLIL::Module *module) +void prep_hier(RTLIL::Design *design, bool dff_mode) { - // For every unique SCC found, (arbitrarily) find the first - // cell in the component, and replace its output connections - // with a new wire driven by the old connection but with a - // special (* abc9_scc *) attribute set (which is used by - // write_xaiger to break this wire into PI and POs) - pool ids_seen; - for (auto cell : module->cells()) { - auto it = cell->attributes.find(ID::abc9_scc_id); - if (it == cell->attributes.end()) - continue; - auto id = it->second; - auto r = ids_seen.insert(id); - cell->attributes.erase(it); - if (!r.second) - continue; - for (auto &c : cell->connections_) { - if (c.second.is_fully_const()) continue; - if (cell->output(c.first)) { - Wire *w = module->addWire(NEW_ID, GetSize(c.second)); - w->set_bool_attribute(ID::abc9_scc); - module->connect(w, c.second); - c.second = w; + auto r = saved_designs.emplace("$abc9_unmap", nullptr); + if (r.second) + r.first->second = new Design; + Design *unmap_design = r.first->second; + + pool seq_types{ + ID($dff), ID($dffsr), ID($adff), + ID($dlatch), ID($dlatchsr), ID($sr), + ID($mem), + ID($_DFF_N_), ID($_DFF_P_), + ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), + ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), + ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), + ID($_DLATCH_N_), ID($_DLATCH_P_), + ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), + ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), + ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_) + }; + + for (auto module : design->selected_modules()) + for (auto cell : module->cells()) { + auto inst_module = design->module(cell->type); + if (!inst_module) + continue; + auto derived_type = inst_module->derive(design, cell->parameters); + auto derived_module = design->module(derived_type); + if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) + continue; + + if (inst_module->attributes.count(ID::abc9_flop) && !dff_mode) + continue; + if (!inst_module->attributes.count(ID::abc9_box) && !inst_module->attributes.count(ID::abc9_flop)) + continue; + + if (!unmap_design->module(derived_type)) { + if (derived_module->has_processes()) + Pass::call_on_module(design, derived_module, "proc"); + + if (derived_module->get_bool_attribute(ID::abc9_flop)) { + for (auto derived_cell : derived_module->cells()) + if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { + SigBit Q = derived_cell->getPort(ID::Q); + Const init = Q.wire->attributes.at(ID::init, State::Sx); + log_assert(GetSize(init) == 1); + + // Block sequential synthesis on cells with (* init *) != 1'b0 + // because ABC9 doesn't support them + if (init != State::S0) { + log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); + // TODO: still necessary? + // Do not use set_bool_attribute() as it will unset the value + // and (attributes.count(ID::abc9_flop) will fail) + derived_module->attributes[ID::abc9_flop] = false; + goto skip_cell; + } + break; + } + } + else if (derived_module->get_bool_attribute(ID::abc9_box)) { + bool found = false; + for (auto derived_cell : derived_module->cells()) + if (seq_types.count(derived_cell->type)) { + found = true; + break; + } + + if (!found) { + derived_module->set_bool_attribute(ID::abc9_box, false); + log_assert(!derived_module->attributes.count(ID::abc9_box)); + goto skip_cell; + } + + // TODO: still necessary? + // Do not use set_bool_attribute() as it will unset the value + // and (attributes.count(ID::abc9_box) will fail) + derived_module->attributes[ID::abc9_box] = false; + } + + if (derived_type != cell->type) { + auto unmap_module = unmap_design->addModule(derived_type); + for (auto port : derived_module->ports) { + auto w = unmap_module->addWire(port, derived_module->wire(port)); + // Do not propagate (* init *) values inside the box + if (w->port_output) + w->attributes.erase(ID::init); + } + unmap_module->ports = derived_module->ports; + unmap_module->check(); + + auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); + for (const auto &conn : cell->connections()) { + auto w = unmap_module->wire(conn.first); + log_assert(w); + replace_cell->setPort(conn.first, w); + } + replace_cell->parameters = cell->parameters; + } } + + cell->type = derived_type; + cell->parameters.clear(); + +skip_cell: ; } - } } - -void prep_dff_hier(RTLIL::Design *design) +void prep_bypass(RTLIL::Design *design) { - auto r YS_ATTRIBUTE(unused) = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); - log_assert(r.second); - auto &modules_sel = design->selection_vars.at(ID($abc9_flops)); + auto r = saved_designs.emplace("$abc9_map", nullptr); + if (r.second) + r.first->second = new Design; + Design *map_design = r.first->second; - Design *unmap_design = new Design; + r = saved_designs.emplace("$abc9_unmap", nullptr); + if (r.second) + r.first->second = new Design; + Design *unmap_design = r.first->second; + pool processed; for (auto module : design->selected_modules()) for (auto cell : module->cells()) { + if (!processed.insert(cell->type).second) + continue; auto inst_module = design->module(cell->type); - if (inst_module && inst_module->attributes.count(ID::abc9_flop)) { - if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) - log_error("Module '%s' with (* abc9_flop *) is not a whitebox.\n", log_id(inst_module)); - // Derive modules for all instantiations of (* abc9_flop *) - auto derived_type = inst_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_type); - if (!derived_module->get_bool_attribute(ID::abc9_flop)) + if (!inst_module) + continue; + auto derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); + log_assert(inst_module); + if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) + continue; + // Skip if (* abc9_box *) exists or is true + auto it = inst_module->attributes.find(ID::abc9_box); + if (it == inst_module->attributes.end() || it->second.as_bool()) + continue; + + + // The idea is to create two techmap designs, one which maps: + // + // box u0 (.i(i), .o(o)); + // + // to + // + // wire $abc9$o; + // box u0 (.i(i), .o($abc9_byp$o)); + // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o)); + // + // the purpose being to move the (* abc9_box *) status from 'box' + // (which is stateful) to 'box_$abc9_byp' (which becomes a new + // combinatorial black- (not white-) box with all state elements + // removed). This has the effect of preserving any combinatorial + // paths through an otherwise sequential primitive -- e.g. LUTRAMs. + // + // The unmap design performs the reverse: + // + // wire $abc9$o; + // box u0 (.i(i), .o($abc9_byp$o)); + // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o)); + // + // to: + // + // wire $abc9$o; + // box u0 (.i(i), .o($abc9_byp$o)); + // assign o = $abc9_byp$o; + + + // Copy derived_module into map_design, with the same interface + // and duplicate $abc9$* wires for its output ports + auto map_module = map_design->addModule(cell->type); + for (auto port_name : inst_module->ports) { + auto w = map_module->addWire(port_name, inst_module->wire(port_name)); + if (w->port_output) + w->attributes.erase(ID::init); + } + map_module->ports = inst_module->ports; + map_module->check(); + map_module->set_bool_attribute(ID::whitebox); + + // Create the bypass module in the user design, which has the same + // interface as the derived module but with additional input + // ports driven by the outputs of the replaced cell + auto bypass_module = design->addModule(cell->type.str() + "_$abc9_byp"); + for (auto port_name : inst_module->ports) { + auto port = inst_module->wire(port_name); + if (!port->port_output) + continue; + auto dst = bypass_module->addWire(port_name, port); + auto src = bypass_module->addWire("$abc9byp$" + port_name.str(), GetSize(port)); + src->port_input = true; + // For these new input ports driven by the replaced + // cell, then create a new simple-path specify entry: + // (input => output) = 0 + auto specify = bypass_module->addCell(NEW_ID, ID($specify2)); + specify->setPort(ID::EN, State::S1); + specify->setPort(ID::SRC, src); + specify->setPort(ID::DST, dst); + specify->setParam(ID::FULL, 0); + specify->setParam(ID::SRC_WIDTH, GetSize(src)); + specify->setParam(ID::DST_WIDTH, GetSize(dst)); + specify->setParam(ID::SRC_DST_PEN, 0); + specify->setParam(ID::SRC_DST_POL, 0); + specify->setParam(ID::T_RISE_MIN, 0); + specify->setParam(ID::T_RISE_TYP, 0); + specify->setParam(ID::T_RISE_MAX, 0); + specify->setParam(ID::T_FALL_MIN, 0); + specify->setParam(ID::T_FALL_TYP, 0); + specify->setParam(ID::T_FALL_MAX, 0); + } + bypass_module->set_bool_attribute(ID::blackbox); + bypass_module->set_bool_attribute(ID::abc9_box); + + // Copy any 'simple' (combinatorial) specify paths from + // the derived module into the bypass module, if EN + // is not false and SRC/DST are driven only by + // module ports; create new input port if one doesn't + // already exist + for (auto cell : inst_module->cells()) { + if (cell->type != ID($specify2)) + continue; + auto EN = cell->getPort(ID::EN).as_bit(); + SigBit newEN; + if (!EN.wire && EN != State::S1) continue; - // And create the stub in the $abc9_unmap design - if (!modules_sel.selected_whole_module(derived_type)) { - if (derived_type != cell->type) - modules_sel.select(inst_module); - - modules_sel.select(derived_module); - - auto unmap_module = unmap_design->addModule(derived_type.str() + "_$abc9_flop"); - auto unmap_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); - for (const auto &conn : cell->connections()) - unmap_cell->setPort(conn.first, SigSpec()); - unmap_cell->parameters = cell->parameters; + auto SRC = cell->getPort(ID::SRC); + for (const auto &c : SRC.chunks()) + if (c.wire && !c.wire->port_input) { + SRC = SigSpec(); + break; + } + if (SRC.empty()) + continue; + auto DST = cell->getPort(ID::DST); + for (const auto &c : DST.chunks()) + if (c.wire && !c.wire->port_output) { + DST = SigSpec(); + break; + } + if (DST.empty()) + continue; + auto rw = [bypass_module](RTLIL::SigSpec &sig) + { + SigSpec new_sig; + for (auto c : sig.chunks()) { + if (c.wire) { + auto port = bypass_module->wire(c.wire->name); + if (!port) + port = bypass_module->addWire(c.wire->name, c.wire); + c.wire = port; + } + new_sig.append(std::move(c)); + } + sig = std::move(new_sig); + }; + auto specify = bypass_module->addCell(NEW_ID, cell); + specify->rewrite_sigspecs(rw); + } + bypass_module->fixup_ports(); + + // Create an _TECHMAP_REPLACE_ cell identical to the original cell, + // and a bypass cell that has the same inputs/outputs as the + // original cell, but with additional inputs taken from the + // replaced cell + auto replace_cell = map_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); + auto bypass_cell = map_module->addCell(NEW_ID, cell->type.str() + "_$abc9_byp"); + for (const auto &conn : cell->connections()) { + auto port = map_module->wire(conn.first); + if (cell->input(conn.first)) { + replace_cell->setPort(conn.first, port); + if (bypass_module->wire(conn.first)) + bypass_cell->setPort(conn.first, port); + } + if (cell->output(conn.first)) { + bypass_cell->setPort(conn.first, port); + auto n = "$abc9byp$" + conn.first.str(); + auto w = map_module->addWire(n, GetSize(conn.second)); + replace_cell->setPort(conn.first, w); + bypass_cell->setPort(n, w); } } + + + // Lastly, create a new module in the unmap_design that shorts + // out the bypass cell back to leave the replace cell behind + // driving the outputs + auto unmap_module = unmap_design->addModule(cell->type.str() + "_$abc9_byp"); + for (auto port_name : inst_module->ports) { + auto w = unmap_module->addWire(port_name, inst_module->wire(port_name)); + if (w->port_output) { + w->attributes.erase(ID::init); + auto w2 = unmap_module->addWire("$abc9byp$" + port_name.str(), GetSize(w)); + w2->port_input = true; + unmap_module->connect(w, w2); + } + } + unmap_module->fixup_ports(); } +} + +void prep_dff(RTLIL::Design *design) +{ + auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false))); + auto &modules_sel = r.first->second; - auto r2 YS_ATTRIBUTE(unused) = saved_designs.emplace("$abc9_unmap", unmap_design); - log_assert(r2.second); + for (auto module : design->selected_modules()) + for (auto cell : module->cells()) { + if (modules_sel.selected_whole_module(cell->type)) + continue; + auto inst_module = design->module(cell->type); + if (!inst_module) + continue; + if (!inst_module->attributes.count(ID::abc9_flop)) + continue; + auto derived_type = inst_module->derive(design, cell->parameters); + auto derived_module = design->module(derived_type); + log_assert(derived_module); + if (!derived_module->get_bool_attribute(ID::abc9_flop)) + continue; + log_assert(!derived_module->get_blackbox_attribute(true /* ignore_wb */)); + modules_sel.select(derived_module); + } } void prep_dff_map(RTLIL::Design *design) { - Design *unmap_design = saved_designs.at("$abc9_unmap"); - for (auto module : design->modules()) { vector specify_cells; - SigBit D, Q; - Cell *c; + SigBit Q; Cell* dff_cell = nullptr; - // If module has a public name (i.e. not $paramod) and it doesn't exist - // in the $abc9_unmap then it means only derived modules were - // instantiated, so make this a blackbox - if (module->name[0] == '\\' && !unmap_design->module(module->name.str() + "_$abc9_flop")) { - module->makeblackbox(); - module->set_bool_attribute(ID::blackbox, false); - module->set_bool_attribute(ID::whitebox, true); + if (!module->get_bool_attribute(ID::abc9_flop)) continue; - } for (auto cell : module->cells()) if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - if (dff_cell) - log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(module)); + log_assert(!dff_cell); dff_cell = cell; - - // Block sequential synthesis on cells with (* init *) != 1'b0 - // because ABC9 doesn't support them Q = cell->getPort(ID::Q); log_assert(GetSize(Q.wire) == 1); - - if (!Q.wire->port_output) - log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(module), log_id(cell->type)); - - Const init = Q.wire->attributes.at(ID::init, State::Sx); - log_assert(GetSize(init) == 1); - if (init != State::S0) { - log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(module), log_id(cell->type)); - - module->makeblackbox(); - module->set_bool_attribute(ID::blackbox, false); - - auto wire = module->addWire(ID(_TECHMAP_FAIL_)); - wire->set_bool_attribute(ID::keep); - module->connect(wire, State::S1); - - goto continue_outer_loop; - } } - else if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), - ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), - ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1), - ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1))) - log_error("Module '%s' with (* abc9_flop *) contains an asynchronous $_DFFE?_[NP][NP][01]_? cell, which is not supported for sequential synthesis.\n", log_id(module)); - else if (cell->type.in(ID($specify2), ID($specify3), ID($specrule))) + else if (cell->type.in(ID($specify3), ID($specrule))) specify_cells.emplace_back(cell); - if (!dff_cell) - log_error("Module '%s' with (* abc9_flop *) does not any contain $_DFF_[NP]_ cells.\n", log_id(module)); + log_assert(dff_cell); // Add dummy buffers for all module inputs/outputs // to ensure that these ports exists in the flop box @@ -231,8 +498,8 @@ void prep_dff_map(RTLIL::Design *design) } // Add an additional buffer that drives $_DFF_[NP]_.D // so that the flop box will have an output - D = module->addWire(NEW_ID); - c = module->addBufGate(NEW_ID, dff_cell->getPort(ID::D), D); + SigBit D = module->addWire(NEW_ID); + Cell *c = module->addBufGate(NEW_ID, dff_cell->getPort(ID::D), D); c->set_bool_attribute(ID::keep); dff_cell->setPort(ID::D, D); @@ -246,8 +513,6 @@ void prep_dff_map(RTLIL::Design *design) } design->scratchpad_set_bool("abc9_ops.prep_dff_map.did_something", true); - -continue_outer_loop: ; } } @@ -255,28 +520,61 @@ void prep_dff_unmap(RTLIL::Design *design) { Design *unmap_design = saved_designs.at("$abc9_unmap"); - // Create the reverse techmap rule -- (* abc9_box *) back to flop - for (auto module : unmap_design->modules()) { - auto flop_module = design->module(module->name.str()); - if (!flop_module) - continue; // May not exist if init = 1'b1 + for (auto module : design->modules()) { + if (!module->get_bool_attribute(ID::abc9_flop) || module->get_bool_attribute(ID::abc9_box)) + continue; - auto unmap_module = unmap_design->module(flop_module->name); - log_assert(unmap_module); - for (auto port : flop_module->ports) { - auto w = unmap_module->addWire(port, flop_module->wire(port)); + auto unmap_module = unmap_design->addModule(module->name.str() + "_$abc9_flop"); + auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name); + for (auto port_name : module->ports) { + auto w = unmap_module->addWire(port_name, module->wire(port_name)); // Do not propagate (* init *) values inside the box - w->attributes.erase(ID::init); + if (w->port_output) + w->attributes.erase(ID::init); + replace_cell->setPort(port_name, w); + } + + // Add new ports appearing in "_$abc9_flop" + auto box_module = design->module(unmap_module->name); + log_assert(box_module); + for (auto port_name : box_module->ports) { + auto port = box_module->wire(port_name); + auto unmap_port = unmap_module->wire(port_name); + if (!unmap_port) + unmap_port = unmap_module->addWire(port_name, port); + else + unmap_port->port_id = port->port_id; } - unmap_module->ports = flop_module->ports; + unmap_module->ports = box_module->ports; unmap_module->check(); + } +} - auto unmap_cell = unmap_module->cell(ID::_TECHMAP_REPLACE_); - log_assert(unmap_cell); - for (const auto &conn : unmap_cell->connections()) { - auto rhs = unmap_module->wire(conn.first); - log_assert(rhs); - unmap_cell->setPort(conn.first, rhs); +void mark_scc(RTLIL::Module *module) +{ + // For every unique SCC found, (arbitrarily) find the first + // cell in the component, and replace its output connections + // with a new wire driven by the old connection but with a + // special (* abc9_scc *) attribute set (which is used by + // write_xaiger to break this wire into PI and POs) + pool ids_seen; + for (auto cell : module->cells()) { + auto it = cell->attributes.find(ID::abc9_scc_id); + if (it == cell->attributes.end()) + continue; + auto id = it->second; + auto r = ids_seen.insert(id); + cell->attributes.erase(it); + if (!r.second) + continue; + for (auto &c : cell->connections_) { + if (c.second.is_fully_const()) continue; + if (cell->output(c.first)) { + Wire *w = module->addWire(NEW_ID, GetSize(c.second)); + w->set_bool_attribute(ID::abc9_scc); + module->connect(w, c.second); + c.second = w; + } } } } @@ -477,7 +775,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) continue; if (!inst_module->get_blackbox_attribute()) continue; - if (inst_module->attributes.count(ID::abc9_box)) + if (inst_module->get_bool_attribute(ID::abc9_box)) continue; IdString derived_type = inst_module->derive(design, cell->parameters); inst_module = design->module(derived_type); @@ -630,7 +928,12 @@ void prep_box(RTLIL::Design *design) dict> box_ports; for (auto module : design->modules()) { - if (!module->attributes.erase(ID::abc9_box)) + auto it = module->attributes.find(ID::abc9_box); + if (it == module->attributes.end()) + continue; + bool box = it->second.as_bool(); + module->attributes.erase(it); + if (!box) continue; auto r = module->attributes.insert(ID::abc9_box_id); @@ -758,8 +1061,6 @@ void prep_box(RTLIL::Design *design) auto &t = timing.setup_module(module); if (t.comb.empty()) log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module)); - if (!t.arrival.empty() || !t.required.empty()) - log_error("Module '%s' with (* abc9_box *) has setup and/or edge-sensitive timing information.\n", log_id(module)); for (const auto &o : outputs) { first = true; @@ -1226,21 +1527,38 @@ struct Abc9OpsPass : public Pass { log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n"); log(" (* abc9_carry *) is only given for one input/output port, etc.\n"); log("\n"); - log(" -prep_dff_hier\n"); - log(" derive all cells with a type instantiating an (* abc9_flop *) module.\n"); - log(" store such modules in named selection '$abc9_flops'. create stubs within\n"); - log(" a new '$abc9_unmap' design to be used by -prep_dff_unmap.\n"); + log(" -prep_hier\n"); + log(" derive all used (* abc9_box *) requiring bypass, or (* abc9_flop *) (if\n"); + log(" -dff option) whitebox modules. with (* abc9_box *) modules, bypassing is\n"); + log(" necessary if sequential elements (e.g. $dff, $mem, etc.) are discovered\n"); + log(" inside, to ensure that any combinatorial paths are correctly captured.\n"); + log(" with (* abc9_flop *) modules, only those containing $dff/$_DFF_[NP]_\n"); + log(" cells with zero initial state -- due to an ABC limitation -- will be\n"); + log(" derived. for such derived modules, add a rule inside the '$abc9_unmap'\n"); + log(" design that can map a cell instantiating a derived module back to the\n"); + log(" original cell with parameters.\n"); + log("\n"); + log(" -prep_bypass\n"); + log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n"); + log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n"); + log(" (named *_$abc9_byp) that has inherited all its $specify2 (simple path)\n"); + log(" cells.\n"); + log("\n"); + log(" -prep_dff\n"); + log(" select all (* abc9_flop *) modules instantiated in the design and store\n"); + log(" in the named selection '$abc9_flops'.\n"); log("\n"); log(" -prep_dff_map\n"); - log(" within (* abc9_flop *) modules, move all $specify{2,3}/$specrule cells\n"); - log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n"); - log(" the DFF's 'D' port. this is to prepare such specify cells to be moved into\n"); - log(" a submodule.\n"); + log(" within (* abc9_flop *) modules, attach dummy buffers to all ports and move\n"); + log(" all $specify3/$specrule cells that share a 'DST' port with the $_DFF_[NP]_.Q\n"); + log(" port from this 'Q' port to the DFF's 'D' port. this is to ensure that all\n"); + log(" module ports will exist in any submodule, and prepare such specify cells to\n"); + log(" be moved within.\n"); log("\n"); log(" -prep_dff_unmap\n"); - log(" fill in previously created '$abc9_unmap' design to contain techmap rules\n"); - log(" for mapping *_$abc9_flop cells back into their original (* abc9_flop *)\n"); - log(" cells (including their original parameters).\n"); + log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n"); + log(" cells back into their derived cell types (where the rules created by\n"); + log(" -prep_hier will then map back to the original cell with parameters).\n"); log("\n"); log(" -prep_delays\n"); log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); @@ -1288,7 +1606,9 @@ struct Abc9OpsPass : public Pass { bool check_mode = false; bool prep_delays_mode = false; bool mark_scc_mode = false; - bool prep_dff_hier_mode = false, prep_dff_map_mode = false, prep_dff_unmap_mode = false; + bool prep_hier_mode = false; + bool prep_bypass_mode = false; + bool prep_dff_mode = false, prep_dff_map_mode = false, prep_dff_unmap_mode = false; bool prep_xaiger_mode = false; bool prep_lut_mode = false; bool prep_box_mode = false; @@ -1312,8 +1632,18 @@ struct Abc9OpsPass : public Pass { valid = true; continue; } - if (arg == "-prep_dff_hier") { - prep_dff_hier_mode = true; + if (arg == "-prep_hier") { + prep_hier_mode = true; + valid = true; + continue; + } + if (arg == "-prep_bypass") { + prep_bypass_mode = true; + valid = true; + continue; + } + if (arg == "-prep_dff") { + prep_dff_mode = true; valid = true; continue; } @@ -1376,13 +1706,17 @@ struct Abc9OpsPass : public Pass { if (!valid) log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); - if (dff_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode) - log_cmd_error("'-dff' option is only relevant for -prep_{delay,xaiger} or -reintegrate.\n"); + if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode) + log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n"); if (check_mode) - check(design); - if (prep_dff_hier_mode) - prep_dff_hier(design); + check(design, dff_mode); + if (prep_hier_mode) + prep_hier(design, dff_mode); + if (prep_bypass_mode) + prep_bypass(design); + if (prep_dff_mode) + prep_dff(design); if (prep_dff_map_mode) prep_dff_map(design); if (prep_dff_unmap_mode) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index c1545cbb5..3e475baab 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -316,7 +316,7 @@ struct SynthEcp5Pass : public ScriptPass if (!nodffe) run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); if ((abc9 && dff) || help_mode) - run("zinit -all", "(-abc9 and -dff only)"); + run("zinit -all t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); run("opt_expr -undriven -mux_undef"); run("simplemap"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index f780832e6..f2270dbca 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -362,7 +362,7 @@ struct SynthIce40Pass : public ScriptPass run("simplemap t:$dff"); } if ((abc9 && dff) || help_mode) - run("zinit -all", "(-abc9 and -dff only)"); + run("zinit -all t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); run("techmap -map +/ice40/ff_map.v"); run("opt_expr -mux_undef"); run("simplemap"); diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc index 9984290a6..d4d863831 100644 --- a/techlibs/xilinx/Makefile.inc +++ b/techlibs/xilinx/Makefile.inc @@ -54,8 +54,6 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v)) -$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v)) $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v)) $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v deleted file mode 100644 index 1d733a650..000000000 --- a/techlibs/xilinx/abc9_map.v +++ /dev/null @@ -1,432 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -// The following techmapping rules are intended to be run (with -max_iter 1) -// before invoking the `abc9` pass in order to transform the design into -// a format that it understands. - -// Attach a (combinatorial) black-box onto the output -// of thes LUTRAM primitives to capture their -// asynchronous read behaviour -module RAM32X1D ( - output DPO, SPO, - (* techmap_autopurge *) input D, - (* techmap_autopurge *) input WCLK, - (* techmap_autopurge *) input WE, - (* techmap_autopurge *) input A0, A1, A2, A3, A4, - (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 -); - parameter INIT = 32'h0; - parameter IS_WCLK_INVERTED = 1'b0; - wire $DPO, $SPO; - RAM32X1D #( - .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .DPO($DPO), .SPO($SPO), - .D(D), .WCLK(WCLK), .WE(WE), - .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), - .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4) - ); - $__ABC9_RAM6 spo (.A($SPO), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO)); - $__ABC9_RAM6 dpo (.A($DPO), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); -endmodule - -module RAM64X1D ( - output DPO, SPO, - (* techmap_autopurge *) input D, - (* techmap_autopurge *) input WCLK, - (* techmap_autopurge *) input WE, - (* techmap_autopurge *) input A0, A1, A2, A3, A4, A5, - (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 -); - parameter INIT = 64'h0; - parameter IS_WCLK_INVERTED = 1'b0; - wire $DPO, $SPO; - RAM64X1D #( - .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .DPO($DPO), .SPO($SPO), - .D(D), .WCLK(WCLK), .WE(WE), - .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5), - .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5) - ); - $__ABC9_RAM6 spo (.A($SPO), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO)); - $__ABC9_RAM6 dpo (.A($DPO), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); -endmodule - -module RAM128X1D ( - output DPO, SPO, - (* techmap_autopurge *) input D, - (* techmap_autopurge *) input WCLK, - (* techmap_autopurge *) input WE, - (* techmap_autopurge *) input [6:0] A, DPRA -); - parameter INIT = 128'h0; - parameter IS_WCLK_INVERTED = 1'b0; - wire $DPO, $SPO; - RAM128X1D #( - .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .DPO($DPO), .SPO($SPO), - .D(D), .WCLK(WCLK), .WE(WE), - .A(A), - .DPRA(DPRA) - ); - $__ABC9_RAM7 spo (.A($SPO), .S(A), .Y(SPO)); - $__ABC9_RAM7 dpo (.A($DPO), .S(DPRA), .Y(DPO)); -endmodule - -module RAM32M ( - output [1:0] DOA, - output [1:0] DOB, - output [1:0] DOC, - output [1:0] DOD, - (* techmap_autopurge *) input [4:0] ADDRA, - (* techmap_autopurge *) input [4:0] ADDRB, - (* techmap_autopurge *) input [4:0] ADDRC, - (* techmap_autopurge *) input [4:0] ADDRD, - (* techmap_autopurge *) input [1:0] DIA, - (* techmap_autopurge *) input [1:0] DIB, - (* techmap_autopurge *) input [1:0] DIC, - (* techmap_autopurge *) input [1:0] DID, - (* techmap_autopurge *) input WCLK, - (* techmap_autopurge *) input WE -); - parameter [63:0] INIT_A = 64'h0000000000000000; - parameter [63:0] INIT_B = 64'h0000000000000000; - parameter [63:0] INIT_C = 64'h0000000000000000; - parameter [63:0] INIT_D = 64'h0000000000000000; - parameter [0:0] IS_WCLK_INVERTED = 1'b0; - wire [1:0] $DOA, $DOB, $DOC, $DOD; - RAM32M #( - .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), - .IS_WCLK_INVERTED(IS_WCLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), - .WCLK(WCLK), .WE(WE), - .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), - .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) - ); - $__ABC9_RAM6 doa0 (.A($DOA[0]), .S({1'b1, ADDRA}), .Y(DOA[0])); - $__ABC9_RAM6 doa1 (.A($DOA[1]), .S({1'b1, ADDRA}), .Y(DOA[1])); - $__ABC9_RAM6 dob0 (.A($DOB[0]), .S({1'b1, ADDRB}), .Y(DOB[0])); - $__ABC9_RAM6 dob1 (.A($DOB[1]), .S({1'b1, ADDRB}), .Y(DOB[1])); - $__ABC9_RAM6 doc0 (.A($DOC[0]), .S({1'b1, ADDRC}), .Y(DOC[0])); - $__ABC9_RAM6 doc1 (.A($DOC[1]), .S({1'b1, ADDRC}), .Y(DOC[1])); - $__ABC9_RAM6 dod0 (.A($DOD[0]), .S({1'b1, ADDRD}), .Y(DOD[0])); - $__ABC9_RAM6 dod1 (.A($DOD[1]), .S({1'b1, ADDRD}), .Y(DOD[1])); -endmodule - -module RAM64M ( - output DOA, - output DOB, - output DOC, - output DOD, - (* techmap_autopurge *) input [5:0] ADDRA, - (* techmap_autopurge *) input [5:0] ADDRB, - (* techmap_autopurge *) input [5:0] ADDRC, - (* techmap_autopurge *) input [5:0] ADDRD, - (* techmap_autopurge *) input DIA, - (* techmap_autopurge *) input DIB, - (* techmap_autopurge *) input DIC, - (* techmap_autopurge *) input DID, - (* techmap_autopurge *) input WCLK, - (* techmap_autopurge *) input WE -); - parameter [63:0] INIT_A = 64'h0000000000000000; - parameter [63:0] INIT_B = 64'h0000000000000000; - parameter [63:0] INIT_C = 64'h0000000000000000; - parameter [63:0] INIT_D = 64'h0000000000000000; - parameter [0:0] IS_WCLK_INVERTED = 1'b0; - wire $DOA, $DOB, $DOC, $DOD; - RAM64M #( - .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), - .IS_WCLK_INVERTED(IS_WCLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), - .WCLK(WCLK), .WE(WE), - .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), - .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) - ); - $__ABC9_RAM6 doa (.A($DOA), .S(ADDRA), .Y(DOA)); - $__ABC9_RAM6 dob (.A($DOB), .S(ADDRB), .Y(DOB)); - $__ABC9_RAM6 doc (.A($DOC), .S(ADDRC), .Y(DOC)); - $__ABC9_RAM6 dod (.A($DOD), .S(ADDRD), .Y(DOD)); -endmodule - -module SRL16 ( - output Q, - (* techmap_autopurge *) input A0, A1, A2, A3, CLK, D -); - parameter [15:0] INIT = 16'h0000; - wire $Q; - SRL16 #( - .INIT(INIT), - ) _TECHMAP_REPLACE_ ( - .Q($Q), - .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CLK(CLK), .D(D) - ); - $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); -endmodule - -module SRL16E ( - output Q, - (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D -); - parameter [15:0] INIT = 16'h0000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - wire $Q; - SRL16E #( - .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .Q($Q), - .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) - ); - $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); -endmodule - -module SRLC16 ( - output Q, Q15, - (* techmap_autopurge *) input A0, A1, A2, A3, CLK, D -); - parameter [15:0] INIT = 16'h0000; - wire $Q; - SRLC16 #( - .INIT(INIT), - ) _TECHMAP_REPLACE_ ( - .Q($Q), .Q(Q15), - .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CLK(CLK), .D(D) - ); - $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); -endmodule - -module SRLC16E ( - output Q, Q15, - (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D -); - parameter [15:0] INIT = 16'h0000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - wire $Q; - SRLC16E #( - .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .Q($Q), .Q(Q15), - .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) - ); - $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); -endmodule - -module SRLC32E ( - output Q, - output Q31, - (* techmap_autopurge *) input [4:0] A, - (* techmap_autopurge *) input CE, CLK, D -); - parameter [31:0] INIT = 32'h00000000; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - wire $Q; - SRLC32E #( - .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) - ) _TECHMAP_REPLACE_ ( - .Q($Q), .Q31(Q31), - .A(A), .CE(CE), .CLK(CLK), .D(D) - ); - $__ABC9_RAM6 q (.A($Q), .S({1'b1, A}), .Y(Q)); -endmodule - -module DSP48E1 ( - (* techmap_autopurge *) output [29:0] ACOUT, - (* techmap_autopurge *) output [17:0] BCOUT, - (* techmap_autopurge *) output reg CARRYCASCOUT, - (* techmap_autopurge *) output reg [3:0] CARRYOUT, - (* techmap_autopurge *) output reg MULTSIGNOUT, - (* techmap_autopurge *) output OVERFLOW, - (* techmap_autopurge *) output reg signed [47:0] P, - (* techmap_autopurge *) output PATTERNBDETECT, - (* techmap_autopurge *) output PATTERNDETECT, - (* techmap_autopurge *) output [47:0] PCOUT, - (* techmap_autopurge *) output UNDERFLOW, - (* techmap_autopurge *) input signed [29:0] A, - (* techmap_autopurge *) input [29:0] ACIN, - (* techmap_autopurge *) input [3:0] ALUMODE, - (* techmap_autopurge *) input signed [17:0] B, - (* techmap_autopurge *) input [17:0] BCIN, - (* techmap_autopurge *) input [47:0] C, - (* techmap_autopurge *) input CARRYCASCIN, - (* techmap_autopurge *) input CARRYIN, - (* techmap_autopurge *) input [2:0] CARRYINSEL, - (* techmap_autopurge *) input CEA1, - (* techmap_autopurge *) input CEA2, - (* techmap_autopurge *) input CEAD, - (* techmap_autopurge *) input CEALUMODE, - (* techmap_autopurge *) input CEB1, - (* techmap_autopurge *) input CEB2, - (* techmap_autopurge *) input CEC, - (* techmap_autopurge *) input CECARRYIN, - (* techmap_autopurge *) input CECTRL, - (* techmap_autopurge *) input CED, - (* techmap_autopurge *) input CEINMODE, - (* techmap_autopurge *) input CEM, - (* techmap_autopurge *) input CEP, - (* techmap_autopurge *) input CLK, - (* techmap_autopurge *) input [24:0] D, - (* techmap_autopurge *) input [4:0] INMODE, - (* techmap_autopurge *) input MULTSIGNIN, - (* techmap_autopurge *) input [6:0] OPMODE, - (* techmap_autopurge *) input [47:0] PCIN, - (* techmap_autopurge *) input RSTA, - (* techmap_autopurge *) input RSTALLCARRYIN, - (* techmap_autopurge *) input RSTALUMODE, - (* techmap_autopurge *) input RSTB, - (* techmap_autopurge *) input RSTC, - (* techmap_autopurge *) input RSTCTRL, - (* techmap_autopurge *) input RSTD, - (* techmap_autopurge *) input RSTINMODE, - (* techmap_autopurge *) input RSTM, - (* techmap_autopurge *) input RSTP -); - parameter integer ACASCREG = 1; - parameter integer ADREG = 1; - parameter integer ALUMODEREG = 1; - parameter integer AREG = 1; - parameter AUTORESET_PATDET = "NO_RESET"; - parameter A_INPUT = "DIRECT"; - parameter integer BCASCREG = 1; - parameter integer BREG = 1; - parameter B_INPUT = "DIRECT"; - parameter integer CARRYINREG = 1; - parameter integer CARRYINSELREG = 1; - parameter integer CREG = 1; - parameter integer DREG = 1; - parameter integer INMODEREG = 1; - parameter integer MREG = 1; - parameter integer OPMODEREG = 1; - parameter integer PREG = 1; - parameter SEL_MASK = "MASK"; - parameter SEL_PATTERN = "PATTERN"; - parameter USE_DPORT = "FALSE"; - parameter USE_MULT = "MULTIPLY"; - parameter USE_PATTERN_DETECT = "NO_PATDET"; - parameter USE_SIMD = "ONE48"; - parameter [47:0] MASK = 48'h3FFFFFFFFFFF; - parameter [47:0] PATTERN = 48'h000000000000; - parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; - parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; - parameter [0:0] IS_CLK_INVERTED = 1'b0; - parameter [4:0] IS_INMODE_INVERTED = 5'b0; - parameter [6:0] IS_OPMODE_INVERTED = 7'b0; - - wire [47:0] $P, $PCOUT; - - DSP48E1 #( - .ACASCREG(ACASCREG), - .ADREG(ADREG), - .ALUMODEREG(ALUMODEREG), - .AREG(AREG), - .AUTORESET_PATDET(AUTORESET_PATDET), - .A_INPUT(A_INPUT), - .BCASCREG(BCASCREG), - .BREG(BREG), - .B_INPUT(B_INPUT), - .CARRYINREG(CARRYINREG), - .CARRYINSELREG(CARRYINSELREG), - .CREG(CREG), - .DREG(DREG), - .INMODEREG(INMODEREG), - .MREG(MREG), - .OPMODEREG(OPMODEREG), - .PREG(PREG), - .SEL_MASK(SEL_MASK), - .SEL_PATTERN(SEL_PATTERN), - .USE_DPORT(USE_DPORT), - .USE_MULT(USE_MULT), - .USE_PATTERN_DETECT(USE_PATTERN_DETECT), - .USE_SIMD(USE_SIMD), - .MASK(MASK), - .PATTERN(PATTERN), - .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), - .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), - .IS_CLK_INVERTED(IS_CLK_INVERTED), - .IS_INMODE_INVERTED(IS_INMODE_INVERTED), - .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) - ) _TECHMAP_REPLACE_ ( - .ACOUT(ACOUT), - .BCOUT(BCOUT), - .CARRYCASCOUT(CARRYCASCOUT), - .CARRYOUT(CARRYOUT), - .MULTSIGNOUT(MULTSIGNOUT), - .OVERFLOW(OVERFLOW), - .P($P), - .PATTERNBDETECT(PATTERNBDETECT), - .PATTERNDETECT(PATTERNDETECT), - .PCOUT($PCOUT), - .UNDERFLOW(UNDERFLOW), - .A(A), - .ACIN(ACIN), - .ALUMODE(ALUMODE), - .B(B), - .BCIN(BCIN), - .C(C), - .CARRYCASCIN(CARRYCASCIN), - .CARRYIN(CARRYIN), - .CARRYINSEL(CARRYINSEL), - .CEA1(CEA1), - .CEA2(CEA2), - .CEAD(CEAD), - .CEALUMODE(CEALUMODE), - .CEB1(CEB1), - .CEB2(CEB2), - .CEC(CEC), - .CECARRYIN(CECARRYIN), - .CECTRL(CECTRL), - .CED(CED), - .CEINMODE(CEINMODE), - .CEM(CEM), - .CEP(CEP), - .CLK(CLK), - .D(D), - .INMODE(INMODE), - .MULTSIGNIN(MULTSIGNIN), - .OPMODE(OPMODE), - .PCIN(PCIN), - .RSTA(RSTA), - .RSTALLCARRYIN(RSTALLCARRYIN), - .RSTALUMODE(RSTALUMODE), - .RSTB(RSTB), - .RSTC(RSTC), - .RSTCTRL(RSTCTRL), - .RSTD(RSTD), - .RSTINMODE(RSTINMODE), - .RSTM(RSTM), - .RSTP(RSTP) - ); - $__ABC9_DSP48E1 #( - .ADREG(ADREG), - .AREG(AREG), - .BREG(BREG), - .CREG(CREG), - .DREG(DREG), - .MREG(MREG), - .PREG(PREG), - .USE_DPORT(USE_DPORT), - .USE_MULT(USE_MULT) - ) dsp_comb ( - .$A(A), .$B(B), .$C(C), .$D(D), .$P($P), .$PCIN(PCIN), .$PCOUT($PCOUT), .P(P), .PCOUT(PCOUT)); -endmodule diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v index 2d109ef8a..db44ff00b 100644 --- a/techlibs/xilinx/abc9_model.v +++ b/techlibs/xilinx/abc9_model.v @@ -37,174 +37,3 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); (S1 => O) = 273; endspecify endmodule - -// Box to emulate async behaviour of FDC* -(* abc9_box, lib_whitebox *) -module \$__ABC9_ASYNC0 (input A, S, output Y); - assign Y = S ? 1'b0 : A; - specify - (A => Y) = 0; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 - (S => Y) = 764; - endspecify -endmodule - -// Box to emulate async behaviour of FDP* -(* abc9_box, lib_whitebox *) -module \$__ABC9_ASYNC1 (input A, S, output Y); - assign Y = S ? 1'b1 : A; - specify - (A => Y) = 0; - // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 - (S => Y) = 764; - endspecify -endmodule - -// Box to emulate comb/seq behaviour of RAM{32,64} and SRL{16,32} -// Necessary since RAMD* and SRL* have both combinatorial (i.e. -// same-cycle read operation) and sequential (write operation -// is only committed on the next clock edge). -// To model the combinatorial path, such cells have to be split -// into comb and seq parts, with this box modelling only the former. -(* abc9_box *) -module \$__ABC9_RAM6 (input A, input [5:0] S, output Y); - specify - (A => Y) = 0; - (S[0] => Y) = 642; - (S[1] => Y) = 631; - (S[2] => Y) = 472; - (S[3] => Y) = 407; - (S[4] => Y) = 238; - (S[5] => Y) = 127; - endspecify -endmodule -// Box to emulate comb/seq behaviour of RAM128 -(* abc9_box *) -module \$__ABC9_RAM7 (input A, input [6:0] S, output Y); - specify - (A => Y) = 0; - // https://github.com/SymbiFlow/prjxray-db/blob/1c85daf1b115da4d27ca83c6b89f53a94de39748/artix7/timings/slicel.sdf#L867 - (S[0] => Y) = 642 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (S[1] => Y) = 631 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (S[2] => Y) = 472 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (S[3] => Y) = 407 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (S[4] => Y) = 238 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (S[5] => Y) = 127 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; - (S[6] => Y) = 0 + 296 /* to select F7BMUX */ + 174 /* CMUX */; - endspecify -endmodule - -// Boxes used to represent the comb behaviour of DSP48E1 -(* abc9_box *) -module $__ABC9_DSP48E1 ( - input [29:0] $A, - input [17:0] $B, - input [47:0] $C, - input [24:0] $D, - input [47:0] $P, - input [47:0] $PCIN, - input [47:0] $PCOUT, - output [47:0] P, - output [47:0] PCOUT -); - parameter integer ADREG = 1; - parameter integer AREG = 1; - parameter integer BREG = 1; - parameter integer CREG = 1; - parameter integer DREG = 1; - parameter integer MREG = 1; - parameter integer PREG = 1; - parameter USE_DPORT = "FALSE"; - parameter USE_MULT = "MULTIPLY"; - - function integer \A.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \A.P.comb = 2823; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.P.comb = 3806; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \A.P.comb = 1523; - end - endfunction - function integer \A.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \A.PCOUT.comb = 2970; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.PCOUT.comb = 3954; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \A.PCOUT.comb = 1671; - end - endfunction - function integer \B.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \B.P.comb = 2690; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.P.comb = 2690; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \B.P.comb = 1509; - end - endfunction - function integer \B.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \B.PCOUT.comb = 2838; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.PCOUT.comb = 2838; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \B.PCOUT.comb = 1658; - end - endfunction - function integer \C.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \C.P.comb = 1325; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.P.comb = 1325; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \C.P.comb = 1325; - end - endfunction - function integer \C.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") \C.PCOUT.comb = 1474; - else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.PCOUT.comb = 1474; - else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") \C.PCOUT.comb = 1474; - end - endfunction - function integer \D.P.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \D.P.comb = 3717; - end - endfunction - function integer \D.PCOUT.comb ; - begin - if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \D.PCOUT.comb = 3700; - end - endfunction - - specify - ($P *> P) = 0; - ($PCOUT *> PCOUT) = 0; - endspecify - - // Identical comb delays to DSP48E1 in cells_sim.v - generate - if (PREG == 0 && MREG == 0 && AREG == 0 && ADREG == 0) - specify - ($A *> P) = \A.P.comb (); - ($A *> PCOUT) = \A.PCOUT.comb (); - endspecify - - if (PREG == 0 && MREG == 0 && BREG == 0) - specify - ($B *> P) = \B.P.comb (); - ($B *> PCOUT) = \B.PCOUT.comb (); - endspecify - - if (PREG == 0 && CREG == 0) - specify - ($C *> P) = \C.P.comb (); - ($C *> PCOUT) = \C.PCOUT.comb (); - endspecify - - if (PREG == 0 && MREG == 0 && ADREG == 0 && DREG == 0) - specify - ($D *> P) = \D.P.comb (); - ($D *> PCOUT) = \D.PCOUT.comb (); - endspecify - - if (PREG == 0) - specify - ($PCIN *> P) = 1107; - ($PCIN *> PCOUT) = 1255; - endspecify - endgenerate -endmodule diff --git a/techlibs/xilinx/abc9_unmap.v b/techlibs/xilinx/abc9_unmap.v deleted file mode 100644 index 49a7bd88c..000000000 --- a/techlibs/xilinx/abc9_unmap.v +++ /dev/null @@ -1,57 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * 2019 Eddie Hung - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -// ============================================================================ - -(* techmap_celltype = "$__ABC9_ASYNC0 $__ABC9_ASYNC1" *) -module $__ABC9_ASYNC01(input A, S, output Y); - assign Y = A; -endmodule - -module $__ABC9_RAM6(input A, input [5:0] S, output Y); - assign Y = A; -endmodule -module $__ABC9_RAM7(input A, input [6:0] S, output Y); - assign Y = A; -endmodule - -module $__ABC9_DSP48E1( - input [29:0] $A, - input [17:0] $B, - input [47:0] $C, - input [24:0] $D, - input [47:0] $P, - input [47:0] $PCIN, - input [47:0] $PCOUT, - output [47:0] P, - output [47:0] PCOUT -); - parameter integer ADREG = 1; - parameter integer AREG = 1; - parameter integer BREG = 1; - parameter integer CREG = 1; - parameter integer DREG = 1; - parameter integer MREG = 1; - parameter integer PREG = 1; - parameter USE_DPORT = "FALSE"; - parameter USE_MULT = "MULTIPLY"; - - assign P = $P, PCOUT = $PCOUT; -endmodule diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 25df3a865..a6eb9a90e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -524,10 +524,10 @@ module FDRE ( $setup(R , posedge C &&& !IS_C_INVERTED, 404); $setup(R , negedge C &&& IS_C_INVERTED, 404); // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 - if (!IS_C_INVERTED && R ^ IS_R_INVERTED) (posedge C => (Q : 1'b0)) = 303; - if ( IS_C_INVERTED && R ^ IS_R_INVERTED) (negedge C => (Q : 1'b0)) = 303; - if (!IS_C_INVERTED && R ~^ IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && R ~^ IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if (!IS_C_INVERTED && R != IS_R_INVERTED) (posedge C => (Q : 1'b0)) = 303; + if ( IS_C_INVERTED && R != IS_R_INVERTED) (negedge C => (Q : 1'b0)) = 303; + if (!IS_C_INVERTED && R == IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if ( IS_C_INVERTED && R == IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; endspecify endmodule @@ -589,10 +589,10 @@ module FDSE ( $setup(S , posedge C &&& !IS_C_INVERTED, 404); $setup(S , negedge C &&& IS_C_INVERTED, 404); // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 - if (!IS_C_INVERTED && S ^ IS_S_INVERTED) (posedge C => (Q : 1'b1)) = 303; - if ( IS_C_INVERTED && S ^ IS_S_INVERTED) (negedge C => (Q : 1'b1)) = 303; - if (!IS_C_INVERTED && S ~^ IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && S ~^ IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if (!IS_C_INVERTED && S != IS_S_INVERTED) (posedge C => (Q : 1'b1)) = 303; + if ( IS_C_INVERTED && S != IS_S_INVERTED) (negedge C => (Q : 1'b1)) = 303; + if (!IS_C_INVERTED && S == IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if ( IS_C_INVERTED && S == IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; endspecify endmodule @@ -656,6 +656,7 @@ module FDRSE ( Q <= d; endmodule +(* abc9_box, lib_whitebox *) module FDCE ( output reg Q, (* clkbuf_sink *) @@ -691,13 +692,15 @@ module FDCE ( $setup(CLR, posedge C &&& !IS_C_INVERTED, 404); $setup(CLR, negedge C &&& IS_C_INVERTED, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 - //if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 - //if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 - if (!IS_C_INVERTED && CLR ~^ IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && CLR ~^ IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if (IS_CLR_INVERTED != CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path + if (!IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if ( IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; endspecify endmodule +(* abc9_box, lib_whitebox *) module FDCE_1 ( output reg Q, (* clkbuf_sink *) @@ -717,11 +720,14 @@ module FDCE_1 ( // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 $setup(CLR, negedge C, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 - //(posedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 + if (CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path if (!CLR && CE) (negedge C => (Q : D)) = 303; endspecify endmodule +//(* abc9_box, lib_whitebox *) module FDPE ( output reg Q, (* clkbuf_sink *) @@ -756,13 +762,15 @@ module FDPE ( $setup(PRE, posedge C &&& !IS_C_INVERTED, 404); $setup(PRE, negedge C &&& IS_C_INVERTED, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 - //if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 - //if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 - if (!IS_C_INVERTED && PRE ~^ IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; - if ( IS_C_INVERTED && PRE ~^ IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if (IS_PRE_INVERTED != PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path + if (!IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; + if ( IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; endspecify endmodule +(* abc9_box, lib_whitebox *) module FDPE_1 ( output reg Q, (* clkbuf_sink *) @@ -782,8 +790,9 @@ module FDPE_1 ( // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 $setup(PRE, negedge C, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 - //if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 - //if (IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 + if (PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path if (!PRE && CE) (negedge C => (Q : D)) = 303; endspecify endmodule @@ -1395,6 +1404,7 @@ module RAM16X1D_1 ( always @(negedge clk) if (WE) mem[a] <= D; endmodule +(* abc9_box, lib_whitebox *) module RAM32X1D ( output DPO, SPO, input D, @@ -1441,15 +1451,15 @@ module RAM32X1D ( if (!IS_WCLK_INVERTED) (posedge WCLK => (DPO : 1'bx)) = 1153; if ( IS_WCLK_INVERTED) (posedge WCLK => (SPO : D)) = 1153; if ( IS_WCLK_INVERTED) (negedge WCLK => (DPO : 1'bx)) = 1153; - // Captured by $__ABC9_RAM6 - //({A0,DPRA0} => {SPO,DPO}) = 642; - //({A1,DPRA1} => {SPO,DPO}) = 631; - //({A2,DPRA2} => {SPO,DPO}) = 472; - //({A3,DPRA3} => {SPO,DPO}) = 407; - //({A4,DPRA4} => {SPO,DPO}) = 238; + (A0 => SPO) = 642; (DPRA0 => DPO) = 642; + (A1 => SPO) = 632; (DPRA1 => DPO) = 631; + (A2 => SPO) = 472; (DPRA2 => DPO) = 472; + (A3 => SPO) = 407; (DPRA3 => DPO) = 407; + (A4 => SPO) = 238; (DPRA4 => DPO) = 238; endspecify endmodule +(* abc9_box, lib_whitebox *) module RAM32X1D_1 ( output DPO, SPO, input D, @@ -1491,15 +1501,15 @@ module RAM32X1D_1 ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 if (WE) (negedge WCLK => (SPO : D)) = 1153; if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; - // Captured by $__ABC9_RAM6 - //({A0,DPRA0} => {SPO,DPO}) = 642; - //({A1,DPRA1} => {SPO,DPO}) = 631; - //({A2,DPRA2} => {SPO,DPO}) = 472; - //({A3,DPRA3} => {SPO,DPO}) = 407; - //({A4,DPRA4} => {SPO,DPO}) = 238; + (A0 => SPO) = 642; (DPRA0 => DPO) = 642; + (A1 => SPO) = 632; (DPRA1 => DPO) = 631; + (A2 => SPO) = 472; (DPRA2 => DPO) = 472; + (A3 => SPO) = 407; (DPRA3 => DPO) = 407; + (A4 => SPO) = 238; (DPRA4 => DPO) = 238; endspecify endmodule +(* abc9_box, lib_whitebox *) module RAM64X1D ( output DPO, SPO, input D, @@ -1549,13 +1559,12 @@ module RAM64X1D ( if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DPO : 1'bx)) = 1153; if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (SPO : D)) = 1153; if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153; - // Captured by $__ABC9_RAM6 - //({A0,DPRA0} => {SPO,DPO}) = 642; - //({A1,DPRA1} => {SPO,DPO}) = 631; - //({A2,DPRA2} => {SPO,DPO}) = 472; - //({A3,DPRA3} => {SPO,DPO}) = 407; - //({A4,DPRA4} => {SPO,DPO}) = 238; - //({A5,DPRA5} => {SPO,DPO}) = 127; + (A0 => SPO) = 642; (DPRA0 => DPO) = 642; + (A1 => SPO) = 632; (DPRA1 => DPO) = 631; + (A2 => SPO) = 472; (DPRA2 => DPO) = 472; + (A3 => SPO) = 407; (DPRA3 => DPO) = 407; + (A4 => SPO) = 238; (DPRA4 => DPO) = 238; + (A5 => SPO) = 127; (DPRA5 => DPO) = 127; endspecify endmodule @@ -1598,9 +1607,16 @@ module RAM64X1D_1 ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 if (WE) (negedge WCLK => (SPO : D)) = 1153; if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; + (A0 => SPO) = 642; (DPRA0 => DPO) = 642; + (A1 => SPO) = 632; (DPRA1 => DPO) = 631; + (A2 => SPO) = 472; (DPRA2 => DPO) = 472; + (A3 => SPO) = 407; (DPRA3 => DPO) = 407; + (A4 => SPO) = 238; (DPRA4 => DPO) = 238; + (A5 => SPO) = 127; (DPRA5 => DPO) = 127; endspecify endmodule +(* abc9_box, lib_whitebox *) module RAM128X1D ( output DPO, SPO, input D, @@ -1645,21 +1661,20 @@ module RAM128X1D ( if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D)) = 1153 + 217 /* to cross F7AMUX */ + 175 /* AMUX */; if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; `endif - // Captured by $__ABC9_RAM7 - //(A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - //(A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - //(A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - //(A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - //(A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - //(A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; - //(A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */; - //(DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - //(DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - //(DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - //(DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - //(DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - //(DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; - //(DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */; + (A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; + (A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; + (A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; + (A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; + (A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; + (A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; + (A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */; + (DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; + (DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; + (DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; + (DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; + (DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; + (DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; + (DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */; endspecify endmodule @@ -1683,6 +1698,7 @@ endmodule // Multi port. +(* abc9_box, lib_whitebox *) module RAM32M ( output [1:0] DOA, output [1:0] DOB, @@ -1779,12 +1795,11 @@ module RAM32M ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061 if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[1] : DID[1])) = 1190; if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[1] : DID[1])) = 1190; - // Captured by $__ABC9_RAM6 - //({{2{ADDRA[0]}},{2{ADDRB[0]}},{2{ADDRC[0]}},{2{ADDRD[0]}}} => {DOA,DOB,DOC,DOD}) = 642; - //({{2{ADDRA[1]}},{2{ADDRB[1]}},{2{ADDRC[1]}},{2{ADDRD[1]}}} => {DOA,DOB,DOC,DOD}) = 631; - //({{2{ADDRA[2]}},{2{ADDRB[2]}},{2{ADDRC[2]}},{2{ADDRD[2]}}} => {DOA,DOB,DOC,DOD}) = 472; - //({{2{ADDRA[3]}},{2{ADDRB[3]}},{2{ADDRC[3]}},{2{ADDRD[3]}}} => {DOA,DOB,DOC,DOD}) = 407; - //({{2{ADDRA[4]}},{2{ADDRB[4]}},{2{ADDRC[4]}},{2{ADDRD[4]}}} => {DOA,DOB,DOC,DOD}) = 238; + (ADDRA[0] *> DOA) = 642; (ADDRB[0] *> DOB) = 642; (ADDRC[0] *> DOC) = 642; (ADDRD[0] *> DOD) = 642; + (ADDRA[1] *> DOA) = 631; (ADDRB[1] *> DOB) = 631; (ADDRC[1] *> DOC) = 631; (ADDRD[1] *> DOD) = 631; + (ADDRA[2] *> DOA) = 472; (ADDRB[2] *> DOB) = 472; (ADDRC[2] *> DOC) = 472; (ADDRD[2] *> DOD) = 472; + (ADDRA[3] *> DOA) = 407; (ADDRB[3] *> DOB) = 407; (ADDRC[3] *> DOC) = 407; (ADDRD[3] *> DOD) = 407; + (ADDRA[4] *> DOA) = 238; (ADDRB[4] *> DOB) = 238; (ADDRC[4] *> DOC) = 238; (ADDRD[4] *> DOD) = 238; endspecify endmodule @@ -1857,6 +1872,7 @@ module RAM32M16 ( end endmodule +(* abc9_box, lib_whitebox *) module RAM64M ( output DOA, output DOB, @@ -1935,12 +1951,11 @@ module RAM64M ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD : DID)) = 1163; if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD : DID)) = 1163; - // Captured by $__ABC9_RAM6 - //({ADDRA[0],ADDRB[0],ADDRC[0],ADDRD[0]} => {DOA,DOB,DOC,DOD}) = 642; - //({ADDRA[1],ADDRB[1],ADDRC[1],ADDRD[1]} => {DOA,DOB,DOC,DOD}) = 631; - //({ADDRA[2],ADDRB[2],ADDRC[2],ADDRD[2]} => {DOA,DOB,DOC,DOD}) = 472; - //({ADDRA[3],ADDRB[3],ADDRC[3],ADDRD[3]} => {DOA,DOB,DOC,DOD}) = 407; - //({ADDRA[4],ADDRB[4],ADDRC[4],ADDRD[4]} => {DOA,DOB,DOC,DOD}) = 238; + (ADDRA[0] => DOA) = 642; (ADDRB[0] => DOB) = 642; (ADDRC[0] => DOC) = 642; (ADDRD[0] => DOD) = 642; + (ADDRA[1] => DOA) = 631; (ADDRB[1] => DOB) = 631; (ADDRC[1] => DOC) = 631; (ADDRD[1] => DOD) = 631; + (ADDRA[2] => DOA) = 472; (ADDRB[2] => DOB) = 472; (ADDRC[2] => DOC) = 472; (ADDRD[2] => DOD) = 472; + (ADDRA[3] => DOA) = 407; (ADDRB[3] => DOB) = 407; (ADDRC[3] => DOC) = 407; (ADDRD[3] => DOD) = 407; + (ADDRA[4] => DOA) = 238; (ADDRB[4] => DOB) = 238; (ADDRC[4] => DOC) = 238; (ADDRD[4] => DOD) = 238; endspecify endmodule @@ -2057,6 +2072,7 @@ endmodule // Shift registers. +(* abc9_box, lib_whitebox *) module SRL16 ( output Q, input A0, A1, A2, A3, @@ -2075,14 +2091,14 @@ module SRL16 ( (posedge CLK => (Q : 1'bx)) = 1472; // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 $setup(D , posedge CLK, 173); - // Captured by $__ABC9_RAM6 - //(A0 => Q) = 631; - //(A1 => Q) = 472; - //(A2 => Q) = 407; - //(A3 => Q) = 238; + (A0 => Q) = 631; + (A1 => Q) = 472; + (A2 => Q) = 407; + (A3 => Q) = 238; endspecify endmodule +(* abc9_box, lib_whitebox *) module SRL16E ( output Q, input A0, A1, A2, A3, CE, @@ -2108,16 +2124,19 @@ module SRL16E ( $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); $setup(D , negedge CLK &&& IS_CLK_INVERTED, 173); // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 + if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; + if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; - // Captured by $__ABC9_RAM6 - //(A0 => Q) = 631; - //(A1 => Q) = 472; - //(A2 => Q) = 407; - //(A3 => Q) = 238; + (A0 => Q) = 631; + (A1 => Q) = 472; + (A2 => Q) = 407; + (A3 => Q) = 238; endspecify endmodule +(* abc9_box, lib_whitebox *) module SRLC16 ( output Q, output Q15, @@ -2134,18 +2153,20 @@ module SRLC16 ( always @(posedge CLK) r <= { r[14:0], D }; specify - // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 - (posedge CLK => (Q : 1'bx)) = 1472; // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 $setup(D , posedge CLK, 173); - // Captured by $__ABC9_RAM6 - //(A0 => Q) = 631; - //(A1 => Q) = 472; - //(A2 => Q) = 407; - //(A3 => Q) = 238; + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 + (posedge CLK => (Q : 1'bx)) = 1472; + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 + (posedge CLK => (Q15 : 1'bx)) = 1114; + (A0 => Q) = 631; + (A1 => Q) = 472; + (A2 => Q) = 407; + (A3 => Q) = 238; endspecify endmodule +(* abc9_box, lib_whitebox *) module SRLC16E ( output Q, output Q15, @@ -2172,18 +2193,23 @@ module SRLC16E ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); $setup(D , negedge CLK &&& IS_CLK_INVERTED, 173); + // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 + $setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109); + $setup(CE, negedge CLK &&& IS_CLK_INVERTED, 109); // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; - // Captured by $__ABC9_RAM6 - //(A0 => Q) = 642; - //(A1 => Q) = 631; - //(A2 => Q) = 472; - //(A3 => Q) = 407; - //(A4 => Q) = 238; + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 + if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q15 : 1'bx)) = 1114; + if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q15 : 1'bx)) = 1114; + (A0 => Q) = 631; + (A1 => Q) = 472; + (A2 => Q) = 407; + (A3 => Q) = 238; endspecify endmodule +(* abc9_box, lib_whitebox *) module SRLC32E ( output Q, output Q31, @@ -2211,18 +2237,20 @@ module SRLC32E ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); $setup(D , negedge CLK &&& IS_CLK_INVERTED, 173); + // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 + $setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109); + $setup(CE, negedge CLK &&& IS_CLK_INVERTED, 109); // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 - if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1114; - if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1114; - // Captured by $__ABC9_RAM6 - //(A0 => Q) = 642; - //(A1 => Q) = 631; - //(A2 => Q) = 472; - //(A3 => Q) = 407; - //(A4 => Q) = 238; + if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q31 : 1'bx)) = 1114; + if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q31 : 1'bx)) = 1114; + (A[0] => Q) = 642; + (A[1] => Q) = 631; + (A[2] => Q) = 472; + (A[3] => Q) = 407; + (A[4] => Q) = 238; endspecify endmodule @@ -2990,6 +3018,8 @@ endmodule // Virtex 6, Series 7. +(* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG), + lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *) module DSP48E1 ( output [29:0] ACOUT, output [17:0] BCOUT, diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index d6ca9e57e..d05715ec2 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -598,7 +598,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_ffs", "('-abc9' only)")) { if (abc9 || help_mode) { if (dff || help_mode) - run("zinit -all", "('-dff' only)"); + run("zinit -all t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "('-dff' only)"); run("techmap -map " + ff_map_file); } } @@ -615,7 +615,6 @@ struct SynthXilinxPass : public ScriptPass if (family != "xc7") log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " "will use timing for 'xc7' instead.\n", family.c_str()); - run("techmap -map +/xilinx/abc9_map.v -max_iter 1"); run("read_verilog -icells -lib -specify +/xilinx/abc9_model.v"); std::string abc9_opts; std::string k = "synth_xilinx.abc9.W"; @@ -630,7 +629,6 @@ struct SynthXilinxPass : public ScriptPass if (dff) abc9_opts += " -dff"; run("abc9" + abc9_opts); - run("techmap -map +/xilinx/abc9_unmap.v"); } else { std::string abc_opts; diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index 15343970f..fd343969b 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -46,16 +46,40 @@ FDCE #(.INIT(1)) fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2])); FDPE #(.INIT(1)) fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3])); FDRE_1 #(.INIT(1)) fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4])); FDSE_1 #(.INIT(1)) fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5])); -FDCE_1 #(.INIT(1)) fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); +FDCE_1 /*#(.INIT(1))*/ fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); FDPE_1 #(.INIT(1)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); endmodule EOT -logger -expect warning "Module '\$paramod\\FDRE\\INIT=1' contains a \$_DFF_P_ cell .*" 1 -logger -expect warning "Module '\$paramod\\FDRE_1\\INIT=1' contains a \$_DFF_N_ cell .*" 1 -logger -expect warning "Module 'FDSE' contains a \$_DFF_P_ cell .*" 1 -logger -expect warning "Module '\$paramod\\FDSE_1\\INIT=1' contains a \$_DFF_N_ cell .*" 1 +logger -expect warning "Module '\$paramod\\FDRE\\INIT=1' contains a \$dff cell .*" 1 +logger -expect warning "Module '\$paramod\\FDRE_1\\INIT=1' contains a \$dff cell .*" 1 +logger -expect warning "Module 'FDSE' contains a \$dff cell .*" 1 +logger -expect warning "Module '\$paramod\\FDSE_1\\INIT=1' contains a \$dff cell .*" 1 equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf design -load postopt select -assert-count 8 t:FD* + +design -reset +read_verilog < Date: Tue, 21 Apr 2020 12:30:25 -0700 Subject: abc9_ops: cleanup; -prep_dff -> -prep_dff_submod --- passes/techmap/abc9.cc | 6 +++--- passes/techmap/abc9_ops.cc | 30 +++++++++++------------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index ff9b46b5f..3355cd7aa 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -298,9 +298,9 @@ struct Abc9Pass : public ScriptPass run("opt"); if (dff_mode) { if (!help_mode) - active_design->scratchpad_unset("abc9_ops.prep_dff_map.did_something"); - run("abc9_ops -prep_dff_map", "(only if -dff)"); // rewrite specify - bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_map.did_something"); + active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something"); + run("abc9_ops -prep_dff_submod", "(only if -dff)"); // rewrite specify + bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_submod.did_something"); if (did_something) { // select all $_DFF_[NP]_ // then select all its fanins diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 25ac5c340..bc20d4731 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -191,10 +191,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) // because ABC9 doesn't support them if (init != State::S0) { log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); - // TODO: still necessary? - // Do not use set_bool_attribute() as it will unset the value - // and (attributes.count(ID::abc9_flop) will fail) - derived_module->attributes[ID::abc9_flop] = false; + derived_module->set_bool_attribute(ID::abc9_flop, false); goto skip_cell; } break; @@ -214,10 +211,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) goto skip_cell; } - // TODO: still necessary? - // Do not use set_bool_attribute() as it will unset the value - // and (attributes.count(ID::abc9_box) will fail) - derived_module->attributes[ID::abc9_box] = false; + derived_module->set_bool_attribute(ID::abc9_box, false); } if (derived_type != cell->type) { @@ -273,9 +267,7 @@ void prep_bypass(RTLIL::Design *design) log_assert(inst_module); if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) continue; - // Skip if (* abc9_box *) exists or is true - auto it = inst_module->attributes.find(ID::abc9_box); - if (it == inst_module->attributes.end() || it->second.as_bool()) + if (!inst_module->get_bool_attribute(ID::abc9_box)) continue; @@ -464,7 +456,7 @@ void prep_dff(RTLIL::Design *design) } } -void prep_dff_map(RTLIL::Design *design) +void prep_dff_submod(RTLIL::Design *design) { for (auto module : design->modules()) { vector specify_cells; @@ -512,7 +504,7 @@ void prep_dff_map(RTLIL::Design *design) cell->setPort(ID::DST, DST); } - design->scratchpad_set_bool("abc9_ops.prep_dff_map.did_something", true); + design->scratchpad_set_bool("abc9_ops.prep_dff_submod.did_something", true); } } @@ -1548,7 +1540,7 @@ struct Abc9OpsPass : public Pass { log(" select all (* abc9_flop *) modules instantiated in the design and store\n"); log(" in the named selection '$abc9_flops'.\n"); log("\n"); - log(" -prep_dff_map\n"); + log(" -prep_dff_submod\n"); log(" within (* abc9_flop *) modules, attach dummy buffers to all ports and move\n"); log(" all $specify3/$specrule cells that share a 'DST' port with the $_DFF_[NP]_.Q\n"); log(" port from this 'Q' port to the DFF's 'D' port. this is to ensure that all\n"); @@ -1608,7 +1600,7 @@ struct Abc9OpsPass : public Pass { bool mark_scc_mode = false; bool prep_hier_mode = false; bool prep_bypass_mode = false; - bool prep_dff_mode = false, prep_dff_map_mode = false, prep_dff_unmap_mode = false; + bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false; bool prep_xaiger_mode = false; bool prep_lut_mode = false; bool prep_box_mode = false; @@ -1647,8 +1639,8 @@ struct Abc9OpsPass : public Pass { valid = true; continue; } - if (arg == "-prep_dff_map") { - prep_dff_map_mode = true; + if (arg == "-prep_dff_submod") { + prep_dff_submod_mode = true; valid = true; continue; } @@ -1717,8 +1709,8 @@ struct Abc9OpsPass : public Pass { prep_bypass(design); if (prep_dff_mode) prep_dff(design); - if (prep_dff_map_mode) - prep_dff_map(design); + if (prep_dff_submod_mode) + prep_dff_submod(design); if (prep_dff_unmap_mode) prep_dff_unmap(design); if (prep_delays_mode) -- cgit v1.2.3 From e2044fd9c7de4534428ee4f3e8cf1448c493a7fc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 12:32:30 -0700 Subject: abc9_ops: -prep_delays to not insert delay box if input connection is const --- passes/techmap/abc9_ops.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index bc20d4731..d7280e3fd 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -804,6 +804,8 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) log_id(conn.first), log_id(cell->name), log_id(cell->type), log_id(module->name)); if (!port_wire->port_input) continue; + if (conn.second.is_fully_const()) + continue; SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); for (int i = 0; i < GetSize(conn.second); i++) { -- cgit v1.2.3 From d5a8aaba8c6160fe51214677f7452492e950b702 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 12:42:09 -0700 Subject: abc9_ops: tidy up, suppress error if no boxes/holes --- passes/techmap/abc9.cc | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 3355cd7aa..8fa1f60c5 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -296,25 +296,25 @@ struct Abc9Pass : public ScriptPass run("wbflip"); run("techmap"); run("opt"); - if (dff_mode) { + if (dff_mode || help_mode) { if (!help_mode) active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something"); - run("abc9_ops -prep_dff_submod", "(only if -dff)"); // rewrite specify + run("abc9_ops -prep_dff_submod", " (only if -dff)"); // rewrite specify bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_submod.did_something"); if (did_something) { // select all $_DFF_[NP]_ // then select all its fanins // then select all fanouts of all that // lastly remove $_DFF_[NP]_ cells - run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d"); - run("submod"); - run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop"); - run("abc9_ops -prep_dff_unmap"); - run("design -copy-to $abc9 *_$abc9_flop"); // copy submod out - run("delete *_$abc9_flop"); + run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)"); + run("submod", " (only if -dff)"); + run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)"); + run("abc9_ops -prep_dff_unmap", " (only if -dff)"); + run("design -copy-to $abc9 *_$abc9_flop", " (only if -dff)"); // copy submod out + run("delete *_$abc9_flop", " (only if -dff)"); if (help_mode) { run("foreach module in design"); - run(" rename _$abc9_flop _TECHMAP_REPLACE_"); + run(" rename _$abc9_flop _TECHMAP_REPLACE_", " (only if -dff)"); } else { // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs @@ -346,17 +346,17 @@ struct Abc9Pass : public ScriptPass run(stringf("abc9_ops -prep_lut %d", maxlut)); if (help_mode) run("abc9_ops -prep_box", "(skip if -box)"); - else if (box_file.empty()) { + else if (box_file.empty()) run("abc9_ops -prep_box"); + if (saved_designs.count("$abc9_holes") || help_mode) { + run("design -stash $abc9"); + run("design -load $abc9_holes"); + run("techmap -wb -map %$abc9 -map +/techmap.v"); + run("opt -purge"); + run("design -stash $abc9_holes"); + run("design -load $abc9"); + run("design -delete $abc9"); } - run("design -stash $abc9"); - run("design -load $abc9_holes"); - run("techmap -wb -map %$abc9 -map +/techmap.v"); - run("opt -purge"); - run("aigmap"); - run("design -stash $abc9_holes"); - run("design -load $abc9"); - run("design -delete $abc9"); } if (check_label("exe")) { -- cgit v1.2.3 From b3e2538a140cac36c32b133d4475a052cfc46809 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 14:12:28 -0700 Subject: abc9_ops: fix bypass boxes using (* abc9_bypass *) --- kernel/constids.inc | 3 +-- passes/techmap/abc9_ops.cc | 21 +++++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/kernel/constids.inc b/kernel/constids.inc index 6b40a5908..25996d2d8 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -2,10 +2,9 @@ X(A) X(abc9_box) X(abc9_box_id) X(abc9_box_seq) +X(abc9_bypass) X(abc9_carry) X(abc9_flop) -X(abc9_holes) -X(abc9_init) X(abc9_lut) X(abc9_mergeability) X(abc9_scc) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index d7280e3fd..37d0528c1 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -102,7 +102,7 @@ void check(RTLIL::Design *design, bool dff_mode) auto inst_module = design->module(cell->type); if (!inst_module) continue; - if (!inst_module->attributes.count(ID::abc9_flop)) + if (!inst_module->get_bool_attribute(ID::abc9_flop)) continue; auto derived_type = inst_module->derive(design, cell->parameters); if (!processed.insert(derived_type).second) @@ -171,9 +171,9 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) continue; - if (inst_module->attributes.count(ID::abc9_flop) && !dff_mode) + if (inst_module->get_bool_attribute(ID::abc9_flop) && !dff_mode) continue; - if (!inst_module->attributes.count(ID::abc9_box) && !inst_module->attributes.count(ID::abc9_flop)) + if (!inst_module->get_bool_attribute(ID::abc9_box) && !inst_module->get_bool_attribute(ID::abc9_flop)) continue; if (!unmap_design->module(derived_type)) { @@ -205,13 +205,11 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) break; } - if (!found) { - derived_module->set_bool_attribute(ID::abc9_box, false); - log_assert(!derived_module->attributes.count(ID::abc9_box)); + if (!found) goto skip_cell; - } derived_module->set_bool_attribute(ID::abc9_box, false); + derived_module->set_bool_attribute(ID::abc9_bypass); } if (derived_type != cell->type) { @@ -265,9 +263,8 @@ void prep_bypass(RTLIL::Design *design) auto derived_type = inst_module->derive(design, cell->parameters); inst_module = design->module(derived_type); log_assert(inst_module); - if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) - continue; - if (!inst_module->get_bool_attribute(ID::abc9_box)) + log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); + if (!inst_module->get_bool_attribute(ID::abc9_bypass)) continue; @@ -444,7 +441,7 @@ void prep_dff(RTLIL::Design *design) auto inst_module = design->module(cell->type); if (!inst_module) continue; - if (!inst_module->attributes.count(ID::abc9_flop)) + if (!inst_module->get_bool_attribute(ID::abc9_flop)) continue; auto derived_type = inst_module->derive(design, cell->parameters); auto derived_module = design->module(derived_type); @@ -589,7 +586,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) continue; auto inst_module = design->module(cell->type); - bool abc9_flop = inst_module && inst_module->attributes.count(ID::abc9_flop); + bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop); if (abc9_flop && !dff) continue; -- cgit v1.2.3 From a323881e152c0d51728f3df773ac2f326544b379 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 14:13:38 -0700 Subject: xilinx/ecp5/ice40: add (* abc9_flop *) to bypass-able cells --- techlibs/ecp5/cells_sim.v | 29 ++++++++- techlibs/ice40/cells_sim.v | 153 ++++++++++++++++++++++++++++++++++++++++++++ techlibs/xilinx/cells_sim.v | 20 +++++- 3 files changed, 198 insertions(+), 4 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 563592218..6f37823e4 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -186,6 +186,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); endmodule // --------------------------------------- +(* abc9_box, lib_whitebox *) module TRELLIS_DPR16X4 ( input [3:0] DI, input [3:0] WAD, @@ -222,10 +223,16 @@ module TRELLIS_DPR16X4 ( mem[WAD] <= DI; assign DO = mem[RAD]; + + specify + // TODO + (RAD *> DO) = 0; + endspecify endmodule // --------------------------------------- +(* abc9_box, lib_whitebox *) module DPR16X4C ( input [3:0] DI, input WCK, WRE, @@ -281,6 +288,10 @@ module DPR16X4C ( assign DO = ram[RAD]; + specify + // TODO + (RAD *> DO) = 0; + endspecify endmodule // --------------------------------------- @@ -295,7 +306,7 @@ endmodule // --------------------------------------- `ifdef YOSYS -(* abc9_flop=(SRMODE != "ASYNC"), lib_whitebox=(SRMODE != "ASYNC") *) +(* abc9_flop=(SRMODE != "ASYNC"), abc9_box=(SRMODE == "ASYNC"), lib_whitebox *) `endif module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); parameter GSR = "ENABLED"; @@ -351,15 +362,27 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); $setup(DI, negedge CLK, 0); $setup(CE, negedge CLK, 0); $setup(LSR, negedge CLK, 0); - if (muxlsr) (negedge CLK => (Q : DI)) = 0; - if (!muxlsr && muxce) (negedge CLK => (Q : srval)) = 0; +`ifndef YOSYS + if (muxlsr) (negedge CLK => (Q : srval)) = 0; +`else + if (muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif + if (!muxlsr && muxce) (negedge CLK => (Q : DI)) = 0; endspecify else specify $setup(DI, posedge CLK, 0); $setup(CE, posedge CLK, 0); $setup(LSR, posedge CLK, 0); +`ifndef YOSYS if (muxlsr) (posedge CLK => (Q : srval)) = 0; +`else + if (muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0; endspecify endgenerate diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v index 1b759a28f..ad572c877 100644 --- a/techlibs/ice40/cells_sim.v +++ b/techlibs/ice40/cells_sim.v @@ -372,6 +372,7 @@ module SB_DFFSR ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFR ( output `SB_DFF_REG, input C, R, D @@ -389,7 +390,13 @@ module SB_DFFR ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(negedge R, posedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 599; +`else + if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (!R) (posedge C => (Q : D)) = 540; endspecify @@ -402,7 +409,13 @@ module SB_DFFR ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(negedge R, posedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 883; +`else + if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (!R) (posedge C => (Q : D)) = 796; endspecify @@ -415,7 +428,13 @@ module SB_DFFR ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge R, posedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 1589; +`else + if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (!R) (posedge C => (Q : D)) = 1391; endspecify @@ -470,6 +489,7 @@ module SB_DFFSS ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFS ( output `SB_DFF_REG, input C, S, D @@ -487,7 +507,13 @@ module SB_DFFS ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(negedge S, posedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 599; +`else + if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (!S) (posedge C => (Q : D)) = 540; endspecify @@ -500,7 +526,13 @@ module SB_DFFS ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(negedge S, posedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 883; +`else + if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (!S) (posedge C => (Q : D)) = 796; endspecify @@ -513,7 +545,13 @@ module SB_DFFS ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge S, posedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 1589; +`else + if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (!S) (posedge C => (Q : D)) = 1391; endspecify @@ -576,6 +614,7 @@ module SB_DFFESR ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFER ( output `SB_DFF_REG, input C, E, R, D @@ -595,7 +634,13 @@ module SB_DFFER ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(negedge R, posedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 599; +`else + if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (E && !R) (posedge C => (Q : D)) = 540; endspecify @@ -610,7 +655,13 @@ module SB_DFFER ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(negedge R, posedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 883; +`else + if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (E && !R) (posedge C => (Q : D)) = 796; endspecify @@ -625,7 +676,13 @@ module SB_DFFER ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge R, posedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 1589; +`else + if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (E && !R) (posedge C => (Q : D)) = 1391; endspecify @@ -688,6 +745,7 @@ module SB_DFFESS ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFES ( output `SB_DFF_REG, input C, E, S, D @@ -707,7 +765,13 @@ module SB_DFFES ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(posedge S, posedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 599; +`else + if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (E && !S) (posedge C => (Q : D)) = 540; endspecify @@ -722,7 +786,13 @@ module SB_DFFES ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(posedge S, posedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 883; +`else + if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (E && !S) (posedge C => (Q : D)) = 796; endspecify @@ -737,7 +807,13 @@ module SB_DFFES ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(posedge S, posedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 1589; +`else + if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (E && !S) (posedge C => (Q : D)) = 1391; endspecify @@ -891,7 +967,13 @@ module SB_DFFNR ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(negedge R, negedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 599; +`else + if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (!R) (negedge C => (Q : D)) = 540; endspecify @@ -904,7 +986,13 @@ module SB_DFFNR ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(negedge R, negedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 883; +`else + if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (!R) (negedge C => (Q : D)) = 796; endspecify @@ -917,7 +1005,13 @@ module SB_DFFNR ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge R, negedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 1589; +`else + if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (!R) (negedge C => (Q : D)) = 1391; endspecify @@ -972,6 +1066,7 @@ module SB_DFFNSS ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFNS ( output `SB_DFF_REG, input C, S, D @@ -989,7 +1084,13 @@ module SB_DFFNS ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(negedge S, negedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 599; +`else + if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (!S) (negedge C => (Q : D)) = 540; endspecify @@ -1002,7 +1103,13 @@ module SB_DFFNS ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(negedge S, negedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 883; +`else + if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (!S) (negedge C => (Q : D)) = 796; endspecify @@ -1015,7 +1122,13 @@ module SB_DFFNS ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge S, negedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 1589; +`else + if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (!S) (negedge C => (Q : D)) = 1391; endspecify @@ -1078,6 +1191,7 @@ module SB_DFFNESR ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFNER ( output `SB_DFF_REG, input C, E, R, D @@ -1097,7 +1211,13 @@ module SB_DFFNER ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(R, negedge C, 2160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 599; +`else + if (R) (R => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (E && !R) (negedge C => (Q : D)) = 540; endspecify @@ -1112,7 +1232,13 @@ module SB_DFFNER ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(R, negedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 883; +`else + if (R) (R => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (E && !R) (negedge C => (Q : D)) = 796; endspecify @@ -1127,7 +1253,13 @@ module SB_DFFNER ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge R, negedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge R => (Q : 1'b0)) = 1589; +`else + if (R) (R => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (E && !R) (negedge C => (Q : D)) = 1391; endspecify @@ -1190,6 +1322,7 @@ module SB_DFFNESS ( `endif endmodule +(* abc9_box, lib_whitebox *) module SB_DFFNES ( output `SB_DFF_REG, input C, E, S, D @@ -1209,7 +1342,14 @@ module SB_DFFNES ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 $setup(negedge S, negedge C, 160); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 599; +`else + if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif + // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 if (E && !S) (negedge C => (Q : D)) = 540; endspecify @@ -1224,7 +1364,13 @@ module SB_DFFNES ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 $setup(negedge S, negedge C, 235); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 883; +`else + if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 if (E && !S) (negedge C => (Q : D)) = 796; endspecify @@ -1239,7 +1385,13 @@ module SB_DFFNES ( // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 $setup(negedge S, negedge C, 424); // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 +`ifndef YOSYS (posedge S => (Q : 1'b1)) = 1589; +`else + if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path +`endif // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 if (E && !S) (negedge C => (Q : D)) = 1391; endspecify @@ -2736,6 +2888,7 @@ module SB_IO_OD ( `endif endmodule +//(* abc9_box, lib_whitebox *) // TODO module SB_MAC16 ( input CLK, CE, input [15:0] C, A, B, D, diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index a6eb9a90e..cd611399e 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -692,9 +692,14 @@ module FDCE ( $setup(CLR, posedge C &&& !IS_C_INVERTED, 404); $setup(CLR, negedge C &&& IS_C_INVERTED, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 +`ifndef YOSYS + if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; + if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; +`else if (IS_CLR_INVERTED != CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path // but for facilitating a bypass box, let's pretend it's // a simple path +`endif if (!IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; if ( IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; endspecify @@ -720,14 +725,18 @@ module FDCE_1 ( // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 $setup(CLR, negedge C, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 +`ifndef YOSYS + (posedge CLR => (Q : 1'b0)) = 764; +`else if (CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path // but for facilitating a bypass box, let's pretend it's // a simple path +`endif if (!CLR && CE) (negedge C => (Q : D)) = 303; endspecify endmodule -//(* abc9_box, lib_whitebox *) +(* abc9_box, lib_whitebox *) module FDPE ( output reg Q, (* clkbuf_sink *) @@ -762,9 +771,14 @@ module FDPE ( $setup(PRE, posedge C &&& !IS_C_INVERTED, 404); $setup(PRE, negedge C &&& IS_C_INVERTED, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 +`ifndef YOSYS + if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; + if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; +`else if (IS_PRE_INVERTED != PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path // but for facilitating a bypass box, let's pretend it's // a simple path +`endif if (!IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; if ( IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; endspecify @@ -790,9 +804,13 @@ module FDPE_1 ( // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 $setup(PRE, negedge C, 404); // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 +`ifndef YOSYS + (posedge PRE => (Q : 1'b1)) = 764; +`else if (PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path // but for facilitating a bypass box, let's pretend it's // a simple path +`endif if (!PRE && CE) (negedge C => (Q : D)) = 303; endspecify endmodule -- cgit v1.2.3 From ed7cb0b095e0eaf0ced643f7f828ea2c61b939b5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 15:42:05 -0700 Subject: abc9: put 'aigmap' back --- passes/techmap/abc9.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8fa1f60c5..93751e0bc 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -353,6 +353,7 @@ struct Abc9Pass : public ScriptPass run("design -load $abc9_holes"); run("techmap -wb -map %$abc9 -map +/techmap.v"); run("opt -purge"); + run("aigmap"); run("design -stash $abc9_holes"); run("design -load $abc9"); run("design -delete $abc9"); -- cgit v1.2.3 From b65610fb628cfd38edcab3c64507477a58cbdd10 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 15:44:56 -0700 Subject: abc9_ops: move assert --- passes/techmap/abc9_ops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 37d0528c1..b3f5b9919 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -263,9 +263,9 @@ void prep_bypass(RTLIL::Design *design) auto derived_type = inst_module->derive(design, cell->parameters); inst_module = design->module(derived_type); log_assert(inst_module); - log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); if (!inst_module->get_bool_attribute(ID::abc9_bypass)) continue; + log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); // The idea is to create two techmap designs, one which maps: -- cgit v1.2.3 From 6c34945371a0446159423b0d70f9f10dbc2c4d07 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 15:45:05 -0700 Subject: xilinx/ice40/ecp5: zinit requires selected wires, so select them all --- techlibs/ecp5/synth_ecp5.cc | 2 +- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 3e475baab..0e49ef01a 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -316,7 +316,7 @@ struct SynthEcp5Pass : public ScriptPass if (!nodffe) run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); if ((abc9 && dff) || help_mode) - run("zinit -all t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); + run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); run("opt_expr -undriven -mux_undef"); run("simplemap"); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index f2270dbca..27850b075 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -362,7 +362,7 @@ struct SynthIce40Pass : public ScriptPass run("simplemap t:$dff"); } if ((abc9 && dff) || help_mode) - run("zinit -all t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); + run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); run("techmap -map +/ice40/ff_map.v"); run("opt_expr -mux_undef"); run("simplemap"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index d05715ec2..d0de73f83 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -598,7 +598,7 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_ffs", "('-abc9' only)")) { if (abc9 || help_mode) { if (dff || help_mode) - run("zinit -all t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "('-dff' only)"); + run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "('-dff' only)"); run("techmap -map " + ff_map_file); } } @@ -608,7 +608,7 @@ struct SynthXilinxPass : public ScriptPass if (flatten_before_abc) run("flatten"); if (help_mode) - run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for 'nowidelut', '-dff', '-retime')"); + run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); else if (abc9) { if (lut_size != 6) log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n"); -- cgit v1.2.3 From 7146c0339e0b79ec24bc89e7fdf15331436e0e53 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 17:03:28 -0700 Subject: timinginfo: ignore $specify2 cells if EN is false --- kernel/timinginfo.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index 36908868c..d818e580b 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -82,6 +82,9 @@ struct TimingInfo for (auto cell : module->cells()) { if (cell->type == ID($specify2)) { + auto en = cell->getPort(ID::EN); + if (en.is_fully_const() && !en.as_bool()) + continue; auto src = cell->getPort(ID::SRC); auto dst = cell->getPort(ID::DST); for (const auto &c : src.chunks()) -- cgit v1.2.3 From 8cda29137e0e1c19e1115211ee695681bc901030 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 17:04:26 -0700 Subject: ecp5: TRELLIS_FF bypass path only in async mode --- techlibs/ecp5/cells_sim.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 6f37823e4..357fd9173 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -363,11 +363,11 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); $setup(CE, negedge CLK, 0); $setup(LSR, negedge CLK, 0); `ifndef YOSYS - if (muxlsr) (negedge CLK => (Q : srval)) = 0; + if (SRMODE == "ASYNC" && muxlsr) (negedge CLK => (Q : srval)) = 0; `else - if (muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path + if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path `endif if (!muxlsr && muxce) (negedge CLK => (Q : DI)) = 0; endspecify @@ -377,11 +377,11 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); $setup(CE, posedge CLK, 0); $setup(LSR, posedge CLK, 0); `ifndef YOSYS - if (muxlsr) (posedge CLK => (Q : srval)) = 0; + if (SRMODE == "ASYNC" && muxlsr) (posedge CLK => (Q : srval)) = 0; `else - if (muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path - // but for facilitating a bypass box, let's pretend it's - // a simple path + if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path + // but for facilitating a bypass box, let's pretend it's + // a simple path `endif if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0; endspecify -- cgit v1.2.3 From 2946bb60e95408be1ffc5b667b6c84160f7f41e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 17:25:15 -0700 Subject: abc9: rework submod -- since it won't move (* keep *) cells --- passes/techmap/abc9.cc | 7 +++--- passes/techmap/abc9_ops.cc | 56 +++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 93751e0bc..147d6e572 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -309,9 +309,6 @@ struct Abc9Pass : public ScriptPass run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)"); run("submod", " (only if -dff)"); run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)"); - run("abc9_ops -prep_dff_unmap", " (only if -dff)"); - run("design -copy-to $abc9 *_$abc9_flop", " (only if -dff)"); // copy submod out - run("delete *_$abc9_flop", " (only if -dff)"); if (help_mode) { run("foreach module in design"); run(" rename _$abc9_flop _TECHMAP_REPLACE_", " (only if -dff)"); @@ -323,7 +320,11 @@ struct Abc9Pass : public ScriptPass if (module->cell(stringf("%s_$abc9_flop", module->name.c_str()))) run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); } + active_design->selected_active_module.clear(); } + run("abc9_ops -prep_dff_unmap", " (only if -dff)"); + run("design -copy-to $abc9 *_$abc9_flop", " (only if -dff)"); // copy submod out + run("delete *_$abc9_flop", " (only if -dff)"); } } run("design -stash $abc9_map"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index b3f5b9919..5521bdf62 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -474,22 +474,11 @@ void prep_dff_submod(RTLIL::Design *design) specify_cells.emplace_back(cell); log_assert(dff_cell); - // Add dummy buffers for all module inputs/outputs - // to ensure that these ports exists in the flop box - // created by later submod pass - for (auto port_name : module->ports) { - auto port = module->wire(port_name); - log_assert(GetSize(port) == 1); - auto c = module->addBufGate(NEW_ID, port, module->addWire(NEW_ID)); - // Need to set (* keep *) otherwise opt_clean - // inside submod will blow it away - c->set_bool_attribute(ID::keep); - } - // Add an additional buffer that drives $_DFF_[NP]_.D - // so that the flop box will have an output + // Add an always-enabled CE mux that drives $_DFF_[NP]_.D so that: + // (a) flop box will have an output + // (b) $_DFF_[NP]_.Q will be present as an input SigBit D = module->addWire(NEW_ID); - Cell *c = module->addBufGate(NEW_ID, dff_cell->getPort(ID::D), D); - c->set_bool_attribute(ID::keep); + module->addMuxGate(NEW_ID, dff_cell->getPort(ID::D), Q, State::S0, D); dff_cell->setPort(ID::D, D); // Rewrite $specify cells that end with $_DFF_[NP]_.Q @@ -513,26 +502,31 @@ void prep_dff_unmap(RTLIL::Design *design) if (!module->get_bool_attribute(ID::abc9_flop) || module->get_bool_attribute(ID::abc9_box)) continue; - auto unmap_module = unmap_design->addModule(module->name.str() + "_$abc9_flop"); - auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name); + // Make sure the box module has all the same ports present on flop cell + auto replace_cell = module->cell(ID::_TECHMAP_REPLACE_); + log_assert(replace_cell); + auto box_module = design->module(module->name.str() + "_$abc9_flop"); + log_assert(box_module); for (auto port_name : module->ports) { - auto w = unmap_module->addWire(port_name, module->wire(port_name)); - // Do not propagate (* init *) values inside the box - if (w->port_output) - w->attributes.erase(ID::init); - replace_cell->setPort(port_name, w); + auto port = module->wire(port_name); + auto box_port = box_module->wire(port_name); + if (box_port) { + // Do not propagate init -- already captured by box + box_port->attributes.erase(ID::init); + continue; + } + log_assert(port->port_input); + box_module->addWire(port_name, port); + replace_cell->setPort(port_name, port); } + box_module->fixup_ports(); - // Add new ports appearing in "_$abc9_flop" - auto box_module = design->module(unmap_module->name); - log_assert(box_module); + auto unmap_module = unmap_design->addModule(box_module->name); + replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name); for (auto port_name : box_module->ports) { - auto port = box_module->wire(port_name); - auto unmap_port = unmap_module->wire(port_name); - if (!unmap_port) - unmap_port = unmap_module->addWire(port_name, port); - else - unmap_port->port_id = port->port_id; + auto w = unmap_module->addWire(port_name, box_module->wire(port_name)); + if (module->wire(port_name)) + replace_cell->setPort(port_name, w); } unmap_module->ports = box_module->ports; unmap_module->check(); -- cgit v1.2.3 From 57c478c537ef23c05ca34ecdf4c4334fd82c104e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 17:54:24 -0700 Subject: abc9: only do +/abc9_map if `DFF --- passes/techmap/abc9.cc | 5 ++++- techlibs/common/abc9_map.v | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 147d6e572..60a88f729 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -330,7 +330,10 @@ struct Abc9Pass : public ScriptPass run("design -stash $abc9_map"); run("design -load $abc9"); run("design -delete $abc9"); - run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v"); + if (help_mode) + run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)"); + else + run(stringf("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : "")); run("design -delete $abc9_map"); } diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index 5f1822485..57b3831d8 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -1,3 +1,4 @@ +`ifdef DFF (* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; @@ -23,3 +24,4 @@ module $_DFF_x_(input C, D, output Q); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule +`endif -- cgit v1.2.3 From ca4f8c94441c16392ffc02a6117f9b3883e7042e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 Apr 2020 20:44:11 -0700 Subject: xilinx: gate specify/attributes from iverilog --- techlibs/xilinx/cells_sim.v | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index cd611399e..d87cfe91b 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1678,7 +1678,6 @@ module RAM128X1D ( // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D)) = 1153 + 217 /* to cross F7AMUX */ + 175 /* AMUX */; if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; -`endif (A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; (A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; (A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; @@ -1693,6 +1692,7 @@ module RAM128X1D ( (DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; (DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; (DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */; +`endif endspecify endmodule @@ -3036,8 +3036,10 @@ endmodule // Virtex 6, Series 7. +`ifdef YOSYS (* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG), lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *) +`endif module DSP48E1 ( output [29:0] ACOUT, output [17:0] BCOUT, -- cgit v1.2.3 From f652a9c11c75b7728db838c1c74c587ba92043ca Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 22 Apr 2020 13:07:19 -0700 Subject: abc9_ops: update docs --- passes/techmap/abc9_ops.cc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 5521bdf62..a87a94b1d 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1516,29 +1516,28 @@ struct Abc9OpsPass : public Pass { log(" derive all used (* abc9_box *) requiring bypass, or (* abc9_flop *) (if\n"); log(" -dff option) whitebox modules. with (* abc9_box *) modules, bypassing is\n"); log(" necessary if sequential elements (e.g. $dff, $mem, etc.) are discovered\n"); - log(" inside, to ensure that any combinatorial paths are correctly captured.\n"); + log(" inside to ensure that any combinatorial paths are correctly captured.\n"); log(" with (* abc9_flop *) modules, only those containing $dff/$_DFF_[NP]_\n"); log(" cells with zero initial state -- due to an ABC limitation -- will be\n"); - log(" derived. for such derived modules, add a rule inside the '$abc9_unmap'\n"); - log(" design that can map a cell instantiating a derived module back to the\n"); - log(" original cell with parameters.\n"); + log(" derived.\n"); log("\n"); log(" -prep_bypass\n"); log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n"); log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n"); - log(" (named *_$abc9_byp) that has inherited all its $specify2 (simple path)\n"); - log(" cells.\n"); + log(" (named *_$abc9_byp). this bypass box will only contain ports that are\n"); + log(" referenced by a simple path declaration ($specify2 cell) inside a\n"); + log(" specify block.\n"); log("\n"); log(" -prep_dff\n"); log(" select all (* abc9_flop *) modules instantiated in the design and store\n"); log(" in the named selection '$abc9_flops'.\n"); log("\n"); log(" -prep_dff_submod\n"); - log(" within (* abc9_flop *) modules, attach dummy buffers to all ports and move\n"); - log(" all $specify3/$specrule cells that share a 'DST' port with the $_DFF_[NP]_.Q\n"); - log(" port from this 'Q' port to the DFF's 'D' port. this is to ensure that all\n"); - log(" module ports will exist in any submodule, and prepare such specify cells to\n"); - log(" be moved within.\n"); + log(" within (* abc9_flop *) modules, rewrite all edge-sensitive path\n"); + log(" declarations and $setup() timing checks ($specify3 and $specrule cells)\n"); + log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n"); + log(" the DFF's 'D' port. this is to prepare such specify cells to be moved\n"); + log(" into the flop box.\n"); log("\n"); log(" -prep_dff_unmap\n"); log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n"); -- cgit v1.2.3 From 8d34aee3d5addfc796ca7057d38e77628c6a77b4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 22 Apr 2020 17:37:07 -0700 Subject: abc9: update to =_$abc9_flops pattern which includes whiteboxes --- passes/techmap/abc9.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 60a88f729..06097a6f7 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -323,8 +323,8 @@ struct Abc9Pass : public ScriptPass active_design->selected_active_module.clear(); } run("abc9_ops -prep_dff_unmap", " (only if -dff)"); - run("design -copy-to $abc9 *_$abc9_flop", " (only if -dff)"); // copy submod out - run("delete *_$abc9_flop", " (only if -dff)"); + run("design -copy-to $abc9 =*_$abc9_flop", " (only if -dff)"); // copy submod out + run("delete =*_$abc9_flop", " (only if -dff)"); } } run("design -stash $abc9_map"); @@ -333,7 +333,7 @@ struct Abc9Pass : public ScriptPass if (help_mode) run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)"); else - run(stringf("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : "")); + run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : "")); run("design -delete $abc9_map"); } -- cgit v1.2.3 From 39759d5f0ec9bfc0db3dd718cb035596da7f9668 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 14:12:06 -0700 Subject: ecp5: fix rebase mistake --- techlibs/ecp5/synth_ecp5.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 0e49ef01a..c13020cc1 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -348,10 +348,10 @@ struct SynthEcp5Pass : public ScriptPass else abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); if (nowidelut) - abc9_args += " -maxlut 4"; + abc9_opts += " -maxlut 4"; if (dff) - abc9_args += " -dff"; - run("abc9" + abc9_args); + abc9_opts += " -dff"; + run("abc9" + abc9_opts); run("techmap -map +/ecp5/abc9_unmap.v"); } else { std::string abc_args = " -dress"; -- cgit v1.2.3 From fdc340db8e93d5b50ef515a231f2fef18bdd8165 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 14:16:42 -0700 Subject: ecp5: synth_ecp5 to no longer need +/ecp5/abc9_{,un}map.v --- techlibs/ecp5/Makefile.inc | 3 --- techlibs/ecp5/abc9_map.v | 27 --------------------------- techlibs/ecp5/abc9_unmap.v | 5 ----- techlibs/ecp5/synth_ecp5.cc | 11 +++-------- 4 files changed, 3 insertions(+), 43 deletions(-) delete mode 100644 techlibs/ecp5/abc9_map.v delete mode 100644 techlibs/ecp5/abc9_unmap.v diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 217151e96..9a337b2b6 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -23,9 +23,6 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v)) - -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_map.v)) -$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_unmap.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_model.v)) EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk diff --git a/techlibs/ecp5/abc9_map.v b/techlibs/ecp5/abc9_map.v deleted file mode 100644 index 113a35b91..000000000 --- a/techlibs/ecp5/abc9_map.v +++ /dev/null @@ -1,27 +0,0 @@ -// --------------------------------------- - -// Attach a (combinatorial) black-box onto the output -// of this LUTRAM primitive to capture its -// asynchronous read behaviour -module TRELLIS_DPR16X4 ( - (* techmap_autopurge *) input [3:0] DI, - (* techmap_autopurge *) input [3:0] WAD, - (* techmap_autopurge *) input WRE, - (* techmap_autopurge *) input WCK, - (* techmap_autopurge *) input [3:0] RAD, - output [3:0] DO -); - parameter WCKMUX = "WCK"; - parameter WREMUX = "WRE"; - parameter [63:0] INITVAL = 64'h0000000000000000; - wire [3:0] $DO; - - TRELLIS_DPR16X4 #( - .WCKMUX(WCKMUX), .WREMUX(WREMUX), .INITVAL(INITVAL) - ) _TECHMAP_REPLACE_ ( - .DI(DI), .WAD(WAD), .WRE(WRE), .WCK(WCK), - .RAD(RAD), .DO($DO) - ); - - $__ABC9_DPR16X4_COMB do (.$DO($DO), .RAD(RAD), .DO(DO)); -endmodule diff --git a/techlibs/ecp5/abc9_unmap.v b/techlibs/ecp5/abc9_unmap.v deleted file mode 100644 index cbdffdaf1..000000000 --- a/techlibs/ecp5/abc9_unmap.v +++ /dev/null @@ -1,5 +0,0 @@ -// --------------------------------------- - -module \$__ABC9_DPR16X4_COMB (input [3:0] $DO, RAD, output [3:0] DO); - assign DO = $DO; -endmodule diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index c13020cc1..b99cbdf83 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -328,14 +328,10 @@ struct SynthEcp5Pass : public ScriptPass if (check_label("map_luts")) { - if (abc2 || help_mode) { + if (abc2 || help_mode) run("abc", " (only if -abc2)"); - } - std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v"; - if (abc9) - techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1"; - if (!techmap_args.empty()) - run("techmap " + techmap_args); + if (asyncprld || help_mode) + run("techmap -map +/ecp5/latches_map.v", "(only if -asyncprld)"); if (abc9) { run("read_verilog -icells -lib -specify +/ecp5/abc9_model.v"); @@ -352,7 +348,6 @@ struct SynthEcp5Pass : public ScriptPass if (dff) abc9_opts += " -dff"; run("abc9" + abc9_opts); - run("techmap -map +/ecp5/abc9_unmap.v"); } else { std::string abc_args = " -dress"; if (nowidelut) -- cgit v1.2.3 From cea614f5aeb78446c663240103f94f10e71681e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 14:42:18 -0700 Subject: ecp5: latches_map.v if *not* -asyncprld --- techlibs/ecp5/synth_ecp5.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index b99cbdf83..e5c1f7550 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -330,8 +330,8 @@ struct SynthEcp5Pass : public ScriptPass { if (abc2 || help_mode) run("abc", " (only if -abc2)"); - if (asyncprld || help_mode) - run("techmap -map +/ecp5/latches_map.v", "(only if -asyncprld)"); + if (!asyncprld || help_mode) + run("techmap -map +/ecp5/latches_map.v", "(skip if -asyncprld)"); if (abc9) { run("read_verilog -icells -lib -specify +/ecp5/abc9_model.v"); -- cgit v1.2.3 From e79127fcebf9c5aed47f6f56fcfc8a4c4f98705c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 18:02:05 -0700 Subject: Cleanup; reduce Module::derive() calls --- backends/aiger/xaiger.cc | 38 +++--- passes/techmap/abc9_ops.cc | 271 ++++++++++++++++++++++--------------------- techlibs/common/abc9_model.v | 6 +- techlibs/common/abc9_unmap.v | 2 +- 4 files changed, 164 insertions(+), 153 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e1962119c..413566699 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -76,6 +76,7 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { + Design *design; Module *module; SigMap sigmap; @@ -138,7 +139,7 @@ struct XAigerWriter return a; } - XAigerWriter(Module *module, bool dff_mode) : module(module), sigmap(module) + XAigerWriter(Module *module, bool dff_mode) : design(module->design), module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -240,15 +241,16 @@ struct XAigerWriter continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module) { + RTLIL::Module* inst_module = design->module(cell->type); + if (inst_module && inst_module->get_blackbox_attribute()) { IdString derived_type; if (cell->parameters.empty()) derived_type = cell->type; else - derived_type = inst_module->derive(module->design, cell->parameters); - inst_module = module->design->module(derived_type); + derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); log_assert(inst_module); + log_assert(inst_module->get_blackbox_attribute()); bool abc9_flop = false; if (!cell->has_keep_attr()) { @@ -326,9 +328,9 @@ struct XAigerWriter for (auto cell : box_list) { log_assert(cell); - RTLIL::Module* box_module = module->design->module(cell->type); + RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); - log_assert(box_module->attributes.count(ID::abc9_box_id)); + log_assert(box_module->has_attribute(ID::abc9_box_id)); auto r = box_ports.insert(cell->type); if (r.second) { @@ -576,23 +578,23 @@ struct XAigerWriter for (auto cell : box_list) { log_assert(cell); - RTLIL::Module* box_module = module->design->module(cell->type); + RTLIL::Module* box_module = design->module(cell->type); log_assert(box_module); IdString derived_type; if (cell->parameters.empty()) derived_type = cell->type; else - derived_type = box_module->derive(module->design, cell->parameters); - box_module = box_module->design->module(derived_type); - log_assert(box_module); + derived_type = box_module->derive(design, cell->parameters); + auto derived_module = design->module(derived_type); + log_assert(derived_module); auto r = cell_cache.insert(derived_type); auto &v = r.first->second; if (r.second) { int box_inputs = 0, box_outputs = 0; - for (auto port_name : box_module->ports) { - RTLIL::Wire *w = box_module->wire(port_name); + for (auto port_name : derived_module->ports) { + RTLIL::Wire *w = derived_module->wire(port_name); log_assert(w); if (w->port_input) box_inputs += GetSize(w); @@ -602,7 +604,7 @@ struct XAigerWriter std::get<0>(v) = box_inputs; std::get<1>(v) = box_outputs; - std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int(); + std::get<2>(v) = derived_module->attributes.at(ID::abc9_box_id).as_int(); } write_h_buffer(std::get<0>(v)); @@ -699,10 +701,10 @@ struct XAigerWriter f << stringf("Generated by %s\n", yosys_version_str); - module->design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); - module->design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); - module->design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); - module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); + design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); + design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); + design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); + design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); } void write_map(std::ostream &f) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index a87a94b1d..2fbae8c5e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -87,7 +87,7 @@ void check(RTLIL::Design *design, bool dff_mode) } if (dff_mode) { - pool unsupported{ + static pool unsupported{ ID($adff), ID($dlatch), ID($dlatchsr), ID($sr), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), @@ -102,38 +102,38 @@ void check(RTLIL::Design *design, bool dff_mode) auto inst_module = design->module(cell->type); if (!inst_module) continue; - if (!inst_module->get_bool_attribute(ID::abc9_flop)) + if (!inst_module->get_blackbox_attribute()) continue; auto derived_type = inst_module->derive(design, cell->parameters); if (!processed.insert(derived_type).second) continue; - if (inst_module->get_blackbox_attribute(true /* ignore_wb */)) + auto derived_module = design->module(derived_type); + if (!derived_module->get_bool_attribute(ID::abc9_flop)) + continue; + if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type)); - auto derived_module = design->module(derived_type); if (derived_module->has_processes()) Pass::call_on_module(design, derived_module, "proc"); - if (derived_module->get_bool_attribute(ID::abc9_flop)) { - bool found = false; - for (auto derived_cell : derived_module->cells()) - if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { - if (found) - log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); - found = true; + bool found = false; + for (auto derived_cell : derived_module->cells()) { + if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { + if (found) + log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); + found = true; - SigBit Q = derived_cell->getPort(ID::Q); - log_assert(GetSize(Q.wire) == 1); + SigBit Q = derived_cell->getPort(ID::Q); + log_assert(GetSize(Q.wire) == 1); - if (!Q.wire->port_output) - log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(derived_module), log_id(derived_cell->type)); + if (!Q.wire->port_output) + log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(derived_module), log_id(derived_cell->type)); - Const init = Q.wire->attributes.at(ID::init, State::Sx); - log_assert(GetSize(init) == 1); - } - else if (unsupported.count(derived_cell->type)) { - log_error("Module '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); - } + Const init = Q.wire->attributes.at(ID::init, State::Sx); + log_assert(GetSize(init) == 1); + } + else if (unsupported.count(derived_cell->type)) + log_error("Module '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); } } } @@ -146,7 +146,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) r.first->second = new Design; Design *unmap_design = r.first->second; - pool seq_types{ + static const pool seq_types{ ID($dff), ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr), ID($sr), ID($mem), @@ -166,14 +166,16 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) auto inst_module = design->module(cell->type); if (!inst_module) continue; + if (!inst_module->get_blackbox_attribute()) + continue; auto derived_type = inst_module->derive(design, cell->parameters); auto derived_module = design->module(derived_type); if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) continue; - if (inst_module->get_bool_attribute(ID::abc9_flop) && !dff_mode) + if (derived_module->get_bool_attribute(ID::abc9_flop) && !dff_mode) continue; - if (!inst_module->get_bool_attribute(ID::abc9_box) && !inst_module->get_bool_attribute(ID::abc9_flop)) + if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_flop)) continue; if (!unmap_design->module(derived_type)) { @@ -260,11 +262,9 @@ void prep_bypass(RTLIL::Design *design) auto inst_module = design->module(cell->type); if (!inst_module) continue; - auto derived_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(derived_type); - log_assert(inst_module); if (!inst_module->get_bool_attribute(ID::abc9_bypass)) continue; + log_assert(cell->parameters.empty()); log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); @@ -297,7 +297,7 @@ void prep_bypass(RTLIL::Design *design) // assign o = $abc9_byp$o; - // Copy derived_module into map_design, with the same interface + // Copy inst_module into map_design, with the same interface // and duplicate $abc9$* wires for its output ports auto map_module = map_design->addModule(cell->type); for (auto port_name : inst_module->ports) { @@ -443,13 +443,9 @@ void prep_dff(RTLIL::Design *design) continue; if (!inst_module->get_bool_attribute(ID::abc9_flop)) continue; - auto derived_type = inst_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_type); - log_assert(derived_module); - if (!derived_module->get_bool_attribute(ID::abc9_flop)) - continue; - log_assert(!derived_module->get_blackbox_attribute(true /* ignore_wb */)); - modules_sel.select(derived_module); + log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); + log_assert(cell->parameters.empty()); + modules_sel.select(inst_module); } } @@ -562,6 +558,99 @@ void mark_scc(RTLIL::Module *module) } } +void prep_delays(RTLIL::Design *design, bool dff_mode) +{ + TimingInfo timing; + + // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes + // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations + pool flops; + std::vector> cells; + for (auto module : design->selected_modules()) { + if (module->processes.size() > 0) { + log("Skipping module %s as it contains processes.\n", log_id(module)); + continue; + } + + for (auto cell : module->cells()) { + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_), ID($__ABC9_DELAY))) + continue; + + RTLIL::Module* inst_module = design->module(cell->type); + if (!inst_module) + continue; + if (!inst_module->get_blackbox_attribute()) + continue; + + IdString derived_type; + if (cell->parameters.empty()) + derived_type = cell->type; + else + derived_type = inst_module->derive(design, cell->parameters); + auto derived_module = design->module(derived_type); + log_assert(derived_module); + log_assert(derived_module->get_blackbox_attribute()); + + if (derived_module->get_bool_attribute(ID::abc9_box)) + continue; + if (derived_module->get_bool_attribute(ID::abc9_bypass)) + continue; + + if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) { + flops.insert(inst_module); + continue; // do not add $__ABC9_DELAY boxes to flops + // as delays will be captured in the flop box + } + + if (!timing.count(derived_type)) + timing.setup_module(derived_module); + + cells.emplace_back(cell, derived_module); + } + } + + // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes + // (or bypassed white-boxes with required times) + for (const auto &i : cells) { + auto cell = i.first; + auto module = cell->module; + auto derived_module = i.second; + auto derived_type = derived_module->name; + + auto &t = timing.at(derived_type).required; + for (auto &conn : cell->connections_) { + auto port_wire = derived_module->wire(conn.first); + if (!port_wire) + log_error("Port %s in cell %s (type %s) of module %s does not actually exist", + log_id(conn.first), log_id(cell->name), log_id(cell->type), log_id(module->name)); + if (!port_wire->port_input) + continue; + if (conn.second.is_fully_const()) + continue; + + SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); + for (int i = 0; i < GetSize(conn.second); i++) { + auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); + if (d == 0) + continue; + +#ifndef NDEBUG + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", + log_id(cell->type), log_id(conn.first), i, d); + } +#endif + auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); + box->setPort(ID::I, conn.second[i]); + box->setPort(ID::O, O[i]); + box->setParam(ID::DELAY, d); + conn.second[i] = O[i]; + } + } + } +} + void prep_xaiger(RTLIL::Module *module, bool dff) { auto design = module->design; @@ -670,30 +759,36 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(cell); RTLIL::Module* box_module = design->module(cell->type); - if (!box_module || !box_module->get_bool_attribute(ID::abc9_box)) + if (!box_module) + continue; + if (!box_module->get_blackbox_attribute()) continue; - - cell->attributes[ID::abc9_box_seq] = box_count++; IdString derived_type; if (cell->parameters.empty()) derived_type = cell->type; else derived_type = box_module->derive(design, cell->parameters); - box_module = design->module(derived_type); + auto derived_module = design->module(derived_type); + log_assert(derived_module); + + if (!derived_module->get_bool_attribute(ID::abc9_box)) + continue; + + cell->attributes[ID::abc9_box_seq] = box_count++; auto r = cell_cache.insert(derived_type); auto &holes_cell = r.first->second; if (r.second) { - if (box_module->get_bool_attribute(ID::whitebox)) { + if (derived_module->get_bool_attribute(ID::whitebox)) { holes_cell = holes_module->addCell(cell->name, derived_type); - if (box_module->has_processes()) - Pass::call_on_module(design, box_module, "proc"); + if (derived_module->has_processes()) + Pass::call_on_module(design, derived_module, "proc"); int box_inputs = 0; for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); + RTLIL::Wire *w = derived_module->wire(port_name); log_assert(w); log_assert(!w->port_input || !w->port_output); auto &conn = holes_cell->connections_[port_name]; @@ -714,12 +809,12 @@ void prep_xaiger(RTLIL::Module *module, bool dff) conn = holes_module->addWire(stringf("%s.%s", derived_type.c_str(), log_id(port_name)), GetSize(w)); } } - else // box_module is a blackbox + else // derived_module is a blackbox log_assert(holes_cell == nullptr); } for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = box_module->wire(port_name); + RTLIL::Wire *w = derived_module->wire(port_name); log_assert(w); if (!w->port_output) continue; @@ -735,92 +830,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } -void prep_delays(RTLIL::Design *design, bool dff_mode) -{ - TimingInfo timing; - - // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes - // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations - pool flops; - std::vector cells; - for (auto module : design->selected_modules()) { - if (module->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(module)); - continue; - } - - for (auto cell : module->cells()) { - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_), ID($__ABC9_DELAY))) - continue; - - RTLIL::Module* inst_module = module->design->module(cell->type); - if (!inst_module) - continue; - if (!inst_module->get_blackbox_attribute()) - continue; - if (inst_module->get_bool_attribute(ID::abc9_box)) - continue; - IdString derived_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(derived_type); - log_assert(inst_module); - - if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) { - flops.insert(inst_module); - continue; // do not add $__ABC9_DELAY boxes to flops - // as delays will be captured in the flop box - } - - if (!timing.count(derived_type)) - timing.setup_module(inst_module); - - cells.emplace_back(cell); - } - } - - // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes - // with required times - for (auto cell : cells) { - auto module = cell->module; - RTLIL::Module* inst_module = module->design->module(cell->type); - log_assert(inst_module); - IdString derived_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(derived_type); - log_assert(inst_module); - - auto &t = timing.at(derived_type).required; - for (auto &conn : cell->connections_) { - auto port_wire = inst_module->wire(conn.first); - if (!port_wire) - log_error("Port %s in cell %s (type %s) of module %s does not actually exist", - log_id(conn.first), log_id(cell->name), log_id(cell->type), log_id(module->name)); - if (!port_wire->port_input) - continue; - if (conn.second.is_fully_const()) - continue; - - SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); - for (int i = 0; i < GetSize(conn.second); i++) { - auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); - if (d == 0) - continue; - -#ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", - log_id(cell->type), log_id(conn.first), i, d); - } -#endif - auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); - box->setPort(ID::I, conn.second[i]); - box->setPort(ID::O, O[i]); - box->setParam(ID::DELAY, d); - conn.second[i] = O[i]; - } - } - } -} - void prep_lut(RTLIL::Design *design, int maxlut) { TimingInfo timing; diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index 41acf4d97..a86f6a436 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -1,5 +1,5 @@ (* abc9_box *) -module \$__ABC9_DELAY (input I, output O); +module $__ABC9_DELAY (input I, output O); parameter DELAY = 0; specify (I => O) = DELAY; @@ -7,7 +7,7 @@ module \$__ABC9_DELAY (input I, output O); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_N__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); +module $__DFF_N__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); parameter [0:0] INIT = 1'bx; assign n1 = D; specify @@ -17,7 +17,7 @@ module $__DFF_N__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_P__$abc9_flop(input C, D, Q, (* init=INIT *) output n1); +module $__DFF_P__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); parameter [0:0] INIT = 1'bx; assign n1 = D; specify diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index 4dfac0cbb..d628a73ac 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -12,7 +12,7 @@ module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); endmodule (* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) -module $__DFF_N__$abc9_flop(input C, D, output Q); +module $__DFF_N__$abc9_flop (input C, D, output Q); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); -- cgit v1.2.3 From 97a0a0431489568300b40c1d376af7b5d8cb7027 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 21:56:06 -0700 Subject: abc9_ops/xaiger: further reducing Module::derive() calls by ... replacing _all_ (* abc9_box *) instantiations with their derived types --- backends/aiger/xaiger.cc | 72 ++++++++---------- passes/techmap/abc9_ops.cc | 172 +++++++++++++++++++++---------------------- techlibs/common/abc9_map.v | 6 +- techlibs/common/abc9_model.v | 6 +- 4 files changed, 121 insertions(+), 135 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 413566699..3aa0e1110 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -243,34 +243,33 @@ struct XAigerWriter RTLIL::Module* inst_module = design->module(cell->type); if (inst_module && inst_module->get_blackbox_attribute()) { - IdString derived_type; - if (cell->parameters.empty()) - derived_type = cell->type; - else - derived_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(derived_type); - log_assert(inst_module); - log_assert(inst_module->get_blackbox_attribute()); - bool abc9_flop = false; - if (!cell->has_keep_attr()) { - auto it = cell->attributes.find(ID::abc9_box_seq); - if (it != cell->attributes.end()) { - int abc9_box_seq = it->second.as_int(); - if (GetSize(box_list) <= abc9_box_seq) - box_list.resize(abc9_box_seq+1); - box_list[abc9_box_seq] = cell; - // Only flop boxes may have arrival times - // (all others are combinatorial) - abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); - if (!abc9_flop) - continue; - } + + auto it = cell->attributes.find(ID::abc9_box_seq); + if (it != cell->attributes.end()) { + log_assert(!cell->has_keep_attr()); + int abc9_box_seq = it->second.as_int(); + if (GetSize(box_list) <= abc9_box_seq) + box_list.resize(abc9_box_seq+1); + box_list[abc9_box_seq] = cell; + // Only flop boxes may have arrival times + // (all others are combinatorial) + log_assert(cell->parameters.empty()); + abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); + if (!abc9_flop) + continue; } - if (!timing.count(derived_type)) + if (!cell->parameters.empty()) { + auto derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); + log_assert(inst_module); + log_assert(inst_module->get_blackbox_attribute()); + } + + if (!timing.count(inst_module->name)) timing.setup_module(inst_module); - auto &t = timing.at(derived_type).arrival; + auto &t = timing.at(inst_module->name).arrival; for (const auto &conn : cell->connections()) { auto port_wire = inst_module->wire(conn.first); if (!port_wire->port_output) @@ -284,7 +283,7 @@ struct XAigerWriter #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", + if (seen.emplace(inst_module->name, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", log_id(cell->type), log_id(conn.first), i, d); } #endif @@ -577,24 +576,17 @@ struct XAigerWriter int box_count = 0; for (auto cell : box_list) { log_assert(cell); + log_assert(cell->parameters.empty()); - RTLIL::Module* box_module = design->module(cell->type); - log_assert(box_module); - - IdString derived_type; - if (cell->parameters.empty()) - derived_type = cell->type; - else - derived_type = box_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_type); - log_assert(derived_module); - - auto r = cell_cache.insert(derived_type); + auto r = cell_cache.insert(cell->type); auto &v = r.first->second; if (r.second) { + RTLIL::Module* box_module = design->module(cell->type); + log_assert(box_module); + int box_inputs = 0, box_outputs = 0; - for (auto port_name : derived_module->ports) { - RTLIL::Wire *w = derived_module->wire(port_name); + for (auto port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); if (w->port_input) box_inputs += GetSize(w); @@ -604,7 +596,7 @@ struct XAigerWriter std::get<0>(v) = box_inputs; std::get<1>(v) = box_outputs; - std::get<2>(v) = derived_module->attributes.at(ID::abc9_box_id).as_int(); + std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int(); } write_h_buffer(std::get<0>(v)); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 2fbae8c5e..2794c913a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -104,10 +104,17 @@ void check(RTLIL::Design *design, bool dff_mode) continue; if (!inst_module->get_blackbox_attribute()) continue; - auto derived_type = inst_module->derive(design, cell->parameters); - if (!processed.insert(derived_type).second) - continue; - auto derived_module = design->module(derived_type); + IdString derived_type; + Module *derived_module; + if (cell->parameters.empty()) { + derived_type = cell->type; + derived_module = inst_module; + } + else { + derived_type = inst_module->derive(design, cell->parameters); + derived_module = design->module(derived_type); + log_assert(derived_module); + } if (!derived_module->get_bool_attribute(ID::abc9_flop)) continue; if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) @@ -168,15 +175,27 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) continue; if (!inst_module->get_blackbox_attribute()) continue; - auto derived_type = inst_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_type); + IdString derived_type; + Module *derived_module; + if (cell->parameters.empty()) { + derived_type = cell->type; + derived_module = inst_module; + } + else { + derived_type = inst_module->derive(design, cell->parameters); + derived_module = design->module(derived_type); + } if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) continue; - if (derived_module->get_bool_attribute(ID::abc9_flop) && !dff_mode) - continue; - if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_flop)) - continue; + if (derived_module->get_bool_attribute(ID::abc9_flop)) { + if (!dff_mode) + continue; + } + else { + if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass)) + continue; + } if (!unmap_design->module(derived_type)) { if (derived_module->has_processes()) @@ -200,18 +219,12 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) } } else if (derived_module->get_bool_attribute(ID::abc9_box)) { - bool found = false; for (auto derived_cell : derived_module->cells()) if (seq_types.count(derived_cell->type)) { - found = true; + derived_module->set_bool_attribute(ID::abc9_box, false); + derived_module->set_bool_attribute(ID::abc9_bypass); break; } - - if (!found) - goto skip_cell; - - derived_module->set_bool_attribute(ID::abc9_box, false); - derived_module->set_bool_attribute(ID::abc9_bypass); } if (derived_type != cell->type) { @@ -264,8 +277,8 @@ void prep_bypass(RTLIL::Design *design) continue; if (!inst_module->get_bool_attribute(ID::abc9_bypass)) continue; - log_assert(cell->parameters.empty()); log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */)); + log_assert(cell->parameters.empty()); // The idea is to create two techmap designs, one which maps: @@ -564,8 +577,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations - pool flops; - std::vector> cells; + std::vector cells; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(module)); @@ -573,56 +585,51 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) } for (auto cell : module->cells()) { - if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_), ID($__ABC9_DELAY))) + if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_))) continue; + log_assert(!cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")); RTLIL::Module* inst_module = design->module(cell->type); if (!inst_module) continue; if (!inst_module->get_blackbox_attribute()) continue; + if (!cell->parameters.empty()) + continue; - IdString derived_type; - if (cell->parameters.empty()) - derived_type = cell->type; - else - derived_type = inst_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_type); - log_assert(derived_module); - log_assert(derived_module->get_blackbox_attribute()); - - if (derived_module->get_bool_attribute(ID::abc9_box)) + if (inst_module->get_bool_attribute(ID::abc9_box)) continue; - if (derived_module->get_bool_attribute(ID::abc9_bypass)) + if (inst_module->get_bool_attribute(ID::abc9_bypass)) continue; if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) { - flops.insert(inst_module); continue; // do not add $__ABC9_DELAY boxes to flops // as delays will be captured in the flop box } - if (!timing.count(derived_type)) - timing.setup_module(derived_module); + if (!timing.count(cell->type)) + timing.setup_module(inst_module); - cells.emplace_back(cell, derived_module); + cells.emplace_back(cell); } } // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes // (or bypassed white-boxes with required times) - for (const auto &i : cells) { - auto cell = i.first; + dict box_cache; + Module *delay_module = design->module(ID($__ABC9_DELAY)); + log_assert(delay_module); + for (auto cell : cells) { auto module = cell->module; - auto derived_module = i.second; - auto derived_type = derived_module->name; + auto inst_module = design->module(cell->type); + log_assert(inst_module); - auto &t = timing.at(derived_type).required; + auto &t = timing.at(cell->type).required; for (auto &conn : cell->connections_) { - auto port_wire = derived_module->wire(conn.first); + auto port_wire = inst_module->wire(conn.first); if (!port_wire) - log_error("Port %s in cell %s (type %s) of module %s does not actually exist", - log_id(conn.first), log_id(cell->name), log_id(cell->type), log_id(module->name)); + log_error("Port %s in cell %s (type %s) from module %s does not actually exist", + log_id(conn.first), log_id(cell), log_id(cell->type), log_id(module)); if (!port_wire->port_input) continue; if (conn.second.is_fully_const()) @@ -637,14 +644,18 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", + if (seen.emplace(cell->type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", log_id(cell->type), log_id(conn.first), i, d); } #endif - auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); + auto r = box_cache.insert(d); + if (r.second) { + r.first->second = delay_module->derive(design, {{ID::DELAY, d}}); + log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY=")); + } + auto box = module->addCell(NEW_ID, r.first->second); box->setPort(ID::I, conn.second[i]); box->setPort(ID::O, O[i]); - box->setParam(ID::DELAY, d); conn.second[i] = O[i]; } } @@ -761,34 +772,26 @@ void prep_xaiger(RTLIL::Module *module, bool dff) RTLIL::Module* box_module = design->module(cell->type); if (!box_module) continue; - if (!box_module->get_blackbox_attribute()) - continue; - - IdString derived_type; - if (cell->parameters.empty()) - derived_type = cell->type; - else - derived_type = box_module->derive(design, cell->parameters); - auto derived_module = design->module(derived_type); - log_assert(derived_module); - - if (!derived_module->get_bool_attribute(ID::abc9_box)) + if (!box_module->get_bool_attribute(ID::abc9_box)) continue; +log_cell(cell); + log_assert(cell->parameters.empty()); + log_assert(box_module->get_blackbox_attribute()); cell->attributes[ID::abc9_box_seq] = box_count++; - auto r = cell_cache.insert(derived_type); + auto r = cell_cache.insert(cell->type); auto &holes_cell = r.first->second; if (r.second) { - if (derived_module->get_bool_attribute(ID::whitebox)) { - holes_cell = holes_module->addCell(cell->name, derived_type); + if (box_module->get_bool_attribute(ID::whitebox)) { + holes_cell = holes_module->addCell(cell->name, cell->type); - if (derived_module->has_processes()) - Pass::call_on_module(design, derived_module, "proc"); + if (box_module->has_processes()) + Pass::call_on_module(design, box_module, "proc"); int box_inputs = 0; for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = derived_module->wire(port_name); + RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); log_assert(!w->port_input || !w->port_output); auto &conn = holes_cell->connections_[port_name]; @@ -806,15 +809,15 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } else if (w->port_output) - conn = holes_module->addWire(stringf("%s.%s", derived_type.c_str(), log_id(port_name)), GetSize(w)); + conn = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), log_id(port_name)), GetSize(w)); } } - else // derived_module is a blackbox + else // box_module is a blackbox log_assert(holes_cell == nullptr); } for (auto port_name : box_ports.at(cell->type)) { - RTLIL::Wire *w = derived_module->wire(port_name); + RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); if (!w->port_output) continue; @@ -1282,7 +1285,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) if (!existing_cell) log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell)); - if (existing_cell->type == ID($__ABC9_DELAY)) { + if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { SigBit I = mapped_cell->getPort(ID(i)); SigBit O = mapped_cell->getPort(ID(o)); if (I.wire) @@ -1294,14 +1297,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) } RTLIL::Module* box_module = design->module(existing_cell->type); - IdString derived_type; - if (existing_cell->parameters.empty()) - derived_type = existing_cell->type; - else - derived_type = box_module->derive(design, existing_cell->parameters); - RTLIL::Module* derived_module = design->module(derived_type); - log_assert(derived_module); - log_assert(mapped_cell->type == stringf("$__boxid%d", derived_module->attributes.at(ID::abc9_box_id).as_int())); + log_assert(existing_cell->parameters.empty()); + log_assert(mapped_cell->type == stringf("$__boxid%d", box_module->attributes.at(ID::abc9_box_id).as_int())); mapped_cell->type = existing_cell->type; RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); @@ -1329,7 +1326,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) } int input_count = 0, output_count = 0; - for (const auto &port_name : box_ports.at(derived_type)) { + for (const auto &port_name : box_ports.at(existing_cell->type)) { RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); @@ -1522,19 +1519,18 @@ struct Abc9OpsPass : public Pass { log(" (* abc9_carry *) is only given for one input/output port, etc.\n"); log("\n"); log(" -prep_hier\n"); - log(" derive all used (* abc9_box *) requiring bypass, or (* abc9_flop *) (if\n"); - log(" -dff option) whitebox modules. with (* abc9_box *) modules, bypassing is\n"); - log(" necessary if sequential elements (e.g. $dff, $mem, etc.) are discovered\n"); - log(" inside to ensure that any combinatorial paths are correctly captured.\n"); - log(" with (* abc9_flop *) modules, only those containing $dff/$_DFF_[NP]_\n"); - log(" cells with zero initial state -- due to an ABC limitation -- will be\n"); - log(" derived.\n"); + log(" derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)\n"); + log(" whitebox modules. with (* abc9_flop *) modules, only those containing\n"); + log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation\n"); + log(" -- will be derived.\n"); log("\n"); log(" -prep_bypass\n"); log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n"); log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n"); - log(" (named *_$abc9_byp). this bypass box will only contain ports that are\n"); - log(" referenced by a simple path declaration ($specify2 cell) inside a\n"); + log(" (named *_$abc9_byp). bypassing is necessary if sequential elements (e.g.\n"); + log(" $dff, $mem, etc.) are discovered inside so that any combinatorial paths\n"); + log(" will be correctly captured. this bypass box will only contain ports that\n"); + log(" are referenced by a simple path declaration ($specify2 cell) inside a\n"); log(" specify block.\n"); log("\n"); log(" -prep_dff\n"); diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index 57b3831d8..182915842 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -3,10 +3,10 @@ module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; parameter _TECHMAP_CELLTYPE_ = ""; - wire D_; + (* init=_TECHMAP_WIREINIT_Q_ *) wire D_; generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - $__DFF_N__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); end else @@ -14,7 +14,7 @@ module $_DFF_x_(input C, D, output Q); end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin - $__DFF_P__$abc9_flop #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); + $__DFF_P__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); end else diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index a86f6a436..4fee60f75 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -7,8 +7,7 @@ module $__ABC9_DELAY (input I, output O); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_N__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); - parameter [0:0] INIT = 1'bx; +module $__DFF_N__$abc9_flop (input C, D, Q, output n1); assign n1 = D; specify $setup(D, posedge C, 0); @@ -17,8 +16,7 @@ module $__DFF_N__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); endmodule (* abc9_flop, abc9_box, lib_whitebox *) -module $__DFF_P__$abc9_flop (input C, D, Q, (* init=INIT *) output n1); - parameter [0:0] INIT = 1'bx; +module $__DFF_P__$abc9_flop (input C, D, Q, output n1); assign n1 = D; specify $setup(D, posedge C, 0); -- cgit v1.2.3 From fa31e84112c004348fae30e64ca224367b71d187 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 13 May 2020 22:10:24 -0700 Subject: Fix broken test when ignoring abc9_flop with init == 1'b1 --- passes/techmap/abc9_ops.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 2794c913a..41a11e9a7 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -213,7 +213,6 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) if (init != State::S0) { log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); derived_module->set_bool_attribute(ID::abc9_flop, false); - goto skip_cell; } break; } @@ -250,8 +249,6 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) cell->type = derived_type; cell->parameters.clear(); - -skip_cell: ; } } -- cgit v1.2.3 From 13f9d65b6fc09af76330c02ab420324b50db61da Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 May 2020 00:29:45 -0700 Subject: abc9: preserve $_DFF_?_.Q's (* init *); rely on clean to remove it --- passes/techmap/abc9_ops.cc | 18 +----------------- techlibs/common/abc9_map.v | 4 ++-- techlibs/common/abc9_unmap.v | 5 ++--- tests/various/abc9.ys | 11 ++++++++--- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 41a11e9a7..03a3c5583 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1101,17 +1101,6 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) map_autoidx = autoidx++; - // TODO: Get rid of this expensive lookup - dict> sig2inits; - SigMap sigmap(module); - for (auto w : module->wires()) { - auto it = w->attributes.find(ID::init); - if (it == w->attributes.end()) - continue; - for (const auto &b : SigSpec(w)) - sig2inits[sigmap(b)].emplace_back(b); - } - RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name.c_str())); if (mapped_mod == NULL) log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module)); @@ -1164,12 +1153,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) // Short out $_DFF_[NP]_ cells since the flop box already has // all the information we need to reconstruct cell if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { - SigBit Q = cell->getPort(ID::Q); - auto it = sig2inits.find(Q); - if (it != sig2inits.end()) - for (const auto &b : it->second) - b.wire->attributes.at(ID::init)[b.offset] = State::Sx; - module->connect(Q, cell->getPort(ID::D)); + module->connect(cell->getPort(ID::Q), cell->getPort(ID::D)); module->remove(cell); } else if (cell->type.in(ID($_AND_), ID($_NOT_))) diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index 182915842..bb2b4a4b1 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -3,14 +3,14 @@ module $_DFF_x_(input C, D, output Q); parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; parameter _TECHMAP_CELLTYPE_ = ""; - (* init=_TECHMAP_WIREINIT_Q_ *) wire D_; + wire D_; generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin $__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); end else - $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q));// hide from abc9 using $__ prefix + $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index d628a73ac..b765356d8 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -1,6 +1,5 @@ (* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) -module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); - parameter [0:0] INIT = 1'bx; +module $__DFF_x__$abc9_flop (input C, D, Q, output n1); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); @@ -12,7 +11,7 @@ module $__DFF_x__$abc9_flop (input C, D, Q, (* init = INIT *) output n1); endmodule (* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) -module $__DFF_N__$abc9_flop (input C, D, output Q); +module $__DFF_x_ (input C, D, output Q); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index 9586091c4..ac714665f 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -78,18 +78,23 @@ abc9 design -reset read_verilog -icells < Date: Thu, 14 May 2020 02:09:13 -0700 Subject: abc9_ops: -prep_hier to create unmap module that removes Q's (* init *) --- passes/techmap/abc9_ops.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 03a3c5583..6a8dbde8b 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -230,9 +230,12 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) auto unmap_module = unmap_design->addModule(derived_type); for (auto port : derived_module->ports) { auto w = unmap_module->addWire(port, derived_module->wire(port)); - // Do not propagate (* init *) values inside the box - if (w->port_output) - w->attributes.erase(ID::init); + // Do not propagate (* init *) values into the box, + // in fact, remove it from outside too + if (w->port_output && w->attributes.erase(ID::init)) { + auto r = unmap_module->addWire(stringf("\\_TECHMAP_REMOVEINIT_%s_", log_id(port))); + unmap_module->connect(r, State::S1); + } } unmap_module->ports = derived_module->ports; unmap_module->check(); @@ -771,7 +774,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff) continue; if (!box_module->get_bool_attribute(ID::abc9_box)) continue; -log_cell(cell); log_assert(cell->parameters.empty()); log_assert(box_module->get_blackbox_attribute()); -- cgit v1.2.3 From 67fc0c3698693f049e805211c49d6219f17d7c7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 May 2020 16:44:35 -0700 Subject: abc9: use (* abc9_keep *) instead of (* abc9_scc *); apply to $_DFF_?_ instead of moving them to $__ prefix --- backends/aiger/xaiger.cc | 10 +++++----- kernel/constids.inc | 2 +- passes/techmap/abc9_ops.cc | 6 +++--- techlibs/common/abc9_map.v | 4 ++-- techlibs/common/abc9_unmap.v | 12 ------------ 5 files changed, 11 insertions(+), 23 deletions(-) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3aa0e1110..69797ceaf 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -177,12 +177,12 @@ struct XAigerWriter undriven_bits.insert(bit); unused_bits.insert(bit); - bool scc = wire->attributes.count(ID::abc9_scc); - if (wire->port_input || scc) + bool keep = wire->get_bool_attribute(ID::abc9_keep); + if (wire->port_input || keep) input_bits.insert(bit); - bool keep = wire->get_bool_attribute(ID::keep); - if (wire->port_output || keep || scc) { + keep = keep || wire->get_bool_attribute(ID::keep); + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -225,7 +225,7 @@ struct XAigerWriter continue; } - if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) + if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) { SigBit D = sigmap(cell->getPort(ID::D).as_bit()); SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); diff --git a/kernel/constids.inc b/kernel/constids.inc index 25996d2d8..345bfaee8 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -5,9 +5,9 @@ X(abc9_box_seq) X(abc9_bypass) X(abc9_carry) X(abc9_flop) +X(abc9_keep) X(abc9_lut) X(abc9_mergeability) -X(abc9_scc) X(abc9_scc_id) X(abcgroup) X(ABITS) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 6a8dbde8b..10c980f73 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -563,7 +563,7 @@ void mark_scc(RTLIL::Module *module) if (c.second.is_fully_const()) continue; if (cell->output(c.first)) { Wire *w = module->addWire(NEW_ID, GetSize(c.second)); - w->set_bool_attribute(ID::abc9_scc); + w->set_bool_attribute(ID::abc9_keep); module->connect(w, c.second); c.second = w; } @@ -1154,7 +1154,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) // Short out $_DFF_[NP]_ cells since the flop box already has // all the information we need to reconstruct cell - if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) { + if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) { module->connect(cell->getPort(ID::Q), cell->getPort(ID::D)); module->remove(cell); } @@ -1373,7 +1373,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) RTLIL::Wire *mapped_wire = mapped_mod->wire(port); RTLIL::Wire *wire = module->wire(port); log_assert(wire); - wire->attributes.erase(ID::abc9_scc); + wire->attributes.erase(ID::abc9_keep); RTLIL::Wire *remap_wire = module->wire(remap_name(port)); RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire)); diff --git a/techlibs/common/abc9_map.v b/techlibs/common/abc9_map.v index bb2b4a4b1..6ed90b5f5 100644 --- a/techlibs/common/abc9_map.v +++ b/techlibs/common/abc9_map.v @@ -10,7 +10,7 @@ module $_DFF_x_(input C, D, output Q); $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); end else - $__DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix + (* abc9_keep *) $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); end else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin @@ -18,7 +18,7 @@ module $_DFF_x_(input C, D, output Q); $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); end else - $__DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); // hide from abc9 using $__ prefix + (* abc9_keep *) $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); end else if (_TECHMAP_CELLTYPE_ != "") $error("Unrecognised _TECHMAP_CELLTYPE_"); diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index b765356d8..bcbe91477 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -9,15 +9,3 @@ module $__DFF_x__$abc9_flop (input C, D, Q, output n1); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule - -(* techmap_celltype = "$__DFF_N_ $__DFF_P_" *) -module $__DFF_x_ (input C, D, output Q); - parameter _TECHMAP_CELLTYPE_ = ""; - generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N_") - $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (_TECHMAP_CELLTYPE_ == "$__DFF_P_") - $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); - else if (_TECHMAP_CELLTYPE_ != "") - $error("Unrecognised _TECHMAP_CELLTYPE_"); - endgenerate -endmodule -- cgit v1.2.3