Merge remote-tracking branch 'origin/master' into eddie/cleanup

This commit is contained in:
Eddie Hung 2019-08-07 11:11:50 -07:00
commit e6d5147214
19 changed files with 880 additions and 384 deletions

View File

@ -17,6 +17,8 @@ Yosys 0.9 .. Yosys 0.9-dev
- Added automatic gzip decompression for frontends - Added automatic gzip decompression for frontends
- Added $_NMUX_ cell type - Added $_NMUX_ cell type
- Added automatic gzip compression (based on filename extension) for backends - Added automatic gzip compression (based on filename extension) for backends
- Improve attribute and parameter encoding in JSON to avoid ambiguities between
bit vectors and strings containing [01xz]*
Yosys 0.8 .. Yosys 0.8-dev Yosys 0.8 .. Yosys 0.8-dev
-------------------------- --------------------------

View File

@ -381,10 +381,10 @@ struct FirrtlWorker
// Given an expression for a shift amount, and a maximum width, // Given an expression for a shift amount, and a maximum width,
// generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics. // generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics.
std::string gen_dshl(const string b_expr, const int b_padded_width) std::string gen_dshl(const string b_expr, const int b_width)
{ {
string result = b_expr; string result = b_expr;
if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) { if (b_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) {
int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1; int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1;
string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<<max_shift_width_bits) - 1); string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<<max_shift_width_bits) - 1);
// Deal with the difference in semantics between FIRRTL and verilog // Deal with the difference in semantics between FIRRTL and verilog
@ -422,22 +422,33 @@ struct FirrtlWorker
for (auto cell : module->cells()) for (auto cell : module->cells())
{ {
bool extract_y_bits = false; // Assume no extraction of final bits will be required. static Const ndef(0, 0);
// Is this cell is a module instance? // Is this cell is a module instance?
if (cell->type[0] != '$') if (cell->type[0] != '$')
{ {
process_instance(cell, wire_exprs); process_instance(cell, wire_exprs);
continue; continue;
} }
// Not a module instance. Set up cell properties
bool extract_y_bits = false; // Assume no extraction of final bits will be required.
int a_width = cell->parameters.at("\\A_WIDTH", ndef).as_int(); // The width of "A"
int b_width = cell->parameters.at("\\B_WIDTH", ndef).as_int(); // The width of "A"
const int y_width = cell->parameters.at("\\Y_WIDTH", ndef).as_int(); // The width of the result
const bool a_signed = cell->parameters.at("\\A_SIGNED", ndef).as_bool();
const bool b_signed = cell->parameters.at("\\B_SIGNED", ndef).as_bool();
bool firrtl_is_signed = a_signed; // The result is signed (subsequent code may change this).
int firrtl_width = 0;
string primop;
bool always_uint = false;
string y_id = make_id(cell->name);
if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor"))
{ {
string y_id = make_id(cell->name);
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A")); string a_expr = make_expr(cell->getPort("\\A"));
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->parameters.at("\\A_SIGNED").as_bool()) { if (a_signed) {
a_expr = "asSInt(" + a_expr + ")"; a_expr = "asSInt(" + a_expr + ")";
} }
@ -446,12 +457,13 @@ struct FirrtlWorker
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
} }
string primop; // Assume the FIRRTL width is a single bit.
bool always_uint = false; firrtl_width = 1;
if (cell->type == "$not") primop = "not"; if (cell->type == "$not") primop = "not";
else if (cell->type == "$neg") { else if (cell->type == "$neg") {
primop = "neg"; primop = "neg";
is_signed = true; // Result of "neg" is signed (an SInt). firrtl_is_signed = true; // Result of "neg" is signed (an SInt).
firrtl_width = a_width;
} else if (cell->type == "$logic_not") { } else if (cell->type == "$logic_not") {
primop = "eq"; primop = "eq";
a_expr = stringf("%s, UInt(0)", a_expr.c_str()); a_expr = stringf("%s, UInt(0)", a_expr.c_str());
@ -466,14 +478,12 @@ struct FirrtlWorker
else if (cell->type == "$reduce_bool") { else if (cell->type == "$reduce_bool") {
primop = "neq"; primop = "neq";
// Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
int a_width = cell->parameters.at("\\A_WIDTH").as_int();
a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width); a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width);
} }
string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str()); string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str());
if ((is_signed && !always_uint)) if ((firrtl_is_signed && !always_uint))
expr = stringf("asUInt(%s)", expr.c_str()); expr = stringf("asUInt(%s)", expr.c_str());
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
@ -481,81 +491,121 @@ struct FirrtlWorker
continue; continue;
} }
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx", if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx",
"$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
"$logic_and", "$logic_or")) "$logic_and", "$logic_or", "$pow"))
{ {
string y_id = make_id(cell->name);
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A")); string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->parameters.at("\\A_SIGNED").as_bool()) { if (a_signed) {
a_expr = "asSInt(" + a_expr + ")"; a_expr = "asSInt(" + a_expr + ")";
} // Expand the "A" operand to the result width
// Shift amount is always unsigned, and needn't be padded to result width. if (a_width < y_width) {
if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) { a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
if (cell->parameters.at("\\B_SIGNED").as_bool()) { a_width = y_width;
b_expr = "asSInt(" + b_expr + ")";
} }
if (b_padded_width < y_width) { }
auto b_sig = cell->getPort("\\B"); // Shift amount is always unsigned, and needn't be padded to result width,
b_padded_width = y_width; // otherwise, we need to cast the b_expr appropriately
if (b_signed && !cell->type.in("$shr", "$sshr", "$shl", "$sshl", "$pow")) {
b_expr = "asSInt(" + b_expr + ")";
// Expand the "B" operand to the result width
if (b_width < y_width) {
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
b_width = y_width;
} }
} }
// For the arithmetic ops, expand operand widths to result widths befor performing the operation.
// This corresponds (according to iverilog) to what verilog compilers implement.
if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or"))
{
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
a_width = y_width;
}
if (b_width < y_width) {
b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
b_width = y_width;
}
}
// Assume the FIRRTL width is the width of "A"
firrtl_width = a_width;
auto a_sig = cell->getPort("\\A"); auto a_sig = cell->getPort("\\A");
if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) { if (cell->type == "$add") {
a_expr = "asUInt(" + a_expr + ")"; primop = "add";
firrtl_is_signed = a_signed | b_signed;
firrtl_width = max(a_width, b_width);
} else if (cell->type == "$sub") {
primop = "sub";
firrtl_is_signed = true;
int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0;
int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0;
firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc);
} else if (cell->type == "$mul") {
primop = "mul";
firrtl_is_signed = a_signed | b_signed;
firrtl_width = a_width + b_width;
} else if (cell->type == "$div") {
primop = "div";
firrtl_is_signed = a_signed | b_signed;
firrtl_width = a_width;
} else if (cell->type == "$mod") {
primop = "rem";
firrtl_width = min(a_width, b_width);
} else if (cell->type == "$and") {
primop = "and";
always_uint = true;
firrtl_width = max(a_width, b_width);
} }
string primop;
bool always_uint = false;
if (cell->type == "$add") primop = "add";
else if (cell->type == "$sub") primop = "sub";
else if (cell->type == "$mul") primop = "mul";
else if (cell->type == "$div") primop = "div";
else if (cell->type == "$mod") primop = "rem";
else if (cell->type == "$and") {
primop = "and";
always_uint = true;
}
else if (cell->type == "$or" ) { else if (cell->type == "$or" ) {
primop = "or"; primop = "or";
always_uint = true; always_uint = true;
} firrtl_width = max(a_width, b_width);
}
else if (cell->type == "$xor") { else if (cell->type == "$xor") {
primop = "xor"; primop = "xor";
always_uint = true; always_uint = true;
} firrtl_width = max(a_width, b_width);
}
else if (cell->type == "$xnor") {
primop = "xnor";
always_uint = true;
firrtl_width = max(a_width, b_width);
}
else if ((cell->type == "$eq") | (cell->type == "$eqx")) { else if ((cell->type == "$eq") | (cell->type == "$eqx")) {
primop = "eq"; primop = "eq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$ne") | (cell->type == "$nex")) { else if ((cell->type == "$ne") | (cell->type == "$nex")) {
primop = "neq"; primop = "neq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$gt") { else if (cell->type == "$gt") {
primop = "gt"; primop = "gt";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$ge") { else if (cell->type == "$ge") {
primop = "geq"; primop = "geq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$lt") { else if (cell->type == "$lt") {
primop = "lt"; primop = "lt";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if (cell->type == "$le") { else if (cell->type == "$le") {
primop = "leq"; primop = "leq";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$shl") | (cell->type == "$sshl")) { else if ((cell->type == "$shl") | (cell->type == "$sshl")) {
// FIRRTL will widen the result (y) by the amount of the shift. // FIRRTL will widen the result (y) by the amount of the shift.
// We'll need to offset this by extracting the un-widened portion as Verilog would do. // We'll need to offset this by extracting the un-widened portion as Verilog would do.
@ -564,11 +614,14 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B"); auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) { if (b_sig.is_fully_const()) {
primop = "shl"; primop = "shl";
b_expr = std::to_string(b_sig.as_int()); int shift_amount = b_sig.as_int();
b_expr = std::to_string(shift_amount);
firrtl_width = a_width + shift_amount;
} else { } else {
primop = "dshl"; primop = "dshl";
// Convert from FIRRTL left shift semantics. // Convert from FIRRTL left shift semantics.
b_expr = gen_dshl(b_expr, b_padded_width); b_expr = gen_dshl(b_expr, b_width);
firrtl_width = a_width + (1 << b_width) - 1;
} }
} }
else if ((cell->type == "$shr") | (cell->type == "$sshr")) { else if ((cell->type == "$shr") | (cell->type == "$sshr")) {
@ -578,36 +631,86 @@ struct FirrtlWorker
auto b_sig = cell->getPort("\\B"); auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) { if (b_sig.is_fully_const()) {
primop = "shr"; primop = "shr";
b_expr = std::to_string(b_sig.as_int()); int shift_amount = b_sig.as_int();
b_expr = std::to_string(shift_amount);
firrtl_width = max(1, a_width - shift_amount);
} else { } else {
primop = "dshr"; primop = "dshr";
firrtl_width = a_width;
}
// We'll need to do some special fixups if the source (and thus result) is signed.
if (firrtl_is_signed) {
// If this is a "logical" shift right, pretend the source is unsigned.
if (cell->type == "$shr") {
a_expr = "asUInt(" + a_expr + ")";
}
} }
} }
else if ((cell->type == "$logic_and")) { else if ((cell->type == "$logic_and")) {
primop = "and"; primop = "and";
a_expr = "neq(" + a_expr + ", UInt(0))"; a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$logic_or")) { else if ((cell->type == "$logic_or")) {
primop = "or"; primop = "or";
a_expr = "neq(" + a_expr + ", UInt(0))"; a_expr = "neq(" + a_expr + ", UInt(0))";
b_expr = "neq(" + b_expr + ", UInt(0))"; b_expr = "neq(" + b_expr + ", UInt(0))";
always_uint = true; always_uint = true;
} firrtl_width = 1;
}
else if ((cell->type == "$pow")) {
if (a_sig.is_fully_const() && a_sig.as_int() == 2) {
// We'll convert this to a shift. To simplify things, change the a_expr to "1"
// so we can use b_expr directly as a shift amount.
// Only support 2 ** N (i.e., shift left)
// FIRRTL will widen the result (y) by the amount of the shift.
// We'll need to offset this by extracting the un-widened portion as Verilog would do.
a_expr = firrtl_is_signed ? "SInt(1)" : "UInt(1)";
extract_y_bits = true;
// Is the shift amount constant?
auto b_sig = cell->getPort("\\B");
if (b_sig.is_fully_const()) {
primop = "shl";
int shiftAmount = b_sig.as_int();
if (shiftAmount < 0) {
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell));
}
b_expr = std::to_string(shiftAmount);
firrtl_width = a_width + shiftAmount;
} else {
primop = "dshl";
// Convert from FIRRTL left shift semantics.
b_expr = gen_dshl(b_expr, b_width);
firrtl_width = a_width + (1 << b_width) - 1;
}
} else {
log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell));
}
}
if (!cell->parameters.at("\\B_SIGNED").as_bool()) { if (!cell->parameters.at("\\B_SIGNED").as_bool()) {
b_expr = "asUInt(" + b_expr + ")"; b_expr = "asUInt(" + b_expr + ")";
} }
string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); string expr;
// Deal with $xnor == ~^ (not xor)
// Deal with FIRRTL's "shift widens" semantics if (primop == "xnor") {
if (extract_y_bits) { expr = stringf("not(xor(%s, %s))", a_expr.c_str(), b_expr.c_str());
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1); } else {
expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
} }
if ((is_signed && !always_uint) || cell->type.in("$sub")) // Deal with FIRRTL's "shift widens" semantics, or the need to widen the FIRRTL result.
// If the operation is signed, the FIRRTL width will be 1 one bit larger.
if (extract_y_bits) {
expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1);
} else if (firrtl_is_signed && (firrtl_width + 1) < y_width) {
expr = stringf("pad(%s, %d)", expr.c_str(), y_width);
}
if ((firrtl_is_signed && !always_uint))
expr = stringf("asUInt(%s)", expr.c_str()); expr = stringf("asUInt(%s)", expr.c_str());
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
@ -618,7 +721,6 @@ struct FirrtlWorker
if (cell->type.in("$mux")) if (cell->type.in("$mux"))
{ {
string y_id = make_id(cell->name);
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at("\\WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A")); string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
@ -762,15 +864,14 @@ struct FirrtlWorker
if (clkpol == false) if (clkpol == false)
log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell));
string q_id = make_id(cell->name);
int width = cell->parameters.at("\\WIDTH").as_int(); int width = cell->parameters.at("\\WIDTH").as_int();
string expr = make_expr(cell->getPort("\\D")); string expr = make_expr(cell->getPort("\\D"));
string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")"; string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")";
wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", q_id.c_str(), width, clk_expr.c_str())); wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str()));
cell_exprs.push_back(stringf(" %s <= %s\n", q_id.c_str(), expr.c_str())); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
register_reverse_wire_map(q_id, cell->getPort("\\Q")); register_reverse_wire_map(y_id, cell->getPort("\\Q"));
continue; continue;
} }
@ -785,8 +886,6 @@ struct FirrtlWorker
// assign y = a[b +: y_width]; // assign y = a[b +: y_width];
// We'll extract the correct bits as part of the primop. // We'll extract the correct bits as part of the primop.
string y_id = make_id(cell->name);
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A")); string a_expr = make_expr(cell->getPort("\\A"));
// Get the initial bit selector // Get the initial bit selector
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
@ -808,18 +907,15 @@ struct FirrtlWorker
// assign y = a >> b; // assign y = a >> b;
// where b may be negative // where b may be negative
string y_id = make_id(cell->name);
int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
string a_expr = make_expr(cell->getPort("\\A")); string a_expr = make_expr(cell->getPort("\\A"));
string b_expr = make_expr(cell->getPort("\\B")); string b_expr = make_expr(cell->getPort("\\B"));
auto b_string = b_expr.c_str(); auto b_string = b_expr.c_str();
int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
string expr; string expr;
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
if (cell->getParam("\\B_SIGNED").as_bool()) { if (cell->getParam("\\B_SIGNED").as_bool()) {
// We generate a left or right shift based on the sign of b. // We generate a left or right shift based on the sign of b.
std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width); std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width);
std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
expr = stringf("mux(%s < 0, %s, %s)", expr = stringf("mux(%s < 0, %s, %s)",
b_string, b_string,
@ -833,6 +929,20 @@ struct FirrtlWorker
register_reverse_wire_map(y_id, cell->getPort("\\Y")); register_reverse_wire_map(y_id, cell->getPort("\\Y"));
continue; continue;
} }
if (cell->type == "$pos") {
// assign y = a;
// printCell(cell);
string a_expr = make_expr(cell->getPort("\\A"));
// Verilog appears to treat the result as signed, so if the result is wider than "A",
// we need to pad.
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
}
wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), a_expr.c_str()));
register_reverse_wire_map(y_id, cell->getPort("\\Y"));
continue;
}
log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
} }

