Merge remote-tracking branch 'origin/master' into xc7dsp

This commit is contained in:
Eddie Hung 2019-08-07 13:44:08 -07:00
commit e3d898dccb
49 changed files with 1136 additions and 554 deletions

View File

@ -15,6 +15,10 @@ Yosys 0.9 .. Yosys 0.9-dev
- Added "script -scriptwire - Added "script -scriptwire
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable) - "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
- Added automatic gzip decompression for frontends - Added automatic gzip decompression for frontends
- Added $_NMUX_ cell type
- 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

@ -261,7 +261,8 @@ CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS)) LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w" ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc" # TODO: Try to solve pthread linking issue in more appropriate way
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LDFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
EXE = .exe EXE = .exe
else ifeq ($(CONFIG),msys2) else ifeq ($(CONFIG),msys2)
@ -401,7 +402,7 @@ endif
ifeq ($(CONFIG),mxe) ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL CXXFLAGS += -DYOSYS_ENABLE_TCL
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
else else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
ifeq ($(OS), FreeBSD) ifeq ($(OS), FreeBSD)
@ -869,9 +870,11 @@ config-mxe: clean
config-msys2: clean config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf echo 'CONFIG := msys2' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-msys2-64: clean config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-cygwin: clean config-cygwin: clean
echo 'CONFIG := cygwin' > Makefile.conf echo 'CONFIG := cygwin' > Makefile.conf

View File

@ -53,7 +53,7 @@ PRIVATE_NAMESPACE_BEGIN
inline int32_t to_big_endian(int32_t i32) { inline int32_t to_big_endian(int32_t i32) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return __builtin_bswap32(i32); return bswap32(i32);
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return i32; return i32;
#else #else
@ -610,19 +610,18 @@ struct XAigerWriter
std::stringstream h_buffer; std::stringstream h_buffer;
auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
write_h_buffer(1); write_h_buffer(1);
log_debug("ciNum = %zu\n", input_bits.size() + ci_bits.size()); log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits));
write_h_buffer(input_bits.size() + ci_bits.size()); write_h_buffer(input_bits.size() + ci_bits.size());
log_debug("coNum = %zu\n", output_bits.size() + co_bits.size()); log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits));
write_h_buffer(output_bits.size() + co_bits.size()); write_h_buffer(output_bits.size() + co_bits.size());
log_debug("piNum = %zu\n", input_bits.size()); log_debug("piNum = %d\n", GetSize(input_bits));
write_h_buffer(input_bits.size()); write_h_buffer(input_bits.size());
log_debug("poNum = %zu\n", output_bits.size()); log_debug("poNum = %d\n", GetSize(output_bits));
write_h_buffer(output_bits.size()); write_h_buffer(output_bits.size());
log_debug("boxNum = %zu\n", box_list.size()); log_debug("boxNum = %d\n", GetSize(box_list));
write_h_buffer(box_list.size()); write_h_buffer(box_list.size());
RTLIL::Module *holes_module = nullptr; RTLIL::Module *holes_module = module->design->addModule("$__holes__");
holes_module = module->design->addModule("$__holes__");
log_assert(holes_module); log_assert(holes_module);
int port_id = 1; int port_id = 1;
@ -726,20 +725,26 @@ struct XAigerWriter
if (!cell->type.in("$_NOT_", "$_AND_")) if (!cell->type.in("$_NOT_", "$_AND_"))
log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n");
Pass::call(holes_module->design, "clean -purge"); holes_module->design->selection_stack.pop_back();
// Move into a new (temporary) design so that "clean" will only
// operate (and run checks on) this one module
RTLIL::Design *holes_design = new RTLIL::Design;
holes_module->design->modules_.erase(holes_module->name);
holes_design->add(holes_module);
Pass::call(holes_design, "clean -purge");
std::stringstream a_buffer; std::stringstream a_buffer;
XAigerWriter writer(holes_module, true /* holes_mode */); XAigerWriter writer(holes_module, true /* holes_mode */);
writer.write_aiger(a_buffer, false /*ascii_mode*/); writer.write_aiger(a_buffer, false /*ascii_mode*/);
holes_module->design->selection_stack.pop_back(); delete holes_design;
f << "a"; f << "a";
std::string buffer_str = a_buffer.str(); std::string buffer_str = a_buffer.str();
int32_t buffer_size_be = to_big_endian(buffer_str.size()); int32_t buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be)); f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size()); f.write(buffer_str.data(), buffer_str.size());
holes_module->design->remove(holes_module);
log_pop(); log_pop();
} }
@ -772,7 +777,7 @@ struct XAigerWriter
if (output_bits.count(b)) { if (output_bits.count(b)) {
int o = ordered_outputs.at(b); int o = ordered_outputs.at(b);
output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire)); output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire));
continue; continue;
} }

View File

