diff options
Diffstat (limited to 'passes/cmds')
31 files changed, 1275 insertions, 156 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index 01ada773..44a83b2b 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -25,4 +25,8 @@ OBJS += passes/cmds/plugin.o OBJS += passes/cmds/check.o OBJS += passes/cmds/qwp.o OBJS += passes/cmds/edgetypes.o +OBJS += passes/cmds/chformal.o +OBJS += passes/cmds/chtype.o +OBJS += passes/cmds/blackbox.o +OBJS += passes/cmds/ltp.o diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index e698926f..cfccca96 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -83,7 +83,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n struct AddPass : public Pass { AddPass() : Pass("add", "add objects to the design") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -106,7 +106,7 @@ struct AddPass : public Pass { log("selected modules.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::string command; std::string arg_name; diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc new file mode 100644 index 00000000..6094f8f1 --- /dev/null +++ b/passes/cmds/blackbox.cc @@ -0,0 +1,81 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct BlackboxPass : public Pass { + BlackboxPass() : Pass("blackbox", "change type of cells in the design") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" blackbox [options] [selection]\n"); + log("\n"); + log("Convert modules into blackbox modules (remove contents and set the blackbox\n"); + log("module attribute).\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-???") { + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_whole_modules_warn()) + { + pool<Cell*> remove_cells; + pool<Wire*> remove_wires; + + for (auto cell : module->cells()) + remove_cells.insert(cell); + + for (auto wire : module->wires()) + if (wire->port_id == 0) + remove_wires.insert(wire); + + for (auto it = module->memories.begin(); it != module->memories.end(); ++it) + delete it->second; + module->memories.clear(); + + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) + delete it->second; + module->processes.clear(); + + module->new_connections(std::vector<RTLIL::SigSig>()); + + for (auto cell : remove_cells) + module->remove(cell); + + module->remove(remove_wires); + + module->set_bool_attribute("\\blackbox"); + } + } +} BlackboxPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index b3622cb1..64697c13 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct CheckPass : public Pass { CheckPass() : Pass("check", "check for obvious problems in the design") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -44,14 +44,18 @@ struct CheckPass : public Pass { log("When called with -noinit then this command also checks for wires which have\n"); log("the 'init' attribute set.\n"); log("\n"); + log("When called with -initdrv then this command also checks for wires which have\n"); + log("the 'init' attribute set and aren't driven by a FF cell type.\n"); + log("\n"); log("When called with -assert then the command will produce an error if any\n"); log("problems are found in the current design.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { int counter = 0; bool noinit = false; + bool initdrv = false; bool assert_mode = false; size_t argidx; @@ -60,6 +64,10 @@ struct CheckPass : public Pass { noinit = true; continue; } + if (args[argidx] == "-initdrv") { + initdrv = true; + continue; + } if (args[argidx] == "-assert") { assert_mode = true; continue; @@ -70,6 +78,49 @@ struct CheckPass : public Pass { log_header(design, "Executing CHECK pass (checking for obvious problems).\n"); + pool<IdString> fftypes; + fftypes.insert("$sr"); + fftypes.insert("$ff"); + fftypes.insert("$dff"); + fftypes.insert("$dffe"); + fftypes.insert("$dffsr"); + fftypes.insert("$adff"); + fftypes.insert("$dlatch"); + fftypes.insert("$dlatchsr"); + fftypes.insert("$_DFFE_NN_"); + fftypes.insert("$_DFFE_NP_"); + fftypes.insert("$_DFFE_PN_"); + fftypes.insert("$_DFFE_PP_"); + fftypes.insert("$_DFFSR_NNN_"); + fftypes.insert("$_DFFSR_NNP_"); + fftypes.insert("$_DFFSR_NPN_"); + fftypes.insert("$_DFFSR_NPP_"); + fftypes.insert("$_DFFSR_PNN_"); + fftypes.insert("$_DFFSR_PNP_"); + fftypes.insert("$_DFFSR_PPN_"); + fftypes.insert("$_DFFSR_PPP_"); + fftypes.insert("$_DFF_NN0_"); + fftypes.insert("$_DFF_NN1_"); + fftypes.insert("$_DFF_NP0_"); + fftypes.insert("$_DFF_NP1_"); + fftypes.insert("$_DFF_N_"); + fftypes.insert("$_DFF_PN0_"); + fftypes.insert("$_DFF_PN1_"); + fftypes.insert("$_DFF_PP0_"); + fftypes.insert("$_DFF_PP1_"); + fftypes.insert("$_DFF_P_"); + fftypes.insert("$_DLATCHSR_NNN_"); + fftypes.insert("$_DLATCHSR_NNP_"); + fftypes.insert("$_DLATCHSR_NPN_"); + fftypes.insert("$_DLATCHSR_NPP_"); + fftypes.insert("$_DLATCHSR_PNN_"); + fftypes.insert("$_DLATCHSR_PNP_"); + fftypes.insert("$_DLATCHSR_PPN_"); + fftypes.insert("$_DLATCHSR_PPP_"); + fftypes.insert("$_DLATCH_N_"); + fftypes.insert("$_DLATCH_P_"); + fftypes.insert("$_FF_"); + for (auto module : design->selected_whole_modules_warn()) { if (module->has_processes_warn()) @@ -109,6 +160,8 @@ struct CheckPass : public Pass { if (bit.wire) wire_drivers_count[bit]++; } + pool<SigBit> init_bits; + for (auto wire : module->wires()) { if (wire->port_input) { SigSpec sig = sigmap(wire); @@ -121,9 +174,15 @@ struct CheckPass : public Pass { if (wire->port_input && !wire->port_output) for (auto bit : sigmap(wire)) if (bit.wire) wire_drivers_count[bit]++; - if (noinit && wire->attributes.count("\\init")) { - log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire)); - counter++; + if (wire->attributes.count("\\init")) { + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + init_bits.insert(sigmap(SigBit(wire, i))); + if (noinit) { + log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire)); + counter++; + } } } @@ -150,6 +209,26 @@ struct CheckPass : public Pass { log_warning("%s", message.c_str()); counter++; } + + if (initdrv) + { + for (auto cell : module->cells()) + { + if (fftypes.count(cell->type) == 0) + continue; + + for (auto bit : sigmap(cell->getPort("\\Q"))) + init_bits.erase(bit); + } + + SigSpec init_sig(init_bits); + init_sig.sort_and_unify(); + + for (auto chunk : init_sig.chunks()) { + log_warning("Wire %s.%s has 'init' attribute and is not driven by an FF cell.\n", log_id(module), log_signal(chunk)); + counter++; + } + } } log("found and reported %d problems.\n", counter); diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc new file mode 100644 index 00000000..522758ea --- /dev/null +++ b/passes/cmds/chformal.cc @@ -0,0 +1,282 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct ChformalPass : public Pass { + ChformalPass() : Pass("chformal", "change formal constraints of the design") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" chformal [types] [mode] [options] [selection]\n"); + log("\n"); + log("Make changes to the formal constraints of the design. The [types] options\n"); + log("the type of constraint to operate on. If none of the folling options is given,\n"); + log("the command will operate on all constraint types:\n"); + log("\n"); + log(" -assert $assert cells, representing assert(...) constraints\n"); + log(" -assume $assume cells, representing assume(...) constraints\n"); + log(" -live $live cells, representing assert(s_eventually ...)\n"); + log(" -fair $fair cells, representing assume(s_eventually ...)\n"); + log(" -cover $cover cells, representing cover() statements\n"); + log("\n"); + log("Exactly one of the following modes must be specified:\n"); + log("\n"); + log(" -remove\n"); + log(" remove the cells and thus constraints from the design\n"); + log("\n"); + log(" -early\n"); + log(" bypass FFs that only delay the activation of a constraint\n"); + log("\n"); + log(" -delay <N>\n"); + log(" delay activation of the constraint by <N> clock cycles\n"); + log("\n"); + log(" -skip <N>\n"); + log(" ignore activation of the constraint in the first <N> clock cycles\n"); + log("\n"); + log(" -assert2assume\n"); + log(" -assume2assert\n"); + log(" -live2fair\n"); + log(" -fair2live\n"); + log(" change the roles of cells as indicated. this options can be combined\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + bool assert2assume = false; + bool assume2assert = false; + bool live2fair = false; + bool fair2live = false; + + pool<IdString> constr_types; + char mode = 0; + int mode_arg = 0; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-assert") { + constr_types.insert("$assert"); + continue; + } + if (args[argidx] == "-assume") { + constr_types.insert("$assume"); + continue; + } + if (args[argidx] == "-live") { + constr_types.insert("$live"); + continue; + } + if (args[argidx] == "-fair") { + constr_types.insert("$fair"); + continue; + } + if (args[argidx] == "-cover") { + constr_types.insert("$cover"); + continue; + } + if (mode == 0 && args[argidx] == "-remove") { + mode = 'r'; + continue; + } + if (mode == 0 && args[argidx] == "-early") { + mode = 'e'; + continue; + } + if (mode == 0 && args[argidx] == "-delay" && argidx+1 < args.size()) { + mode = 'd'; + mode_arg = atoi(args[++argidx].c_str()); + continue; + } + if (mode == 0 && args[argidx] == "-skip" && argidx+1 < args.size()) { + mode = 's'; + mode_arg = atoi(args[++argidx].c_str()); + continue; + } + if ((mode == 0 || mode == 'c') && args[argidx] == "-assert2assume") { + assert2assume = true; + mode = 'c'; + continue; + } + if ((mode == 0 || mode == 'c') && args[argidx] == "-assume2assert") { + assume2assert = true; + mode = 'c'; + continue; + } + if ((mode == 0 || mode == 'c') && args[argidx] == "-live2fair") { + live2fair = true; + mode = 'c'; + continue; + } + if ((mode == 0 || mode == 'c') && args[argidx] == "-fair2live") { + fair2live = true; + mode = 'c'; + continue; + } + break; + } + extra_args(args, argidx, design); + + if (constr_types.empty()) { + constr_types.insert("$assert"); + constr_types.insert("$assume"); + constr_types.insert("$live"); + constr_types.insert("$fair"); + constr_types.insert("$cover"); + } + + if (mode == 0) + log_cmd_error("Mode option is missing.\n"); + + for (auto module : design->selected_modules()) + { + vector<Cell*> constr_cells; + + for (auto cell : module->selected_cells()) + if (constr_types.count(cell->type)) + constr_cells.push_back(cell); + + if (mode == 'r') + { + for (auto cell : constr_cells) + module->remove(cell); + } + else + if (mode == 'e') + { + SigMap sigmap(module); + dict<SigBit, pair<SigBit, pair<SigBit, bool>>> ffmap; + pool<SigBit> init_zero, init_one; + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init") == 0) + continue; + + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) { + if (initval[i] == State::S0) + init_zero.insert(initsig[i]); + if (initval[i] == State::S1) + init_one.insert(initsig[i]); + } + } + + for (auto cell : module->selected_cells()) + { + if (cell->type == "$ff") { + SigSpec D = sigmap(cell->getPort("\\D")); + SigSpec Q = sigmap(cell->getPort("\\Q")); + for (int i = 0; i < GetSize(D); i++) + ffmap[Q[i]] = make_pair(D[i], make_pair(State::Sm, false)); + } + if (cell->type == "$dff") { + SigSpec D = sigmap(cell->getPort("\\D")); + SigSpec Q = sigmap(cell->getPort("\\Q")); + SigSpec C = sigmap(cell->getPort("\\CLK")); + bool clockpol = cell->getParam("\\CLK_POLARITY").as_bool(); + for (int i = 0; i < GetSize(D); i++) + ffmap[Q[i]] = make_pair(D[i], make_pair(C, clockpol)); + } + } + + for (auto cell : constr_cells) + while (true) + { + SigSpec A = sigmap(cell->getPort("\\A")); + SigSpec EN = sigmap(cell->getPort("\\EN")); + + if (ffmap.count(A) == 0 || ffmap.count(EN) == 0) + break; + + if (!init_zero.count(EN)) { + if (cell->type == "$cover") break; + if (cell->type.in("$assert", "$assume") && !init_one.count(A)) break; + } + + const auto &A_map = ffmap.at(A); + const auto &EN_map = ffmap.at(EN); + + if (A_map.second != EN_map.second) + break; + + cell->setPort("\\A", A_map.first); + cell->setPort("\\EN", EN_map.first); + } + } + else + if (mode == 'd') + { + for (auto cell : constr_cells) + for (int i = 0; i < mode_arg; i++) + { + SigSpec orig_a = cell->getPort("\\A"); + SigSpec orig_en = cell->getPort("\\EN"); + + Wire *new_a = module->addWire(NEW_ID); + Wire *new_en = module->addWire(NEW_ID); + new_en->attributes["\\init"] = State::S0; + + module->addFf(NEW_ID, orig_a, new_a); + module->addFf(NEW_ID, orig_en, new_en); + + cell->setPort("\\A", new_a); + cell->setPort("\\EN", new_en); + } + } + else + if (mode == 's') + { + SigSpec en = State::S1; + + for (int i = 0; i < mode_arg; i++) { + Wire *w = module->addWire(NEW_ID); + w->attributes["\\init"] = State::S0; + module->addFf(NEW_ID, en, w); + en = w; + } + + for (auto cell : constr_cells) + cell->setPort("\\EN", module->LogicAnd(NEW_ID, en, cell->getPort("\\EN"))); + } + else + if (mode == 'c') + { + for (auto cell : constr_cells) + if (assert2assume && cell->type == "$assert") + cell->type = "$assume"; + else if (assume2assert && cell->type == "$assume") + cell->type = "$assert"; + else if (live2fair && cell->type == "$live") + cell->type = "$fair"; + else if (fair2live && cell->type == "$fair") + cell->type = "$live"; + } + } + } +} ChformalPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc new file mode 100644 index 00000000..979aeadd --- /dev/null +++ b/passes/cmds/chtype.cc @@ -0,0 +1,83 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct ChtypePass : public Pass { + ChtypePass() : Pass("chtype", "change type of cells in the design") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" chtype [options] [selection]\n"); + log("\n"); + log("Change the types of cells in the design.\n"); + log("\n"); + log(" -set <type>\n"); + log(" set the cell type to the given type\n"); + log("\n"); + log(" -map <old_type> <new_type>\n"); + log(" change cells types that match <old_type> to <new_type>\n"); + log("\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + IdString set_type; + dict<IdString, IdString> map_types; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (set_type == IdString() && args[argidx] == "-set" && argidx+1 < args.size()) { + set_type = RTLIL::escape_id(args[++argidx]); + continue; + } + if (args[argidx] == "-map" && argidx+2 < args.size()) { + IdString old_type = RTLIL::escape_id(args[++argidx]); + IdString new_type = RTLIL::escape_id(args[++argidx]); + map_types[old_type] = new_type; + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + for (auto cell : module->selected_cells()) + { + if (map_types.count(cell->type)) { + cell->type = map_types.at(cell->type); + continue; + } + + if (set_type != IdString()) { + cell->type = set_type; + continue; + } + } + } + } +} ChtypePass; + +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index 52611cf4..d480b79a 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -43,7 +43,7 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap & struct ConnectPass : public Pass { ConnectPass() : Pass("connect", "create or remove connections") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -75,7 +75,7 @@ struct ConnectPass : public Pass { log("This command does not operate on module with processes.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { RTLIL::Module *module = NULL; for (auto &it : design->modules_) { diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index c9ab226d..5a15cbba 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -149,8 +149,8 @@ struct ConnwrappersWorker }; struct ConnwrappersPass : public Pass { - ConnwrappersPass() : Pass("connwrappers", "replace undef values with defined constants") { } - virtual void help() + ConnwrappersPass() : Pass("connwrappers", "match width of input-output port pairs") { } + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -172,7 +172,7 @@ struct ConnwrappersPass : public Pass { log("The options -signed, -unsigned, and -port can be specified multiple times.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { ConnwrappersWorker worker; diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc index fb863512..acd2dba5 100644 --- a/passes/cmds/copy.cc +++ b/passes/cmds/copy.cc @@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN struct CopyPass : public Pass { CopyPass() : Pass("copy", "copy modules in the design") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -36,7 +36,7 @@ struct CopyPass : public Pass { log("by this command.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { if (args.size() != 3) log_cmd_error("Invalid number of arguments!\n"); diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index 1475475c..0ec74767 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -35,7 +35,7 @@ PRIVATE_NAMESPACE_BEGIN struct CoverPass : public Pass { CoverPass() : Pass("cover", "print code coverage counters") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -83,7 +83,7 @@ struct CoverPass : public Pass { log("Coverage counters are only available in Yosys for Linux.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::vector<FILE*> out_files; std::vector<std::string> patterns; @@ -128,7 +128,7 @@ struct CoverPass : public Pass { log("\n"); } -#if defined(YOSYS_ENABLE_COVER) && defined(__linux__) +#if defined(YOSYS_ENABLE_COVER) && (defined(__linux__) || defined(__FreeBSD__)) for (auto &it : get_coverage_data()) { if (!patterns.empty()) { for (auto &p : patterns) diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 6d51d30e..f8d91ea4 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN struct DeletePass : public Pass { DeletePass() : Pass("delete", "delete objects in the design") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -40,7 +40,7 @@ struct DeletePass : public Pass { log("selected wires, thus 'deleting' module ports.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool flag_input = false; bool flag_output = false; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index e900e7b9..172addcc 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -17,10 +17,8 @@ * */ -#include "kernel/register.h" -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" +#include "kernel/yosys.h" +#include "frontends/ast/ast.h" YOSYS_NAMESPACE_BEGIN @@ -29,7 +27,7 @@ std::vector<RTLIL::Design*> pushed_designs; struct DesignPass : public Pass { DesignPass() : Pass("design", "save, restore and reset current design") { } - virtual ~DesignPass() { + ~DesignPass() YS_OVERRIDE { for (auto &it : saved_designs) delete it.second; saved_designs.clear(); @@ -37,7 +35,7 @@ struct DesignPass : public Pass { delete it; pushed_designs.clear(); } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -82,13 +80,28 @@ struct DesignPass : public Pass { log("\n"); log("Copy modules from the current design into the specified one.\n"); log("\n"); + log("\n"); + log(" design -import <name> [-as <new_top_name>] [selection]\n"); + log("\n"); + log("Import the specified design into the current design. The source design must\n"); + log("either have a selected top module or the selection must contain exactly one\n"); + log("module that is then used as top module for this command.\n"); + log("\n"); + log("\n"); + log(" design -reset-vlog\n"); + log("\n"); + log("The Verilog front-end remembers defined macros and top-level declarations\n"); + log("between calls to 'read_verilog'. This command resets this memory.\n"); + log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool got_mode = false; bool reset_mode = false; + bool reset_vlog_mode = false; bool push_mode = false; bool pop_mode = false; + bool import_mode = false; RTLIL::Design *copy_from_design = NULL, *copy_to_design = NULL; std::string save_name, load_name, as_name; std::vector<RTLIL::Module*> copy_src_modules; @@ -102,6 +115,11 @@ struct DesignPass : public Pass { reset_mode = true; continue; } + if (!got_mode && args[argidx] == "-reset-vlog") { + got_mode = true; + reset_vlog_mode = true; + continue; + } if (!got_mode && args[argidx] == "-push") { got_mode = true; push_mode = true; @@ -146,8 +164,17 @@ struct DesignPass : public Pass { copy_from_design = design; continue; } - if (copy_from_design != NULL && args[argidx] == "-as" && argidx+1 < args.size()) { + if (!got_mode && args[argidx] == "-import" && argidx+1 < args.size()) { got_mode = true; + import_mode = true; + if (saved_designs.count(args[++argidx]) == 0) + log_cmd_error("No saved design '%s' found!\n", args[argidx].c_str()); + copy_from_design = saved_designs.at(args[argidx]); + copy_to_design = design; + as_name = args[argidx]; + continue; + } + if (copy_from_design != NULL && args[argidx] == "-as" && argidx+1 < args.size()) { as_name = args[++argidx]; continue; } @@ -156,10 +183,10 @@ struct DesignPass : public Pass { if (copy_from_design != NULL) { - if (copy_from_design != design && argidx == args.size()) + if (copy_from_design != design && argidx == args.size() && !import_mode) cmd_error(args, argidx, "Missing selection."); - RTLIL::Selection sel = design->selection_stack.back(); + RTLIL::Selection sel; if (argidx != args.size()) { handle_extra_select_args(this, args, argidx, args.size(), copy_from_design); sel = copy_from_design->selection_stack.back(); @@ -175,6 +202,17 @@ struct DesignPass : public Pass { if (sel.selected_module(it.first)) log_cmd_error("Module %s is only partly selected.\n", RTLIL::id2cstr(it.first)); } + + if (import_mode) { + for (auto module : copy_src_modules) + { + if (module->get_bool_attribute("\\top")) { + copy_src_modules.clear(); + copy_src_modules.push_back(module); + break; + } + } + } } extra_args(args, argidx, design, false); @@ -185,6 +223,68 @@ struct DesignPass : public Pass { if (pop_mode && pushed_designs.empty()) log_cmd_error("No pushed designs.\n"); + if (import_mode) + { + std::string prefix = RTLIL::escape_id(as_name); + + pool<Module*> queue; + dict<IdString, IdString> done; + + if (copy_to_design->modules_.count(prefix)) + delete copy_to_design->modules_.at(prefix); + + if (GetSize(copy_src_modules) != 1) + log_cmd_error("No top module found in source design.\n"); + + for (auto mod : copy_src_modules) + { + log("Importing %s as %s.\n", log_id(mod), log_id(prefix)); + + copy_to_design->modules_[prefix] = mod->clone(); + copy_to_design->modules_[prefix]->name = prefix; + copy_to_design->modules_[prefix]->design = copy_to_design; + copy_to_design->modules_[prefix]->attributes.erase("\\top"); + + queue.insert(copy_to_design->modules_[prefix]); + done[mod->name] = prefix; + } + + while (!queue.empty()) + { + pool<Module*> old_queue; + old_queue.swap(queue); + + for (auto mod : old_queue) + for (auto cell : mod->cells()) + { + Module *fmod = copy_from_design->module(cell->type); + + if (fmod == nullptr) + continue; + + if (done.count(cell->type) == 0) + { + std::string trg_name = prefix + "." + (cell->type.c_str() + (*cell->type.c_str() == '\\')); + + log("Importing %s as %s.\n", log_id(fmod), log_id(trg_name)); + + if (copy_to_design->modules_.count(trg_name)) + delete copy_to_design->modules_.at(trg_name); + + copy_to_design->modules_[trg_name] = fmod->clone(); + copy_to_design->modules_[trg_name]->name = trg_name; + copy_to_design->modules_[trg_name]->design = copy_to_design; + copy_to_design->modules_[trg_name]->attributes.erase("\\top"); + + queue.insert(copy_to_design->modules_[trg_name]); + done[cell->type] = trg_name; + } + + cell->type = done.at(cell->type); + } + } + } + else if (copy_to_design != NULL) { if (!as_name.empty() && copy_src_modules.size() > 1) @@ -196,6 +296,7 @@ struct DesignPass : public Pass { if (copy_to_design->modules_.count(trg_name)) delete copy_to_design->modules_.at(trg_name); + copy_to_design->modules_[trg_name] = mod->clone(); copy_to_design->modules_[trg_name]->name = trg_name; copy_to_design->modules_[trg_name]->design = copy_to_design; @@ -235,19 +336,34 @@ struct DesignPass : public Pass { design->selection_stack.push_back(RTLIL::Selection()); } + if (reset_mode || reset_vlog_mode || !load_name.empty() || push_mode || pop_mode) + { + for (auto node : design->verilog_packages) + delete node; + design->verilog_packages.clear(); + + for (auto node : design->verilog_globals) + delete node; + design->verilog_globals.clear(); + + design->verilog_defines.clear(); + } + if (!load_name.empty() || pop_mode) { RTLIL::Design *saved_design = pop_mode ? pushed_designs.back() : saved_designs.at(load_name); - if (pop_mode) - pushed_designs.pop_back(); - for (auto &it : saved_design->modules_) design->add(it.second->clone()); design->selection_stack = saved_design->selection_stack; design->selection_vars = saved_design->selection_vars; design->selected_active_module = saved_design->selected_active_module; + + if (pop_mode) { + delete saved_design; + pushed_designs.pop_back(); + } } } } DesignPass; diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc index 7b75a009..58ed6457 100644 --- a/passes/cmds/edgetypes.cc +++ b/passes/cmds/edgetypes.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct EdgetypePass : public Pass { EdgetypePass() : Pass("edgetypes", "list all types of edges in selection") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -35,7 +35,7 @@ struct EdgetypePass : public Pass { log("is a 4-tuple of source and sink cell type and port name.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc index 85386f3d..522e1089 100644 --- a/passes/cmds/logcmd.cc +++ b/passes/cmds/logcmd.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct LogPass : public Pass { LogPass() : Pass("log", "print text and log files") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -52,7 +52,7 @@ struct LogPass : public Pass { log(" do not append a newline\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design*) + void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE { size_t argidx; bool to_stdout = false; diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc new file mode 100644 index 00000000..05701710 --- /dev/null +++ b/passes/cmds/ltp.cc @@ -0,0 +1,185 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/celltypes.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct LtpWorker +{ + RTLIL::Design *design; + RTLIL::Module *module; + SigMap sigmap; + + dict<SigBit, tuple<int, SigBit, Cell*>> bits; + dict<SigBit, dict<SigBit, Cell*>> bit2bits; + dict<SigBit, tuple<SigBit, Cell*>> bit2ff; + + int maxlvl; + SigBit maxbit; + pool<SigBit> busy; + + LtpWorker(RTLIL::Module *module, bool noff) : design(module->design), module(module), sigmap(module) + { + CellTypes ff_celltypes; + + if (noff) { + ff_celltypes.setup_internals_mem(); + ff_celltypes.setup_stdcells_mem(); + } + + for (auto wire : module->selected_wires()) + for (auto bit : sigmap(wire)) + bits[bit] = tuple<int, SigBit, Cell*>(-1, State::Sx, nullptr); + + for (auto cell : module->selected_cells()) + { + pool<SigBit> src_bits, dst_bits; + + for (auto &conn : cell->connections()) + for (auto bit : sigmap(conn.second)) { + if (cell->input(conn.first)) + src_bits.insert(bit); + if (cell->output(conn.first)) + dst_bits.insert(bit); + } + + if (noff && ff_celltypes.cell_known(cell->type)) { + for (auto s : src_bits) + for (auto d : dst_bits) { + bit2ff[s] = tuple<SigBit, Cell*>(d, cell); + break; + } + continue; + } + + for (auto s : src_bits) + for (auto d : dst_bits) + bit2bits[s][d] = cell; + } + + maxlvl = -1; + maxbit = State::Sx; + } + + void runner(SigBit bit, int level, SigBit from, Cell *via) + { + auto &bitinfo = bits.at(bit); + + if (get<0>(bitinfo) >= level) + return; + + if (busy.count(bit) > 0) { + log_warning("Detected loop at %s in %s\n", log_signal(bit), log_id(module)); + return; + } + + busy.insert(bit); + get<0>(bitinfo) = level; + get<1>(bitinfo) = from; + get<2>(bitinfo) = via; + + if (level > maxlvl) { + maxlvl = level; + maxbit = bit; + } + + if (bit2bits.count(bit)) { + for (auto &it : bit2bits.at(bit)) + runner(it.first, level+1, bit, it.second); + } + + busy.erase(bit); + } + + void printpath(SigBit bit) + { + auto &bitinfo = bits.at(bit); + if (get<2>(bitinfo)) { + printpath(get<1>(bitinfo)); + log("%5d: %s (via %s)\n", get<0>(bitinfo), log_signal(bit), log_id(get<2>(bitinfo))); + } else { + log("%5d: %s\n", get<0>(bitinfo), log_signal(bit)); + } + } + + void run() + { + for (auto &it : bits) + if (get<0>(it.second) < 0) + runner(it.first, 0, State::Sx, nullptr); + + log("\n"); + log("Longest topological path in %s (length=%d):\n", log_id(module), maxlvl); + + if (maxlvl >= 0) + printpath(maxbit); + + if (bit2ff.count(maxbit)) + log("%5s: %s (via %s)\n", "ff", log_signal(get<0>(bit2ff.at(maxbit))), log_id(get<1>(bit2ff.at(maxbit)))); + } +}; + +struct LtpPass : public Pass { + LtpPass() : Pass("ltp", "print longest topological path") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" ltp [options] [selection]\n"); + log("\n"); + log("This command prints the longest topological path in the design. (Only considers\n"); + log("paths within a single module, so the design must be flattened.)\n"); + log("\n"); + log(" -noff\n"); + log(" automatically exclude FF cell types\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + bool noff = false; + + log_header(design, "Executing LTP pass (find longest path).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-noff") { + noff = true; + continue; + } + break; + } + + extra_args(args, argidx, design); + + for (Module *module : design->selected_modules()) + { + if (module->has_processes_warn()) + continue; + + LtpWorker worker(module, noff); + worker.run(); + } + } +} LtpPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index 828c671d..aa6d5b6c 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -58,7 +58,7 @@ void load_plugin(std::string, std::vector<std::string>) struct PluginPass : public Pass { PluginPass() : Pass("plugin", "load and list loaded plugins") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -76,7 +76,7 @@ struct PluginPass : public Pass { log(" List loaded plugins\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::string plugin_filename; std::vector<std::string> plugin_aliases; diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc index 1b800b6d..1c64a7b7 100644 --- a/passes/cmds/qwp.cc +++ b/passes/cmds/qwp.cc @@ -778,7 +778,7 @@ struct QwpWorker struct QwpPass : public Pass { QwpPass() : Pass("qwp", "quadratic wirelength placer") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -808,7 +808,7 @@ struct QwpPass : public Pass { log("dense matrix operations. It is only a toy-placer for small circuits.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { QwpConfig config; xorshift32_state = 123456789; @@ -835,6 +835,7 @@ struct QwpPass : public Pass { } if (args[argidx] == "-dump" && argidx+1 < args.size()) { config.dump_file.open(args[++argidx], std::ofstream::trunc); + yosys_output_files.insert(args[argidx]); continue; } break; diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 6a002869..dce576fd 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -54,7 +54,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: struct RenamePass : public Pass { RenamePass() : Pass("rename", "rename object in the design") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -81,7 +81,7 @@ struct RenamePass : public Pass { log("Rename top module.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::string pattern_prefix = "_", pattern_suffix = "_"; bool flag_enumerate = false; diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc index f083e1f6..7123ba9f 100644 --- a/passes/cmds/scatter.cc +++ b/passes/cmds/scatter.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct ScatterPass : public Pass { ScatterPass() : Pass("scatter", "add additional intermediate nets") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -41,7 +41,7 @@ struct ScatterPass : public Pass { log("Use the opt_clean command to get rid of the additional nets.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { CellTypes ct(design); extra_args(args, 1, design); diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc index bb6d7447..99f4fbae 100644 --- a/passes/cmds/scc.cc +++ b/passes/cmds/scc.cc @@ -163,16 +163,8 @@ struct SccWorker } for (auto cell : workQueue) - cellToNextCell[cell] = sigToNextCells.find(cellToNextSig[cell]); - - labelCounter = 0; - cellLabels.clear(); - - while (workQueue.size() > 0) { - RTLIL::Cell *cell = *workQueue.begin(); - log_assert(cellStack.size() == 0); - cellDepth.clear(); + cellToNextCell[cell] = sigToNextCells.find(cellToNextSig[cell]); if (!nofeedbackMode && cellToNextCell[cell].count(cell)) { log("Found an SCC:"); @@ -183,6 +175,16 @@ struct SccWorker sccList.push_back(scc); log("\n"); } + } + + labelCounter = 0; + cellLabels.clear(); + + while (!workQueue.empty()) + { + RTLIL::Cell *cell = *workQueue.begin(); + log_assert(cellStack.size() == 0); + cellDepth.clear(); run(cell, 0, maxDepth); } @@ -216,7 +218,7 @@ struct SccWorker struct SccPass : public Pass { SccPass() : Pass("scc", "detect strongly connected components (logic loops)") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -244,20 +246,18 @@ struct SccPass : public Pass { log(" are assumed to be bidirectional 'inout' ports.\n"); log("\n"); log(" -set_attr <name> <value>\n"); - log(" -set_cell_attr <name> <value>\n"); - log(" -set_wire_attr <name> <value>\n"); - log(" set the specified attribute on all cells and/or wires that are part of\n"); - log(" a logic loop. the special token {} in the value is replaced with a\n"); - log(" unique identifier for the logic loop.\n"); + log(" set the specified attribute on all cells that are part of a logic\n"); + log(" loop. the special token {} in the value is replaced with a unique\n"); + log(" identifier for the logic loop.\n"); log("\n"); log(" -select\n"); log(" replace the current selection with a selection of all cells and wires\n"); log(" that are part of a found logic loop\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { - std::map<std::string, std::string> setCellAttr, setWireAttr; + std::map<std::string, std::string> setAttr; bool allCellTypes = false; bool selectMode = false; bool nofeedbackMode = false; @@ -285,18 +285,7 @@ struct SccPass : public Pass { continue; } if (args[argidx] == "-set_attr" && argidx+2 < args.size()) { - setCellAttr[args[argidx+1]] = args[argidx+2]; - setWireAttr[args[argidx+1]] = args[argidx+2]; - argidx += 2; - continue; - } - if (args[argidx] == "-set_cell_attr" && argidx+2 < args.size()) { - setCellAttr[args[argidx+1]] = args[argidx+2]; - argidx += 2; - continue; - } - if (args[argidx] == "-set_wire_attr" && argidx+2 < args.size()) { - setWireAttr[args[argidx+1]] = args[argidx+2]; + setAttr[args[argidx+1]] = args[argidx+2]; argidx += 2; continue; } @@ -309,9 +298,6 @@ struct SccPass : public Pass { int origSelectPos = design->selection_stack.size() - 1; extra_args(args, argidx, design); - if (setCellAttr.size() > 0 || setWireAttr.size() > 0) - log_cmd_error("The -set*_attr options are not implemented at the moment!\n"); - RTLIL::Selection newSelection(false); int scc_counter = 0; @@ -319,7 +305,33 @@ struct SccPass : public Pass { if (design->selected(mod_it.second)) { SccWorker worker(design, mod_it.second, nofeedbackMode, allCellTypes, maxDepth); - scc_counter += GetSize(worker.sccList); + + if (!setAttr.empty()) + { + for (const auto &cells : worker.sccList) + { + for (auto attr : setAttr) + { + IdString attr_name(RTLIL::escape_id(attr.first)); + string attr_valstr = attr.second; + string index = stringf("%d", scc_counter); + + for (size_t pos = 0; (pos = attr_valstr.find("{}", pos)) != string::npos; pos += index.size()) + attr_valstr.replace(pos, 2, index); + + Const attr_value(attr_valstr); + + for (auto cell : cells) + cell->attributes[attr_name] = attr_value; + } + + scc_counter++; + } + } + else + { + scc_counter += GetSize(worker.sccList); + } if (selectMode) worker.select(newSelection); diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index d2e1a2e2..d97aa2b3 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -760,6 +760,9 @@ static void select_stmt(RTLIL::Design *design, std::string arg) if (!design->selected_active_module.empty()) { arg_mod = design->selected_active_module; arg_memb = arg; + } else + if (GetSize(arg) >= 2 && arg[0] >= 'a' && arg[0] <= 'z' && arg[1] == ':') { + arg_mod = "*", arg_memb = arg; } else { size_t pos = arg.find('/'); if (pos == std::string::npos) { @@ -947,7 +950,7 @@ PRIVATE_NAMESPACE_BEGIN struct SelectPass : public Pass { SelectPass() : Pass("select", "modify and view the list of selected objects") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -961,7 +964,7 @@ struct SelectPass : public Pass { log("list of selected objects.\n"); log("\n"); log("Note that many commands support an optional [selection] argument that can be\n"); - log("used to override the global selection for the command. The syntax of this\n"); + log("used to YS_OVERRIDE the global selection for the command. The syntax of this\n"); log("optional argument is identical to the syntax of the <selection> argument\n"); log("described here.\n"); log("\n"); @@ -1164,7 +1167,7 @@ struct SelectPass : public Pass { log(" select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool add_mode = false; bool del_mode = false; @@ -1263,6 +1266,7 @@ struct SelectPass : public Pass { log_cmd_error("Option -read can not be combined with a selection expression.\n"); std::ifstream f(read_file); + yosys_input_files.insert(read_file); if (f.fail()) log_error("Can't open '%s' for reading: %s\n", read_file.c_str(), strerror(errno)); @@ -1331,6 +1335,7 @@ struct SelectPass : public Pass { FILE *f = NULL; if (!write_file.empty()) { f = fopen(write_file.c_str(), "w"); + yosys_output_files.insert(write_file); if (f == NULL) log_error("Can't open '%s' for writing: %s\n", write_file.c_str(), strerror(errno)); } @@ -1465,7 +1470,7 @@ struct SelectPass : public Pass { struct CdPass : public Pass { CdPass() : Pass("cd", "a shortcut for 'select -module <name>'") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1482,17 +1487,53 @@ struct CdPass : public Pass { log("\n"); log(" cd ..\n"); log("\n"); + log("Remove trailing substrings that start with '.' in current module name until\n"); + log("the name of a module in the current design is generated, then switch to that\n"); + log("module. Otherwise clear the current selection.\n"); + log("\n"); + log(" cd\n"); + log("\n"); log("This is just a shortcut for 'select -clear'.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { - if (args.size() != 2) + if (args.size() != 1 && args.size() != 2) log_cmd_error("Invalid number of arguments.\n"); - if (args[1] == "..") { + if (args.size() == 1 || args[1] == "/") { + design->selection_stack.back() = RTLIL::Selection(true); + design->selected_active_module = std::string(); + return; + } + + if (args[1] == "..") + { + string modname = design->selected_active_module; + design->selection_stack.back() = RTLIL::Selection(true); design->selected_active_module = std::string(); + + while (1) + { + size_t pos = modname.rfind('.'); + + if (pos == string::npos) + break; + + modname = modname.substr(0, pos); + Module *mod = design->module(modname); + + if (mod == nullptr) + continue; + + design->selected_active_module = modname; + design->selection_stack.back() = RTLIL::Selection(); + select_filter_active_mod(design, design->selection_stack.back()); + design->selection_stack.back().optimize(design); + return; + } + return; } @@ -1537,7 +1578,7 @@ static void log_matches(const char *title, Module *module, T list) struct LsPass : public Pass { LsPass() : Pass("ls", "list modules or objects in modules") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1548,7 +1589,7 @@ struct LsPass : public Pass { log("When an active module is selected, this prints a list of objects in the module.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx = 1; extra_args(args, argidx, design); diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 689e3148..d38a6b3d 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -56,7 +56,7 @@ static void do_setunset(dict<RTLIL::IdString, RTLIL::Const> &attrs, const std::v struct SetattrPass : public Pass { SetattrPass() : Pass("setattr", "set/unset attributes on objects") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -69,7 +69,7 @@ struct SetattrPass : public Pass { log("instead of objects within modules.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::vector<setunset_t> setunset_list; bool flag_mod = false; @@ -130,7 +130,7 @@ struct SetattrPass : public Pass { struct SetparamPass : public Pass { SetparamPass() : Pass("setparam", "set/unset parameters on objects") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -142,7 +142,7 @@ struct SetparamPass : public Pass { log("The -type option can be used to change the cell type of the selected cells.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { vector<setunset_t> setunset_list; string new_cell_type; @@ -188,7 +188,7 @@ struct SetparamPass : public Pass { struct ChparamPass : public Pass { ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -203,7 +203,7 @@ struct ChparamPass : public Pass { log("List the available parameters of the selected modules.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::vector<setunset_t> setunset_list; dict<RTLIL::IdString, RTLIL::Const> new_parameters; diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index 26b2eb87..62d940ce 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -23,33 +23,82 @@ #include "kernel/rtlil.h" #include "kernel/log.h" +#define MODE_ZERO 0 +#define MODE_ONE 1 +#define MODE_UNDEF 2 +#define MODE_RANDOM 3 +#define MODE_ANYSEQ 4 +#define MODE_ANYCONST 5 + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +static RTLIL::Wire * add_wire(RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output) +{ + RTLIL::Wire *wire = NULL; + name = RTLIL::escape_id(name); + + if (module->count_id(name) != 0) + { + log("Module %s already has such an object %s.\n", module->name.c_str(), name.c_str()); + name += "$"; + return add_wire(module, name, width, flag_input, flag_output); + } + else + { + wire = module->addWire(name, width); + wire->port_input = flag_input; + wire->port_output = flag_output; + + if (flag_input || flag_output) { + wire->port_id = module->wires_.size(); + module->fixup_ports(); + } + + log("Added wire %s to module %s.\n", name.c_str(), module->name.c_str()); + } + + return wire; +} + struct SetundefWorker { int next_bit_mode; uint32_t next_bit_state; + vector<SigSpec*> siglist; RTLIL::State next_bit() { - if (next_bit_mode == 0) + if (next_bit_mode == MODE_ZERO) return RTLIL::State::S0; - if (next_bit_mode == 1) + if (next_bit_mode == MODE_ONE) return RTLIL::State::S1; - // xorshift32 - next_bit_state ^= next_bit_state << 13; - next_bit_state ^= next_bit_state >> 17; - next_bit_state ^= next_bit_state << 5; - log_assert(next_bit_state != 0); + if (next_bit_mode == MODE_UNDEF) + return RTLIL::State::Sx; + + if (next_bit_mode == MODE_RANDOM) + { + // xorshift32 + next_bit_state ^= next_bit_state << 13; + next_bit_state ^= next_bit_state >> 17; + next_bit_state ^= next_bit_state << 5; + log_assert(next_bit_state != 0); - return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1; + return ((next_bit_state >> (next_bit_state & 15)) & 16) ? RTLIL::State::S0 : RTLIL::State::S1; + } + + log_abort(); } void operator()(RTLIL::SigSpec &sig) { + if (next_bit_mode == MODE_ANYSEQ || next_bit_mode == MODE_ANYCONST) { + siglist.push_back(&sig); + return; + } + for (auto &bit : sig) if (bit.wire == NULL && bit.data > RTLIL::State::S1) bit = next_bit(); @@ -58,23 +107,35 @@ struct SetundefWorker struct SetundefPass : public Pass { SetundefPass() : Pass("setundef", "replace undef values with defined constants") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" setundef [options] [selection]\n"); log("\n"); - log("This command replaced undef (x) constants with defined (0/1) constants.\n"); + log("This command replaces undef (x) constants with defined (0/1) constants.\n"); log("\n"); log(" -undriven\n"); log(" also set undriven nets to constant values\n"); log("\n"); + log(" -expose\n"); + log(" also expose undriven nets as inputs (use with -undriven)\n"); + log("\n"); log(" -zero\n"); log(" replace with bits cleared (0)\n"); log("\n"); log(" -one\n"); log(" replace with bits set (1)\n"); log("\n"); + log(" -undef\n"); + log(" replace with undef (x) bits, may be used with -undriven\n"); + log("\n"); + log(" -anyseq\n"); + log(" replace with $anyseq drivers (for formal)\n"); + log("\n"); + log(" -anyconst\n"); + log(" replace with $anyconst drivers (for formal)\n"); + log("\n"); log(" -random <seed>\n"); log(" replace with random bits using the specified integer als seed\n"); log(" value for the random number generator.\n"); @@ -83,13 +144,16 @@ struct SetundefPass : public Pass { log(" also create/update init values for flip-flops\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool got_value = false; bool undriven_mode = false; + bool expose_mode = false; bool init_mode = false; SetundefWorker worker; + log_header(design, "Executing SETUNDEF pass (replace undef values with defined constants).\n"); + size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -97,14 +161,39 @@ struct SetundefPass : public Pass { undriven_mode = true; continue; } + if (args[argidx] == "-expose") { + got_value = true; + expose_mode = true; + continue; + } if (args[argidx] == "-zero") { got_value = true; - worker.next_bit_mode = 0; + worker.next_bit_mode = MODE_ZERO; + worker.next_bit_state = 0; continue; } if (args[argidx] == "-one") { got_value = true; - worker.next_bit_mode = 1; + worker.next_bit_mode = MODE_ONE; + worker.next_bit_state = 0; + continue; + } + if (args[argidx] == "-anyseq") { + got_value = true; + worker.next_bit_mode = MODE_ANYSEQ; + worker.next_bit_state = 0; + continue; + } + if (args[argidx] == "-anyconst") { + got_value = true; + worker.next_bit_mode = MODE_ANYCONST; + worker.next_bit_state = 0; + continue; + } + if (args[argidx] == "-undef") { + got_value = true; + worker.next_bit_mode = MODE_UNDEF; + worker.next_bit_state = 0; continue; } if (args[argidx] == "-init") { @@ -113,7 +202,7 @@ struct SetundefPass : public Pass { } if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) { got_value = true; - worker.next_bit_mode = 2; + worker.next_bit_mode = MODE_RANDOM; worker.next_bit_state = atoi(args[++argidx].c_str()) + 1; for (int i = 0; i < 10; i++) worker.next_bit(); @@ -123,8 +212,13 @@ struct SetundefPass : public Pass { } extra_args(args, argidx, design); + if (expose_mode && !undriven_mode) + log_cmd_error("Option -expose must be used with option -undriven.\n"); if (!got_value) - log_cmd_error("One of the options -zero, -one, or -random <seed> must be specified.\n"); + log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> must be specified.\n"); + + if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)) + log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n"); for (auto module : design->selected_modules()) { @@ -133,25 +227,103 @@ struct SetundefPass : public Pass { if (!module->processes.empty()) log_error("The 'setundef' command can't operate in -undriven mode on modules with processes. Run 'proc' first.\n"); - SigMap sigmap(module); - SigPool undriven_signals; + if (expose_mode) + { + SigMap sigmap(module); + dict<SigBit, bool> wire_drivers; + pool<SigBit> used_wires; + SigPool undriven_signals; + + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) { + SigSpec sig = sigmap(conn.second); + if (cell->input(conn.first)) + for (auto bit : sig) + if (bit.wire) + used_wires.insert(bit); + if (cell->output(conn.first)) + for (int i = 0; i < GetSize(sig); i++) + if (sig[i].wire) + wire_drivers[sig[i]] = true; + } + + for (auto wire : module->wires()) { + if (wire->port_input) { + SigSpec sig = sigmap(wire); + for (int i = 0; i < GetSize(sig); i++) + wire_drivers[sig[i]] = true; + } + if (wire->port_output) { + SigSpec sig = sigmap(wire); + for (auto bit : sig) + if (bit.wire) + used_wires.insert(bit); + } + } + + pool<RTLIL::Wire*> undriven_wires; + for (auto bit : used_wires) + if (!wire_drivers.count(bit)) + undriven_wires.insert(bit.wire); + + for (auto &it : undriven_wires) + undriven_signals.add(sigmap(it)); + + for (auto &it : undriven_wires) + if (it->port_input) + undriven_signals.del(sigmap(it)); + + CellTypes ct(design); + for (auto &it : module->cells_) + for (auto &conn : it.second->connections()) + if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) + undriven_signals.del(sigmap(conn.second)); + + RTLIL::SigSpec sig = undriven_signals.export_all(); + for (auto &c : sig.chunks()) { + RTLIL::Wire * wire; + if (c.wire->width == c.width) { + wire = c.wire; + wire->port_input = true; + } else { + string name = c.wire->name.str() + "$[" + std::to_string(c.width + c.offset) + ":" + std::to_string(c.offset) + "]"; + wire = add_wire(module, name, c.width, true, false); + module->connect(RTLIL::SigSig(c, wire)); + } + log("Exposing undriven wire %s as input.\n", wire->name.c_str()); + } + module->fixup_ports(); + } + else + { + SigMap sigmap(module); + SigPool undriven_signals; - for (auto &it : module->wires_) - if (!it.second->port_input) + for (auto &it : module->wires_) undriven_signals.add(sigmap(it.second)); - CellTypes ct(design); - for (auto &it : module->cells_) - for (auto &conn : it.second->connections()) - if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) - undriven_signals.del(sigmap(conn.second)); - - RTLIL::SigSpec sig = undriven_signals.export_all(); - for (auto &c : sig.chunks()) { - RTLIL::SigSpec bits; - for (int i = 0; i < c.width; i++) - bits.append(worker.next_bit()); - module->connect(RTLIL::SigSig(c, bits)); + for (auto &it : module->wires_) + if (it.second->port_input) + undriven_signals.del(sigmap(it.second)); + + CellTypes ct(design); + for (auto &it : module->cells_) + for (auto &conn : it.second->connections()) + if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) + undriven_signals.del(sigmap(conn.second)); + + RTLIL::SigSpec sig = undriven_signals.export_all(); + for (auto &c : sig.chunks()) { + RTLIL::SigSpec bits; + if (worker.next_bit_mode == MODE_ANYSEQ) + bits = module->Anyseq(NEW_ID, c.width); + else if (worker.next_bit_mode == MODE_ANYCONST) + bits = module->Anyconst(NEW_ID, c.width); + else + for (int i = 0; i < c.width; i++) + bits.append(worker.next_bit()); + module->connect(RTLIL::SigSig(c, bits)); + } } } @@ -236,6 +408,35 @@ struct SetundefPass : public Pass { } module->rewrite_sigspecs(worker); + + if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST) + { + vector<SigSpec*> siglist; + siglist.swap(worker.siglist); + + for (auto sigptr : siglist) + { + SigSpec &sig = *sigptr; + int cursor = 0; + + while (cursor < GetSize(sig)) + { + int width = 0; + while (cursor+width < GetSize(sig) && sig[cursor+width] == State::Sx) + width++; + + if (width > 0) { + if (worker.next_bit_mode == MODE_ANYSEQ) + sig.replace(cursor, module->Anyseq(NEW_ID, width)); + else + sig.replace(cursor, module->Anyconst(NEW_ID, width)); + cursor += width; + } else { + cursor++; + } + } + } + } } } } SetundefPass; diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 3a3939a8..a4887324 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -30,6 +30,10 @@ # include <readline/readline.h> #endif +#ifdef YOSYS_ENABLE_EDITLINE +# include <editline/readline.h> +#endif + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -569,7 +573,7 @@ struct ShowWorker struct ShowPass : public Pass { ShowPass() : Pass("show", "generate schematics using graphviz") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -580,6 +584,7 @@ struct ShowPass : public Pass { log("\n"); log(" -viewer <viewer>\n"); log(" Run the specified command with the graphics file as parameter.\n"); + log(" On Windows, this pauses yosys until the viewer exits.\n"); log("\n"); log(" -format <format>\n"); log(" Generate a graphics file in the specified format. Use 'dot' to just\n"); @@ -641,7 +646,7 @@ struct ShowPass : public Pass { log(" do not add the module name as graph title to the dot file\n"); log("\n"); log("When no <format> is specified, 'dot' is used. When no <format> and <viewer> is\n"); - log("specified, 'xdot' is used to display the schematic.\n"); + log("specified, 'xdot' is used to display the schematic (POSIX systems only).\n"); log("\n"); log("The generated output files are '~/.yosys_show.dot' and '~/.yosys_show.<format>',\n"); log("unless another prefix is specified using -prefix <prefix>.\n"); @@ -651,7 +656,7 @@ struct ShowPass : public Pass { log("the 'show' command is executed.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Generating Graphviz representation of design.\n"); log_push(); @@ -677,6 +682,7 @@ struct ShowPass : public Pass { bool flag_enum = false; bool flag_abbreviate = true; bool flag_notitle = false; + bool custom_prefix = false; RTLIL::IdString colorattr; size_t argidx; @@ -693,6 +699,7 @@ struct ShowPass : public Pass { } if (arg == "-prefix" && argidx+1 < args.size()) { prefix = args[++argidx]; + custom_prefix = true; continue; } if (arg == "-color" && argidx+2 < args.size()) { @@ -778,6 +785,7 @@ struct ShowPass : public Pass { for (auto filename : libfiles) { std::ifstream f; f.open(filename.c_str()); + yosys_input_files.insert(filename); if (f.fail()) log_error("Can't open lib file `%s'.\n", filename.c_str()); RTLIL::Design *lib = new RTLIL::Design; @@ -793,6 +801,8 @@ struct ShowPass : public Pass { log("Writing dot description to `%s'.\n", dot_file.c_str()); FILE *f = fopen(dot_file.c_str(), "w"); + if (custom_prefix) + yosys_output_files.insert(dot_file); if (f == NULL) { for (auto lib : libs) delete lib; @@ -808,14 +818,30 @@ struct ShowPass : public Pass { log_cmd_error("Nothing there to show.\n"); if (format != "dot" && !format.empty()) { - std::string cmd = stringf("dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'", format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str()); + #ifdef _WIN32 + // system()/cmd.exe does not understand single quotes on Windows. + #define DOT_CMD "dot -T%s \"%s\" > \"%s.new\" && move \"%s.new\" \"%s\"" + #else + #define DOT_CMD "dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'" + #endif + std::string cmd = stringf(DOT_CMD, format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str()); + #undef DOT_CMD log("Exec: %s\n", cmd.c_str()); if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); } if (!viewer_exe.empty()) { - std::string cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str()); + #ifdef _WIN32 + // system()/cmd.exe does not understand single quotes nor + // background tasks on Windows. So we have to pause yosys + // until the viewer exits. + #define VIEW_CMD "%s \"%s\"" + #else + #define VIEW_CMD "%s '%s' &" + #endif + std::string cmd = stringf(VIEW_CMD, viewer_exe.c_str(), out_file.c_str()); + #undef VIEW_CMD log("Exec: %s\n", cmd.c_str()); if (run_command(cmd) != 0) log_cmd_error("Shell command failed!\n"); diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index 7418ec4d..bafafca4 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -247,7 +247,7 @@ struct SpliceWorker struct SplicePass : public Pass { SplicePass() : Pass("splice", "create explicit splicing cells") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -288,7 +288,7 @@ struct SplicePass : public Pass { log("by selected wires are rewired.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool sel_by_cell = false; bool sel_by_wire = false; diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 14eeb066..f5a1f17b 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -37,14 +37,20 @@ struct SplitnetsWorker new_wire_name += format.substr(0, 1); if (width > 1) { - new_wire_name += stringf("%d", offset+width-1); + if (wire->upto) + new_wire_name += stringf("%d", wire->start_offset+wire->width-(offset+width)-1); + else + new_wire_name += stringf("%d", wire->start_offset+offset+width-1); if (format.size() > 2) new_wire_name += format.substr(2, 1); else new_wire_name += ":"; } - new_wire_name += stringf("%d", offset); + if (wire->upto) + new_wire_name += stringf("%d", wire->start_offset+wire->width-offset-1); + else + new_wire_name += stringf("%d", wire->start_offset+offset); if (format.size() > 1) new_wire_name += format.substr(1, 1); @@ -81,7 +87,7 @@ struct SplitnetsWorker struct SplitnetsPass : public Pass { SplitnetsPass() : Pass("splitnets", "split up multi-bit nets") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -103,7 +109,7 @@ struct SplitnetsPass : public Pass { log(" and split nets so that no driver drives only part of a net.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool flag_ports = false; bool flag_driver = false; diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 362a0edf..54f4ea81 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -112,7 +112,7 @@ struct statdata_t "$lut", "$and", "$or", "$xor", "$xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", - "$add", "$sub", "$mul", "$div", "$mod", "$pow")) { + "$add", "$sub", "$mul", "$div", "$mod", "$pow", "$alu")) { int width_a = it.second->hasPort("\\A") ? GetSize(it.second->getPort("\\A")) : 0; int width_b = it.second->hasPort("\\B") ? GetSize(it.second->getPort("\\B")) : 0; int width_y = it.second->hasPort("\\Y") ? GetSize(it.second->getPort("\\Y")) : 0; @@ -142,7 +142,7 @@ struct statdata_t } } - void log_data() + void log_data(RTLIL::IdString mod_name, bool top_mod) { log(" Number of wires: %6d\n", num_wires); log(" Number of wire bits: %6d\n", num_wire_bits); @@ -163,7 +163,7 @@ struct statdata_t if (area != 0) { log("\n"); - log(" Chip area for this module: %f\n", area); + log(" Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area); } } }; @@ -190,6 +190,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil { std::ifstream f; f.open(liberty_file.c_str()); + yosys_input_files.insert(liberty_file); if (f.fail()) log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file.c_str(), strerror(errno)); LibertyParser libparser(f); @@ -208,7 +209,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil struct StatPass : public Pass { StatPass() : Pass("stat", "print some statistics") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -230,7 +231,7 @@ struct StatPass : public Pass { log(" e.g. $add_8 for an 8 bit wide $add cell.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Printing statistics.\n"); @@ -274,7 +275,7 @@ struct StatPass : public Pass { log("\n"); log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); log("\n"); - data.log_data(); + data.log_data(mod->name, false); } if (top_mod != NULL && GetSize(mod_stat) > 1) @@ -287,7 +288,7 @@ struct StatPass : public Pass { statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0); log("\n"); - data.log_data(); + data.log_data(top_mod->name, true); } log("\n"); diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index 3db2dbf0..ff80f385 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct TeePass : public Pass { TeePass() : Pass("tee", "redirect command output to file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -49,7 +49,7 @@ struct TeePass : public Pass { log(" Add/subract INT from the -v setting for this command.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { std::vector<FILE*> backup_log_files, files_to_close; int backup_log_verbose_level = log_verbose_level; @@ -65,6 +65,7 @@ struct TeePass : public Pass { if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) { const char *open_mode = args[argidx] == "-o" ? "w" : "a+"; FILE *f = fopen(args[++argidx].c_str(), open_mode); + yosys_input_files.insert(args[argidx]); if (f == NULL) { for (auto cf : files_to_close) fclose(cf); diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc index 56223610..3c0eac8d 100644 --- a/passes/cmds/torder.cc +++ b/passes/cmds/torder.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct TorderPass : public Pass { TorderPass() : Pass("torder", "print cells in topological order") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -43,7 +43,7 @@ struct TorderPass : public Pass { log(" are not used in topological sorting. this option deactivates that.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { bool noautostop = false; dict<IdString, pool<IdString>> stop_db; diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 1a5f873f..f5305cde 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -25,34 +25,34 @@ PRIVATE_NAMESPACE_BEGIN struct TraceMonitor : public RTLIL::Monitor { - virtual void notify_module_add(RTLIL::Module *module) YS_OVERRIDE + void notify_module_add(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Module add: %s\n", log_id(module)); } - virtual void notify_module_del(RTLIL::Module *module) YS_OVERRIDE + void notify_module_del(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Module delete: %s\n", log_id(module)); } - virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE + void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE { log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig)); } - virtual void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_OVERRIDE + void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_OVERRIDE { log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second)); } - virtual void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) YS_OVERRIDE + void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) YS_OVERRIDE { log("#TRACE# New connections in module %s:\n", log_id(module)); for (auto &sigsig : sigsig_vec) log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second)); } - virtual void notify_blackout(RTLIL::Module *module) YS_OVERRIDE + void notify_blackout(RTLIL::Module *module) YS_OVERRIDE { log("#TRACE# Blackout in module %s:\n", log_id(module)); } @@ -60,7 +60,7 @@ struct TraceMonitor : public RTLIL::Monitor struct TracePass : public Pass { TracePass() : Pass("trace", "redirect command output to file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -70,7 +70,7 @@ struct TracePass : public Pass { log("the design in real time.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -95,4 +95,3 @@ struct TracePass : public Pass { } TracePass; PRIVATE_NAMESPACE_END - diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index b7826593..9613b462 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct WriteFileFrontend : public Frontend { WriteFileFrontend() : Frontend("=write_file", "write a text to a file") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -44,7 +44,7 @@ struct WriteFileFrontend : public Frontend { log(" EOT\n"); log("\n"); } - virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) + void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE { bool append_mode = false; std::string output_filename; @@ -67,6 +67,7 @@ struct WriteFileFrontend : public Frontend { extra_args(f, filename, args, argidx); FILE *of = fopen(output_filename.c_str(), append_mode ? "a" : "w"); + yosys_output_files.insert(output_filename); char buffer[64 * 1024]; int bytes; |