View File

@ -83,20 +83,43 @@ struct JsonWriter
return str + " ]"; return str + " ]";
} }
void write_parameter_value(const Const &value)
{
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
string str = value.decode_string();
int state = 0;
for (char c : str) {
if (state == 0) {
if (c == '0' || c == '1' || c == 'x' || c == 'z')
state = 0;
else if (c == ' ')
state = 1;
else
state = 2;
} else if (state == 1 && c != ' ')
state = 2;
}
if (state < 2)
str += " ";
f << get_string(str);
} else
if (GetSize(value) == 32 && value.is_fully_def()) {
if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", value.as_int());
else
f << stringf("%u", value.as_int());
} else {
f << get_string(value.as_string());
}
}
void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false) void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false)
{ {
bool first = true; bool first = true;
for (auto &param : parameters) { for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ","); f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str()); f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) write_parameter_value(param.second);
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
else
f << stringf("%u", param.second.as_int());
first = false; first = false;
} }
} }
@ -342,12 +365,13 @@ struct JsonBackend : public Backend {
log("Module and cell ports and nets can be single bit wide or vectors of multiple\n"); log("Module and cell ports and nets can be single bit wide or vectors of multiple\n");
log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n"); log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n");
log("values referenced above are vectors of this integers. Signal bits that are\n"); log("values referenced above are vectors of this integers. Signal bits that are\n");
log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n"); log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n");
log("a number.\n"); log("\"z\" instead of a number.\n");
log("\n"); log("\n");
log("Numeric parameter and attribute values up to 32 bits are written as decimal\n"); log("Numeric 32-bit parameter and attribute values are written as decimal values.\n");
log("values. Numbers larger than that are written as string holding the binary\n"); log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n");
log("representation of the value.\n"); log("as string holding the binary representation of the value. Strings are written\n");
log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n");
log("\n"); log("\n");
log("For example the following Verilog code:\n"); log("For example the following Verilog code:\n");
log("\n"); log("\n");

