diff --git a/CHANGELOG b/CHANGELOG index b172988d5..f42eaca27 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,9 +2,23 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.39 .. Yosys 0.40-dev +Yosys 0.40 .. Yosys 0.41-dev -------------------------- +Yosys 0.39 .. Yosys 0.40 +-------------------------- + * New commands and options + - Added option "-vhdl2019" to "read" and "verific" pass. + + * Various + - Major documentation overhaul. + - Added port statistics to "stat" command. + - Added new formatting features to cxxrtl backend. + + * Verific support + - Added better support for VHDL constants import. + - Added support for VHDL 2009. + Yosys 0.38 .. Yosys 0.39 -------------------------- * New commands and options diff --git a/CODEOWNERS b/CODEOWNERS index 7d680e9f2..879bb8dee 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -10,6 +10,7 @@ # PATH (can use glob) USERNAME(S) +CODEOWNERS @nakengelhardt passes/cmds/scratchpad.cc @nakengelhardt frontends/rpc/ @whitequark backends/cxxrtl/ @whitequark @@ -19,7 +20,7 @@ passes/opt/opt_lut.cc @whitequark passes/techmap/abc9*.cc @eddiehung @Ravenslofty backends/aiger/xaiger.cc @eddiehung docs/ @KrystalDelusion - +.github/workflows/*.yml @mmicko ## External Contributors # Only users with write permission to the repository get review diff --git a/Makefile b/Makefile index a7d225269..2912a572a 100644 --- a/Makefile +++ b/Makefile @@ -141,7 +141,7 @@ LIBS += -lrt endif endif -YOSYS_VER := 0.39+183 +YOSYS_VER := 0.40+7 # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo @@ -157,7 +157,7 @@ endif OBJS = kernel/version_$(GIT_REV).o bumpversion: - sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 0033808.. | wc -l`/;" Makefile + sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline a1bb025.. | wc -l`/;" Makefile # set 'ABCREV = default' to use abc/ as it is # diff --git a/docs/source/code_examples/extensions/.gitignore b/docs/source/code_examples/extensions/.gitignore index ccdd6bd5c..675a532ed 100644 --- a/docs/source/code_examples/extensions/.gitignore +++ b/docs/source/code_examples/extensions/.gitignore @@ -1,2 +1,3 @@ my_cmd.so my_cmd.d +*.log diff --git a/frontends/verific/Makefile.inc b/frontends/verific/Makefile.inc index c82428613..df3ac8d2d 100644 --- a/frontends/verific/Makefile.inc +++ b/frontends/verific/Makefile.inc @@ -14,6 +14,7 @@ ifneq ($(DISABLE_VERIFIC_VHDL),1) $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1987/. share/verific.new/vhdl_vdbs_1987 $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1993/. share/verific.new/vhdl_vdbs_1993 $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2008/. share/verific.new/vhdl_vdbs_2008 + $(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2019/. share/verific.new/vhdl_vdbs_2019 endif $(Q) chmod -R a+rX share/verific.new $(Q) mv share/verific.new share/verific diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 792e82e26..d99353a06 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -214,23 +214,120 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj) return s; } -// When used as attributes or parameter values Verific constants come already processed. -// - Real string values are already under quotes -// - Numeric values with specified width are always converted to binary -// - Rest of user defined values are handled as 32bit integers -// - There could be some internal values that are strings without quotes -// so we check if value is all digits or not -// -// Note: For signed values, verific uses 'sb and decimal values can -// also be negative. -static const RTLIL::Const verific_const(const char *value, bool allow_string = true, bool output_signed = false) +RTLIL::Const mkconst_str(const std::string &str) { - size_t found; + RTLIL::Const val; + std::vector data; + data.reserve(str.size() * 8); + for (size_t i = 0; i < str.size(); i++) { + unsigned char ch = str[str.size() - i - 1]; + for (int j = 0; j < 8; j++) { + data.push_back((ch & 1) ? State::S1 : State::S0); + ch = ch >> 1; + } + } + val.bits = data; + val.flags |= RTLIL::CONST_FLAG_STRING; + return val; +} + +static const RTLIL::Const extract_vhdl_boolean(std::string &val) +{ + if (val == "false") + return RTLIL::Const::from_string("0"); + if (val == "true") + return RTLIL::Const::from_string("1"); + log_error("Expecting VHDL boolean value.\n"); +} + +static const RTLIL::Const extract_vhdl_bit(std::string &val, std::string &typ) +{ + if (val.size()==3 && val[0]=='\'' && val.back()=='\'') + return RTLIL::Const::from_string(val.substr(1,val.size()-2)); + log_error("Error parsing VHDL %s.\n", typ.c_str()); +} + +static const RTLIL::Const extract_vhdl_bit_vector(std::string &val, std::string &typ) +{ + if (val.size()>1 && val[0]=='\"' && val.back()=='\"') { + RTLIL::Const c = RTLIL::Const::from_string(val.substr(1,val.size()-2)); + if (typ == "signed") + c.flags |= RTLIL::CONST_FLAG_SIGNED; + return c; + } + log_error("Error parsing VHDL %s.\n", typ.c_str()); +} + +static const RTLIL::Const extract_vhdl_integer(std::string &val) +{ + char *end; + return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10), 32); +} + +static const RTLIL::Const extract_vhdl_char(std::string &val) +{ + if (val.size()==3 && val[0]=='\"' && val.back()=='\"') + return RTLIL::Const((int)val[1], 32); + log_error("Error parsing VHDL character.\n"); +} + +static const RTLIL::Const extract_real_value(std::string &val) +{ + RTLIL::Const c = mkconst_str(val); + c.flags |= RTLIL::CONST_FLAG_REAL; + return c; +} + +static const RTLIL::Const extract_vhdl_string(std::string &val) +{ + if (!(val.size()>1 && val[0]=='\"' && val.back()=='\"')) + log_error("Error parsing VHDL string.\n"); + return RTLIL::Const(val.substr(1,val.size()-2)); +} + +static const RTLIL::Const extract_vhdl_const(const char *value, bool output_signed) +{ + RTLIL::Const c; char *end; int decimal; bool is_signed = false; - RTLIL::Const c; std::string val = std::string(value); + + if (val.size()>1 && val[0]=='\"' && val.back()=='\"') { + std::string data = val.substr(1,val.size()-2); + bool isBinary = std::all_of(data.begin(), data.end(), [](char c) {return c=='1' || c=='0'; }); + if (isBinary) + c = RTLIL::Const::from_string(data); + else + c = RTLIL::Const(data); + } else if (val.size()==3 && val[0]=='\'' && val.back()=='\'') { + c = RTLIL::Const::from_string(val.substr(1,val.size()-2)); + } else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && + ((decimal = std::strtol(value, &end, 10)), !end[0])) { + is_signed = output_signed; + c = RTLIL::Const((int)decimal, 32); + } else if (val == "false") { + c = RTLIL::Const::from_string("0"); + } else if (val == "true") { + c = RTLIL::Const::from_string("1"); + } else { + c = mkconst_str(val); + log_warning("encoding value '%s' as string.\n", value); + } + if (is_signed) + c.flags |= RTLIL::CONST_FLAG_SIGNED; + return c; +} + +static const RTLIL::Const extract_verilog_const(const char *value, bool allow_string, bool output_signed) +{ + RTLIL::Const c; + char *end; + int decimal; + bool is_signed = false; + size_t found; + std::string val = std::string(value); + if (allow_string && val.size()>1 && val[0]=='\"' && val.back()=='\"') { c = RTLIL::Const(val.substr(1,val.size()-2)); } else if ((found = val.find("'sb")) != std::string::npos) { @@ -245,15 +342,56 @@ static const RTLIL::Const verific_const(const char *value, bool allow_string = t } else if (allow_string) { c = RTLIL::Const(val); } else { - log_error("expected numeric constant but found '%s'", value); + c = mkconst_str(val); + log_warning("encoding value '%s' as string.\n", value); } - if (is_signed) c.flags |= RTLIL::CONST_FLAG_SIGNED; - return c; } +// When used as attributes or parameter values Verific constants come already processed. +// - Real string values are already under quotes +// - Numeric values with specified width are always converted to binary +// - Rest of user defined values are handled as 32bit integers +// - There could be some internal values that are strings without quotes +// so we check if value is all digits or not +// +// Note: For signed values, verific uses 'sb and decimal values can +// also be negative. +static const RTLIL::Const verific_const(const char* type_name, const char *value, DesignObj *obj, bool allow_string = true, bool output_signed = false) +{ + std::string val = std::string(value); + // VHDL + if (obj->IsFromVhdl()) { + if (type_name) { + std::string typ = std::string(type_name); + transform(typ.begin(), typ.end(), typ.begin(), ::tolower); + if (typ == "integer" || typ == "natural" || typ=="positive") return extract_vhdl_integer(val); + else if (typ =="boolean") return extract_vhdl_boolean(val); + else if (typ == "bit" || typ =="std_logic" || typ == "std_ulogic") return extract_vhdl_bit(val,typ); + else if (typ == "character") return extract_vhdl_char(val); + else if (typ == "bit_vector" || typ == "std_logic_vector" || typ == "std_ulogic_vector" || + typ == "unsigned" || typ == "signed") return extract_vhdl_bit_vector(val,typ); + else if (typ == "real") return extract_real_value(val); + else if (typ == "string") return extract_vhdl_string(val); + else { + if (val.size()>1 && val[0]=='\"' && val.back()=='\"') + return RTLIL::Const(val.substr(1,val.size()-2)); + else if (val.size()==3 && val[0]=='\'' && val.back()=='\'') + return RTLIL::Const(val.substr(1,val.size()-2)); + else + return RTLIL::Const(val); + } + } else extract_vhdl_const(value, output_signed); + } + // SystemVerilog + if (type_name && strcmp(type_name, "real")==0) { + return extract_real_value(val); + } else + return extract_verilog_const(value, allow_string, output_signed); +} + static const std::string verific_unescape(const char *value) { std::string val = std::string(value); @@ -276,7 +414,7 @@ void VerificImporter::import_attributes(dict &att FOREACH_ATTRIBUTE(obj, mi, attr) { if (attr->Key()[0] == ' ' || attr->Value() == nullptr) continue; - attributes[RTLIL::escape_id(attr->Key())] = verific_const(attr->Value()); + attributes[RTLIL::escape_id(attr->Key())] = verific_const(nullptr, attr->Value(), obj); } if (nl) { @@ -298,7 +436,7 @@ void VerificImporter::import_attributes(dict &att const char *k, *v; FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) { if (nl->IsFromVerilog()) { - auto const value = verific_const(v, false); + auto const value = verific_const(type_name, v, nl, false); attributes.emplace(stringf("\\enum_value_%s", value.as_string().c_str()), RTLIL::escape_id(k)); } @@ -1306,7 +1444,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma MapIter mi; FOREACH_PARAMETER_OF_NETLIST(nl, mi, param_name, param_value) { module->avail_parameters(RTLIL::escape_id(param_name)); - module->parameter_default_values[RTLIL::escape_id(param_name)] = verific_const(param_value); + const TypeRange *tr = nl->GetTypeRange(param_name) ; + module->parameter_default_values[RTLIL::escape_id(param_name)] = verific_const(tr->GetTypeName(), param_value, nl); } SetIter si; @@ -2007,7 +2146,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma const char *param_value ; if (is_blackbox(inst->View())) { FOREACH_PARAMETER_OF_INST(inst, mi2, param_name, param_value) { - cell->setParam(RTLIL::escape_id(param_name), verific_const(param_value)); + const TypeRange *tr = inst->View()->GetTypeRange(param_name) ; + cell->setParam(RTLIL::escape_id(param_name), verific_const(tr->GetTypeName(), param_value, inst->View())); } } @@ -2702,7 +2842,7 @@ struct VerificPass : public Pass { log("\n"); log("\n"); #ifdef VERIFIC_VHDL_SUPPORT - log(" import {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} ..\n"); + log(" import {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl2019|-vhdl} ..\n"); log("\n"); log("Load the specified VHDL files into IMPORT.\n"); log("\n"); @@ -3439,6 +3579,29 @@ struct VerificPass : public Pass { goto check_error; } + if (GetSize(args) > argidx && (args[argidx] == "-vhdl2019")) { + vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2019").c_str()); + bool flag_lib = false; + for (argidx++; argidx < GetSize(args); argidx++) { + if (args[argidx] == "-lib") { + flag_lib = true; + continue; + } + if (args[argidx].compare(0, 1, "-") == 0) { + cmd_error(args, argidx, "unknown option"); + goto check_error; + } + Map map(POINTER_HASH); + add_units_to_map(map, work, flag_lib); + std::string filename = frontent_rewrite(args, argidx, tmp_files); + if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2019)) + log_cmd_error("Reading `%s' in VHDL_2019 mode failed.\n", filename.c_str()); + set_units_to_blackbox(map, work, flag_lib); + } + verific_import_pending = true; + goto check_error; + } + if (GetSize(args) > argidx && (args[argidx] == "-vhdl2008" || args[argidx] == "-vhdl")) { vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2008").c_str()); bool flag_lib = false; @@ -3982,7 +4145,7 @@ struct ReadPass : public Pass { log("\n"); log("\n"); #ifdef VERIFIC_VHDL_SUPPORT - log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} ..\n"); + log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl2019|-vhdl} ..\n"); log("\n"); log("Load the specified VHDL files. (Requires Verific.)\n"); log("\n"); @@ -4086,7 +4249,7 @@ struct ReadPass : public Pass { } #ifdef VERIFIC_VHDL_SUPPORT - if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") { + if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl2019" || args[1] == "-vhdl") { if (use_verific) { args[0] = "verific"; Pass::call(design, args); diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index cafc0aaf3..d1dd0fd88 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -415,7 +415,7 @@ struct MemoryMapPass : public Pass { log(" to any of the values.\n"); log("\n"); log(" -iattr\n"); - log(" for -attr, ignore case of .\n"); + log(" for -attr, suppress case sensitivity in matching of .\n"); log("\n"); log(" -rom-only\n"); log(" only perform conversion for ROMs (memories with no write ports).\n"); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index b3e43c18c..ba39b9c80 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -443,13 +443,6 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (!raw_used_signals.check_any(s1)) { // delete wires that aren't used by anything directly goto delete_this_wire; - } else - if (!used_signals.check_any(s2)) { - // this path shouldn't be possible: this wire is used directly (otherwise it would get cleaned up above), and indirectly - // used wires are a superset of those used directly - log_assert(false); - // delete wires that aren't used by anything indirectly, even though other wires may alias it - goto delete_this_wire; } if (0) diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index 1464c4177..4db3a8101 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -183,7 +183,7 @@ struct OptDemorganPass : public Pass { { log_header(design, "Executing OPT_DEMORGAN pass (push inverters through $reduce_* cells).\n"); - int argidx = 0; + int argidx = 1; extra_args(args, argidx, design); unsigned int cells_changed = 0; diff --git a/tests/arch/quicklogic/.gitignore b/tests/arch/quicklogic/.gitignore index 9a71dca69..ae20ed342 100644 --- a/tests/arch/quicklogic/.gitignore +++ b/tests/arch/quicklogic/.gitignore @@ -1,4 +1,4 @@ *.log -/run-test.mk +run-test.mk +*_synth.v +*_testbench