diff options
37 files changed, 2665 insertions, 239 deletions
diff --git a/.github/issue_template.md b/.github/issue_template.md index 24e91a4e7..4563a71de 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,7 +1,7 @@ ## Steps to reproduce the issue *Provide instructions for reproducing the issue. Make sure to include -all neccessary source files. (You can simply drag&drop a .zip file into +all necessary source files. (You can simply drag&drop a .zip file into the issue editor.)* ## Expected behavior @@ -3,6 +3,14 @@ List of major changes and improvements between releases ======================================================= +Yosys 0.8 .. Yosys 0.8-dev +-------------------------- + + * Various + - Added $changed support to read_verilog + - Added "write_edif -attrprop" + + Yosys 0.7 .. Yosys 0.8 ---------------------- @@ -1,4 +1,4 @@ -Copyright (C) 2012 - 2017 Clifford Wolf <clifford@clifford.at> +Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -99,7 +99,7 @@ LDFLAGS += -rdynamic LDLIBS += -lrt endif -YOSYS_VER := 0.7+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 61f6811.. | wc -l; }) +YOSYS_VER := 0.8+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 4d4665b.. | wc -l; }) GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN) OBJS = kernel/version_$(GIT_REV).o @@ -109,7 +109,7 @@ OBJS = kernel/version_$(GIT_REV).o # is just a symlink to your actual ABC working directory, as 'make mrproper' # will remove the 'abc' directory and you do not want to accidentally # delete your work on ABC.. -ABCREV = ae6716b +ABCREV = 14d985a ABCPULL = 1 ABCURL ?= https://github.com/berkeley-abc/abc ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 @@ -573,6 +573,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/bram && bash run-test.sh $(SEEDOPT) +cd tests/various && bash run-test.sh +cd tests/sat && bash run-test.sh + +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) @echo "" @echo " Passed \"make test\"." @echo "" @@ -655,6 +656,7 @@ clean: rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_* + rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff rm -f tests/tools/cmp_tbdata clean-abc: @@ -1,7 +1,7 @@ ``` yosys -- Yosys Open SYnthesis Suite -Copyright (C) 2012 - 2017 Clifford Wolf <clifford@clifford.at> +Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -452,6 +452,9 @@ from SystemVerilog: into a design with ``read_verilog``, all its packages are available to SystemVerilog files being read into the same design afterwards. +- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether + ports are inputs or outputs are supported. + Building the documentation ========================== diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 5f9ec54fd..d4e56a9eb 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -106,6 +106,9 @@ struct EdifBackend : public Backend { log(" if the design contains constant nets. use \"hilomap\" to map to custom\n"); log(" constant drivers first)\n"); log("\n"); + log(" -attrprop\n"); + log(" create EDIF properties for cell attributes\n"); + log("\n"); log(" -pvector {par|bra|ang}\n"); log(" sets the delimiting character for module port rename clauses to\n"); log(" parentheses, square brackets, or angle brackets.\n"); @@ -121,6 +124,7 @@ struct EdifBackend : public Backend { log_header(design, "Executing EDIF backend.\n"); std::string top_module_name; bool port_rename = false; + bool attr_properties = false; std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports; bool nogndvcc = false; CellTypes ct(design); @@ -137,6 +141,10 @@ struct EdifBackend : public Backend { nogndvcc = true; continue; } + if (args[argidx] == "-attrprop") { + attr_properties = true; + continue; + } if (args[argidx] == "-pvector" && argidx+1 < args.size()) { std::string parray; port_rename = true; @@ -332,24 +340,33 @@ struct EdifBackend : public Backend { *f << stringf(" (instance %s\n", EDIF_DEF(cell->name)); *f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); - for (auto &p : cell->parameters) - if ((p.second.flags & RTLIL::CONST_FLAG_STRING) != 0) - *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(p.first), p.second.decode_string().c_str()); - else if (p.second.bits.size() <= 32 && RTLIL::SigSpec(p.second).is_fully_def()) - *f << stringf("\n (property %s (integer %u))", EDIF_DEF(p.first), p.second.as_int()); + + auto add_prop = [&](IdString name, Const val) { + if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) + *f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); + else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) + *f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int()); else { std::string hex_string = ""; - for (size_t i = 0; i < p.second.bits.size(); i += 4) { + for (size_t i = 0; i < val.bits.size(); i += 4) { int digit_value = 0; - if (i+0 < p.second.bits.size() && p.second.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; - if (i+1 < p.second.bits.size() && p.second.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; - if (i+2 < p.second.bits.size() && p.second.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; - if (i+3 < p.second.bits.size() && p.second.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; + if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; + if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; + if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; + if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; hex_string = std::string(digit_str) + hex_string; } - *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(p.first), GetSize(p.second.bits), hex_string.c_str()); + *f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); } + }; + + for (auto &p : cell->parameters) + add_prop(p.first, p.second); + if (attr_properties) + for (auto &p : cell->attributes) + add_prop(p.first, p.second); + *f << stringf(")\n"); for (auto &p : cell->connections()) { RTLIL::SigSpec sig = sigmap(p.second); diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index b8383412b..f379c9c48 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -42,7 +42,7 @@ struct SmvWorker pool<Wire*> partial_assignment_wires; dict<SigBit, std::pair<const char*, int>> partial_assignment_bits; - vector<string> assignments, invarspecs; + vector<string> inputvars, vars, definitions, assignments, invarspecs; const char *cid() { @@ -195,7 +195,7 @@ struct SmvWorker return rvalue(sig); const char *temp_id = cid(); - f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig)); +// f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig)); int offset = 0; for (auto bit : sig) { @@ -210,14 +210,14 @@ struct SmvWorker void run() { f << stringf("MODULE %s\n", cid(module->name)); - f << stringf(" VAR\n"); for (auto wire : module->wires()) { if (SigSpec(wire) != sigmap(wire)) partial_assignment_wires.insert(wire); - f << stringf(" %s : unsigned word[%d]; -- %s\n", cid(wire->name), wire->width, log_id(wire)); + if (wire->port_input) + inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire))); if (wire->attributes.count("\\init")) assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at("\\init")))); @@ -275,8 +275,8 @@ struct SmvWorker const char *b_shr = rvalue_u(sig_b); const char *b_shl = cid(); - f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b)); - assignments.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b))); +// f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b)); + definitions.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b))); string expr_shl = stringf("resize(%s << %s[%d:0], %d)", expr_a.c_str(), b_shl, shift_b_width-1, width_y); string expr_shr = stringf("resize(%s >> %s[%d:0], %d)", expr_a.c_str(), b_shr, shift_b_width-1, width_y); @@ -303,7 +303,7 @@ struct SmvWorker GetSize(sig_b)-shift_b_width, width_y, expr.c_str()); } - assignments.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); + definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); continue; } @@ -319,12 +319,12 @@ struct SmvWorker if (cell->getParam("\\A_SIGNED").as_bool()) { - assignments.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue_s(cell->getPort("\\A"), width))); } else { - assignments.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue_u(cell->getPort("\\A"), width))); } @@ -346,12 +346,12 @@ struct SmvWorker if (cell->getParam("\\A_SIGNED").as_bool()) { - assignments.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")), rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width))); } else { - assignments.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width))); } @@ -370,12 +370,12 @@ struct SmvWorker if (cell->getParam("\\A_SIGNED").as_bool()) { - assignments.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width), width_y)); } else { - assignments.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")), rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width), width_y)); } @@ -407,7 +407,7 @@ struct SmvWorker expr_b = stringf("resize(%s, %d)", rvalue(cell->getPort("\\B")), width); } - assignments.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")), expr_a.c_str(), op.c_str(), expr_b.c_str(), GetSize(cell->getPort("\\Y")))); continue; @@ -425,7 +425,7 @@ struct SmvWorker if (cell->type == "$reduce_or") expr = stringf("%s != 0ub%d_0", expr_a, width_a); if (cell->type == "$reduce_bool") expr = stringf("%s != 0ub%d_0", expr_a, width_a); - assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); continue; } @@ -444,7 +444,7 @@ struct SmvWorker if (cell->type == "$reduce_xnor") expr = "!(" + expr + ")"; - assignments.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y)); continue; } @@ -462,7 +462,7 @@ struct SmvWorker if (cell->type == "$logic_and") expr = expr_a + " & " + expr_b; if (cell->type == "$logic_or") expr = expr_a + " | " + expr_b; - assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y)); continue; } @@ -474,7 +474,7 @@ struct SmvWorker string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a); const char *expr_y = lvalue(cell->getPort("\\Y")); - assignments.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y)); + definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y)); continue; } @@ -490,12 +490,13 @@ struct SmvWorker expr += stringf("bool(%s) ? %s : ", rvalue(sig_s[i]), rvalue(sig_b.extract(i*width, width))); expr += rvalue(sig_a); - assignments.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); + definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str())); continue; } if (cell->type == "$dff") { + vars.push_back(stringf("%s : unsigned word[%d]; -- %s", lvalue(cell->getPort("\\Q")), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q")))); assignments.push_back(stringf("next(%s) := %s;", lvalue(cell->getPort("\\Q")), rvalue(cell->getPort("\\D")))); continue; } @@ -503,7 +504,7 @@ struct SmvWorker if (cell->type.in("$_BUF_", "$_NOT_")) { string op = cell->type == "$_NOT_" ? "!" : ""; - assignments.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A")))); + definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A")))); continue; } @@ -517,49 +518,49 @@ struct SmvWorker if (cell->type.in("$_XNOR_")) op = "xnor"; if (cell->type.in("$_ANDNOT_", "$_ORNOT_")) - assignments.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); else if (cell->type.in("$_NAND_", "$_NOR_")) - assignments.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); else - assignments.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B")))); continue; } if (cell->type == "$_MUX_") { - assignments.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort("\\Y")), + 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_") { - assignments.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")))); continue; } if (cell->type == "$_OAI3_") { - assignments.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")))); continue; } if (cell->type == "$_AOI4_") { - assignments.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D")))); continue; } if (cell->type == "$_OAI4_") { - assignments.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")), + definitions.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")), rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D")))); continue; } @@ -567,13 +568,13 @@ struct SmvWorker if (cell->type[0] == '$') log_error("Found currently unsupported cell type %s (%s.%s).\n", log_id(cell->type), log_id(module), log_id(cell)); - f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type)); +// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type)); for (auto &conn : cell->connections()) if (cell->output(conn.first)) - assignments.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first))); + definitions.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first))); else - assignments.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second))); + definitions.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second))); } for (Wire *wire : partial_assignment_wires) @@ -657,7 +658,25 @@ struct SmvWorker } } - assignments.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str())); + definitions.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str())); + } + + if (!inputvars.empty()) { + f << stringf(" IVAR\n"); + for (const string &line : inputvars) + f << stringf(" %s\n", line.c_str()); + } + + if (!vars.empty()) { + f << stringf(" VAR\n"); + for (const string &line : vars) + f << stringf(" %s\n", line.c_str()); + } + + if (!definitions.empty()) { + f << stringf(" DEFINE\n"); + for (const string &line : definitions) + f << stringf(" %s\n", line.c_str()); } if (!assignments.empty()) { diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index ae9031510..dde03f920 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -388,7 +388,7 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) void dump_memory(std::ostream &f, std::string indent, RTLIL::Memory *memory) { dump_attributes(f, indent, memory->attributes); - f << stringf("%s" "reg [%d:0] %s [%d:0];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size-1); + f << stringf("%s" "reg [%d:0] %s [%d:%d];\n", indent.c_str(), memory->width-1, id(memory->name).c_str(), memory->size+memory->start_offset-1, memory->start_offset); } void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, bool gen_signed = true) @@ -952,6 +952,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) std::string mem_id = id(cell->parameters["\\MEMID"].decode_string()); int abits = cell->parameters["\\ABITS"].as_int(); int size = cell->parameters["\\SIZE"].as_int(); + int offset = cell->parameters["\\OFFSET"].as_int(); int width = cell->parameters["\\WIDTH"].as_int(); bool use_init = !(RTLIL::SigSpec(cell->parameters["\\INIT"]).is_fully_undef()); @@ -960,7 +961,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) // initial begin // memid[0] = ... // end - f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size-1, 0); + f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size+offset-1, offset); if (use_init) { f << stringf("%s" "initial begin\n", indent.c_str()); diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index e79be953a..7600e2912 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -905,7 +906,7 @@ RTLIL::Const AstNode::realAsConst(int width) // create a new AstModule from an AST_MODULE AST node static AstModule* process_module(AstNode *ast, bool defer) { - log_assert(ast->type == AST_MODULE); + log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); if (defer) log("Storing AST representation for module `%s'.\n", ast->str.c_str()); @@ -916,6 +917,7 @@ static AstModule* process_module(AstNode *ast, bool defer) current_module->ast = NULL; current_module->name = ast->str; current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); + current_module->set_bool_attribute("\\cells_not_processed"); current_ast_mod = ast; AstNode *ast_before_simplify = ast->clone(); @@ -989,6 +991,8 @@ static AstModule* process_module(AstNode *ast, bool defer) ignoreThisSignalsInInitial = RTLIL::SigSpec(); } + if (ast->type == AST_INTERFACE) + current_module->set_bool_attribute("\\is_interface"); current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; current_module->nomeminit = flag_nomeminit; @@ -1031,7 +1035,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump log_assert(current_ast->type == AST_DESIGN); for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) { - if ((*it)->type == AST_MODULE) + if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE) { for (auto n : design->verilog_globals) (*it)->children.push_back(n->clone()); @@ -1083,8 +1087,179 @@ AstModule::~AstModule() delete ast; } +// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again +// from AST. The interface members are copied into the AST module with the prefix of the interface. +void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module*> local_interfaces) +{ + bool is_top = false; + AstNode *new_ast = ast->clone(); + for (auto &intf : local_interfaces) { + std::string intfname = intf.first.str(); + RTLIL::Module *intfmodule = intf.second; + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string newname = log_id(wire_it.first); + newname = intfname + "." + newname; + wire->str = newname; + new_ast->children.push_back(wire); + } + } + + // The old module will be deleted. Rename and mark for deletion: + std::string original_name = this->name.str(); + std::string changed_name = original_name + "_before_replacing_local_interfaces"; + design->rename(this, changed_name); + this->set_bool_attribute("\\to_delete"); + + // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the + // new module. + if (this->get_bool_attribute("\\initial_top")) { + this->attributes.erase("\\initial_top"); + is_top = true; + } + + // Generate RTLIL from AST for the new module and add to the design: + AstModule *newmod = process_module(new_ast, false); + design->add(newmod); + RTLIL::Module* mod = design->module(original_name); + if (is_top) + mod->set_bool_attribute("\\top"); + + // Set the attribute "interfaces_replaced_in_module" so that it does not happen again. + mod->set_bool_attribute("\\interfaces_replaced_in_module"); +} + +// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces +// This method is used to explode the interface when the interface is a port of the module (not instantiated inside) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) +{ + AstNode *new_ast = NULL; + std::string modname = derive_common(design, parameters, &new_ast, mayfail); + + // Since interfaces themselves may be instantiated with different parameters, + // "modname" must also take those into account, so that unique modules + // are derived for any variant of interface connections: + std::string interf_info = ""; + + bool has_interfaces = false; + for(auto &intf : interfaces) { + interf_info += log_id(intf.second->name); + has_interfaces = true; + } + + if (has_interfaces) + modname += "$interfaces$" + interf_info; + + + if (!design->has(modname)) { + new_ast->str = modname; + + // Iterate over all interfaces which are ports in this module: + for(auto &intf : interfaces) { + RTLIL::Module * intfmodule = intf.second; + std::string intfname = intf.first.str(); + // Check if a modport applies for the interface port: + AstNode *modport = NULL; + if (modports.count(intfname) > 0) { + std::string interface_modport = modports.at(intfname).str(); + AstModule *ast_module_of_interface = (AstModule*)intfmodule; + AstNode *ast_node_of_interface = ast_module_of_interface->ast; + for (auto &ch : ast_node_of_interface->children) { + if (ch->type == AST_MODPORT) { + if (ch->str == interface_modport) { // Modport found + modport = ch; + } + } + } + } + // Iterate over all wires in the interface and add them to the module: + for (auto &wire_it : intfmodule->wires_){ + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); + std::string origname = log_id(wire_it.first); + std::string newname = intfname + "." + origname; + wire->str = newname; + if (modport != NULL) { + bool found_in_modport = false; + // Search for the current wire in the wire list for the current modport + for (auto &ch : modport->children) { + if (ch->type == AST_MODPORTMEMBER) { + std::string compare_name = "\\" + origname; + if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output + found_in_modport = true; + wire->is_input = ch->is_input; + wire->is_output = ch->is_output; + break; + } + } + } + if (found_in_modport) { + new_ast->children.push_back(wire); + } + else { // If not found in modport, do not create port + delete wire; + } + } + else { // If no modport, set inout + wire->is_input = true; + wire->is_output = true; + new_ast->children.push_back(wire); + } + } + } + + design->add(process_module(new_ast, false)); + design->module(modname)->check(); + + RTLIL::Module* mod = design->module(modname); + + // Now that the interfaces have been exploded, we can delete the dummy port related to every interface. + for(auto &intf : interfaces) { + if(mod->wires_.count(intf.first)) { + mod->wires_.erase(intf.first); + mod->fixup_ports(); + // We copy the cell of the interface to the sub-module such that it can further be found if it is propagated + // down to sub-sub-modules etc. + RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); + new_subcell->set_bool_attribute("\\is_interface"); + } + else { + log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str()); + } + } + + // If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module': + if (interfaces.size() > 0) { + mod->set_bool_attribute("\\interfaces_replaced_in_module"); + } + + } else { + log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); + } + + delete new_ast; + return modname; +} + +// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) +{ + AstNode *new_ast = NULL; + std::string modname = derive_common(design, parameters, &new_ast, mayfail); + + if (!design->has(modname)) { + new_ast->str = modname; + design->add(process_module(new_ast, false)); + design->module(modname)->check(); + } else { + log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); + } + + delete new_ast; + return modname; +} + // create a new parametric module (when needed) and return the name of the generated module -RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool) +std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool) { std::string stripped_name = name.str(); @@ -1156,15 +1331,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R else modname = "$paramod" + stripped_name + para_info; - if (!design->has(modname)) { - new_ast->str = modname; - design->add(process_module(new_ast, false)); - design->module(modname)->check(); - } else { - log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); - } - delete new_ast; + (*new_ast_out) = new_ast; return modname; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 7e97bdb3b..8187b1ac6 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -142,6 +142,11 @@ namespace AST AST_NEGEDGE, AST_EDGE, + AST_INTERFACE, + AST_INTERFACEPORT, + AST_INTERFACEPORTTYPE, + AST_MODPORT, + AST_MODPORTMEMBER, AST_PACKAGE }; @@ -284,6 +289,9 @@ namespace AST bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; + RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; + std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail); + void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE; RTLIL::Module *clone() const YS_OVERRIDE; }; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index c9345ff08..32b9af6e9 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -853,6 +853,52 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) case AST_GENIF: case AST_GENCASE: case AST_PACKAGE: + case AST_MODPORT: + case AST_MODPORTMEMBER: + break; + case AST_INTERFACEPORT: { + // If a port in a module with unknown type is found, mark it with the attribute 'is_interface' + // This is used by the hierarchy pass to know when it can replace interface connection with the individual + // signals. + RTLIL::Wire *wire = current_module->addWire(str, 1); + wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + wire->start_offset = 0; + wire->port_id = port_id; + wire->port_input = true; + wire->port_output = true; + wire->set_bool_attribute("\\is_interface"); + if (children.size() > 0) { + for(size_t i=0; i<children.size();i++) { + if(children[i]->type == AST_INTERFACEPORTTYPE) { + std::string name_type = children[i]->str; + size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); + // Separate the interface instance name from any modports: + if (ndots == 0) { // Does not have modport + wire->attributes["\\interface_type"] = name_type; + } + else { + std::stringstream name_type_stream(name_type); + std::string segment; + std::vector<std::string> seglist; + while(std::getline(name_type_stream, segment, '.')) { + seglist.push_back(segment); + } + if (ndots == 1) { // Has modport + wire->attributes["\\interface_type"] = seglist[0]; + wire->attributes["\\interface_modport"] = seglist[1]; + } + else { // Erroneous port type + log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); + } + } + break; + } + } + } + wire->upto = 0; + } + break; + case AST_INTERFACEPORTTYPE: break; // remember the parameter, needed for example in techmap @@ -949,6 +995,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) { RTLIL::Wire *wire = NULL; RTLIL::SigChunk chunk; + bool is_interface = false; int add_undef_bits_msb = 0; int add_undef_bits_lsb = 0; @@ -969,15 +1016,41 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) chunk = RTLIL::Const(id2ast->children[0]->bits); goto use_const_chunk; } - else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE && - id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0) + else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { + RTLIL::Wire *current_wire = current_module->wire(str); + if (current_wire->get_bool_attribute("\\is_interface")) + is_interface = true; + // Ignore + } + // If an identifier is found that is not already known, assume that it is an interface: + else if (1) { // FIXME: Check if sv_mode first? + is_interface = true; + } + else { log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); + } if (id2ast->type == AST_MEMORY) log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); + // If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' + // This makes it possible for the hierarchy pass to see what are interface connections and then replace them + // with the individual signals: + if (is_interface) { + RTLIL::Wire *dummy_wire; + std::string dummy_wire_name = "$dummywireforinterface" + str; + if (current_module->wires_.count(dummy_wire_name)) + dummy_wire = current_module->wires_[dummy_wire_name]; + else { + dummy_wire = current_module->addWire(dummy_wire_name); + dummy_wire->set_bool_attribute("\\is_interface"); + } + RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire); + return tmp; + } + wire = current_module->wires_[str]; chunk.wire = wire; chunk.width = wire->width; @@ -1423,6 +1496,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) RTLIL::Cell *cell = current_module->addCell(str, ""); cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); + // Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass + cell->set_bool_attribute("\\module_not_derived"); for (auto it = children.begin(); it != children.end(); it++) { AstNode *child = *it; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 71eba547c..e56a62563 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (stage == 0) { - log_assert(type == AST_MODULE); + log_assert(type == AST_MODULE || type == AST_INTERFACE); last_blocking_assignment_warn = pair<string, int>(); deep_recursion_warning = true; @@ -1336,6 +1336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, str.clear(); type = AST_ASSIGN; children.push_back(children_list.at(0)); + children.back()->was_checked = true; children.push_back(node); did_something = true; } @@ -1372,6 +1373,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, str.clear(); type = AST_ASSIGN; children.push_back(children_list[0]); + children.back()->was_checked = true; children.push_back(node); did_something = true; } @@ -1530,6 +1532,7 @@ skip_dynamic_range_lvalue_expansion:; wire_tmp_id->str = wire_tmp->str; newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone())); + newNode->children.back()->was_checked = true; int cursor = 0; for (auto child : children[0]->children) @@ -1815,6 +1818,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *regid = new AstNode(AST_IDENTIFIER); regid->str = reg->str; regid->id2ast = reg; + regid->was_checked = true; AstNode *rhs = nullptr; @@ -2204,6 +2208,8 @@ skip_dynamic_range_lvalue_expansion:; AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_EQ, lvalue, clone()))); + always->children[0]->children[0]->was_checked = true; + current_ast_mod->children.push_back(always); goto replace_fcall_with_id; @@ -2253,6 +2259,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign = child->is_input ? new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone()); + assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { if (*it != current_block_child) @@ -2323,6 +2330,7 @@ skip_dynamic_range_lvalue_expansion:; AstNode *assign = child->is_input ? new AstNode(AST_ASSIGN_EQ, wire_id, arg) : new AstNode(AST_ASSIGN_EQ, arg, wire_id); + assign->children[0]->was_checked = true; for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) { if (*it != current_block_child) @@ -2762,6 +2770,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value)); block->children.back()->children[0]->str = memory->str; block->children.back()->children[0]->id2ast = memory; + block->children.back()->children[0]->was_checked = true; } cursor += increment; @@ -3022,6 +3031,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *newNode = clone(); newNode->type = AST_ASSIGN_EQ; + newNode->children[0]->was_checked = true; async_block->children[0]->children.push_back(newNode); newNode = new AstNode(AST_NONE); @@ -3067,6 +3077,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); assign_addr->children[0]->str = id_addr; + assign_addr->children[0]->was_checked = true; block->children.insert(block->children.begin()+assign_idx+1, assign_addr); AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); @@ -3090,6 +3101,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, children[0]->id2ast = NULL; children[0]->str = id_data; type = AST_ASSIGN_EQ; + children[0]->was_checked = true; did_something = true; } diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 0a5bd84de..66db43baf 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -634,9 +634,12 @@ struct LibertyFrontend : public Frontend { } } - for (auto node : cell->children) + if (!flag_lib) { - if (!flag_lib) { + // some liberty files do not put ff/latch at the beginning of a cell + // try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes + for (auto node : cell->children) + { if (node->id == "ff" && node->args.size() == 2) create_ff(module, node); if (node->id == "latch" && node->args.size() == 2) @@ -645,7 +648,10 @@ struct LibertyFrontend : public Frontend { goto skip_cell; } } + } + for (auto node : cell->children) + { if (node->id == "pin" && node->args.size() == 1) { LibertyAst *dir = node->find("direction"); diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index c5fa58313..dba3b0f0c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -118,6 +118,18 @@ RTLIL::SigBit VerificImporter::net_map_at(Net *net) return net_map.at(net); } +bool is_blackbox(Netlist *nl) +{ + if (nl->IsBlackBox()) + return true; + + const char *attr = nl->GetAttValue("blackbox"); + if (attr != nullptr && strcmp(attr, "0")) + return true; + + return false; +} + void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj) { MapIter mi; @@ -709,7 +721,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se netlist = nl; if (design->has(module_name)) { - if (!nl->IsOperator()) + if (!nl->IsOperator() && !is_blackbox(nl)) log_cmd_error("Re-definition of module `%s'.\n", nl->Owner()->Name()); return; } @@ -718,7 +730,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se module->name = module_name; design->add(module); - if (nl->IsBlackBox()) { + if (is_blackbox(nl)) { log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name)); module->set_bool_attribute("\\blackbox"); } else { @@ -1676,6 +1688,7 @@ YOSYS_NAMESPACE_END PRIVATE_NAMESPACE_BEGIN +#ifdef YOSYS_ENABLE_VERIFIC bool check_noverific_env() { const char *e = getenv("YOSYS_NOVERIFIC"); @@ -1685,6 +1698,7 @@ bool check_noverific_env() return false; return true; } +#endif struct VerificPass : public Pass { VerificPass() : Pass("verific", "load Verilog and VHDL designs using Verific") { } diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 83921bf0b..f9118e142 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -135,6 +135,9 @@ YOSYS_NAMESPACE_END frontend_verilog_yyerror("Unsupported default nettype: %s", p); } +"`protect"[^\n]* /* ignore `protect*/ +"`endprotect"[^\n]* /* ignore `endprotect*/ + "`"[a-zA-Z_$][a-zA-Z0-9_$]* { frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext); } @@ -150,6 +153,9 @@ YOSYS_NAMESPACE_END "specparam" { return TOK_SPECPARAM; } "package" { SV_KEYWORD(TOK_PACKAGE); } "endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); } +"interface" { SV_KEYWORD(TOK_INTERFACE); } +"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); } +"modport" { SV_KEYWORD(TOK_MODPORT); } "parameter" { return TOK_PARAMETER; } "localparam" { return TOK_LOCALPARAM; } "defparam" { return TOK_DEFPARAM; } @@ -295,6 +301,11 @@ supply1 { return TOK_SUPPLY1; } return TOK_ID; } +[a-zA-Z_$][a-zA-Z0-9_$\.]* { + frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); + return TOK_ID; +} + "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { static bool printed_warning = false; if (!printed_warning) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 16cac1460..4dbe028a0 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -61,6 +61,7 @@ namespace VERILOG_FRONTEND { bool noassert_mode, noassume_mode, norestrict_mode; bool assume_asserts_mode, assert_assumes_mode; bool current_wire_rand, current_wire_const; + bool current_modport_input, current_modport_output; std::istream *lexin; } YOSYS_NAMESPACE_END @@ -106,6 +107,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP +%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT @@ -168,6 +170,7 @@ design: param_decl design | localparam_decl design | package design | + interface design | /* empty */; attr: @@ -320,6 +323,21 @@ module_arg: } delete $1; } module_arg_opt_assignment | + TOK_ID { + astbuf1 = new AstNode(AST_INTERFACEPORT); + astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE)); + astbuf1->children[0]->str = *$1; + delete $1; + } TOK_ID { /* SV interfaces */ + if (!sv_mode) + frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); + astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type. + astbuf2->str = *$3; + delete $3; + astbuf2->port_id = ++port_counter; + ast_stack.back()->children.push_back(astbuf2); + delete astbuf1; // really only needed if multiple instances of same type. + } module_arg_opt_assignment | attr wire_type range TOK_ID { AstNode *node = $2; node->str = *$4; @@ -357,6 +375,33 @@ package_body: package_body_stmt: localparam_decl; +interface: + TOK_INTERFACE TOK_ID { + do_not_require_port_stubs = false; + AstNode *intf = new AstNode(AST_INTERFACE); + ast_stack.back()->children.push_back(intf); + ast_stack.push_back(intf); + current_ast_mod = intf; + port_stubs.clear(); + port_counter = 0; + intf->str = *$2; + delete $2; + } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE { + if (port_stubs.size() != 0) + frontend_verilog_yyerror("Missing details for module port `%s'.", + port_stubs.begin()->first.c_str()); + ast_stack.pop_back(); + log_assert(ast_stack.size() == 1); + current_ast_mod = NULL; + }; + +interface_body: + interface_body interface_body_stmt |; + +interface_body_stmt: + param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | + modport_stmt; + non_opt_delay: '#' TOK_ID { delete $2; } | '#' TOK_CONSTVAL { delete $2; } | @@ -1280,6 +1325,41 @@ opt_property: opt_stmt_label: TOK_ID ':' | /* empty */; +modport_stmt: + TOK_MODPORT TOK_ID { + AstNode *modport = new AstNode(AST_MODPORT); + ast_stack.back()->children.push_back(modport); + ast_stack.push_back(modport); + modport->str = *$2; + delete $2; + } modport_args_opt { + ast_stack.pop_back(); + log_assert(ast_stack.size() == 2); + } ';' + +modport_args_opt: + '(' ')' | '(' modport_args optional_comma ')'; + +modport_args: + modport_arg | modport_args ',' modport_arg; + +modport_arg: + modport_type_token modport_member | + modport_member + +modport_member: + TOK_ID { + AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); + ast_stack.back()->children.push_back(modport_member); + modport_member->str = *$1; + modport_member->is_input = current_modport_input; + modport_member->is_output = current_modport_output; + delete $1; + } + +modport_type_token: + TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} + assert: opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { if (noassert_mode) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index fcc4fcc4b..6041168bb 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -157,7 +157,7 @@ struct CellTypes IdString A = "\\A", B = "\\B", C = "\\C", D = "\\D"; IdString E = "\\E", F = "\\F", G = "\\G", H = "\\H"; IdString I = "\\I", J = "\\J", K = "\\K", L = "\\L"; - IdString M = "\\I", N = "\\N", O = "\\O", P = "\\P"; + IdString M = "\\M", N = "\\N", O = "\\O", P = "\\P"; IdString S = "\\S", T = "\\T", U = "\\U", V = "\\V"; IdString Y = "\\Y"; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a4fa2cf04..14259f8ed 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -639,6 +639,11 @@ RTLIL::Module::~Module() delete it->second; } +void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>) +{ + log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name)); +} + RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, bool mayfail) { if (mayfail) @@ -646,6 +651,14 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLI log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name)); } + +RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, dict<RTLIL::IdString, RTLIL::Module*>, dict<RTLIL::IdString, RTLIL::IdString>, bool mayfail) +{ + if (mayfail) + return RTLIL::IdString(); + log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name)); +} + size_t RTLIL::Module::count_id(RTLIL::IdString id) { return wires_.count(id) + memories.count(id) + cells_.count(id) + processes.count(id); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 027faf416..276540aa1 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -907,7 +907,9 @@ public: Module(); virtual ~Module(); virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail = false); + virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail = false); virtual size_t count_id(RTLIL::IdString id); + virtual void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces); virtual void sort(); virtual void check(); diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex index fea2354e6..bed6326e2 100644 --- a/manual/command-reference-manual.tex +++ b/manual/command-reference-manual.tex @@ -23,45 +23,47 @@ library to a target architecture. if no -script parameter is given, the following scripts are used: for -liberty without -constr: - strash; dc2; scorr; ifraig; retime -o {D}; strash; dch -f; - map {D} + strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; + &nf {D}; &put for -liberty with -constr: - strash; dc2; scorr; ifraig; retime -o {D}; strash; dch -f; - map {D}; buffer; upsize {D}; dnsize {D}; stime -p + strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; + &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p for -lut/-luts (only one LUT size): - strash; dc2; scorr; ifraig; retime -o; strash; dch -f; if; mfs; - lutpack + strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2; + lutpack {S} for -lut/-luts (different LUT sizes): - strash; dc2; scorr; ifraig; retime -o; strash; dch -f; if; mfs + strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2 for -sop: - strash; dc2; scorr; ifraig; retime -o; strash; dch -f; + strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P} otherwise: - strash; dc2; scorr; ifraig; retime -o; strash; dch -f; map + strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; + &nf {D}; &put -fast use different default scripts that are slightly faster (at the cost of output quality): for -liberty without -constr: - retime -o {D}; map {D} + strash; dretime; map {D} for -liberty with -constr: - retime -o {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p + strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; + stime -p for -lut/-luts: - retime -o; if + strash; dretime; if for -sop: - retime -o; cover -I {I} -P {P} + strash; dretime; cover -I {I} -P {P} otherwise: - retime -o; map + strash; dretime; map -liberty <file> generate netlists for the specified cell library (using the liberty @@ -81,6 +83,8 @@ library to a target architecture. -D <picoseconds> set delay target. the string {D} in the default scripts above is replaced by this option when used, and an empty string otherwise. + this also replaces 'dretime' with 'dretime; retime -o {D}' in the + default scripts above. -I <num> maximum number of SOP inputs. @@ -90,6 +94,10 @@ library to a target architecture. maximum number of SOP products. (replaces {P} in the default scripts above) + -S <num> + maximum number of LUT inputs shared. + (replaces {S} in the default scripts above, default: -S 1) + -lut <width> generate netlist using luts of (max) the specified width. @@ -107,10 +115,21 @@ library to a target architecture. map to sum-of-product cells and inverters -g type1,type2,... - Map the the specified list of gate types. Supported gates types are: - AND, NAND, OR, NOR, XOR, XNOR, MUX, AOI3, OAI3, AOI4, OAI4. + Map to the specified list of gate types. Supported gates types are: + AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4. (The NOT gate is always added to this list automatically.) + The following aliases can be used to reference common sets of gate types: + simple: AND OR XOR MUX + cmos2: NAND NOR + cmos3: NAND NOR AOI3 OAI3 + cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4 + gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT + aig: AND NAND OR NOR ANDNOT ORNOT + + Prefix a gate type with a '-' to remove it from the list. For example + the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent. + -dff also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many clock domains are automatically partitioned in clock domains and each @@ -140,8 +159,12 @@ library to a target architecture. When neither -liberty nor -lut is used, the Yosys standard cell library is loaded into ABC before the ABC script is executed. -This pass does not operate on modules with unprocessed processes in it. -(I.e. the 'proc' pass should be used first to convert processes to netlists.) +Note that this is a logic optimization pass within Yosys that is calling ABC +internally. This is not going to "run ABC on your design". It will instead run +ABC on logic snippets extracted from your design. You will not get any useful +output when passing an ABC script that writes a file. Instead write your full +design as BLIF file with write_blif and the load that into ABC externally if +you want to use ABC to convert your design into another format. [1] http://www.eecs.berkeley.edu/~alanmi/abc/ \end{lstlisting} @@ -206,6 +229,22 @@ This command adds asserts to the design that assert that all parallel muxes additional constrained and check the $pmux condition always. \end{lstlisting} +\section{async2sync -- convert async FF inputs to sync circuits} +\label{cmd:async2sync} +\begin{lstlisting}[numbers=left,frame=single] + async2sync [options] [selection] + +This command replaces async FF inputs with sync circuits emulating the same +behavior for when the async signals are actually synchronized to the clock. + +This pass assumes negative hold time for the async FF inputs. For example when +a reset deasserts with the clock edge, then the FF output will still drive the +reset value in the next cycle regardless of the data-in value at the time of +the clock edge. + +Currently only $adff cells are supported by this pass. +\end{lstlisting} + \section{attrmap -- renaming attributes} \label{cmd:attrmap} \begin{lstlisting}[numbers=left,frame=single] @@ -268,6 +307,15 @@ Move or copy attributes on wires to the cells driving them. multiple times. \end{lstlisting} +\section{blackbox -- change type of cells in the design} +\label{cmd:blackbox} +\begin{lstlisting}[numbers=left,frame=single] + blackbox [options] [selection] + +Convert modules into blackbox modules (remove contents and set the blackbox +module attribute). +\end{lstlisting} + \section{cd -- a shortcut for 'select -module <name>'} \label{cmd:cd} \begin{lstlisting}[numbers=left,frame=single] @@ -284,6 +332,12 @@ to 'cd <celltype>'. cd .. +Remove trailing substrings that start with '.' in current module name until +the name of a module in the current design is generated, then switch to that +module. Otherwise clear the current selection. + + cd + This is just a shortcut for 'select -clear'. \end{lstlisting} @@ -303,10 +357,49 @@ This pass identifies the following problems in the current design: When called with -noinit then this command also checks for wires which have the 'init' attribute set. +When called with -initdrv then this command also checks for wires which have +the 'init' attribute set and aren't driven by a FF cell type. + When called with -assert then the command will produce an error if any problems are found in the current design. \end{lstlisting} +\section{chformal -- change formal constraints of the design} +\label{cmd:chformal} +\begin{lstlisting}[numbers=left,frame=single] + chformal [types] [mode] [options] [selection] + +Make changes to the formal constraints of the design. The [types] options +the type of constraint to operate on. If none of the folling options is given, +the command will operate on all constraint types: + + -assert $assert cells, representing assert(...) constraints + -assume $assume cells, representing assume(...) constraints + -live $live cells, representing assert(s_eventually ...) + -fair $fair cells, representing assume(s_eventually ...) + -cover $cover cells, representing cover() statements + +Exactly one of the following modes must be specified: + + -remove + remove the cells and thus constraints from the design + + -early + bypass FFs that only delay the activation of a constraint + + -delay <N> + delay activation of the constraint by <N> clock cycles + + -skip <N> + ignore activation of the constraint in the first <N> clock cycles + + -assert2assume + -assume2assert + -live2fair + -fair2live + change the roles of cells as indicated. this options can be combined +\end{lstlisting} + \section{chparam -- re-evaluate modules with new parameters} \label{cmd:chparam} \begin{lstlisting}[numbers=left,frame=single] @@ -321,6 +414,20 @@ passed in double quotes ("). List the available parameters of the selected modules. \end{lstlisting} +\section{chtype -- change type of cells in the design} +\label{cmd:chtype} +\begin{lstlisting}[numbers=left,frame=single] + chtype [options] [selection] + +Change the types of cells in the design. + + -set <type> + set the cell type to the given type + + -map <old_type> <new_type> + change cells types that match <old_type> to <new_type> +\end{lstlisting} + \section{clean -- remove unused cells and wires} \label{cmd:clean} \begin{lstlisting}[numbers=left,frame=single] @@ -376,7 +483,7 @@ be selected or an active module must be set using the 'cd' command. This command does not operate on module with processes. \end{lstlisting} -\section{connwrappers -- replace undef values with defined constants} +\section{connwrappers -- match width of input-output port pairs} \label{cmd:connwrappers} \begin{lstlisting}[numbers=left,frame=single] connwrappers [options] [selection] @@ -397,6 +504,14 @@ the driving cell. The options -signed, -unsigned, and -port can be specified multiple times. \end{lstlisting} +\section{coolrunner2\_sop -- break \$sop cells into ANDTERM/ORTERM cells} +\label{cmd:coolrunner2_sop} +\begin{lstlisting}[numbers=left,frame=single] + coolrunner2_sop [options] [selection] + +Break $sop cells into ANDTERM/ORTERM cells. +\end{lstlisting} + \section{copy -- copy modules in the design} \label{cmd:copy} \begin{lstlisting}[numbers=left,frame=single] @@ -519,6 +634,19 @@ evaluated in the other design. design -copy-to <name> [-as <new_mod_name>] [selection] Copy modules from the current design into the specified one. + + + design -import <name> [-as <new_top_name>] [selection] + +Import the specified design into the current design. The source design must +either have a selected top module or the selection must contain exactly one +module that is then used as top module for this command. + + + design -reset-vlog + +The Verilog front-end remembers defined macros and top-level declarations +between calls to 'read_verilog'. This command resets this memory. \end{lstlisting} \section{dff2dffe -- transform \$dff cells to \$dffe cells} @@ -546,8 +674,18 @@ $_DFF_P_, $_DFF_N_ and $_MUX_. -direct-match <pattern> like -direct for all DFF cell types matching the expression. this will use $__DFFE_* as <external_gate_type> matching the - internal gate type $_DFF_*_, except for $_DFF_[NP]_, which is - converted to $_DFFE_[NP]_. + internal gate type $_DFF_*_, and $__DFFSE_* for those matching + $_DFFS_*_, except for $_DFF_[NP]_, which is converted to + $_DFFE_[NP]_. +\end{lstlisting} + +\section{dff2dffs -- process sync set/reset with SR over CE priority} +\label{cmd:dff2dffs} +\begin{lstlisting}[numbers=left,frame=single] + dff2dffs [options] [selection] + +Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before +dff2dffe for SR over CE priority. \end{lstlisting} \section{dffinit -- set INIT param on FF cells} @@ -561,6 +699,11 @@ drives. (This is primarily used in FPGA flows.) -ff <cell_name> <output_port> <init_param> operate on the specified cell type. this option can be used multiple times. + + -highlow + use the string values "high" and "low" to represent a single-bit + initial value of 1 or 0. (multi-bit values are not supported in this + mode.) \end{lstlisting} \section{dfflibmap -- technology mapping of flip-flops} @@ -767,6 +910,10 @@ This command tries to prove $equiv cells using a simple direct SAT approach. -undef enable modelling of undef states + -short + create shorter input cones that stop at shared nodes. This yields + simpler SAT problems but sometimes fails to prove equivalence. + -nogroup disabling grouping of $equiv cells by output wire @@ -852,6 +999,10 @@ outputs. when exposing a wire, create an input/output pair and cut the internal signal path at that wire. + -input + when exposing a wire, create an input port and disconnect the internal + driver. + -shared only expose those signals that are shared among the selected modules. this is useful for preparing modules for equivalence checking. @@ -956,6 +1107,64 @@ tries to map the modules to the design (ascending, default value is 0). See 'help techmap' for a pass that does the opposite thing. \end{lstlisting} +\section{extract\_counter -- Extract GreenPak4 counter cells} +\label{cmd:extract_counter} +\begin{lstlisting}[numbers=left,frame=single] + extract_counter [options] [selection] + +This pass converts non-resettable or async resettable down counters to +counter cells. Use a target-specific 'techmap' map file to convert those cells +to the actual target cells. + + -maxwidth N + Only extract counters up to N bits wide + + -pout X,Y,... + Only allow parallel output from the counter to the listed cell types + (if not specified, parallel outputs are not restricted) +\end{lstlisting} + +\section{extract\_fa -- find and extract full/half adders} +\label{cmd:extract_fa} +\begin{lstlisting}[numbers=left,frame=single] + extract_fa [options] [selection] + +This pass extracts full/half adders from a gate-level design. + + -fa, -ha + Enable cell types (fa=full adder, ha=half adder) + All types are enabled if none of this options is used + + -d <int> + Set maximum depth for extracted logic cones (default=20) + + -b <int> + Set maximum breadth for extracted logic cones (default=6) + + -v + Verbose output +\end{lstlisting} + +\section{extract\_reduce -- converts gate chains into \$reduce\_* cells} +\label{cmd:extract_reduce} +\begin{lstlisting}[numbers=left,frame=single] + extract_reduce [options] [selection] + +converts gate chains into $reduce_* cells + +This command finds chains of $_AND_, $_OR_, and $_XOR_ cells and replaces them +with their corresponding $reduce_* cells. Because this command only operates on +these cell types, it is recommended to map the design to only these cell types +using the `abc -g` command. Note that, in some cases, it may be more effective +to map the design to only $_AND_ cells, run extract_reduce, map the remaining +parts of the design to AND/OR/XOR cells, and run extract_reduce a second time. + + -allow-off-chain + Allows matching of cells that have loads outside the chain. These cells + will be replicated and folded into the $reduce_* cell, but the original + cell will remain, driving its original loads. +\end{lstlisting} + \section{flatten -- flatten design} \label{cmd:flatten} \begin{lstlisting}[numbers=left,frame=single] @@ -1155,21 +1364,12 @@ one-hot encoding and binary encoding is supported. .map <old_bitpattern> <new_bitpattern> \end{lstlisting} -\section{greenpak4\_counters -- Extract GreenPak4 counter cells} -\label{cmd:greenpak4_counters} -\begin{lstlisting}[numbers=left,frame=single] - greenpak4_counters [options] [selection] - -This pass converts non-resettable or async resettable down counters to GreenPak4 -counter cells (All other GreenPak4 counter modes must be instantiated manually.) -\end{lstlisting} - -\section{greenpak4\_dffinv -- merge greenpak4 inverters and DFFs} +\section{greenpak4\_dffinv -- merge greenpak4 inverters and DFF/latches} \label{cmd:greenpak4_dffinv} \begin{lstlisting}[numbers=left,frame=single] greenpak4_dffinv [options] [selection] -Merge GP_INV cells with GP_DFF* cells. +Merge GP_INV cells with GP_DFF* and GP_DLATCH* cells. \end{lstlisting} \section{help -- display help messages} @@ -1199,6 +1399,10 @@ needed. also check the design hierarchy. this generates an error when an unknown module is used as cell type. + -simcheck + like -check, but also thow an error if blackbox modules are + instantiated, and throw an error if the design has no top module + -purge_lib by default the hierarchy command will not remove library (blackbox) modules. use this option to also remove unused blackbox modules. @@ -1212,6 +1416,11 @@ needed. per default this pass also converts positional arguments in cells to arguments using port names. this option disables this behavior. + -keep_portwidths + per default this pass adjusts the port width on cells that are + module instances when the width does not match the module port. this + option disables this behavior. + -nokeep_asserts per default this pass sets the "keep" attribute on all modules that directly or indirectly contain one or more $assert cells. this @@ -1416,6 +1625,18 @@ When no active module is selected, this prints a list of modules. When an active module is selected, this prints a list of objects in the module. \end{lstlisting} +\section{ltp -- print longest topological path} +\label{cmd:ltp} +\begin{lstlisting}[numbers=left,frame=single] + ltp [options] [selection] + +This command prints the longest topological path in the design. (Only considers +paths within a single module, so the design must be flattened.) + + -noff + automatically exclude FF cell types +\end{lstlisting} + \section{lut2mux -- convert \$lut to \$\_MUX\_} \label{cmd:lut2mux} \begin{lstlisting}[numbers=left,frame=single] @@ -1582,6 +1803,15 @@ This pass adds additional circuitry that emulates the Verilog simulation behavior for out-of-bounds memory reads and writes. \end{lstlisting} +\section{memory\_nordff -- extract read port FFs from memories} +\label{cmd:memory_nordff} +\begin{lstlisting}[numbers=left,frame=single] + memory_nordff [options] [selection] + +This pass extracts FFs from memory read ports. This results in a netlist +similar to what one would get from calling memory_dff with -nordff. +\end{lstlisting} + \section{memory\_share -- consolidate memory ports} \label{cmd:memory_share} \begin{lstlisting}[numbers=left,frame=single] @@ -1745,6 +1975,15 @@ This pass only operates on completely selected modules without processes. also remove internal nets if they have a public name \end{lstlisting} +\section{opt\_demorgan -- Optimize reductions with DeMorgan equivalents} +\label{cmd:opt_demorgan} +\begin{lstlisting}[numbers=left,frame=single] + opt_demorgan [selection] + +This pass pushes inverters through $reduce_* cells if this will reduce the +overall gate count of the circuit +\end{lstlisting} + \section{opt\_expr -- perform const folding and simple expression rewriting} \label{cmd:opt_expr} \begin{lstlisting}[numbers=left,frame=single] @@ -1884,15 +2123,16 @@ on partly selected designs. -memx simulate verilog simulation behavior for out-of-bounds memory accesses - using the 'memory_memx' pass. This option implies -nordff. + using the 'memory_memx' pass. -nomem do not run any of the memory_* passes - -nordff - passed to 'memory_dff'. prohibits merging of FFs into memory read ports + -rdff + do not pass -nordff to 'memory_dff'. This enables merging of FFs into + memory read ports. - -nokeepdc + -nokeepdc do not call opt_* with -keepdc -run <from_label>[:<to_label>] @@ -2058,6 +2298,38 @@ Note: This implementation of a quadratic wirelength placer uses exact dense matrix operations. It is only a toy-placer for small circuits. \end{lstlisting} +\section{read -- load HDL designs} +\label{cmd:read} +\begin{lstlisting}[numbers=left,frame=single] + read {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal} <verilog-file>.. + +Load the specified Verilog/SystemVerilog files. (Full SystemVerilog support +is only available via Verific.) + +Additional -D<macro>[=<value>] options may be added after the option indicating +the language version (and before file names) to set additional verilog defines. + + + read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>.. + +Load the specified VHDL files. (Requires Verific.) + + + read -define <macro>[=<value>].. + +Set global Verilog/SystemVerilog defines. + + + read -undef <macro>.. + +Unset global Verilog/SystemVerilog defines. + + + read -incdir <directory> + +Add directory to global Verilog/SystemVerilog include directories. +\end{lstlisting} + \section{read\_blif -- read BLIF file} \label{cmd:read_blif} \begin{lstlisting}[numbers=left,frame=single] @@ -2067,6 +2339,10 @@ Load modules from a BLIF file into the current design. -sop Create $sop cells instead of $lut cells + + -wideports + Merge ports that match the pattern 'name[int]' into a single + multi-bit port 'name'. \end{lstlisting} \section{read\_ilang -- read modules from ilang file} @@ -2078,6 +2354,15 @@ Load modules from an ilang file to the current design. (ilang is a text representation of a design in yosys's internal format.) \end{lstlisting} +\section{read\_json -- read JSON file} +\label{cmd:read_json} +\begin{lstlisting}[numbers=left,frame=single] + read_json [filename] + +Load modules from a JSON file into the current design See "help write_json" +for a description of the file format. +\end{lstlisting} + \section{read\_liberty -- read cells from liberty file} \label{cmd:read_liberty} \begin{lstlisting}[numbers=left,frame=single] @@ -2088,9 +2373,13 @@ Read cells from liberty file as modules into current design. -lib only create empty blackbox modules - -ignore_redef + -nooverwrite ignore re-definitions of modules. (the default behavior is to - create an error message.) + create an error message if the existing module is not a blackbox + module, and overwrite the existing module if it is a blackbox module.) + + -overwrite + overwrite existing modules with the same name -ignore_miss_func ignore cells with missing function specification of outputs @@ -2099,6 +2388,9 @@ Read cells from liberty file as modules into current design. ignore cells with a missing or invalid direction specification on a pin + -ignore_miss_data_latch + ignore latches with missing data and/or enable pins + -setattr <attribute_name> set the specified attribute (to the value 1) on all loaded modules \end{lstlisting} @@ -2131,6 +2423,9 @@ Verilog-2005 is supported. -dump_ast2 dump abstract syntax tree (after simplification) + -no_dump_ptr + do not include hex memory addresses in dump (easier to diff dumps) + -dump_vlog dump ast as Verilog code (after simplification) @@ -2190,9 +2485,13 @@ Verilog-2005 is supported. -icells interpret cell types starting with '$' as internal cell types - -ignore_redef + -nooverwrite ignore re-definitions of modules. (the default behavior is to - create an error message.) + create an error message if the existing module is not a black box + module, and overwrite the existing module otherwise.) + + -overwrite + overwrite existing modules with the same name -defer only read the abstract syntax tree and defer actual compilation @@ -2221,6 +2520,10 @@ verilog input, but has not very good error reporting. It generally is recommended to use a simulator (for example Icarus Verilog) for checking the syntax of the code, rather than to rely on read_verilog for that. +Depending on if read_verilog is run in -formal mode, either the macro +SYNTHESIS or FORMAL is defined automatically. In addition, read_verilog +always defines the macro YOSYS. + See the Yosys README file for a list of non-standard Verilog features supported by the Yosys Verilog front-end. \end{lstlisting} @@ -2251,6 +2554,15 @@ with public names. This ignores all selected ports. Rename top module. \end{lstlisting} +\section{rmports -- remove module ports with no connections} +\label{cmd:rmports} +\begin{lstlisting}[numbers=left,frame=single] + rmports [selection] + +This pass identifies ports in the selected modules which are not used or +driven and removes them. +\end{lstlisting} + \section{sat -- solve a SAT problem in the circuit} \label{cmd:sat} \begin{lstlisting}[numbers=left,frame=single] @@ -2457,11 +2769,9 @@ design. are assumed to be bidirectional 'inout' ports. -set_attr <name> <value> - -set_cell_attr <name> <value> - -set_wire_attr <name> <value> - set the specified attribute on all cells and/or wires that are part of - a logic loop. the special token {} in the value is replaced with a - unique identifier for the logic loop. + set the specified attribute on all cells that are part of a logic + loop. the special token {} in the value is replaced with a unique + identifier for the logic loop. -select replace the current selection with a selection of all cells and wires @@ -2497,7 +2807,7 @@ of the design to operate on. This command can be used to modify and view this list of selected objects. Note that many commands support an optional [selection] argument that can be -used to override the global selection for the command. The syntax of this +used to YS_OVERRIDE the global selection for the command. The syntax of this optional argument is identical to the syntax of the <selection> argument described here. @@ -2728,17 +3038,29 @@ The -type option can be used to change the cell type of the selected cells. \begin{lstlisting}[numbers=left,frame=single] setundef [options] [selection] -This command replaced undef (x) constants with defined (0/1) constants. +This command replaces undef (x) constants with defined (0/1) constants. -undriven also set undriven nets to constant values + -expose + also expose undriven nets as inputs (use with -undriven) + -zero replace with bits cleared (0) -one replace with bits set (1) + -undef + replace with undef (x) bits, may be used with -undriven + + -anyseq + replace with $anyseq drivers (for formal) + + -anyconst + replace with $anyconst drivers (for formal) + -random <seed> replace with random bits using the specified integer als seed value for the random number generator. @@ -2821,6 +3143,7 @@ to a graphics file (usually SVG or PostScript). -viewer <viewer> Run the specified command with the graphics file as parameter. + On Windows, this pauses yosys until the viewer exits. -format <format> Generate a graphics file in the specified format. Use 'dot' to just @@ -2882,7 +3205,7 @@ to a graphics file (usually SVG or PostScript). do not add the module name as graph title to the dot file When no <format> is specified, 'dot' is used. When no <format> and <viewer> is -specified, 'xdot' is used to display the schematic. +specified, 'xdot' is used to display the schematic (POSIX systems only). The generated output files are '~/.yosys_show.dot' and '~/.yosys_show.<format>', unless another prefix is specified using -prefix <prefix>. @@ -2949,6 +3272,47 @@ will use the same interface as the original $_DFF_*_ cells. The cell parameter map to greenpak4 shift registers. \end{lstlisting} +\section{sim -- simulate the circuit} +\label{cmd:sim} +\begin{lstlisting}[numbers=left,frame=single] + sim [options] [top-level] + +This command simulates the circuit using the given top-level module. + + -vcd <filename> + write the simulation results to the given VCD file + + -clock <portname> + name of top-level clock input + + -clockn <portname> + name of top-level clock input (inverse polarity) + + -reset <portname> + name of top-level reset input (active high) + + -resetn <portname> + name of top-level inverted reset input (active low) + + -rstlen <integer> + number of cycles reset should stay active (default: 1) + + -zinit + zero-initialize all uninitialized regs and memories + + -n <integer> + number of cycles to simulate (default: 20) + + -a + include all nets in VCD output, not just those with public names + + -w + writeback mode: use final simulation state as new init state + + -d + enable debug output +\end{lstlisting} + \section{simplemap -- mapping simple coarse-grain cells} \label{cmd:simplemap} \begin{lstlisting}[numbers=left,frame=single] @@ -2963,22 +3327,6 @@ primitives. The following internal cell types are mapped by this pass: $sr, $ff, $dff, $dffsr, $adff, $dlatch \end{lstlisting} -\section{singleton -- create singleton modules} -\label{cmd:singleton} -\begin{lstlisting}[numbers=left,frame=single] - singleton [selection] - -By default, a module that is instantiated by several other modules is only -kept once in the design. This preserves the original modularity of the design -and reduces the overall size of the design in memory. But it prevents certain -optimizations and other operations on the design. This pass creates singleton -modules for all selected cells. The created modules are marked with the -'singleton' attribute. - -This commands only operates on modules that by themself have the 'singleton' -attribute set (the 'top' module is a singleton implicitly). -\end{lstlisting} - \section{splice -- create explicit splicing cells} \label{cmd:splice} \begin{lstlisting}[numbers=left,frame=single] @@ -3122,6 +3470,9 @@ on partly selected designs. -nordff passed to 'memory'. prohibits merging of FFs into memory read ports + -noshare + do not run SAT-based resource sharing + -run <from_label>[:<to_label>] only run the commands between the labels (see below). an empty from label is synonymous to 'begin', and empty to label is @@ -3164,6 +3515,344 @@ The following commands are executed by this synthesis command: check \end{lstlisting} +\section{synth\_achronix -- synthesis for Acrhonix Speedster22i FPGAs.} +\label{cmd:synth_achronix} +\begin{lstlisting}[numbers=left,frame=single] + synth_achronix [options] + +This command runs synthesis for Achronix Speedster eFPGAs. This work is still experimental. + + -top <module> + use the specified module as top module (default='top') + + -vout <file> + write the design to the specified Verilog netlist file. writing of an + output file is omitted if this parameter is not specified. + + -run <from_label>:<to_label> + only run the commands between the labels (see below). an empty + from label is synonymous to 'begin', and empty to label is + synonymous to the end of the command list. + + -noflatten + do not flatten design before synthesis + + -retime + run 'abc' with -dff option + + +The following commands are executed by this synthesis command: + + begin: + read_verilog -sv -lib +/achronix/speedster22i/cells_sim.v + hierarchy -check -top <top> + + flatten: (unless -noflatten) + proc + flatten + tribuf -logic + deminout + + coarse: + synth -run coarse + + fine: + opt -fast -mux_undef -undriven -fine -full + memory_map + opt -undriven -fine + dffsr2dff + dff2dffe -direct-match $_DFF_* + opt -fine + techmap -map +/techmap.v + opt -full + clean -purge + setundef -undriven -zero + abc -markgroups -dff (only if -retime) + + map_luts: + abc -lut 4 + clean + + map_cells: + iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I + techmap -map +/achronix/speedster22i/cells_map.v + clean -purge + + check: + hierarchy -check + stat + check -noinit + + vout: + write_verilog -nodec -attr2comment -defparam -renameprefix syn_ <file-name> +\end{lstlisting} + +\section{synth\_coolrunner2 -- synthesis for Xilinx Coolrunner-II CPLDs} +\label{cmd:synth_coolrunner2} +\begin{lstlisting}[numbers=left,frame=single] + synth_coolrunner2 [options] + +This command runs synthesis for Coolrunner-II CPLDs. This work is experimental. +It is intended to be used with https://github.com/azonenberg/openfpga as the +place-and-route. + + -top <module> + use the specified module as top module (default='top') + + -json <file> + write the design to the specified JSON file. writing of an output file + is omitted if this parameter is not specified. + + -run <from_label>:<to_label> + only run the commands between the labels (see below). an empty + from label is synonymous to 'begin', and empty to label is + synonymous to the end of the command list. + + -noflatten + do not flatten design before synthesis + + -retime + run 'abc' with -dff option + + +The following commands are executed by this synthesis command: + + begin: + read_verilog -lib +/coolrunner2/cells_sim.v + hierarchy -check -top <top> + + flatten: (unless -noflatten) + proc + flatten + tribuf -logic + + coarse: + synth -run coarse + + fine: + opt -fast -full + techmap + techmap -map +/coolrunner2/cells_latch.v + dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib + + map_tff: + abc -g AND,XOR + clean + extract -map +/coolrunner2/tff_extract.v + + map_pla: + abc -sop -I 40 -P 56 + clean + + map_cells: + dfflibmap -liberty +/coolrunner2/xc2_dff.lib + dffinit -ff FDCP Q INIT + dffinit -ff FDCP_N Q INIT + dffinit -ff FTCP Q INIT + dffinit -ff FTCP_N Q INIT + dffinit -ff LDCP Q INIT + dffinit -ff LDCP_N Q INIT + coolrunner2_sop + iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO + attrmvcp -attr src -attr LOC t:IOBUFE n:* + attrmvcp -attr src -attr LOC -driven t:IBUF n:* + splitnets + clean + + check: + hierarchy -check + stat + check -noinit + + json: + write_json <file-name> +\end{lstlisting} + +\section{synth\_easic -- synthesis for eASIC platform} +\label{cmd:synth_easic} +\begin{lstlisting}[numbers=left,frame=single] + synth_easic [options] + +This command runs synthesis for eASIC platform. + + -top <module> + use the specified module as top module + + -vlog <file> + write the design to the specified structural Verilog file. writing of + an output file is omitted if this parameter is not specified. + + -etools <path> + set path to the eTools installation. (default=/opt/eTools) + + -run <from_label>:<to_label> + only run the commands between the labels (see below). an empty + from label is synonymous to 'begin', and empty to label is + synonymous to the end of the command list. + + -noflatten + do not flatten design before synthesis + + -retime + run 'abc' with -dff option + + +The following commands are executed by this synthesis command: + + begin: + read_liberty -lib <etools_phys_clk_lib> + read_liberty -lib <etools_logic_lut_lib> + hierarchy -check -top <top> + + flatten: (unless -noflatten) + proc + flatten + + coarse: + synth -run coarse + + fine: + opt -fast -mux_undef -undriven -fine + memory_map + opt -undriven -fine + techmap + opt -fast + abc -dff (only if -retime) + opt_clean (only if -retime) + + map: + dfflibmap -liberty <etools_phys_clk_lib> + abc -liberty <etools_logic_lut_lib> + opt_clean + + check: + hierarchy -check + stat + check -noinit + + vlog: + write_verilog -noexpr -attr2comment <file-name> +\end{lstlisting} + +\section{synth\_ecp5 -- synthesis for ECP5 FPGAs} +\label{cmd:synth_ecp5} +\begin{lstlisting}[numbers=left,frame=single] + synth_ecp5 [options] + +This command runs synthesis for ECP5 FPGAs. + + -top <module> + use the specified module as top module + + -blif <file> + write the design to the specified BLIF file. writing of an output file + is omitted if this parameter is not specified. + + -edif <file> + write the design to the specified EDIF file. writing of an output file + is omitted if this parameter is not specified. + + -json <file> + write the design to the specified JSON file. writing of an output file + is omitted if this parameter is not specified. + + -run <from_label>:<to_label> + only run the commands between the labels (see below). an empty + from label is synonymous to 'begin', and empty to label is + synonymous to the end of the command list. + + -noflatten + do not flatten design before synthesis + + -retime + run 'abc' with -dff option + + -noccu2 + do not use CCU2 cells in output netlist + + -nodffe + do not use flipflops with CE in output netlist + + -nobram + do not use BRAM cells in output netlist + + -nodram + do not use distributed RAM cells in output netlist + + -nomux + do not use PFU muxes to implement LUTs larger than LUT4s + + -abc2 + run two passes of 'abc' for slightly improved logic density + + -vpr + generate an output netlist (and BLIF file) suitable for VPR + (this feature is experimental and incomplete) + + +The following commands are executed by this synthesis command: + + begin: + read_verilog -lib +/ecp5/cells_sim.v + hierarchy -check -top <top> + + flatten: (unless -noflatten) + proc + flatten + tribuf -logic + deminout + + coarse: + synth -run coarse + + bram: (skip if -nobram) + + dram: (skip if -nodram) + memory_bram -rules +/ecp5/dram.txt + techmap -map +/ecp5/drams_map.v + + fine: + opt -fast -mux_undef -undriven -fine + memory_map + opt -undriven -fine + techmap -map +/techmap.v -map +/ecp5/arith_map.v + abc -dff (only if -retime) + + map_ffs: + dffsr2dff + dff2dffs + opt_clean + dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_* + techmap -D NO_LUT -map +/ecp5/cells_map.v + opt_expr -mux_undef + simplemap + + map_luts: + abc (only if -abc2) + abc -lut 4:7 + clean + + map_cells: + techmap -map +/ecp5/cells_map.v (with -D NO_LUT in vpr mode) + clean + + check: + hierarchy -check + stat + check -noinit + + blif: + opt_clean -purge (vpr mode) + write_blif -attr -cname -conn -param <file-name> (vpr mode) + write_blif -gates -attr -param <file-name> (non-vpr mode) + + edif: + write_edif <file-name> + + json: + write_json <file-name> +\end{lstlisting} + \section{synth\_gowin -- synthesis for Gowin FPGAs} \label{cmd:synth_gowin} \begin{lstlisting}[numbers=left,frame=single] @@ -3228,7 +3917,7 @@ The following commands are executed by this synthesis command: check -noinit vout: - write_verilog -attr2comment -defparam -renameprefix gen <file-name> + write_verilog -nodec -attr2comment -defparam -renameprefix gen <file-name> \end{lstlisting} \section{synth\_greenpak4 -- synthesis for GreenPAK4 FPGAs} @@ -3237,6 +3926,8 @@ The following commands are executed by this synthesis command: synth_greenpak4 [options] This command runs synthesis for GreenPAK4 FPGAs. This work is experimental. +It is intended to be used with https://github.com/azonenberg/openfpga as the +place-and-route. -top <module> use the specified module as top module (default='top') @@ -3276,12 +3967,13 @@ The following commands are executed by this synthesis command: synth -run coarse fine: - greenpak4_counters + extract_counter -pout GP_DCMP,GP_DAC -maxwidth 14 clean opt -fast -mux_undef -undriven -fine memory_map opt -undriven -fine techmap + techmap -map +/greenpak4/cells_latch.v dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib opt -fast abc -dff (only if -retime) @@ -3323,14 +4015,18 @@ The following commands are executed by this synthesis command: This command runs synthesis for iCE40 FPGAs. -top <module> - use the specified module as top module (default='top') + use the specified module as top module -blif <file> write the design to the specified BLIF file. writing of an output file is omitted if this parameter is not specified. -edif <file> - write the design to the specified edif file. writing of an output file + write the design to the specified EDIF file. writing of an output file + is omitted if this parameter is not specified. + + -json <file> + write the design to the specified JSON file. writing of an output file is omitted if this parameter is not specified. -run <from_label>:<to_label> @@ -3347,12 +4043,19 @@ This command runs synthesis for iCE40 FPGAs. -nocarry do not use SB_CARRY cells in output netlist + -nodffe + do not use SB_DFFE* cells in output netlist + -nobram do not use SB_RAM40_4K* cells in output netlist -abc2 run two passes of 'abc' for slightly improved logic density + -vpr + generate an output netlist (and BLIF file) suitable for VPR + (this feature is experimental and incomplete) + The following commands are executed by this synthesis command: @@ -3384,7 +4087,7 @@ The following commands are executed by this synthesis command: map_ffs: dffsr2dff dff2dffe -direct-match $_DFF_* - techmap -map +/ice40/cells_map.v + techmap -D NO_LUT -map +/ice40/cells_map.v opt_expr -mux_undef simplemap ice40_ffinit @@ -3399,7 +4102,7 @@ The following commands are executed by this synthesis command: clean map_cells: - techmap -map +/ice40/cells_map.v + techmap -map +/ice40/cells_map.v (with -D NO_LUT in vpr mode) clean check: @@ -3408,10 +4111,116 @@ The following commands are executed by this synthesis command: check -noinit blif: - write_blif -gates -attr -param <file-name> + opt_clean -purge (vpr mode) + write_blif -attr -cname -conn -param <file-name> (vpr mode) + write_blif -gates -attr -param <file-name> (non-vpr mode) edif: write_edif <file-name> + + json: + write_json <file-name> +\end{lstlisting} + +\section{synth\_intel -- synthesis for Intel (Altera) FPGAs.} +\label{cmd:synth_intel} +\begin{lstlisting}[numbers=left,frame=single] + synth_intel [options] + +This command runs synthesis for Intel FPGAs. + + -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive> + generate the synthesis netlist for the specified family. + MAX10 is the default target if not family argument specified. + For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive. + Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument. + + -top <module> + use the specified module as top module (default='top') + + -vqm <file> + write the design to the specified Verilog Quartus Mapping File. Writing of an + output file is omitted if this parameter is not specified. + + -vpr <file> + write BLIF files for VPR flow experiments. The synthesized BLIF output file is not + compatible with the Quartus flow. Writing of an + output file is omitted if this parameter is not specified. + + -run <from_label>:<to_label> + only run the commands between the labels (see below). an empty + from label is synonymous to 'begin', and empty to label is + synonymous to the end of the command list. + + -noiopads + do not use altsyncram cells in output netlist + + -nobram + do not use altsyncram cells in output netlist + + -noflatten + do not flatten design before synthesis + + -retime + run 'abc' with -dff option + +The following commands are executed by this synthesis command: + + begin: + + family: + read_verilog -sv -lib +/intel/max10/cells_sim.v + read_verilog -sv -lib +/intel/common/m9k_bb.v + read_verilog -sv -lib +/intel/common/altpll_bb.v + hierarchy -check -top <top> + + flatten: (unless -noflatten) + proc + flatten + tribuf -logic + deminout + + coarse: + synth -run coarse + + bram: (skip if -nobram) + memory_bram -rules +/intel/common/brams.txt + techmap -map +/intel/common/brams_map.v + + fine: + opt -fast -mux_undef -undriven -fine -full + memory_map + opt -undriven -fine + dffsr2dff + dff2dffe -direct-match $_DFF_* + opt -fine + techmap -map +/techmap.v + opt -full + clean -purge + setundef -undriven -zero + abc -markgroups -dff (only if -retime) + + map_luts: + abc -lut 4 + clean + + map_cells: + iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I (unless -noiopads) + techmap -map +/intel/max10/cells_map.v + dffinit -highlow -ff dffeas q power_up + clean -purge + + check: + hierarchy -check + stat + check -noinit + + vqm: + write_verilog -attr2comment -defparam -nohex -decimal -renameprefix syn_ <file-name> + + vpr: + opt_clean -purge + write_blif <file-name> \end{lstlisting} \section{synth\_xilinx -- synthesis for Xilinx FPGAs} @@ -3430,6 +4239,14 @@ compatible with 7-Series Xilinx devices. write the design to the specified edif file. writing of an output file is omitted if this parameter is not specified. + -blif <file> + write the design to the specified BLIF file. writing of an output file + is omitted if this parameter is not specified. + + -vpr + generate an output netlist (and BLIF file) suitable for VPR + (this feature is experimental and incomplete) + -run <from_label>:<to_label> only run the commands between the labels (see below). an empty from label is synonymous to 'begin', and empty to label is @@ -3448,7 +4265,6 @@ The following commands are executed by this synthesis command: read_verilog -lib +/xilinx/cells_sim.v read_verilog -lib +/xilinx/cells_xtra.v read_verilog -lib +/xilinx/brams_bb.v - read_verilog -lib +/xilinx/drams_bb.v hierarchy -check -top <top> flatten: (only if -flatten) @@ -3480,7 +4296,7 @@ The following commands are executed by this synthesis command: clean map_cells: - techmap -map +/xilinx/cells_map.v + techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode) dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT clean @@ -3491,6 +4307,9 @@ The following commands are executed by this synthesis command: edif: (only if -edif) write_edif <file-name> + + blif: (only if -blif) + write_blif <file-name> \end{lstlisting} \section{tcl -- execute a TCL script file} @@ -3502,9 +4321,9 @@ This command executes the tcl commands in the specified file. Use 'yosys cmd' to run the yosys command 'cmd' from tcl. The tcl command 'yosys -import' can be used to import all yosys -commands directly as tcl commands to the tcl shell. The yosys -command 'proc' is wrapped using the tcl command 'procs' in order -to avoid a name collision with the tcl builtin command 'proc'. +commands directly as tcl commands to the tcl shell. Yosys commands +'proc' and 'rename' are wrapped to tcl commands 'procs' and 'renames' +in order to avoid a name collision with the built in commands. \end{lstlisting} \section{techmap -- generic technology mapper} @@ -3548,7 +4367,7 @@ file. -D <define>, -I <incdir> this options are passed as-is to the Verilog frontend for loading the map file. Note that the Verilog frontend is also called with the - '-ignore_redef' option set. + '-nooverwrite' option set. When a module in the map file has the 'techmap_celltype' attribute set, it will match cells with a type that match the text value of this attribute. Otherwise @@ -3629,7 +4448,7 @@ the design is connected to a constant value. The parameter is then set to the constant value. A cell with the name _TECHMAP_REPLACE_ in the map file will inherit the name -of the cell that is being replaced. +and attributes of the cell that is being replaced. See 'help extract' for a pass that does the opposite thing. @@ -3795,24 +4614,134 @@ This pass transforms $mux cells with 'z' inputs to tristate buffers. to non-tristate logic. this option implies -merge. \end{lstlisting} +\section{uniquify -- create unique copies of modules} +\label{cmd:uniquify} +\begin{lstlisting}[numbers=left,frame=single] + uniquify [selection] + +By default, a module that is instantiated by several other modules is only +kept once in the design. This preserves the original modularity of the design +and reduces the overall size of the design in memory. But it prevents certain +optimizations and other operations on the design. This pass creates unique +modules for all selected cells. The created modules are marked with the +'unique' attribute. + +This commands only operates on modules that by themself have the 'unique' +attribute set (the 'top' module is unique implicitly). +\end{lstlisting} + \section{verific -- load Verilog and VHDL designs using Verific} \label{cmd:verific} \begin{lstlisting}[numbers=left,frame=single] - verific {-vlog95|-vlog2k|-sv2005|-sv2009|-sv} <verilog-file>.. + verific {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv} <verilog-file>.. Load the specified Verilog/SystemVerilog files into Verific. +All files specified in one call to this command are one compilation unit. +Files passed to different calls to this command are treated as belonging to +different compilation units. + +Additional -D<macro>[=<value>] options may be added after the option indicating +the language version (and before file names) to set additional verilog defines. +The macros SYNTHESIS and VERIFIC are defined implicitly. + + + verific -formal <verilog-file>.. - verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008} <vhdl-file>.. +Like -sv, but define FORMAL instead of SYNTHESIS. + + + verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>.. Load the specified VHDL files into Verific. - verific -import [-gates] {-all | <top-module>..} + verific -work <libname> {-sv|-vhdl|...} <hdl-file> + +Load the specified Verilog/SystemVerilog/VHDL file into the specified library. +(default library when -work is not present: "work") + + + verific -vlog-incdir <directory>.. + +Add Verilog include directories. + + + verific -vlog-libdir <directory>.. + +Add Verilog library directories. Verific will search in this directories to +find undefined modules. + + + verific -vlog-define <macro>[=<value>].. + +Add Verilog defines. + + + verific -vlog-undef <macro>.. + +Remove Verilog defines previously set with -vlog-define. + + + verific -set-error <msg_id>.. + verific -set-warning <msg_id>.. + verific -set-info <msg_id>.. + verific -set-ignore <msg_id>.. + +Set message severity. <msg_id> is the string in square brackets when a message +is printed, such as VERI-1209. + + + verific -import [options] <top-module>.. Elaborate the design for the specified top modules, import to Yosys and -reset the internal state of Verific. A gate-level netlist is created -when called with -gates. +reset the internal state of Verific. + +Import options: + + -all + Elaborate all modules, not just the hierarchy below the given top + modules. With this option the list of modules to import is optional. + + -gates + Create a gate-level netlist. + + -flatten + Flatten the design in Verific before importing. + + -extnets + Resolve references to external nets by adding module ports as needed. + + -autocover + Generate automatic cover statements for all asserts + + -v, -vv + Verbose log messages. (-vv is even more verbose than -v.) + +The following additional import options are useful for debugging the Verific +bindings (for Yosys and/or Verific developers): + + -k + Keep going after an unsupported verific primitive is found. The + unsupported primitive is added as blockbox module to the design. + This will also add all SVA related cells to the design parallel to + the checker logic inferred by it. + + -V + Import Verific netlist as-is without translating to Yosys cell types. + + -nosva + Ignore SVA properties, do not infer checker logic. + + -L <int> + Maximum number of ctrl bits for SVA checker FSMs (default=16). + + -n + Keep all Verific names on instances and nets. By default only + user-declared names are preserved. + + -d <dump_file> + Dump the Verific netlist as a verilog file. Visit http://verific.com/ for more information on Verific. \end{lstlisting} @@ -3837,40 +4766,19 @@ Push or pop the list of default options to a stack. Note that -push does not imply -clear. \end{lstlisting} -\section{vhdl2verilog -- importing VHDL designs using vhdl2verilog} -\label{cmd:vhdl2verilog} +\section{verilog\_defines -- define and undefine verilog defines} +\label{cmd:verilog_defines} \begin{lstlisting}[numbers=left,frame=single] - vhdl2verilog [options] <vhdl-file>.. - -This command reads VHDL source files using the 'vhdl2verilog' tool and the -Yosys Verilog frontend. - - -out <out_file> - do not import the vhdl2verilog output. instead write it to the - specified file. - - -vhdl2verilog_dir <directory> - do use the specified vhdl2verilog installation. this is the directory - that contains the setup_env.sh file. when this option is not present, - it is assumed that vhdl2verilog is in the PATH environment variable. + verilog_defines [options] - -top <top-entity-name> - The name of the top entity. This option is mandatory. +Define and undefine verilog preprocessor macros. -The following options are passed as-is to vhdl2verilog: - - -arch <architecture_name> - -unroll_generate - -nogenericeval - -nouniquify - -oldparser - -suppress <list> - -quiet - -nobanner - -mapfile <file> + -Dname[=definition] + define the preprocessor symbol 'name' and set its optional value + 'definition' -vhdl2verilog can be obtained from: -http://www.edautils.com/vhdl2verilog.html + -Uname[=definition] + undefine the preprocessor symbol 'name' \end{lstlisting} \section{wreduce -- reduce the word size of operations if possible} @@ -3892,6 +4800,38 @@ Options: flows that use the 'memory_memx' pass. \end{lstlisting} +\section{write\_aiger -- write design to AIGER file} +\label{cmd:write_aiger} +\begin{lstlisting}[numbers=left,frame=single] + write_aiger [options] [filename] + +Write the current design to an AIGER file. The design must be flattened and +must not contain any cell types except $_AND_, $_NOT_, simple FF types, +$assert and $assume cells, and $initstate cells. + +$assert and $assume cells are converted to AIGER bad state properties and +invariant constraints. + + -ascii + write ASCII version of AGIER format + + -zinit + convert FFs to zero-initialized FFs, adding additional inputs for + uninitialized FFs. + + -miter + design outputs are AIGER bad state properties + + -symbols + include a symbol table in the generated AIGER file + + -map <filename> + write an extra file with port and latch symbols + + -vmap <filename> + like -map, but more verbose +\end{lstlisting} + \section{write\_blif -- write design to BLIF file} \label{cmd:write_blif} \begin{lstlisting}[numbers=left,frame=single] @@ -3949,6 +4889,11 @@ file *.blif when any of this options is used. -cname use the non-standard .cname statement to write cell names + -iname, -iattr + enable -cname and -attr functionality for .names statements + (the .cname and .attr statements will be included in the BLIF + output after the truth table for the .names statement) + -blackbox write blackbox cells with .blackbox statement. @@ -3959,9 +4904,15 @@ file *.blif when any of this options is used. \section{write\_btor -- write design to BTOR file} \label{cmd:write_btor} \begin{lstlisting}[numbers=left,frame=single] - write_btor [filename] + write_btor [options] [filename] + +Write a BTOR description of the current design. -Write the current design to an BTOR file. + -v + Add comments and indentation to BTOR output file + + -s + Output only a single bad property for all asserts \end{lstlisting} \section{write\_edif -- write design to EDIF netlist file} @@ -3979,6 +4930,10 @@ Write the current design to an EDIF netlist file. if the design contains constant nets. use "hilomap" to map to custom constant drivers first) + -pvector {par|bra|ang} + sets the delimiting character for module port rename clauses to + parentheses, square brackets, or angle brackets. + Unfortunately there are different "flavors" of the EDIF file format. This command generates EDIF files for the Xilinx place&route tools. It might be necessary to make small modifications to this command when a different tool @@ -4003,6 +4958,14 @@ Inside a script the input file can also can a here-document: EOT \end{lstlisting} +\section{write\_firrtl -- write design to a FIRRTL file} +\label{cmd:write_firrtl} +\begin{lstlisting}[numbers=left,frame=single] + write_firrtl [options] [filename] + +Write a FIRRTL netlist of the current design. +\end{lstlisting} + \section{write\_ilang -- write design to ilang file} \label{cmd:write_ilang} \begin{lstlisting}[numbers=left,frame=single] @@ -4123,6 +5086,10 @@ values referenced above are vectors of this integers. Signal bits that are connected to a constant driver are denoted as string "0" or "1" instead of a number. +Numeric parameter and attribute values up to 32 bits are written as decimal +values. Numbers larger than that are written as string holding the binary +representation of the value. + For example the following Verilog code: module test(input x, y); @@ -4242,43 +5209,109 @@ Future version of Yosys might add support for additional fields in the JSON format. A program processing this format must ignore all unknown fields. \end{lstlisting} -\section{write\_smt2 -- write design to SMT-LIBv2 file} -\label{cmd:write_smt2} +\section{write\_simplec -- convert design to simple C code} +\label{cmd:write_simplec} \begin{lstlisting}[numbers=left,frame=single] - write_smt2 [options] [filename] + write_simplec [options] [filename] -Write a SMT-LIBv2 [1] description of the current design. For a module with name -'<mod>' this will declare the sort '<mod>_s' (state of the module) and the -functions operating on that state. +Write simple C code for simulating the design. The C code writen can be used to +simulate the design in a C environment, but the purpose of this command is to +generate code that works well with C-based formal verification. -The '<mod>_s' sort represents a module state. Additional '<mod>_n' functions -are provided that can be used to access the values of the signals in the module. -By default only ports, registers, and wires with the 'keep' attribute set are -made available via such functions. With the -nobv option, multi-bit wires are -exported as separate functions of type Bool for the individual bits. Without --nobv multi-bit wires are exported as single functions of type BitVec. + -verbose + this will print the recursive walk used to export the modules. -The '<mod>_t' function evaluates to 'true' when the given pair of states -describes a valid state transition. + -i8, -i16, -i32, -i64 + set the maximum integer bit width to use in the generated code. -The '<mod>_a' function evaluates to 'true' when the given state satisfies -the asserts in the module. +THIS COMMAND IS UNDER CONSTRUCTION +\end{lstlisting} -The '<mod>_u' function evaluates to 'true' when the given state satisfies -the assumptions in the module. +\section{write\_smt2 -- write design to SMT-LIBv2 file} +\label{cmd:write_smt2} +\begin{lstlisting}[numbers=left,frame=single] + write_smt2 [options] [filename] -The '<mod>_i' function evaluates to 'true' when the given state conforms -to the initial state. Furthermore the '<mod>_is' function should be asserted -to be true for initial states in addition to '<mod>_i', and should be -asserted to be false for non-initial states. +Write a SMT-LIBv2 [1] description of the current design. For a module with name +'<mod>' this will declare the sort '<mod>_s' (state of the module) and will +define and declare functions operating on that state. + +The following SMT2 functions are generated for a module with name '<mod>'. +Some declarations/definitions are printed with a special comment. A prover +using the SMT2 files can use those comments to collect all relevant metadata +about the design. + + ; yosys-smt2-module <mod> + (declare-sort |<mod>_s| 0) + The sort representing a state of module <mod>. + + (define-fun |<mod>_h| ((state |<mod>_s|)) Bool (...)) + This function must be asserted for each state to establish the + design hierarchy. + + ; yosys-smt2-input <wirename> <width> + ; yosys-smt2-output <wirename> <width> + ; yosys-smt2-register <wirename> <width> + ; yosys-smt2-wire <wirename> <width> + (define-fun |<mod>_n <wirename>| (|<mod>_s|) (_ BitVec <width>)) + (define-fun |<mod>_n <wirename>| (|<mod>_s|) Bool) + For each port, register, and wire with the 'keep' attribute set an + accessor function is generated. Single-bit wires are returned as Bool, + multi-bit wires as BitVec. + + ; yosys-smt2-cell <submod> <instancename> + (declare-fun |<mod>_h <instancename>| (|<mod>_s|) |<submod>_s|) + There is a function like that for each hierarchical instance. It + returns the sort that represents the state of the sub-module that + implements the instance. + + (declare-fun |<mod>_is| (|<mod>_s|) Bool) + This function must be asserted 'true' for initial states, and 'false' + otherwise. + + (define-fun |<mod>_i| ((state |<mod>_s|)) Bool (...)) + This function must be asserted 'true' for initial states. For + non-initial states it must be left unconstrained. + + (define-fun |<mod>_t| ((state |<mod>_s|) (next_state |<mod>_s|)) Bool (...)) + This function evaluates to 'true' if the states 'state' and + 'next_state' form a valid state transition. + + (define-fun |<mod>_a| ((state |<mod>_s|)) Bool (...)) + This function evaluates to 'true' if all assertions hold in the state. + + (define-fun |<mod>_u| ((state |<mod>_s|)) Bool (...)) + This function evaluates to 'true' if all assumptions hold in the state. + + ; yosys-smt2-assert <id> <filename:linenum> + (define-fun |<mod>_a <id>| ((state |<mod>_s|)) Bool (...)) + Each $assert cell is converted into one of this functions. The function + evaluates to 'true' if the assert statement holds in the state. + + ; yosys-smt2-assume <id> <filename:linenum> + (define-fun |<mod>_u <id>| ((state |<mod>_s|)) Bool (...)) + Each $assume cell is converted into one of this functions. The function + evaluates to 'true' if the assume statement holds in the state. + + ; yosys-smt2-cover <id> <filename:linenum> + (define-fun |<mod>_c <id>| ((state |<mod>_s|)) Bool (...)) + Each $cover cell is converted into one of this functions. The function + evaluates to 'true' if the cover statement is activated in the state. -For hierarchical designs, the '<mod>_h' function must be asserted for each -state to establish the design hierarchy. The '<mod>_h <cellname>' function -evaluates to the state corresponding to the given cell within <mod>. +Options: -verbose this will print the recursive walk used to export the modules. + -stbv + Use a BitVec sort to represent a state instead of an uninterpreted + sort. As a side-effect this will prevent use of arrays to model + memories. + + -stdt + Use SMT-LIB 2.6 style datatypes to represent a state instead of an + uninterpreted sort. + -nobv disable support for BitVec (FixedSizeBitVectors theory). without this option multi-bit wires are represented using the BitVec sort and @@ -4394,6 +5427,25 @@ Write the current design to an SPICE netlist file. set the specified module as design top module \end{lstlisting} +\section{write\_table -- write design as connectivity table} +\label{cmd:write_table} +\begin{lstlisting}[numbers=left,frame=single] + write_table [options] [filename] + +Write the current design as connectivity table. The output is a tab-separated +ASCII table with the following columns: + + module name + cell name + cell type + cell port + direction + signal + +module inputs and outputs are output using cell type and port '-' and with +'pi' (primary input) or 'po' (primary output) or 'pio' as direction. +\end{lstlisting} + \section{write\_verilog -- write design to Verilog file} \label{cmd:write_verilog} \begin{lstlisting}[numbers=left,frame=single] @@ -4424,6 +5476,14 @@ Write the current design to a Verilog file. not bit pattern. This option deactivates this feature and instead will write out all constants in binary. + -decimal + dump 32-bit constants in decimal and without size and radix + + -nohex + constant values that are compatible with hex output are usually + dumped as hex values. This option deactivates this feature and + instead will write out all constants in binary. + -nostr Parameters and attributes that are specified as strings in the original input will be output as strings by this back-end. This diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index b1f88d55e..66ee28aff 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -40,6 +40,16 @@ struct EquivMakeWorker pool<SigBit> undriven_bits; SigMap assign_map; + dict<SigBit, pool<Cell*>> bit2driven; // map: bit <--> and its driven cells + + CellTypes comb_ct; + + EquivMakeWorker() + { + comb_ct.setup_internals(); + comb_ct.setup_stdcells(); + } + void read_blacklists() { for (auto fn : blacklists) @@ -278,12 +288,20 @@ struct EquivMakeWorker } } + init_bit2driven(); + + pool<Cell*> visited_cells; for (auto c : cells_list) for (auto &conn : c->connections()) if (!ct.cell_output(c->type, conn.first)) { SigSpec old_sig = assign_map(conn.second); SigSpec new_sig = rd_signal_map(old_sig); + + visited_cells.clear(); if (old_sig != new_sig) { + if (check_signal_in_fanout(visited_cells, old_sig, new_sig)) + continue; + log("Changing input %s of cell %s (%s): %s -> %s\n", log_id(conn.first), log_id(c), log_id(c->type), log_signal(old_sig), log_signal(new_sig)); @@ -378,6 +396,57 @@ struct EquivMakeWorker } } + void init_bit2driven() + { + for (auto cell : equiv_mod->cells()) { + if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) + continue; + for (auto &conn : cell->connections()) + { + if (yosys_celltypes.cell_input(cell->type, conn.first)) + for (auto bit : assign_map(conn.second)) + { + bit2driven[bit].insert(cell); + } + } + } + } + + bool check_signal_in_fanout(pool<Cell*> & visited_cells, SigBit source_bit, SigBit target_bit) + { + if (source_bit == target_bit) + return true; + + if (bit2driven.count(source_bit) == 0) + return false; + + auto driven_cells = bit2driven.at(source_bit); + for (auto driven_cell: driven_cells) + { + bool is_comb = comb_ct.cell_known(driven_cell->type); + if (!is_comb) + continue; + + if (visited_cells.count(driven_cell) > 0) + continue; + visited_cells.insert(driven_cell); + + for (auto &conn: driven_cell->connections()) + { + if (yosys_celltypes.cell_input(driven_cell->type, conn.first)) + continue; + + for (auto bit: conn.second) { + bool is_in_fanout = check_signal_in_fanout(visited_cells, bit, target_bit); + if (is_in_fanout == true) + return true; + } + } + } + + return false; + } + void run() { copy_to_equiv(); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 5df69848e..7e93a6f9a 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -145,9 +146,25 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check std::map<RTLIL::Cell*, std::pair<int, int>> array_cells; std::string filename; + // Always keep track of all derived interfaces available in the current module in 'interfaces_in_module': + dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module; for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; + if(cell->get_bool_attribute("\\is_interface")) { + RTLIL::Module *intf_module = design->modules_[cell->type]; + interfaces_in_module[cell->name] = intf_module; + } + } + + for (auto &cell_it : module->cells_) + { + RTLIL::Cell *cell = cell_it.second; + bool has_interfaces_not_found = false; + + std::vector<RTLIL::IdString> connections_to_remove; + std::vector<RTLIL::IdString> connections_to_add_name; + std::vector<RTLIL::SigSpec> connections_to_add_signal; if (cell->type.substr(0, 7) == "$array:") { int pos_idx = cell->type.str().find_first_of(':'); @@ -158,6 +175,8 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check array_cells[cell] = std::pair<int, int>(idx, num); cell->type = cell->type.str().substr(pos_type + 1); } + dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule; + dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule; if (design->modules_.count(cell->type) == 0) { @@ -200,11 +219,76 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check if (design->modules_.count(cell->type) == 0) log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str()); did_something = true; - } else + } else { + + RTLIL::Module *mod = design->module(cell->type); + + // Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to + // some lists, so that the ports for sub-modules can be replaced further down: + for (auto &conn : cell->connections()) { + if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list + //const pool<string> &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_type"); + //for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module (not crucially important, but good for robustness) + //} + + // Find if the sub-module has set a modport for the current interface connection: + const pool<string> &interface_modport_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_modport"); + std::string interface_modport = ""; + for (auto &d : interface_modport_pool) { + interface_modport = "\\" + d; + } + if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) { // Check if the connected wire is a potential interface in the parent module + std::string interface_name_str = conn.second.bits()[0].wire->name.str(); + interface_name_str.replace(0,23,""); // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name + interface_name_str = "\\" + interface_name_str; + RTLIL::IdString interface_name = interface_name_str; + bool not_found_interface = false; + if(module->get_bool_attribute("\\interfaces_replaced_in_module")) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either + if (interfaces_in_module.count(interface_name) > 0) { // Check if the interface instance is present in module + RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name); + for (auto &mod_wire : mod_replace_ports->wires_) { // Go over all wires in interface, and add replacements to lists. + std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire.first); + std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire.first); + connections_to_add_name.push_back(RTLIL::IdString(signal_name1)); + if(module->wires_.count(signal_name2) == 0) { + log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), log_id(module->name)); + } + else { + RTLIL::Wire *wire_in_parent = module->wire(signal_name2); + connections_to_add_signal.push_back(wire_in_parent); + } + } + connections_to_remove.push_back(conn.first); + interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name); + + // Add modports to a dict which will be passed to AstModule::derive + if (interface_modport != "") { + modports_used_in_submodule[conn.first] = interface_modport; + } + } + else not_found_interface = true; + } + else not_found_interface = true; + // If the interface instance has not already been derived in the module, we cannot complete at this stage. Set "has_interfaces_not_found" + // which will delay the expansion of this cell: + if (not_found_interface) { + // If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error: + if(!(module->get_bool_attribute("\\cells_not_processed"))) { + log_warning("Could not find interface instance for `%s' in `%s'\n", log_id(interface_name), log_id(module)); + } + else { + // Only set has_interfaces_not_found if it would be possible to find them, since otherwiser we will end up in an infinite loop: + has_interfaces_not_found = true; + } + } + } + } + } + // + if (flag_check || flag_simcheck) { - RTLIL::Module *mod = design->module(cell->type); - for (auto &conn : cell->connections()) + for (auto &conn : cell->connections()) { if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { int id = atoi(conn.first.c_str()+1); if (id <= 0 || id > GetSize(mod->ports)) @@ -213,11 +297,15 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check } else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0) log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first)); + } for (auto ¶m : cell->parameters) if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL) log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(param.first)); + + } } + RTLIL::Module *mod = design->modules_[cell->type]; if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) { if (flag_simcheck) @@ -226,15 +314,62 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check continue; } - if (cell->parameters.size() == 0) + // If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here: + if(has_interfaces_not_found) { + did_something = true; // waiting for interfaces to be handled continue; + } - RTLIL::Module *mod = design->modules_[cell->type]; - cell->type = mod->derive(design, cell->parameters); + // Do the actual replacements of the SV interface port connection with the individual signal connections: + for(unsigned int i=0;i<connections_to_add_name.size();i++) { + cell->connections_[connections_to_add_name[i]] = connections_to_add_signal[i]; + } + // Remove the connection for the interface itself: + for(unsigned int i=0;i<connections_to_remove.size();i++) { + cell->connections_.erase(connections_to_remove[i]); + } + + // If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type + // for the cell: + if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute("\\module_not_derived")))) { + // If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:", + // so that the signals of the interface are added to the parent module. + if (mod->get_bool_attribute("\\is_interface")) { + goto handle_interface_instance; + } + continue; + } + + cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule, modports_used_in_submodule); cell->parameters.clear(); did_something = true; + + handle_interface_instance: + + // We add all the signals of the interface explicitly to the parent module. This is always needed when we encounter + // an interface instance: + if (mod->get_bool_attribute("\\is_interface") && cell->get_bool_attribute("\\module_not_derived")) { + cell->set_bool_attribute("\\is_interface"); + RTLIL::Module *derived_module = design->modules_[cell->type]; + interfaces_in_module[cell->name] = derived_module; + did_something = true; + } + // We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell) + cell->attributes.erase("\\module_not_derived"); + } + // Clear the attribute 'cells_not_processed' such that it can be known that we + // have been through all cells at least once, and that we can know whether + // to flag an error because of interface instances not found: + module->attributes.erase("\\cells_not_processed"); + + + // If any interface instances were found in the module, we need to rederive it completely: + if (interfaces_in_module.size() > 0 && !module->get_bool_attribute("\\interfaces_replaced_in_module")) { + module->reprocess_module(design, interfaces_in_module); + return did_something; } + for (auto &it : array_cells) { RTLIL::Cell *cell = it.first; @@ -341,6 +476,20 @@ int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db) return db.at(module); } +RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod) +{ + if(top_mod != NULL && top_mod->get_bool_attribute("\\initial_top")) + return top_mod; + else { + for (auto mod : design->modules()) { + if (mod->get_bool_attribute("\\top")) { + return mod; + } + } + } + return NULL; +} + struct HierarchyPass : public Pass { HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { } void help() YS_OVERRIDE @@ -568,6 +717,14 @@ struct HierarchyPass : public Pass { if (flag_simcheck && top_mod == nullptr) log_error("Design has no top module.\n"); + if (top_mod != NULL) { + for (auto &mod_it : design->modules_) + if (mod_it.second == top_mod) + mod_it.second->attributes["\\initial_top"] = RTLIL::Const(1); + else + mod_it.second->attributes.erase("\\initial_top"); + } + bool did_something = true; while (did_something) { @@ -586,19 +743,43 @@ struct HierarchyPass : public Pass { if (expand_module(design, module, flag_check, flag_simcheck, libdirs)) did_something = true; } + + + // The top module might have changed if interface instances have been detected in it: + RTLIL::Module *tmp_top_mod = check_if_top_has_changed(design, top_mod); + if (tmp_top_mod != NULL) { + if (tmp_top_mod != top_mod){ + top_mod = tmp_top_mod; + did_something = true; + } + } + + // Delete modules marked as 'to_delete': + std::vector<RTLIL::Module *> modules_to_delete; + for(auto &mod_it : design->modules_) { + if (mod_it.second->get_bool_attribute("\\to_delete")) { + modules_to_delete.push_back(mod_it.second); + } + } + for(size_t i=0; i<modules_to_delete.size(); i++) { + design->remove(modules_to_delete[i]); + } } + if (top_mod != NULL) { log_header(design, "Analyzing design hierarchy..\n"); hierarchy_clean(design, top_mod, purge_lib); } if (top_mod != NULL) { - for (auto &mod_it : design->modules_) + for (auto &mod_it : design->modules_) { if (mod_it.second == top_mod) mod_it.second->attributes["\\top"] = RTLIL::Const(1); else mod_it.second->attributes.erase("\\top"); + mod_it.second->attributes.erase("\\initial_top"); + } } if (!nokeep_asserts) { diff --git a/techlibs/ecp5/.gitignore b/techlibs/ecp5/.gitignore new file mode 100644 index 000000000..54c329735 --- /dev/null +++ b/techlibs/ecp5/.gitignore @@ -0,0 +1,9 @@ +bram_init_1_2_4.vh +bram_init_9_18_36.vh +brams_init.mk +bram_conn_1.vh +bram_conn_2.vh +bram_conn_4.vh +bram_conn_9.vh +bram_conn_18.vh +brams_connect.mk diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc index 9d3247347..f45859392 100644 --- a/techlibs/ecp5/Makefile.inc +++ b/techlibs/ecp5/Makefile.inc @@ -5,4 +5,38 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt)) $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) + +EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk +.SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk + +techlibs/ecp5/brams_init.mk: techlibs/ecp5/brams_init.py + $(Q) mkdir -p techlibs/ecp5 + $(P) python3 $< + $(Q) touch $@ + +techlibs/ecp5/brams_connect.mk: techlibs/ecp5/brams_connect.py + $(Q) mkdir -p techlibs/ecp5 + $(P) python3 $< + $(Q) touch $@ + + +techlibs/ecp5/bram_init_1_2_4.vh: techlibs/ecp5/brams_init.mk +techlibs/ecp5/bram_init_9_18_36.vh: techlibs/ecp5/brams_init.mk + +techlibs/ecp5/bram_conn_1.vh: techlibs/ecp5/brams_connect.mk +techlibs/ecp5/bram_conn_2.vh: techlibs/ecp5/brams_connect.mk +techlibs/ecp5/bram_conn_4.vh: techlibs/ecp5/brams_connect.mk +techlibs/ecp5/bram_conn_9.vh: techlibs/ecp5/brams_connect.mk +techlibs/ecp5/bram_conn_18.vh: techlibs/ecp5/brams_connect.mk + +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_1_2_4.vh)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_9_18_36.vh)) + +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_1.vh)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_2.vh)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_4.vh)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_9.vh)) +$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_18.vh)) diff --git a/techlibs/ecp5/bram.txt b/techlibs/ecp5/bram.txt new file mode 100644 index 000000000..f223a42b8 --- /dev/null +++ b/techlibs/ecp5/bram.txt @@ -0,0 +1,29 @@ +bram $__ECP5_DP16KD + init 1 + + abits 10 @a10d18 + dbits 18 @a10d18 + abits 11 @a11d9 + dbits 9 @a11d9 + abits 12 @a12d4 + dbits 4 @a12d4 + abits 13 @a13d2 + dbits 2 @a13d2 + abits 14 @a14d1 + dbits 1 @a14d1 + + groups 2 + ports 1 1 + wrmode 1 0 + enable 2 1 @a10d18 + enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 + transp 0 2 + clocks 2 3 + clkpol 2 3 +endbram + +match $__ECP5_DP16KD + min bits 2048 + min efficiency 5 + shuffle_enable B +endmatch diff --git a/techlibs/ecp5/brams_connect.py b/techlibs/ecp5/brams_connect.py new file mode 100755 index 000000000..f86dcfcf0 --- /dev/null +++ b/techlibs/ecp5/brams_connect.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +def write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits): + ada_conn = [".ADA%d(%s)" % (i, ada_bits[i]) for i in range(len(ada_bits))] + adb_conn = [".ADB%d(%s)" % (i, adb_bits[i]) for i in range(len(adb_bits))] + dia_conn = [".DIA%d(%s)" % (i, dia_bits[i]) for i in range(len(dia_bits))] + dob_conn = [".DOB%d(%s)" % (i, dob_bits[i]) for i in range(len(dob_bits))] + print(" %s," % ", ".join(ada_conn), file=f) + print(" %s," % ", ".join(adb_conn), file=f) + print(" %s," % ", ".join(dia_conn), file=f) + print(" %s," % ", ".join(dob_conn), file=f) + +with open("techlibs/ecp5/bram_conn_1.vh", "w") as f: + ada_bits = ["A1ADDR[%d]" % i for i in range(14)] + adb_bits = ["B1ADDR[%d]" % i for i in range(14)] + dia_bits = ["A1DATA[0]"] + ["1'b0" for i in range(17)] + dob_bits = ["B1DATA[0]"] + write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits) + +with open("techlibs/ecp5/bram_conn_2.vh", "w") as f: + ada_bits = ["1'b0"] + ["A1ADDR[%d]" % i for i in range(13)] + adb_bits = ["1'b0"] + ["B1ADDR[%d]" % i for i in range(13)] + dia_bits = ["A1DATA[%d]" % i for i in range(2)] + ["1'b0" for i in range(16)] + dob_bits = ["B1DATA[%d]" % i for i in range(2)] + write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits) + +with open("techlibs/ecp5/bram_conn_4.vh", "w") as f: + ada_bits = ["1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(12)] + adb_bits = ["1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(12)] + dia_bits = ["A1DATA[%d]" % i for i in range(4)] + ["1'b0" for i in range(14)] + dob_bits = ["B1DATA[%d]" % i for i in range(4)] + write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits) + +with open("techlibs/ecp5/bram_conn_9.vh", "w") as f: + ada_bits = ["1'b0", "1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(11)] + adb_bits = ["1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(11)] + dia_bits = ["A1DATA[%d]" % i for i in range(9)] + ["1'b0" for i in range(9)] + dob_bits = ["B1DATA[%d]" % i for i in range(9)] + write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits) + +with open("techlibs/ecp5/bram_conn_18.vh", "w") as f: + ada_bits = ["A1EN[0]", "A1EN[1]", "1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(10)] + adb_bits = ["1'b0", "1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(10)] + dia_bits = ["A1DATA[%d]" % i for i in range(18)] + dob_bits = ["B1DATA[%d]" % i for i in range(18)] + write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits) diff --git a/techlibs/ecp5/brams_init.py b/techlibs/ecp5/brams_init.py new file mode 100755 index 000000000..96a47bdcd --- /dev/null +++ b/techlibs/ecp5/brams_init.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +with open("techlibs/ecp5/bram_init_1_2_4.vh", "w") as f: + for i in range(0, 0x40): + init_snippets = [] + for j in range(32): + init_snippets.append("INIT[%4d*8 +: 8]" % (32 * i + j)) + init_snippets.append("3'b000" if (j % 2 == 1) else "1'b0") + init_snippets = list(reversed(init_snippets)) + for k in range(8, 64, 8): + init_snippets[k] = "\n " + init_snippets[k] + print(".INITVAL_%02X({%s})," % (i, ", ".join(init_snippets)), file=f) + +with open("techlibs/ecp5/bram_init_9_18_36.vh", "w") as f: + for i in range(0, 0x40): + init_snippets = [] + for j in range(16): + init_snippets.append("INIT[%3d*18 +: 18]" % (16 * i + j)) + init_snippets.append("2'b00") + init_snippets = list(reversed(init_snippets)) + for k in range(8, 32, 8): + init_snippets[k] = "\n " + init_snippets[k] + print(".INITVAL_%02X({%s})," % (i, ", ".join(init_snippets)), file=f) diff --git a/techlibs/ecp5/brams_map.v b/techlibs/ecp5/brams_map.v new file mode 100644 index 000000000..b2c136863 --- /dev/null +++ b/techlibs/ecp5/brams_map.v @@ -0,0 +1,115 @@ +module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 10; + parameter CFG_DBITS = 18; + parameter CFG_ENABLE_A = 2; + + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [18431:0] INIT = 18432'bx; + parameter TRANSP2 = 0; + + input CLK2; + input CLK3; + + input [CFG_ABITS-1:0] A1ADDR; + input [CFG_DBITS-1:0] A1DATA; + input [CFG_ENABLE_A-1:0] A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + output [CFG_DBITS-1:0] B1DATA; + input B1EN; + + localparam CLKAMUX = CLKPOL2 ? "CLKA" : "INV"; + localparam CLKBMUX = CLKPOL3 ? "CLKB" : "INV"; + + localparam WRITEMODE_A = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE"; + + generate if (CFG_DBITS == 1) begin + DP16KD #( + `include "bram_init_1_2_4.vh" + .DATA_WIDTH_A(1), + .DATA_WIDTH_B(1), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WRITEMODE_A(WRITEMODE_A), + .WRITEMODE_B("READBEFOREWRITE"), + .GSR("DISABLED") + ) _TECHMAP_REPLACE_ ( + `include "bram_conn_1.vh" + .CLKA(CLK2), .CLKB(CLK3), + .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1), + .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1), + .RSTA(1'b0), .RSTB(1'b0) + ); + end else if (CFG_DBITS == 2) begin + DP16KD #( + `include "bram_init_1_2_4.vh" + .DATA_WIDTH_A(2), + .DATA_WIDTH_B(2), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WRITEMODE_A(WRITEMODE_A), + .WRITEMODE_B("READBEFOREWRITE"), + .GSR("DISABLED") + ) _TECHMAP_REPLACE_ ( + `include "bram_conn_2.vh" + .CLKA(CLK2), .CLKB(CLK3), + .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1), + .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1), + .RSTA(1'b0), .RSTB(1'b0) + ); + end else if (CFG_DBITS <= 4) begin + DP16KD #( + `include "bram_init_1_2_4.vh" + .DATA_WIDTH_A(4), + .DATA_WIDTH_B(4), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WRITEMODE_A(WRITEMODE_A), + .WRITEMODE_B("READBEFOREWRITE"), + .GSR("DISABLED") + ) _TECHMAP_REPLACE_ ( + `include "bram_conn_4.vh" + .CLKA(CLK2), .CLKB(CLK3), + .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1), + .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1), + .RSTA(1'b0), .RSTB(1'b0) + ); + end else if (CFG_DBITS <= 9) begin + DP16KD #( + `include "bram_init_9_18_36.vh" + .DATA_WIDTH_A(9), + .DATA_WIDTH_B(9), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WRITEMODE_A(WRITEMODE_A), + .WRITEMODE_B("READBEFOREWRITE"), + .GSR("DISABLED") + ) _TECHMAP_REPLACE_ ( + `include "bram_conn_9.vh" + .CLKA(CLK2), .CLKB(CLK3), + .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1), + .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1), + .RSTA(1'b0), .RSTB(1'b0) + ); + end else if (CFG_DBITS <= 18) begin + DP16KD #( + `include "bram_init_9_18_36.vh" + .DATA_WIDTH_A(18), + .DATA_WIDTH_B(18), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WRITEMODE_A(WRITEMODE_A), + .WRITEMODE_B("READBEFOREWRITE"), + .GSR("DISABLED") + ) _TECHMAP_REPLACE_ ( + `include "bram_conn_18.vh" + .CLKA(CLK2), .CLKB(CLK3), + .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1), + .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1), + .RSTA(1'b0), .RSTB(1'b0) + ); + end else begin + wire TECHMAP_FAIL = 1'b1; + end endgenerate +endmodule diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v index 48162a4dc..23182bdeb 100644 --- a/techlibs/ecp5/cells_map.v +++ b/techlibs/ecp5/cells_map.v @@ -7,40 +7,40 @@ module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .C module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule -module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule -module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule +module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index 1700694e8..e43632c64 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -446,3 +446,102 @@ module TRELLIS_SLICE( ); endmodule +(* blackbox *) +module DP16KD( + input DIA17, DIA16, DIA15, DIA14, DIA13, DIA12, DIA11, DIA10, DIA9, DIA8, DIA7, DIA6, DIA5, DIA4, DIA3, DIA2, DIA1, DIA0, + input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0, + input CEA, OCEA, CLKA, WEA, RSTA, + input CSA2, CSA1, CSA0, + output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0, + + input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0, + input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0, + input CEB, OCEB, CLKB, WEB, RSTB, + input CSB2, CSB1, CSB0, + output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 +); + parameter DATA_WIDTH_A = 18; + parameter DATA_WIDTH_B = 18; + + parameter REGMODE_A = "NOREG"; + parameter REGMODE_B = "NOREG"; + + parameter RESETMODE = "SYNC"; + parameter ASYNC_RESET_RELEASE = "SYNC"; + + parameter CSDECODE_A = "0b000"; + parameter CSDECODE_B = "0b000"; + + parameter WRITEMODE_A = "NORMAL"; + parameter WRITEMODE_B = "NORMAL"; + + parameter CLKAMUX = "CLKA"; + parameter CLKBMUX = "CLKB"; + + parameter GSR = "ENABLED"; + + parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; +endmodule diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index a13dd8d41..ab56a9444 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -222,11 +222,8 @@ struct SynthEcp5Pass : public ScriptPass if (!nobram && check_label("bram", "(skip if -nobram)")) { - //TODO -#if 0 - run("memory_bram -rules +/ecp5/brams.txt"); + run("memory_bram -rules +/ecp5/bram.txt"); run("techmap -map +/ecp5/brams_map.v"); -#endif } if (!nodram && check_label("dram", "(skip if -nodram)")) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 590fe61d2..b27c08529 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -235,10 +235,9 @@ struct SynthXilinxPass : public Pass if (check_label(active, run_from, run_to, "map_cells")) { + Pass::call(design, "techmap -map +/xilinx/cells_map.v"); if (vpr) - Pass::call(design, "techmap -D NO_LUT -map +/xilinx/cells_map.v"); - else - Pass::call(design, "techmap -map +/xilinx/cells_map.v"); + Pass::call(design, "techmap -map +/xilinx/lut2lut.v"); Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT"); Pass::call(design, "clean"); } diff --git a/tests/svinterfaces/run-test.sh b/tests/svinterfaces/run-test.sh new file mode 100755 index 000000000..1630859bd --- /dev/null +++ b/tests/svinterfaces/run-test.sh @@ -0,0 +1,5 @@ +#/bin/bash -e + + + +./runone.sh svinterface1 diff --git a/tests/svinterfaces/runone.sh b/tests/svinterfaces/runone.sh new file mode 100755 index 000000000..345801389 --- /dev/null +++ b/tests/svinterfaces/runone.sh @@ -0,0 +1,41 @@ +#!/bin/bash + + +TESTNAME=$1 + +STDOUTFILE=${TESTNAME}.log_stdout +STDERRFILE=${TESTNAME}.log_stderr + +echo "" > $STDOUTFILE +echo "" > $STDERRFILE + +echo -n "Test: ${TESTNAME} -> " + +$PWD/../../yosys -p "read_verilog -sv ${TESTNAME}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog ${TESTNAME}_syn.v" >> $STDOUTFILE >> $STDERRFILE +$PWD/../../yosys -p "read_verilog -sv ${TESTNAME}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog ${TESTNAME}_ref_syn.v" >> $STDOUTFILE >> $STDERRFILE + +rm -f a.out reference_result.txt dut_result.txt + +set -e + +iverilog -g2012 ${TESTNAME}_syn.v +iverilog -g2012 ${TESTNAME}_ref_syn.v + +set +e + +iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v +./a.out +mv output.txt reference_result.txt +iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v +./a.out +mv output.txt dut_result.txt + +diff reference_result.txt dut_result.txt > ${TESTNAME}.diff +RET=$? +if [ "$RET" != "0" ] ; then + echo "ERROR!" + exit -1 +fi + +echo "ok" +exit 0 diff --git a/tests/svinterfaces/svinterface1.sv b/tests/svinterfaces/svinterface1.sv new file mode 100644 index 000000000..6d60b4880 --- /dev/null +++ b/tests/svinterfaces/svinterface1.sv @@ -0,0 +1,117 @@ + + +module TopModule( + input logic clk, + input logic rst, + output logic [21:0] outOther, + input logic [1:0] sig, + input logic flip, + output logic [1:0] sig_out, + output logic [15:0] passThrough); + + MyInterface #(.WIDTH(4)) MyInterfaceInstance(); + + SubModule1 u_SubModule1 ( + .clk(clk), + .rst(rst), + .u_MyInterface(MyInterfaceInstance), + .outOther(outOther), + .sig (sig) + ); + + assign sig_out = MyInterfaceInstance.mysig_out; + + + assign MyInterfaceInstance.setting = flip; + + assign passThrough = MyInterfaceInstance.passThrough; + +endmodule + +interface MyInterface #( + parameter WIDTH = 3)( + ); + + logic setting; + logic [WIDTH-1:0] other_setting; + + logic [1:0] mysig_out; + + logic [15:0] passThrough; + + modport submodule1 ( + input setting, + output other_setting, + output mysig_out, + output passThrough + ); + + modport submodule2 ( + input setting, + output other_setting, + input mysig_out, + output passThrough + ); + +endinterface + + +module SubModule1( + input logic clk, + input logic rst, + MyInterface.submodule1 u_MyInterface, + input logic [1:0] sig, + output logic [21:0] outOther + + ); + + always_ff @(posedge clk or posedge rst) + if(rst) + u_MyInterface.mysig_out <= 0; + else begin + if(u_MyInterface.setting) + u_MyInterface.mysig_out <= sig; + else + u_MyInterface.mysig_out <= ~sig; + end + + MyInterface #(.WIDTH(22)) MyInterfaceInstanceInSub(); + + SubModule2 u_SubModule2 ( + .clk(clk), + .rst(rst), + .u_MyInterfaceInSub2(u_MyInterface), + .u_MyInterfaceInSub3(MyInterfaceInstanceInSub) + ); + + assign outOther = MyInterfaceInstanceInSub.other_setting; + + assign MyInterfaceInstanceInSub.setting = 0; + assign MyInterfaceInstanceInSub.mysig_out = sig; + +endmodule + +module SubModule2( + + input logic clk, + input logic rst, + MyInterface.submodule2 u_MyInterfaceInSub2, + MyInterface.submodule2 u_MyInterfaceInSub3 + + ); + + always_comb begin + if (u_MyInterfaceInSub3.mysig_out == 2'b00) + u_MyInterfaceInSub3.other_setting[21:0] = 1000; + else if (u_MyInterfaceInSub3.mysig_out == 2'b01) + u_MyInterfaceInSub3.other_setting[21:0] = 2000; + else if (u_MyInterfaceInSub3.mysig_out == 2'b10) + u_MyInterfaceInSub3.other_setting[21:0] = 3000; + else + u_MyInterfaceInSub3.other_setting[21:0] = 4000; + end + + assign u_MyInterfaceInSub2.passThrough[7:0] = 124; + assign u_MyInterfaceInSub2.passThrough[15:8] = 200; + +endmodule diff --git a/tests/svinterfaces/svinterface1_ref.v b/tests/svinterfaces/svinterface1_ref.v new file mode 100644 index 000000000..b119f4037 --- /dev/null +++ b/tests/svinterfaces/svinterface1_ref.v @@ -0,0 +1,107 @@ + +module TopModule( + input logic clk, + input logic rst, + input logic [1:0] sig, + input logic flip, + output logic [15:0] passThrough, + output logic [21:0] outOther, + output logic [1:0] sig_out); + + + logic MyInterfaceInstance_setting; + logic [3:0] MyInterfaceInstance_other_setting; + logic [1:0] MyInterfaceInstance_mysig_out; + + SubModule1 u_SubModule1 ( + .clk(clk), + .rst(rst), + .u_MyInterface_setting(MyInterfaceInstance_setting), + .u_MyInterface_mysig_out(MyInterfaceInstance_mysig_out), + .u_MyInterface_other_setting(MyInterfaceInstance_other_setting), + .outOther(outOther), + .passThrough (passThrough), + .sig (sig) + ); + + assign sig_out = MyInterfaceInstance_mysig_out; + + + assign MyInterfaceInstance_setting = flip; + +endmodule + + +module SubModule1( + input logic clk, + input logic rst, + input logic u_MyInterface_setting, + output logic [3:0] u_MyInterface_other_setting, + output logic [1:0] u_MyInterface_mysig_out, + output logic [21:0] outOther, + input logic [1:0] sig, + output logic [15:0] passThrough + ); + + always @(posedge clk or posedge rst) + if(rst) + u_MyInterface_mysig_out <= 0; + else begin + if(u_MyInterface_setting) + u_MyInterface_mysig_out <= sig; + else + u_MyInterface_mysig_out <= ~sig; + end + + logic MyInterfaceInstanceInSub_setting; + logic [21:0] MyInterfaceInstanceInSub_other_setting; + logic [1:0] MyInterfaceInstanceInSub_mysig_out; + + + SubModule2 u_SubModule2 ( + .clk(clk), + .rst(rst), + .u_MyInterfaceInSub2_setting(u_MyInterface_setting), + .u_MyInterfaceInSub2_mysig_out(u_MyInterface_mysig_out), + .u_MyInterfaceInSub2_other_setting(u_MyInterface_other_setting), + .u_MyInterfaceInSub3_setting(MyInterfaceInstanceInSub_setting), + .u_MyInterfaceInSub3_mysig_out(MyInterfaceInstanceInSub_mysig_out), + .u_MyInterfaceInSub3_other_setting(MyInterfaceInstanceInSub_other_setting), + .passThrough (passThrough) + ); + assign outOther = MyInterfaceInstanceInSub_other_setting; + + assign MyInterfaceInstanceInSub_setting = 0; + assign MyInterfaceInstanceInSub_mysig_out = sig; + +endmodule + +module SubModule2( + + input logic clk, + input logic rst, + input logic u_MyInterfaceInSub2_setting, + output logic [3:0] u_MyInterfaceInSub2_other_setting, + input logic [1:0] u_MyInterfaceInSub2_mysig_out, + input logic u_MyInterfaceInSub3_setting, + output logic [21:0] u_MyInterfaceInSub3_other_setting, + input logic [1:0] u_MyInterfaceInSub3_mysig_out, + output logic [15:0] passThrough + + ); + + always @(u_MyInterfaceInSub3_mysig_out) begin + if (u_MyInterfaceInSub3_mysig_out == 2'b00) + u_MyInterfaceInSub3_other_setting[21:0] = 1000; + else if (u_MyInterfaceInSub3_mysig_out == 2'b01) + u_MyInterfaceInSub3_other_setting[21:0] = 2000; + else if (u_MyInterfaceInSub3_mysig_out == 2'b10) + u_MyInterfaceInSub3_other_setting[21:0] = 3000; + else + u_MyInterfaceInSub3_other_setting[21:0] = 4000; + end + + assign passThrough[7:0] = 124; + assign passThrough[15:8] = 200; + +endmodule diff --git a/tests/svinterfaces/svinterface1_tb.v b/tests/svinterfaces/svinterface1_tb.v new file mode 100644 index 000000000..44c3b5f68 --- /dev/null +++ b/tests/svinterfaces/svinterface1_tb.v @@ -0,0 +1,57 @@ +`timescale 1ns/10ps + +module svinterface1_tb; + + + logic clk; + logic rst; + logic [21:0] outOther; + logic [1:0] sig; + logic [1:0] sig_out; + logic flip; + logic [15:0] passThrough; + integer outfile; + + TopModule u_dut ( + .clk(clk), + .rst(rst), + .outOther(outOther), + .sig(sig), + .flip(flip), + .passThrough(passThrough), + .sig_out(sig_out) + ); + + initial begin + clk = 0; + while(1) begin + clk = ~clk; + #50; + end + end + + initial begin + outfile = $fopen("output.txt"); + rst = 1; + sig = 0; + flip = 0; + @(posedge clk); + #(2); + rst = 0; + @(posedge clk); + for(int j=0;j<2;j++) begin + for(int i=0;i<20;i++) begin + #(2); + flip = j; + sig = i; + @(posedge clk); + end + end + $finish; + end + + always @(negedge clk) begin + $fdisplay(outfile, "%d %d %d", outOther, sig_out, passThrough); + end + +endmodule |