View File

@ -3439,19 +3439,11 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
{ {
std::map<std::string, AstNode*> backup_scope; std::map<std::string, AstNode*> backup_scope;
std::map<std::string, AstNode::varinfo_t> variables; std::map<std::string, AstNode::varinfo_t> variables;
bool delete_temp_block = false; AstNode *block = new AstNode(AST_BLOCK);
AstNode *block = NULL;
size_t argidx = 0; size_t argidx = 0;
for (auto child : children) for (auto child : children)
{ {
if (child->type == AST_BLOCK)
{
log_assert(block == NULL);
block = child;
continue;
}
if (child->type == AST_WIRE) if (child->type == AST_WIRE)
{ {
while (child->simplify(true, false, false, 1, -1, false, true)) { } while (child->simplify(true, false, false, 1, -1, false, true)) { }
@ -3468,13 +3460,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
continue; continue;
} }
log_assert(block == NULL);
delete_temp_block = true;
block = new AstNode(AST_BLOCK);
block->children.push_back(child->clone()); block->children.push_back(child->clone());
} }
log_assert(block != NULL);
log_assert(variables.count(str) != 0); log_assert(variables.count(str) != 0);
while (!block->children.empty()) while (!block->children.empty())
@ -3642,8 +3630,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
log_abort(); log_abort();
} }
if (delete_temp_block) delete block;
delete block;
for (auto &it : backup_scope) for (auto &it : backup_scope)
if (it.second == NULL) if (it.second == NULL)

View File