@ -327,6 +327,13 @@ struct BlifDumper
goto internal_cell; goto internal_cell;
} }
if (!config->icells_mode && cell->type == "$_NMUX_") {
f << stringf(".names %s %s %s %s\n0-0 1\n-01 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_FF_") { if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q"))); cstr_init(cell->getPort("\\Q")));

View File

@ -496,7 +496,7 @@ struct BtorWorker
goto okay; goto okay;
} }
if (cell->type.in("$mux", "$_MUX_")) if (cell->type.in("$mux", "$_MUX_", "$_NMUX_"))
{ {
SigSpec sig_a = sigmap(cell->getPort("\\A")); SigSpec sig_a = sigmap(cell->getPort("\\A"));
SigSpec sig_b = sigmap(cell->getPort("\\B")); SigSpec sig_b = sigmap(cell->getPort("\\B"));
@ -511,6 +511,12 @@ struct BtorWorker
int nid = next_nid++; int nid = next_nid++;
btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a); btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a);
if (cell->type == "$_NMUX_") {
int tmp = nid;
nid = next_nid++;
btorf("%d not %d %d\n", nid, sid, tmp);
}
add_nid_sig(nid, sig_y); add_nid_sig(nid, sig_y);
goto okay; goto okay;
} }

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,80 +491,120 @@ 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
if (a_width < y_width) {
a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
a_width = y_width;
} }
// Shift amount is always unsigned, and needn't be padded to result width. }
if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) { // Shift amount is always unsigned, and needn't be padded to result width,
if (cell->parameters.at("\\B_SIGNED").as_bool()) { // 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 + ")"; b_expr = "asSInt(" + b_expr + ")";
} // Expand the "B" operand to the result width
if (b_padded_width < y_width) { if (b_width < y_width) {
auto b_sig = cell->getPort("\\B"); b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
b_padded_width = 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);
string primop; } else if (cell->type == "$sub") {
bool always_uint = false; primop = "sub";
if (cell->type == "$add") primop = "add"; firrtl_is_signed = true;
else if (cell->type == "$sub") primop = "sub"; int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0;
else if (cell->type == "$mul") primop = "mul"; int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0;
else if (cell->type == "$div") primop = "div"; firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc);
else if (cell->type == "$mod") primop = "rem"; } else if (cell->type == "$mul") {
else if (cell->type == "$and") { 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"; primop = "and";
always_uint = true; always_uint = true;
firrtl_width = max(a_width, b_width);
} }
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.
@ -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,9 +631,19 @@ 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")) {
@ -588,26 +651,66 @@ struct FirrtlWorker
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

@ -472,7 +472,7 @@ struct SimplecWorker
return; return;
} }
if (cell->type == "$_MUX_") if (cell->type.in("$_MUX_", "$_NMUX_"))
{ {
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A")); SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B")); SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
@ -484,7 +484,9 @@ struct SimplecWorker
string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0"; string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
// casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933) // casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); string expr = stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr.c_str(),
cell->type == "$_NMUX_" ? "!" : "", b_expr.c_str(),
cell->type == "$_NMUX_" ? "!" : "", a_expr.c_str());
log_assert(y.wire); log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +

View File

@ -510,6 +510,7 @@ struct Smt2Worker
if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))"); if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))");
if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))"); if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))");
if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)"); if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)");
if (cell->type == "$_NMUX_") return export_gate(cell, "(not (ite S B A))");
if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))"); if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))");
if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))"); if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))");
if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))"); if (cell->type == "$_AOI4_") return export_gate(cell, "(not (or (and A B) (and C D)))");

View File

@ -537,6 +537,13 @@ struct SmvWorker
continue; continue;
} }
if (cell->type == "$_NMUX_")
{
definitions.push_back(stringf("%s := !(bool(%s) ? %s : %s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A"))));
continue;
}
if (cell->type == "$_AOI3_") if (cell->type == "$_AOI3_")
{ {
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),

View File

@ -558,6 +558,20 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true; return true;
} }
if (cell->type == "$_NMUX_") {
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y"));
f << stringf(" = !(");
dump_cell_expr_port(f, cell, "S", false);
f << stringf(" ? ");
dump_attributes(f, "", cell->attributes, ' ');
dump_cell_expr_port(f, cell, "B", false);
f << stringf(" : ");
dump_cell_expr_port(f, cell, "A", false);
f << stringf(");\n");
return true;
}
if (cell->type.in("$_AOI3_", "$_OAI3_")) { if (cell->type.in("$_AOI3_", "$_OAI3_")) {
f << stringf("%s" "assign ", indent.c_str()); f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y")); dump_sigspec(f, cell->getPort("\\Y"));

View File

@ -301,7 +301,11 @@ static uint32_t parse_xaiger_literal(std::istream &f)
uint32_t l; uint32_t l;
f.read(reinterpret_cast<char*>(&l), sizeof(l)); f.read(reinterpret_cast<char*>(&l), sizeof(l));
if (f.gcount() != sizeof(l)) if (f.gcount() != sizeof(l))
#if defined(_WIN32) && defined(__MINGW32__)
log_error("Offset %I64d: unable to read literal!\n", static_cast<int64_t>(f.tellg()));
#else
log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg())); log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
#endif
return from_big_endian(l); return from_big_endian(l);
} }
@ -333,7 +337,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
return wire; return wire;
} }
void AigerReader::parse_xaiger() void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
{ {
std::string header; std::string header;
f >> header; f >> header;
@ -369,21 +373,6 @@ void AigerReader::parse_xaiger()
if (n0) if (n0)
module->connect(n0, RTLIL::S0); module->connect(n0, RTLIL::S0);
dict<int,IdString> box_lookup;
for (auto m : design->modules()) {
auto it = m->attributes.find("\\abc_box_id");
if (it == m->attributes.end())
continue;
if (m->name.begins_with("$paramod"))
continue;
auto id = it->second.as_int();
auto r = box_lookup.insert(std::make_pair(id, m->name));
if (!r.second)
log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
log_id(m), id, log_id(r.first->second));
log_assert(r.second);
}
// Parse footer (symbol table, comments, etc.) // Parse footer (symbol table, comments, etc.)
std::string s; std::string s;
bool comment_seen = false; bool comment_seen = false;
@ -982,16 +971,17 @@ void AigerReader::post_process()
} }
module->fixup_ports(); module->fixup_ports();
// Insert into a new (temporary) design so that "clean" will only
// operate (and run checks on) this one module
RTLIL::Design *mapped_design = new RTLIL::Design;
mapped_design->add(module);
Pass::call(mapped_design, "clean");
mapped_design->modules_.erase(module->name);
delete mapped_design;
design->add(module); design->add(module);
design->selection_stack.emplace_back(false);
RTLIL::Selection& sel = design->selection_stack.back();
sel.select(module);
Pass::call(design, "clean");
design->selection_stack.pop_back();
for (auto cell : module->cells().to_vector()) { for (auto cell : module->cells().to_vector()) {
if (cell->type != "$lut") continue; if (cell->type != "$lut") continue;
auto y_port = cell->getPort("\\Y").as_bit(); auto y_port = cell->getPort("\\Y").as_bit();

View File

@ -47,7 +47,7 @@ struct AigerReader
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
void parse_aiger(); void parse_aiger();
void parse_xaiger(); void parse_xaiger(const dict<int,IdString> &box_lookup);
void parse_aiger_ascii(); void parse_aiger_ascii();
void parse_aiger_binary(); void parse_aiger_binary();
void post_process(); void post_process();

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,7 +3630,6 @@ 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)

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

@ -325,6 +325,8 @@ Aig::Aig(Cell *cell)
int A = mk.inport("\\A", i); int A = mk.inport("\\A", i);
int B = mk.inport("\\B", i); int B = mk.inport("\\B", i);
int Y = mk.mux_gate(A, B, S); int Y = mk.mux_gate(A, B, S);
if (cell->type == "$_NMUX_")
Y = mk.not_gate(Y);
mk.outport(Y, "\\Y", i); mk.outport(Y, "\\Y", i);
} }
goto optimize; goto optimize;

