From 05cdd58c8dc73968992681d0ee1cbfa89880b94f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 17 May 2017 09:08:29 +0200 Subject: [PATCH] Add $_ANDNOT_ and $_ORNOT_ gates --- backends/blif/blif.cc | 12 ++++++ backends/simplec/simplec.cc | 16 ++++---- backends/smt2/smt2.cc | 2 + backends/smv/smv.cc | 10 +++-- backends/verilog/verilog_backend.cc | 10 +++-- kernel/cellaigs.cc | 16 +++++++- kernel/celltypes.h | 2 + kernel/cost.h | 28 +++++++------ kernel/rtlil.cc | 56 ++++++++++++++------------ kernel/rtlil.h | 28 +++++++------ kernel/satgen.h | 19 ++++++++- manual/CHAPTER_CellLib.tex | 3 +- passes/techmap/abc.cc | 62 +++++++++++++++++++---------- techlibs/common/simcells.v | 38 ++++++++++++++++++ 14 files changed, 211 insertions(+), 91 deletions(-) diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 4dbaca0bd..f9230a1e6 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -279,6 +279,18 @@ struct BlifDumper continue; } + if (!config->icells_mode && cell->type == "$_ANDNOT_") { + f << stringf(".names %s %s %s\n10 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); + continue; + } + + if (!config->icells_mode && cell->type == "$_ORNOT_") { + f << stringf(".names %s %s %s\n1- 1\n-0 1\n", + cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); + continue; + } + if (!config->icells_mode && cell->type == "$_AOI3_") { f << stringf(".names %s %s %s %s\n-00 1\n0-0 1\n", cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y"))); diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 15399831e..5768e3499 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -397,7 +397,7 @@ struct SimplecWorker return; } - if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); @@ -407,12 +407,14 @@ struct SimplecWorker string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0"; string expr; - if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str()); - if (cell->type == "$_NAND_") expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str()); - if (cell->type == "$_OR_") expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str()); - if (cell->type == "$_NOR_") expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str()); - if (cell->type == "$_XOR_") expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str()); - if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_NAND_") expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_OR_") expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_NOR_") expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_XOR_") expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_ANDNOT_") expr = stringf("%s & (!%s)", a_expr.c_str(), b_expr.c_str()); + if (cell->type == "$_ORNOT_") expr = stringf("%s | (!%s)", a_expr.c_str(), b_expr.c_str()); log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 372dbeb57..df189fc3f 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -434,6 +434,8 @@ struct Smt2Worker if (cell->type == "$_NOR_") return export_gate(cell, "(not (or A B))"); if (cell->type == "$_XOR_") return export_gate(cell, "(xor A B)"); if (cell->type == "$_XNOR_") return export_gate(cell, "(not (xor A B))"); + if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))"); + if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))"); if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)"); if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))"); if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))"); diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index 162ce4906..768969e6b 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -507,15 +507,19 @@ struct SmvWorker continue; } - if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { string op; - if (cell->type.in("$_AND_", "$_NAND_")) op = "&"; - if (cell->type.in("$_OR_", "$_NOR_")) op = "|"; + if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_")) op = "&"; + if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_")) op = "|"; if (cell->type.in("$_XOR_")) op = "xor"; if (cell->type.in("$_XNOR_")) op = "xnor"; + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) + assignments.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")), + rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); + else if (cell->type.in("$_NAND_", "$_NOR_")) assignments.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 191553324..bb312944e 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -470,7 +470,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) { + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, cell->getPort("\\Y")); f << stringf(" = "); @@ -478,16 +478,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) f << stringf("~("); dump_cell_expr_port(f, cell, "A", false); f << stringf(" "); - if (cell->type.in("$_AND_", "$_NAND_")) + if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_")) f << stringf("&"); - if (cell->type.in("$_OR_", "$_NOR_")) + if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_")) f << stringf("|"); if (cell->type.in("$_XOR_", "$_XNOR_")) f << stringf("^"); dump_attributes(f, "", cell->attributes, ' '); f << stringf(" "); + if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) + f << stringf("~("); dump_cell_expr_port(f, cell, "B", false); - if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_")) + if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) f << stringf(")"); f << stringf(";\n"); return true; diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc index 41f81355d..5fd76afe5 100644 --- a/kernel/cellaigs.cc +++ b/kernel/cellaigs.cc @@ -202,6 +202,16 @@ struct AigMaker return or_gate(and_gate(A, B), nor_gate(A, B)); } + int andnot_gate(int A, int B) + { + return and_gate(A, not_gate(B)); + } + + int ornot_gate(int A, int B) + { + return or_gate(A, not_gate(B)); + } + int mux_gate(int A, int B, int S) { return or_gate(and_gate(A, not_gate(S)), and_gate(B, S)); @@ -290,7 +300,7 @@ Aig::Aig(Cell *cell) goto optimize; } - if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_")) + if (cell->type.in("$and", "$_AND_", "$_NAND_", "$or", "$_OR_", "$_NOR_", "$xor", "$xnor", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { for (int i = 0; i < GetSize(cell->getPort("\\Y")); i++) { int A = mk.inport("\\A", i); @@ -300,7 +310,9 @@ Aig::Aig(Cell *cell) cell->type.in("$or", "$_OR_") ? mk.or_gate(A, B) : cell->type.in("$_NOR_") ? mk.nor_gate(A, B) : cell->type.in("$xor", "$_XOR_") ? mk.xor_gate(A, B) : - cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) : -1; + cell->type.in("$xnor", "$_XNOR_") ? mk.xnor_gate(A, B) : + cell->type.in("$_ANDNOT_") ? mk.andnot_gate(A, B) : + cell->type.in("$_ORNOT_") ? mk.ornot_gate(A, B) : -1; mk.outport(Y, "\\Y", i); } goto optimize; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index c43f685ac..b8a4cc74c 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -167,6 +167,8 @@ struct CellTypes setup_type("$_NOR_", {A, B}, {Y}, true); setup_type("$_XOR_", {A, B}, {Y}, true); setup_type("$_XNOR_", {A, B}, {Y}, true); + setup_type("$_ANDNOT_", {A, B}, {Y}, true); + setup_type("$_ORNOT_", {A, B}, {Y}, true); setup_type("$_MUX_", {A, B, S}, {Y}, true); setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true); setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true); diff --git a/kernel/cost.h b/kernel/cost.h index 4f12889f4..84fd6cd6d 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -30,19 +30,21 @@ int get_cell_cost(RTLIL::IdString type, const dict *mod_cost_cache = nullptr) { static dict gate_cost = { - { "$_BUF_", 1 }, - { "$_NOT_", 2 }, - { "$_AND_", 4 }, - { "$_NAND_", 4 }, - { "$_OR_", 4 }, - { "$_NOR_", 4 }, - { "$_XOR_", 8 }, - { "$_XNOR_", 8 }, - { "$_AOI3_", 6 }, - { "$_OAI3_", 6 }, - { "$_AOI4_", 8 }, - { "$_OAI4_", 8 }, - { "$_MUX_", 4 } + { "$_BUF_", 1 }, + { "$_NOT_", 2 }, + { "$_AND_", 4 }, + { "$_NAND_", 4 }, + { "$_OR_", 4 }, + { "$_NOR_", 4 }, + { "$_ANDNOT_", 4 }, + { "$_ORNOT_", 4 }, + { "$_XOR_", 8 }, + { "$_XNOR_", 8 }, + { "$_AOI3_", 6 }, + { "$_OAI3_", 6 }, + { "$_AOI4_", 8 }, + { "$_OAI4_", 8 }, + { "$_MUX_", 4 } }; if (gate_cost.count(type)) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 6ce3f1376..93cfef80e 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1053,19 +1053,21 @@ namespace { return; } - if (cell->type == "$_BUF_") { check_gate("AY"); return; } - if (cell->type == "$_NOT_") { check_gate("AY"); return; } - if (cell->type == "$_AND_") { check_gate("ABY"); return; } - if (cell->type == "$_NAND_") { check_gate("ABY"); return; } - if (cell->type == "$_OR_") { check_gate("ABY"); return; } - if (cell->type == "$_NOR_") { check_gate("ABY"); return; } - if (cell->type == "$_XOR_") { check_gate("ABY"); return; } - if (cell->type == "$_XNOR_") { check_gate("ABY"); return; } - if (cell->type == "$_MUX_") { check_gate("ABSY"); return; } - if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; } - if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; } - if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; } - if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; } + if (cell->type == "$_BUF_") { check_gate("AY"); return; } + if (cell->type == "$_NOT_") { check_gate("AY"); return; } + if (cell->type == "$_AND_") { check_gate("ABY"); return; } + if (cell->type == "$_NAND_") { check_gate("ABY"); return; } + if (cell->type == "$_OR_") { check_gate("ABY"); return; } + if (cell->type == "$_NOR_") { check_gate("ABY"); return; } + if (cell->type == "$_XOR_") { check_gate("ABY"); return; } + if (cell->type == "$_XNOR_") { check_gate("ABY"); return; } + if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; } + if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; } + if (cell->type == "$_MUX_") { check_gate("ABSY"); return; } + if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; } + if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; } + if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; } + if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; } if (cell->type == "$_TBUF_") { check_gate("AYE"); return; } @@ -1729,19 +1731,21 @@ DEF_METHOD(Pmux, "$pmux", 1) add ## _func(name, sig1, sig2, sig3, sig4, sig5); \ return sig5; \ } -DEF_METHOD_2(BufGate, "$_BUF_", A, Y) -DEF_METHOD_2(NotGate, "$_NOT_", A, Y) -DEF_METHOD_3(AndGate, "$_AND_", A, B, Y) -DEF_METHOD_3(NandGate, "$_NAND_", A, B, Y) -DEF_METHOD_3(OrGate, "$_OR_", A, B, Y) -DEF_METHOD_3(NorGate, "$_NOR_", A, B, Y) -DEF_METHOD_3(XorGate, "$_XOR_", A, B, Y) -DEF_METHOD_3(XnorGate, "$_XNOR_", A, B, Y) -DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, Y) -DEF_METHOD_4(Aoi3Gate, "$_AOI3_", A, B, C, Y) -DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y) -DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y) -DEF_METHOD_5(Oai4Gate, "$_OAI4_", A, B, C, D, Y) +DEF_METHOD_2(BufGate, "$_BUF_", A, Y) +DEF_METHOD_2(NotGate, "$_NOT_", A, Y) +DEF_METHOD_3(AndGate, "$_AND_", A, B, Y) +DEF_METHOD_3(NandGate, "$_NAND_", A, B, Y) +DEF_METHOD_3(OrGate, "$_OR_", A, B, Y) +DEF_METHOD_3(NorGate, "$_NOR_", A, B, Y) +DEF_METHOD_3(XorGate, "$_XOR_", A, B, Y) +DEF_METHOD_3(XnorGate, "$_XNOR_", A, B, Y) +DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y) +DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y) +DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, Y) +DEF_METHOD_4(Aoi3Gate, "$_AOI3_", A, B, C, Y) +DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y) +DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y) +DEF_METHOD_5(Oai4Gate, "$_OAI4_", A, B, C, D, Y) #undef DEF_METHOD_2 #undef DEF_METHOD_3 #undef DEF_METHOD_4 diff --git a/kernel/rtlil.h b/kernel/rtlil.h index ab8771256..034ce9c0c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1024,19 +1024,21 @@ public: RTLIL::Cell* addDlatchsr (RTLIL::IdString name, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true); - RTLIL::Cell* addBufGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y); - RTLIL::Cell* addNotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y); - RTLIL::Cell* addAndGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); - RTLIL::Cell* addNandGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); - RTLIL::Cell* addOrGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); - RTLIL::Cell* addNorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); - RTLIL::Cell* addXorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); - RTLIL::Cell* addXnorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); - RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y); - RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y); - RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y); - RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y); - RTLIL::Cell* addOai4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y); + RTLIL::Cell* addBufGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y); + RTLIL::Cell* addNotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_y); + RTLIL::Cell* addAndGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addNandGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addOrGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addNorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addXorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addXnorGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addOrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y); + RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y); + RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y); + RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y); + RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y); + RTLIL::Cell* addOai4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y); RTLIL::Cell* addFfGate (RTLIL::IdString name, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q); RTLIL::Cell* addDffGate (RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity = true); diff --git a/kernel/satgen.h b/kernel/satgen.h index 25a22fd8a..8d760fff7 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -310,7 +310,7 @@ struct SatGen arith_undef_handled = true; } - if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$and", "$or", "$xor", "$xnor", "$add", "$sub")) { std::vector a = importDefSigSpec(cell->getPort("\\A"), timestep); @@ -332,6 +332,10 @@ struct SatGen ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy)); if (cell->type == "$xnor" || cell->type == "$_XNOR_") ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy)); + if (cell->type == "$_ANDNOT_") + ez->assume(ez->vec_eq(ez->vec_and(a, ez->vec_not(b)), yy)); + if (cell->type == "$_ORNOT_") + ez->assume(ez->vec_eq(ez->vec_or(a, ez->vec_not(b)), yy)); if (cell->type == "$add") ez->assume(ez->vec_eq(ez->vec_add(a, b), yy)); if (cell->type == "$sub") @@ -360,6 +364,19 @@ struct SatGen std::vector yX = ez->vec_or(undef_a, undef_b); ez->assume(ez->vec_eq(yX, undef_y)); } + else if (cell->type == "$_ANDNOT_") { + std::vector a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a)); + std::vector b1 = ez->vec_and(b, ez->vec_not(undef_b)); + std::vector yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b1))); + ez->assume(ez->vec_eq(yX, undef_y)); + } + + else if (cell->type == "$_ORNOT_") { + std::vector a1 = ez->vec_and(a, ez->vec_not(undef_a)); + std::vector b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b)); + std::vector yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b0))); + ez->assume(ez->vec_eq(yX, undef_y)); + } else log_abort(); diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex index b2ba1fd88..c36e61b05 100644 --- a/manual/CHAPTER_CellLib.tex +++ b/manual/CHAPTER_CellLib.tex @@ -449,6 +449,7 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA \end{fixme} \begin{fixme} -Add information about {\tt \$\_NAND\_}, {\tt \$\_NOR\_}, {\tt \$\_XNOR\_}, {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells. +Add information about {\tt \$\_NAND\_}, {\tt \$\_NOR\_}, {\tt \$\_XNOR\_}, {\tt \$\_ANDNOT\_}, {\tt \$\_ORNOT\_}, +{\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells. \end{fixme} diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index a1cea3aaf..386398e45 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -74,6 +74,8 @@ enum class gate_type_t { G_NOR, G_XOR, G_XNOR, + G_ANDNOT, + G_ORNOT, G_MUX, G_AOI3, G_OAI3, @@ -207,7 +209,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) return; } - if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_b = cell->getPort("\\B"); @@ -232,6 +234,10 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) map_signal(sig_y, G(XOR), mapped_a, mapped_b); else if (cell->type == "$_XNOR_") map_signal(sig_y, G(XNOR), mapped_a, mapped_b); + else if (cell->type == "$_ANDNOT_") + map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b); + else if (cell->type == "$_ORNOT_") + map_signal(sig_y, G(ORNOT), mapped_a, mapped_b); else log_abort(); @@ -813,6 +819,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); fprintf(f, "00 1\n"); fprintf(f, "11 1\n"); + } else if (si.type == G(ANDNOT)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "10 1\n"); + } else if (si.type == G(ORNOT)) { + fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id); + fprintf(f, "1- 1\n"); + fprintf(f, "-0 1\n"); } else if (si.type == G(MUX)) { fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id); fprintf(f, "1-0 1\n"); @@ -858,38 +871,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin f = fopen(buffer.c_str(), "wt"); if (f == NULL) log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); - fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); - fprintf(f, "GATE ONE 1 Y=CONST1;\n"); - fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); - fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_")); + fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); + fprintf(f, "GATE ONE 1 Y=CONST1;\n"); + fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_BUF_")); + fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOT_")); if (enabled_gates.empty() || enabled_gates.count("AND")) - fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_")); + fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_")); if (enabled_gates.empty() || enabled_gates.count("NAND")) - fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_")); + fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_")); if (enabled_gates.empty() || enabled_gates.count("OR")) - fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_")); + fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_")); if (enabled_gates.empty() || enabled_gates.count("NOR")) - fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_")); + fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_")); if (enabled_gates.empty() || enabled_gates.count("XOR")) - fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_")); + fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_")); if (enabled_gates.empty() || enabled_gates.count("XNOR")) - fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_")); + fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_")); + if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) + fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_")); + if (enabled_gates.empty() || enabled_gates.count("ORNOT")) + fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_")); if (enabled_gates.empty() || enabled_gates.count("AOI3")) - fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_")); + fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_")); if (enabled_gates.empty() || enabled_gates.count("OAI3")) - fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_")); + fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_")); if (enabled_gates.empty() || enabled_gates.count("AOI4")) - fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_")); + fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_")); if (enabled_gates.empty() || enabled_gates.count("OAI4")) - fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); + fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_")); if (enabled_gates.empty() || enabled_gates.count("MUX")) - fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_")); + fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_")); if (map_mux4) - fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_")); + fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_")); if (map_mux8) - fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_")); + fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_")); if (map_mux16) - fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); + fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_")); fclose(f); if (!lut_costs.empty()) { @@ -961,7 +978,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin design->select(module, cell); continue; } - if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || c->type == "\\XNOR") { + if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" || + c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") { RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_"); if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); @@ -1297,7 +1315,7 @@ struct AbcPass : public Pass { // log("\n"); log(" -g type1,type2,...\n"); log(" Map the the specified list of gate types. Supported gates types are:\n"); - log(" AND, NAND, OR, NOR, XOR, XNOR, MUX, AOI3, OAI3, AOI4, OAI4.\n"); + log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n"); log(" (The NOT gate is always added to this list automatically.)\n"); log("\n"); log(" -dff\n"); @@ -1468,6 +1486,8 @@ struct AbcPass : public Pass { if (g == "NOR") goto ok_gate; if (g == "XOR") goto ok_gate; if (g == "XNOR") goto ok_gate; + if (g == "ANDNOT") goto ok_gate; + if (g == "ORNOT") goto ok_gate; if (g == "MUX") goto ok_gate; if (g == "AOI3") goto ok_gate; if (g == "OAI3") goto ok_gate; diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index e770c5453..937512e7c 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -173,6 +173,44 @@ output Y; assign Y = ~(A ^ B); endmodule +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ANDNOT_ (A, B, Y) +//- +//- A 2-input AND-NOT gate. +//- +//- Truth table: A B | Y +//- -----+--- +//- 0 0 | 0 +//- 0 1 | 0 +//- 1 0 | 1 +//- 1 1 | 0 +//- +module \$_ANDNOT_ (A, B, Y); +input A, B; +output Y; +assign Y = A & (~B); +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ORNOT_ (A, B, Y) +//- +//- A 2-input OR-NOT gate. +//- +//- Truth table: A B | Y +//- -----+--- +//- 0 0 | 1 +//- 0 1 | 0 +//- 1 0 | 1 +//- 1 1 | 1 +//- +module \$_ORNOT_ (A, B, Y); +input A, B; +output Y; +assign Y = A | (~B); +endmodule + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- //- $_MUX_ (A, B, S, Y) -- 2.30.2