@ -25,7 +25,7 @@ struct JsonNode
{ {
char type; // S=String, N=Number, A=Array, D=Dict char type; // S=String, N=Number, A=Array, D=Dict
string data_string; string data_string;
int data_number; int64_t data_number;
vector<JsonNode*> data_array; vector<JsonNode*> data_array;
dict<string, JsonNode*> data_dict; dict<string, JsonNode*> data_dict;
vector<string> data_dict_keys; vector<string> data_dict_keys;
@ -206,6 +206,38 @@ struct JsonNode
} }
}; };
Const json_parse_attr_param_value(JsonNode *node)
{
Const value;
if (node->type == 'S') {
string &s = node->data_string;
size_t cursor = s.find_first_not_of("01xz");
if (cursor == string::npos) {
value = Const::from_string(s);
} else if (s.find_first_not_of(' ', cursor) == string::npos) {
value = Const(s.substr(0, GetSize(s)-1));
} else {
value = Const(s);
}
} else
if (node->type == 'N') {
value = Const(node->data_number, 32);
if (node->data_number < 0)
value.flags |= RTLIL::CONST_FLAG_SIGNED;
} else
if (node->type == 'A') {
log_error("JSON attribute or parameter value is an array.\n");
} else
if (node->type == 'D') {
log_error("JSON attribute or parameter value is a dict.\n");
} else {
log_abort();
}
return value;
}
void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node) void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
{ {
if (node->type != 'D') if (node->type != 'D')
@ -214,28 +246,7 @@ void json_parse_attr_param(dict<IdString, Const> &results, JsonNode *node)
for (auto it : node->data_dict) for (auto it : node->data_dict)
{ {
IdString key = RTLIL::escape_id(it.first.c_str()); IdString key = RTLIL::escape_id(it.first.c_str());
JsonNode *value_node = it.second; Const value = json_parse_attr_param_value(it.second);
Const value;
if (value_node->type == 'S') {
string &s = value_node->data_string;
if (s.find_first_not_of("01xz") == string::npos)
value = Const::from_string(s);
else
value = Const(s);
} else
if (value_node->type == 'N') {
value = Const(value_node->data_number, 32);
} else
if (value_node->type == 'A') {
log_error("JSON attribute or parameter value is an array.\n");
} else
if (value_node->type == 'D') {
log_error("JSON attribute or parameter value is a dict.\n");
} else {
log_abort();
}
results[key] = value; results[key] = value;
} }
} }

View File

@ -24,86 +24,92 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false); struct CellCosts
inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> &parameters = dict<RTLIL::IdString, RTLIL::Const>(),
RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false)
{ {
static dict<RTLIL::IdString, int> gate_cost = { static const dict<RTLIL::IdString, int>& default_gate_cost() {
{ "$_BUF_", 1 }, static const dict<RTLIL::IdString, int> db = {
{ "$_NOT_", 2 }, { "$_BUF_", 1 },
{ "$_AND_", 4 }, { "$_NOT_", 2 },
{ "$_NAND_", 4 }, { "$_AND_", 4 },
{ "$_OR_", 4 }, { "$_NAND_", 4 },
{ "$_NOR_", 4 }, { "$_OR_", 4 },
{ "$_ANDNOT_", 4 }, { "$_NOR_", 4 },
{ "$_ORNOT_", 4 }, { "$_ANDNOT_", 4 },
{ "$_XOR_", 8 }, { "$_ORNOT_", 4 },
{ "$_XNOR_", 8 }, { "$_XOR_", 5 },
{ "$_AOI3_", 6 }, { "$_XNOR_", 5 },
{ "$_OAI3_", 6 }, { "$_AOI3_", 6 },
{ "$_AOI4_", 8 }, { "$_OAI3_", 6 },
{ "$_OAI4_", 8 }, { "$_AOI4_", 7 },
{ "$_MUX_", 4 }, { "$_OAI4_", 7 },
{ "$_NMUX_", 4 } { "$_MUX_", 4 },
}; { "$_NMUX_", 4 }
};
// match costs in "stat -tech cmos" return db;
static dict<RTLIL::IdString, int> cmos_gate_cost = {
{ "$_BUF_", 1 },
{ "$_NOT_", 2 },
{ "$_AND_", 6 },
{ "$_NAND_", 4 },
{ "$_OR_", 6 },
{ "$_NOR_", 4 },
{ "$_ANDNOT_", 6 },
{ "$_ORNOT_", 6 },
{ "$_XOR_", 12 },
{ "$_XNOR_", 12 },
{ "$_AOI3_", 6 },
{ "$_OAI3_", 6 },
{ "$_AOI4_", 8 },
{ "$_OAI4_", 8 },
{ "$_MUX_", 12 },
{ "$_NMUX_", 10 }
};
if (cmos_cost && cmos_gate_cost.count(type))
return cmos_gate_cost.at(type);
if (gate_cost.count(type))
return gate_cost.at(type);
if (parameters.empty() && design && design->module(type))
{
RTLIL::Module *mod = design->module(type);
if (mod->attributes.count("\\cost"))
return mod->attributes.at("\\cost").as_int();
dict<RTLIL::IdString, int> local_mod_cost_cache;
if (mod_cost_cache == nullptr)
mod_cost_cache = &local_mod_cost_cache;
if (mod_cost_cache->count(mod->name))
return mod_cost_cache->at(mod->name);
int module_cost = 1;
for (auto c : mod->cells())
module_cost += get_cell_cost(c, mod_cost_cache);
(*mod_cost_cache)[mod->name] = module_cost;
return module_cost;
} }
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
return 1; static const dict<RTLIL::IdString, int> db = {
} { "$_BUF_", 1 },
{ "$_NOT_", 2 },
{ "$_AND_", 6 },
{ "$_NAND_", 4 },
{ "$_OR_", 6 },
{ "$_NOR_", 4 },
{ "$_ANDNOT_", 6 },
{ "$_ORNOT_", 6 },
{ "$_XOR_", 12 },
{ "$_XNOR_", 12 },
{ "$_AOI3_", 6 },
{ "$_OAI3_", 6 },
{ "$_AOI4_", 8 },
{ "$_OAI4_", 8 },
{ "$_MUX_", 12 },
{ "$_NMUX_", 10 }
};
return db;
}
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache, bool cmos_cost) dict<RTLIL::IdString, int> mod_cost_cache;
{ const dict<RTLIL::IdString, int> *gate_cost = nullptr;
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost); Design *design = nullptr;
}
int get(RTLIL::IdString type) const
{
if (gate_cost && gate_cost->count(type))
return gate_cost->at(type);
log_warning("Can't determine cost of %s cell.\n", log_id(type));
return 1;
}
int get(RTLIL::Cell *cell)
{
if (gate_cost && gate_cost->count(cell->type))
return gate_cost->at(cell->type);
if (design && design->module(cell->type) && cell->parameters.empty())
{
RTLIL::Module *mod = design->module(cell->type);
if (mod->attributes.count("\\cost"))
return mod->attributes.at("\\cost").as_int();
if (mod_cost_cache.count(mod->name))
return mod_cost_cache.at(mod->name);
int module_cost = 1;
for (auto c : mod->cells())
module_cost += get(c);
mod_cost_cache[mod->name] = module_cost;
return module_cost;
}
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
return 1;
}
};
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END