View File

@ -193,6 +193,7 @@ struct CellTypes
setup_type("$_ANDNOT_", {A, B}, {Y}, true); setup_type("$_ANDNOT_", {A, B}, {Y}, true);
setup_type("$_ORNOT_", {A, B}, {Y}, true); setup_type("$_ORNOT_", {A, B}, {Y}, true);
setup_type("$_MUX_", {A, B, S}, {Y}, true); setup_type("$_MUX_", {A, B, S}, {Y}, true);
setup_type("$_NMUX_", {A, B, S}, {Y}, true);
setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true); setup_type("$_MUX4_", {A, B, C, D, S, T}, {Y}, true);
setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true); setup_type("$_MUX8_", {A, B, C, D, E, F, G, H, S, T, U}, {Y}, true);
setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true); setup_type("$_MUX16_", {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V}, {Y}, true);

View File

@ -145,7 +145,7 @@ struct ConstEval
if (cell->hasPort("\\B")) if (cell->hasPort("\\B"))
sig_b = cell->getPort("\\B"); sig_b = cell->getPort("\\B");
if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") if (cell->type.in("$mux", "$pmux", "$_MUX_", "$_NMUX_"))
{ {
std::vector<RTLIL::SigSpec> y_candidates; std::vector<RTLIL::SigSpec> y_candidates;
int count_maybe_set_s_bits = 0; int count_maybe_set_s_bits = 0;
@ -175,6 +175,9 @@ struct ConstEval
for (auto &yc : y_candidates) { for (auto &yc : y_candidates) {
if (!eval(yc, undef, cell)) if (!eval(yc, undef, cell))
return false; return false;
if (cell->type == "$_NMUX_")
y_values.push_back(RTLIL::const_not(yc.as_const(), Const(), false, false, GetSize(yc)));
else
y_values.push_back(yc.as_const()); y_values.push_back(yc.as_const());
} }

View File

@ -24,12 +24,10 @@
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr); 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)
{ {
static dict<RTLIL::IdString, int> gate_cost = { static const dict<RTLIL::IdString, int>& default_gate_cost() {
static const dict<RTLIL::IdString, int> db = {
{ "$_BUF_", 1 }, { "$_BUF_", 1 },
{ "$_NOT_", 2 }, { "$_NOT_", 2 },
{ "$_AND_", 4 }, { "$_AND_", 4 },
@ -38,48 +36,80 @@ inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL
{ "$_NOR_", 4 }, { "$_NOR_", 4 },
{ "$_ANDNOT_", 4 }, { "$_ANDNOT_", 4 },
{ "$_ORNOT_", 4 }, { "$_ORNOT_", 4 },
{ "$_XOR_", 8 }, { "$_XOR_", 5 },
{ "$_XNOR_", 8 }, { "$_XNOR_", 5 },
{ "$_AOI3_", 6 },
{ "$_OAI3_", 6 },
{ "$_AOI4_", 7 },
{ "$_OAI4_", 7 },
{ "$_MUX_", 4 },
{ "$_NMUX_", 4 }
};
return db;
}
static const dict<RTLIL::IdString, int>& cmos_gate_cost() {
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 }, { "$_AOI3_", 6 },
{ "$_OAI3_", 6 }, { "$_OAI3_", 6 },
{ "$_AOI4_", 8 }, { "$_AOI4_", 8 },
{ "$_OAI4_", 8 }, { "$_OAI4_", 8 },
{ "$_MUX_", 4 } { "$_MUX_", 12 },
{ "$_NMUX_", 10 }
}; };
return db;
}
if (gate_cost.count(type)) dict<RTLIL::IdString, int> mod_cost_cache;
return gate_cost.at(type); const dict<RTLIL::IdString, int> *gate_cost = nullptr;
Design *design = nullptr;
if (parameters.empty() && design && design->module(type)) int get(RTLIL::IdString type) const
{ {
RTLIL::Module *mod = design->module(type); 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")) if (mod->attributes.count("\\cost"))
return mod->attributes.at("\\cost").as_int(); return mod->attributes.at("\\cost").as_int();
dict<RTLIL::IdString, int> local_mod_cost_cache; if (mod_cost_cache.count(mod->name))
if (mod_cost_cache == nullptr) return mod_cost_cache.at(mod->name);
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; int module_cost = 1;
for (auto c : mod->cells()) for (auto c : mod->cells())
module_cost += get_cell_cost(c, mod_cost_cache); module_cost += get(c);
(*mod_cost_cache)[mod->name] = module_cost; mod_cost_cache[mod->name] = module_cost;
return module_cost; return module_cost;
} }
log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters));
return 1; return 1;
} }
};
inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache)
{
return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache);
}
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

