mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
Added additional gate types: $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_
This commit is contained in:
parent
56a30cf42c
commit
47c2637a96
8 changed files with 399 additions and 48 deletions
|
@ -131,9 +131,16 @@ struct CellTypes
|
|||
{
|
||||
setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true);
|
||||
setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true);
|
||||
setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true);
|
||||
setup_type("$_OR_", {"\\A", "\\B"}, {"\\Y"}, true);
|
||||
setup_type("$_NOR_", {"\\A", "\\B"}, {"\\Y"}, true);
|
||||
setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, true);
|
||||
setup_type("$_XNOR_", {"\\A", "\\B"}, {"\\Y"}, true);
|
||||
setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
|
||||
setup_type("$_AOI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
|
||||
setup_type("$_OAI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true);
|
||||
setup_type("$_AOI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
|
||||
setup_type("$_OAI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true);
|
||||
}
|
||||
|
||||
void setup_stdcells_mem()
|
||||
|
@ -194,6 +201,14 @@ struct CellTypes
|
|||
return it != cell_types.end() && it->second.is_evaluable;
|
||||
}
|
||||
|
||||
static RTLIL::Const eval_not(RTLIL::Const v)
|
||||
{
|
||||
for (auto &bit : v.bits)
|
||||
if (bit == RTLIL::S0) bit = RTLIL::S1;
|
||||
else if (bit == RTLIL::S1) bit = RTLIL::S0;
|
||||
return v;
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
{
|
||||
if (type == "$sshr" && !signed1)
|
||||
|
@ -247,13 +262,19 @@ struct CellTypes
|
|||
#undef HANDLE_CELL_TYPE
|
||||
|
||||
if (type == "$_NOT_")
|
||||
return const_not(arg1, arg2, false, false, 1);
|
||||
return eval_not(arg1);
|
||||
if (type == "$_AND_")
|
||||
return const_and(arg1, arg2, false, false, 1);
|
||||
if (type == "$_NAND_")
|
||||
return eval_not(const_and(arg1, arg2, false, false, 1));
|
||||
if (type == "$_OR_")
|
||||
return const_or(arg1, arg2, false, false, 1);
|
||||
if (type == "$_NOR_")
|
||||
return eval_not(const_and(arg1, arg2, false, false, 1));
|
||||
if (type == "$_XOR_")
|
||||
return const_xor(arg1, arg2, false, false, 1);
|
||||
if (type == "$_XNOR_")
|
||||
return const_xnor(arg1, arg2, false, false, 1);
|
||||
|
||||
log_abort();
|
||||
}
|
||||
|
@ -280,21 +301,37 @@ struct CellTypes
|
|||
return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &sel)
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
|
||||
{
|
||||
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") {
|
||||
if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
|
||||
RTLIL::Const ret = arg1;
|
||||
for (size_t i = 0; i < sel.bits.size(); i++)
|
||||
if (sel.bits[i] == RTLIL::State::S1) {
|
||||
for (size_t i = 0; i < arg3.bits.size(); i++)
|
||||
if (arg3.bits[i] == RTLIL::State::S1) {
|
||||
std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size());
|
||||
ret = RTLIL::Const(bits);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
log_assert(sel.bits.size() == 0);
|
||||
if (cell->type == "$_AOI3_")
|
||||
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1));
|
||||
if (cell->type == "$_OAI3_")
|
||||
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
|
||||
|
||||
log_assert(arg3.bits.size() == 0);
|
||||
return eval(cell, arg1, arg2);
|
||||
}
|
||||
|
||||
static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4)
|
||||
{
|
||||
if (cell->type == "$_AOI4_")
|
||||
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
|
||||
if (cell->type == "$_OAI4_")
|
||||
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
|
||||
|
||||
log_assert(arg4.bits.size() == 0);
|
||||
return eval(cell, arg1, arg2, arg3);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -156,11 +156,26 @@ struct ConstEval
|
|||
}
|
||||
else
|
||||
{
|
||||
RTLIL::SigSpec sig_c, sig_d;
|
||||
|
||||
if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) {
|
||||
if (cell->hasPort("\\C"))
|
||||
sig_c = cell->getPort("\\C");
|
||||
if (cell->hasPort("\\D"))
|
||||
sig_d = cell->getPort("\\D");
|
||||
}
|
||||
|
||||
if (sig_a.size() > 0 && !eval(sig_a, undef, cell))
|
||||
return false;
|
||||
if (sig_b.size() > 0 && !eval(sig_b, undef, cell))
|
||||
return false;
|
||||
set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const()));
|
||||
if (sig_c.size() > 0 && !eval(sig_c, undef, cell))
|
||||
return false;
|
||||
if (sig_d.size() > 0 && !eval(sig_d, undef, cell))
|
||||
return false;
|
||||
|
||||
set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(),
|
||||
sig_c.as_const(), sig_d.as_const()));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -758,11 +758,18 @@ namespace {
|
|||
return;
|
||||
}
|
||||
|
||||
if (cell->type == "$_NOT_") { check_gate("AY"); return; }
|
||||
if (cell->type == "$_AND_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_OR_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_XOR_") { check_gate("ABY"); return; }
|
||||
if (cell->type == "$_MUX_") { check_gate("ABSY"); 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 == "$_SR_NN_") { check_gate("SRQ"); return; }
|
||||
if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; }
|
||||
|
|
|
@ -175,6 +175,11 @@ struct SatGen
|
|||
}
|
||||
}
|
||||
|
||||
void undefGating(int y, int yy, int undef)
|
||||
{
|
||||
ez->assume(ez->OR(undef, ez->IFF(y, yy)));
|
||||
}
|
||||
|
||||
bool importCell(RTLIL::Cell *cell, int timestep = -1)
|
||||
{
|
||||
bool arith_undef_handled = false;
|
||||
|
@ -211,9 +216,8 @@ struct SatGen
|
|||
arith_undef_handled = true;
|
||||
}
|
||||
|
||||
if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_" ||
|
||||
cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" ||
|
||||
cell->type == "$add" || cell->type == "$sub")
|
||||
if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_",
|
||||
"$and", "$or", "$xor", "$xnor", "$add", "$sub"))
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
|
||||
std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
|
||||
|
@ -224,11 +228,15 @@ struct SatGen
|
|||
|
||||
if (cell->type == "$and" || cell->type == "$_AND_")
|
||||
ez->assume(ez->vec_eq(ez->vec_and(a, b), yy));
|
||||
if (cell->type == "$_NAND_")
|
||||
ez->assume(ez->vec_eq(ez->vec_not(ez->vec_and(a, b)), yy));
|
||||
if (cell->type == "$or" || cell->type == "$_OR_")
|
||||
ez->assume(ez->vec_eq(ez->vec_or(a, b), yy));
|
||||
if (cell->type == "$_NOR_")
|
||||
ez->assume(ez->vec_eq(ez->vec_not(ez->vec_or(a, b)), yy));
|
||||
if (cell->type == "$xor" || cell->type == "$_XOR_")
|
||||
ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy));
|
||||
if (cell->type == "$xnor")
|
||||
if (cell->type == "$xnor" || cell->type == "$_XNOR_")
|
||||
ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy));
|
||||
if (cell->type == "$add")
|
||||
ez->assume(ez->vec_eq(ez->vec_add(a, b), yy));
|
||||
|
@ -242,19 +250,19 @@ struct SatGen
|
|||
std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
|
||||
extendSignalWidth(undef_a, undef_b, undef_y, cell, false);
|
||||
|
||||
if (cell->type == "$and" || cell->type == "$_AND_") {
|
||||
if (cell->type.in("$and", "$_AND_", "$_NAND_")) {
|
||||
std::vector<int> a0 = ez->vec_and(ez->vec_not(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(a0, b0)));
|
||||
ez->assume(ez->vec_eq(yX, undef_y));
|
||||
}
|
||||
else if (cell->type == "$or" || cell->type == "$_OR_") {
|
||||
else if (cell->type.in("$or", "$_OR_", "$_NOR_")) {
|
||||
std::vector<int> a1 = ez->vec_and(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(a1, b1)));
|
||||
ez->assume(ez->vec_eq(yX, undef_y));
|
||||
}
|
||||
else if (cell->type == "$xor" || cell->type == "$_XOR_" || cell->type == "$xnor") {
|
||||
else if (cell->type.in("$xor", "$xnor", "$_XOR_", "$_XNOR_")) {
|
||||
std::vector<int> yX = ez->vec_or(undef_a, undef_b);
|
||||
ez->assume(ez->vec_eq(yX, undef_y));
|
||||
}
|
||||
|
@ -271,6 +279,72 @@ struct SatGen
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
|
||||
{
|
||||
bool aoi_mode = cell->type.in("$_AOI3_", "$_AOI4_");
|
||||
bool three_mode = cell->type.in("$_AOI3_", "$_OAI3_");
|
||||
|
||||
int a = importDefSigSpec(cell->getPort("\\A"), timestep).at(0);
|
||||
int b = importDefSigSpec(cell->getPort("\\B"), timestep).at(0);
|
||||
int c = importDefSigSpec(cell->getPort("\\C"), timestep).at(0);
|
||||
int d = three_mode ? (aoi_mode ? ez->TRUE : ez->FALSE) : importDefSigSpec(cell->getPort("\\D"), timestep).at(0);
|
||||
int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0);
|
||||
int yy = model_undef ? ez->literal() : y;
|
||||
|
||||
if (cell->type.in("$_AOI3_", "$_AOI4_"))
|
||||
ez->assume(ez->IFF(ez->NOT(ez->OR(ez->AND(a, b), ez->AND(c, d))), yy));
|
||||
else
|
||||
ez->assume(ez->IFF(ez->NOT(ez->AND(ez->OR(a, b), ez->OR(c, d))), yy));
|
||||
|
||||
if (model_undef)
|
||||
{
|
||||
int undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep).at(0);
|
||||
int undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep).at(0);
|
||||
int undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep).at(0);
|
||||
int undef_d = three_mode ? ez->FALSE : importUndefSigSpec(cell->getPort("\\D"), timestep).at(0);
|
||||
int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0);
|
||||
|
||||
if (aoi_mode)
|
||||
{
|
||||
int a0 = ez->AND(ez->NOT(a), ez->NOT(undef_a));
|
||||
int b0 = ez->AND(ez->NOT(b), ez->NOT(undef_b));
|
||||
int c0 = ez->AND(ez->NOT(c), ez->NOT(undef_c));
|
||||
int d0 = ez->AND(ez->NOT(d), ez->NOT(undef_d));
|
||||
|
||||
int ab = ez->AND(a, b), cd = ez->AND(c, d);
|
||||
int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a0, b0)));
|
||||
int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c0, d0)));
|
||||
|
||||
int ab1 = ez->AND(ab, ez->NOT(undef_ab));
|
||||
int cd1 = ez->AND(cd, ez->NOT(undef_cd));
|
||||
int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab1, cd1)));
|
||||
|
||||
ez->assume(ez->IFF(yX, undef_y));
|
||||
}
|
||||
else
|
||||
{
|
||||
int a1 = ez->AND(a, ez->NOT(undef_a));
|
||||
int b1 = ez->AND(b, ez->NOT(undef_b));
|
||||
int c1 = ez->AND(c, ez->NOT(undef_c));
|
||||
int d1 = ez->AND(d, ez->NOT(undef_d));
|
||||
|
||||
int ab = ez->OR(a, b), cd = ez->OR(c, d);
|
||||
int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a1, b1)));
|
||||
int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c1, d1)));
|
||||
|
||||
int ab0 = ez->AND(ez->NOT(ab), ez->NOT(undef_ab));
|
||||
int cd0 = ez->AND(ez->NOT(cd), ez->NOT(undef_cd));
|
||||
int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab0, cd0)));
|
||||
|
||||
ez->assume(ez->IFF(yX, undef_y));
|
||||
}
|
||||
|
||||
undefGating(y, yy, undef_y);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$_NOT_" || cell->type == "$not")
|
||||
{
|
||||
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue