summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-09-08 12:15:39 +0200
committerClifford Wolf <clifford@clifford.at>2014-09-08 12:15:39 +0200
commitd46bac330520f91ee5bf8027abe98a8f9389f696 (patch)
treed1b87a2409d082fa281d2c9ea100e94c69a43912 /kernel
parent1a88e47396305bd6b5ee2a7a91a1d014ebd37c10 (diff)
Added "$fa" cell type
Diffstat (limited to 'kernel')
-rw-r--r--kernel/celltypes.h1
-rw-r--r--kernel/consteval.h25
-rw-r--r--kernel/rtlil.cc15
-rw-r--r--kernel/satgen.h49
4 files changed, 90 insertions, 0 deletions
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 74e9f1fd..b42cf4e9 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -106,6 +106,7 @@ struct CellTypes
setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, true);
+ setup_type("$fa", {"\\A", "\\B", "\\C"}, {"\\X", "\\Y"}, true);
setup_type("$assert", {"\\A", "\\EN"}, std::set<RTLIL::IdString>(), true);
}
diff --git a/kernel/consteval.h b/kernel/consteval.h
index f995c9cc..7423f950 100644
--- a/kernel/consteval.h
+++ b/kernel/consteval.h
@@ -155,6 +155,31 @@ struct ConstEval
else
set(sig_y, y_values.front());
}
+ else if (cell->type == "$fa")
+ {
+ RTLIL::SigSpec sig_c = cell->getPort("\\C");
+ RTLIL::SigSpec sig_x = cell->getPort("\\X");
+ int width = SIZE(sig_c);
+
+ if (!eval(sig_a, undef, cell))
+ return false;
+
+ if (!eval(sig_b, undef, cell))
+ return false;
+
+ if (!eval(sig_c, undef, cell))
+ return false;
+
+ RTLIL::Const t1 = const_xor(sig_a.as_const(), sig_b.as_const(), false, false, width);
+ RTLIL::Const val_y = const_xor(t1, sig_c.as_const(), false, false, width);
+
+ RTLIL::Const t2 = const_and(sig_a.as_const(), sig_b.as_const(), false, false, width);
+ RTLIL::Const t3 = const_and(sig_c.as_const(), t1, false, false, width);
+ RTLIL::Const val_x = const_or(t2, t3, false, false, width);
+
+ set(sig_y, val_y);
+ set(sig_x, val_x);
+ }
else if (cell->type == "$alu")
{
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 97a2946a..b5cede8b 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -620,6 +620,16 @@ namespace {
return;
}
+ if (cell->type == "$fa") {
+ port("\\A", param("\\WIDTH"));
+ port("\\B", param("\\WIDTH"));
+ port("\\C", param("\\WIDTH"));
+ port("\\X", param("\\WIDTH"));
+ port("\\Y", param("\\WIDTH"));
+ check_expected();
+ return;
+ }
+
if (cell->type == "$alu") {
param_bool("\\A_SIGNED");
param_bool("\\B_SIGNED");
@@ -1793,6 +1803,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
return;
}
+ if (type == "$fa") {
+ parameters["\\WIDTH"] = SIZE(connections_["\\Y"]);
+ return;
+ }
+
bool signedness_ab = !type.in("$slice", "$concat", "$macc");
if (connections_.count("\\A")) {
diff --git a/kernel/satgen.h b/kernel/satgen.h
index 3429f823..4aabe437 100644
--- a/kernel/satgen.h
+++ b/kernel/satgen.h
@@ -963,6 +963,55 @@ struct SatGen
return true;
}
+ if (cell->type == "$fa")
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
+ std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
+ std::vector<int> c = importDefSigSpec(cell->getPort("\\C"), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+ std::vector<int> x = importDefSigSpec(cell->getPort("\\X"), timestep);
+
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ std::vector<int> xx = model_undef ? ez->vec_var(x.size()) : x;
+
+ std::vector<int> t1 = ez->vec_xor(a, b);
+ ez->assume(ez->vec_eq(yy, ez->vec_xor(t1, c)));
+
+ std::vector<int> t2 = ez->vec_and(a, b);
+ std::vector<int> t3 = ez->vec_and(c, t1);
+ ez->assume(ez->vec_eq(xx, ez->vec_or(t2, t3)));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
+ std::vector<int> undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep);
+ std::vector<int> undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep);
+
+ std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep);
+ std::vector<int> undef_x = importUndefSigSpec(cell->getPort("\\X"), timestep);
+
+ ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c)));
+
+ std::vector<int> undef_t1 = ez->vec_or(undef_a, undef_b);
+
+ 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> undef_t2 = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0)));
+
+ std::vector<int> c0 = ez->vec_and(ez->vec_not(c), ez->vec_not(undef_c));
+ std::vector<int> t10 = ez->vec_and(ez->vec_not(t1), ez->vec_not(undef_t1));
+ std::vector<int> undef_t3 = ez->vec_and(ez->vec_or(undef_c, undef_t1), ez->vec_not(ez->vec_or(c0, t10)));
+
+ std::vector<int> t21 = ez->vec_and(t2, ez->vec_not(undef_t2));
+ std::vector<int> t31 = ez->vec_and(t3, ez->vec_not(undef_t3));
+ ez->assume(ez->vec_eq(undef_x, ez->vec_and(ez->vec_or(undef_t2, undef_t3), ez->vec_not(ez->vec_or(t21, t31)))));
+
+ undefGating(y, yy, undef_y);
+ undefGating(x, xx, undef_x);
+ }
+ return true;
+ }
+
if (cell->type == "$alu")
{
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);