@ -41,6 +41,45 @@ void decompress_gzip(const std::string &filename, std::stringstream &out)
} }
gzclose(gzf); gzclose(gzf);
} }
/*
An output stream that uses a stringbuf to buffer data internally,
using zlib to write gzip-compressed data every time the stream is flushed.
*/
class gzip_ostream : public std::ostream {
public:
gzip_ostream()
{
rdbuf(&outbuf);
}
bool open(const std::string &filename)
{
return outbuf.open(filename);
}
private:
class gzip_streambuf : public std::stringbuf {
public:
gzip_streambuf() { };
bool open(const std::string &filename)
{
gzf = gzopen(filename.c_str(), "wb");
return gzf != nullptr;
}
virtual int sync() override
{
gzwrite(gzf, reinterpret_cast<const void *>(str().c_str()), unsigned(str().size()));
str("");
return 0;
}
~gzip_streambuf()
{
sync();
gzclose(gzf);
}
private:
gzFile gzf = nullptr;
} outbuf;
};
PRIVATE_NAMESPACE_END PRIVATE_NAMESPACE_END
#endif #endif
@ -256,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)
@ -339,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)
@ -534,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) :
@ -588,6 +625,19 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
filename = arg; filename = arg;
rewrite_filename(filename); rewrite_filename(filename);
if (filename.size() > 3 && filename.substr(filename.size()-3) == ".gz") {
#ifdef YOSYS_ENABLE_ZLIB
gzip_ostream *gf = new gzip_ostream;
if (!gf->open(filename)) {
delete gf;
log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
yosys_output_files.insert(filename);
f = gf;
#else
log_cmd_error("Yosys is compiled without zlib support, unable to write gzip output.\n");
#endif
} else {
std::ofstream *ff = new std::ofstream; std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), std::ofstream::trunc); ff->open(filename.c_str(), std::ofstream::trunc);
yosys_output_files.insert(filename); yosys_output_files.insert(filename);
@ -597,6 +647,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
} }
f = ff; f = ff;
} }
}
if (called_with_fp) if (called_with_fp)
args.push_back(filename); args.push_back(filename);
@ -645,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

@ -1249,6 +1249,7 @@ namespace {
if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; } if (cell->type == "$_ANDNOT_") { check_gate("ABY"); return; }
if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; } if (cell->type == "$_ORNOT_") { check_gate("ABY"); return; }
if (cell->type == "$_MUX_") { check_gate("ABSY"); return; } if (cell->type == "$_MUX_") { check_gate("ABSY"); return; }
if (cell->type == "$_NMUX_") { check_gate("ABSY"); return; }
if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; } if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; }
if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; } if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; }
if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; } if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; }
@ -1976,6 +1977,7 @@ DEF_METHOD_3(XnorGate, "$_XNOR_", A, B, Y)
DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y) DEF_METHOD_3(AndnotGate, "$_ANDNOT_", A, B, Y)
DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y) DEF_METHOD_3(OrnotGate, "$_ORNOT_", A, B, Y)
DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, Y) DEF_METHOD_4(MuxGate, "$_MUX_", A, B, S, Y)
DEF_METHOD_4(NmuxGate, "$_NMUX_", A, B, S, Y)
DEF_METHOD_4(Aoi3Gate, "$_AOI3_", A, B, C, Y) DEF_METHOD_4(Aoi3Gate, "$_AOI3_", A, B, C, Y)
DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y) DEF_METHOD_4(Oai3Gate, "$_OAI3_", A, B, C, Y)
DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y) DEF_METHOD_5(Aoi4Gate, "$_AOI4_", A, B, C, D, Y)
@ -3354,13 +3356,7 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
{ {
unpack(); unpack();
cover("kernel.rtlil.sigspec.extract_pos"); cover("kernel.rtlil.sigspec.extract_pos");
auto it = bits_.begin() + std::min<int>(offset, width_); return std::vector<RTLIL::SigBit>(bits_.begin() + offset, bits_.begin() + offset + length);
decltype(it) ie;
if (length >= 0)
ie = bits_.begin() + std::min<int>(offset + length, width_);
else
ie = bits_.end() + std::max<int>(length + 1, offset - width_);
return std::vector<RTLIL::SigBit>(it, ie);
} }
void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal)

View File

@ -788,6 +788,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);
@ -1155,6 +1156,7 @@ public:
RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); RTLIL::Cell* addAndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addOrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = ""); RTLIL::Cell* addOrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = ""); RTLIL::Cell* addMuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addNmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = ""); RTLIL::Cell* addAoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = ""); RTLIL::Cell* addOai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_y, const std::string &src = "");
RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = ""); RTLIL::Cell* addAoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, RTLIL::SigBit sig_y, const std::string &src = "");
@ -1230,6 +1232,7 @@ public:
RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); RTLIL::SigBit AndnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
RTLIL::SigBit OrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = ""); RTLIL::SigBit OrnotGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, const std::string &src = "");
RTLIL::SigBit MuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = ""); RTLIL::SigBit MuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
RTLIL::SigBit NmuxGate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_s, const std::string &src = "");
RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = ""); RTLIL::SigBit Aoi3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
RTLIL::SigBit Oai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = ""); RTLIL::SigBit Oai3Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, const std::string &src = "");
RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = ""); RTLIL::SigBit Aoi4Gate (RTLIL::IdString name, RTLIL::SigBit sig_a, RTLIL::SigBit sig_b, RTLIL::SigBit sig_c, RTLIL::SigBit sig_d, const std::string &src = "");

