Add $_ANDNOT_ and $_ORNOT_ gates

This commit is contained in:
Clifford Wolf 2017-05-17 09:08:29 +02:00
parent 9f4fbc5e74
commit 05cdd58c8d
14 changed files with 211 additions and 91 deletions

View File

@ -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")));

View File

@ -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"));
@ -413,6 +413,8 @@ struct SimplecWorker
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) +

View File

@ -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))");

View File

@ -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"))));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -36,6 +36,8 @@ int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const
{ "$_NAND_", 4 },
{ "$_OR_", 4 },
{ "$_NOR_", 4 },
{ "$_ANDNOT_", 4 },
{ "$_ORNOT_", 4 },
{ "$_XOR_", 8 },
{ "$_XNOR_", 8 },
{ "$_AOI3_", 6 },

View File

@ -1061,6 +1061,8 @@ namespace {
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; }
@ -1737,6 +1739,8 @@ 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)

View File

@ -1032,6 +1032,8 @@ public:
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);

View File

@ -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();

View File

@ -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}

View File

@ -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");
@ -874,6 +887,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
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_"));
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_"));
if (enabled_gates.empty() || enabled_gates.count("OAI3"))
@ -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;

View File

@ -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)