View File

@ -522,6 +522,12 @@ int main(int argc, char **argv)
if (!backend_command.empty()) if (!backend_command.empty())
run_backend(output_filename, backend_command); run_backend(output_filename, backend_command);
yosys_design->check();
for (auto it : saved_designs)
it.second->check();
for (auto it : pushed_designs)
it->check();
if (!depsfile.empty()) if (!depsfile.empty())
{ {
FILE *f = fopen(depsfile.c_str(), "wt"); FILE *f = fopen(depsfile.c_str(), "wt");

View File

@ -295,8 +295,6 @@ void Pass::call(RTLIL::Design *design, std::vector<std::string> args)
pass_register[args[0]]->post_execute(state); pass_register[args[0]]->post_execute(state);
while (design->selection_stack.size() > orig_sel_stack_pos) while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back(); design->selection_stack.pop_back();
design->check();
} }
void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command) void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command)
@ -378,8 +376,10 @@ void ScriptPass::run(std::string command, std::string info)
log(" %s\n", command.c_str()); log(" %s\n", command.c_str());
else else
log(" %s %s\n", command.c_str(), info.c_str()); log(" %s %s\n", command.c_str(), info.c_str());
} else } else {
Pass::call(active_design, command); Pass::call(active_design, command);
active_design->check();
}
} }
void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to) void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to)
@ -573,8 +573,6 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string
args.push_back(filename); args.push_back(filename);
frontend_register[args[0]]->execute(args, design); frontend_register[args[0]]->execute(args, design);
} }
design->check();
} }
Backend::Backend(std::string name, std::string short_help) : Backend::Backend(std::string name, std::string short_help) :
@ -698,8 +696,6 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f
while (design->selection_stack.size() > orig_sel_stack_pos) while (design->selection_stack.size() > orig_sel_stack_pos)
design->selection_stack.pop_back(); design->selection_stack.pop_back();
design->check();
} }
static struct CellHelpMessages { static struct CellHelpMessages {

View File

@ -792,6 +792,7 @@ public:
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(int offset, int length = 1) const; RTLIL::SigSpec extract(int offset, int length = 1) const;
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); }
void append(const RTLIL::SigSpec &signal); void append(const RTLIL::SigSpec &signal);
void append_bit(const RTLIL::SigBit &bit); void append_bit(const RTLIL::SigBit &bit);
@ -838,6 +839,7 @@ public:
operator std::vector<RTLIL::SigChunk>() const { return chunks(); } operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
operator std::vector<RTLIL::SigBit>() const { return bits(); } operator std::vector<RTLIL::SigBit>() const { return bits(); }
RTLIL::SigBit at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
unsigned int hash() const { if (!hash_) updhash(); return hash_; }; unsigned int hash() const { if (!hash_) updhash(); return hash_; };

View File

@ -964,14 +964,18 @@ void run_frontend(std::string filename, std::string command, std::string *backen
command += next_line; command += next_line;
} }
handle_label(command, from_to_active, run_from, run_to); handle_label(command, from_to_active, run_from, run_to);
if (from_to_active) if (from_to_active) {
Pass::call(design, command); Pass::call(design, command);
design->check();
}
} }
if (!command.empty()) { if (!command.empty()) {
handle_label(command, from_to_active, run_from, run_to); handle_label(command, from_to_active, run_from, run_to);
if (from_to_active) if (from_to_active) {
Pass::call(design, command); Pass::call(design, command);
design->check();
}
} }
} }
catch (...) { catch (...) {
@ -1000,6 +1004,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen
Pass::call(design, vector<string>({command, filename})); Pass::call(design, vector<string>({command, filename}));
else else
Frontend::frontend_call(design, NULL, filename, command); Frontend::frontend_call(design, NULL, filename, command);
design->check();
} }
void run_frontend(std::string filename, std::string command, RTLIL::Design *design) void run_frontend(std::string filename, std::string command, RTLIL::Design *design)
@ -1183,6 +1188,7 @@ void shell(RTLIL::Design *design)
design->selection_stack.pop_back(); design->selection_stack.pop_back();
log_reset_stack(); log_reset_stack();
} }
design->check();
} }
if (command == NULL) if (command == NULL)
printf("exit\n"); printf("exit\n");

View File

@ -17,11 +17,10 @@
* *
*/ */
#include "kernel/register.h" #include "kernel/yosys.h"
#include "kernel/celltypes.h" #include "kernel/celltypes.h"
#include "passes/techmap/libparse.h" #include "passes/techmap/libparse.h"
#include "kernel/cost.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
@ -228,25 +227,16 @@ struct statdata_t
{ {
int tran_cnt = 0; int tran_cnt = 0;
bool tran_cnt_exact = true; bool tran_cnt_exact = true;
auto &gate_costs = CellCosts::cmos_gate_cost();
for (auto it : num_cells_by_type) { for (auto it : num_cells_by_type) {
auto ctype = it.first; auto ctype = it.first;
auto cnum = it.second; auto cnum = it.second;
if (ctype == "$_NOT_") if (gate_costs.count(ctype))
tran_cnt += 2*cnum; tran_cnt += cnum * gate_costs.at(ctype);
else if (ctype.in("$_NAND_", "$_NOR_"))
tran_cnt += 4*cnum;
else if (ctype.in("$_AOI3_", "$_OAI3_"))
tran_cnt += 6*cnum;
else if (ctype.in("$_AOI4_", "$_OAI4_"))
tran_cnt += 8*cnum;
else if (ctype.in("$_NMUX_"))
tran_cnt += 10*cnum;
else if (ctype.in("$_MUX_", "$_XOR_", "$_XNOR_"))
tran_cnt += 12*cnum;
else if (ctype.in("$_DFF_P_", "$_DFF_N_")) else if (ctype.in("$_DFF_P_", "$_DFF_N_"))
tran_cnt += 16*cnum; tran_cnt += cnum * 16;
else else
tran_cnt_exact = false; tran_cnt_exact = false;
} }

View File

@ -640,6 +640,31 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
did_something = true; did_something = true;
} }
} }
if (cell->type.in("$add", "$sub")) {
RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
bool sub = cell->type == "$sub";
int i;
for (i = 0; i < GetSize(sig_y); i++) {
if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx)
module->connect(sig_y[i], sig_a[i]);
else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx)
module->connect(sig_y[i], sig_b[i]);
else
break;
}
if (i > 0) {
cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str());
cell->setPort("\\A", sig_a.extract_end(i));
cell->setPort("\\B", sig_b.extract_end(i));
cell->setPort("\\Y", sig_y.extract_end(i));
cell->fixup_parameters();
did_something = true;
}
}
} }
if (cell->type.in("$reduce_xor", "$reduce_xnor", "$shift", "$shiftx", "$shl", "$shr", "$sshl", "$sshr", if (cell->type.in("$reduce_xor", "$reduce_xnor", "$shift", "$shiftx", "$shl", "$shr", "$sshl", "$sshr",

View File

@ -342,9 +342,9 @@ struct WreduceWorker
} }
} }
if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor")) if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub"))
{ {
bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub";
int a_size = 0, b_size = 0; int a_size = 0, b_size = 0;
if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A")); if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A"));
@ -352,7 +352,7 @@ struct WreduceWorker
int max_y_size = max(a_size, b_size); int max_y_size = max(a_size, b_size);
if (cell->type == "$add") if (cell->type.in("$add", "$sub"))
max_y_size++; max_y_size++;
if (cell->type == "$mul") if (cell->type == "$mul")

