aboutsummaryrefslogtreecommitdiffstats
path: root/backends
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2020-01-14 12:57:56 -0800
committerEddie Hung <eddie@fpgeh.com>2020-01-14 12:57:56 -0800
commit915e7dde734094e21803f83e37f8827b8ff2fe32 (patch)
treef6d0a2fb338c92f865e6c6c1f2e43716d90716c8 /backends
parentf9aae90e7a9d238f5063d980e2b1e85a94cff4c7 (diff)
parent654247abe9078566f93960a135ce08b0cfc96442 (diff)
downloadyosys-915e7dde734094e21803f83e37f8827b8ff2fe32.tar.gz
yosys-915e7dde734094e21803f83e37f8827b8ff2fe32.tar.bz2
yosys-915e7dde734094e21803f83e37f8827b8ff2fe32.zip
Merge remote-tracking branch 'origin/eddie/abc9_refactor' into eddie/abc9_required
Diffstat (limited to 'backends')
-rw-r--r--backends/aiger/xaiger.cc177
-rw-r--r--backends/edif/edif.cc62
2 files changed, 145 insertions, 94 deletions
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index d934a9aa9..d3415e45d 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -156,7 +156,6 @@ struct XAigerWriter
if (wire->get_bool_attribute(ID::keep))
sigmap.add(wire);
-
for (auto wire : module->wires())
for (int i = 0; i < GetSize(wire); i++)
{
@@ -174,93 +173,101 @@ struct XAigerWriter
undriven_bits.insert(bit);
unused_bits.insert(bit);
- if (wire->port_input)
+ bool keep = wire->get_bool_attribute(ID::keep);
+ if (wire->port_input || keep)
input_bits.insert(bit);
- if (wire->port_output) {
+ if (wire->port_output || keep) {
if (bit != wirebit)
alias_map[wirebit] = bit;
output_bits.insert(wirebit);
}
}
- std::vector<int> arrivals;
+ dict<IdString,dict<IdString,std::vector<int>>> arrivals_cache;
for (auto cell : module->cells()) {
- if (cell->type == "$_NOT_")
- {
- SigBit A = sigmap(cell->getPort("\\A").as_bit());
- SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
- unused_bits.erase(A);
- undriven_bits.erase(Y);
- not_map[Y] = A;
- continue;
- }
-
- if (cell->type == "$_AND_")
- {
- SigBit A = sigmap(cell->getPort("\\A").as_bit());
- SigBit B = sigmap(cell->getPort("\\B").as_bit());
- SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
- unused_bits.erase(A);
- unused_bits.erase(B);
- undriven_bits.erase(Y);
- and_map[Y] = make_pair(A, B);
- continue;
- }
+ RTLIL::Module* inst_module = module->design->module(cell->type);
+ if (!cell->has_keep_attr()) {
+ if (cell->type == "$_NOT_")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+ unused_bits.erase(A);
+ undriven_bits.erase(Y);
+ not_map[Y] = A;
+ continue;
+ }
- if (cell->type == "$__ABC9_FF_" &&
- // The presence of an abc9_mergeability attribute indicates
- // that we do want to pass this flop to ABC
- cell->attributes.count("\\abc9_mergeability"))
- {
- SigBit D = sigmap(cell->getPort("\\D").as_bit());
- SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
- unused_bits.erase(D);
- undriven_bits.erase(Q);
- alias_map[Q] = D;
- auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
- log_assert(r.second);
- continue;
- }
+ if (cell->type == "$_AND_")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit B = sigmap(cell->getPort("\\B").as_bit());
+ SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+ unused_bits.erase(A);
+ unused_bits.erase(B);
+ undriven_bits.erase(Y);
+ and_map[Y] = make_pair(A, B);
+ continue;
+ }
- RTLIL::Module* inst_module = module->design->module(cell->type);
- if (inst_module && inst_module->get_blackbox_attribute()) {
- auto it = cell->attributes.find("\\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)
- if (!inst_module->get_bool_attribute("\\abc9_flop"))
- continue;
+ if (cell->type == "$__ABC9_FF_" &&
+ // The presence of an abc9_mergeability attribute indicates
+ // that we do want to pass this flop to ABC
+ cell->attributes.count("\\abc9_mergeability"))
+ {
+ SigBit D = sigmap(cell->getPort("\\D").as_bit());
+ SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
+ unused_bits.erase(D);
+ undriven_bits.erase(Q);
+ alias_map[Q] = D;
+ auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
+ log_assert(r.second);
+ continue;
}
- for (const auto &conn : cell->connections()) {
- auto port_wire = inst_module->wire(conn.first);
- if (port_wire->port_output) {
- arrivals.clear();
- auto it = port_wire->attributes.find("\\abc9_arrival");
- if (it == port_wire->attributes.end())
+ if (inst_module) {
+ auto it = cell->attributes.find("\\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)
+ if (!inst_module->get_bool_attribute("\\abc9_flop"))
continue;
- if (it->second.flags == 0)
- arrivals.emplace_back(it->second.as_int());
- else
- for (const auto &tok : split_tokens(it->second.decode_string()))
- arrivals.push_back(atoi(tok.c_str()));
+ }
+
+ auto &cell_arrivals = arrivals_cache[cell->type];
+ for (const auto &conn : cell->connections()) {
+ auto port_wire = inst_module->wire(conn.first);
+ if (!port_wire->port_output)
+ continue;
+
+ auto r = cell_arrivals.insert(conn.first);
+ auto &arrivals = r.first->second;
+ if (r.second) {
+ auto it = port_wire->attributes.find("\\abc9_arrival");
+ if (it == port_wire->attributes.end())
+ continue;
+ if (it->second.flags == 0)
+ arrivals.emplace_back(it->second.as_int());
+ else
+ for (const auto &tok : split_tokens(it->second.decode_string()))
+ arrivals.push_back(atoi(tok.c_str()));
+ }
+
if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire))
log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first),
GetSize(port_wire), log_signal(it->second), GetSize(arrivals));
- auto jt = arrivals.begin();
+ auto jt = arrivals.begin();
#ifndef NDEBUG
if (ys_debug(1)) {
static std::set<std::pair<IdString,IdString>> seen;
if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_arrival = %d\n", log_id(cell->type), log_id(conn.first), *jt);
}
#endif
-
for (auto bit : sigmap(conn.second)) {
arrival_times[bit] = *jt;
if (arrivals.size() > 1)
@@ -283,6 +290,9 @@ struct XAigerWriter
for (auto b : c.second) {
Wire *w = b.wire;
if (!w) continue;
+ // Do not add as PO if bit is already a PI
+ if (input_bits.count(b))
+ continue;
if (!w->port_output || !cell_known) {
SigBit I = sigmap(b);
if (I != b)
@@ -337,12 +347,11 @@ struct XAigerWriter
}
}
- // Fully pad all unused input connections of this box cell with S0
- // Fully pad all undriven output connections of this box cell with anonymous wires
for (auto port_name : r.first->second) {
auto w = box_module->wire(port_name);
log_assert(w);
- auto rhs = cell->getPort(port_name);
+ auto rhs = cell->connections_.at(port_name, SigSpec());
+ rhs.append(Const(State::Sx, GetSize(w)-GetSize(rhs)));
if (w->port_input)
for (auto b : rhs) {
SigBit I = sigmap(b);
@@ -364,6 +373,11 @@ struct XAigerWriter
alias_map[O] = b;
ci_bits.emplace_back(b);
undriven_bits.erase(O);
+ // If PI and CI, then must be a (* keep *) wire
+ if (input_bits.erase(O)) {
+ log_assert(output_bits.count(O));
+ log_assert(O.wire->get_bool_attribute(ID::keep));
+ }
}
}
@@ -432,6 +446,10 @@ struct XAigerWriter
for (auto &bit : ci_bits) {
aig_m++, aig_i++;
+ // 1'bx may exist here due to a box output
+ // that has been padded to its full width
+ if (bit == State::Sx)
+ continue;
log_assert(!aig_map.count(bit));
aig_map[bit] = 2*aig_m;
}
@@ -443,7 +461,27 @@ struct XAigerWriter
for (const auto &bit : output_bits) {
ordered_outputs[bit] = aig_o++;
- aig_outputs.push_back(bit2aig(bit));
+ int aig;
+ // Unlike bit2aig() which checks aig_map first, for
+ // inout/keep bits, since aig_map will point to
+ // the PI, first attempt to find the NOT/AND driver
+ // before resorting to an aig_map lookup (which
+ // could be another PO)
+ if (input_bits.count(bit)) {
+ if (not_map.count(bit)) {
+ aig = bit2aig(not_map.at(bit)) ^ 1;
+ } else if (and_map.count(bit)) {
+ auto args = and_map.at(bit);
+ int a0 = bit2aig(args.first);
+ int a1 = bit2aig(args.second);
+ aig = mkgate(a0, a1);
+ }
+ else
+ aig = aig_map.at(bit);
+ }
+ else
+ aig = bit2aig(bit);
+ aig_outputs.push_back(aig);
}
for (auto &i : ff_bits) {
@@ -720,7 +758,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_, $_ABC9_FF_, or");
log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n");
- log("pseudo-outputs.\n");
+ log("pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'\n");
+ log("module, if it exists.\n");
log("\n");
log(" -ascii\n");
log(" write ASCII version of AIGER format\n");
diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc
index 6d9469538..6735d670f 100644
--- a/backends/edif/edif.cc
+++ b/backends/edif/edif.cc
@@ -300,6 +300,26 @@ struct EdifBackend : public Backend {
*f << stringf(" (library DESIGN\n");
*f << stringf(" (edifLevel 0)\n");
*f << stringf(" (technology (numberDefinition))\n");
+
+ auto add_prop = [&](IdString name, Const val) {
+ if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
+ *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str());
+ else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def())
+ *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
+ else {
+ std::string hex_string = "";
+ for (size_t i = 0; i < val.bits.size(); i += 4) {
+ int digit_value = 0;
+ if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1;
+ if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2;
+ if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4;
+ if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8;
+ char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
+ hex_string = std::string(digit_str) + hex_string;
+ }
+ *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str());
+ }
+ };
for (auto module : sorted_modules)
{
if (module->get_blackbox_attribute())
@@ -323,14 +343,23 @@ struct EdifBackend : public Backend {
else if (!wire->port_input)
dir = "OUTPUT";
if (wire->width == 1) {
- *f << stringf(" (port %s (direction %s))\n", EDIF_DEF(wire->name), dir);
+ *f << stringf(" (port %s (direction %s)", EDIF_DEF(wire->name), dir);
+ if (attr_properties)
+ for (auto &p : wire->attributes)
+ add_prop(p.first, p.second);
+ *f << ")\n";
RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire));
net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name)));
} else {
int b[2];
b[wire->upto ? 0 : 1] = wire->start_offset;
b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1;
- *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir);
+ *f << stringf(" (port (array %s %d) (direction %s)", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir);
+ if (attr_properties)
+ for (auto &p : wire->attributes)
+ add_prop(p.first, p.second);
+
+ *f << ")\n";
for (int i = 0; i < wire->width; i++) {
RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i));
net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1));
@@ -348,27 +377,6 @@ struct EdifBackend : public Backend {
*f << stringf(" (instance %s\n", EDIF_DEF(cell->name));
*f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type),
lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : "");
-
- auto add_prop = [&](IdString name, Const val) {
- if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
- *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str());
- else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def())
- *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
- else {
- std::string hex_string = "";
- for (size_t i = 0; i < val.bits.size(); i += 4) {
- int digit_value = 0;
- if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1;
- if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2;
- if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4;
- if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8;
- char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
- hex_string = std::string(digit_str) + hex_string;
- }
- *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str());
- }
- };
-
for (auto &p : cell->parameters)
add_prop(p.first, p.second);
if (attr_properties)
@@ -431,8 +439,12 @@ struct EdifBackend : public Backend {
*f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');
if (sig == RTLIL::State::S1)
*f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P');
- }
- *f << stringf(" ))\n");
+ }
+ *f << stringf(" )");
+ if (attr_properties && sig.wire != NULL)
+ for (auto &p : sig.wire->attributes)
+ add_prop(p.first, p.second);
+ *f << stringf("\n )\n");
}
*f << stringf(" )\n");
*f << stringf(" )\n");