aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/abc9.cc156
1 files changed, 111 insertions, 45 deletions
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 4cdd392b5..50a6e0fe5 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -85,7 +85,7 @@ void handle_loops(RTLIL::Design *design,
// cell in the component, and select (and mark) all its output
// wires
pool<RTLIL::Const> ids_seen;
- for (auto cell : module->cells()) {
+ for (auto cell : module->selected_cells()) {
auto it = cell->attributes.find(ID(abc_scc_id));
if (it != cell->attributes.end()) {
auto r = ids_seen.insert(it->second);
@@ -269,7 +269,7 @@ struct abc_output_filter
};
void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
- bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
+ bool cleanup, vector<int> lut_costs, bool /*retime_mode*/, std::string clk_str,
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
bool show_tempdir, std::string box_file, std::string lut_file,
std::string wire_delay, const dict<int,IdString> &box_lookup,
@@ -309,8 +309,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0));
}
- if (dff_mode && clk_sig.empty())
- log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
+ //if (retime_mode && clk_sig.empty())
+ // log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
if (!cleanup)
@@ -383,7 +383,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
fprintf(f, "%s\n", abc_script.c_str());
fclose(f);
- if (dff_mode || !clk_str.empty())
+ if (/*retime_mode ||*/ !clk_str.empty())
{
if (clk_sig.size() == 0)
log("No%s clock domain found. Not extracting any FF cells.\n", clk_str.empty() ? "" : " matching");
@@ -420,6 +420,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
//log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
// count_gates, GetSize(signal_list), count_input, count_output);
+#if 0
+ Pass::call(design, stringf("write_verilog -noexpr -norename %s/before.v", tempdir_name.c_str()));
+#endif
Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
std::string buffer;
@@ -440,8 +443,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
design->remove(design->module(ID($__abc9__)));
#endif
- design->selection_stack.pop_back();
-
// Now 'unexpose' those wires by undoing
// the expose operation -- remove them from PO/PI
// and re-connecting them back together
@@ -528,6 +529,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
for (int i = 0; i < GetSize(w); i++)
output_bits.insert({wire, i});
}
+
+ auto jt = w->attributes.find("\\init");
+ if (jt != w->attributes.end()) {
+ auto r = remap_wire->attributes.insert(std::make_pair("\\init", jt->second));
+ log_assert(r.second);
+ }
}
for (auto &it : module->connections_) {
@@ -541,9 +548,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
dict<IdString, bool> abc_box;
vector<RTLIL::Cell*> boxes;
- for (const auto &it : module->cells_) {
- auto cell = it.second;
- if (cell->type.in(ID($_AND_), ID($_NOT_))) {
+ for (auto cell : module->selected_cells()) {
+ if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC_FF_))) {
module->remove(cell);
continue;
}
@@ -579,8 +585,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
log_assert(wire);
module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
}
- else if (!lut_costs.empty() || !lut_file.empty()) {
- RTLIL::Cell* driver_lut = nullptr;
+ else {
+ RTLIL::Cell* driving_lut = nullptr;
// ABC can return NOT gates that drive POs
if (!a_bit.wire->port_input) {
// If it's not a NOT gate that that comes from a PI directly,
@@ -592,10 +598,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
driver_name = stringf("%s$lut", a_bit.wire->name.c_str());
else
driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset);
- driver_lut = mapped_mod->cell(driver_name);
+ driving_lut = mapped_mod->cell(driver_name);
}
- if (!driver_lut) {
+ if (!driving_lut) {
// If a driver couldn't be found (could be from PI or box CI)
// then implement using a LUT
cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
@@ -606,11 +612,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
cell_stats[ID($lut)]++;
}
else
- not2drivers[c] = driver_lut;
+ not2drivers[c] = driving_lut;
continue;
}
- else
- log_abort();
if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue;
}
@@ -639,6 +643,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (existing_cell) {
cell->parameters = existing_cell->parameters;
cell->attributes = existing_cell->attributes;
+
+ auto it = cell->parameters.find("\\$abc_flop_clk_pol");
+ if (it != cell->parameters.end())
+ cell->parameters.erase(it);
+ it = cell->parameters.find("\\$abc_flop_en_pol");
+ if (it != cell->parameters.end())
+ cell->parameters.erase(it);
}
else {
cell->parameters = c->parameters;
@@ -694,25 +705,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
int in_wires = 0, out_wires = 0;
// Stitch in mapped_mod's inputs/outputs into module
- for (auto &it : mapped_mod->wires_) {
- RTLIL::Wire *w = it.second;
- if (!w->port_input && !w->port_output)
- continue;
- RTLIL::Wire *wire = module->wire(w->name);
+ for (auto port_name : mapped_mod->ports) {
+ RTLIL::Wire *port = mapped_mod->wire(port_name);
+ log_assert(port);
+ RTLIL::Wire *wire = module->wire(port->name);
log_assert(wire);
- RTLIL::Wire *remap_wire = module->wire(remap_name(w->name));
+ RTLIL::Wire *remap_wire = module->wire(remap_name(port->name));
RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
log_assert(GetSize(signal) >= GetSize(remap_wire));
- log_assert(w->port_input || w->port_output);
RTLIL::SigSig conn;
- if (w->port_input) {
+ if (port->port_input) {
conn.first = remap_wire;
conn.second = signal;
in_wires++;
module->connect(conn);
}
- if (w->port_output) {
+ if (port->port_output) {
conn.first = signal;
conn.second = remap_wire;
out_wires++;
@@ -935,7 +944,7 @@ struct Abc9Pass : public Pass {
#endif
std::string script_file, clk_str, box_file, lut_file;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
- bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
+ bool fast_mode = false, /*retime_mode = false,*/ keepff = false, cleanup = true;
bool show_tempdir = false;
vector<int> lut_costs;
markgroups = false;
@@ -1026,13 +1035,13 @@ struct Abc9Pass : public Pass {
fast_mode = true;
continue;
}
- //if (arg == "-dff") {
- // dff_mode = true;
+ //if (arg == "-retime") {
+ // retime_mode = true;
// continue;
//}
//if (arg == "-clk" && argidx+1 < args.size()) {
// clk_str = args[++argidx];
- // dff_mode = true;
+ // retime_mode = true;
// continue;
//}
//if (arg == "-keepff") {
@@ -1066,6 +1075,9 @@ struct Abc9Pass : public Pass {
}
extra_args(args, argidx, design);
+ if (lut_costs.empty() && lut_file.empty())
+ log_cmd_error("abc9 must be called with '-lut' or '-luts'\n");
+
dict<int,IdString> box_lookup;
dict<IdString,pool<IdString>> scc_break_inputs;
for (auto m : design->modules()) {
@@ -1144,10 +1156,16 @@ struct Abc9Pass : public Pass {
assign_map.set(mod);
- if (!dff_mode || !clk_str.empty()) {
- abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
+ if (true || /*!dff_mode ||*/ !clk_str.empty()) {
+
+ design->selection_stack.emplace_back(false);
+ RTLIL::Selection& sel = design->selection_stack.back();
+ sel.select(mod);
+
+ abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, false, clk_str, keepff,
delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, box_lookup, scc_break_inputs);
+ design->selection_stack.pop_back();
continue;
}
@@ -1167,8 +1185,10 @@ struct Abc9Pass : public Pass {
std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down;
std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down;
- for (auto cell : all_cells)
- {
+ pool<IdString> seen_cells;
+ dict<IdString, std::pair<RTLIL::IdString,RTLIL::IdString>> flop_data;
+
+ for (auto cell : all_cells) {
clkdomain_t key;
for (auto &conn : cell->connections())
@@ -1188,19 +1208,54 @@ struct Abc9Pass : 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());
+ decltype(flop_data)::iterator it;
+ if (seen_cells.insert(cell->type).second) {
+ RTLIL::Module* inst_module = design->module(cell->type);
+ if (!inst_module)
+ continue;
+
+ if (!inst_module->attributes.count("\\abc_flop"))
+ continue;
+
+ IdString abc_flop_clk, abc_flop_en;
+ for (auto port_name : inst_module->ports) {
+ auto wire = inst_module->wire(port_name);
+ log_assert(wire);
+ if (wire->attributes.count("\\abc_flop_clk")) {
+ if (abc_flop_clk != IdString())
+ log_error("More than one port has the 'abc_flop_clk' attribute set on module '%s'.\n", log_id(cell->type));
+ abc_flop_clk = port_name;
+ }
+ if (wire->attributes.count("\\abc_flop_en")) {
+ if (abc_flop_en != IdString())
+ log_error("More than one port has the 'abc_flop_en' attribute set on module '%s'.\n", log_id(cell->type));
+ abc_flop_en = port_name;
+ }
+ }
+
+ if (abc_flop_clk == IdString())
+ log_error("'abc_flop_clk' attribute not found on any ports on module '%s'.\n", log_id(cell->type));
+ if (abc_flop_en == IdString())
+ log_error("'abc_flop_en' attribute not found on any ports on module '%s'.\n", log_id(cell->type));
+ it = flop_data.insert(std::make_pair(cell->type, std::make_pair(abc_flop_clk, abc_flop_en))).first;
}
- 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 {
+ it = flop_data.find(cell->type);
+ if (it == flop_data.end())
+ continue;
}
- else
- continue;
+
+ auto jt = cell->parameters.find("\\$abc_flop_clk_pol");
+ if (jt == cell->parameters.end())
+ log_error("'$abc_flop_clk_pol' parameter not found on module '%s'.\n", log_id(cell->type));
+ bool this_clk_pol = jt->second.as_bool();
+ jt = cell->parameters.find("\\$abc_flop_en_pol");
+ if (jt == cell->parameters.end())
+ log_error("'$abc_flop_en_pol' parameter not found on module '%s'.\n", log_id(cell->type));
+ bool this_en_pol = jt->second.as_bool();
+
+ const auto &data = it->second;
+ key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(data.first)), this_en_pol, assign_map(cell->getPort(data.second)));
unassigned_cells.erase(cell);
expand_queue.insert(cell);
@@ -1286,16 +1341,27 @@ struct Abc9Pass : public Pass {
std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));
+ design->selection_stack.emplace_back(false);
+ RTLIL::Selection& sel = design->selection_stack.back();
+
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));
+
+ pool<RTLIL::IdString> assigned_names;
+ for (auto i : it.second)
+ assigned_names.insert(i->name);
+ sel.selected_members[mod->name] = std::move(assigned_names);
+
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, box_lookup, scc_break_inputs);
assign_map.set(mod);
}
+
+ design->selection_stack.pop_back();
}
assign_map.clear();