View File

@ -475,7 +475,7 @@ struct SatGen
return true; return true;
} }
if (cell->type == "$_MUX_" || cell->type == "$mux") if (cell->type == "$_MUX_" || cell->type == "$mux" || cell->type == "$_NMUX_")
{ {
std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep); std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep); std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep);
@ -483,6 +483,9 @@ struct SatGen
std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep); std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y; std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
if (cell->type == "$_NMUX_")
ez->assume(ez->vec_eq(ez->vec_not(ez->vec_ite(s.at(0), b, a)), yy));
else
ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy)); ez->assume(ez->vec_eq(ez->vec_ite(s.at(0), b, a), yy));
if (model_undef) if (model_undef)

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

@ -88,6 +88,10 @@ extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
extern void Tcl_Finalize(void); extern void Tcl_Finalize(void);
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
extern const char *Tcl_GetStringResult(Tcl_Interp *interp); extern const char *Tcl_GetStringResult(Tcl_Interp *interp);
extern Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length);
extern Tcl_Obj *Tcl_NewIntObj(int intValue);
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
# endif # endif
#endif #endif

View File

@ -494,6 +494,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA
\end{fixme} \end{fixme}
\begin{fixme} \begin{fixme}
Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells. Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, {\tt \$\_OAI4\_}, and {\tt \$\_NMUX\_} cells.
\end{fixme} \end{fixme}

View File

@ -61,6 +61,7 @@ SOFTWARE. */
#include <windows.h> #include <windows.h>
#include <tchar.h> #include <tchar.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h>
int child_pid=0; int child_pid=0;
@ -338,7 +339,7 @@ int run(int argc, char **argv, int is_gui) {
if (is_gui) { if (is_gui) {
/* Use exec, we don't need to wait for the GUI to finish */ /* Use exec, we don't need to wait for the GUI to finish */
execv(ptr, (const char * const *)(newargs)); execv(ptr, (char * const *)(newargs));
return fail("Could not exec %s", ptr); /* shouldn't get here! */ return fail("Could not exec %s", ptr); /* shouldn't get here! */
} }

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,21 +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("$_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

@ -641,6 +641,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 == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" || if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" ||

View File

@ -81,7 +81,7 @@ struct OptLutWorker
} }
} }
log("Number of LUTs: %8zu\n", luts.size()); log("Number of LUTs: %8d\n", GetSize(luts));
for (int arity = 1; arity <= max_arity; arity++) for (int arity = 1; arity <= max_arity; arity++)
{ {
if (arity_counts[arity]) if (arity_counts[arity])
@ -351,14 +351,14 @@ struct OptLutWorker
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
if (lutA_dlogic_inputs.size()) if (lutA_dlogic_inputs.size())
log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); log_debug(" Cell A is a %d-LUT with %d dedicated connections. ", lutA_arity, GetSize(lutA_dlogic_inputs));
else else
log_debug(" Cell A is a %d-LUT. ", lutA_arity); log_debug(" Cell A is a %d-LUT. ", lutA_arity);
if (lutB_dlogic_inputs.size()) if (lutB_dlogic_inputs.size())
log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); log_debug("Cell B is a %d-LUT with %d dedicated connections.\n", lutB_arity, GetSize(lutB_dlogic_inputs));
else else
log_debug("Cell B is a %d-LUT.\n", lutB_arity); log_debug("Cell B is a %d-LUT.\n", lutB_arity);
log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); log_debug(" Cells share %d input(s) and can be merged into one %d-LUT.\n", GetSize(common_inputs), lutM_arity);
const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
int combine_mask = 0; int combine_mask = 0;

View File

@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass {
wire->port_output = false; wire->port_output = false;
wire->port_id = 0; wire->port_id = 0;
} }
log("Removed %zu unused ports.\n", unused_ports.size()); log("Removed %d unused ports.\n", GetSize(unused_ports));
// Re-number all of the wires that DO have ports still on them // Re-number all of the wires that DO have ports still on them
for(size_t i=0; i<module->ports.size(); i++) for(size_t i=0; i<module->ports.size(); i++)

View File

