aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/hierarchy/submod.cc136
-rw-r--r--passes/techmap/abc9.cc328
2 files changed, 232 insertions, 232 deletions
diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc
index ec242aa1f..3b4f33a60 100644
--- a/passes/hierarchy/submod.cc
+++ b/passes/hierarchy/submod.cc
@@ -20,6 +20,7 @@
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
+#include "kernel/sigtools.h"
#include <stdlib.h>
#include <stdio.h>
#include <set>
@@ -32,49 +33,56 @@ struct SubmodWorker
CellTypes ct;
RTLIL::Design *design;
RTLIL::Module *module;
+ SigMap sigmap;
bool copy_mode;
+ bool hidden_mode;
std::string opt_name;
struct SubModule
{
std::string name, full_name;
- std::set<RTLIL::Cell*> cells;
+ pool<RTLIL::Cell*> cells;
};
std::map<std::string, SubModule> submodules;
struct wire_flags_t {
RTLIL::Wire *new_wire;
- bool is_int_driven, is_int_used, is_ext_driven, is_ext_used;
- wire_flags_t() : new_wire(NULL), is_int_driven(false), is_int_used(false), is_ext_driven(false), is_ext_used(false) { }
+ RTLIL::Const is_int_driven;
+ bool is_int_used, is_ext_driven, is_ext_used;
+ wire_flags_t(RTLIL::Wire* wire) : new_wire(NULL), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { }
};
std::map<RTLIL::Wire*, wire_flags_t> wire_flags;
bool flag_found_something;
- void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
+ void flag_wire(RTLIL::Wire *wire, bool create, bool set_int_used, bool set_ext_driven, bool set_ext_used)
{
if (wire_flags.count(wire) == 0) {
if (!create)
return;
- wire_flags[wire] = wire_flags_t();
+ wire_flags.emplace(wire, wire);
}
- if (set_int_driven)
- wire_flags[wire].is_int_driven = true;
if (set_int_used)
- wire_flags[wire].is_int_used = true;
+ wire_flags.at(wire).is_int_used = true;
if (set_ext_driven)
- wire_flags[wire].is_ext_driven = true;
+ wire_flags.at(wire).is_ext_driven = true;
if (set_ext_used)
- wire_flags[wire].is_ext_used = true;
+ wire_flags.at(wire).is_ext_used = true;
flag_found_something = true;
}
void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
{
for (auto &c : sig.chunks())
- if (c.wire != NULL)
- flag_wire(c.wire, create, set_int_driven, set_int_used, set_ext_driven, set_ext_used);
+ if (c.wire != NULL) {
+ flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used);
+ if (set_int_driven)
+ for (int i = c.offset; i < c.offset+c.width; i++) {
+ wire_flags.at(c.wire).is_int_driven[i] = State::S1;
+ flag_found_something = true;
+ }
+ }
}
void handle_submodule(SubModule &submod)
@@ -127,27 +135,39 @@ struct SubmodWorker
flags.is_ext_driven = true;
if (wire->port_output)
flags.is_ext_used = true;
+ else {
+ auto sig = sigmap(wire);
+ for (auto c : sig.chunks())
+ if (c.wire && c.wire->port_output) {
+ flags.is_ext_used = true;
+ break;
+ }
+ }
bool new_wire_port_input = false;
bool new_wire_port_output = false;
- if (flags.is_int_driven && flags.is_ext_used)
+ if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_used)
new_wire_port_output = true;
if (flags.is_ext_driven && flags.is_int_used)
new_wire_port_input = true;
- if (flags.is_int_driven && flags.is_ext_driven)
+ if (!flags.is_int_driven.is_fully_zero() && flags.is_ext_driven)
new_wire_port_input = true, new_wire_port_output = true;
std::string new_wire_name = wire->name.str();
if (new_wire_port_input || new_wire_port_output) {
- while (new_wire_name[0] == '$') {
- std::string next_wire_name = stringf("\\n%d", auto_name_counter++);
- if (all_wire_names.count(next_wire_name) == 0) {
- all_wire_names.insert(next_wire_name);
- new_wire_name = next_wire_name;
+ if (new_wire_name[0] == '$')
+ while (1) {
+ std::string next_wire_name = stringf("%s\\n%d", hidden_mode ? "$submod" : "", auto_name_counter++);
+ if (all_wire_names.count(next_wire_name) == 0) {
+ all_wire_names.insert(next_wire_name);
+ new_wire_name = next_wire_name;
+ break;
+ }
}
- }
+ else if (hidden_mode)
+ new_wire_name = stringf("$submod%s", new_wire_name.c_str());
}
RTLIL::Wire *new_wire = new_mod->addWire(new_wire_name, wire->width);
@@ -155,6 +175,22 @@ struct SubmodWorker
new_wire->port_output = new_wire_port_output;
new_wire->start_offset = wire->start_offset;
new_wire->attributes = wire->attributes;
+ if (!flags.is_int_driven.is_fully_zero()) {
+ new_wire->attributes.erase(ID(init));
+ auto sig = sigmap(wire);
+ for (int i = 0; i < GetSize(sig); i++) {
+ if (flags.is_int_driven[i] == State::S0)
+ continue;
+ if (!sig[i].wire)
+ continue;
+ auto it = sig[i].wire->attributes.find(ID(init));
+ if (it != sig[i].wire->attributes.end()) {
+ auto jt = new_wire->attributes.insert(std::make_pair(ID(init), Const(State::Sx, GetSize(sig)))).first;
+ jt->second[i] = it->second[sig[i].offset];
+ it->second[sig[i].offset] = State::Sx;
+ }
+ }
+ }
if (new_wire->port_input && new_wire->port_output)
log(" signal %s: inout %s\n", wire->name.c_str(), new_wire->name.c_str());
@@ -177,7 +213,7 @@ struct SubmodWorker
for (auto &bit : conn.second)
if (bit.wire != NULL) {
log_assert(wire_flags.count(bit.wire) > 0);
- bit.wire = wire_flags[bit.wire].new_wire;
+ bit.wire = wire_flags.at(bit.wire).new_wire;
}
log(" cell %s (%s)\n", new_cell->name.c_str(), new_cell->type.c_str());
if (!copy_mode)
@@ -189,16 +225,27 @@ struct SubmodWorker
RTLIL::Cell *new_cell = module->addCell(submod.full_name, submod.full_name);
for (auto &it : wire_flags)
{
- RTLIL::Wire *old_wire = it.first;
+ RTLIL::SigSpec old_sig = sigmap(it.first);
RTLIL::Wire *new_wire = it.second.new_wire;
- if (new_wire->port_id > 0)
- new_cell->setPort(new_wire->name, RTLIL::SigSpec(old_wire));
+ if (new_wire->port_id > 0) {
+ if (new_wire->port_output)
+ for (int i = 0; i < GetSize(old_sig); i++) {
+ auto &b = old_sig[i];
+ // Prevents "ERROR: Mismatch in directionality ..." when flattening
+ if (!b.wire)
+ b = module->addWire(NEW_ID);
+ // Prevents "Warning: multiple conflicting drivers ..."
+ else if (!it.second.is_int_driven[i])
+ b = module->addWire(NEW_ID);
+ }
+ new_cell->setPort(new_wire->name, old_sig);
+ }
}
}
}
- SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, std::string opt_name = std::string()) :
- design(design), module(module), copy_mode(copy_mode), opt_name(opt_name)
+ SubmodWorker(RTLIL::Design *design, RTLIL::Module *module, bool copy_mode = false, bool hidden_mode = false, std::string opt_name = std::string()) :
+ design(design), module(module), sigmap(module), copy_mode(copy_mode), hidden_mode(hidden_mode), opt_name(opt_name)
{
if (!design->selected_whole_module(module->name) && opt_name.empty())
return;
@@ -219,6 +266,12 @@ struct SubmodWorker
ct.setup_stdcells_mem();
ct.setup_design(design);
+ for (auto port : module->ports) {
+ auto wire = module->wire(port);
+ if (wire->port_output)
+ sigmap.add(wire);
+ }
+
if (opt_name.empty())
{
for (auto &it : module->wires_)
@@ -273,7 +326,7 @@ struct SubmodPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" submod [-copy] [selection]\n");
+ log(" submod [options] [selection]\n");
log("\n");
log("This pass identifies all cells with the 'submod' attribute and moves them to\n");
log("a newly created module. The value of the attribute is used as name for the\n");
@@ -285,16 +338,20 @@ struct SubmodPass : public Pass {
log("This pass only operates on completely selected modules with no processes\n");
log("or memories.\n");
log("\n");
+ log(" -copy\n");
+ log(" by default the cells are 'moved' from the source module and the source\n");
+ log(" module will use an instance of the new module after this command is\n");
+ log(" finished. call with -copy to not modify the source module.\n");
log("\n");
- log(" submod -name <name> [-copy] [selection]\n");
- log("\n");
- log("As above, but don't use the 'submod' attribute but instead use the selection.\n");
- log("Only objects from one module might be selected. The value of the -name option\n");
- log("is used as the value of the 'submod' attribute above.\n");
+ log(" -name <name>\n");
+ log(" don't use the 'submod' attribute but instead use the selection. only\n");
+ log(" objects from one module might be selected. the value of the -name option\n");
+ log(" is used as the value of the 'submod' attribute instead.\n");
log("\n");
- log("By default the cells are 'moved' from the source module and the source module\n");
- log("will use an instance of the new module after this command is finished. Call\n");
- log("with -copy to not modify the source module.\n");
+ log(" -hidden\n");
+ log(" instead of creating submodule ports with public names, create ports with\n");
+ log(" private names so that a subsequent 'flatten; clean' call will restore the\n");
+ log(" original module with original public names.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -304,6 +361,7 @@ struct SubmodPass : public Pass {
std::string opt_name;
bool copy_mode = false;
+ bool hidden_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -315,6 +373,10 @@ struct SubmodPass : public Pass {
copy_mode = true;
continue;
}
+ if (args[argidx] == "-hidden") {
+ hidden_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -335,7 +397,7 @@ struct SubmodPass : public Pass {
queued_modules.push_back(mod_it.first);
for (auto &modname : queued_modules)
if (design->modules_.count(modname) != 0) {
- SubmodWorker worker(design, design->modules_[modname], copy_mode);
+ SubmodWorker worker(design, design->modules_[modname], copy_mode, hidden_mode);
handled_modules.insert(modname);
did_something = true;
}
@@ -358,7 +420,7 @@ struct SubmodPass : public Pass {
else {
Pass::call_on_module(design, module, "opt_clean");
log_header(design, "Continuing SUBMOD pass.\n");
- SubmodWorker worker(design, module, copy_mode, opt_name);
+ SubmodWorker worker(design, module, copy_mode, hidden_mode, opt_name);
}
}
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 8276c3c16..8f2d45b62 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -30,7 +30,7 @@
"&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\
"&mfs; &ps -l"
#else
-#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l"
+#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l; &verify -s"
#endif
@@ -65,20 +65,15 @@ PRIVATE_NAMESPACE_BEGIN
bool markgroups;
int map_autoidx;
-SigMap assign_map;
-RTLIL::Module *module;
-
-bool clk_polarity, en_polarity;
-RTLIL::SigSpec clk_sig, en_sig;
inline std::string remap_name(RTLIL::IdString abc9_name)
{
return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
}
-void handle_loops(RTLIL::Design *design)
+void handle_loops(RTLIL::Design *design, RTLIL::Module *module)
{
- Pass::call(design, "scc -set_attr abc9_scc_id {}");
+ Pass::call(design, "scc -set_attr abc9_scc_id {} % w:*");
// For every unique SCC found, (arbitrarily) find the first
// cell in the component, and select (and mark) all its output
@@ -253,49 +248,15 @@ struct abc9_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,
+void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
+ bool cleanup, vector<int> lut_costs, bool /*dff_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, bool nomfs
)
{
- module = current_module;
map_autoidx = autoidx++;
- if (clk_str != "$")
- {
- clk_polarity = true;
- clk_sig = RTLIL::SigSpec();
-
- en_polarity = true;
- en_sig = RTLIL::SigSpec();
- }
-
- if (!clk_str.empty() && clk_str != "$")
- {
- if (clk_str.find(',') != std::string::npos) {
- int pos = clk_str.find(',');
- std::string en_str = clk_str.substr(pos+1);
- clk_str = clk_str.substr(0, pos);
- if (en_str[0] == '!') {
- en_polarity = false;
- en_str = en_str.substr(1);
- }
- if (module->wires_.count(RTLIL::escape_id(en_str)) != 0)
- en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0));
- }
- if (clk_str[0] == '!') {
- clk_polarity = false;
- clk_str = clk_str.substr(1);
- }
- if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0)
- 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());
-
std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
@@ -360,7 +321,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos))
abc9_script = abc9_script.erase(pos, strlen("&mfs"));
- abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
+ abc9_script += stringf("; &write -n %s/output.aig", tempdir_name.c_str());
abc9_script = add_echos_to_abc9_cmd(abc9_script);
for (size_t i = 0; i+1 < abc9_script.size(); i++)
@@ -371,39 +332,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
fprintf(f, "%s\n", abc9_script.c_str());
fclose(f);
- if (dff_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");
- else {
- 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));
- log("\n");
- }
- }
-
- bool count_output = false;
- for (auto port_name : module->ports) {
- RTLIL::Wire *port_wire = module->wire(port_name);
- log_assert(port_wire);
- if (port_wire->port_output) {
- count_output = true;
- break;
- }
- }
-
+ //bool count_output = false;
log_push();
- if (count_output)
+ //if (count_output)
{
- design->selection_stack.emplace_back(false);
- RTLIL::Selection& sel = design->selection_stack.back();
- sel.select(module);
-
- handle_loops(design);
+ handle_loops(design, module);
- Pass::call(design, "aigmap");
+ Pass::call(design, "aigmap -select");
//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);
@@ -421,15 +357,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
log_assert(!design->module(ID($__abc9__)));
{
AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
- reader.parse_xaiger();
+ reader.parse_xaiger(box_lookup);
}
ifs.close();
- Pass::call(design, stringf("write_verilog -noexpr -norename"));
+ Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected"));
design->remove(design->module(ID($__abc9__)));
#endif
- design->selection_stack.pop_back();
-
log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) {
@@ -479,7 +413,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
ifs.close();
#if 0
- Pass::call(design, stringf("write_verilog -noexpr -norename"));
+ Pass::call_on_module(design, design->module(ID($__abc9__)), stringf("write_verilog -noexpr -norename -selected"));
#endif
log_header(design, "Re-integrating ABC9 results.\n");
@@ -487,33 +421,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `$__abc9__'.\n");
- pool<RTLIL::SigBit> output_bits;
for (auto &it : mapped_mod->wires_) {
RTLIL::Wire *w = it.second;
RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
- if (w->port_output) {
- RTLIL::Wire *wire = module->wire(w->name);
- log_assert(wire);
- for (int i = 0; i < GetSize(w); i++)
- output_bits.insert({wire, i});
- }
- }
-
- for (auto &it : module->connections_) {
- auto &signal = it.first;
- auto bits = signal.bits();
- for (auto &b : bits)
- if (output_bits.count(b))
- b = module->addWire(NEW_ID);
- signal = std::move(bits);
}
dict<IdString, bool> abc9_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($__ABC9_FF_))) {
module->remove(cell);
continue;
}
@@ -532,19 +449,19 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
std::map<IdString, int> cell_stats;
- for (auto c : mapped_mod->cells())
+ for (auto mapped_cell : mapped_mod->cells())
{
- toposort.node(c->name);
+ toposort.node(mapped_cell->name);
RTLIL::Cell *cell = nullptr;
- if (c->type == ID($_NOT_)) {
- RTLIL::SigBit a_bit = c->getPort(ID::A);
- RTLIL::SigBit y_bit = c->getPort(ID::Y);
- bit_users[a_bit].insert(c->name);
- bit_drivers[y_bit].insert(c->name);
+ if (mapped_cell->type == ID($_NOT_)) {
+ RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A);
+ RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y);
+ bit_users[a_bit].insert(mapped_cell->name);
+ bit_drivers[y_bit].insert(mapped_cell->name);
if (!a_bit.wire) {
- c->setPort(ID::Y, module->addWire(NEW_ID));
+ mapped_cell->setPort(ID::Y, module->addWire(NEW_ID));
RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
log_assert(wire);
module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
@@ -568,7 +485,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (!driver_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())),
+ cell = module->addLut(remap_name(stringf("%s$lut", mapped_cell->name.c_str())),
RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
RTLIL::Const::from_string("01"));
@@ -576,7 +493,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
cell_stats[ID($lut)]++;
}
else
- not2drivers[c] = driver_lut;
+ not2drivers[mapped_cell] = driver_lut;
continue;
}
else
@@ -584,24 +501,26 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
continue;
}
- cell_stats[c->type]++;
+ cell_stats[mapped_cell->type]++;
RTLIL::Cell *existing_cell = nullptr;
- if (c->type == ID($lut)) {
- if (GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
- SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID::A).as_wire()->name));
- SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID::Y).as_wire()->name));
+ if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) {
+ if (mapped_cell->type == ID($lut) &&
+ GetSize(mapped_cell->getPort(ID::A)) == 1 &&
+ mapped_cell->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
+ SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name));
+ SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name));
module->connect(my_y, my_a);
- if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
+ if (markgroups) mapped_cell->attributes[ID(abcgroup)] = map_autoidx;
log_abort();
continue;
}
- cell = module->addCell(remap_name(c->name), c->type);
+ cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
}
else {
- existing_cell = module->cell(c->name);
+ existing_cell = module->cell(mapped_cell->name);
log_assert(existing_cell);
- cell = module->addCell(remap_name(c->name), c->type);
+ cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
}
if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
@@ -610,10 +529,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
cell->attributes = existing_cell->attributes;
}
else {
- cell->parameters = c->parameters;
- cell->attributes = c->attributes;
+ cell->parameters = mapped_cell->parameters;
+ cell->attributes = mapped_cell->attributes;
}
- for (auto &conn : c->connections()) {
+
+ RTLIL::Module* box_module = design->module(mapped_cell->type);
+ auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop");
+ for (auto &conn : mapped_cell->connections()) {
RTLIL::SigSpec newsig;
for (auto c : conn.second.chunks()) {
if (c.width == 0)
@@ -625,15 +547,17 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
cell->setPort(conn.first, newsig);
- if (cell->input(conn.first)) {
- for (auto i : newsig)
- bit2sinks[i].push_back(cell);
- for (auto i : conn.second)
- bit_users[i].insert(c->name);
+ if (!abc9_flop) {
+ if (cell->input(conn.first)) {
+ for (auto i : newsig)
+ bit2sinks[i].push_back(cell);
+ for (auto i : conn.second)
+ bit_users[i].insert(mapped_cell->name);
+ }
+ if (cell->output(conn.first))
+ for (auto i : conn.second)
+ bit_drivers[i].insert(mapped_cell->name);
}
- if (cell->output(conn.first))
- for (auto i : conn.second)
- bit_drivers[i].insert(c->name);
}
}
@@ -798,10 +722,10 @@ clone_lut:
design->remove(mapped_mod);
}
- else
- {
- log("Don't call ABC as there is nothing to map.\n");
- }
+ //else
+ //{
+ // log("Don't call ABC as there is nothing to map.\n");
+ //}
if (cleanup)
{
@@ -914,8 +838,17 @@ struct Abc9Pass : public Pass {
log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
log("ABC on logic snippets extracted from your design. You will not get any useful\n");
log("output when passing an ABC script that writes a file. Instead write your full\n");
- log("design as BLIF file with write_blif and then load that into ABC externally if\n");
- log("you want to use ABC to convert your design into another format.\n");
+ log("design as an XAIGER file with write_xaiger and then load that into ABC externally\n");
+ log("if you want to use ABC to convert your design into another format.\n");
+ log("\n");
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("Delay targets can also be specified on a per clock basis by attaching a\n");
+ log("'(* abc9_period = <int> *)' attribute onto clock wires (specifically, onto wires\n");
+ log("that appear inside any special '$abc9_clock' wires inserted by abc9_map.v). This\n");
+ log("can be achieved by modifying the source directly, or through a `setattr`\n");
+ log("invocation. Since such attributes cannot yet be propagated through a\n");
+ log("hierarchical design (whether or not it has been uniquified) it is recommended\n");
+ log("that the design be flattened when using this feature.\n");
log("\n");
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
log("\n");
@@ -925,8 +858,6 @@ struct Abc9Pass : public Pass {
log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n");
log_push();
- assign_map.clear();
-
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
@@ -934,7 +865,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, /*dff_mode = false,*/ keepff = false, cleanup = true;
bool show_tempdir = false;
bool nomfs = false;
vector<int> lut_costs;
@@ -1136,48 +1067,37 @@ struct Abc9Pass : public Pass {
}
}
- for (auto mod : design->selected_modules())
+ SigMap assign_map;
+ CellTypes ct(design);
+ for (auto module : design->selected_modules())
{
- if (mod->attributes.count(ID(abc9_box_id)))
- continue;
-
- if (mod->processes.size() > 0) {
- log("Skipping module %s as it contains processes.\n", log_id(mod));
+ if (module->attributes.count(ID(abc9_box_id)))
continue;
- }
- 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,
- delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay, box_lookup, nomfs);
+ if (module->processes.size() > 0) {
+ log("Skipping module %s as it contains processes.\n", log_id(module));
continue;
}
- CellTypes ct(design);
+ assign_map.set(module);
- std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
+ std::vector<RTLIL::Cell*> all_cells = module->selected_cells();
std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());
std::set<RTLIL::Cell*> expand_queue, next_expand_queue;
std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;
- typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
- std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells;
+ typedef std::pair<SigSpec, IdString> clkdomain_t;
+ std::map<clkdomain_t, pool<RTLIL::IdString>> assigned_cells;
std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;
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)
- {
- clkdomain_t key;
-
+ for (auto cell : all_cells) {
for (auto &conn : cell->connections())
- for (auto bit : conn.second) {
- bit = assign_map(bit);
+ for (auto bit : assign_map(conn.second))
if (bit.wire != nullptr) {
cell_to_bit[cell].insert(bit);
bit_to_cell[bit].insert(cell);
@@ -1190,29 +1110,37 @@ struct Abc9Pass : public Pass {
bit_to_cell_up[bit].insert(cell);
}
}
- }
- 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
+ auto inst_module = design->module(cell->type);
+ if (!inst_module || !inst_module->attributes.count("\\abc9_flop"))
continue;
+ Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str()));
+ if (abc9_clock_wire == NULL)
+ log_error("'%s$abc9_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);
+
unassigned_cells.erase(cell);
expand_queue.insert(cell);
expand_queue_up.insert(cell);
expand_queue_down.insert(cell);
- assigned_cells[key].push_back(cell);
+ clkdomain_t key(abc9_clock, cell->type);
+ assigned_cells[key].insert(cell->name);
assigned_cells_reverse[cell] = key;
+
+ auto YS_ATTRIBUTE(unused) r2 = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), 1));
+ log_assert(r2.second);
+
+ Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str()));
+ if (abc9_init_wire == NULL)
+ log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+ log_assert(GetSize(abc9_init_wire) == 1);
+ SigSpec abc9_init = assign_map(abc9_init_wire);
+ if (!abc9_init.is_fully_const())
+ log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+ r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
+ log_assert(r2.second);
}
while (!expand_queue_up.empty() || !expand_queue_down.empty())
@@ -1220,15 +1148,15 @@ struct Abc9Pass : public Pass {
if (!expand_queue_up.empty())
{
RTLIL::Cell *cell = *expand_queue_up.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
+ auto key = assigned_cells_reverse.at(cell);
expand_queue_up.erase(cell);
for (auto bit : cell_to_bit_up[cell])
for (auto c : bit_to_cell_up[bit])
- if (unassigned_cells.count(c)) {
+ if (unassigned_cells.count(c) && !c->type.in("$__ABC9_FF_", "$__ABC9_ASYNC_")) {
unassigned_cells.erase(c);
next_expand_queue_up.insert(c);
- assigned_cells[key].push_back(c);
+ assigned_cells[key].insert(c->name);
assigned_cells_reverse[c] = key;
expand_queue.insert(c);
}
@@ -1237,7 +1165,7 @@ struct Abc9Pass : public Pass {
if (!expand_queue_down.empty())
{
RTLIL::Cell *cell = *expand_queue_down.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
+ auto key = assigned_cells_reverse.at(cell);
expand_queue_down.erase(cell);
for (auto bit : cell_to_bit_down[cell])
@@ -1245,7 +1173,7 @@ struct Abc9Pass : public Pass {
if (unassigned_cells.count(c)) {
unassigned_cells.erase(c);
next_expand_queue_up.insert(c);
- assigned_cells[key].push_back(c);
+ assigned_cells[key].insert(c->name);
assigned_cells_reverse[c] = key;
expand_queue.insert(c);
}
@@ -1260,7 +1188,7 @@ struct Abc9Pass : public Pass {
while (!expand_queue.empty())
{
RTLIL::Cell *cell = *expand_queue.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
+ auto key = assigned_cells_reverse.at(cell);
expand_queue.erase(cell);
for (auto bit : cell_to_bit.at(cell)) {
@@ -1268,7 +1196,7 @@ struct Abc9Pass : public Pass {
if (unassigned_cells.count(c)) {
unassigned_cells.erase(c);
next_expand_queue.insert(c);
- assigned_cells[key].push_back(c);
+ assigned_cells[key].insert(c->name);
assigned_cells_reverse[c] = key;
}
bit_to_cell[bit].clear();
@@ -1278,32 +1206,42 @@ struct Abc9Pass : public Pass {
expand_queue.swap(next_expand_queue);
}
- clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
+ clkdomain_t key;
for (auto cell : unassigned_cells) {
- assigned_cells[key].push_back(cell);
+ assigned_cells[key].insert(cell->name);
assigned_cells_reverse[cell] = key;
}
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),
- std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
- std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));
+ log(" %d cells in clk=%s cell=%s\n", GetSize(it.second), log_signal(it.first.first), log_id(it.first.second));
+ design->selection_stack.emplace_back(false);
+ design->selected_active_module = module->name.str();
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));
- abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
- keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
+ std::string target = delay_target;
+ if (target.empty()) {
+ for (auto b : assign_map(it.first.first))
+ if (b.wire) {
+ auto jt = b.wire->attributes.find("\\abc9_period");
+ if (jt != b.wire->attributes.end()) {
+ target = stringf("-D %d", jt->second.as_int());
+ log("Target period = %s ps for clock domain %s\n", target.c_str(), log_signal(it.first.first));
+ break;
+ }
+ }
+ }
+ RTLIL::Selection& sel = design->selection_stack.back();
+ sel.selected_members[module->name] = std::move(it.second);
+ abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, false, "$",
+ keepff, target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay, box_lookup, nomfs);
- assign_map.set(mod);
+ assign_map.set(module);
}
+ design->selection_stack.pop_back();
+ design->selected_active_module.clear();
}
- assign_map.clear();
-
log_pop();
}
} Abc9Pass;