aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/aiger
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/aiger')
-rw-r--r--frontends/aiger/aigerparse.cc88
1 files changed, 70 insertions, 18 deletions
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 1ac0f7ba4..30e35da01 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -440,6 +440,7 @@ void AigerReader::parse_xaiger()
else if (c == 'r') {
uint32_t dataSize = parse_xaiger_literal(f);
flopNum = parse_xaiger_literal(f);
+ log_debug("flopNum: %u\n", flopNum);
log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
f.ignore(flopNum * sizeof(uint32_t));
}
@@ -461,7 +462,7 @@ void AigerReader::parse_xaiger()
uint32_t poNum = parse_xaiger_literal(f);
log_debug("poNum = %u\n", poNum);
uint32_t boxNum = parse_xaiger_literal(f);
- log_debug("boxNum = %u\n", poNum);
+ log_debug("boxNum = %u\n", boxNum);
for (unsigned i = 0; i < boxNum; i++) {
f.ignore(2*sizeof(uint32_t));
uint32_t boxUniqueId = parse_xaiger_literal(f);
@@ -506,8 +507,7 @@ void AigerReader::parse_aiger_ascii()
// Parse latches
RTLIL::Wire *clk_wire = nullptr;
- if (L > 0) {
- log_assert(clk_name != "");
+ if (L > 0 && !clk_name.empty()) {
clk_wire = module->wire(clk_name);
log_assert(!clk_wire);
log_debug2("Creating %s\n", clk_name.c_str());
@@ -523,7 +523,10 @@ void AigerReader::parse_aiger_ascii()
RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
- module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire);
+ if (clk_wire)
+ module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire);
+ else
+ module->addFfGate(NEW_ID, d_wire, q_wire);
// Reset logic is optional in AIGER 1.9
if (f.peek() == ' ') {
@@ -631,8 +634,7 @@ void AigerReader::parse_aiger_binary()
// Parse latches
RTLIL::Wire *clk_wire = nullptr;
- if (L > 0) {
- log_assert(clk_name != "");
+ if (L > 0 && !clk_name.empty()) {
clk_wire = module->wire(clk_name);
log_assert(!clk_wire);
log_debug2("Creating %s\n", clk_name.c_str());
@@ -648,7 +650,10 @@ void AigerReader::parse_aiger_binary()
RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
- module->addDff(NEW_ID, clk_wire, d_wire, q_wire);
+ if (clk_wire)
+ module->addDff(NEW_ID, clk_wire, d_wire, q_wire);
+ else
+ module->addFf(NEW_ID, d_wire, q_wire);
// Reset logic is optional in AIGER 1.9
if (f.peek() == ' ') {
@@ -737,13 +742,29 @@ void AigerReader::parse_aiger_binary()
void AigerReader::post_process()
{
pool<IdString> seen_boxes;
- unsigned ci_count = 0, co_count = 0;
+ dict<IdString, std::pair<RTLIL::Module*,IdString>> flop_data;
+ unsigned ci_count = 0, co_count = 0, flop_count = 0;
for (auto cell : boxes) {
RTLIL::Module* box_module = design->module(cell->type);
log_assert(box_module);
+ RTLIL::Module* flop_module = nullptr;
+ RTLIL::IdString flop_past_q;
if (seen_boxes.insert(cell->type).second) {
- auto it = box_module->attributes.find("\\abc_carry");
+ auto it = box_module->attributes.find("\\abc_flop");
+ if (it != box_module->attributes.end()) {
+ log_assert(flop_count < flopNum);
+ std::string abc_flop = it->second.decode_string();
+ auto pos = abc_flop.find(',');
+ log_assert(pos != std::string::npos);
+ flop_module = design->module(RTLIL::escape_id(abc_flop.substr(0, pos)));
+ log_assert(flop_module);
+ pos = abc_flop.rfind(',');
+ log_assert(pos != std::string::npos);
+ flop_past_q = RTLIL::escape_id(abc_flop.substr(pos+1));
+ flop_data[cell->type] = std::make_pair(flop_module, flop_past_q);
+ }
+ it = box_module->attributes.find("\\abc_carry");
if (it != box_module->attributes.end()) {
RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr;
auto carry_in_out = it->second.decode_string();
@@ -782,23 +803,28 @@ void AigerReader::post_process()
carry_out->port_id = ports.size();
}
}
+ else {
+ auto it = flop_data.find(cell->type);
+ if (it != flop_data.end())
+ std::tie(flop_module,flop_past_q) = it->second;
+ }
// NB: Assume box_module->ports are sorted alphabetically
// (as RTLIL::Module::fixup_ports() would do)
for (auto port_name : box_module->ports) {
- RTLIL::Wire* w = box_module->wire(port_name);
- log_assert(w);
+ RTLIL::Wire* port = box_module->wire(port_name);
+ log_assert(port);
RTLIL::SigSpec rhs;
- RTLIL::Wire* wire = nullptr;
- for (int i = 0; i < GetSize(w); i++) {
- if (w->port_input) {
+ for (int i = 0; i < GetSize(port); i++) {
+ RTLIL::Wire* wire = nullptr;
+ if (port->port_input) {
log_assert(co_count < outputs.size());
wire = outputs[co_count++];
log_assert(wire);
log_assert(wire->port_output);
wire->port_output = false;
}
- if (w->port_output) {
+ if (port->port_output) {
log_assert((piNum + ci_count) < inputs.size());
wire = inputs[piNum + ci_count++];
log_assert(wire);
@@ -807,7 +833,25 @@ void AigerReader::post_process()
}
rhs.append(wire);
}
- cell->setPort(port_name, rhs);
+
+ if (!flop_module || port_name != flop_past_q)
+ cell->setPort(port_name, rhs);
+ }
+
+ if (flop_module) {
+ RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count];
+ log_assert(d);
+ log_assert(d->port_output);
+ d->port_output = false;
+
+ RTLIL::Wire *q = inputs[piNum - flopNum + flop_count];
+ log_assert(q);
+ log_assert(q->port_input);
+ q->port_input = false;
+
+ flop_count++;
+ cell->type = flop_module->name;
+ module->connect(q, d);
}
}
@@ -824,6 +868,7 @@ void AigerReader::post_process()
RTLIL::Wire* wire = inputs[variable];
log_assert(wire);
log_assert(wire->port_input);
+ log_debug("Renaming input %s", log_id(wire));
if (index == 0) {
// Cope with the fact that a CI might be identical
@@ -850,6 +895,7 @@ void AigerReader::post_process()
wire->port_input = false;
}
}
+ log_debug(" -> %s\n", log_id(wire));
}
else if (type == "output") {
log_assert(static_cast<unsigned>(variable + co_count) < outputs.size());
@@ -881,6 +927,7 @@ void AigerReader::post_process()
else {
wire->port_output = false;
module->connect(wire, existing);
+ wire = existing;
}
}
else if (index > 0) {
@@ -906,6 +953,11 @@ void AigerReader::post_process()
wire->port_output = false;
}
}
+ log_debug(" -> %s\n", log_id(wire));
+ int init;
+ mf >> init;
+ if (init < 2)
+ wire->attributes["\\init"] = init;
}
else if (type == "box") {
RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable));
@@ -1016,8 +1068,8 @@ struct AigerFrontend : public Frontend {
log(" Name of module to be created (default: <filename>)\n");
log("\n");
log(" -clk_name <wire_name>\n");
- log(" AIGER latches to be transformed into posedge DFFs clocked by wire of");
- log(" this name (default: clk)\n");
+ log(" If specified, AIGER latches to be transformed into $_DFF_P_ cells\n");
+ log(" clocked by wire of this name. Otherwise, $_FF_ cells will be used.\n");
log("\n");
log(" -map <filename>\n");
log(" read file with port and latch symbols\n");