mirror of https://github.com/YosysHQ/yosys.git
Added "$fa" cell type
This commit is contained in:
parent
1a88e47396
commit
d46bac3305
|
@ -106,6 +106,7 @@ struct CellTypes
|
||||||
setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
|
setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true);
|
||||||
|
|
||||||
setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, 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);
|
setup_type("$assert", {"\\A", "\\EN"}, std::set<RTLIL::IdString>(), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,31 @@ struct ConstEval
|
||||||
else
|
else
|
||||||
set(sig_y, y_values.front());
|
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")
|
else if (cell->type == "$alu")
|
||||||
{
|
{
|
||||||
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
|
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
|
||||||
|
|
|
@ -620,6 +620,16 @@ namespace {
|
||||||
return;
|
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") {
|
if (cell->type == "$alu") {
|
||||||
param_bool("\\A_SIGNED");
|
param_bool("\\A_SIGNED");
|
||||||
param_bool("\\B_SIGNED");
|
param_bool("\\B_SIGNED");
|
||||||
|
@ -1793,6 +1803,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == "$fa") {
|
||||||
|
parameters["\\WIDTH"] = SIZE(connections_["\\Y"]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool signedness_ab = !type.in("$slice", "$concat", "$macc");
|
bool signedness_ab = !type.in("$slice", "$concat", "$macc");
|
||||||
|
|
||||||
if (connections_.count("\\A")) {
|
if (connections_.count("\\A")) {
|
||||||
|
|
|
@ -963,6 +963,55 @@ struct SatGen
|
||||||
return true;
|
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")
|
if (cell->type == "$alu")
|
||||||
{
|
{
|
||||||
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
|
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
|
||||||
|
|
|
@ -106,12 +106,20 @@ struct MaccmapWorker
|
||||||
in2 = in2.extract(start_index, stop_index-start_index);
|
in2 = in2.extract(start_index, stop_index-start_index);
|
||||||
in3 = in3.extract(start_index, stop_index-start_index);
|
in3 = in3.extract(start_index, stop_index-start_index);
|
||||||
|
|
||||||
RTLIL::SigSpec t1 = module->Xor(NEW_ID, in1, in2);
|
int width = SIZE(in1);
|
||||||
out1 = {out_zeros_msb, module->Xor(NEW_ID, t1, in3), out_zeros_lsb};
|
RTLIL::Wire *w1 = module->addWire(NEW_ID, width);
|
||||||
|
RTLIL::Wire *w2 = module->addWire(NEW_ID, width);
|
||||||
|
|
||||||
RTLIL::SigSpec t2 = module->And(NEW_ID, in1, in2);
|
RTLIL::Cell *cell = module->addCell(NEW_ID, "$fa");
|
||||||
RTLIL::SigSpec t3 = module->And(NEW_ID, in3, t1);
|
cell->setParam("\\WIDTH", width);
|
||||||
out2 = {out_zeros_msb, module->Or(NEW_ID, t2, t3), out_zeros_lsb};
|
cell->setPort("\\A", in1);
|
||||||
|
cell->setPort("\\B", in2);
|
||||||
|
cell->setPort("\\C", in3);
|
||||||
|
cell->setPort("\\Y", w1);
|
||||||
|
cell->setPort("\\X", w2);
|
||||||
|
|
||||||
|
out1 = {out_zeros_msb, w1, out_zeros_lsb};
|
||||||
|
out2 = {out_zeros_msb, w2, out_zeros_lsb};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +206,8 @@ struct MaccmapWorker
|
||||||
summands.swap(new_summands);
|
summands.swap(new_summands);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_assert(tree_sum_bits.empty());
|
||||||
|
|
||||||
return module->Add(NEW_ID, summands.front(), summands.back());
|
return module->Add(NEW_ID, summands.front(), summands.back());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,6 +39,36 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
|
||||||
RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
|
RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
|
||||||
RTLIL::Wire *wire;
|
RTLIL::Wire *wire;
|
||||||
|
|
||||||
|
if (cell_type == "$fa")
|
||||||
|
{
|
||||||
|
int width = 1 + xorshift32(8);
|
||||||
|
|
||||||
|
wire = module->addWire("\\A");
|
||||||
|
wire->width = width;
|
||||||
|
wire->port_input = true;
|
||||||
|
cell->setPort("\\A", wire);
|
||||||
|
|
||||||
|
wire = module->addWire("\\B");
|
||||||
|
wire->width = width;
|
||||||
|
wire->port_input = true;
|
||||||
|
cell->setPort("\\B", wire);
|
||||||
|
|
||||||
|
wire = module->addWire("\\C");
|
||||||
|
wire->width = width;
|
||||||
|
wire->port_input = true;
|
||||||
|
cell->setPort("\\C", wire);
|
||||||
|
|
||||||
|
wire = module->addWire("\\X");
|
||||||
|
wire->width = width;
|
||||||
|
wire->port_output = true;
|
||||||
|
cell->setPort("\\X", wire);
|
||||||
|
|
||||||
|
wire = module->addWire("\\Y");
|
||||||
|
wire->width = width;
|
||||||
|
wire->port_output = true;
|
||||||
|
cell->setPort("\\Y", wire);
|
||||||
|
}
|
||||||
|
|
||||||
if (cell_type == "$macc")
|
if (cell_type == "$macc")
|
||||||
{
|
{
|
||||||
Macc macc;
|
Macc macc;
|
||||||
|
@ -603,6 +633,7 @@ struct TestCellPass : public Pass {
|
||||||
cell_types["$lut"] = "*";
|
cell_types["$lut"] = "*";
|
||||||
cell_types["$alu"] = "ABSY";
|
cell_types["$alu"] = "ABSY";
|
||||||
cell_types["$macc"] = "*";
|
cell_types["$macc"] = "*";
|
||||||
|
cell_types["$fa"] = "*";
|
||||||
|
|
||||||
for (; argidx < SIZE(args); argidx++)
|
for (; argidx < SIZE(args); argidx++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -443,6 +443,22 @@ endmodule
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
module \$fa (A, B, C, X, Y);
|
||||||
|
|
||||||
|
parameter WIDTH = 1;
|
||||||
|
|
||||||
|
input [WIDTH-1:0] A, B, C;
|
||||||
|
output [WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
|
wire [WIDTH-1:0] t1, t2, t3;
|
||||||
|
|
||||||
|
assign t1 = A ^ B, t2 = A & B, t3 = C & t1;
|
||||||
|
assign Y = t1 ^ C, X = t2 | t3;
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
module \$alu (A, B, CI, BI, X, Y, CO);
|
module \$alu (A, B, CI, BI, X, Y, CO);
|
||||||
|
|
||||||
parameter A_SIGNED = 0;
|
parameter A_SIGNED = 0;
|
||||||
|
|
|
@ -246,6 +246,18 @@ endmodule
|
||||||
// ALU Infrastructure
|
// ALU Infrastructure
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
module \$fa (A, B, C, X, Y);
|
||||||
|
parameter WIDTH = 1;
|
||||||
|
|
||||||
|
input [WIDTH-1:0] A, B, C;
|
||||||
|
output [WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
|
wire [WIDTH-1:0] t1, t2, t3;
|
||||||
|
|
||||||
|
assign t1 = A ^ B, t2 = A & B, t3 = C & t1;
|
||||||
|
assign Y = t1 ^ C, X = t2 | t3;
|
||||||
|
endmodule
|
||||||
|
|
||||||
module \$__alu_ripple (A, B, CI, X, Y, CO);
|
module \$__alu_ripple (A, B, CI, X, Y, CO);
|
||||||
parameter WIDTH = 1;
|
parameter WIDTH = 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue