aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--backends/blif/blif.cc12
-rw-r--r--backends/simplec/simplec.cc16
-rw-r--r--backends/smt2/smt2.cc2
-rw-r--r--backends/smv/smv.cc10
-rw-r--r--backends/verilog/verilog_backend.cc10
-rw-r--r--kernel/cellaigs.cc16
-rw-r--r--kernel/celltypes.h2
-rw-r--r--kernel/cost.h28
-rw-r--r--kernel/rtlil.cc56
-rw-r--r--kernel/rtlil.h28
-rw-r--r--kernel/satgen.h19
-rw-r--r--manual/CHAPTER_CellLib.tex3
-rw-r--r--passes/techmap/abc.cc62
-rw-r--r--techlibs/common/simcells.v38
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<RTLIL::IdString, RTLIL::Const
RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr)
{
static dict<RTLIL::IdString, int> 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<int> 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<int> yX = ez->vec_or(undef_a, undef_b);
ez->assume(ez->vec_eq(yX, undef_y));
}
+ else if (cell->type == "$_ANDNOT_") {
+ std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a));
+ std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b));
+ std::vector<int> 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<int> a1 = ez->vec_and(a, ez->vec_not(undef_a));
+ std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b));
+ std::vector<int> 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
@@ -175,6 +175,44 @@ 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)
//-
//- A 2-input MUX gate.