@ -365,29 +365,6 @@ struct WreduceWorker
} }
} }
if (cell->type.in("$add", "$sub")) {
SigSpec A = mi.sigmap(cell->getPort("\\A"));
SigSpec B = mi.sigmap(cell->getPort("\\B"));
bool sub = cell->type == "$sub";
int i;
for (i = 0; i < GetSize(sig); i++) {
if (B.at(i, Sx) != S0 && (sub || A.at(i, Sx) != S0))
break;
if (B[i] == S0)
module->connect(sig[i], A[i]);
else if (A[i] == S0)
module->connect(sig[i], B[i]);
else log_abort();
}
if (i > 0) {
cell->setPort("\\A", A.extract(i, -1));
cell->setPort("\\B", B.extract(i, -1));
sig.remove(0, i);
bits_removed += i;
}
}
if (GetSize(sig) == 0) { if (GetSize(sig) == 0) {
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
module->remove(cell); module->remove(cell);
@ -395,7 +372,7 @@ struct WreduceWorker
} }
if (bits_removed) { if (bits_removed) {
log("Removed %d bits (of %d) from port Y of cell %s.%s (%s).\n", log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type));
cell->setPort("\\Y", sig); cell->setPort("\\Y", sig);
did_something = true; did_something = true;

View File

@ -82,14 +82,23 @@ struct PruneWorker
if (root) { if (root) {
bool promotable = true; bool promotable = true;
for (auto &bit : lhs) { for (auto &bit : lhs) {
if (bit.wire && affected[bit]) { if (bit.wire && affected[bit] && !assigned[bit]) {
promotable = false; promotable = false;
break; break;
} }
} }
if (promotable) { if (promotable) {
RTLIL::SigSpec rhs = sigmap(it->second);
RTLIL::SigSig conn;
for (int i = 0; i < GetSize(lhs); i++) {
RTLIL::SigBit lhs_bit = lhs[i];
if (lhs_bit.wire && !assigned[lhs_bit]) {
conn.first.append_bit(lhs_bit);
conn.second.append(rhs.extract(i));
}
}
promoted_count++; promoted_count++;
module->connect(*it); module->connect(conn);
remove.insert(*it); remove.insert(*it);
} }
} }

View File

@ -49,6 +49,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <cctype>
#include <cerrno> #include <cerrno>
#include <sstream> #include <sstream>
#include <climits> #include <climits>
@ -81,6 +82,7 @@ enum class gate_type_t {
G_ANDNOT, G_ANDNOT,
G_ORNOT, G_ORNOT,
G_MUX, G_MUX,
G_NMUX,
G_AOI3, G_AOI3,
G_OAI3, G_OAI3,
G_AOI4, G_AOI4,
@ -111,7 +113,7 @@ std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map; std::map<RTLIL::SigBit, int> signal_map;
std::map<RTLIL::SigBit, RTLIL::State> signal_init; std::map<RTLIL::SigBit, RTLIL::State> signal_init;
pool<std::string> enabled_gates; pool<std::string> enabled_gates;
bool recover_init; bool recover_init, cmos_cost;
bool clk_polarity, en_polarity; bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig; RTLIL::SigSpec clk_sig, en_sig;
@ -257,7 +259,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
return; return;
} }
if (cell->type == "$_MUX_") if (cell->type.in("$_MUX_", "$_NMUX_"))
{ {
RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B"); RTLIL::SigSpec sig_b = cell->getPort("\\B");
@ -273,7 +275,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
int mapped_b = map_signal(sig_b); int mapped_b = map_signal(sig_b);
int mapped_s = map_signal(sig_s); int mapped_s = map_signal(sig_s);
map_signal(sig_y, G(MUX), mapped_a, mapped_b, mapped_s); map_signal(sig_y, cell->type == "$_MUX_" ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
module->remove(cell); module->remove(cell);
return; return;
@ -885,6 +887,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id); fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "1-0 1\n"); fprintf(f, "1-0 1\n");
fprintf(f, "-11 1\n"); fprintf(f, "-11 1\n");
} else if (si.type == G(NMUX)) {
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "0-0 1\n");
fprintf(f, "-01 1\n");
} else if (si.type == G(AOI3)) { } else if (si.type == G(AOI3)) {
fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id); fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "-00 1\n"); fprintf(f, "-00 1\n");
@ -925,46 +931,50 @@ 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 = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_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");
if (f == NULL) if (f == NULL)
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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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", get_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"))
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*get_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*get_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*get_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()) {
@ -1065,8 +1075,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
design->select(module, cell); design->select(module, cell);
continue; continue;
} }
if (c->type == "\\MUX") { if (c->type == "\\MUX" || c->type == "\\NMUX") {
RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_"); RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx; if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)])); cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)])); cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
@ -1409,6 +1419,7 @@ struct AbcPass : public Pass {
log(" cmos2: NAND NOR\n"); log(" cmos2: NAND NOR\n");
log(" cmos3: NAND NOR AOI3 OAI3\n"); log(" cmos3: NAND NOR AOI3 OAI3\n");
log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n"); log(" cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
log(" cmos: NAND NOR AOI3 OAI3 AOI4 OAI4 NMUX MUX XOR XNOR\n");
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n"); log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n"); log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
log("\n"); log("\n");
@ -1488,6 +1499,7 @@ struct AbcPass : public Pass {
map_mux8 = false; map_mux8 = false;
map_mux16 = false; map_mux16 = false;
enabled_gates.clear(); enabled_gates.clear();
cmos_cost = false;
#ifdef _WIN32 #ifdef _WIN32
#ifndef ABCEXTERNAL #ifndef ABCEXTERNAL
@ -1628,11 +1640,15 @@ struct AbcPass : public Pass {
goto ok_alias; goto ok_alias;
} }
if (g == "cmos2") { if (g == "cmos2") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND"); gate_list.push_back("NAND");
gate_list.push_back("NOR"); gate_list.push_back("NOR");
goto ok_alias; goto ok_alias;
} }
if (g == "cmos3") { if (g == "cmos3") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND"); gate_list.push_back("NAND");
gate_list.push_back("NOR"); gate_list.push_back("NOR");
gate_list.push_back("AOI3"); gate_list.push_back("AOI3");
@ -1640,6 +1656,8 @@ struct AbcPass : public Pass {
goto ok_alias; goto ok_alias;
} }
if (g == "cmos4") { if (g == "cmos4") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND"); gate_list.push_back("NAND");
gate_list.push_back("NOR"); gate_list.push_back("NOR");
gate_list.push_back("AOI3"); gate_list.push_back("AOI3");
@ -1648,6 +1666,21 @@ struct AbcPass : public Pass {
gate_list.push_back("OAI4"); gate_list.push_back("OAI4");
goto ok_alias; goto ok_alias;
} }
if (g == "cmos") {
if (!remove_gates)
cmos_cost = true;
gate_list.push_back("NAND");
gate_list.push_back("NOR");
gate_list.push_back("AOI3");
gate_list.push_back("OAI3");
gate_list.push_back("AOI4");
gate_list.push_back("OAI4");
gate_list.push_back("NMUX");
gate_list.push_back("MUX");
gate_list.push_back("XOR");
gate_list.push_back("XNOR");
goto ok_alias;
}
if (g == "gates") { if (g == "gates") {
gate_list.push_back("AND"); gate_list.push_back("AND");
gate_list.push_back("NAND"); gate_list.push_back("NAND");

View File

@ -290,7 +290,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
bool show_tempdir, std::string box_file, std::string lut_file, bool show_tempdir, std::string box_file, std::string lut_file,
std::string wire_delay) std::string wire_delay, const dict<int,IdString> &box_lookup)
{ {
module = current_module; module = current_module;
map_autoidx = autoidx++; map_autoidx = autoidx++;
@ -429,10 +429,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
RTLIL::Selection& sel = design->selection_stack.back(); RTLIL::Selection& sel = design->selection_stack.back();
sel.select(module); sel.select(module);
Pass::call(design, "aigmap");
handle_loops(design); handle_loops(design);
Pass::call(design, "aigmap");
//log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
// count_gates, GetSize(signal_list), count_input, count_output); // count_gates, GetSize(signal_list), count_input, count_output);
@ -476,7 +476,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
} }
module->fixup_ports(); module->fixup_ports();
log_header(design, "Executing ABC9.\n"); log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) { if (!lut_costs.empty()) {
@ -520,8 +519,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym"); buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__")); log_assert(!design->module("$__abc9__"));
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */); AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
reader.parse_xaiger(); reader.parse_xaiger(box_lookup);
ifs.close(); ifs.close();
#if 0 #if 0
@ -646,6 +646,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
} }
else { else {
existing_cell = module->cell(c->name); existing_cell = module->cell(c->name);
log_assert(existing_cell);
cell = module->addCell(remap_name(c->name), c->type); cell = module->addCell(remap_name(c->name), c->type);
module->swap_names(cell, existing_cell); module->swap_names(cell, existing_cell);
} }
@ -1081,6 +1082,21 @@ struct Abc9Pass : public Pass {
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
dict<int,IdString> box_lookup;
for (auto m : design->modules()) {
auto it = m->attributes.find("\\abc_box_id");
if (it == m->attributes.end())
continue;
if (m->name.begins_with("$paramod"))
continue;
auto id = it->second.as_int();
auto r = box_lookup.insert(std::make_pair(id, m->name));
if (!r.second)
log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
log_id(m), id, log_id(r.first->second));
log_assert(r.second);
}
for (auto mod : design->selected_modules()) for (auto mod : design->selected_modules())
{ {
if (mod->attributes.count("\\abc_box_id")) if (mod->attributes.count("\\abc_box_id"))
@ -1096,7 +1112,7 @@ struct Abc9Pass : public Pass {
if (!dff_mode || !clk_str.empty()) { if (!dff_mode || !clk_str.empty()) {
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, lutin_shared, fast_mode, show_tempdir, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay); box_file, lut_file, wire_delay, box_lookup);
continue; continue;
} }
@ -1242,15 +1258,16 @@ struct Abc9Pass : public Pass {
en_sig = assign_map(std::get<3>(it.first)); en_sig = assign_map(std::get<3>(it.first));
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, lutin_shared, fast_mode, show_tempdir, keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
box_file, lut_file, wire_delay); box_file, lut_file, wire_delay, box_lookup);
assign_map.set(mod); assign_map.set(mod);
} }
} }
Pass::call(design, "clean");
assign_map.clear(); assign_map.clear();
// The "clean" pass also contains a design->check() call
Pass::call(design, "clean");
log_pop(); log_pop();
} }
} Abc9Pass; } Abc9Pass;