View File

@ -931,9 +931,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
{ {
log_header(design, "Executing ABC.\n"); log_header(design, "Executing ABC.\n");
auto cell_cost = [](IdString cell_type) { auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
return get_cell_cost(cell_type, dict<RTLIL::IdString, RTLIL::Const>(), nullptr, nullptr, cmos_cost);
};
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt"); f = fopen(buffer.c_str(), "wt");
@ -941,42 +939,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); 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 ZERO 1 Y=CONST0;\n");
fprintf(f, "GATE ONE 1 Y=CONST1;\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", cell_cost("$_BUF_")); fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_BUF_"));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NOT_")); fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOT_"));
if (enabled_gates.empty() || enabled_gates.count("AND")) 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", cell_cost("$_AND_")); fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_AND_"));
if (enabled_gates.empty() || enabled_gates.count("NAND")) 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", cell_cost("$_NAND_")); fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NAND_"));
if (enabled_gates.empty() || enabled_gates.count("OR")) 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", cell_cost("$_OR_")); fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_OR_"));
if (enabled_gates.empty() || enabled_gates.count("NOR")) 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", cell_cost("$_NOR_")); fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOR_"));
if (enabled_gates.empty() || enabled_gates.count("XOR")) 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", cell_cost("$_XOR_")); fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_"));
if (enabled_gates.empty() || enabled_gates.count("XNOR")) 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", cell_cost("$_XNOR_")); fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_"));
if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) 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", cell_cost("$_ANDNOT_")); fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_"));
if (enabled_gates.empty() || enabled_gates.count("ORNOT")) 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", cell_cost("$_ORNOT_")); fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_"));
if (enabled_gates.empty() || enabled_gates.count("AOI3")) 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", cell_cost("$_AOI3_")); fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI3_"));
if (enabled_gates.empty() || enabled_gates.count("OAI3")) 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", cell_cost("$_OAI3_")); fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI3_"));
if (enabled_gates.empty() || enabled_gates.count("AOI4")) 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", cell_cost("$_AOI4_")); fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI4_"));
if (enabled_gates.empty() || enabled_gates.count("OAI4")) 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", cell_cost("$_OAI4_")); fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI4_"));
if (enabled_gates.empty() || enabled_gates.count("MUX")) 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", cell_cost("$_MUX_")); fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_"));
if (enabled_gates.empty() || enabled_gates.count("NMUX")) if (enabled_gates.empty() || enabled_gates.count("NMUX"))
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_NMUX_")); fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_"));
if (map_mux4) 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*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*cell_cost.at("$_MUX_"));
if (map_mux8) 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*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*cell_cost.at("$_MUX_"));
if (map_mux16) 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*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*cell_cost.at("$_MUX_"));
fclose(f); fclose(f);
if (!lut_costs.empty()) { if (!lut_costs.empty()) {

View File

@ -42,10 +42,9 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] AA = A_buf;
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH+1:0] COx; wire [Y_WIDTH+1:0] COx;
wire [Y_WIDTH+1:0] C = {COx, CI}; wire [Y_WIDTH+2:0] C = {COx, CI};
wire dummy; wire dummy;
(* keep *)
AL_MAP_ADDER #( AL_MAP_ADDER #(
.ALUTYPE("ADD_CARRY")) .ALUTYPE("ADD_CARRY"))
adder_cin ( adder_cin (
@ -55,19 +54,6 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
genvar i; genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
if(i==Y_WIDTH-1) begin
(* keep *)
AL_MAP_ADDER #(
.ALUTYPE("ADD"))
adder_cout (
.c(C[Y_WIDTH]),
.o(COx[Y_WIDTH])
);
assign CO = COx[Y_WIDTH];
end
else
begin
(* keep *)
AL_MAP_ADDER #( AL_MAP_ADDER #(
.ALUTYPE("ADD") .ALUTYPE("ADD")
) adder_i ( ) adder_i (
@ -76,9 +62,15 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
.c(C[i+1]), .c(C[i+1]),
.o({COx[i+1],Y[i]}) .o({COx[i+1],Y[i]})
); );
end
end: slice end: slice
endgenerate endgenerate
/* End implementation */ /* End implementation */
AL_MAP_ADDER #(
.ALUTYPE("ADD"))
adder_cout (
.c(C[Y_WIDTH+1]),
.o(COx[Y_WIDTH+1])
);
assign CO = COx[Y_WIDTH+1];
assign X = AA ^ BB; assign X = AA ^ BB;
endmodule endmodule

View File

