From db08afe146b885777bb1bfa2260c090d9554afe3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 8 Feb 2019 14:53:12 -0800 Subject: Copy backends/aiger/aiger.cc to xaiger.cc --- backends/aiger/xaiger.cc | 788 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 788 insertions(+) create mode 100644 backends/aiger/xaiger.cc (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc new file mode 100644 index 000000000..dfe506c66 --- /dev/null +++ b/backends/aiger/xaiger.cc @@ -0,0 +1,788 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +void aiger_encode(std::ostream &f, int x) +{ + log_assert(x >= 0); + + while (x & ~0x7f) { + f.put((x & 0x7f) | 0x80); + x = x >> 7; + } + + f.put(x); +} + +struct AigerWriter +{ + Module *module; + bool zinit_mode; + SigMap sigmap; + + dict init_map; + pool input_bits, output_bits; + dict not_map, ff_map, alias_map; + dict> and_map; + vector> asserts, assumes; + vector> liveness, fairness; + pool initstate_bits; + + vector> aig_gates; + vector aig_latchin, aig_latchinit, aig_outputs; + int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; + int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0; + + dict aig_map; + dict ordered_outputs; + dict ordered_latches; + + dict init_inputs; + int initstate_ff = 0; + + int mkgate(int a0, int a1) + { + aig_m++, aig_a++; + aig_gates.push_back(a0 > a1 ? make_pair(a0, a1) : make_pair(a1, a0)); + return 2*aig_m; + } + + int bit2aig(SigBit bit) + { + if (aig_map.count(bit) == 0) + { + aig_map[bit] = -1; + + if (initstate_bits.count(bit)) { + log_assert(initstate_ff > 0); + aig_map[bit] = initstate_ff; + } else + if (not_map.count(bit)) { + int a = bit2aig(not_map.at(bit)) ^ 1; + aig_map[bit] = a; + } else + if (and_map.count(bit)) { + auto args = and_map.at(bit); + int a0 = bit2aig(args.first); + int a1 = bit2aig(args.second); + aig_map[bit] = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + aig_map[bit] = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) + log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + } + + log_assert(aig_map.at(bit) >= 0); + return aig_map.at(bit); + } + + AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + { + pool undriven_bits; + pool unused_bits; + + // promote public wires + for (auto wire : module->wires()) + if (wire->name[0] == '\\') + sigmap.add(wire); + + // promote input wires + for (auto wire : module->wires()) + if (wire->port_input) + sigmap.add(wire); + + // promote output wires + for (auto wire : module->wires()) + if (wire->port_output) + sigmap.add(wire); + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + init_map[initsig[i]] = initval[i] == State::S1; + } + + for (int i = 0; i < GetSize(wire); i++) + { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); + + if (bit.wire == nullptr) { + if (wire->port_output) { + aig_map[wirebit] = (bit == State::S1) ? 1 : 0; + output_bits.insert(wirebit); + } + continue; + } + + undriven_bits.insert(bit); + unused_bits.insert(bit); + + if (wire->port_input) + input_bits.insert(bit); + + if (wire->port_output) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + } + } + + for (auto bit : input_bits) + undriven_bits.erase(bit); + + for (auto bit : output_bits) + unused_bits.erase(bit); + + 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.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) + { + SigBit D = sigmap(cell->getPort("\\D").as_bit()); + SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + unused_bits.erase(D); + undriven_bits.erase(Q); + ff_map[Q] = D; + 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; + } + + if (cell->type == "$initstate") + { + SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + undriven_bits.erase(Y); + initstate_bits.insert(Y); + continue; + } + + if (cell->type == "$assert") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + asserts.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$assume") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + assumes.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$live") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + liveness.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$fair") + { + SigBit A = sigmap(cell->getPort("\\A").as_bit()); + SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); + unused_bits.erase(A); + unused_bits.erase(EN); + fairness.push_back(make_pair(A, EN)); + continue; + } + + if (cell->type == "$anyconst") + { + for (auto bit : sigmap(cell->getPort("\\Y"))) { + undriven_bits.erase(bit); + ff_map[bit] = bit; + } + continue; + } + + if (cell->type == "$anyseq") + { + for (auto bit : sigmap(cell->getPort("\\Y"))) { + undriven_bits.erase(bit); + input_bits.insert(bit); + } + continue; + } + + log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + } + + for (auto bit : unused_bits) + undriven_bits.erase(bit); + + if (!undriven_bits.empty()) { + undriven_bits.sort(); + for (auto bit : undriven_bits) { + log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + input_bits.insert(bit); + } + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + } + + init_map.sort(); + input_bits.sort(); + output_bits.sort(); + not_map.sort(); + ff_map.sort(); + and_map.sort(); + + aig_map[State::S0] = 0; + aig_map[State::S1] = 1; + + for (auto bit : input_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + if (imode && input_bits.empty()) { + aig_m++, aig_i++; + } + + if (zinit_mode) + { + for (auto it : ff_map) { + if (init_map.count(it.first)) + continue; + aig_m++, aig_i++; + init_inputs[it.first] = 2*aig_m; + } + } + + int fair_live_inputs_cnt = GetSize(liveness); + int fair_live_inputs_m = aig_m; + + aig_m += fair_live_inputs_cnt; + aig_i += fair_live_inputs_cnt; + + for (auto it : ff_map) { + aig_m++, aig_l++; + aig_map[it.first] = 2*aig_m; + ordered_latches[it.first] = aig_l-1; + if (init_map.count(it.first) == 0) + aig_latchinit.push_back(2); + else + aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); + } + + if (!initstate_bits.empty() || !init_inputs.empty()) { + aig_m++, aig_l++; + initstate_ff = 2*aig_m+1; + aig_latchinit.push_back(0); + } + + int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); + int fair_live_latches_m = aig_m; + int fair_live_latches_l = aig_l; + + aig_m += fair_live_latches_cnt; + aig_l += fair_live_latches_cnt; + + for (int i = 0; i < fair_live_latches_cnt; i++) + aig_latchinit.push_back(0); + + if (zinit_mode) + { + for (auto it : ff_map) + { + int l = ordered_latches[it.first]; + + if (aig_latchinit.at(l) == 1) + aig_map[it.first] ^= 1; + + if (aig_latchinit.at(l) == 2) + { + int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + } + } + } + + for (auto it : ff_map) { + int a = bit2aig(it.second); + int l = ordered_latches[it.first]; + if (zinit_mode && aig_latchinit.at(l) == 1) + aig_latchin.push_back(a ^ 1); + else + aig_latchin.push_back(a); + } + + if (!initstate_bits.empty() || !init_inputs.empty()) + aig_latchin.push_back(1); + + for (auto bit : output_bits) { + aig_o++; + ordered_outputs[bit] = aig_o-1; + aig_outputs.push_back(bit2aig(bit)); + } + + if (omode && output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + } + + for (auto it : asserts) { + aig_b++; + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + aig_outputs.push_back(mkgate(bit_a^1, bit_en)); + } + + if (bmode && asserts.empty()) { + aig_b++; + aig_outputs.push_back(0); + } + + for (auto it : assumes) { + aig_c++; + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1); + } + + for (auto it : liveness) + { + int input_m = ++fair_live_inputs_m; + int latch_m1 = ++fair_live_latches_m; + int latch_m2 = ++fair_live_latches_m; + + log_assert(GetSize(aig_latchin) == fair_live_latches_l); + fair_live_latches_l += 2; + + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + int bit_s = 2*input_m; + int bit_q1 = 2*latch_m1; + int bit_q2 = 2*latch_m2; + + int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; + int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; + + aig_j++; + aig_latchin.push_back(bit_d1); + aig_latchin.push_back(bit_d2); + aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); + } + + for (auto it : fairness) + { + int latch_m = ++fair_live_latches_m; + + log_assert(GetSize(aig_latchin) == fair_live_latches_l); + fair_live_latches_l += 1; + + int bit_a = bit2aig(it.first); + int bit_en = bit2aig(it.second); + int bit_q = 2*latch_m; + + aig_f++; + aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); + aig_outputs.push_back(bit_q^1); + } + } + + void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) + { + int aig_obc = aig_o + aig_b + aig_c; + int aig_obcj = aig_obc + aig_j; + int aig_obcjf = aig_obcj + aig_f; + + log_assert(aig_m == aig_i + aig_l + aig_a); + log_assert(aig_l == GetSize(aig_latchin)); + log_assert(aig_l == GetSize(aig_latchinit)); + log_assert(aig_obcjf == GetSize(aig_outputs)); + + if (miter_mode) { + if (aig_b || aig_c || aig_j || aig_f) + log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n"); + f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o); + } else { + f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); + if (aig_b || aig_c || aig_j || aig_f) + f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f); + f << stringf("\n"); + } + + if (ascii_mode) + { + for (int i = 0; i < aig_i; i++) + f << stringf("%d\n", 2*i+2); + + for (int i = 0; i < aig_l; i++) { + if (zinit_mode || aig_latchinit.at(i) == 0) + f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 1) + f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 2) + f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); + } + + for (int i = 0; i < aig_obc; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("1\n"); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obcj; i < aig_obcjf; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = 0; i < aig_a; i++) + f << stringf("%d %d %d\n", 2*(aig_i+aig_l+i)+2, aig_gates.at(i).first, aig_gates.at(i).second); + } + else + { + for (int i = 0; i < aig_l; i++) { + if (zinit_mode || aig_latchinit.at(i) == 0) + f << stringf("%d\n", aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 1) + f << stringf("%d 1\n", aig_latchin.at(i)); + else if (aig_latchinit.at(i) == 2) + f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); + } + + for (int i = 0; i < aig_obc; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("1\n"); + + for (int i = aig_obc; i < aig_obcj; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = aig_obcj; i < aig_obcjf; i++) + f << stringf("%d\n", aig_outputs.at(i)); + + for (int i = 0; i < aig_a; i++) { + int lhs = 2*(aig_i+aig_l+i)+2; + int rhs0 = aig_gates.at(i).first; + int rhs1 = aig_gates.at(i).second; + int delta0 = lhs - rhs0; + int delta1 = rhs0 - rhs1; + aiger_encode(f, delta0); + aiger_encode(f, delta1); + } + } + + if (symbols_mode) + { + dict> symbols; + + for (auto wire : module->wires()) + { + if (wire->name[0] == '$') + continue; + + SigSpec sig = sigmap(wire); + + for (int i = 0; i < GetSize(wire); i++) + { + if (sig[i].wire == nullptr) { + if (wire->port_output) + sig[i] = SigBit(wire, i); + else + continue; + } + + if (wire->port_input) { + int a = aig_map.at(sig[i]); + log_assert((a & 1) == 0); + if (GetSize(wire) != 1) + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); + else + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); + } + + if (wire->port_output) { + int o = ordered_outputs.at(SigSpec(wire, i)); + if (GetSize(wire) != 1) + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); + else + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); + } + + if (init_inputs.count(sig[i])) { + int a = init_inputs.at(sig[i]); + log_assert((a & 1) == 0); + if (GetSize(wire) != 1) + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + else + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + } + + if (ordered_latches.count(sig[i])) { + int l = ordered_latches.at(sig[i]); + const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; + if (GetSize(wire) != 1) + symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); + else + symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); + } + } + } + + symbols.sort(); + + for (auto &sym : symbols) { + f << sym.first; + std::sort(sym.second.begin(), sym.second.end()); + for (auto &s : sym.second) + f << " " << s; + f << std::endl; + } + } + + f << stringf("c\nGenerated by %s\n", yosys_version_str); + } + + void write_map(std::ostream &f, bool verbose_map) + { + dict input_lines; + dict init_lines; + dict output_lines; + dict latch_lines; + dict wire_lines; + + for (auto wire : module->wires()) + { + if (!verbose_map && wire->name[0] == '$') + continue; + + SigSpec sig = sigmap(wire); + + for (int i = 0; i < GetSize(wire); i++) + { + if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr) + continue; + + int a = aig_map.at(sig[i]); + + if (verbose_map) + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); + + if (wire->port_input) { + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + if (wire->port_output) { + int o = ordered_outputs.at(sig[i]); + output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + } + + if (init_inputs.count(sig[i])) { + int a = init_inputs.at(sig[i]); + log_assert((a & 1) == 0); + init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + if (ordered_latches.count(sig[i])) { + int l = ordered_latches.at(sig[i]); + if (zinit_mode && (aig_latchinit.at(l) == 1)) + latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); + else + latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + } + } + } + + input_lines.sort(); + for (auto &it : input_lines) + f << it.second; + + init_lines.sort(); + for (auto &it : init_lines) + f << it.second; + + output_lines.sort(); + for (auto &it : output_lines) + f << it.second; + + latch_lines.sort(); + for (auto &it : latch_lines) + f << it.second; + + wire_lines.sort(); + for (auto &it : wire_lines) + f << it.second; + } +}; + +struct AigerBackend : public Backend { + AigerBackend() : Backend("aiger", "write design to AIGER file") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" write_aiger [options] [filename]\n"); + log("\n"); + log("Write the current design to an AIGER file. The design must be flattened and\n"); + log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n"); + log("$assert and $assume cells, and $initstate cells.\n"); + log("\n"); + log("$assert and $assume cells are converted to AIGER bad state properties and\n"); + log("invariant constraints.\n"); + log("\n"); + log(" -ascii\n"); + log(" write ASCII version of AGIER format\n"); + log("\n"); + log(" -zinit\n"); + log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); + log(" uninitialized FFs.\n"); + log("\n"); + log(" -miter\n"); + log(" design outputs are AIGER bad state properties\n"); + log("\n"); + log(" -symbols\n"); + log(" include a symbol table in the generated AIGER file\n"); + log("\n"); + log(" -map \n"); + log(" write an extra file with port and latch symbols\n"); + log("\n"); + log(" -vmap \n"); + log(" like -map, but more verbose\n"); + log("\n"); + log(" -I, -O, -B\n"); + log(" If the design contains no input/output/assert then create one\n"); + log(" dummy input/output/bad_state pin to make the tools reading the\n"); + log(" AIGER file happy.\n"); + log("\n"); + } + void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + bool ascii_mode = false; + bool zinit_mode = false; + bool miter_mode = false; + bool symbols_mode = false; + bool verbose_map = false; + bool imode = false; + bool omode = false; + bool bmode = false; + std::string map_filename; + + log_header(design, "Executing AIGER backend.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-ascii") { + ascii_mode = true; + continue; + } + if (args[argidx] == "-zinit") { + zinit_mode = true; + continue; + } + if (args[argidx] == "-miter") { + miter_mode = true; + continue; + } + if (args[argidx] == "-symbols") { + symbols_mode = true; + continue; + } + if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + continue; + } + if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) { + map_filename = args[++argidx]; + verbose_map = true; + continue; + } + if (args[argidx] == "-I") { + imode = true; + continue; + } + if (args[argidx] == "-O") { + omode = true; + continue; + } + if (args[argidx] == "-B") { + bmode = true; + continue; + } + break; + } + extra_args(f, filename, args, argidx); + + Module *top_module = design->top_module(); + + if (top_module == nullptr) + log_error("Can't find top module in current design!\n"); + + AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); + + if (!map_filename.empty()) { + std::ofstream mapf; + mapf.open(map_filename.c_str(), std::ofstream::trunc); + if (mapf.fail()) + log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); + writer.write_map(mapf, verbose_map); + } + } +} AigerBackend; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From ecd24461323d4dc0cd369d3173a39912aa459618 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 11 Feb 2019 15:18:42 -0800 Subject: Add write_xaiger --- backends/aiger/xaiger.cc | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dfe506c66..7fc61fa9a 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -35,7 +35,7 @@ void aiger_encode(std::ostream &f, int x) f.put(x); } -struct AigerWriter +struct XAigerWriter { Module *module; bool zinit_mode; @@ -100,7 +100,7 @@ struct AigerWriter return aig_map.at(bit); } - AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -669,20 +669,16 @@ struct AigerWriter } }; -struct AigerBackend : public Backend { - AigerBackend() : Backend("aiger", "write design to AIGER file") { } +struct XAigerBackend : public Backend { + XAigerBackend() : Backend("xaiger", "write design to XAIGER file") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" write_aiger [options] [filename]\n"); + log(" write_xaiger [options] [filename]\n"); log("\n"); - log("Write the current design to an AIGER file. The design must be flattened and\n"); - log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n"); - log("$assert and $assume cells, and $initstate cells.\n"); - log("\n"); - log("$assert and $assume cells are converted to AIGER bad state properties and\n"); - log("invariant constraints.\n"); + log("Write the current design to an XAIGER file. The design must be flattened and\n"); + log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("\n"); log(" -ascii\n"); log(" write ASCII version of AGIER format\n"); @@ -691,9 +687,6 @@ struct AigerBackend : public Backend { log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); log(" uninitialized FFs.\n"); log("\n"); - log(" -miter\n"); - log(" design outputs are AIGER bad state properties\n"); - log("\n"); log(" -symbols\n"); log(" include a symbol table in the generated AIGER file\n"); log("\n"); @@ -721,7 +714,7 @@ struct AigerBackend : public Backend { bool bmode = false; std::string map_filename; - log_header(design, "Executing AIGER backend.\n"); + log_header(design, "Executing XAIGER backend.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -734,10 +727,6 @@ struct AigerBackend : public Backend { zinit_mode = true; continue; } - if (args[argidx] == "-miter") { - miter_mode = true; - continue; - } if (args[argidx] == "-symbols") { symbols_mode = true; continue; @@ -772,7 +761,7 @@ struct AigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - AigerWriter writer(top_module, zinit_mode, imode, omode, bmode); + XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { @@ -783,6 +772,6 @@ struct AigerBackend : public Backend { writer.write_map(mapf, verbose_map); } } -} AigerBackend; +} XAigerBackend; PRIVATE_NAMESPACE_END -- cgit v1.2.3 From afa4389445adc8e53871af78ab1c38c98e03a6fc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 13:27:26 -0800 Subject: Get rid of formal stuff from xaiger backend --- backends/aiger/xaiger.cc | 58 ------------------------------------------------ 1 file changed, 58 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7fc61fa9a..c5cede3b1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -205,64 +205,6 @@ struct XAigerWriter continue; } - if (cell->type == "$assert") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - asserts.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$assume") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - assumes.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$live") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - liveness.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$fair") - { - SigBit A = sigmap(cell->getPort("\\A").as_bit()); - SigBit EN = sigmap(cell->getPort("\\EN").as_bit()); - unused_bits.erase(A); - unused_bits.erase(EN); - fairness.push_back(make_pair(A, EN)); - continue; - } - - if (cell->type == "$anyconst") - { - for (auto bit : sigmap(cell->getPort("\\Y"))) { - undriven_bits.erase(bit); - ff_map[bit] = bit; - } - continue; - } - - if (cell->type == "$anyseq") - { - for (auto bit : sigmap(cell->getPort("\\Y"))) { - undriven_bits.erase(bit); - input_bits.insert(bit); - } - continue; - } - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } -- cgit v1.2.3 From 732877558475788992ad822f28a99fd16336e05a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 14:48:38 -0800 Subject: More cleanup of write_xaiger --- backends/aiger/xaiger.cc | 74 +----------------------------------------------- 1 file changed, 1 insertion(+), 73 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c5cede3b1..758513cd4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -45,8 +45,6 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - vector> asserts, assumes; - vector> liveness, fairness; pool initstate_bits; vector> aig_gates; @@ -249,12 +247,6 @@ struct XAigerWriter } } - int fair_live_inputs_cnt = GetSize(liveness); - int fair_live_inputs_m = aig_m; - - aig_m += fair_live_inputs_cnt; - aig_i += fair_live_inputs_cnt; - for (auto it : ff_map) { aig_m++, aig_l++; aig_map[it.first] = 2*aig_m; @@ -271,16 +263,6 @@ struct XAigerWriter aig_latchinit.push_back(0); } - int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness); - int fair_live_latches_m = aig_m; - int fair_live_latches_l = aig_l; - - aig_m += fair_live_latches_cnt; - aig_l += fair_live_latches_cnt; - - for (int i = 0; i < fair_live_latches_cnt; i++) - aig_latchinit.push_back(0); - if (zinit_mode) { for (auto it : ff_map) @@ -322,64 +304,10 @@ struct XAigerWriter aig_outputs.push_back(0); } - for (auto it : asserts) { - aig_b++; - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - aig_outputs.push_back(mkgate(bit_a^1, bit_en)); - } - - if (bmode && asserts.empty()) { + if (bmode) { aig_b++; aig_outputs.push_back(0); } - - for (auto it : assumes) { - aig_c++; - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1); - } - - for (auto it : liveness) - { - int input_m = ++fair_live_inputs_m; - int latch_m1 = ++fair_live_latches_m; - int latch_m2 = ++fair_live_latches_m; - - log_assert(GetSize(aig_latchin) == fair_live_latches_l); - fair_live_latches_l += 2; - - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - int bit_s = 2*input_m; - int bit_q1 = 2*latch_m1; - int bit_q2 = 2*latch_m2; - - int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1; - int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1; - - aig_j++; - aig_latchin.push_back(bit_d1); - aig_latchin.push_back(bit_d2); - aig_outputs.push_back(mkgate(bit_q1, bit_q2^1)); - } - - for (auto it : fairness) - { - int latch_m = ++fair_live_latches_m; - - log_assert(GetSize(aig_latchin) == fair_live_latches_l); - fair_live_latches_l += 1; - - int bit_a = bit2aig(it.first); - int bit_en = bit2aig(it.second); - int bit_q = 2*latch_m; - - aig_f++; - aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1)); - aig_outputs.push_back(bit_q^1); - } } void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) -- cgit v1.2.3 From c69fba8de5056e5892014b143856993d404e7c84 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Feb 2019 14:52:47 -0800 Subject: More cleanup --- backends/aiger/xaiger.cc | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 758513cd4..4155c5281 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,7 +50,6 @@ struct XAigerWriter vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; - int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0; dict aig_map; dict ordered_outputs; @@ -305,32 +304,24 @@ struct XAigerWriter } if (bmode) { - aig_b++; + //aig_b++; aig_outputs.push_back(0); } } void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) { - int aig_obc = aig_o + aig_b + aig_c; - int aig_obcj = aig_obc + aig_j; - int aig_obcjf = aig_obcj + aig_f; + int aig_obc = aig_o; + int aig_obcj = aig_obc; + int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); log_assert(aig_l == GetSize(aig_latchin)); log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); - if (miter_mode) { - if (aig_b || aig_c || aig_j || aig_f) - log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n"); - f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o); - } else { - f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); - if (aig_b || aig_c || aig_j || aig_f) - f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f); - f << stringf("\n"); - } + f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); + f << stringf("\n"); if (ascii_mode) { -- cgit v1.2.3 From 3ac5b651973debe76d4d41aef86a9d6376bdae46 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 11:51:21 -0800 Subject: write_xaiger to cope with unknown cells by transforming them to CI/CO --- backends/aiger/xaiger.cc | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4155c5281..433f1cdd6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -46,6 +46,8 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; pool initstate_bits; + pool ci_bits, co_bits; + dict type_map; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -149,7 +151,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - output_bits.insert(wirebit); + //output_bits.insert(wirebit); } } } @@ -166,6 +168,8 @@ struct XAigerWriter { SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + if (Y.wire->port_output) + output_bits.insert(Y); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; @@ -187,6 +191,8 @@ struct XAigerWriter SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit B = sigmap(cell->getPort("\\B").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + if (Y.wire->port_output) + output_bits.insert(Y); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -202,7 +208,27 @@ struct XAigerWriter continue; } - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + for (const auto &c : cell->connections()) { + if (c.second.is_fully_const()) continue; + SigBit b = c.second.as_bit(); + Wire *w = b.wire; + if (cell->input(c.first)) { + SigBit I = sigmap(b); + if (!w->port_input) + co_bits.insert(I); + unused_bits.erase(I); + } + else if (cell->output(c.first)) { + SigBit O = sigmap(b); + if (!w->port_output) + ci_bits.insert(O); + undriven_bits.erase(O); + } + else log_abort(); + if (!type_map.count(cell->type)) + type_map[cell->type] = type_map.size()+1; + } + //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : unused_bits) @@ -227,6 +253,12 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; + for (auto bit : ci_bits) { + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + co_bits.erase(bit); + } + for (auto bit : input_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; @@ -292,6 +324,12 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); + for (auto bit : co_bits) { + aig_o++; + ordered_outputs[bit] = aig_o-1; + aig_outputs.push_back(bit2aig(bit)); + } + for (auto bit : output_bits) { aig_o++; ordered_outputs[bit] = aig_o-1; @@ -467,8 +505,8 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (!verbose_map && wire->name[0] == '$') - continue; + //if (!verbose_map && wire->name[0] == '$') + // continue; SigSpec sig = sigmap(wire); @@ -482,12 +520,12 @@ struct XAigerWriter if (verbose_map) wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - if (wire->port_input) { + if (wire->port_input || ci_bits.count(RTLIL::SigBit{wire, i})) { log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (wire->port_output) { + if (wire->port_output || co_bits.count(RTLIL::SigBit{wire, i})) { int o = ordered_outputs.at(sig[i]); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } -- cgit v1.2.3 From 486a2704156c51e1331e69cd5160965a1ef73506 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Feb 2019 15:22:18 -0800 Subject: Fixes needed for DFF circuits --- backends/aiger/xaiger.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 433f1cdd6..27e156a98 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); + //output_bits.insert(wirebit); } continue; } @@ -220,8 +220,7 @@ struct XAigerWriter } else if (cell->output(c.first)) { SigBit O = sigmap(b); - if (!w->port_output) - ci_bits.insert(O); + ci_bits.insert(O); undriven_bits.erase(O); } else log_abort(); @@ -525,7 +524,7 @@ struct XAigerWriter input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (wire->port_output || co_bits.count(RTLIL::SigBit{wire, i})) { + if (output_bits.count(RTLIL::SigBit{wire, i}) || co_bits.count(RTLIL::SigBit{wire, i})) { int o = ordered_outputs.at(sig[i]); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } -- cgit v1.2.3 From 2c1655ae9440c470a62ab7e493024a94f5d054ad Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:46:25 -0800 Subject: write_aiger() to perform CI/CO post-processing and fix symbols --- backends/aiger/xaiger.cc | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 27e156a98..3d0968cad 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -216,12 +216,10 @@ struct XAigerWriter SigBit I = sigmap(b); if (!w->port_input) co_bits.insert(I); - unused_bits.erase(I); } else if (cell->output(c.first)) { SigBit O = sigmap(b); ci_bits.insert(O); - undriven_bits.erase(O); } else log_abort(); if (!type_map.count(cell->type)) @@ -230,6 +228,19 @@ struct XAigerWriter //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + // Do some CI/CO post-processing: + // Erase all COs that are undriven + for (auto bit : undriven_bits) + co_bits.erase(bit); + // Erase all CIs that are also COs or POs + for (auto bit : co_bits) + ci_bits.erase(bit); + for (auto bit : output_bits) + ci_bits.erase(bit); + // CIs cannot be undriven + for (auto bit : ci_bits) + undriven_bits.erase(bit); + for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -255,7 +266,6 @@ struct XAigerWriter for (auto bit : ci_bits) { aig_m++, aig_i++; aig_map[bit] = 2*aig_m; - co_bits.erase(bit); } for (auto bit : input_bits) { @@ -429,8 +439,8 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->name[0] == '$') - continue; + //if (wire->name[0] == '$') + // continue; SigSpec sig = sigmap(wire); @@ -443,7 +453,7 @@ struct XAigerWriter continue; } - if (wire->port_input) { + if (input_bits.count(sig[i]) || ci_bits.count(SigSpec(sig[i]))) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -452,7 +462,7 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (wire->port_output) { + if (output_bits.count(SigSpec(wire, i)) || co_bits.count(SigSpec(wire, i))) { int o = ordered_outputs.at(SigSpec(wire, i)); if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); -- cgit v1.2.3 From 0c409e6d8cd51360b3099a725fdad6174a2dbb66 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 08:48:33 -0800 Subject: Tidy up write_xaiger --- backends/aiger/xaiger.cc | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3d0968cad..c0bd9e921 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -137,7 +137,7 @@ struct XAigerWriter if (bit.wire == nullptr) { if (wire->port_output) { aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - //output_bits.insert(wirebit); + output_bits.insert(wirebit); } continue; } @@ -151,7 +151,7 @@ struct XAigerWriter if (wire->port_output) { if (bit != wirebit) alias_map[wirebit] = bit; - //output_bits.insert(wirebit); + output_bits.insert(wirebit); } } } @@ -168,8 +168,6 @@ struct XAigerWriter { SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - if (Y.wire->port_output) - output_bits.insert(Y); unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; @@ -191,8 +189,6 @@ struct XAigerWriter SigBit A = sigmap(cell->getPort("\\A").as_bit()); SigBit B = sigmap(cell->getPort("\\B").as_bit()); SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - if (Y.wire->port_output) - output_bits.insert(Y); unused_bits.erase(A); unused_bits.erase(B); undriven_bits.erase(Y); @@ -229,9 +225,11 @@ struct XAigerWriter } // Do some CI/CO post-processing: - // Erase all COs that are undriven - for (auto bit : undriven_bits) + // Erase all POs and COs that are undriven + for (auto bit : undriven_bits) { co_bits.erase(bit); + output_bits.erase(bit); + } // Erase all CIs that are also COs or POs for (auto bit : co_bits) ci_bits.erase(bit); -- cgit v1.2.3 From b9a305b85d17ce61880ee057e19e5ceafd7a6c05 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 20:08:59 -0800 Subject: write_aiger -O to write dummy output as __dummy_o__ --- backends/aiger/xaiger.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index c0bd9e921..25e03fa5f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -502,7 +502,7 @@ struct XAigerWriter f << stringf("c\nGenerated by %s\n", yosys_version_str); } - void write_map(std::ostream &f, bool verbose_map) + void write_map(std::ostream &f, bool verbose_map, bool omode) { dict input_lines; dict init_lines; @@ -564,6 +564,9 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; + if (omode && output_bits.empty()) { + f << "output 0 0 __dummy_o__\n"; + } latch_lines.sort(); for (auto &it : latch_lines) @@ -675,7 +678,7 @@ struct XAigerBackend : public Backend { mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); - writer.write_map(mapf, verbose_map); + writer.write_map(mapf, verbose_map, omode); } } } XAigerBackend; -- cgit v1.2.3 From 6a57de90137df146529d84a04f70269382df8795 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:00:39 -0800 Subject: write_xaiger to support non-bit cell connections, and cope with COs for -O --- backends/aiger/xaiger.cc | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 25e03fa5f..456f3f899 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -206,18 +206,20 @@ struct XAigerWriter for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - SigBit b = c.second.as_bit(); - Wire *w = b.wire; - if (cell->input(c.first)) { - SigBit I = sigmap(b); - if (!w->port_input) - co_bits.insert(I); - } - else if (cell->output(c.first)) { - SigBit O = sigmap(b); - ci_bits.insert(O); + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + if (cell->input(c.first)) { + SigBit I = sigmap(b); + if (!w->port_input) + co_bits.insert(I); + } + else if (cell->output(c.first)) { + SigBit O = sigmap(b); + ci_bits.insert(O); + } + else log_abort(); } - else log_abort(); if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } @@ -343,7 +345,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (omode && output_bits.empty()) { + if (omode && output_bits.empty() && co_bits.empty()) { aig_o++; aig_outputs.push_back(0); } @@ -564,7 +566,7 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; - if (omode && output_bits.empty()) { + if (omode && output_bits.empty() && co_bits.empty()) { f << "output 0 0 __dummy_o__\n"; } -- cgit v1.2.3 From 76c35f80f4d2ad3b2e686186c9febc2872f5c9ff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 21:09:48 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 456f3f899..ae296d395 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -566,9 +566,8 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; - if (omode && output_bits.empty() && co_bits.empty()) { + if (omode && output_lines.empty()) f << "output 0 0 __dummy_o__\n"; - } latch_lines.sort(); for (auto &it : latch_lines) -- cgit v1.2.3 From 30f1204721ed592256ddde04f22dd40888b9e27c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Feb 2019 22:22:17 -0800 Subject: Cleanup --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ae296d395..d4686736d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -521,7 +521,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr) + if (aig_map.count(sig[i]) == 0 /*|| sig[i].wire == nullptr*/) continue; int a = aig_map.at(sig[i]); @@ -529,13 +529,14 @@ struct XAigerWriter if (verbose_map) wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - if (wire->port_input || ci_bits.count(RTLIL::SigBit{wire, i})) { + RTLIL::SigBit b(wire, i); + if (wire->port_input || ci_bits.count(b)) { log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } - if (output_bits.count(RTLIL::SigBit{wire, i}) || co_bits.count(RTLIL::SigBit{wire, i})) { - int o = ordered_outputs.at(sig[i]); + if (output_bits.count(b) || co_bits.count(b)) { + int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); } -- cgit v1.2.3 From ef60ca171743292e88457684d53d632c680210e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 11:09:13 -0800 Subject: write_xaiger to not write latches, CO/PO fixes --- backends/aiger/xaiger.cc | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d4686736d..d125335f9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -174,15 +174,15 @@ struct XAigerWriter continue; } - if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - { - SigBit D = sigmap(cell->getPort("\\D").as_bit()); - SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - unused_bits.erase(D); - undriven_bits.erase(Q); - ff_map[Q] = D; - continue; - } + //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) + //{ + // SigBit D = sigmap(cell->getPort("\\D").as_bit()); + // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); + // unused_bits.erase(D); + // undriven_bits.erase(Q); + // ff_map[Q] = D; + // continue; + //} if (cell->type == "$_AND_") { @@ -240,6 +240,9 @@ struct XAigerWriter // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); + // POs override COs + for (auto bit : output_bits) + co_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -521,29 +524,25 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (aig_map.count(sig[i]) == 0 /*|| sig[i].wire == nullptr*/) - continue; - - int a = aig_map.at(sig[i]); - - if (verbose_map) - wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); - RTLIL::SigBit b(wire, i); if (wire->port_input || ci_bits.count(b)) { + int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + continue; } if (output_bits.count(b) || co_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + continue; } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + continue; } if (ordered_latches.count(sig[i])) { @@ -552,6 +551,15 @@ struct XAigerWriter latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); else latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); + continue; + } + + if (verbose_map) { + if (aig_map.count(sig[i]) == 0) + continue; + + int a = aig_map.at(sig[i]); + wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire)); } } } @@ -567,6 +575,7 @@ struct XAigerWriter output_lines.sort(); for (auto &it : output_lines) f << it.second; + log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) f << "output 0 0 __dummy_o__\n"; -- cgit v1.2.3 From f89b112fbf19a751070406449ab78f07b2c5e639 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Feb 2019 15:35:32 -0800 Subject: write_aiger: fix CI/CO and symbols --- backends/aiger/xaiger.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d125335f9..56d361fff 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -232,17 +232,22 @@ struct XAigerWriter co_bits.erase(bit); output_bits.erase(bit); } - // Erase all CIs that are also COs or POs - for (auto bit : co_bits) + // Erase all POs and CIs that are also PIs + for (auto bit : input_bits) { + output_bits.erase(bit); ci_bits.erase(bit); - for (auto bit : output_bits) + } + for (auto bit : output_bits) { + ci_bits.erase(bit); + // POs override COs + co_bits.erase(bit); + } + // Erase all CIs that are also COs + for (auto bit : co_bits) ci_bits.erase(bit); // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); - // POs override COs - for (auto bit : output_bits) - co_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -525,7 +530,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (wire->port_input || ci_bits.count(b)) { + if (input_bits.count(b) || ci_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); @@ -567,6 +572,7 @@ struct XAigerWriter input_lines.sort(); for (auto &it : input_lines) f << it.second; + log_assert(input_lines.size() == input_bits.size() + ci_bits.size()); init_lines.sort(); for (auto &it : init_lines) -- cgit v1.2.3 From 2f96a0ed32799eba95837d0b64953b889e607c22 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 11:15:25 -0800 Subject: write_xaiger to use original bit for co, not sigmap()-ed bit --- backends/aiger/xaiger.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 56d361fff..b0602dbd8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -210,9 +210,12 @@ struct XAigerWriter Wire *w = b.wire; if (!w) continue; if (cell->input(c.first)) { - SigBit I = sigmap(b); - if (!w->port_input) - co_bits.insert(I); + if (!w->port_input) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.insert(b); + } } else if (cell->output(c.first)) { SigBit O = sigmap(b); -- cgit v1.2.3 From 085ed9f4878e5a376bed6b7c59dc99db46140b41 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 14:40:13 -0800 Subject: Add attribution --- backends/aiger/xaiger.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index b0602dbd8..dd174d5ee 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 5180338e8085bdf0bc653e2321559c7504c169f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Feb 2019 17:03:18 -0800 Subject: write_xaiger to write __dummy_o__ for -symbols too --- backends/aiger/xaiger.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index dd174d5ee..2b7f52d30 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -368,7 +368,7 @@ struct XAigerWriter } } - void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode) + void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -449,6 +449,7 @@ struct XAigerWriter { dict> symbols; + bool output_seen = false; for (auto wire : module->wires()) { //if (wire->name[0] == '$') @@ -458,14 +459,8 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { - if (sig[i].wire == nullptr) { - if (wire->port_output) - sig[i] = SigBit(wire, i); - else - continue; - } - - if (input_bits.count(sig[i]) || ci_bits.count(SigSpec(sig[i]))) { + RTLIL::SigBit b(wire, i); + if (input_bits.count(b) || ci_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -474,8 +469,9 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(SigSpec(wire, i)) || co_bits.count(SigSpec(wire, i))) { - int o = ordered_outputs.at(SigSpec(wire, i)); + if (output_bits.count(b) || co_bits.count(b)) { + int o = ordered_outputs.at(b); + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -502,6 +498,9 @@ struct XAigerWriter } } + if (omode && !output_seen) + symbols["o0"].push_back("__dummy_o__"); + symbols.sort(); for (auto &sym : symbols) { @@ -692,7 +691,7 @@ struct XAigerBackend : public Backend { log_error("Can't find top module in current design!\n"); XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); - writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); + writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode); if (!map_filename.empty()) { std::ofstream mapf; -- cgit v1.2.3 From 292f80d231174951b8ebda5b1f9b70b6b95a545a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 15:20:56 -0800 Subject: Cleanup abc9 code --- backends/aiger/xaiger.cc | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2b7f52d30..db0395d28 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -157,8 +157,11 @@ struct XAigerWriter } } - for (auto bit : input_bits) + for (auto bit : input_bits) { undriven_bits.erase(bit); + // Erase POs that are also PIs + output_bits.erase(bit); + } for (auto bit : output_bits) unused_bits.erase(bit); @@ -215,12 +218,14 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - co_bits.insert(b); + if (!output_bits.count(b)) + co_bits.insert(b); } } else if (cell->output(c.first)) { SigBit O = sigmap(b); - ci_bits.insert(O); + if (!input_bits.count(O) && !output_bits.count(O)) + ci_bits.insert(O); } else log_abort(); } @@ -236,16 +241,6 @@ struct XAigerWriter co_bits.erase(bit); output_bits.erase(bit); } - // Erase all POs and CIs that are also PIs - for (auto bit : input_bits) { - output_bits.erase(bit); - ci_bits.erase(bit); - } - for (auto bit : output_bits) { - ci_bits.erase(bit); - // POs override COs - co_bits.erase(bit); - } // Erase all CIs that are also COs for (auto bit : co_bits) ci_bits.erase(bit); -- cgit v1.2.3 From c492a3a1c4a36c273cb3ce8266d974a7cb595808 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 25 Feb 2019 18:39:36 -0800 Subject: write_xaiger duplicate inout port into out port with $inout.out suffix --- backends/aiger/xaiger.cc | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index db0395d28..2c4cdf080 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -213,7 +213,10 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (cell->input(c.first)) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { if (!w->port_input) { SigBit I = sigmap(b); if (I != b) @@ -222,12 +225,11 @@ struct XAigerWriter co_bits.insert(b); } } - else if (cell->output(c.first)) { + if (is_output) { SigBit O = sigmap(b); if (!input_bits.count(O) && !output_bits.count(O)) ci_bits.insert(O); } - else log_abort(); } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; @@ -260,6 +262,27 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } + for (auto bit : input_bits) { + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, then create a new wire with $inout.out + // suffix, make it a CO driven by the existing inout, and inherit existing + // inout's drivers + if (wire->port_input && wire->port_output) { + RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + if (!new_wire) + new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) + not_map[new_bit] = not_map.at(bit); + else if (and_map.count(bit)) + and_map[new_bit] = and_map.at(bit); + else if (alias_map.count(bit)) + alias_map[new_bit] = alias_map.at(bit); + co_bits.insert(new_bit); + } + } + init_map.sort(); input_bits.sort(); output_bits.sort(); -- cgit v1.2.3 From 8e883d92edef57214093ae7c5d8be6edb8462c8d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 26 Feb 2019 12:17:51 -0800 Subject: write_xaiger to behave for undriven/unused inouts --- backends/aiger/xaiger.cc | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2c4cdf080..a4ef89931 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -158,13 +158,15 @@ struct XAigerWriter } for (auto bit : input_bits) { - undriven_bits.erase(bit); + if (!bit.wire->port_output) + undriven_bits.erase(bit); // Erase POs that are also PIs output_bits.erase(bit); } for (auto bit : output_bits) - unused_bits.erase(bit); + if (!bit.wire->port_input) + unused_bits.erase(bit); for (auto cell : module->cells()) { @@ -237,6 +239,27 @@ struct XAigerWriter //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + for (auto bit : input_bits) { + RTLIL::Wire *wire = bit.wire; + // If encountering an inout port, then create a new wire with $inout.out + // suffix, make it a CO driven by the existing inout, and inherit existing + // inout's drivers + if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + if (!new_wire) + new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + SigBit new_bit(new_wire, bit.offset); + module->connect(new_bit, bit); + if (not_map.count(bit)) + not_map[new_bit] = not_map.at(bit); + else if (and_map.count(bit)) + and_map[new_bit] = and_map.at(bit); + else if (alias_map.count(bit)) + alias_map[new_bit] = alias_map.at(bit); + co_bits.insert(new_bit); + } + } + // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { @@ -262,27 +285,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - for (auto bit : input_bits) { - RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a CO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output) { - RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); - if (!new_wire) - new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); - SigBit new_bit(new_wire, bit.offset); - module->connect(new_bit, bit); - if (not_map.count(bit)) - not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); - else if (alias_map.count(bit)) - alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); - } - } - init_map.sort(); input_bits.sort(); output_bits.sort(); -- cgit v1.2.3 From 2217d59e299ce0cc15887d53308d7b7cb6400c52 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 18:06:33 -0700 Subject: Add non-input bits driven by unrecognised cells as ci_bits --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a4ef89931..bad9322bb 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -229,7 +229,7 @@ struct XAigerWriter } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O) && !output_bits.count(O)) + if (!input_bits.count(O)) ci_bits.insert(O); } } -- cgit v1.2.3 From c7483917307bd1c281b159fe15f0f79af4e305b3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 14:13:11 -0700 Subject: WIP --- backends/aiger/xaiger.cc | 82 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 14 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bad9322bb..ce10028f7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -61,6 +61,8 @@ struct XAigerWriter dict init_inputs; int initstate_ff = 0; + vector box_list; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -211,7 +213,7 @@ struct XAigerWriter } for (const auto &c : cell->connections()) { - if (c.second.is_fully_const()) continue; + /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -219,30 +221,32 @@ struct XAigerWriter auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - if (!w->port_input) { + /*if (!w->port_input)*/ { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - if (!output_bits.count(b)) + /*if (!output_bits.count(b))*/ co_bits.insert(b); } } if (is_output) { SigBit O = sigmap(b); - if (!input_bits.count(O)) + /*if (!input_bits.count(O))*/ ci_bits.insert(O); } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - //log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + + box_list.emplace_back(cell); + log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a CO driven by the existing inout, and inherit existing + // suffix, make it a PO driven by the existing inout, and inherit existing // inout's drivers if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); @@ -256,19 +260,19 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); - co_bits.insert(new_bit); + output_bits.insert(new_bit); } } // Do some CI/CO post-processing: // Erase all POs and COs that are undriven for (auto bit : undriven_bits) { - co_bits.erase(bit); + //co_bits.erase(bit); output_bits.erase(bit); } // Erase all CIs that are also COs - for (auto bit : co_bits) - ci_bits.erase(bit); + //for (auto bit : co_bits) + // ci_bits.erase(bit); // CIs cannot be undriven for (auto bit : ci_bits) undriven_bits.erase(bit); @@ -491,7 +495,8 @@ struct XAigerWriter if (output_bits.count(b) || co_bits.count(b)) { int o = ordered_outputs.at(b); - output_seen = !miter_mode; + if (output_seen && output_bits.count(b)) + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -532,7 +537,52 @@ struct XAigerWriter } } - f << stringf("c\nGenerated by %s\n", yosys_version_str); + f << "c"; + + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + int box_id = 0; + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + for (const auto &c : cell->connections()) + if (cell->input(c.first)) + box_inputs += c.second.size(); + else + box_outputs += c.second.size(); + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id++); + write_h_buffer(0 /* OldBoxNum */); + } + std::string h_buffer_str = h_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); +#else + int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); +#endif + f << "h"; + f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); + f.write(h_buffer_str.data(), h_buffer_str.size()); + + f << stringf("Generated by %s\n", yosys_version_str); } void write_map(std::ostream &f, bool verbose_map, bool omode) @@ -557,7 +607,11 @@ struct XAigerWriter int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; + + // Only continue if this input is not a CO, + // otherwise write as CO below + if (!co_bits.count(b)) + continue; } if (output_bits.count(b) || co_bits.count(b)) { @@ -606,7 +660,7 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); if (omode && output_lines.empty()) - f << "output 0 0 __dummy_o__\n"; + f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) -- cgit v1.2.3 From 686e772f0bb3129e7d6469dc25548497f107ebc5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 16:17:48 -0700 Subject: ci_bits and co_bits now a list, order is important for ABC --- backends/aiger/xaiger.cc | 58 ++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 24 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce10028f7..f67f7620b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -47,7 +47,7 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; pool initstate_bits; - pool ci_bits, co_bits; + vector> ci_bits, co_bits; dict type_map; vector> aig_gates; @@ -226,13 +226,13 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ - co_bits.insert(b); + co_bits.emplace_back(b, 0); } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ - ci_bits.insert(O); + ci_bits.emplace_back(O, 0); } } if (!type_map.count(cell->type)) @@ -240,7 +240,7 @@ struct XAigerWriter } box_list.emplace_back(cell); - log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } for (auto bit : input_bits) { @@ -274,8 +274,8 @@ struct XAigerWriter //for (auto bit : co_bits) // ci_bits.erase(bit); // CIs cannot be undriven - for (auto bit : ci_bits) - undriven_bits.erase(bit); + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); @@ -299,9 +299,10 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto bit : ci_bits) { + for (auto &c : ci_bits) { aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + c.second = 2*aig_m; + aig_map[c.first] = c.second; } for (auto bit : input_bits) { @@ -369,15 +370,15 @@ struct XAigerWriter if (!initstate_bits.empty() || !init_inputs.empty()) aig_latchin.push_back(1); - for (auto bit : co_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + for (auto &c : co_bits) { + RTLIL::SigBit bit = c.first; + c.second = aig_o++; + ordered_outputs[bit] = c.second; aig_outputs.push_back(bit2aig(bit)); } for (auto bit : output_bits) { - aig_o++; - ordered_outputs[bit] = aig_o-1; + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -484,7 +485,7 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) @@ -493,10 +494,9 @@ struct XAigerWriter symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); - if (output_seen && output_bits.count(b)) - output_seen = !miter_mode; + output_seen = !miter_mode; if (GetSize(wire) != 1) symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); else @@ -603,18 +603,13 @@ struct XAigerWriter for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); - if (input_bits.count(b) || ci_bits.count(b)) { + if (input_bits.count(b)) { int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - - // Only continue if this input is not a CO, - // otherwise write as CO below - if (!co_bits.count(b)) - continue; } - if (output_bits.count(b) || co_bits.count(b)) { + if (output_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); continue; @@ -646,6 +641,21 @@ struct XAigerWriter } } + for (const auto &c : ci_bits) { + RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; + int i = b.offset; + int a = c.second; + log_assert((a & 1) == 0); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + } + + for (const auto &c : co_bits) { + RTLIL::SigBit b = c.first; + int o = c.second; + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + } + input_lines.sort(); for (auto &it : input_lines) f << it.second; -- cgit v1.2.3 From fe0b421212a17dae32cd30a09dc43c688a285f8c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 12 Apr 2019 18:16:25 -0700 Subject: Output __const0__ and __const1__ CIs --- backends/aiger/xaiger.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f67f7620b..d3384e136 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -215,8 +215,6 @@ struct XAigerWriter for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { - Wire *w = b.wire; - if (!w) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); @@ -382,7 +380,7 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - if (omode && output_bits.empty() && co_bits.empty()) { + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); } @@ -561,11 +559,12 @@ struct XAigerWriter int box_id = 0; for (auto cell : box_list) { int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) + for (const auto &c : cell->connections()) { if (cell->input(c.first)) box_inputs += c.second.size(); - else + if (cell->output(c.first)) box_outputs += c.second.size(); + } write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_id++); @@ -652,8 +651,12 @@ struct XAigerWriter for (const auto &c : co_bits) { RTLIL::SigBit b = c.first; + RTLIL::Wire *wire = b.wire; int o = c.second; - output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(b.wire)); + if (wire) + output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire)); + else + output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data); } input_lines.sort(); @@ -669,7 +672,7 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size() + co_bits.size()); - if (omode && output_lines.empty()) + if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); -- cgit v1.2.3 From 55a3638c71229e2730e1d0f7340f6c9d4087522d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 15:01:45 -0700 Subject: Port from xc7mux branch --- backends/aiger/xaiger.cc | 146 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 37 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d3384e136..66ab3878e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -212,6 +212,9 @@ struct XAigerWriter continue; } + RTLIL::Module* box_module = module->design->module(cell->type); + bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); + for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -224,20 +227,33 @@ struct XAigerWriter if (I != b) alias_map[b] = I; /*if (!output_bits.count(b))*/ + if (abc_box) co_bits.emplace_back(b, 0); + else if (b.wire) { + output_bits.insert(b); + if (!b.wire->port_input) + unused_bits.erase(b); + } } } if (is_output) { SigBit O = sigmap(b); /*if (!input_bits.count(O))*/ + if (abc_box) ci_bits.emplace_back(O, 0); + else { + input_bits.insert(O); + if (!O.wire->port_output) + undriven_bits.erase(O); + } } } if (!type_map.count(cell->type)) type_map[cell->type] = type_map.size()+1; } - box_list.emplace_back(cell); + if (abc_box) + box_list.emplace_back(cell); //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } @@ -537,49 +553,105 @@ struct XAigerWriter f << "c"; - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { - // TODO: Don't assume we're on little endian + if (!box_list.empty()) { + std::stringstream h_buffer; + auto write_h_buffer = [&h_buffer](int i32) { + // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int i32_be = _byteswap_ulong(i32); #else - int i32_be = __builtin_bswap32(i32); + int i32_be = __builtin_bswap32(i32); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; - write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); - write_h_buffer(box_list.size()); - int box_id = 0; - for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - for (const auto &c : cell->connections()) { - if (cell->input(c.first)) - box_inputs += c.second.size(); - if (cell->output(c.first)) - box_outputs += c.second.size(); + h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + int num_outputs = output_bits.size(); + if (omode && num_outputs == 0) + num_outputs = 1; + write_h_buffer(1); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); + write_h_buffer(box_list.size()); + + RTLIL::Module *holes_module = nullptr; + holes_module = module->design->addModule("\\__holes__"); + + for (auto cell : box_list) { + int box_inputs = 0, box_outputs = 0; + int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + Cell *holes_cell = nullptr; + if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); + RTLIL::Wire *holes_wire; + int num_inputs = 0; + for (const auto &c : cell->connections()) { + if (cell->input(c.first)) { + box_inputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire->port_input = true; + } + ++num_inputs; + holes_cell->setPort(c.first, holes_wire); + } + } + if (cell->output(c.first)) { + box_outputs += c.second.size(); + if (holes_cell) { + holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); + holes_wire->port_output = true; + holes_cell->setPort(c.first, holes_wire); + } + } + } + write_h_buffer(box_inputs); + write_h_buffer(box_outputs); + write_h_buffer(box_id); + write_h_buffer(0 /* OldBoxNum */); } - write_h_buffer(box_inputs); - write_h_buffer(box_outputs); - write_h_buffer(box_id++); - write_h_buffer(0 /* OldBoxNum */); - } - std::string h_buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian + + f << "h"; + std::string buffer_str = h_buffer.str(); + // TODO: Don't assume we're on little endian #ifdef _WIN32 - int h_buffer_size_be = _byteswap_ulong(h_buffer_str.size()); + int buffer_size_be = _byteswap_ulong(buffer_str.size()); #else - int h_buffer_size_be = __builtin_bswap32(h_buffer_str.size()); + int buffer_size_be = __builtin_bswap32(buffer_str.size()); #endif - f << "h"; - f.write(reinterpret_cast(&h_buffer_size_be), sizeof(h_buffer_size_be)); - f.write(h_buffer_str.data(), h_buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + + if (holes_module) { + holes_module->fixup_ports(); + + holes_module->design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = holes_module->design->selection_stack.back(); + sel.select(holes_module); + + Pass::call(holes_module->design, "flatten; aigmap"); + + holes_module->design->selection_stack.pop_back(); + + std::stringstream a_buffer; + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + + f << "a"; + std::string buffer_str = a_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + holes_module->design->remove(holes_module); + } + } f << stringf("Generated by %s\n", yosys_version_str); } -- cgit v1.2.3 From e7a8955818b8b0fee02673607b429f1de0f7164e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 16:37:47 -0700 Subject: CIs before PIs; also sort each cell's connections before iterating --- backends/aiger/xaiger.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 66ab3878e..ce93ffb28 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -215,6 +215,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); + cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { @@ -313,15 +314,15 @@ struct XAigerWriter aig_map[State::S0] = 0; aig_map[State::S1] = 1; - for (auto &c : ci_bits) { + for (auto bit : input_bits) { aig_m++, aig_i++; - c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[bit] = 2*aig_m; } - for (auto bit : input_bits) { + for (auto &c : ci_bits) { aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; + c.second = 2*aig_m; + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -585,6 +586,7 @@ struct XAigerWriter holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); RTLIL::Wire *holes_wire; int num_inputs = 0; + // NB: cell->connections_ already sorted from before for (const auto &c : cell->connections()) { if (cell->input(c.first)) { box_inputs += c.second.size(); -- cgit v1.2.3 From 5c134980c4d0f5c1f961d50c9c1fe1752d966e48 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 16 Apr 2019 21:05:44 -0700 Subject: Optimise --- backends/aiger/xaiger.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ce93ffb28..06496dbc3 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -585,18 +585,17 @@ struct XAigerWriter if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); RTLIL::Wire *holes_wire; - int num_inputs = 0; // NB: cell->connections_ already sorted from before for (const auto &c : cell->connections()) { + log_assert(c.second.size() == 1); if (cell->input(c.first)) { box_inputs += c.second.size(); if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", num_inputs)); + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs)); + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; } - ++num_inputs; holes_cell->setPort(c.first, holes_wire); } } -- cgit v1.2.3 From d59185f1d6bdc5f63704b41553bfc72eecd84223 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 11:08:42 -0700 Subject: Remove init* from xaiger, also topo-sort cells for box flow --- backends/aiger/xaiger.cc | 252 +++++++++++++++++++++++++++++------------------ 1 file changed, 157 insertions(+), 95 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 06496dbc3..ed0fc656f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -20,6 +20,8 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/celltypes.h" +#include "kernel/utils.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -46,9 +48,8 @@ struct XAigerWriter pool input_bits, output_bits; dict not_map, ff_map, alias_map; dict> and_map; - pool initstate_bits; + //pool initstate_bits; vector> ci_bits, co_bits; - dict type_map; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -58,11 +59,11 @@ struct XAigerWriter dict ordered_outputs; dict ordered_latches; - dict init_inputs; - int initstate_ff = 0; - vector box_list; + //dict init_inputs; + //int initstate_ff = 0; + int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -76,10 +77,10 @@ struct XAigerWriter { aig_map[bit] = -1; - if (initstate_bits.count(bit)) { - log_assert(initstate_ff > 0); - aig_map[bit] = initstate_ff; - } else + //if (initstate_bits.count(bit)) { + // log_assert(initstate_ff > 0); + // aig_map[bit] = initstate_ff; + //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -170,8 +171,35 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); + dict> bit_drivers, bit_users; + TopoSort toposort; + bool abc_box_seen = false; + for (auto cell : module->cells()) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) + { + // HACK!!! + if (cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFESR", "\\SB_DFFSR", "\\SB_DFFESS") && conn.first.in("\\Q")) + continue; + + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } + + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -204,60 +232,94 @@ struct XAigerWriter continue; } - if (cell->type == "$initstate") - { - SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - undriven_bits.erase(Y); - initstate_bits.insert(Y); - continue; - } + //if (cell->type == "$initstate") + //{ + // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); + // undriven_bits.erase(Y); + // initstate_bits.insert(Y); + // continue; + //} RTLIL::Module* box_module = module->design->module(cell->type); - bool abc_box = box_module && box_module->attributes.count("\\abc_box_id"); - - cell->connections_.sort(RTLIL::sort_by_id_str()); - for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - /*if (!w->port_input)*/ { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - /*if (!output_bits.count(b))*/ - if (abc_box) - co_bits.emplace_back(b, 0); - else if (b.wire) { + if (!box_module || !box_module->attributes.count("\\abc_box_id")) { + for (const auto &c : cell->connections()) { + /*if (c.second.is_fully_const()) continue;*/ + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { + if (!w->port_input) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; output_bits.insert(b); - if (!b.wire->port_input) - unused_bits.erase(b); + unused_bits.erase(b); } } - } - if (is_output) { - SigBit O = sigmap(b); - /*if (!input_bits.count(O))*/ - if (abc_box) - ci_bits.emplace_back(O, 0); - else { + if (is_output) { + SigBit O = sigmap(b); input_bits.insert(O); if (!O.wire->port_output) undriven_bits.erase(O); } } } - if (!type_map.count(cell->type)) - type_map[cell->type] = type_map.size()+1; } + else + abc_box_seen = true; - if (abc_box) - box_list.emplace_back(cell); //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } + if (abc_box_seen) { + for (auto &it : bit_users) + if (bit_drivers.count(it.first)) + for (auto driver_cell : bit_drivers.at(it.first)) + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + + toposort.sort(); + log_assert(!toposort.found_loops); + + for (auto cell_name : toposort.sorted) { + RTLIL::Cell *cell = module->cell(cell_name); + RTLIL::Module* box_module = module->design->module(cell->type); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; + + cell->connections_.sort(RTLIL::sort_by_id_str()); + for (const auto &c : cell->connections()) { + /*if (c.second.is_fully_const()) continue;*/ + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input) { + /*if (!w->port_input)*/ { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + /*if (!output_bits.count(b))*/ + co_bits.emplace_back(b, 0); + } + } + if (is_output) { + SigBit O = sigmap(b); + /*if (!input_bits.count(O))*/ + ci_bits.emplace_back(O, 0); + } + } + } + + box_list.emplace_back(cell); + } + + // TODO: Free memory from toposort, bit_drivers, bit_users + } + for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; // If encountering an inout port, then create a new wire with $inout.out @@ -329,15 +391,15 @@ struct XAigerWriter aig_m++, aig_i++; } - if (zinit_mode) - { - for (auto it : ff_map) { - if (init_map.count(it.first)) - continue; - aig_m++, aig_i++; - init_inputs[it.first] = 2*aig_m; - } - } + //if (zinit_mode) + //{ + // for (auto it : ff_map) { + // if (init_map.count(it.first)) + // continue; + // aig_m++, aig_i++; + // init_inputs[it.first] = 2*aig_m; + // } + //} for (auto it : ff_map) { aig_m++, aig_l++; @@ -349,29 +411,29 @@ struct XAigerWriter aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); } - if (!initstate_bits.empty() || !init_inputs.empty()) { - aig_m++, aig_l++; - initstate_ff = 2*aig_m+1; - aig_latchinit.push_back(0); - } - - if (zinit_mode) - { - for (auto it : ff_map) - { - int l = ordered_latches[it.first]; - - if (aig_latchinit.at(l) == 1) - aig_map[it.first] ^= 1; - - if (aig_latchinit.at(l) == 2) - { - int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - } - } - } + //if (!initstate_bits.empty() || !init_inputs.empty()) { + // aig_m++, aig_l++; + // initstate_ff = 2*aig_m+1; + // aig_latchinit.push_back(0); + //} + + //if (zinit_mode) + //{ + // for (auto it : ff_map) + // { + // int l = ordered_latches[it.first]; + + // if (aig_latchinit.at(l) == 1) + // aig_map[it.first] ^= 1; + + // if (aig_latchinit.at(l) == 2) + // { + // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); + // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); + // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; + // } + // } + //} for (auto it : ff_map) { int a = bit2aig(it.second); @@ -382,8 +444,8 @@ struct XAigerWriter aig_latchin.push_back(a); } - if (!initstate_bits.empty() || !init_inputs.empty()) - aig_latchin.push_back(1); + //if (!initstate_bits.empty() || !init_inputs.empty()) + // aig_latchin.push_back(1); for (auto &c : co_bits) { RTLIL::SigBit bit = c.first; @@ -518,14 +580,14 @@ struct XAigerWriter symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); } - if (init_inputs.count(sig[i])) { - int a = init_inputs.at(sig[i]); - log_assert((a & 1) == 0); - if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); - else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); - } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // if (GetSize(wire) != 1) + // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + // else + // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + //} if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); @@ -687,12 +749,12 @@ struct XAigerWriter continue; } - if (init_inputs.count(sig[i])) { - int a = init_inputs.at(sig[i]); - log_assert((a & 1) == 0); - init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - continue; - } + //if (init_inputs.count(sig[i])) { + // int a = init_inputs.at(sig[i]); + // log_assert((a & 1) == 0); + // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + // continue; + //} if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); -- cgit v1.2.3 From 2b860809e9dae557a435f01a3125e6dd4b4a8599 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 12:28:19 -0700 Subject: Stop topological sort at abc_flop_q --- backends/aiger/xaiger.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ed0fc656f..070d6d403 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -180,14 +180,20 @@ struct XAigerWriter toposort.node(cell->name); for (const auto &conn : cell->connections()) { - // HACK!!! - if (cell->type.in("\\SB_DFF", "\\SB_DFFE", "\\SB_DFFESR", "\\SB_DFFSR", "\\SB_DFFESS") && conn.first.in("\\Q")) - continue; + if (!cell->type.in("$_NOT_", "$_AND_")) { + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } - if (yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + + if (inst_module_port->attributes.count("\\abc_flop_q")) continue; } -- cgit v1.2.3 From 1ec5f18346dd3f50e2340f4b79239a045ce7dd72 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 14:43:45 -0700 Subject: Cope with inout ports --- backends/aiger/xaiger.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 070d6d403..14fa4fb7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -197,9 +197,12 @@ struct XAigerWriter continue; } - if (cell->input(conn.first)) + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; for (auto bit : sigmap(conn.second)) bit_users[bit].insert(cell->name); + } if (cell->output(conn.first)) for (auto bit : sigmap(conn.second)) @@ -287,7 +290,18 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); +#ifndef NDEBUG + toposort.analyze_loops = true; +#endif toposort.sort(); +#ifndef NDEBUG + for (auto &it : toposort.loops) { + log(" loop"); + for (auto cell : it) + log(" %s", log_id(cell)); + log("\n"); + } +#endif log_assert(!toposort.found_loops); for (auto cell_name : toposort.sorted) { -- cgit v1.2.3 From 23cd2e5de042949bf47a9c72b8dd8fae48e900ce Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 17 Apr 2019 16:03:29 -0700 Subject: Fix $anyseq warning and cleanup --- backends/aiger/xaiger.cc | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 14fa4fb7f..582c49976 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -252,7 +252,7 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); if (!box_module || !box_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ + if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; @@ -271,8 +271,7 @@ struct XAigerWriter if (is_output) { SigBit O = sigmap(b); input_bits.insert(O); - if (!O.wire->port_output) - undriven_bits.erase(O); + undriven_bits.erase(O); } } } @@ -312,24 +311,19 @@ struct XAigerWriter cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { - /*if (c.second.is_fully_const()) continue;*/ for (auto b : c.second.bits()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); log_assert(is_input || is_output); if (is_input) { - /*if (!w->port_input)*/ { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - /*if (!output_bits.count(b))*/ - co_bits.emplace_back(b, 0); - } + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.emplace_back(b, 0); } if (is_output) { SigBit O = sigmap(b); - /*if (!input_bits.count(O))*/ - ci_bits.emplace_back(O, 0); + ci_bits.emplace_back(O, 0); } } } @@ -367,9 +361,6 @@ struct XAigerWriter //co_bits.erase(bit); output_bits.erase(bit); } - // Erase all CIs that are also COs - //for (auto bit : co_bits) - // ci_bits.erase(bit); // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); -- cgit v1.2.3 From 4c327cf316404fbedb1d26b0aebecaaf01d46f6b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:32:41 -0700 Subject: Use new -wb flag for ABC flow --- backends/aiger/xaiger.cc | 60 +++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 582c49976..975780488 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -103,7 +103,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool ignore_boxes=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -177,36 +177,38 @@ struct XAigerWriter for (auto cell : module->cells()) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) - { - if (!cell->type.in("$_NOT_", "$_AND_")) { - if (yosys_celltypes.cell_known(cell->type)) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") + if (!ignore_boxes) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) + { + if (!cell->type.in("$_NOT_", "$_AND_")) { + if (yosys_celltypes.cell_known(cell->type)) { + if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) + continue; + if (cell->type == "$memrd" && conn.first == "\\DATA") + continue; + } + + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + + if (inst_module_port->attributes.count("\\abc_flop_q")) continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); - log_assert(inst_module); - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; - } + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); } - - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); } if (cell->type == "$_NOT_") @@ -249,7 +251,7 @@ struct XAigerWriter // continue; //} - RTLIL::Module* box_module = module->design->module(cell->type); + RTLIL::Module* box_module = !ignore_boxes ? module->design->module(cell->type) : nullptr; if (!box_module || !box_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; @@ -705,12 +707,12 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten; aigmap"); + Pass::call(holes_module->design, "flatten -wb; aigmap"); holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* ignore_boxes */); writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); f << "a"; -- cgit v1.2.3 From 6bdf98d591a4ee5752d687d35238b454288e1d96 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 17:43:13 -0700 Subject: Add flop support for write_xaiger --- backends/aiger/xaiger.cc | 94 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 975780488..587294a40 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -177,6 +178,9 @@ struct XAigerWriter for (auto cell : module->cells()) { + RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + if (!ignore_boxes) { toposort.node(cell->name); for (const auto &conn : cell->connections()) @@ -189,7 +193,6 @@ struct XAigerWriter continue; } - RTLIL::Module* inst_module = module->design->module(cell->type); log_assert(inst_module); RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); @@ -251,8 +254,32 @@ struct XAigerWriter // continue; //} - RTLIL::Module* box_module = !ignore_boxes ? module->design->module(cell->type) : nullptr; - if (!box_module || !box_module->attributes.count("\\abc_box_id")) { + log_assert(inst_module); + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (!inst_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -311,6 +338,7 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { for (auto b : c.second.bits()) { @@ -394,10 +422,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -472,6 +510,12 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -629,7 +673,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -644,10 +688,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -700,6 +744,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); @@ -792,7 +864,7 @@ struct XAigerWriter RTLIL::SigBit b = c.first; RTLIL::Wire *wire = b.wire; int i = b.offset; - int a = c.second; + int a = bit2aig(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } @@ -845,7 +917,7 @@ struct XAigerBackend : public Backend { log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n"); log("\n"); log(" -ascii\n"); - log(" write ASCII version of AGIER format\n"); + log(" write ASCII version of AIGER format\n"); log("\n"); log(" -zinit\n"); log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); -- cgit v1.2.3 From 3544a7cd7b6b2595d25c56c5b1c3fbf6c9cccf7e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:37:10 -0700 Subject: ignore_boxes -> holes_mode --- backends/aiger/xaiger.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 587294a40..71aaebfd9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -104,7 +104,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool ignore_boxes=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -181,7 +181,7 @@ struct XAigerWriter RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (!ignore_boxes) { + if (!holes_mode) { toposort.node(cell->name); for (const auto &conn : cell->connections()) { @@ -398,7 +398,7 @@ struct XAigerWriter for (auto bit : unused_bits) undriven_bits.erase(bit); - if (!undriven_bits.empty()) { + if (!undriven_bits.empty() && !holes_mode) { undriven_bits.sort(); for (auto bit : undriven_bits) { log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); @@ -511,7 +511,6 @@ struct XAigerWriter } for (auto &f : ff_bits) { - auto bit = f.second; aig_o++; aig_outputs.push_back(ff_aig_map.at(f.second)); } @@ -779,12 +778,12 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten -wb; aigmap"); + Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge"); holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* ignore_boxes */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); f << "a"; -- cgit v1.2.3 From 35f44f3ae8618b5e5da068c3df3d35b2fdc3d1aa Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 08:44:53 -0700 Subject: Do not assume inst_module is always present --- backends/aiger/xaiger.cc | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 71aaebfd9..31b74f9aa 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -193,12 +193,13 @@ struct XAigerWriter continue; } - log_assert(inst_module); - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); + if (inst_module) { + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (inst_module_port->attributes.count("\\abc_flop_q")) + continue; + } } if (cell->input(conn.first)) { @@ -254,7 +255,6 @@ struct XAigerWriter // continue; //} - log_assert(inst_module); if (inst_flop) { SigBit d, q; for (const auto &c : cell->connections()) { @@ -279,7 +279,7 @@ struct XAigerWriter ff_bits.emplace_back(d, q); undriven_bits.erase(q); } - else if (!inst_module->attributes.count("\\abc_box_id")) { + else if (inst_module && !inst_module->attributes.count("\\abc_box_id")) { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -386,15 +386,12 @@ struct XAigerWriter } // Do some CI/CO post-processing: - // Erase all POs and COs that are undriven - for (auto bit : undriven_bits) { - //co_bits.erase(bit); + // Erase all POs that are undriven + for (auto bit : undriven_bits) output_bits.erase(bit); - } // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); - for (auto bit : unused_bits) undriven_bits.erase(bit); -- cgit v1.2.3 From 76bba4918205445e9129895f071d35e42e23efec Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Apr 2019 15:47:36 -0700 Subject: Fixes for simple_abc9 tests --- backends/aiger/xaiger.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 31b74f9aa..e93fd35f7 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -180,13 +180,14 @@ struct XAigerWriter { RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { toposort.node(cell->name); for (const auto &conn : cell->connections()) { if (!cell->type.in("$_NOT_", "$_AND_")) { - if (yosys_celltypes.cell_known(cell->type)) { + if (known_type) { if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; if (cell->type == "$memrd" && conn.first == "\\DATA") @@ -279,7 +280,10 @@ struct XAigerWriter ff_bits.emplace_back(d, q); undriven_bits.erase(q); } - else if (inst_module && !inst_module->attributes.count("\\abc_box_id")) { + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + abc_box_seen = true; + } + else { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; for (auto b : c.second.bits()) { @@ -305,8 +309,6 @@ struct XAigerWriter } } } - else - abc_box_seen = true; //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } @@ -381,6 +383,8 @@ struct XAigerWriter and_map[new_bit] = and_map.at(bit); else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); + else + alias_map[new_bit] = bit; output_bits.insert(new_bit); } } -- cgit v1.2.3 From b780c0a7de3b0f095099461af1434624d2af0c32 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:22:29 -0700 Subject: Allow POs to be PIs in XAIG --- backends/aiger/xaiger.cc | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index e93fd35f7..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -161,12 +161,8 @@ struct XAigerWriter } } - for (auto bit : input_bits) { - if (!bit.wire->port_output) - undriven_bits.erase(bit); - // Erase POs that are also PIs - output_bits.erase(bit); - } + for (auto bit : input_bits) + undriven_bits.erase(bit); for (auto bit : output_bits) if (!bit.wire->port_input) @@ -275,7 +271,8 @@ struct XAigerWriter } } } - if (!abc_box_seen) abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); ff_bits.emplace_back(d, q); undriven_bits.erase(q); -- cgit v1.2.3 From eaf3c247729365cec776e147f380ce59f7dccd4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 11:54:19 -0700 Subject: Temporarily remove 'r' extension --- backends/aiger/xaiger.cc | 84 ++++-------------------------------------------- 1 file changed, 7 insertions(+), 77 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..d6438a297 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,7 +50,6 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; - vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -175,7 +174,6 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -252,32 +250,7 @@ struct XAigerWriter // continue; //} - if (inst_flop) { - SigBit d, q; - for (const auto &c : cell->connections()) { - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - d = b; - } - if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { - SigBit O = sigmap(b); - q = O; - } - } - } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - - ff_bits.emplace_back(d, q); - undriven_bits.erase(q); - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -420,20 +393,10 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - auto bit = f.second; - aig_m++, aig_i++; - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - auto r = aig_map.insert(std::make_pair(c.first, c.second)); - if (!r.second) { - ff_aig_map[c.first] = c.second; - } + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -508,11 +471,6 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } - for (auto &f : ff_bits) { - aig_o++; - aig_outputs.push_back(ff_aig_map.at(f.second)); - } - if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -670,7 +628,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -685,10 +643,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); - write_h_buffer(input_bits.size() + ff_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()); + write_h_buffer(input_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + co_bits.size()); + write_h_buffer(input_bits.size()); + write_h_buffer(num_outputs); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -741,34 +699,6 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (!ff_bits.empty()) { - std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); - - f << "r"; - std::string buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } - if (holes_module) { holes_module->fixup_ports(); -- cgit v1.2.3 From 8f30019b68c68258979137a9d9fbbe68794781c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 22 Apr 2019 17:41:21 -0700 Subject: Revert "Temporarily remove 'r' extension" This reverts commit eaf3c247729365cec776e147f380ce59f7dccd4d. --- backends/aiger/xaiger.cc | 84 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..a881b1b88 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -50,6 +50,7 @@ struct XAigerWriter dict> and_map; //pool initstate_bits; vector> ci_bits, co_bits; + vector> ff_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -174,6 +175,7 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -250,7 +252,32 @@ struct XAigerWriter // continue; //} - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_flop) { + SigBit d, q; + for (const auto &c : cell->connections()) { + for (auto b : c.second.bits()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + d = b; + } + if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { + SigBit O = sigmap(b); + q = O; + } + } + } + if (!abc_box_seen) + abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + ff_bits.emplace_back(d, q); + undriven_bits.erase(q); + } + else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -393,10 +420,20 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } + for (auto &f : ff_bits) { + auto bit = f.second; + aig_m++, aig_i++; + aig_map[bit] = 2*aig_m; + } + + dict ff_aig_map; for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + auto r = aig_map.insert(std::make_pair(c.first, c.second)); + if (!r.second) { + ff_aig_map[c.first] = c.second; + } } if (imode && input_bits.empty()) { @@ -471,6 +508,11 @@ struct XAigerWriter aig_outputs.push_back(bit2aig(bit)); } + for (auto &f : ff_bits) { + aig_o++; + aig_outputs.push_back(ff_aig_map.at(f.second)); + } + if (omode && output_bits.empty()) { aig_o++; aig_outputs.push_back(0); @@ -628,7 +670,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty()) { + if (!box_list.empty() || !ff_bits.empty()) { std::stringstream h_buffer; auto write_h_buffer = [&h_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -643,10 +685,10 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); - write_h_buffer(input_bits.size() + ci_bits.size()); - write_h_buffer(num_outputs + co_bits.size()); - write_h_buffer(input_bits.size()); - write_h_buffer(num_outputs); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); + write_h_buffer(num_outputs + ff_bits.size() + co_bits.size()); + write_h_buffer(input_bits.size() + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; @@ -699,6 +741,34 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); + if (!ff_bits.empty()) { + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(ff_bits.size()); + int mergeability_class = 1; + for (auto cell : ff_bits) + write_r_buffer(mergeability_class++); + + f << "r"; + std::string buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + int buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); + } + if (holes_module) { holes_module->fixup_ports(); -- cgit v1.2.3 From bfd71e09906096c72039beebb1b3b6a79dd6b36c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d6438a297..504a66086 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -133,6 +133,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -151,8 +153,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -338,10 +342,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a PO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -354,7 +360,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -750,7 +758,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } -- cgit v1.2.3 From ac2aff9e28a087a9a2697cd6ccf754af738903a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 23 Apr 2019 16:11:14 -0700 Subject: Fix abc9 with (* keep *) wires --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index a881b1b88..7126002f6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -134,6 +134,8 @@ struct XAigerWriter init_map[initsig[i]] = initval[i] == State::S1; } + bool keep = wire->attributes.count("\\keep"); + for (int i = 0; i < GetSize(wire); i++) { SigBit wirebit(wire, i); @@ -152,8 +154,10 @@ struct XAigerWriter if (wire->port_input) input_bits.insert(bit); + else if (keep) + input_bits.insert(wirebit); - if (wire->port_output) { + if (wire->port_output || keep) { if (bit != wirebit) alias_map[wirebit] = bit; output_bits.insert(wirebit); @@ -365,10 +369,12 @@ struct XAigerWriter for (auto bit : input_bits) { RTLIL::Wire *wire = bit.wire; - // If encountering an inout port, then create a new wire with $inout.out - // suffix, make it a PO driven by the existing inout, and inherit existing - // inout's drivers - if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) { + // If encountering an inout port, or a keep-ed wire, then create a new wire + // with $inout.out suffix, make it a PO driven by the existing inout, and + // inherit existing inout's drivers + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + || wire->attributes.count("\\keep")) { + log_assert(input_bits.count(bit) && output_bits.count(bit)); RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); if (!new_wire) new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); @@ -381,7 +387,9 @@ struct XAigerWriter else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else + //log_abort(); alias_map[new_bit] = bit; + output_bits.erase(bit); output_bits.insert(new_bit); } } @@ -820,7 +828,7 @@ struct XAigerWriter { RTLIL::SigBit b(wire, i); if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); + int a = aig_map.at(b); log_assert((a & 1) == 0); input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); } -- cgit v1.2.3 From eec314e2621d3d055d7810f4b7e573a99e0239b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 24 Apr 2019 21:06:53 -0700 Subject: Remove topo sort no-loop assertion, with test --- backends/aiger/xaiger.cc | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 504a66086..f9d874e2d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -294,20 +294,7 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); -#ifndef NDEBUG - toposort.analyze_loops = true; -#endif toposort.sort(); -#ifndef NDEBUG - for (auto &it : toposort.loops) { - log(" loop"); - for (auto cell : it) - log(" %s", log_id(cell)); - log("\n"); - } -#endif - log_assert(!toposort.found_loops); - for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); -- cgit v1.2.3 From 0f094fba08b69baa2329e749daf19f41a624a0a0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 21 May 2019 16:19:23 -0700 Subject: Pad all boxes so that all input/output connections specified --- backends/aiger/xaiger.cc | 89 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 22 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f9d874e2d..676311440 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -301,6 +301,35 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + // Fully pad all unused input connections of this box cell with S0 + // Fully pad all undriven output connections of thix box cell with anonymous wires + for (const auto w : box_module->wires()) { + if (w->port_input) { + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) { + RTLIL::SigSpec padded_connection(RTLIL::S0, GetSize(w)-GetSize(it->second)); + padded_connection.append(it->second); + it->second = std::move(padded_connection); + } + } + else + cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + } + if (w->port_output) { + auto it = cell->connections_.find(w->name); + if (it != cell->connections_.end()) { + if (GetSize(it->second) < GetSize(w)) { + RTLIL::SigSpec padded_connection = module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)); + padded_connection.append(it->second); + it->second = std::move(padded_connection); + } + } + else + cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); + } + } + // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { @@ -646,37 +675,53 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); + log_assert(holes_module); + dict> box_io; for (auto cell : box_list) { - int box_inputs = 0, box_outputs = 0; - int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int(); + RTLIL::Module* box_module = module->design->module(cell->type); + int box_id = box_module->attributes.at("\\abc_box_id").as_int(); Cell *holes_cell = nullptr; - if (holes_module && !holes_module->cell(stringf("\\u%d", box_id))) + int box_inputs = 0, box_outputs = 0; + + auto it = box_io.find(cell->type); + if (it == box_io.end()) { holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); - RTLIL::Wire *holes_wire; - // NB: cell->connections_ already sorted from before - for (const auto &c : cell->connections()) { - log_assert(c.second.size() == 1); - if (cell->input(c.first)) { - box_inputs += c.second.size(); - if (holes_cell) { - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; + + RTLIL::Wire *holes_wire; + box_module->wires_.sort(RTLIL::sort_by_id_str()); + for (const auto w : box_module->wires()) { + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; + } + port_wire.append(holes_wire); } - holes_cell->setPort(c.first, holes_wire); + holes_cell->setPort(w->name, holes_wire); } - } - if (cell->output(c.first)) { - box_outputs += c.second.size(); - if (holes_cell) { - holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str())); - holes_wire->port_output = true; - holes_cell->setPort(c.first, holes_wire); + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->type.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + port_wire.append(holes_wire); + } + holes_cell->setPort(w->name, holes_wire); } } + box_io[cell->type] = std::make_pair(box_inputs,box_outputs); } + else + std::tie(box_inputs,box_outputs) = it->second; + write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_id); -- cgit v1.2.3 From 01684643b6edd4290701b2e08114cb731db5f446 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 25 May 2019 22:34:50 -0700 Subject: Fix "write_xaiger", and to write each box contents into holes --- backends/aiger/xaiger.cc | 101 +++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 39 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 676311440..7e674cb87 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -385,8 +385,9 @@ struct XAigerWriter // Do some CI/CO post-processing: // Erase all POs that are undriven - for (auto bit : undriven_bits) - output_bits.erase(bit); + if (!holes_mode) + for (auto bit : undriven_bits) + output_bits.erase(bit); // CIs cannot be undriven for (const auto &c : ci_bits) undriven_bits.erase(c.first); @@ -676,55 +677,45 @@ struct XAigerWriter RTLIL::Module *holes_module = nullptr; holes_module = module->design->addModule("\\__holes__"); log_assert(holes_module); - dict> box_io; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); - int box_id = box_module->attributes.at("\\abc_box_id").as_int(); - Cell *holes_cell = nullptr; int box_inputs = 0, box_outputs = 0; + Cell *holes_cell = holes_module->addCell(cell->name, cell->type); - auto it = box_io.find(cell->type); - if (it == box_io.end()) { - holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type); - - RTLIL::Wire *holes_wire; - box_module->wires_.sort(RTLIL::sort_by_id_str()); - for (const auto w : box_module->wires()) { - RTLIL::SigSpec port_wire; - if (w->port_input) { - for (int i = 0; i < GetSize(w); i++) { - box_inputs++; - holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); - if (!holes_wire) { - holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); - holes_wire->port_input = true; - } - port_wire.append(holes_wire); + RTLIL::Wire *holes_wire; + box_module->wires_.sort(RTLIL::sort_by_id_str()); + for (const auto w : box_module->wires()) { + RTLIL::SigSpec port_wire; + if (w->port_input) { + for (int i = 0; i < GetSize(w); i++) { + box_inputs++; + holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + if (!holes_wire) { + holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); + holes_wire->port_input = true; } - holes_cell->setPort(w->name, holes_wire); + port_wire.append(holes_wire); } - if (w->port_output) { - box_outputs += GetSize(w); - for (int i = 0; i < GetSize(w); i++) { - if (GetSize(w) == 1) - holes_wire = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), w->name.c_str())); - else - holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->type.c_str(), w->name.c_str(), i)); - holes_wire->port_output = true; - port_wire.append(holes_wire); - } - holes_cell->setPort(w->name, holes_wire); + holes_cell->setPort(w->name, port_wire); + } + if (w->port_output) { + box_outputs += GetSize(w); + for (int i = 0; i < GetSize(w); i++) { + if (GetSize(w) == 1) + holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str())); + else + holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); + holes_wire->port_output = true; + port_wire.append(holes_wire); } + holes_cell->setPort(w->name, port_wire); } - box_io[cell->type] = std::make_pair(box_inputs,box_outputs); } - else - std::tie(box_inputs,box_outputs) = it->second; write_h_buffer(box_inputs); write_h_buffer(box_outputs); - write_h_buffer(box_id); + write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); write_h_buffer(0 /* OldBoxNum */); } @@ -746,7 +737,16 @@ struct XAigerWriter RTLIL::Selection& sel = holes_module->design->selection_stack.back(); sel.select(holes_module); - Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge"); + // TODO: Should not need to opt_merge if we only instantiate + // each box type once... + Pass::call(holes_module->design, "opt_merge -share_all"); + + Pass::call(holes_module->design, "flatten -wb;"); + + // TODO: Should techmap all lib_whitebox-es once + Pass::call(holes_module->design, "techmap;"); + + Pass::call(holes_module->design, "aigmap; clean -purge"); holes_module->design->selection_stack.pop_back(); @@ -766,6 +766,29 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); } + + std::stringstream r_buffer; + auto write_r_buffer = [&r_buffer](int i32) { + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + int i32_be = _byteswap_ulong(i32); +#else + int i32_be = __builtin_bswap32(i32); +#endif + r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + }; + write_r_buffer(0); + + f << "r"; + buffer_str = r_buffer.str(); + // TODO: Don't assume we're on little endian +#ifdef _WIN32 + buffer_size_be = _byteswap_ulong(buffer_str.size()); +#else + buffer_size_be = __builtin_bswap32(buffer_str.size()); +#endif + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); } f << stringf("Generated by %s\n", yosys_version_str); -- cgit v1.2.3 From 32a4c10c0df7e82c69b0d96a63be0c5267d33257 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 02:44:36 -0700 Subject: Fix "a" extension --- backends/aiger/xaiger.cc | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e674cb87..3d275214b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -681,9 +681,12 @@ struct XAigerWriter for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; - Cell *holes_cell = holes_module->addCell(cell->name, cell->type); + Cell *holes_cell = nullptr; + if (box_module->get_bool_attribute("\\whitebox")) + holes_cell = holes_module->addCell(cell->name, cell->type); RTLIL::Wire *holes_wire; + // TODO: Only sort once box_module->wires_.sort(RTLIL::sort_by_id_str()); for (const auto w : box_module->wires()) { RTLIL::SigSpec port_wire; @@ -695,9 +698,11 @@ struct XAigerWriter holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; } - port_wire.append(holes_wire); + if (holes_cell) + port_wire.append(holes_wire); } - holes_cell->setPort(w->name, port_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } if (w->port_output) { box_outputs += GetSize(w); @@ -707,9 +712,13 @@ struct XAigerWriter else holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; - port_wire.append(holes_wire); + if (holes_cell) + port_wire.append(holes_wire); + else + holes_module->connect(holes_wire, RTLIL::S0); } - holes_cell->setPort(w->name, port_wire); + if (!port_wire.empty()) + holes_cell->setPort(w->name, port_wire); } } @@ -741,12 +750,13 @@ struct XAigerWriter // each box type once... Pass::call(holes_module->design, "opt_merge -share_all"); - Pass::call(holes_module->design, "flatten -wb;"); + Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap all lib_whitebox-es once - Pass::call(holes_module->design, "techmap;"); + //Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap; clean -purge"); + Pass::call(holes_module->design, "aigmap"); + Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); -- cgit v1.2.3 From 67f7c64a778e46882f884fd7058dc7bc07c5ca1e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 11:26:38 -0700 Subject: Fix padding, remove CIs from undriven_bits before erasing undriven POs --- backends/aiger/xaiger.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3d275214b..618a6500d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -302,16 +302,13 @@ struct XAigerWriter continue; // Fully pad all unused input connections of this box cell with S0 - // Fully pad all undriven output connections of thix box cell with anonymous wires + // Fully pad all undriven output connections of this box cell with anonymous wires for (const auto w : box_module->wires()) { if (w->port_input) { auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) { - RTLIL::SigSpec padded_connection(RTLIL::S0, GetSize(w)-GetSize(it->second)); - padded_connection.append(it->second); - it->second = std::move(padded_connection); - } + if (GetSize(it->second) < GetSize(w)) + it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); } else cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); @@ -319,11 +316,8 @@ struct XAigerWriter if (w->port_output) { auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { - if (GetSize(it->second) < GetSize(w)) { - RTLIL::SigSpec padded_connection = module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)); - padded_connection.append(it->second); - it->second = std::move(padded_connection); - } + if (GetSize(it->second) < GetSize(w)) + it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); } else cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); @@ -384,13 +378,13 @@ struct XAigerWriter } // Do some CI/CO post-processing: + // CIs cannot be undriven + for (const auto &c : ci_bits) + undriven_bits.erase(c.first); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) output_bits.erase(bit); - // CIs cannot be undriven - for (const auto &c : ci_bits) - undriven_bits.erase(c.first); for (auto bit : unused_bits) undriven_bits.erase(bit); -- cgit v1.2.3 From 3c8368454f5f9643425bab0065158587b03e2716 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 26 May 2019 14:14:13 -0700 Subject: Fix "a" connectivity --- backends/aiger/xaiger.cc | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 618a6500d..6cf0cb026 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -398,8 +398,25 @@ struct XAigerWriter } init_map.sort(); - input_bits.sort(); - output_bits.sort(); + if (holes_mode) { +#ifndef NDEBUG + RTLIL::SigBit last_bit; + for (auto bit : input_bits) { + log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); + last_bit = bit; + } + last_bit = RTLIL::SigBit(); + for (auto bit : output_bits) { + log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); + last_bit = bit; + } +#endif + } + else { + input_bits.sort(); + output_bits.sort(); + } + not_map.sort(); ff_map.sort(); and_map.sort(); @@ -415,7 +432,7 @@ struct XAigerWriter for (auto &c : ci_bits) { aig_m++, aig_i++; c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[c.first] = c.second; } if (imode && input_bits.empty()) { @@ -672,6 +689,7 @@ struct XAigerWriter holes_module = module->design->addModule("\\__holes__"); log_assert(holes_module); + int port_id = 1; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; @@ -691,6 +709,8 @@ struct XAigerWriter if (!holes_wire) { holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); } if (holes_cell) port_wire.append(holes_wire); @@ -706,6 +726,8 @@ struct XAigerWriter else holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i)); holes_wire->port_output = true; + holes_wire->port_id = port_id++; + holes_module->ports.push_back(holes_wire->name); if (holes_cell) port_wire.append(holes_wire); else @@ -734,7 +756,9 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { - holes_module->fixup_ports(); + // NB: fixup_ports() will sort ports by name + //holes_module->fixup_ports(); + holes_module->check(); holes_module->design->selection_stack.emplace_back(false); RTLIL::Selection& sel = holes_module->design->selection_stack.back(); @@ -750,7 +774,8 @@ struct XAigerWriter //Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - Pass::call(holes_module->design, "clean -purge"); + //TODO: clean will mess up port_ids + //Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); -- cgit v1.2.3 From 03b289a851c62eb2a7e3592432876bfa8a56770b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 11:38:52 -0700 Subject: Add 'cinput' and 'coutput' to symbols file for boxes --- backends/aiger/xaiger.cc | 58 ++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6cf0cb026..582e8e076 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -49,7 +49,8 @@ struct XAigerWriter dict not_map, ff_map, alias_map; dict> and_map; //pool initstate_bits; - vector> ci_bits, co_bits; + vector> ci_bits; + vector> co_bits; vector> aig_gates; vector aig_latchin, aig_latchinit, aig_outputs; @@ -327,6 +328,7 @@ struct XAigerWriter // Box ordering is alphabetical cell->connections_.sort(RTLIL::sort_by_id_str()); for (const auto &c : cell->connections()) { + int offset = 0; for (auto b : c.second.bits()) { auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); @@ -335,11 +337,11 @@ struct XAigerWriter SigBit I = sigmap(b); if (I != b) alias_map[b] = I; - co_bits.emplace_back(b, 0); + co_bits.emplace_back(b, cell, c.first, offset++, 0); } if (is_output) { SigBit O = sigmap(b); - ci_bits.emplace_back(O, 0); + ci_bits.emplace_back(O, cell, c.first, offset++); } } } @@ -380,7 +382,7 @@ struct XAigerWriter // Do some CI/CO post-processing: // CIs cannot be undriven for (const auto &c : ci_bits) - undriven_bits.erase(c.first); + undriven_bits.erase(std::get<0>(c)); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) @@ -399,18 +401,13 @@ struct XAigerWriter init_map.sort(); if (holes_mode) { -#ifndef NDEBUG - RTLIL::SigBit last_bit; - for (auto bit : input_bits) { - log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); - last_bit = bit; - } - last_bit = RTLIL::SigBit(); - for (auto bit : output_bits) { - log_assert(!last_bit.wire || last_bit.wire->port_id < bit.wire->port_id); - last_bit = bit; - } -#endif + struct sort_by_port_id { + bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { + return a.wire->port_id < b.wire->port_id; + } + }; + input_bits.sort(sort_by_port_id()); + output_bits.sort(sort_by_port_id()); } else { input_bits.sort(); @@ -431,8 +428,7 @@ struct XAigerWriter for (auto &c : ci_bits) { aig_m++, aig_i++; - c.second = 2*aig_m; - aig_map[c.first] = c.second; + aig_map[std::get<0>(c)] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -496,9 +492,9 @@ struct XAigerWriter // aig_latchin.push_back(1); for (auto &c : co_bits) { - RTLIL::SigBit bit = c.first; - c.second = aig_o++; - ordered_outputs[bit] = c.second; + RTLIL::SigBit bit = std::get<0>(c); + std::get<4>(c) = aig_o++; + ordered_outputs[bit] = std::get<4>(c); aig_outputs.push_back(bit2aig(bit)); } @@ -774,8 +770,7 @@ struct XAigerWriter //Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - //TODO: clean will mess up port_ids - //Pass::call(holes_module->design, "clean -purge"); + Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back(); @@ -880,22 +875,17 @@ struct XAigerWriter } for (const auto &c : ci_bits) { - RTLIL::SigBit b = c.first; - RTLIL::Wire *wire = b.wire; - int i = b.offset; + RTLIL::SigBit b = std::get<0>(c); + int i = std::get<3>(c); int a = bit2aig(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire)); + input_lines[a] += stringf("cinput %d %d %s %s\n", (a >> 1)-1, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); } for (const auto &c : co_bits) { - RTLIL::SigBit b = c.first; - RTLIL::Wire *wire = b.wire; - int o = c.second; - if (wire) - output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire)); - else - output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data); + int i = std::get<3>(c); + int o = std::get<4>(c); + output_lines[o] += stringf("coutput %d %d %s %s\n", o, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); } input_lines.sort(); -- cgit v1.2.3 From 234156c01a4086a69ff9ac9f6ae668d64734d525 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 12:16:10 -0700 Subject: Instantiate cell type (from sym file) otherwise 'clean' warnings --- backends/aiger/xaiger.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 582e8e076..3c96f6c9e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -879,13 +879,15 @@ struct XAigerWriter int i = std::get<3>(c); int a = bit2aig(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("cinput %d %d %s %s\n", (a >> 1)-1, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); + RTLIL::Cell* cell = std::get<1>(c); + input_lines[a] += stringf("cinput %d %d %s %s %s\n", (a >> 1)-1, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); } for (const auto &c : co_bits) { int i = std::get<3>(c); int o = std::get<4>(c); - output_lines[o] += stringf("coutput %d %d %s %s\n", o, i, log_id(std::get<1>(c)), log_id(std::get<2>(c))); + RTLIL::Cell* cell = std::get<1>(c); + output_lines[o] += stringf("coutput %d %d %s %s %s\n", o, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); } input_lines.sort(); -- cgit v1.2.3 From 3f60061615a8b5df3ad05b997407f195c8197754 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 27 May 2019 23:10:59 -0700 Subject: Map file to include boxes not CI/CO --- backends/aiger/xaiger.cc | 83 ++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 45 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3c96f6c9e..2bc059dc5 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -304,48 +304,52 @@ 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 (const auto w : box_module->wires()) { + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + auto it = cell->connections_.find(port_name); if (w->port_input) { - auto it = cell->connections_.find(w->name); + RTLIL::SigSpec rhs; if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second))); + rhs = it->second; + } + else { + rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); + cell->setPort(port_name, rhs); + } + + int offset = 0; + for (const auto &b : rhs.bits()) { + SigBit I = sigmap(b); + if (I != b) + alias_map[b] = I; + co_bits.emplace_back(b, cell, port_name, offset++, 0); } - else - cell->connections_[w->name] = RTLIL::SigSpec(RTLIL::S0, GetSize(w)); } if (w->port_output) { + RTLIL::SigSpec rhs; auto it = cell->connections_.find(w->name); if (it != cell->connections_.end()) { if (GetSize(it->second) < GetSize(w)) it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); + rhs = it->second; } - else - cell->connections_[w->name] = module->addWire(NEW_ID, GetSize(w)); - } - } - - // Box ordering is alphabetical - cell->connections_.sort(RTLIL::sort_by_id_str()); - for (const auto &c : cell->connections()) { - int offset = 0; - for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; - co_bits.emplace_back(b, cell, c.first, offset++, 0); + else { + rhs = module->addWire(NEW_ID, GetSize(w)); + cell->setPort(port_name, rhs); } - if (is_output) { + + int offset = 0; + for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); - ci_bits.emplace_back(O, cell, c.first, offset++); + ci_bits.emplace_back(O, cell, port_name, offset++); } } } - box_list.emplace_back(cell); } @@ -686,6 +690,7 @@ struct XAigerWriter log_assert(holes_module); int port_id = 1; + int box_count = 0; for (auto cell : box_list) { RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; @@ -737,7 +742,7 @@ struct XAigerWriter write_h_buffer(box_inputs); write_h_buffer(box_outputs); write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int()); - write_h_buffer(0 /* OldBoxNum */); + write_h_buffer(box_count++); } f << "h"; @@ -844,7 +849,7 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire)); + output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire)); continue; } @@ -874,35 +879,23 @@ struct XAigerWriter } } - for (const auto &c : ci_bits) { - RTLIL::SigBit b = std::get<0>(c); - int i = std::get<3>(c); - int a = bit2aig(b); - log_assert((a & 1) == 0); - RTLIL::Cell* cell = std::get<1>(c); - input_lines[a] += stringf("cinput %d %d %s %s %s\n", (a >> 1)-1, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); - } - - for (const auto &c : co_bits) { - int i = std::get<3>(c); - int o = std::get<4>(c); - RTLIL::Cell* cell = std::get<1>(c); - output_lines[o] += stringf("coutput %d %d %s %s %s\n", o, i, log_id(cell), log_id(std::get<2>(c)), log_id(cell->type)); - } - input_lines.sort(); for (auto &it : input_lines) f << it.second; - log_assert(input_lines.size() == input_bits.size() + ci_bits.size()); + log_assert(input_lines.size() == input_bits.size()); init_lines.sort(); for (auto &it : init_lines) f << it.second; + int box_count = 0; + for (auto cell : box_list) + f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); + output_lines.sort(); for (auto &it : output_lines) f << it.second; - log_assert(output_lines.size() == output_bits.size() + co_bits.size()); + log_assert(output_lines.size() == output_bits.size()); if (omode && output_bits.empty()) f << "output " << output_lines.size() << " 0 __dummy_o__\n"; -- cgit v1.2.3 From 13e233217cd0caceeb5d30d2eefa5238ffc5bfc9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 11:29:59 -0700 Subject: Small improvement --- backends/aiger/xaiger.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2bc059dc5..5919b2302 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -328,6 +328,7 @@ struct XAigerWriter if (I != b) alias_map[b] = I; co_bits.emplace_back(b, cell, port_name, offset++, 0); + unused_bits.erase(b); } } if (w->port_output) { @@ -347,6 +348,7 @@ struct XAigerWriter for (const auto &b : rhs.bits()) { SigBit O = sigmap(b); ci_bits.emplace_back(O, cell, port_name, offset++); + undriven_bits.erase(O); } } } @@ -383,10 +385,6 @@ struct XAigerWriter } } - // Do some CI/CO post-processing: - // CIs cannot be undriven - for (const auto &c : ci_bits) - undriven_bits.erase(std::get<0>(c)); // Erase all POs that are undriven if (!holes_mode) for (auto bit : undriven_bits) -- cgit v1.2.3 From b4321a31bbd9f215e753563d5d031b2c24f1b371 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 28 May 2019 12:42:17 -0700 Subject: Fix for abc9_test022 --- backends/aiger/xaiger.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 5919b2302..2ffd460dd 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -277,8 +277,10 @@ struct XAigerWriter } } if (is_output) { + input_bits.insert(b); SigBit O = sigmap(b); - input_bits.insert(O); + if (O != b) + alias_map[O] = b; undriven_bits.erase(O); } } @@ -346,8 +348,10 @@ struct XAigerWriter int offset = 0; for (const auto &b : rhs.bits()) { + ci_bits.emplace_back(b, cell, port_name, offset++); SigBit O = sigmap(b); - ci_bits.emplace_back(O, cell, port_name, offset++); + if (O != b) + alias_map[O] = b; undriven_bits.erase(O); } } -- cgit v1.2.3 From 1423384367d4fa31f09c6c7b69c1b89edc3dd066 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 29 May 2019 15:24:09 -0700 Subject: Fix abc_test024 --- backends/aiger/xaiger.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2ffd460dd..bf696bfd6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,10 +152,11 @@ struct XAigerWriter undriven_bits.insert(bit); unused_bits.insert(bit); - if (wire->port_input) - input_bits.insert(bit); - else if (keep) + if (wire->port_input || keep) { + if (bit != wirebit) + alias_map[bit] = wirebit; input_bits.insert(wirebit); + } if (wire->port_output || keep) { if (bit != wirebit) @@ -166,7 +167,7 @@ struct XAigerWriter } for (auto bit : input_bits) - undriven_bits.erase(bit); + undriven_bits.erase(sigmap(bit)); for (auto bit : output_bits) if (!bit.wire->port_input) -- cgit v1.2.3 From fdfc18be91123e2939f134dafc12e1e0c1a82f7b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 01:23:36 -0700 Subject: Carry in/out to be the last input/output for chains to be preserved --- backends/aiger/xaiger.cc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf696bfd6..25de7daba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -298,6 +298,8 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); + pool abc_carry_modules; + toposort.sort(); for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); @@ -305,6 +307,42 @@ struct XAigerWriter if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; + RTLIL::Wire* last_in = nullptr, *last_out = nullptr; + for (const auto &port_name : box_module->ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_input) { + if (w->attributes.count("\\abc_carry_in")) { + log_assert(!carry_in); + carry_in = w; + } + log_assert(!last_in || last_in->port_id < w->port_id); + last_in = w; + } + if (w->port_output) { + if (w->attributes.count("\\abc_carry_out")) { + log_assert(!carry_out); + carry_out = w; + } + log_assert(!last_out || last_out->port_id < w->port_id); + last_out = w; + } + } + + if (carry_in) { + log_assert(last_in); + std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]); + std::swap(carry_in->port_id, last_in->port_id); + } + if (carry_out) { + log_assert(last_out); + std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]); + std::swap(carry_out->port_id, last_out->port_id); + } + } + // 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 // NB: Assume box_module->ports are sorted alphabetically -- cgit v1.2.3 From e3c8132d7acaae328adeb8d4db1857275b5e8323 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 12:26:51 -0700 Subject: Do not re-sort box_module ports --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 25de7daba..efdd1844b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -739,10 +739,12 @@ struct XAigerWriter if (box_module->get_bool_attribute("\\whitebox")) holes_cell = holes_module->addCell(cell->name, cell->type); - RTLIL::Wire *holes_wire; - // TODO: Only sort once - box_module->wires_.sort(RTLIL::sort_by_id_str()); - for (const auto w : box_module->wires()) { + // NB: Assume box_module->ports are sorted alphabetically + // (as RTLIL::Module::fixup_ports() would do) + for (const auto &port_name : box_module->ports) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + RTLIL::Wire *holes_wire; RTLIL::SigSpec port_wire; if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { -- cgit v1.2.3 From 887c31f33b82e5cb3f50523873d41ceb0cb8e7f4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 30 May 2019 16:03:22 -0700 Subject: Fix issue where keep signal became PI, but also box was adding CI driver --- backends/aiger/xaiger.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index efdd1844b..cd15b6160 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -392,6 +392,12 @@ struct XAigerWriter if (O != b) alias_map[O] = b; undriven_bits.erase(O); + + auto jt = input_bits.find(b); + if (jt != input_bits.end()) { + log_assert(b.wire->attributes.count("\\keep")); + input_bits.erase(b); + } } } } @@ -409,9 +415,10 @@ struct XAigerWriter if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { log_assert(input_bits.count(bit) && output_bits.count(bit)); - RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out"); + RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; + RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) - new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire)); + new_wire = module->addWire(wire_name, GetSize(wire)); SigBit new_bit(new_wire, bit.offset); module->connect(new_bit, bit); if (not_map.count(bit)) @@ -468,12 +475,15 @@ struct XAigerWriter for (auto bit : input_bits) { aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } for (auto &c : ci_bits) { + RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - aig_map[std::get<0>(c)] = 2*aig_m; + log_assert(!aig_map.count(bit)); + aig_map[bit] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -538,8 +548,7 @@ struct XAigerWriter for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); - std::get<4>(c) = aig_o++; - ordered_outputs[bit] = std::get<4>(c); + std::get<4>(c) = ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@ -720,10 +729,15 @@ struct XAigerWriter if (omode && num_outputs == 0) num_outputs = 1; write_h_buffer(1); + log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", num_outputs + co_bits.size()); write_h_buffer(num_outputs + co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size()); write_h_buffer(input_bits.size()); + log_debug("poNum = %d\n", num_outputs); write_h_buffer(num_outputs); + log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; -- cgit v1.2.3 From 4623177655892c4aaf68757efff89aa748090c58 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 31 May 2019 15:23:33 -0700 Subject: ABC9 to understand flops --- backends/aiger/xaiger.cc | 73 ++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 46 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7a139f68f..90fea2db1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -181,7 +181,6 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; bool known_type = yosys_celltypes.cell_known(cell->type); if (!holes_mode) { @@ -258,22 +257,28 @@ struct XAigerWriter // continue; //} + bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; if (inst_flop) { SigBit d, q; for (const auto &c : cell->connections()) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + RTLIL::Wire* port = inst_module->wire(c.first); for (auto b : c.second.bits()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) { - SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; + if (is_input && port->attributes.count("\\abc_flop_d")) { d = b; + SigBit I = sigmap(d); + if (I != d) + alias_map[I] = d; + unused_bits.erase(d); } - if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) { - SigBit O = sigmap(b); - q = O; + if (is_output && port->attributes.count("\\abc_flop_q")) { + q = b; + SigBit O = sigmap(q); + if (O != q) + alias_map[O] = q; + undriven_bits.erase(O); } } } @@ -281,7 +286,6 @@ struct XAigerWriter abc_box_seen = inst_module->attributes.count("\\abc_box_id"); ff_bits.emplace_back(d, q); - undriven_bits.erase(q); } else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; @@ -507,8 +511,9 @@ struct XAigerWriter } for (auto &f : ff_bits) { - auto bit = f.second; + RTLIL::SigBit bit = f.second; aig_m++, aig_i++; + log_assert(!aig_map.count(bit)); aig_map[bit] = 2*aig_m; } @@ -516,12 +521,9 @@ struct XAigerWriter for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - //auto r = aig_map.insert(std::make_pair(c.first, c.second)); - //if (!r.second) { - // ff_aig_map[std::get<0>(c)] = 2*aig_m; - //} + auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); + if (!r.second) + ff_aig_map[bit] = 2*aig_m; } if (imode && input_bits.empty()) { @@ -597,7 +599,8 @@ struct XAigerWriter for (auto &f : ff_bits) { aig_o++; - aig_outputs.push_back(ff_aig_map.at(f.second)); + RTLIL::SigBit bit = f.second; + aig_outputs.push_back(ff_aig_map.at(bit)); } if (omode && output_bits.empty()) { @@ -778,8 +781,8 @@ struct XAigerWriter write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %d\n", num_outputs); - write_h_buffer(num_outputs); + log_debug("poNum = %zu\n", num_outputs + ff_bits.size()); + write_h_buffer(num_outputs + ff_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -856,7 +859,7 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - if (!ff_bits.empty()) { + /*if (!ff_bits.empty())*/ { std::stringstream r_buffer; auto write_r_buffer = [&r_buffer](int i32) { // TODO: Don't assume we're on little endian @@ -867,6 +870,7 @@ struct XAigerWriter #endif r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); int mergeability_class = 1; for (auto cell : ff_bits) @@ -923,29 +927,6 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); } - - std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; - write_r_buffer(0); - - f << "r"; - buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); } f << stringf("Generated by %s\n", yosys_version_str); -- cgit v1.2.3 From 257f7ff5f63635f0a754f34cf8af93ed06632b5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 3 Jun 2019 12:30:54 -0700 Subject: When creating new holes cell, inherit parameters too --- backends/aiger/xaiger.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 90fea2db1..818caebba 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -796,8 +796,10 @@ struct XAigerWriter RTLIL::Module* box_module = module->design->module(cell->type); int box_inputs = 0, box_outputs = 0; Cell *holes_cell = nullptr; - if (box_module->get_bool_attribute("\\whitebox")) + if (box_module->get_bool_attribute("\\whitebox")) { holes_cell = holes_module->addCell(cell->name, cell->type); + holes_cell->parameters = cell->parameters; + } // NB: Assume box_module->ports are sorted alphabetically // (as RTLIL::Module::fixup_ports() would do) -- cgit v1.2.3 From 1b836c93bbaa3c85d4730b0251aed64cdf207422 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 11:56:58 -0700 Subject: Only toposort builtin and abc types --- backends/aiger/xaiger.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 818caebba..4d45bb650 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -181,14 +181,17 @@ struct XAigerWriter for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); - bool known_type = yosys_celltypes.cell_known(cell->type); + bool builtin_type = yosys_celltypes.cell_known(cell->type); + bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); if (!holes_mode) { toposort.node(cell->name); - for (const auto &conn : cell->connections()) - { + for (const auto &conn : cell->connections()) { + if (!builtin_type && !abc_type) + continue; + if (!cell->type.in("$_NOT_", "$_AND_")) { - if (known_type) { + if (builtin_type) { if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) continue; if (cell->type == "$memrd" && conn.first == "\\DATA") @@ -199,8 +202,8 @@ struct XAigerWriter RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q")) + continue; } } -- cgit v1.2.3 From 7b186740d33972612cfc9f2ebe31258edb0cca2b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 4 Jun 2019 12:01:25 -0700 Subject: Add log_assert to ensure no loops --- backends/aiger/xaiger.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4d45bb650..bf2f9f1bc 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -334,7 +334,21 @@ struct XAigerWriter pool abc_carry_modules; - toposort.sort(); +#if 0 + toposort.analyze_loops = true; +#endif + bool no_loops = toposort.sort(); +#if 0 + unsigned i = 0; + for (auto &it : toposort.loops) { + log(" loop %d", i++); + for (auto cell : it) + log(" %s", log_id(cell)); + log("\n"); + } +#endif + log_assert(no_loops); + for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); -- cgit v1.2.3 From b21d29598a59f0f137a42f00a000b7937dabb402 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:40:51 -0700 Subject: Consistency --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bf2f9f1bc..730f50f5b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -2,7 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf - * Copyright (C) 2019 Eddie Hung + * 2019 Eddie Hung * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 4be417f6e15ee3f3d8da8cd75d8405b90d5b32ba Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 09:53:14 -0700 Subject: Cleanup write_xaiger --- backends/aiger/xaiger.cc | 98 +++--------------------------------------------- 1 file changed, 6 insertions(+), 92 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 730f50f5b..fd0620cac 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -105,7 +105,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -624,14 +624,9 @@ struct XAigerWriter aig_o++; aig_outputs.push_back(0); } - - if (bmode) { - //aig_b++; - aig_outputs.push_back(0); - } } - void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode) + void write_aiger(std::ostream &f, bool ascii_mode, bool omode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -708,73 +703,6 @@ struct XAigerWriter } } - if (symbols_mode) - { - dict> symbols; - - bool output_seen = false; - for (auto wire : module->wires()) - { - //if (wire->name[0] == '$') - // continue; - - SigSpec sig = sigmap(wire); - - for (int i = 0; i < GetSize(wire); i++) - { - RTLIL::SigBit b(wire, i); - if (input_bits.count(b)) { - int a = aig_map.at(sig[i]); - log_assert((a & 1) == 0); - if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); - else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); - } - - if (output_bits.count(b)) { - int o = ordered_outputs.at(b); - output_seen = !miter_mode; - if (GetSize(wire) != 1) - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); - else - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); - } - - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // if (GetSize(wire) != 1) - // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); - // else - // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); - //} - - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; - if (GetSize(wire) != 1) - symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); - else - symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); - } - } - } - - if (omode && !output_seen) - symbols["o0"].push_back("__dummy_o__"); - - symbols.sort(); - - for (auto &sym : symbols) { - f << sym.first; - std::sort(sym.second.begin(), sym.second.end()); - for (auto &s : sym.second) - f << " " << s; - f << std::endl; - } - } - f << "c"; if (!box_list.empty() || !ff_bits.empty()) { @@ -931,8 +859,8 @@ struct XAigerWriter holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/); + XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/, false /* omode */); f << "a"; std::string buffer_str = a_buffer.str(); @@ -1055,9 +983,6 @@ struct XAigerBackend : public Backend { log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); log(" uninitialized FFs.\n"); log("\n"); - log(" -symbols\n"); - log(" include a symbol table in the generated AIGER file\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -1074,12 +999,9 @@ struct XAigerBackend : public Backend { { bool ascii_mode = false; bool zinit_mode = false; - bool miter_mode = false; - bool symbols_mode = false; bool verbose_map = false; bool imode = false; bool omode = false; - bool bmode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -1095,10 +1017,6 @@ struct XAigerBackend : public Backend { zinit_mode = true; continue; } - if (args[argidx] == "-symbols") { - symbols_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -1116,10 +1034,6 @@ struct XAigerBackend : public Backend { omode = true; continue; } - if (args[argidx] == "-B") { - bmode = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1129,8 +1043,8 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode); - writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode); + XAigerWriter writer(top_module, zinit_mode, imode, omode); + writer.write_aiger(*f, ascii_mode, omode); if (!map_filename.empty()) { std::ofstream mapf; -- cgit v1.2.3 From 14e870d4c47e18abf45f82f2d9329d1488e0650c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 10:00:57 -0700 Subject: More write_xaiger cleanup --- backends/aiger/xaiger.cc | 52 +++++++++++------------------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fd0620cac..af9a30135 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -105,7 +105,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -543,10 +543,6 @@ struct XAigerWriter ff_aig_map[bit] = 2*aig_m; } - if (imode && input_bits.empty()) { - aig_m++, aig_i++; - } - //if (zinit_mode) //{ // for (auto it : ff_map) { @@ -620,13 +616,9 @@ struct XAigerWriter aig_outputs.push_back(ff_aig_map.at(bit)); } - if (omode && output_bits.empty()) { - aig_o++; - aig_outputs.push_back(0); - } } - void write_aiger(std::ostream &f, bool ascii_mode, bool omode) + void write_aiger(std::ostream &f, bool ascii_mode) { int aig_obc = aig_o; int aig_obcj = aig_obc; @@ -716,18 +708,15 @@ struct XAigerWriter #endif h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; - int num_outputs = output_bits.size(); - if (omode && num_outputs == 0) - num_outputs = 1; write_h_buffer(1); log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size()); + log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", num_outputs + ff_bits.size()); - write_h_buffer(num_outputs + ff_bits.size()); + log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); + write_h_buffer(output_bits.size() + ff_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -859,8 +848,8 @@ struct XAigerWriter holes_module->design->selection_stack.pop_back(); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, true /* holes_mode */); - writer.write_aiger(a_buffer, false /*ascii_mode*/, false /* omode */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + writer.write_aiger(a_buffer, false /*ascii_mode*/); f << "a"; std::string buffer_str = a_buffer.str(); @@ -879,7 +868,7 @@ struct XAigerWriter f << stringf("Generated by %s\n", yosys_version_str); } - void write_map(std::ostream &f, bool verbose_map, bool omode) + void write_map(std::ostream &f, bool verbose_map) { dict input_lines; dict init_lines; @@ -952,8 +941,6 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); - if (omode && output_bits.empty()) - f << "output " << output_lines.size() << " 0 __dummy_o__\n"; latch_lines.sort(); for (auto &it : latch_lines) @@ -989,19 +976,12 @@ struct XAigerBackend : public Backend { log(" -vmap \n"); log(" like -map, but more verbose\n"); log("\n"); - log(" -I, -O, -B\n"); - log(" If the design contains no input/output/assert then create one\n"); - log(" dummy input/output/bad_state pin to make the tools reading the\n"); - log(" AIGER file happy.\n"); - log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; bool zinit_mode = false; bool verbose_map = false; - bool imode = false; - bool omode = false; std::string map_filename; log_header(design, "Executing XAIGER backend.\n"); @@ -1026,14 +1006,6 @@ struct XAigerBackend : public Backend { verbose_map = true; continue; } - if (args[argidx] == "-I") { - imode = true; - continue; - } - if (args[argidx] == "-O") { - omode = true; - continue; - } break; } extra_args(f, filename, args, argidx); @@ -1043,15 +1015,15 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode, imode, omode); - writer.write_aiger(*f, ascii_mode, omode); + XAigerWriter writer(top_module, zinit_mode); + writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { std::ofstream mapf; mapf.open(map_filename.c_str(), std::ofstream::trunc); if (mapf.fail()) log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno)); - writer.write_map(mapf, verbose_map, omode); + writer.write_map(mapf, verbose_map); } } } XAigerBackend; -- cgit v1.2.3 From 2e7b3eee400a4d845398be8e15ca023672f05270 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:43:43 -0700 Subject: Add a couple more tests --- backends/aiger/xaiger.cc | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index af9a30135..3dbff5496 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,14 +142,6 @@ struct XAigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - if (bit.wire == nullptr) { - if (wire->port_output) { - aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); - } - continue; - } - undriven_bits.insert(bit); unused_bits.insert(bit); @@ -160,8 +152,10 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) + if (bit != wirebit) { alias_map[wirebit] = bit; + undriven_bits.insert(wirebit); + } output_bits.insert(wirebit); } } @@ -169,7 +163,6 @@ struct XAigerWriter for (auto bit : input_bits) undriven_bits.erase(sigmap(bit)); - for (auto bit : output_bits) if (!bit.wire->port_input) unused_bits.erase(bit); @@ -178,8 +171,7 @@ struct XAigerWriter TopoSort toposort; bool abc_box_seen = false; - for (auto cell : module->cells()) - { + for (auto cell : module->cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); bool builtin_type = yosys_celltypes.cell_known(cell->type); bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); @@ -296,14 +288,15 @@ struct XAigerWriter else { for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - for (auto b : c.second.bits()) { - Wire *w = b.wire; - if (!w) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - if (is_input) { - if (!w->port_input) { + auto is_input = cell->input(c.first); + auto is_output = cell->output(c.first); + log_assert(is_input || is_output); + + if (is_input) { + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; + if (!w->port_output) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; @@ -311,7 +304,11 @@ struct XAigerWriter unused_bits.erase(b); } } - if (is_output) { + } + if (is_output) { + for (auto b : c.second.bits()) { + Wire *w = b.wire; + if (!w) continue; input_bits.insert(b); SigBit O = sigmap(b); if (O != b) -- cgit v1.2.3 From fb2758aade4561d8c379e8b9d97ee871b1bbfde3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:44:30 -0700 Subject: write_xaiger to preserve POs even if driven by constant --- backends/aiger/xaiger.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3dbff5496..3a4b353e2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -142,8 +142,10 @@ struct XAigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - undriven_bits.insert(bit); - unused_bits.insert(bit); + if (bit.wire) { + undriven_bits.insert(bit); + unused_bits.insert(bit); + } if (wire->port_input || keep) { if (bit != wirebit) @@ -154,7 +156,8 @@ struct XAigerWriter if (wire->port_output || keep) { if (bit != wirebit) { alias_map[wirebit] = bit; - undriven_bits.insert(wirebit); + if (!bit.wire) + undriven_bits.insert(wirebit); } output_bits.insert(wirebit); } @@ -480,10 +483,6 @@ struct XAigerWriter } } - // Erase all POs that are undriven - if (!holes_mode) - for (auto bit : undriven_bits) - output_bits.erase(bit); for (auto bit : unused_bits) undriven_bits.erase(bit); -- cgit v1.2.3 From 8374eb1cb4dcb99b2125543a3d5f9f6adbdd6b7d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Jun 2019 15:55:02 -0700 Subject: Remove unnecessary undriven_bits.insert --- backends/aiger/xaiger.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3a4b353e2..fcf9a7bf1 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -154,11 +154,8 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) { + if (bit != wirebit) alias_map[wirebit] = bit; - if (!bit.wire) - undriven_bits.insert(wirebit); - } output_bits.insert(wirebit); } } -- cgit v1.2.3 From 95665730540c0fd7c76690f28d0fd6b5f13f2223 Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 14 Jun 2019 12:02:12 +0100 Subject: ecp5: Add abc9 option Signed-off-by: David Shah --- backends/aiger/xaiger.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fcf9a7bf1..5fa20c9c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -833,8 +833,7 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); // TODO: Should techmap all lib_whitebox-es once - //Pass::call(holes_module->design, "techmap"); - + Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); Pass::call(holes_module->design, "clean -purge"); -- cgit v1.2.3 From 1948e7c846ea318d003148974945d917701a4452 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:13:17 -0700 Subject: Cleanup/optimise toposort in write_xaiger --- backends/aiger/xaiger.cc | 101 ++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 54 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index fcf9a7bf1..5a26548b8 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -167,51 +167,12 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - dict> bit_drivers, bit_users; - TopoSort toposort; + SigMap topomap; + topomap.database = sigmap.database; + bool abc_box_seen = false; for (auto cell : module->cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - bool builtin_type = yosys_celltypes.cell_known(cell->type); - bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id"); - - if (!holes_mode) { - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (!builtin_type && !abc_type) - continue; - - if (!cell->type.in("$_NOT_", "$_AND_")) { - if (builtin_type) { - if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA")) - continue; - if (cell->type == "$memrd" && conn.first == "\\DATA") - continue; - } - - if (inst_module) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - - if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q")) - continue; - } - } - - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : sigmap(conn.second)) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -219,6 +180,8 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; + if (!holes_mode) + topomap.add(Y, A); continue; } @@ -241,6 +204,10 @@ struct XAigerWriter unused_bits.erase(B); undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); + if (!holes_mode) { + topomap.add(Y, A); + topomap.add(Y, B); + } continue; } @@ -252,6 +219,7 @@ struct XAigerWriter // continue; //} + RTLIL::Module* inst_module = module->design->module(cell->type); bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; if (inst_flop) { SigBit d, q; @@ -322,20 +290,46 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc_box_seen) { + if (abc_box_seen && !holes_mode) { + TopoSort toposort; + dict> bit_drivers, bit_users; + + for (auto cell : module->cells()) { + RTLIL::Module* inst_module = module->design->module(cell->type); + if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) + continue; + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : topomap(conn.second)) + if (bit.wire) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) { + RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); + log_assert(inst_module_port); + if (inst_module_port->attributes.count("\\abc_flop_q")) + continue; + for (auto bit : topomap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } + } + for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); - pool abc_carry_modules; - -#if 0 +#if 1 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 0 +#if 1 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -346,13 +340,14 @@ struct XAigerWriter #endif log_assert(no_loops); + pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - if (!box_module || !box_module->attributes.count("\\abc_box_id")) - continue; + log_assert(box_module); + log_assert(box_module->attributes.count("\\abc_box_id")); - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { + if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -448,8 +443,6 @@ struct XAigerWriter } box_list.emplace_back(cell); } - - // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { -- cgit v1.2.3 From 1656c44373dbf7375c068d5626e38a76b5a83c4d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:29:27 -0700 Subject: Cleanup --- backends/aiger/xaiger.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bba0ec713..daefd3a73 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -20,7 +20,6 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "kernel/celltypes.h" #include "kernel/utils.h" USING_YOSYS_NAMESPACE -- cgit v1.2.3 From ee428f73abdbbde95601e583db186d86a8fa6b91 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 10:37:52 -0700 Subject: Remove WIP ABC9 flop support --- backends/aiger/xaiger.cc | 66 ++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index daefd3a73..1e70f3230 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -219,37 +219,37 @@ struct XAigerWriter //} RTLIL::Module* inst_module = module->design->module(cell->type); - bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - if (inst_flop) { - SigBit d, q; - for (const auto &c : cell->connections()) { - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); - log_assert(is_input || is_output); - RTLIL::Wire* port = inst_module->wire(c.first); - for (auto b : c.second.bits()) { - if (is_input && port->attributes.count("\\abc_flop_d")) { - d = b; - SigBit I = sigmap(d); - if (I != d) - alias_map[I] = d; - unused_bits.erase(d); - } - if (is_output && port->attributes.count("\\abc_flop_q")) { - q = b; - SigBit O = sigmap(q); - if (O != q) - alias_map[O] = q; - undriven_bits.erase(O); - } - } - } - if (!abc_box_seen) - abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - - ff_bits.emplace_back(d, q); - } - else if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; + //if (inst_flop) { + // SigBit d, q; + // for (const auto &c : cell->connections()) { + // auto is_input = cell->input(c.first); + // auto is_output = cell->output(c.first); + // log_assert(is_input || is_output); + // RTLIL::Wire* port = inst_module->wire(c.first); + // for (auto b : c.second.bits()) { + // if (is_input && port->attributes.count("\\abc_flop_d")) { + // d = b; + // SigBit I = sigmap(d); + // if (I != d) + // alias_map[I] = d; + // unused_bits.erase(d); + // } + // if (is_output && port->attributes.count("\\abc_flop_q")) { + // q = b; + // SigBit O = sigmap(q); + // if (O != q) + // alias_map[O] = q; + // undriven_bits.erase(O); + // } + // } + // } + // if (!abc_box_seen) + // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); + + // ff_bits.emplace_back(d, q); + //} + /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; } else { @@ -310,8 +310,8 @@ struct XAigerWriter if (cell->output(conn.first)) { RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); log_assert(inst_module_port); - if (inst_module_port->attributes.count("\\abc_flop_q")) - continue; + //if (inst_module_port->attributes.count("\\abc_flop_q")) + // continue; for (auto bit : topomap(conn.second)) bit_drivers[bit].insert(cell->name); } -- cgit v1.2.3 From 97d265637505a239e3d328a3ee7e26c6fd5d6744 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:00:02 -0700 Subject: Resolve comments from @daveshah1 --- backends/aiger/xaiger.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1e70f3230..42a2233e4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -683,16 +683,18 @@ struct XAigerWriter f << "c"; if (!box_list.empty() || !ff_bits.empty()) { - std::stringstream h_buffer; - auto write_h_buffer = [&h_buffer](int i32) { + auto write_buffer = [](std::stringstream &buffer, int i32) { // TODO: Don't assume we're on little endian #ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); + int32_t i32_be = _byteswap_ulong(i32); #else - int i32_be = __builtin_bswap32(i32); + int32_t i32_be = __builtin_bswap32(i32); #endif - h_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); + buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; + + std::stringstream h_buffer; + auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); @@ -782,15 +784,7 @@ struct XAigerWriter /*if (!ff_bits.empty())*/ { std::stringstream r_buffer; - auto write_r_buffer = [&r_buffer](int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int i32_be = _byteswap_ulong(i32); -#else - int i32_be = __builtin_bswap32(i32); -#endif - r_buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); - }; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); int mergeability_class = 1; -- cgit v1.2.3 From a48b5bfaa5c55bfe4e5ff859b453ee00a1dd68c6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:25:06 -0700 Subject: Further cleanup based on @daveshah1 --- backends/aiger/xaiger.cc | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42a2233e4..7e22dca7f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -25,6 +25,20 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +inline int32_t to_big_endian(int32_t i32) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#ifdef _WIN32 + return _byteswap_ulong(i32); +#else + return __builtin_bswap32(i32); +#endif +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return i32; +#else +#error "Unknown endianness" +#endif +} + void aiger_encode(std::ostream &f, int x) { log_assert(x >= 0); @@ -684,12 +698,7 @@ struct XAigerWriter if (!box_list.empty() || !ff_bits.empty()) { auto write_buffer = [](std::stringstream &buffer, int i32) { - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int32_t i32_be = _byteswap_ulong(i32); -#else - int32_t i32_be = __builtin_bswap32(i32); -#endif + int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); }; @@ -773,12 +782,7 @@ struct XAigerWriter f << "h"; std::string buffer_str = h_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); @@ -787,18 +791,13 @@ struct XAigerWriter auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); log_debug("flopNum = %zu\n", ff_bits.size()); write_r_buffer(ff_bits.size()); - int mergeability_class = 1; - for (auto cell : ff_bits) - write_r_buffer(mergeability_class++); + //int mergeability_class = 1; + //for (auto cell : ff_bits) + // write_r_buffer(mergeability_class++); f << "r"; std::string buffer_str = r_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); } @@ -831,12 +830,7 @@ struct XAigerWriter f << "a"; std::string buffer_str = a_buffer.str(); - // TODO: Don't assume we're on little endian -#ifdef _WIN32 - int buffer_size_be = _byteswap_ulong(buffer_str.size()); -#else - int buffer_size_be = __builtin_bswap32(buffer_str.size()); -#endif + int32_t buffer_size_be = to_big_endian(buffer_str.size()); f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); -- cgit v1.2.3 From 7876b5b8bef1ff8460e48232e68bb5136f04e7b5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 12:40:51 -0700 Subject: Cover __APPLE__ too for little to big endian --- backends/aiger/xaiger.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7e22dca7f..7cb311736 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -18,6 +18,15 @@ * */ +// https://stackoverflow.com/a/46137633 +#ifdef _MSC_VER +#include +#define __builtin_bswap32 _byteswap_ulong +#elif defined(__APPLE__) +#include +#define __builtin_bswap32 OSSwapInt32 +#endif + #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/utils.h" @@ -27,11 +36,7 @@ PRIVATE_NAMESPACE_BEGIN inline int32_t to_big_endian(int32_t i32) { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#ifdef _WIN32 - return _byteswap_ulong(i32); -#else return __builtin_bswap32(i32); -#endif #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return i32; #else -- cgit v1.2.3 From 2d85725604271c658382e8fdd8ff28275fb94b03 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:07:56 -0700 Subject: Get rid of compiler warnings --- backends/aiger/xaiger.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7cb311736..3f7edc627 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -190,7 +190,7 @@ struct XAigerWriter bool abc_box_seen = false; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { if (cell->type == "$_NOT_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -312,7 +312,7 @@ struct XAigerWriter TopoSort toposort; dict> bit_drivers, bit_users; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { RTLIL::Module* inst_module = module->design->module(cell->type); if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) continue; -- cgit v1.2.3 From 0fa6a441f1a222b039975cf622ddca479a65cf24 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:08:38 -0700 Subject: Check that whiteboxes are synthesisable --- backends/aiger/xaiger.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 3f7edc627..bc722e492 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -722,7 +722,7 @@ struct XAigerWriter write_h_buffer(box_list.size()); RTLIL::Module *holes_module = nullptr; - holes_module = module->design->addModule("\\__holes__"); + holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); int port_id = 1; @@ -822,17 +822,21 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap all lib_whitebox-es once + // TODO: Should techmap/AIG all lib_whitebox-es once Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); - Pass::call(holes_module->design, "clean -purge"); + for (auto cell : holes_module->cells()) + if (!cell->type.in("$_NOT_", "$_AND_")) + log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - holes_module->design->selection_stack.pop_back(); + Pass::call(holes_module->design, "clean -purge"); std::stringstream a_buffer; XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); + holes_module->design->selection_stack.pop_back(); + f << "a"; std::string buffer_str = a_buffer.str(); int32_t buffer_size_be = to_big_endian(buffer_str.size()); -- cgit v1.2.3 From 746f70a9ce163f921b0e55b21042c59769bbcba9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:10:46 -0700 Subject: Update comment --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index bc722e492..0c2ae62e6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -822,7 +822,8 @@ struct XAigerWriter Pass::call(holes_module->design, "flatten -wb"); - // TODO: Should techmap/AIG all lib_whitebox-es once + // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, + // instead of per write_xaiger call Pass::call(holes_module->design, "techmap"); Pass::call(holes_module->design, "aigmap"); for (auto cell : holes_module->cells()) -- cgit v1.2.3 From 9b55e69755a00a46c97104f344c0ee7065a8f13c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:28:47 -0700 Subject: Revert "Cleanup/optimise toposort in write_xaiger" This reverts commit 1948e7c846ea318d003148974945d917701a4452. Restores old toposort with optimisations --- backends/aiger/xaiger.cc | 84 +++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 44 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 0c2ae62e6..1d502a748 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,9 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); - SigMap topomap; - topomap.database = sigmap.database; - + dict> bit_drivers, bit_users; + TopoSort toposort; bool abc_box_seen = false; for (auto cell : module->selected_cells()) { @@ -198,8 +197,11 @@ struct XAigerWriter unused_bits.erase(A); undriven_bits.erase(Y); not_map[Y] = A; - if (!holes_mode) - topomap.add(Y, A); + if (!holes_mode) { + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_drivers[Y].insert(cell->name); + } continue; } @@ -223,12 +225,16 @@ struct XAigerWriter undriven_bits.erase(Y); and_map[Y] = make_pair(A, B); if (!holes_mode) { - topomap.add(Y, A); - topomap.add(Y, B); + toposort.node(cell->name); + bit_users[A].insert(cell->name); + bit_users[B].insert(cell->name); + bit_drivers[Y].insert(cell->name); } continue; } + log_assert(!holes_mode); + //if (cell->type == "$initstate") //{ // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); @@ -265,11 +271,26 @@ struct XAigerWriter // } // if (!abc_box_seen) // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); //} /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; + + if (!holes_mode) { + toposort.node(cell->name); + for (const auto &conn : cell->connections()) { + if (cell->input(conn.first)) { + // Ignore inout for the sake of topographical ordering + if (cell->output(conn.first)) continue; + for (auto bit : sigmap(conn.second)) + bit_users[bit].insert(cell->name); + } + + if (cell->output(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_drivers[bit].insert(cell->name); + } + } } else { for (const auto &c : cell->connections()) { @@ -309,45 +330,19 @@ struct XAigerWriter } if (abc_box_seen && !holes_mode) { - TopoSort toposort; - dict> bit_drivers, bit_users; - - for (auto cell : module->selected_cells()) { - RTLIL::Module* inst_module = module->design->module(cell->type); - if (!inst_module || !inst_module->attributes.count("\\abc_box_id")) - continue; - toposort.node(cell->name); - for (const auto &conn : cell->connections()) { - if (cell->input(conn.first)) { - // Ignore inout for the sake of topographical ordering - if (cell->output(conn.first)) continue; - for (auto bit : topomap(conn.second)) - if (bit.wire) - bit_users[bit].insert(cell->name); - } - - if (cell->output(conn.first)) { - RTLIL::Wire* inst_module_port = inst_module->wire(conn.first); - log_assert(inst_module_port); - //if (inst_module_port->attributes.count("\\abc_flop_q")) - // continue; - for (auto bit : topomap(conn.second)) - bit_drivers[bit].insert(cell->name); - } - } - } - for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); + + pool abc_carry_modules; -#if 1 +#if 0 toposort.analyze_loops = true; #endif bool no_loops = toposort.sort(); -#if 1 +#if 0 unsigned i = 0; for (auto &it : toposort.loops) { log(" loop %d", i++); @@ -358,14 +353,13 @@ struct XAigerWriter #endif log_assert(no_loops); - pool abc_carry_modules; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); RTLIL::Module* box_module = module->design->module(cell->type); - log_assert(box_module); - log_assert(box_module->attributes.count("\\abc_box_id")); + if (!box_module || !box_module->attributes.count("\\abc_box_id")) + continue; - if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) { + if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; RTLIL::Wire* last_in = nullptr, *last_out = nullptr; for (const auto &port_name : box_module->ports) { @@ -461,6 +455,8 @@ struct XAigerWriter } box_list.emplace_back(cell); } + + // TODO: Free memory from toposort, bit_drivers, bit_users } for (auto bit : input_bits) { -- cgit v1.2.3 From 46e69ee934a6a954b73bb7a5669b6ee6d3047247 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:31:18 -0700 Subject: Remove redundant condition --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1d502a748..4d8bb7f00 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -329,7 +329,7 @@ struct XAigerWriter //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); } - if (abc_box_seen && !holes_mode) { + if (abc_box_seen) { for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) -- cgit v1.2.3 From 7ff8330d1e159173f9ed3494b85b83cb97208ab5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Jun 2019 13:34:40 -0700 Subject: Leave breadcrumb behind --- backends/aiger/xaiger.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 4d8bb7f00..df970e341 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -185,6 +185,8 @@ struct XAigerWriter if (!bit.wire->port_input) unused_bits.erase(bit); + // TODO: Speed up toposort -- ultimately we care about + // box ordering, but not individual AIG cells dict> bit_drivers, bit_users; TopoSort toposort; bool abc_box_seen = false; -- cgit v1.2.3 From fb90d8c18c9e8bfad1356e3b4387d77eeb2e9377 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 16 Jun 2019 09:34:26 -0700 Subject: Cleanup --- backends/aiger/xaiger.cc | 253 +++++------------------------------------------ 1 file changed, 25 insertions(+), 228 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index df970e341..1485e2b0c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -59,31 +59,23 @@ void aiger_encode(std::ostream &f, int x) struct XAigerWriter { Module *module; - bool zinit_mode; SigMap sigmap; - dict init_map; pool input_bits, output_bits; - dict not_map, ff_map, alias_map; + dict not_map, alias_map; dict> and_map; - //pool initstate_bits; vector> ci_bits; vector> co_bits; - vector> ff_bits; vector> aig_gates; - vector aig_latchin, aig_latchinit, aig_outputs; + vector aig_outputs; int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0; dict aig_map; dict ordered_outputs; - dict ordered_latches; vector box_list; - //dict init_inputs; - //int initstate_ff = 0; - int mkgate(int a0, int a1) { aig_m++, aig_a++; @@ -97,10 +89,6 @@ struct XAigerWriter { aig_map[bit] = -1; - //if (initstate_bits.count(bit)) { - // log_assert(initstate_ff > 0); - // aig_map[bit] = initstate_ff; - //} else if (not_map.count(bit)) { int a = bit2aig(not_map.at(bit)) ^ 1; aig_map[bit] = a; @@ -123,7 +111,7 @@ struct XAigerWriter return aig_map.at(bit); } - XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module) + XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -145,14 +133,6 @@ struct XAigerWriter for (auto wire : module->wires()) { - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++) - if (initval[i] == State::S0 || initval[i] == State::S1) - init_map[initsig[i]] = initval[i] == State::S1; - } - bool keep = wire->attributes.count("\\keep"); for (int i = 0; i < GetSize(wire); i++) @@ -207,16 +187,6 @@ struct XAigerWriter continue; } - //if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_")) - //{ - // SigBit D = sigmap(cell->getPort("\\D").as_bit()); - // SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); - // unused_bits.erase(D); - // undriven_bits.erase(Q); - // ff_map[Q] = D; - // continue; - //} - if (cell->type == "$_AND_") { SigBit A = sigmap(cell->getPort("\\A").as_bit()); @@ -237,45 +207,8 @@ struct XAigerWriter log_assert(!holes_mode); - //if (cell->type == "$initstate") - //{ - // SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); - // undriven_bits.erase(Y); - // initstate_bits.insert(Y); - // continue; - //} - RTLIL::Module* inst_module = module->design->module(cell->type); - //bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false; - //if (inst_flop) { - // SigBit d, q; - // for (const auto &c : cell->connections()) { - // auto is_input = cell->input(c.first); - // auto is_output = cell->output(c.first); - // log_assert(is_input || is_output); - // RTLIL::Wire* port = inst_module->wire(c.first); - // for (auto b : c.second.bits()) { - // if (is_input && port->attributes.count("\\abc_flop_d")) { - // d = b; - // SigBit I = sigmap(d); - // if (I != d) - // alias_map[I] = d; - // unused_bits.erase(d); - // } - // if (is_output && port->attributes.count("\\abc_flop_q")) { - // q = b; - // SigBit O = sigmap(q); - // if (O != q) - // alias_map[O] = q; - // undriven_bits.erase(O); - // } - // } - // } - // if (!abc_box_seen) - // abc_box_seen = inst_module->attributes.count("\\abc_box_id"); - // ff_bits.emplace_back(d, q); - //} - /*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; if (!holes_mode) { @@ -501,7 +434,6 @@ struct XAigerWriter log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); } - init_map.sort(); if (holes_mode) { struct sort_by_port_id { bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { @@ -517,7 +449,6 @@ struct XAigerWriter } not_map.sort(); - ff_map.sort(); and_map.sort(); aig_map[State::S0] = 0; @@ -529,78 +460,12 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (auto &f : ff_bits) { - RTLIL::SigBit bit = f.second; - aig_m++, aig_i++; - log_assert(!aig_map.count(bit)); - aig_map[bit] = 2*aig_m; - } - - dict ff_aig_map; for (auto &c : ci_bits) { RTLIL::SigBit bit = std::get<0>(c); aig_m++, aig_i++; - auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); - if (!r.second) - ff_aig_map[bit] = 2*aig_m; - } - - //if (zinit_mode) - //{ - // for (auto it : ff_map) { - // if (init_map.count(it.first)) - // continue; - // aig_m++, aig_i++; - // init_inputs[it.first] = 2*aig_m; - // } - //} - - for (auto it : ff_map) { - aig_m++, aig_l++; - aig_map[it.first] = 2*aig_m; - ordered_latches[it.first] = aig_l-1; - if (init_map.count(it.first) == 0) - aig_latchinit.push_back(2); - else - aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0); - } - - //if (!initstate_bits.empty() || !init_inputs.empty()) { - // aig_m++, aig_l++; - // initstate_ff = 2*aig_m+1; - // aig_latchinit.push_back(0); - //} - - //if (zinit_mode) - //{ - // for (auto it : ff_map) - // { - // int l = ordered_latches[it.first]; - - // if (aig_latchinit.at(l) == 1) - // aig_map[it.first] ^= 1; - - // if (aig_latchinit.at(l) == 2) - // { - // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1); - // int gated_initin = mkgate(init_inputs[it.first], initstate_ff); - // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1; - // } - // } - //} - - for (auto it : ff_map) { - int a = bit2aig(it.second); - int l = ordered_latches[it.first]; - if (zinit_mode && aig_latchinit.at(l) == 1) - aig_latchin.push_back(a ^ 1); - else - aig_latchin.push_back(a); + aig_map[bit] = 2*aig_m; } - //if (!initstate_bits.empty() || !init_inputs.empty()) - // aig_latchin.push_back(1); - for (auto &c : co_bits) { RTLIL::SigBit bit = std::get<0>(c); std::get<4>(c) = ordered_outputs[bit] = aig_o++; @@ -611,13 +476,6 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } - - for (auto &f : ff_bits) { - aig_o++; - RTLIL::SigBit bit = f.second; - aig_outputs.push_back(ff_aig_map.at(bit)); - } - } void write_aiger(std::ostream &f, bool ascii_mode) @@ -627,8 +485,6 @@ struct XAigerWriter int aig_obcjf = aig_obcj; log_assert(aig_m == aig_i + aig_l + aig_a); - log_assert(aig_l == GetSize(aig_latchin)); - log_assert(aig_l == GetSize(aig_latchinit)); log_assert(aig_obcjf == GetSize(aig_outputs)); f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a); @@ -639,15 +495,6 @@ struct XAigerWriter for (int i = 0; i < aig_i; i++) f << stringf("%d\n", 2*i+2); - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2); - } - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -665,15 +512,6 @@ struct XAigerWriter } else { - for (int i = 0; i < aig_l; i++) { - if (zinit_mode || aig_latchinit.at(i) == 0) - f << stringf("%d\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 1) - f << stringf("%d 1\n", aig_latchin.at(i)); - else if (aig_latchinit.at(i) == 2) - f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2); - } - for (int i = 0; i < aig_obc; i++) f << stringf("%d\n", aig_outputs.at(i)); @@ -699,7 +537,7 @@ struct XAigerWriter f << "c"; - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty()) { auto write_buffer = [](std::stringstream &buffer, int i32) { int32_t i32_be = to_big_endian(i32); buffer.write(reinterpret_cast(&i32_be), sizeof(i32_be)); @@ -708,14 +546,14 @@ struct XAigerWriter std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); - write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size()); - log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); - write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size()); + log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); + write_h_buffer(input_bits.size() + ci_bits.size()); + log_debug("coNum = %zu\n", output_bits.size() + co_bits.size()); + write_h_buffer(output_bits.size() + co_bits.size()); + log_debug("piNum = %zu\n", input_bits.size()); + write_h_buffer(input_bits.size()); + log_debug("poNum = %zu\n", output_bits.size()); + write_h_buffer(output_bits.size()); log_debug("boxNum = %zu\n", box_list.size()); write_h_buffer(box_list.size()); @@ -789,21 +627,15 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); - /*if (!ff_bits.empty())*/ { - std::stringstream r_buffer; - auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %zu\n", ff_bits.size()); - write_r_buffer(ff_bits.size()); - //int mergeability_class = 1; - //for (auto cell : ff_bits) - // write_r_buffer(mergeability_class++); - - f << "r"; - std::string buffer_str = r_buffer.str(); - int32_t buffer_size_be = to_big_endian(buffer_str.size()); - f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); - f.write(buffer_str.data(), buffer_str.size()); - } + std::stringstream r_buffer; + auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); + write_r_buffer(0); + + f << "r"; + buffer_str = r_buffer.str(); + buffer_size_be = to_big_endian(buffer_str.size()); + f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); + f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { // NB: fixup_ports() will sort ports by name @@ -831,7 +663,7 @@ struct XAigerWriter Pass::call(holes_module->design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); + XAigerWriter writer(holes_module, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); holes_module->design->selection_stack.pop_back(); @@ -851,9 +683,7 @@ struct XAigerWriter void write_map(std::ostream &f, bool verbose_map) { dict input_lines; - dict init_lines; dict output_lines; - dict latch_lines; dict wire_lines; for (auto wire : module->wires()) @@ -878,22 +708,6 @@ struct XAigerWriter continue; } - //if (init_inputs.count(sig[i])) { - // int a = init_inputs.at(sig[i]); - // log_assert((a & 1) == 0); - // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire)); - // continue; - //} - - if (ordered_latches.count(sig[i])) { - int l = ordered_latches.at(sig[i]); - if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire)); - else - latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire)); - continue; - } - if (verbose_map) { if (aig_map.count(sig[i]) == 0) continue; @@ -909,10 +723,6 @@ struct XAigerWriter f << it.second; log_assert(input_lines.size() == input_bits.size()); - init_lines.sort(); - for (auto &it : init_lines) - f << it.second; - int box_count = 0; for (auto cell : box_list) f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); @@ -922,10 +732,6 @@ struct XAigerWriter f << it.second; log_assert(output_lines.size() == output_bits.size()); - latch_lines.sort(); - for (auto &it : latch_lines) - f << it.second; - wire_lines.sort(); for (auto &it : wire_lines) f << it.second; @@ -946,10 +752,6 @@ struct XAigerBackend : public Backend { log(" -ascii\n"); log(" write ASCII version of AIGER format\n"); log("\n"); - log(" -zinit\n"); - log(" convert FFs to zero-initialized FFs, adding additional inputs for\n"); - log(" uninitialized FFs.\n"); - log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -960,7 +762,6 @@ struct XAigerBackend : public Backend { void execute(std::ostream *&f, std::string filename, std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool ascii_mode = false; - bool zinit_mode = false; bool verbose_map = false; std::string map_filename; @@ -973,10 +774,6 @@ struct XAigerBackend : public Backend { ascii_mode = true; continue; } - if (args[argidx] == "-zinit") { - zinit_mode = true; - continue; - } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -995,7 +792,7 @@ struct XAigerBackend : public Backend { if (top_module == nullptr) log_error("Can't find top module in current design!\n"); - XAigerWriter writer(top_module, zinit_mode); + XAigerWriter writer(top_module); writer.write_aiger(*f, ascii_mode); if (!map_filename.empty()) { -- cgit v1.2.3 From f2d541962e92fedce0fbb34d4cf5c1985c7cda40 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:21:57 -0700 Subject: write_xaiger to skip POs driven by 1'bx --- backends/aiger/xaiger.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 1485e2b0c..12b23cfe9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -152,9 +152,13 @@ struct XAigerWriter } if (wire->port_output || keep) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); + if (bit != RTLIL::Sx) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + else + log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit)); } } } -- cgit v1.2.3 From 4e5836a5fb009751a6f3bd7ec3eba20e223861f1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 10:47:20 -0700 Subject: Handle COs driven by 1'bx --- backends/aiger/xaiger.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 12b23cfe9..42f54209b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -355,10 +355,16 @@ struct XAigerWriter } int offset = 0; - for (const auto &b : rhs.bits()) { + for (auto b : rhs.bits()) { SigBit I = sigmap(b); - if (I != b) - alias_map[b] = I; + if (b == RTLIL::Sx) + b = RTLIL::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = RTLIL::S0; + else + alias_map[b] = I; + } co_bits.emplace_back(b, cell, port_name, offset++, 0); unused_bits.erase(b); } -- cgit v1.2.3 From 9faeba7a66c34d57bcae6ad83580e640ee5907e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:27:00 -0700 Subject: Fix broken abc9.v test due to inout being 1'bx --- backends/aiger/xaiger.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 42f54209b..f0a9ccdb9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -75,6 +75,7 @@ struct XAigerWriter dict ordered_outputs; vector box_list; + bool omode = false; int mkgate(int a0, int a1) { @@ -409,9 +410,9 @@ struct XAigerWriter // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(input_bits.count(bit) && output_bits.count(bit)); + log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) @@ -486,6 +487,12 @@ struct XAigerWriter ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } + + if (output_bits.empty()) { + aig_o++; + aig_outputs.push_back(0); + omode = true; + } } void write_aiger(std::ostream &f, bool ascii_mode) @@ -741,6 +748,8 @@ struct XAigerWriter for (auto &it : output_lines) f << it.second; log_assert(output_lines.size() == output_bits.size()); + if (omode && output_bits.empty()) + f << "output " << output_lines.size() << " 0 $__dummy__\n"; wire_lines.sort(); for (auto &it : wire_lines) -- cgit v1.2.3 From ad36eb24c05b578ec8610c9f199280aacefebe54 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:31:22 -0700 Subject: Fix different abc9 test --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index f0a9ccdb9..55a95d835 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -406,13 +406,14 @@ struct XAigerWriter } for (auto bit : input_bits) { + if (!output_bits.count(bit)) + continue; RTLIL::Wire *wire = bit.wire; // If encountering an inout port, or a keep-ed wire, then create a new wire // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers - if ((wire->port_input && wire->port_output && output_bits.count(bit) && !undriven_bits.count(bit)) + if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) || wire->attributes.count("\\keep")) { - log_assert(output_bits.count(bit)); RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) -- cgit v1.2.3 From 8e56cfb6bbaa4e61b201c123b04a4eb4ca3403cf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 19:40:17 -0700 Subject: write_xaiger to flatten 1'bx/1'bz to 1'b0 again --- backends/aiger/xaiger.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 55a95d835..82f0f24b2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -104,8 +104,10 @@ struct XAigerWriter aig_map[bit] = bit2aig(alias_map.at(bit)); } - if (bit == State::Sx || bit == State::Sz) - log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + aig_map[bit] = 0; + } } log_assert(aig_map.at(bit) >= 0); -- cgit v1.2.3 From 32f8014e121cd3338d6786269455c8b3fe9f1631 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 21:55:08 -0700 Subject: Fix gcc error, due to dict invalidation during recursion --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 82f0f24b2..32c3f9045 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -101,12 +101,13 @@ struct XAigerWriter aig_map[bit] = mkgate(a0, a1); } else if (alias_map.count(bit)) { - aig_map[bit] = bit2aig(alias_map.at(bit)); + int a = bit2aig(alias_map.at(bit)); + aig_map[bit] = a; } if (bit == State::Sx || bit == State::Sz) { log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = 0; + aig_map[bit] = aig_map.at(State::S0); } } -- cgit v1.2.3 From e21f01d9380607ba0fb10466273d2dfc3d806282 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Jun 2019 22:09:13 -0700 Subject: Refactor bit2aig for less lookups --- backends/aiger/xaiger.cc | 51 +++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 32c3f9045..48e902666 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,33 +86,36 @@ struct XAigerWriter int bit2aig(SigBit bit) { - if (aig_map.count(bit) == 0) - { - aig_map[bit] = -1; - - if (not_map.count(bit)) { - int a = bit2aig(not_map.at(bit)) ^ 1; - aig_map[bit] = a; - } else - if (and_map.count(bit)) { - auto args = and_map.at(bit); - int a0 = bit2aig(args.first); - int a1 = bit2aig(args.second); - aig_map[bit] = mkgate(a0, a1); - } else - if (alias_map.count(bit)) { - int a = bit2aig(alias_map.at(bit)); - aig_map[bit] = a; - } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + auto it = aig_map.find(bit); + if (it != aig_map.end()) { + log_assert(it->second >= 0); + return it->second; + } - if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); - aig_map[bit] = aig_map.at(State::S0); - } + int a = -1; + if (not_map.count(bit)) { + a = 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); + a = mkgate(a0, a1); + } else + if (alias_map.count(bit)) { + a = bit2aig(alias_map.at(bit)); + } + + if (bit == State::Sx || bit == State::Sz) { + log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + a = aig_map.at(State::S0); } - log_assert(aig_map.at(bit) >= 0); - return aig_map.at(bit); + log_assert(a >= 0); + aig_map[bit] = a; + return a; } XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) -- cgit v1.2.3 From 70c93ea0c4ce023d61553df11198aa0b7e518455 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:43:20 -0700 Subject: Move comment --- backends/aiger/xaiger.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 48e902666..aa10aa55e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -86,14 +86,15 @@ struct XAigerWriter int bit2aig(SigBit bit) { - // NB: Cannot use iterator returned from aig_map.insert() - // since this function is called recursively auto it = aig_map.find(bit); if (it != aig_map.end()) { log_assert(it->second >= 0); return it->second; } + // NB: Cannot use iterator returned from aig_map.insert() + // since this function is called recursively + int a = -1; if (not_map.count(bit)) { a = bit2aig(not_map.at(bit)) ^ 1; -- cgit v1.2.3 From bd7ec673dd5b542031698074e1043dcc32af2168 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:46:55 -0700 Subject: No point logging constant bit --- backends/aiger/xaiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index aa10aa55e..6718e4f2c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -110,7 +110,7 @@ struct XAigerWriter } if (bit == State::Sx || bit == State::Sz) { - log_debug("Bit '%s' contains 'x' or 'z' bits. Treating as 1'b0.\n", log_signal(bit)); + log_debug("Design contains 'x' or 'z' bits. Treating as 1'b0.\n"); a = aig_map.at(State::S0); } -- cgit v1.2.3 From 65c1199acd52f90de86106652dbbca86d4ac5ebc Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 14:35:58 -0700 Subject: One more workaround for gcc-4.8 --- backends/aiger/xaiger.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6718e4f2c..637c54ff9 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -429,12 +429,13 @@ struct XAigerWriter module->connect(new_bit, bit); if (not_map.count(bit)) not_map[new_bit] = not_map.at(bit); - else if (and_map.count(bit)) - and_map[new_bit] = and_map.at(bit); + else if (and_map.count(bit)) { + //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 + and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + } else if (alias_map.count(bit)) alias_map[new_bit] = alias_map.at(bit); else - //log_abort(); alias_map[new_bit] = bit; output_bits.erase(bit); output_bits.insert(new_bit); -- cgit v1.2.3 From 7074ec9cd5d5b5c01e3bbaa8ee45dbae1272f185 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 17:16:38 -0700 Subject: Add log_push()/log_pop() inside write_xaiger --- backends/aiger/xaiger.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 637c54ff9..2070cae8f 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -664,6 +664,8 @@ struct XAigerWriter f.write(buffer_str.data(), buffer_str.size()); if (holes_module) { + log_push(); + // NB: fixup_ports() will sort ports by name //holes_module->fixup_ports(); holes_module->check(); @@ -700,6 +702,8 @@ struct XAigerWriter f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); f.write(buffer_str.data(), buffer_str.size()); holes_module->design->remove(holes_module); + + log_pop(); } } -- cgit v1.2.3 From fddb027cabedff92441b912a6cc472650aa9f74d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 15:45:51 -0700 Subject: Replace assert with error message --- backends/aiger/xaiger.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 2070cae8f..23132f108 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -244,7 +244,8 @@ struct XAigerWriter if (c.second.is_fully_const()) continue; auto is_input = cell->input(c.first); auto is_output = cell->output(c.first); - log_assert(is_input || is_output); + if (!is_input && !is_output) + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); if (is_input) { for (auto b : c.second.bits()) { -- cgit v1.2.3 From 7903ebe3e004c03e7870f1b21c4fb478481756eb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 22 Jun 2019 14:18:42 -0700 Subject: Carry in/out box ordering now move to end, not swap with end --- backends/aiger/xaiger.cc | 60 +++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 23132f108..7cfe8272c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -309,38 +309,46 @@ struct XAigerWriter if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - RTLIL::Wire* last_in = nullptr, *last_out = nullptr; - for (const auto &port_name : box_module->ports) { - RTLIL::Wire* w = box_module->wire(port_name); + auto &ports = box_module->ports; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*it); log_assert(w); - if (w->port_input) { - if (w->attributes.count("\\abc_carry_in")) { - log_assert(!carry_in); - carry_in = w; - } - log_assert(!last_in || last_in->port_id < w->port_id); - last_in = w; + if (w->port_input && w->attributes.count("\\abc_carry_in")) { + if (carry_in) + log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); + carry_in = w; + it = ports.erase(it); + continue; } - if (w->port_output) { - if (w->attributes.count("\\abc_carry_out")) { - log_assert(!carry_out); - carry_out = w; - } - log_assert(!last_out || last_out->port_id < w->port_id); - last_out = w; + if (w->port_output && w->attributes.count("\\abc_carry_out")) { + if (carry_out) + log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); + carry_out = w; + it = ports.erase(it); + continue; } + ++it; } - if (carry_in) { - log_assert(last_in); - std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]); - std::swap(carry_in->port_id, last_in->port_id); - } - if (carry_out) { - log_assert(last_out); - std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]); - std::swap(carry_out->port_id, last_out->port_id); + if (!carry_in) + log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); + if (!carry_out) + log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); + + for (const auto port_name : ports) { + RTLIL::Wire* w = box_module->wire(port_name); + log_assert(w); + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } // Fully pad all unused input connections of this box cell with S0 -- cgit v1.2.3 From 080a5ca536bcd7140ea3dc12483e49a8f076cd92 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Jun 2019 20:02:38 -0700 Subject: Improve debugging message for comb loops --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 7cfe8272c..92df899c2 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -293,10 +293,12 @@ struct XAigerWriter #if 0 unsigned i = 0; for (auto &it : toposort.loops) { - log(" loop %d", i++); - for (auto cell : it) - log(" %s", log_id(cell)); - log("\n"); + log(" loop %d\n", i++); + for (auto cell_name : it) { + auto cell = module->cell(cell_name); + log_assert(cell); + log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute().c_str()); + } } #endif log_assert(no_loops); -- cgit v1.2.3 From 9398921af1d21b47aa291d240a1f274418adcaf2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 27 Jun 2019 16:07:14 -0700 Subject: Refactor for one "abc_carry" attribute on module --- backends/aiger/xaiger.cc | 82 +++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 92df899c2..ae690ec49 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -284,8 +284,6 @@ struct XAigerWriter for (auto user_cell : it.second) toposort.edge(driver_cell, user_cell); - pool abc_carry_modules; - #if 0 toposort.analyze_loops = true; #endif @@ -303,54 +301,54 @@ struct XAigerWriter #endif log_assert(no_loops); + pool seen_boxes; for (auto cell_name : toposort.sorted) { RTLIL::Cell *cell = module->cell(cell_name); + log_assert(cell); + RTLIL::Module* box_module = module->design->module(cell->type); if (!box_module || !box_module->attributes.count("\\abc_box_id")) continue; - if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { - RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr; - auto &ports = box_module->ports; - for (auto it = ports.begin(); it != ports.end(); ) { - RTLIL::Wire* w = box_module->wire(*it); - log_assert(w); - if (w->port_input && w->attributes.count("\\abc_carry_in")) { - if (carry_in) - log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); - carry_in = w; - it = ports.erase(it); - continue; - } - if (w->port_output && w->attributes.count("\\abc_carry_out")) { - if (carry_out) - log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); - carry_out = w; - it = ports.erase(it); - continue; + if (seen_boxes.insert(cell->type).second) { + auto 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(); + auto pos = carry_in_out.find(','); + if (pos == std::string::npos) + log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); + auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); + carry_in = box_module->wire(carry_in_name); + if (!carry_in || !carry_in->port_input) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); + + auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); + carry_out = box_module->wire(carry_out_name); + if (!carry_out || !carry_out->port_output) + log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); + + auto &ports = box_module->ports; + for (auto jt = ports.begin(); jt != ports.end(); ) { + RTLIL::Wire* w = box_module->wire(*jt); + log_assert(w); + if (w == carry_in || w == carry_out) { + jt = ports.erase(jt); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++jt; } - ++it; - } - - if (!carry_in) - log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); - if (!carry_out) - log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); - - for (const auto port_name : ports) { - RTLIL::Wire* w = box_module->wire(port_name); - log_assert(w); - if (w->port_id > carry_in->port_id) - --w->port_id; - if (w->port_id > carry_out->port_id) - --w->port_id; - log_assert(w->port_input || w->port_output); - log_assert(ports[w->port_id-1] == w->name); + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); } - ports.push_back(carry_in->name); - carry_in->port_id = ports.size(); - ports.push_back(carry_out->name); - carry_out->port_id = ports.size(); } // Fully pad all unused input connections of this box cell with S0 -- cgit v1.2.3 From 36e2eb06bb63714d852b758062471222022930c3 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:51:43 -0700 Subject: Fix more potential for undefined behaviour due to container invalidation --- backends/aiger/xaiger.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index ae690ec49..d373ca77e 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -436,14 +436,18 @@ struct XAigerWriter new_wire = module->addWire(wire_name, GetSize(wire)); SigBit new_bit(new_wire, bit.offset); module->connect(new_bit, bit); - if (not_map.count(bit)) - not_map[new_bit] = not_map.at(bit); + if (not_map.count(bit)) { + auto a = not_map.at(bit); + not_map[new_bit] = a; + } else if (and_map.count(bit)) { - //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8 - and_map.insert(std::make_pair(new_bit, and_map.at(bit))); + auto a = and_map.at(bit); + and_map[new_bit] = a; + } + else if (alias_map.count(bit)) { + auto a = alias_map.at(bit); + alias_map[new_bit] = a; } - else if (alias_map.count(bit)) - alias_map[new_bit] = alias_map.at(bit); else alias_map[new_bit] = bit; output_bits.erase(bit); -- cgit v1.2.3 From 38d8806bd74b9bb448c7488ec571e197fe2f96d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 28 Jun 2019 09:59:47 -0700 Subject: Add generic __builtin_bswap32 function --- backends/aiger/xaiger.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d373ca77e..eb3d47569 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -25,6 +25,21 @@ #elif defined(__APPLE__) #include #define __builtin_bswap32 OSSwapInt32 +#elif !defined(__GNUC__) +#include +inline uint32_t __builtin_bswap32(uint32_t x) +{ + // https://stackoverflow.com/a/27796212 + register uint32_t value = number_to_be_reversed; + uint8_t lolo = (value >> 0) & 0xFF; + uint8_t lohi = (value >> 8) & 0xFF; + uint8_t hilo = (value >> 16) & 0xFF; + uint8_t hihi = (value >> 24) & 0xFF; + return (hihi << 24) + | (hilo << 16) + | (lohi << 8) + | (lolo << 0); +} #endif #include "kernel/yosys.h" -- cgit v1.2.3 From 10524064e94b9fe21483092e2733b1b71ae60b4e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 2 Jul 2019 19:14:30 -0700 Subject: write_xaiger to treat unknown cell connections as keep-s --- backends/aiger/xaiger.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index eb3d47569..869b741a6 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -138,6 +138,7 @@ struct XAigerWriter { pool undriven_bits; pool unused_bits; + pool keep_bits; // promote public wires for (auto wire : module->wires()) @@ -168,6 +169,9 @@ struct XAigerWriter unused_bits.insert(bit); } + if (keep) + keep_bits.insert(bit); + if (wire->port_input || keep) { if (bit != wirebit) alias_map[bit] = wirebit; @@ -235,7 +239,7 @@ struct XAigerWriter log_assert(!holes_mode); RTLIL::Module* inst_module = module->design->module(cell->type); - if (inst_module && inst_module->attributes.count("\\abc_box_id")) { + if (inst_module && inst_module->attributes.count("\\abc_box_id")) { abc_box_seen = true; if (!holes_mode) { @@ -255,10 +259,11 @@ struct XAigerWriter } } else { + bool cell_known = cell->known(); for (const auto &c : cell->connections()) { if (c.second.is_fully_const()) continue; - auto is_input = cell->input(c.first); - auto is_output = cell->output(c.first); + auto is_input = !cell_known || cell->input(c.first); + auto is_output = !cell_known || cell->output(c.first); if (!is_input && !is_output) log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); @@ -266,12 +271,15 @@ struct XAigerWriter for (auto b : c.second.bits()) { Wire *w = b.wire; if (!w) continue; - if (!w->port_output) { + if (!w->port_output || !cell_known) { SigBit I = sigmap(b); if (I != b) alias_map[b] = I; output_bits.insert(b); unused_bits.erase(b); + + if (!cell_known) + keep_bits.insert(b); } } } @@ -424,7 +432,7 @@ struct XAigerWriter auto jt = input_bits.find(b); if (jt != input_bits.end()) { - log_assert(b.wire->attributes.count("\\keep")); + log_assert(keep_bits.count(O)); input_bits.erase(b); } } @@ -444,7 +452,7 @@ struct XAigerWriter // with $inout.out suffix, make it a PO driven by the existing inout, and // inherit existing inout's drivers if ((wire->port_input && wire->port_output && !undriven_bits.count(bit)) - || wire->attributes.count("\\keep")) { + || keep_bits.count(bit)) { RTLIL::IdString wire_name = wire->name.str() + "$inout.out"; RTLIL::Wire *new_wire = module->wire(wire_name); if (!new_wire) -- cgit v1.2.3 From 5a0f2e43c796ed91693d60261bd75a489f778a3a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 09:35:09 -0700 Subject: Rename __builtin_bswap32 -> bswap32 --- backends/aiger/xaiger.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'backends/aiger/xaiger.cc') diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 869b741a6..69f63486c 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -21,13 +21,15 @@ // https://stackoverflow.com/a/46137633 #ifdef _MSC_VER #include -#define __builtin_bswap32 _byteswap_ulong +#define bswap32 _byteswap_ulong #elif defined(__APPLE__) #include -#define __builtin_bswap32 OSSwapInt32 -#elif !defined(__GNUC__) +#define bswap32 OSSwapInt32 +#elif defined(__GNUC__) +#define bswap32 __builtin_bswap32 +#else #include -inline uint32_t __builtin_bswap32(uint32_t x) +inline static uint32_t bswap32(uint32_t x) { // https://stackoverflow.com/a/27796212 register uint32_t value = number_to_be_reversed; -- cgit v1.2.3