View File

@ -86,7 +86,7 @@ struct ExtractFaWorker
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
{ {
if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_",
"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_NMUX_",
"$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) "$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
{ {
SigBit y = sigmap(SigBit(cell->getPort("\\Y"))); SigBit y = sigmap(SigBit(cell->getPort("\\Y")));

View File

@ -783,7 +783,7 @@ struct FlowmapWorker
int depth = 0; int depth = 0;
for (auto label : labels) for (auto label : labels)
depth = max(depth, label.second); depth = max(depth, label.second);
log("Mapped to %zu LUTs with maximum depth %d.\n", lut_nodes.size(), depth); log("Mapped to %d LUTs with maximum depth %d.\n", GetSize(lut_nodes), depth);
if (debug) if (debug)
{ {
@ -1195,7 +1195,7 @@ struct FlowmapWorker
bool relax_depth_for_bound(bool first, int depth_bound, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> &lut_critical_outputs) bool relax_depth_for_bound(bool first, int depth_bound, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> &lut_critical_outputs)
{ {
size_t initial_count = lut_nodes.size(); int initial_count = GetSize(lut_nodes);
for (auto node : lut_nodes) for (auto node : lut_nodes)
{ {
@ -1215,7 +1215,7 @@ struct FlowmapWorker
if (potentials.empty()) if (potentials.empty())
{ {
log(" Relaxed to %zu (+%zu) LUTs.\n", lut_nodes.size(), lut_nodes.size() - initial_count); log(" Relaxed to %d (+%d) LUTs.\n", GetSize(lut_nodes), GetSize(lut_nodes) - initial_count);
if (!first && break_num == 1) if (!first && break_num == 1)
{ {
log(" Design fully relaxed.\n"); log(" Design fully relaxed.\n");
@ -1419,9 +1419,9 @@ struct FlowmapWorker
lut_area += lut_table.size(); lut_area += lut_table.size();
if ((int)input_nodes.size() >= minlut) if ((int)input_nodes.size() >= minlut)
log(" Packed into a %zu-LUT %s.%s.\n", input_nodes.size(), log_id(module), log_id(lut)); log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), log_id(module), log_id(lut));
else else
log(" Packed into a %zu-LUT %s.%s (implemented as %d-LUT).\n", input_nodes.size(), log_id(module), log_id(lut), minlut); log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), log_id(module), log_id(lut), minlut);
} }
for (auto node : mapped_nodes) for (auto node : mapped_nodes)

View File

@ -50,7 +50,7 @@ struct AnlogicDetermineInitPass : public Pass {
extra_args(args, args.size(), design); extra_args(args, args.size(), design);
size_t cnt = 0; int cnt = 0;
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
@ -65,7 +65,7 @@ struct AnlogicDetermineInitPass : public Pass {
} }
} }
} }
log_header(design, "Updated %lu cells with determined init value.\n", cnt); log_header(design, "Updated %d cells with determined init value.\n", cnt);
} }
} AnlogicDetermineInitPass; } AnlogicDetermineInitPass;

