From: Marcelina Koƛcielnicka Date: Thu, 7 Apr 2022 01:25:35 +0000 (+0200) Subject: abc: Add support for FFs with reset in -dff X-Git-Tag: yosys-0.17~56 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=376d8cb26fcaa37a8627134dee3796315950885a;p=yosys.git abc: Add support for FFs with reset in -dff --- diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 2c91f3a48..a37b2a0f3 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -45,6 +45,7 @@ #include "kernel/sigtools.h" #include "kernel/celltypes.h" #include "kernel/ffinit.h" +#include "kernel/ff.h" #include "kernel/cost.h" #include "kernel/log.h" #include @@ -73,6 +74,8 @@ PRIVATE_NAMESPACE_BEGIN enum class gate_type_t { G_NONE, G_FF, + G_FF0, + G_FF1, G_BUF, G_NOT, G_AND, @@ -115,10 +118,11 @@ std::vector signal_list; std::map signal_map; FfInitVals initvals; pool enabled_gates; -bool recover_init, cmos_cost; +bool cmos_cost; +bool had_init; -bool clk_polarity, en_polarity; -RTLIL::SigSpec clk_sig, en_sig; +bool clk_polarity, en_polarity, arst_polarity, srst_polarity; +RTLIL::SigSpec clk_sig, en_sig, arst_sig, srst_sig; dict pi_map, po_map; int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1) @@ -165,46 +169,84 @@ void mark_port(RTLIL::SigSpec sig) void extract_cell(RTLIL::Cell *cell, bool keepff) { - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - if (clk_polarity != (cell->type == ID($_DFF_P_))) + if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + FfData ff(&initvals, cell); + gate_type_t type = G(FF); + if (!ff.has_clk) return; - if (clk_sig != assign_map(cell->getPort(ID::C))) + if (ff.has_gclk) return; - if (GetSize(en_sig) != 0) + if (ff.has_aload) return; - goto matching_dff; - } - - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - if (clk_polarity != cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_))) + if (ff.has_sr) return; - if (en_polarity != cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_))) + if (!ff.is_fine) return; - if (clk_sig != assign_map(cell->getPort(ID::C))) + if (clk_polarity != ff.pol_clk) return; - if (en_sig != assign_map(cell->getPort(ID::E))) + if (clk_sig != assign_map(ff.sig_clk)) return; - goto matching_dff; - } - - if (0) { - matching_dff: - RTLIL::SigSpec sig_d = cell->getPort(ID::D); - RTLIL::SigSpec sig_q = cell->getPort(ID::Q); + if (ff.has_ce) { + if (en_polarity != ff.pol_ce) + return; + if (en_sig != assign_map(ff.sig_ce)) + return; + } else { + if (GetSize(en_sig) != 0) + return; + } + if (ff.val_init == State::S1) { + type = G(FF1); + had_init = true; + } else if (ff.val_init == State::S0) { + type = G(FF0); + had_init = true; + } + if (ff.has_arst) { + if (arst_polarity != ff.pol_arst) + return; + if (arst_sig != assign_map(ff.sig_arst)) + return; + if (ff.val_arst == State::S1) { + if (type == G(FF0)) + return; + type = G(FF1); + } else if (ff.val_arst == State::S0) { + if (type == G(FF1)) + return; + type = G(FF0); + } + } else { + if (GetSize(arst_sig) != 0) + return; + } + if (ff.has_srst) { + if (srst_polarity != ff.pol_srst) + return; + if (srst_sig != assign_map(ff.sig_srst)) + return; + if (ff.val_srst == State::S1) { + if (type == G(FF0)) + return; + type = G(FF1); + } else if (ff.val_srst == State::S0) { + if (type == G(FF1)) + return; + type = G(FF0); + } + } else { + if (GetSize(srst_sig) != 0) + return; + } if (keepff) - for (auto &c : sig_q.chunks()) + for (auto &c : ff.sig_q.chunks()) if (c.wire != nullptr) c.wire->attributes[ID::keep] = 1; - assign_map.apply(sig_d); - assign_map.apply(sig_q); - - map_signal(sig_q, G(FF), map_signal(sig_d)); + map_signal(ff.sig_q, type, map_signal(ff.sig_d)); - module->remove(cell); + ff.remove(); return; } @@ -412,7 +454,7 @@ void handle_loops() // dot_f = fopen("test.dot", "w"); for (auto &g : signal_list) { - if (g.type == G(NONE) || g.type == G(FF)) { + if (g.type == G(NONE) || g.type == G(FF) || g.type == G(FF0) || g.type == G(FF1)) { workpool.insert(g.id); } else { if (g.in1 >= 0) { @@ -667,7 +709,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin signal_list.clear(); pi_map.clear(); po_map.clear(); - recover_init = false; if (clk_str != "$") { @@ -676,14 +717,41 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin en_polarity = true; en_sig = RTLIL::SigSpec(); + + arst_polarity = true; + arst_sig = RTLIL::SigSpec(); + + srst_polarity = true; + srst_sig = RTLIL::SigSpec(); } if (!clk_str.empty() && clk_str != "$") { + std::string en_str; + std::string arst_str; + std::string srst_str; if (clk_str.find(',') != std::string::npos) { int pos = clk_str.find(','); - std::string en_str = clk_str.substr(pos+1); + en_str = clk_str.substr(pos+1); clk_str = clk_str.substr(0, pos); + } + if (en_str.find(',') != std::string::npos) { + int pos = en_str.find(','); + arst_str = en_str.substr(pos+1); + arst_str = en_str.substr(0, pos); + } + if (arst_str.find(',') != std::string::npos) { + int pos = arst_str.find(','); + srst_str = arst_str.substr(pos+1); + srst_str = arst_str.substr(0, pos); + } + if (clk_str[0] == '!') { + clk_polarity = false; + clk_str = clk_str.substr(1); + } + if (module->wire(RTLIL::escape_id(clk_str)) != nullptr) + clk_sig = assign_map(module->wire(RTLIL::escape_id(clk_str))); + if (en_str != "") { if (en_str[0] == '!') { en_polarity = false; en_str = en_str.substr(1); @@ -691,12 +759,22 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (module->wire(RTLIL::escape_id(en_str)) != nullptr) en_sig = assign_map(module->wire(RTLIL::escape_id(en_str))); } - if (clk_str[0] == '!') { - clk_polarity = false; - clk_str = clk_str.substr(1); + if (arst_str != "") { + if (arst_str[0] == '!') { + arst_polarity = false; + arst_str = arst_str.substr(1); + } + if (module->wire(RTLIL::escape_id(arst_str)) != nullptr) + arst_sig = assign_map(module->wire(RTLIL::escape_id(arst_str))); + } + if (srst_str != "") { + if (srst_str[0] == '!') { + srst_polarity = false; + srst_str = srst_str.substr(1); + } + if (module->wire(RTLIL::escape_id(srst_str)) != nullptr) + srst_sig = assign_map(module->wire(RTLIL::escape_id(srst_str))); } - if (module->wire(RTLIL::escape_id(clk_str)) != nullptr) - clk_sig = assign_map(module->wire(RTLIL::escape_id(clk_str))); } if (dff_mode && clk_sig.empty()) @@ -789,10 +867,15 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); if (en_sig.size() != 0) log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + if (arst_sig.size() != 0) + log(", asynchronously reset by %s%s", arst_polarity ? "" : "!", log_signal(arst_sig)); + if (srst_sig.size() != 0) + log(", synchronously reset by %s%s", srst_polarity ? "" : "!", log_signal(srst_sig)); log("\n"); } } + had_init = false; for (auto c : cells) extract_cell(c, keepff); @@ -811,6 +894,12 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (en_sig.size() != 0) mark_port(en_sig); + if (arst_sig.size() != 0) + mark_port(arst_sig); + + if (srst_sig.size() != 0) + mark_port(srst_sig); + handle_loops(); buffer = stringf("%s/input.blif", tempdir_name.c_str()); @@ -917,11 +1006,11 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fprintf(f, "00-- 1\n"); fprintf(f, "--00 1\n"); } else if (si.type == G(FF)) { - if (si.init == State::S0 || si.init == State::S1) { - fprintf(f, ".latch ys__n%d ys__n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0); - recover_init = true; - } else - fprintf(f, ".latch ys__n%d ys__n%d 2\n", si.in1, si.id); + fprintf(f, ".latch ys__n%d ys__n%d 2\n", si.in1, si.id); + } else if (si.type == G(FF0)) { + fprintf(f, ".latch ys__n%d ys__n%d 0\n", si.in1, si.id); + } else if (si.type == G(FF1)) { + fprintf(f, ".latch ys__n%d ys__n%d 1\n", si.in1, si.id); } else if (si.type != G(NONE)) log_abort(); if (si.type != G(NONE)) @@ -1043,6 +1132,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin design->select(module, wire); } + SigMap mapped_sigmap(mapped_mod); + FfInitVals mapped_initvals(&mapped_sigmap, mapped_mod); + std::map cell_stats; for (auto c : mapped_mod->cells()) { @@ -1149,20 +1241,41 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == ID(DFF)) { log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell; - if (en_sig.size() == 0) { - cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_)); - } else { + FfData ff(module, &initvals, remap_name(c->name)); + ff.width = 1; + ff.is_fine = true; + ff.has_clk = true; + ff.pol_clk = clk_polarity; + ff.sig_clk = clk_sig; + if (en_sig.size() != 0) { log_assert(en_sig.size() == 1); - cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::E, en_sig); + ff.has_ce = true; + ff.pol_ce = en_polarity; + ff.sig_ce = en_sig; } - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::D, ID::Q}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); + RTLIL::Const init = mapped_initvals(c->getPort(ID::Q)); + if (had_init) + ff.val_init = init; + else + ff.val_init = State::Sx; + if (arst_sig.size() != 0) { + log_assert(arst_sig.size() == 1); + ff.has_arst = true; + ff.pol_arst = arst_polarity; + ff.sig_arst = arst_sig; + ff.val_arst = init; } - cell->setPort(ID::C, clk_sig); + if (srst_sig.size() != 0) { + log_assert(srst_sig.size() == 1); + ff.has_srst = true; + ff.pol_srst = srst_polarity; + ff.sig_srst = srst_sig; + ff.val_srst = init; + } + ff.sig_d = module->wire(remap_name(c->getPort(ID::D).as_wire()->name)); + ff.sig_q = module->wire(remap_name(c->getPort(ID::Q).as_wire()->name)); + RTLIL::Cell *cell = ff.emit(); + if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; design->select(module, cell); continue; } @@ -1180,20 +1293,38 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (c->type == ID(_dff_)) { log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell; - if (en_sig.size() == 0) { - cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_)); - } else { + FfData ff(module, &initvals, remap_name(c->name)); + ff.width = 1; + ff.is_fine = true; + ff.has_clk = true; + ff.pol_clk = clk_polarity; + ff.sig_clk = clk_sig; + if (en_sig.size() != 0) { log_assert(en_sig.size() == 1); - cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N')); - cell->setPort(ID::E, en_sig); + ff.pol_ce = en_polarity; + ff.sig_ce = en_sig; } - if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - for (auto name : {ID::D, ID::Q}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); - cell->setPort(name, module->wire(remapped_name)); + RTLIL::Const init = mapped_initvals(c->getPort(ID::Q)); + if (had_init) + ff.val_init = init; + else + ff.val_init = State::Sx; + if (arst_sig.size() != 0) { + log_assert(arst_sig.size() == 1); + ff.pol_arst = arst_polarity; + ff.sig_arst = arst_sig; + ff.val_arst = init; + } + if (srst_sig.size() != 0) { + log_assert(srst_sig.size() == 1); + ff.pol_srst = srst_polarity; + ff.sig_srst = srst_sig; + ff.val_srst = init; } - cell->setPort(ID::C, clk_sig); + ff.sig_d = module->wire(remap_name(c->getPort(ID::D).as_wire()->name)); + ff.sig_q = module->wire(remap_name(c->getPort(ID::Q).as_wire()->name)); + RTLIL::Cell *cell = ff.emit(); + if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; design->select(module, cell); continue; } @@ -1229,15 +1360,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin module->connect(conn); } - if (recover_init) - for (auto wire : mapped_mod->wires()) { - if (wire->attributes.count(ID::init)) { - Wire *w = module->wire(remap_name(wire->name)); - log_assert(w->attributes.count(ID::init) == 0); - w->attributes[ID::init] = wire->attributes.at(ID::init); - } - } - for (auto &it : cell_stats) log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second); int in_wires = 0, out_wires = 0; @@ -1884,7 +2006,7 @@ struct AbcPass : public Pass { std::set expand_queue_up, next_expand_queue_up; std::set expand_queue_down, next_expand_queue_down; - typedef tuple clkdomain_t; + typedef tuple clkdomain_t; std::map> assigned_cells; std::map assigned_cells_reverse; @@ -1912,19 +2034,30 @@ struct AbcPass : public Pass { } } - if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) - { - key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID::C)), true, RTLIL::SigSpec()); - } - else - if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) - { - bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)); - bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)); - key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID::C)), this_en_pol, assign_map(cell->getPort(ID::E))); - } - else + if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + continue; + + FfData ff(&initvals, cell); + if (!ff.has_clk) + continue; + if (ff.has_gclk) + continue; + if (ff.has_aload) + continue; + if (ff.has_sr) + continue; + if (!ff.is_fine) continue; + key = clkdomain_t( + ff.pol_clk, + ff.sig_clk, + ff.has_ce ? ff.pol_ce : true, + ff.has_ce ? assign_map(ff.sig_ce) : RTLIL::SigSpec(), + ff.has_arst ? ff.pol_arst : true, + ff.has_arst ? assign_map(ff.sig_arst) : RTLIL::SigSpec(), + ff.has_srst ? ff.pol_srst : true, + ff.has_srst ? assign_map(ff.sig_srst) : RTLIL::SigSpec() + ); unassigned_cells.erase(cell); expand_queue.insert(cell); @@ -1998,7 +2131,7 @@ struct AbcPass : public Pass { expand_queue.swap(next_expand_queue); } - clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); + clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec(), true, RTLIL::SigSpec(), true, RTLIL::SigSpec()); for (auto cell : unassigned_cells) { assigned_cells[key].push_back(cell); assigned_cells_reverse[cell] = key; @@ -2006,15 +2139,21 @@ struct AbcPass : public Pass { log_header(design, "Summary of detected clock domains:\n"); for (auto &it : assigned_cells) - log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second), + log(" %d cells in clk=%s%s, en=%s%s, arst=%s%s, srst=%s%s\n", GetSize(it.second), std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)), - std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first))); + std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)), + std::get<4>(it.first) ? "" : "!", log_signal(std::get<5>(it.first)), + std::get<6>(it.first) ? "" : "!", log_signal(std::get<7>(it.first))); for (auto &it : assigned_cells) { clk_polarity = std::get<0>(it.first); clk_sig = assign_map(std::get<1>(it.first)); en_polarity = std::get<2>(it.first); en_sig = assign_map(std::get<3>(it.first)); + arst_polarity = std::get<4>(it.first); + arst_sig = assign_map(std::get<5>(it.first)); + srst_polarity = std::get<6>(it.first); + srst_sig = assign_map(std::get<7>(it.first)); abc_module(design, mod, script_file, exe_file, liberty_files, genlib_files, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$", keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, abc_dress); assign_map.set(mod);