@ -333,6 +333,31 @@ module TRELLIS_SLICE(
parameter [127:0] CCU2_INJECT1_0 = "NO"; parameter [127:0] CCU2_INJECT1_0 = "NO";
parameter [127:0] CCU2_INJECT1_1 = "NO"; parameter [127:0] CCU2_INJECT1_1 = "NO";
parameter WREMUX = "WRE"; parameter WREMUX = "WRE";
parameter WCKMUX = "WCK";
parameter A0MUX = "A0";
parameter A1MUX = "A1";
parameter B0MUX = "B0";
parameter B1MUX = "B1";
parameter C0MUX = "C0";
parameter C1MUX = "C1";
parameter D0MUX = "D0";
parameter D1MUX = "D1";
wire A0m, B0m, C0m, D0m;
wire A1m, B1m, C1m, D1m;
generate
if (A0MUX == "1") assign A0m = 1'b1; else assign A0m = A0;
if (B0MUX == "1") assign B0m = 1'b1; else assign B0m = B0;
if (C0MUX == "1") assign C0m = 1'b1; else assign C0m = C0;
if (D0MUX == "1") assign D0m = 1'b1; else assign D0m = D0;
if (A1MUX == "1") assign A1m = 1'b1; else assign A1m = A1;
if (B1MUX == "1") assign B1m = 1'b1; else assign B1m = B1;
if (C1MUX == "1") assign C1m = 1'b1; else assign C1m = C1;
if (D1MUX == "1") assign D1m = 1'b1; else assign D1m = D1;
endgenerate
function [15:0] permute_initval; function [15:0] permute_initval;
input [15:0] initval; input [15:0] initval;
@ -350,13 +375,13 @@ module TRELLIS_SLICE(
LUT4 #( LUT4 #(
.INIT(LUT0_INITVAL) .INIT(LUT0_INITVAL)
) lut4_0 ( ) lut4_0 (
.A(A0), .B(B0), .C(C0), .D(D0), .A(A0m), .B(B0m), .C(C0m), .D(D0m),
.Z(F0) .Z(F0)
); );
LUT4 #( LUT4 #(
.INIT(LUT1_INITVAL) .INIT(LUT1_INITVAL)
) lut4_1 ( ) lut4_1 (
.A(A1), .B(B1), .C(C1), .D(D1), .A(A1m), .B(B1m), .C(C1m), .D(D1m),
.Z(F1) .Z(F1)
); );
// LUT expansion muxes // LUT expansion muxes
@ -370,20 +395,20 @@ module TRELLIS_SLICE(
.INJECT1_1(CCU2_INJECT1_1) .INJECT1_1(CCU2_INJECT1_1)
) ccu2c_i ( ) ccu2c_i (
.CIN(FCI), .CIN(FCI),
.A0(A0), .B0(B0), .C0(C0), .D0(D0), .A0(A0m), .B0(B0m), .C0(C0m), .D0(D0m),
.A1(A1), .B1(B1), .C1(C1), .D1(D1), .A1(A1m), .B1(B1m), .C1(C1m), .D1(D1m),
.S0(F0), .S1(F1), .S0(F0), .S1(F1),
.COUT(FCO) .COUT(FCO)
); );
end else if (MODE == "RAMW") begin end else if (MODE == "RAMW") begin
assign WDO0 = C1; assign WDO0 = C1m;
assign WDO1 = A1; assign WDO1 = A1m;
assign WDO2 = D1; assign WDO2 = D1m;
assign WDO3 = B1; assign WDO3 = B1m;
assign WADO0 = D0; assign WADO0 = D0m;
assign WADO1 = B0; assign WADO1 = B0m;
assign WADO2 = C0; assign WADO2 = C0m;
assign WADO3 = A0; assign WADO3 = A0m;
end else if (MODE == "DPRAM") begin end else if (MODE == "DPRAM") begin
TRELLIS_RAM16X2 #( TRELLIS_RAM16X2 #(
.INITVAL_0(permute_initval(LUT0_INITVAL)), .INITVAL_0(permute_initval(LUT0_INITVAL)),
@ -393,17 +418,19 @@ module TRELLIS_SLICE(
.DI0(WD0), .DI1(WD1), .DI0(WD0), .DI1(WD1),
.WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3), .WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3),
.WRE(WRE), .WCK(WCK), .WRE(WRE), .WCK(WCK),
.RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0), .RAD0(D0m), .RAD1(B0m), .RAD2(C0m), .RAD3(A0m),
.DO0(F0), .DO1(F1) .DO0(F0), .DO1(F1)
); );
// TODO: confirm RAD and INITVAL ordering // TODO: confirm RAD and INITVAL ordering
// DPRAM mode contract? // DPRAM mode contract?
`ifdef FORMAL
always @(*) begin always @(*) begin
assert(A0==A1); assert(A0m==A1m);
assert(B0==B1); assert(B0m==B1m);
assert(C0==C1); assert(C0m==C1m);
assert(D0==D1); assert(D0m==D1m);
end end
`endif
end else begin end else begin
ERROR_UNKNOWN_SLICE_MODE error(); ERROR_UNKNOWN_SLICE_MODE error();
end end
@ -455,90 +482,206 @@ module DP16KD(
input CSB2, CSB1, CSB0, input CSB2, CSB1, CSB0,
output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
); );
parameter DATA_WIDTH_A = 18; parameter DATA_WIDTH_A = 18;
parameter DATA_WIDTH_B = 18; parameter DATA_WIDTH_B = 18;
parameter REGMODE_A = "NOREG"; parameter REGMODE_A = "NOREG";
parameter REGMODE_B = "NOREG"; parameter REGMODE_B = "NOREG";
parameter RESETMODE = "SYNC"; parameter RESETMODE = "SYNC";
parameter ASYNC_RESET_RELEASE = "SYNC"; parameter ASYNC_RESET_RELEASE = "SYNC";
parameter CSDECODE_A = "0b000"; parameter CSDECODE_A = "0b000";
parameter CSDECODE_B = "0b000"; parameter CSDECODE_B = "0b000";
parameter WRITEMODE_A = "NORMAL"; parameter WRITEMODE_A = "NORMAL";
parameter WRITEMODE_B = "NORMAL"; parameter WRITEMODE_B = "NORMAL";
parameter CLKAMUX = "CLKA"; parameter DIA17MUX = "DIA17";
parameter CLKBMUX = "CLKB"; parameter DIA16MUX = "DIA16";
parameter DIA15MUX = "DIA15";
parameter DIA14MUX = "DIA14";
parameter DIA13MUX = "DIA13";
parameter DIA12MUX = "DIA12";
parameter DIA11MUX = "DIA11";
parameter DIA10MUX = "DIA10";
parameter DIA9MUX = "DIA9";
parameter DIA8MUX = "DIA8";
parameter DIA7MUX = "DIA7";
parameter DIA6MUX = "DIA6";
parameter DIA5MUX = "DIA5";
parameter DIA4MUX = "DIA4";
parameter DIA3MUX = "DIA3";
parameter DIA2MUX = "DIA2";
parameter DIA1MUX = "DIA1";
parameter DIA0MUX = "DIA0";
parameter ADA13MUX = "ADA13";
parameter ADA12MUX = "ADA12";
parameter ADA11MUX = "ADA11";
parameter ADA10MUX = "ADA10";
parameter ADA9MUX = "ADA9";
parameter ADA8MUX = "ADA8";
parameter ADA7MUX = "ADA7";
parameter ADA6MUX = "ADA6";
parameter ADA5MUX = "ADA5";
parameter ADA4MUX = "ADA4";
parameter ADA3MUX = "ADA3";
parameter ADA2MUX = "ADA2";
parameter ADA1MUX = "ADA1";
parameter ADA0MUX = "ADA0";
parameter CEAMUX = "CEA";
parameter OCEAMUX = "OCEA";
parameter CLKAMUX = "CLKA";
parameter WEAMUX = "WEA";
parameter RSTAMUX = "RSTA";
parameter CSA2MUX = "CSA2";
parameter CSA1MUX = "CSA1";
parameter CSA0MUX = "CSA0";
parameter DOA17MUX = "DOA17";
parameter DOA16MUX = "DOA16";
parameter DOA15MUX = "DOA15";
parameter DOA14MUX = "DOA14";
parameter DOA13MUX = "DOA13";
parameter DOA12MUX = "DOA12";
parameter DOA11MUX = "DOA11";
parameter DOA10MUX = "DOA10";
parameter DOA9MUX = "DOA9";
parameter DOA8MUX = "DOA8";
parameter DOA7MUX = "DOA7";
parameter DOA6MUX = "DOA6";
parameter DOA5MUX = "DOA5";
parameter DOA4MUX = "DOA4";
parameter DOA3MUX = "DOA3";
parameter DOA2MUX = "DOA2";
parameter DOA1MUX = "DOA1";
parameter DOA0MUX = "DOA0";
parameter DIB17MUX = "DIB17";
parameter DIB16MUX = "DIB16";
parameter DIB15MUX = "DIB15";
parameter DIB14MUX = "DIB14";
parameter DIB13MUX = "DIB13";
parameter DIB12MUX = "DIB12";
parameter DIB11MUX = "DIB11";
parameter DIB10MUX = "DIB10";
parameter DIB9MUX = "DIB9";
parameter DIB8MUX = "DIB8";
parameter DIB7MUX = "DIB7";
parameter DIB6MUX = "DIB6";
parameter DIB5MUX = "DIB5";
parameter DIB4MUX = "DIB4";
parameter DIB3MUX = "DIB3";
parameter DIB2MUX = "DIB2";
parameter DIB1MUX = "DIB1";
parameter DIB0MUX = "DIB0";
parameter ADB13MUX = "ADB13";
parameter ADB12MUX = "ADB12";
parameter ADB11MUX = "ADB11";
parameter ADB10MUX = "ADB10";
parameter ADB9MUX = "ADB9";
parameter ADB8MUX = "ADB8";
parameter ADB7MUX = "ADB7";
parameter ADB6MUX = "ADB6";
parameter ADB5MUX = "ADB5";
parameter ADB4MUX = "ADB4";
parameter ADB3MUX = "ADB3";
parameter ADB2MUX = "ADB2";
parameter ADB1MUX = "ADB1";
parameter ADB0MUX = "ADB0";
parameter CEBMUX = "CEB";
parameter OCEBMUX = "OCEB";
parameter CLKBMUX = "CLKB";
parameter WEBMUX = "WEB";
parameter RSTBMUX = "RSTB";
parameter CSB2MUX = "CSB2";
parameter CSB1MUX = "CSB1";
parameter CSB0MUX = "CSB0";
parameter DOB17MUX = "DOB17";
parameter DOB16MUX = "DOB16";
parameter DOB15MUX = "DOB15";
parameter DOB14MUX = "DOB14";
parameter DOB13MUX = "DOB13";
parameter DOB12MUX = "DOB12";
parameter DOB11MUX = "DOB11";
parameter DOB10MUX = "DOB10";
parameter DOB9MUX = "DOB9";
parameter DOB8MUX = "DOB8";
parameter DOB7MUX = "DOB7";
parameter DOB6MUX = "DOB6";
parameter DOB5MUX = "DOB5";
parameter DOB4MUX = "DOB4";
parameter DOB3MUX = "DOB3";
parameter DOB2MUX = "DOB2";
parameter DOB1MUX = "DOB1";
parameter DOB0MUX = "DOB0";
parameter GSR = "ENABLED"; parameter WID = 0;
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter GSR = "ENABLED";
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
endmodule endmodule
// TODO: Diamond flip-flops // TODO: Diamond flip-flops