View File

@ -69,7 +69,7 @@ struct AnlogicEqnPass : public Pass {
extra_args(args, args.size(), design); extra_args(args, args.size(), design);
size_t cnt = 0; int cnt = 0;
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
@ -106,7 +106,7 @@ struct AnlogicEqnPass : public Pass {
} }
} }
} }
log_header(design, "Updated %lu of AL_MAP_LUT* elements with equation.\n", cnt); log_header(design, "Updated %d of AL_MAP_LUT* elements with equation.\n", cnt);
} }
} AnlogicEqnPass; } AnlogicEqnPass;

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

@ -228,6 +228,25 @@ output Y;
assign Y = S ? B : A; assign Y = S ? B : A;
endmodule endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $_NMUX_ (A, B, S, Y)
//-
//- A 2-input inverting MUX gate.
//-
//- Truth table: A B S | Y
//- -------+---
//- 0 - 0 | 1
//- 1 - 0 | 0
//- - 0 1 | 1
//- - 1 1 | 0
//-
module \$_NMUX_ (A, B, S, Y);
input A, B, S;
output Y;
assign Y = S ? !B : !A;
endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//- //-
//- $_MUX4_ (A, B, C, D, S, T, Y) //- $_MUX4_ (A, B, C, D, S, T, Y)

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
@ -470,8 +497,124 @@ module DP16KD(
parameter WRITEMODE_A = "NORMAL"; parameter WRITEMODE_A = "NORMAL";
parameter WRITEMODE_B = "NORMAL"; parameter WRITEMODE_B = "NORMAL";
parameter DIA17MUX = "DIA17";
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 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 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 WID = 0;
parameter GSR = "ENABLED"; parameter GSR = "ENABLED";

View File

@ -50,7 +50,7 @@ struct DetermineInitPass : public Pass {
extra_args(args, args.size(), design); extra_args(args, args.size(), design);
size_t cnt = 0; int cnt = 0;
for (auto module : design->selected_modules()) for (auto module : design->selected_modules())
{ {
for (auto cell : module->selected_cells()) for (auto cell : module->selected_cells())
@ -65,7 +65,7 @@ struct DetermineInitPass : public Pass {
} }
} }
} }
log_header(design, "Updated %lu cells with determined init value.\n", cnt); log_header(design, "Updated %d cells with determined init value.\n", cnt);
} }
} DetermineInitPass; } DetermineInitPass;

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)

View File

@ -1,2 +1,4 @@
/*.log /*.log
/*.out /*.out
/write_gzip.v
/write_gzip.v.gz

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

View File

@ -1,78 +1,5 @@
read_verilog <<EOT read_verilog <<EOT
module wreduce_add_test(input [3:0] i, input [7:0] j, output [8:0] o); module wreduce_sub_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
prep # calls 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 wreduce_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
prep # calls 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_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
prep # calls 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 wreduce_sub_test3(input [3:0] i, input [7:0] j, output [8:0] o);
assign o = (j >> 4) - i; assign o = (j >> 4) - i;
endmodule endmodule
EOT EOT
@ -81,7 +8,8 @@ hierarchy -auto-top
proc proc
design -save gold design -save gold
prep # calls wreduce opt_expr
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
@ -96,8 +24,8 @@ sat -verify -prove-asserts -show-ports miter
########## ##########
read_verilog <<EOT read_verilog <<EOT
module wreduce_sub_test4(input [3:0] i, output [8:0] o); module wreduce_sub_signed_test(input signed [3:0] i, input signed [7:0] j, output signed [8:0] o);
assign o = 5'b00010 - i; assign o = (j >>> 4) - i;
endmodule endmodule
EOT EOT
@ -105,9 +33,11 @@ hierarchy -auto-top
proc proc
design -save gold design -save gold
prep # calls wreduce opt_expr
wreduce
select -assert-count 1 t:$sub r:A_WIDTH=2 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i 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 -stash gate

View File

@ -0,0 +1,16 @@
read -vlog2k <<EOT
module top(input a, output y);
assign y = !a;
endmodule
EOT
prep -top top
write_verilog write_gzip.v.gz
design -reset
! rm -f write_gzip.v
! gunzip write_gzip.v.gz
read -vlog2k write_gzip.v
! rm -f write_gzip.v
hierarchy -top top
select -assert-any top