View File

@ -1,10 +1,12 @@
# This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures. # This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures.
arraycells.v inst id[0] of arraycells.v inst id[0] of
defvalue.sv Initial value not supported
dff_different_styles.v dff_different_styles.v
dff_init.v Initial value not supported dff_init.v Initial value not supported
generate.v combinational loop generate.v combinational loop
hierdefparam.v inst id[0] of hierdefparam.v inst id[0] of
i2c_master_tests.v $adff i2c_master_tests.v $adff
implicit_ports.v not fully initialized
macros.v drops modules macros.v drops modules
mem2reg.v drops modules mem2reg.v drops modules
mem_arst.v $adff mem_arst.v $adff
@ -12,7 +14,6 @@ memory.v $adff
multiplier.v inst id[0] of multiplier.v inst id[0] of
muxtree.v drops modules muxtree.v drops modules
omsp_dbg_uart.v $adff omsp_dbg_uart.v $adff
operators.v $pow
partsel.v drops modules partsel.v drops modules
process.v drops modules process.v drops modules
realexpr.v drops modules realexpr.v drops modules
@ -23,5 +24,6 @@ specify.v no code (empty module generates error
subbytes.v $adff subbytes.v $adff
task_func.v drops modules task_func.v drops modules
values.v combinational loop values.v combinational loop
wandwor.v Invalid connect to an expression that is not a reference or a WritePort.
vloghammer.v combinational loop vloghammer.v combinational loop
wreduce.v original verilog issues ( -x where x isn't declared signed) wreduce.v original verilog issues ( -x where x isn't declared signed)

148
tests/various/opt_expr.ys Normal file
View File

@ -0,0 +1,148 @@
read_verilog <<EOT
module opt_expr_add_test(input [3:0] i, input [7:0] j, output [8:0] o);
assign o = (i << 4) + j;
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr -fine
wreduce
select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
##########
read_verilog <<EOT
module opt_expr_add_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
assign o = (i << 4) + j;
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr -fine
wreduce
select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
##########
read_verilog <<EOT
module opt_expr_sub_test1(input [3:0] i, input [7:0] j, output [8:0] o);
assign o = j - (i << 4);
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr -fine
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
##########
read_verilog <<EOT
module opt_expr_sub_signed_test1(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
assign o = j - (i << 4);
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr -fine
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
##########
read_verilog <<EOT
module opt_expr_sub_test2(input [3:0] i, input [7:0] j, output [8:0] o);
assign o = (i << 4) - j;
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr -fine
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
##########
read_verilog <<EOT
module opt_expr_sub_test4(input [3:0] i, output [8:0] o);
assign o = 5'b00010 - i;
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr -fine
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter

48
tests/various/wreduce.ys Normal file
View File

@ -0,0 +1,48 @@
read_verilog <<EOT
module wreduce_sub_test(input [3:0] i, input [7:0] j, output [8:0] o);
assign o = (j >> 4) - i;
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
##########
read_verilog <<EOT
module wreduce_sub_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
assign o = (j >>> 4) - i;
endmodule
EOT
hierarchy -auto-top
proc
design -save gold
opt_expr
wreduce
dump
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
design -import gold -as gold
design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter