diff --git a/.github/actions/setup-build-env/action.yml b/.github/actions/setup-build-env/action.yml index 248709abb..93585fac3 100644 --- a/.github/actions/setup-build-env/action.yml +++ b/.github/actions/setup-build-env/action.yml @@ -1,4 +1,4 @@ -name: Build environment setup +4name: Build environment setup description: Configure build env for Yosys builds runs: using: composite @@ -8,7 +8,8 @@ runs: shell: bash run: | sudo apt-get update - sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache + sudo apt-get install libdwarf-dev libelf-dev elfutils libdw-dev ccache + sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libgtest-dev - name: Install macOS Dependencies if: runner.os == 'macOS' diff --git a/.github/workflows/prepare-docs.yml b/.github/workflows/prepare-docs.yml index 17d37d08c..f19b1c7af 100644 --- a/.github/workflows/prepare-docs.yml +++ b/.github/workflows/prepare-docs.yml @@ -48,7 +48,7 @@ jobs: echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf echo "ENABLE_CCACHE := 1" >> Makefile.conf echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf - make -j$procs ENABLE_LTO=1 + make -j$procs - name: Prepare docs shell: bash diff --git a/.github/workflows/test-sanitizers.yml b/.github/workflows/test-sanitizers.yml index 264aa97f0..fb7c44e78 100644 --- a/.github/workflows/test-sanitizers.yml +++ b/.github/workflows/test-sanitizers.yml @@ -114,3 +114,8 @@ jobs: shell: bash run: | find tests/**/*.err -print -exec cat {} \; + + - name: Run unit tests + shell: bash + run: | + make -j$procs unit-test ENABLE_LIBYOSYS=1 diff --git a/.github/workflows/test-verific.yml b/.github/workflows/test-verific.yml index c2e4228c4..503d6c31b 100644 --- a/.github/workflows/test-verific.yml +++ b/.github/workflows/test-verific.yml @@ -78,3 +78,8 @@ jobs: if: ${{ github.ref == 'refs/heads/main' }} run: | make -C sby run_ci + + - name: Run unit tests + shell: bash + run: | + make -j$procs unit-test ENABLE_LTO=1 ENABLE_LIBYOSYS=1 diff --git a/Brewfile b/Brewfile index 5735fb436..b3e739fd1 100644 --- a/Brewfile +++ b/Brewfile @@ -12,6 +12,8 @@ brew "boost-python3" brew "llvm@20" brew "lld" +brew "googletest" + brew "autoconf" brew "dwarfutils" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 74f9ab10d..403292b0b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,14 +60,11 @@ merge; please do not use these labels if you are not a maintainer. # Asking questions -If you have a question about how to use Yosys, please ask on our [discussions -page](https://github.com/YosysHQ/yosys/discussions) or in our [community -slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA). -The slack is also a great place to ask questions about developing or +If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/) or in our [discussions +page](https://github.com/YosysHQ/yosys/discussions). +The Discourse is also a great place to ask questions about developing or contributing to Yosys. -We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the +We have open [dev 'jour fixe' (JF) meetings](https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing) where developers from YosysHQ and the community come together to discuss open issues and PRs. This is also a good -place to talk to us about how to implement larger PRs. Please join the -community slack if you would like to join the next meeting, the link is -available in the description of the #devel-discuss channel. +place to talk to us about how to implement larger PRs. diff --git a/Makefile b/Makefile index 58759751f..f57abade0 100644 --- a/Makefile +++ b/Makefile @@ -180,7 +180,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+178 +YOSYS_VER := 0.57+218 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 05714bc2e..87cdc17c3 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -106,7 +106,7 @@ struct Index { info.found_blackboxes.insert(cell); } else { if (!submodule || submodule->get_blackbox_attribute()) - log_error("Unsupported cell type: %s (%s in %s)\n", + log_warning("Unsupported cell type: %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(m)); } } @@ -1017,7 +1017,7 @@ struct XAigerWriter : AigerWriter { auto &minfo = cursor.leaf_minfo(*this); for (auto box : minfo.found_blackboxes) { - log_debug(" - %s.%s (type %s): ", cursor.path().c_str(), + log_debug(" - %s.%s (type %s): ", cursor.path(), RTLIL::unescape_id(box->name), log_id(box->type)); diff --git a/docs/source/cmd/index_internal.rst b/docs/source/cmd/index_internal.rst index bfb369dde..ab9c13aba 100644 --- a/docs/source/cmd/index_internal.rst +++ b/docs/source/cmd/index_internal.rst @@ -67,7 +67,7 @@ The ``formatted_help()`` method Dumping command help to json ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `help -dump-cells-json cmds.json` +- `help -dump-cmds-json cmds.json` + generates a ``ContentListing`` for each command registered in Yosys + tries to parse unformatted ``Pass::help()`` output if diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 70d94faff..4df37c0cd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -476,7 +476,7 @@ void AigerReader::parse_xaiger() else if (c == 'n') { parse_xaiger_literal(f); f >> s; - log_debug("n: '%s'\n", s.c_str()); + log_debug("n: '%s'\n", s); } else if (c == 'h') { f.ignore(sizeof(uint32_t)); diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index 625b2c0e8..c21867b30 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -83,11 +83,11 @@ struct RpcServer { std::string request; json_request.dump(request); request += '\n'; - log_debug("RPC frontend request: %s", request.c_str()); + log_debug("RPC frontend request: %s", request); write(request); std::string response = read(); - log_debug("RPC frontend response: %s", response.c_str()); + log_debug("RPC frontend response: %s", response); std::string error; Json json_response = Json::parse(response, error); if (json_response.is_null()) diff --git a/kernel/cost.cc b/kernel/cost.cc index 70feacd52..ce83654ab 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -150,14 +150,14 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) return 1; if (design_ && design_->module(cell->type) && cell->parameters.empty()) { - log_debug("%s is a module, recurse\n", cell->name.c_str()); + log_debug("%s is a module, recurse\n", cell->name); return get(design_->module(cell->type)); } else if (cell->is_builtin_ff()) { log_assert(cell->hasPort(ID::Q) && "Weird flip flop"); - log_debug("%s is ff\n", cell->name.c_str()); + log_debug("%s is ff\n", cell->name); return cell->getParam(ID::WIDTH).as_int(); } else if (cell->type.in(ID($mem), ID($mem_v2))) { - log_debug("%s is mem\n", cell->name.c_str()); + log_debug("%s is mem\n", cell->name); return cell->getParam(ID::WIDTH).as_int() * cell->getParam(ID::SIZE).as_int(); } else if (y_coef(cell->type)) { // linear with Y_WIDTH or WIDTH @@ -166,23 +166,23 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) int width = cell->getParam(param).as_int(); if (cell->type == ID($demux)) width <<= cell->getParam(ID::S_WIDTH).as_int(); - log_debug("%s Y*coef %d * %d\n", cell->name.c_str(), width, y_coef(cell->type)); + log_debug("%s Y*coef %d * %d\n", cell->name, width, y_coef(cell->type)); return width * y_coef(cell->type); } else if (sum_coef(cell->type)) { // linear with sum of port widths unsigned int sum = port_width_sum(cell); - log_debug("%s sum*coef %d * %d\n", cell->name.c_str(), sum, sum_coef(cell->type)); + log_debug("%s sum*coef %d * %d\n", cell->name, sum, sum_coef(cell->type)); return sum * sum_coef(cell->type); } else if (max_inp_coef(cell->type)) { // linear with largest input width unsigned int max = max_inp_width(cell); - log_debug("%s max*coef %d * %d\n", cell->name.c_str(), max, max_inp_coef(cell->type)); + log_debug("%s max*coef %d * %d\n", cell->name, max, max_inp_coef(cell->type)); return max * max_inp_coef(cell->type); } else if (is_div_mod(cell->type) || cell->type == ID($mul)) { // quadratic with sum of port widths unsigned int sum = port_width_sum(cell); unsigned int coef = cell->type == ID($mul) ? 3 : 5; - log_debug("%s coef*(sum**2) %d * %d\n", cell->name.c_str(), coef, sum * sum); + log_debug("%s coef*(sum**2) %d * %d\n", cell->name, coef, sum * sum); return coef * sum * sum; } else if (cell->type.in(ID($macc), ID($macc_v2))) { // quadratic per term @@ -203,15 +203,15 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) } else if (cell->type == ID($lut)) { int width = cell->getParam(ID::WIDTH).as_int(); unsigned int cost = 1U << (unsigned int)width; - log_debug("%s is 2**%d\n", cell->name.c_str(), width); + log_debug("%s is 2**%d\n", cell->name, width); return cost; } else if (cell->type == ID($sop)) { int width = cell->getParam(ID::WIDTH).as_int(); int depth = cell->getParam(ID::DEPTH).as_int(); - log_debug("%s is (2*%d + 1)*%d\n", cell->name.c_str(), width, depth); + log_debug("%s is (2*%d + 1)*%d\n", cell->name, width, depth); return (2 * width + 1) * depth; } else if (is_free(cell->type)) { - log_debug("%s is free\n", cell->name.c_str()); + log_debug("%s is free\n", cell->name); return 0; } else if (is_mem(cell->type)) { // SILIMATE: Memory cells have no bearing on cross module optimizations diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index ed3ff8cbf..c5f2bd2c1 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -164,7 +164,7 @@ void FstData::extractVarNames() char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 16); if (*endptr) { - log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; } @@ -178,7 +178,7 @@ void FstData::extractVarNames() char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 10); if (*endptr) { - log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; } diff --git a/kernel/log.cc b/kernel/log.cc index 0085980b1..34e56f8ac 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -331,10 +331,12 @@ static void log_error_with_prefix(std::string_view prefix, std::string str) if (log_errfile != NULL) log_files.push_back(log_errfile); - if (log_error_stderr) + if (log_error_stderr) { + log_flush(); // Make sure we flush stdout before replacing it with stderr for (auto &f : log_files) if (f == stdout) f = stderr; + } log_last_error = std::move(str); log("%s%s", prefix, log_last_error); @@ -405,6 +407,11 @@ void log_abort_internal(const char *file, int line) log_error("Abort in %s:%d.\n", file, line); } +void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message) +{ + log_error("Abort in %s:%d (%s): %s\n", file, line, func, message); +} + void log_formatted_cmd_error(std::string str) { if (log_cmd_error_throw) { diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a112c7ca0..1be54dca1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4456,7 +4456,7 @@ RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const RTLIL::SigBit RTLIL::SigChunk::operator[](int offset) const { log_assert(offset >= 0); - log_assert(offset <= width); + log_assert(offset < width); RTLIL::SigBit ret; if (wire) { ret.wire = wire; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 94a0d9676..9344a8043 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1252,7 +1252,8 @@ private: public: SigSpec() : width_(0), hash_(0) {} SigSpec(std::initializer_list parts); - + SigSpec(const SigSpec &value) = default; + SigSpec(SigSpec &&value) = default; SigSpec(const RTLIL::Const &value); SigSpec(RTLIL::Const &&value); SigSpec(const RTLIL::SigChunk &chunk); @@ -1269,6 +1270,9 @@ public: SigSpec(const std::set &bits); explicit SigSpec(bool bit); + SigSpec &operator=(const SigSpec &rhs) = default; + SigSpec &operator=(SigSpec &&rhs) = default; + inline const std::vector &chunks() const { pack(); return chunks_; } inline const std::vector &bits() const { inline_unpack(); return bits_; } diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index dcab30e4b..722b7d04d 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -142,7 +142,12 @@ #define YOSYS_CONSTEVAL constexpr #endif -#define YOSYS_ABORT(s) abort() +#define YOSYS_ABORT(s) YOSYS_NAMESPACE_PREFIX log_yosys_abort_message(__FILE__, __LINE__, __FUNCTION__, s) + +// This has to precede including "kernel/io.h" +YOSYS_NAMESPACE_BEGIN +[[noreturn]] void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message); +YOSYS_NAMESPACE_END #include "kernel/io.h" diff --git a/passes/cmds/abstract.cc b/passes/cmds/abstract.cc index 88f07a5aa..2ea71268b 100644 --- a/passes/cmds/abstract.cc +++ b/passes/cmds/abstract.cc @@ -156,9 +156,9 @@ dict> gather_selected_reps(Module* mod, const std void explain_selections(const std::vector& reasons) { for (std::variant reason : reasons) { if (Cell** cell_reason = std::get_if(&reason)) - log_debug("\tcell %s\n", (*cell_reason)->name.c_str()); + log_debug("\tcell %s\n", (*cell_reason)->name); else if (Wire** wire_reason = std::get_if(&reason)) - log_debug("\twire %s\n", (*wire_reason)->name.c_str()); + log_debug("\twire %s\n", (*wire_reason)->name); else log_assert(false && "insane reason variant\n"); } diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc index 737bd3e58..1ad2eab3c 100644 --- a/passes/cmds/autoname.cc +++ b/passes/cmds/autoname.cc @@ -22,11 +22,24 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -int autoname_worker(Module *module, const dict& wire_score) +typedef struct name_proposal { + string name; + unsigned int score; + name_proposal() : name(""), score(-1) { } + name_proposal(string name, unsigned int score) : name(name), score(score) { } + bool operator<(const name_proposal &other) const { + if (score != other.score) + return score < other.score; + else + return name.length() < other.name.length(); + } +} name_proposal; + +int autoname_worker(Module *module, const dict& wire_score) { - dict> proposed_cell_names; - dict> proposed_wire_names; - int best_score = -1; + dict proposed_cell_names; + dict proposed_wire_names; + name_proposal best_name; for (auto cell : module->selected_cells()) { if (cell->name[0] == '$') { @@ -36,14 +49,14 @@ int autoname_worker(Module *module, const dict& wire_score) if (bit.wire != nullptr && bit.wire->name[0] != '$') { if (suffix.empty()) suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first)); - string new_name(bit.wire->name.str() + suffix); - int score = wire_score.at(bit.wire); - if (cell->output(conn.first)) score = 0; - score = 10000*score + new_name.size(); - if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) { - if (best_score < 0 || score < best_score) - best_score = score; - proposed_cell_names[cell] = make_pair(score, new_name); + name_proposal proposed_name( + bit.wire->name.str() + suffix, + cell->output(conn.first) ? 0 : wire_score.at(bit.wire) + ); + if (!proposed_cell_names.count(cell) || proposed_name < proposed_cell_names.at(cell)) { + if (proposed_name < best_name) + best_name = proposed_name; + proposed_cell_names[cell] = proposed_name; } } } @@ -54,37 +67,44 @@ int autoname_worker(Module *module, const dict& wire_score) if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) { if (suffix.empty()) suffix = stringf("_%s", log_id(conn.first)); - string new_name(cell->name.str() + suffix); - int score = wire_score.at(bit.wire); - if (cell->output(conn.first)) score = 0; - score = 10000*score + new_name.size(); - if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) { - if (best_score < 0 || score < best_score) - best_score = score; - proposed_wire_names[bit.wire] = make_pair(score, new_name); + name_proposal proposed_name( + cell->name.str() + suffix, + cell->output(conn.first) ? 0 : wire_score.at(bit.wire) + ); + if (!proposed_wire_names.count(bit.wire) || proposed_name < proposed_wire_names.at(bit.wire)) { + if (proposed_name < best_name) + best_name = proposed_name; + proposed_wire_names[bit.wire] = proposed_name; } } } } } + int count = 0; + // compare against double best score for following comparisons so we don't + // pre-empt a future iteration + best_name.score *= 2; + for (auto &it : proposed_cell_names) { - if (best_score*2 < it.second.first) + if (best_name < it.second) continue; - IdString n = module->uniquify(IdString(it.second.second)); + IdString n = module->uniquify(IdString(it.second.name)); log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); module->rename(it.first, n); + count++; } for (auto &it : proposed_wire_names) { - if (best_score*2 < it.second.first) + if (best_name < it.second) continue; - IdString n = module->uniquify(IdString(it.second.second)); + IdString n = module->uniquify(IdString(it.second.name)); log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); module->rename(it.first, n); + count++; } - return proposed_cell_names.size() + proposed_wire_names.size(); + return count; } struct AutonamePass : public Pass { @@ -110,12 +130,13 @@ struct AutonamePass : public Pass { // } break; } + extra_args(args, argidx, design); log_header(design, "Executing AUTONAME pass.\n"); for (auto module : design->selected_modules()) { - dict wire_score; + dict wire_score; for (auto cell : module->selected_cells()) for (auto &conn : cell->connections()) for (auto bit : conn.second) diff --git a/passes/cmds/box_derive.cc b/passes/cmds/box_derive.cc index da698b04d..a0faacc9a 100644 --- a/passes/cmds/box_derive.cc +++ b/passes/cmds/box_derive.cc @@ -96,7 +96,7 @@ struct BoxDerivePass : Pass { IdString derived_type = base->derive(d, cell->parameters); Module *derived = d->module(derived_type); log_assert(derived && "Failed to derive module\n"); - log_debug("derived %s\n", derived_type.c_str()); + log_debug("derived %s\n", derived_type); if (!naming_attr.empty() && derived->has_attribute(naming_attr)) { IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr)); diff --git a/passes/cmds/linecoverage.cc b/passes/cmds/linecoverage.cc index 6898f33f5..26adcce76 100644 --- a/passes/cmds/linecoverage.cc +++ b/passes/cmds/linecoverage.cc @@ -95,7 +95,7 @@ struct CoveragePass : public Pass { { log_debug("Module %s:\n", log_id(module)); for (auto wire: module->wires()) { - log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute().c_str(), log_id(wire->name)); + log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), log_id(wire->name)); for (auto src: wire->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; @@ -109,7 +109,7 @@ struct CoveragePass : public Pass { } } for (auto cell: module->cells()) { - log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute().c_str(), log_id(cell->name)); + log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), log_id(cell->name)); for (auto src: cell->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; diff --git a/passes/memory/memory_libmap.cc b/passes/memory/memory_libmap.cc index 0fb4608b1..c3c10363b 100644 --- a/passes/memory/memory_libmap.cc +++ b/passes/memory/memory_libmap.cc @@ -392,7 +392,7 @@ void MemMapping::dump_configs(int stage) { void MemMapping::dump_config(MemConfig &cfg) { log_debug("- %s:\n", log_id(cfg.def->id)); for (auto &it: cfg.def->options) - log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second)); + log_debug(" - option %s %s\n", it.first, log_const(it.second)); log_debug(" - emulation score: %d\n", cfg.score_emu); log_debug(" - replicates (for ports): %d\n", cfg.repl_port); log_debug(" - replicates (for data): %d\n", cfg.repl_d); @@ -403,7 +403,7 @@ void MemMapping::dump_config(MemConfig &cfg) { for (int x: cfg.def->dbits) os << " " << x; std::string dbits_s = os.str(); - log_debug(" - abits %d dbits%s\n", cfg.def->abits, dbits_s.c_str()); + log_debug(" - abits %d dbits%s\n", cfg.def->abits, dbits_s); if (cfg.def->byte != 0) log_debug(" - byte width %d\n", cfg.def->byte); log_debug(" - chosen base width %d\n", cfg.def->dbits[cfg.base_width_log2]); @@ -414,25 +414,25 @@ void MemMapping::dump_config(MemConfig &cfg) { else os << " " << x; std::string swizzle_s = os.str(); - log_debug(" - swizzle%s\n", swizzle_s.c_str()); + log_debug(" - swizzle%s\n", swizzle_s); os.str(""); for (int i = 0; (1 << i) <= cfg.hard_wide_mask; i++) if (cfg.hard_wide_mask & 1 << i) os << " " << i; std::string wide_s = os.str(); if (cfg.hard_wide_mask) - log_debug(" - hard wide bits%s\n", wide_s.c_str()); + log_debug(" - hard wide bits%s\n", wide_s); if (cfg.emu_read_first) log_debug(" - emulate read-first behavior\n"); for (int i = 0; i < GetSize(mem.wr_ports); i++) { auto &pcfg = cfg.wr_ports[i]; if (pcfg.rd_port == -1) - log_debug(" - write port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str()); + log_debug(" - write port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0]); else - log_debug(" - write port %d: port group %s (shared with read port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str(), pcfg.rd_port); + log_debug(" - write port %d: port group %s (shared with read port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0], pcfg.rd_port); for (auto &it: pcfg.def->options) - log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second)); + log_debug(" - option %s %s\n", it.first, log_const(it.second)); if (cfg.def->width_mode == WidthMode::PerPort) { std::stringstream os; for (int i = pcfg.def->min_wr_wide_log2; i <= pcfg.def->max_wr_wide_log2; i++) @@ -441,7 +441,7 @@ void MemMapping::dump_config(MemConfig &cfg) { const char *note = ""; if (pcfg.rd_port != -1) note = pcfg.def->width_tied ? " (tied)" : " (independent)"; - log_debug(" - widths%s%s\n", widths_s.c_str(), note); + log_debug(" - widths%s%s\n", widths_s, note); } for (auto i: pcfg.emu_prio) log_debug(" - emulate priority over write port %d\n", i); @@ -449,11 +449,11 @@ void MemMapping::dump_config(MemConfig &cfg) { for (int i = 0; i < GetSize(mem.rd_ports); i++) { auto &pcfg = cfg.rd_ports[i]; if (pcfg.wr_port == -1) - log_debug(" - read port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str()); + log_debug(" - read port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0]); else - log_debug(" - read port %d: port group %s (shared with write port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str(), pcfg.wr_port); + log_debug(" - read port %d: port group %s (shared with write port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0], pcfg.wr_port); for (auto &it: pcfg.def->options) - log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second)); + log_debug(" - option %s %s\n", it.first, log_const(it.second)); if (cfg.def->width_mode == WidthMode::PerPort) { std::stringstream os; for (int i = pcfg.def->min_rd_wide_log2; i <= pcfg.def->max_rd_wide_log2; i++) @@ -462,7 +462,7 @@ void MemMapping::dump_config(MemConfig &cfg) { const char *note = ""; if (pcfg.wr_port != -1) note = pcfg.def->width_tied ? " (tied)" : " (independent)"; - log_debug(" - widths%s%s\n", widths_s.c_str(), note); + log_debug(" - widths%s%s\n", widths_s, note); } if (pcfg.emu_sync) log_debug(" - emulate data register\n"); @@ -2242,7 +2242,7 @@ struct MemoryLibMapPass : public Pass { if (!map.logic_ok) { if (map.cfgs.empty()) { log_debug("Rejected candidates for mapping memory %s.%s:\n", log_id(module->name), log_id(mem.memid)); - log_debug("%s", map.rejected_cfg_debug_msgs.c_str()); + log_debug("%s", map.rejected_cfg_debug_msgs); log_error("no valid mapping found for memory %s.%s\n", log_id(module->name), log_id(mem.memid)); } idx = 0; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index e18ad2715..f3554e4de 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -204,7 +204,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto cell : unused) { if (verbose) - log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str()); + log_debug(" removing unused `%s' cell `%s'.\n", cell->type, cell->name); module->design->scratchpad_set_bool("opt.did_something", true); if (cell->is_builtin_ff()) ffinit.remove_init(cell->getPort(ID::Q)); @@ -215,7 +215,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto it : mem_unused) { if (verbose) - log_debug(" removing unused memory `%s'.\n", it.c_str()); + log_debug(" removing unused memory `%s'.\n", it); delete module->memories.at(it); module->memories.erase(it); } @@ -496,7 +496,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool unused int del_temp_wires_count = 0; for (auto wire : del_wires_queue) { if (ys_debug() || (check_public_name(wire->name) && verbose)) - log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); + log_debug(" removing unused non-port wire %s.\n", wire->name); else del_temp_wires_count++; } @@ -636,7 +636,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool unusedbitsattr } for (auto cell : delcells) { if (verbose) - log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), + log_debug(" removing buffer cell `%s': %s = %s\n", cell->name, log_signal(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::A))); module->remove(cell); } diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 37ae38225..c0a017748 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -162,7 +162,7 @@ struct OptLutWorker { if (lut_width <= dlogic_conn.first) { - log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first); legal = false; break; @@ -173,8 +173,8 @@ struct OptLutWorker if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic.second->getPort(dlogic_conn.second)[0])) { - log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second)); - log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic.second->getPort(dlogic_conn.second))); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type, dlogic_conn.second, log_signal(lut_dlogic.second->getPort(dlogic_conn.second))); legal = false; break; } @@ -182,7 +182,7 @@ struct OptLutWorker if (legal) { - log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); lut_legal_dlogics.insert(lut_dlogic); for (auto &dlogic_conn : dlogic_map) lut_dlogic_inputs.insert(dlogic_conn.first); @@ -496,9 +496,9 @@ struct OptLutWorker lutM_new_table.set(eval, (RTLIL::State) evaluate_lut(lutB, eval_inputs)); } - log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string().c_str()); - log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string().c_str()); - log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); + log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string()); + log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string()); + log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string()); lutM->setParam(ID::LUT, lutM_new_table); lutM->setPort(ID::A, lutM_new_inputs); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 1cb499740..13b1cb293 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -25,6 +25,7 @@ #include "libs/sha1/sha1.h" #include #include +#include #include #include #include @@ -170,24 +171,20 @@ struct OptMergeWorker } } - if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) || - cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) { + if (cell1->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul), + ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) { if (conn1.at(ID::A) < conn1.at(ID::B)) { - RTLIL::SigSpec tmp = conn1[ID::A]; - conn1[ID::A] = conn1[ID::B]; - conn1[ID::B] = tmp; + std::swap(conn1[ID::A], conn1[ID::B]); } if (conn2.at(ID::A) < conn2.at(ID::B)) { - RTLIL::SigSpec tmp = conn2[ID::A]; - conn2[ID::A] = conn2[ID::B]; - conn2[ID::B] = tmp; + std::swap(conn2[ID::A], conn2[ID::B]); } } else - if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) { + if (cell1->type.in(ID($reduce_xor), ID($reduce_xnor))) { conn1[ID::A].sort(); conn2[ID::A].sort(); } else - if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) { + if (cell1->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) { conn1[ID::A].sort_and_unify(); conn2[ID::A].sort_and_unify(); } else @@ -300,11 +297,11 @@ struct OptMergeWorker } did_something = true; - log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), other_cell->name.c_str()); + log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name, other_cell->name); for (auto &it : cell->connections()) { if (cell->output(it.first)) { RTLIL::SigSpec other_sig = other_cell->getPort(it.first); - log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), + log_debug(" Redirecting output %s: %s = %s\n", it.first, log_signal(it.second), log_signal(other_sig)); Const init = initvals(other_sig); initvals.remove_init(it.second); @@ -314,7 +311,7 @@ struct OptMergeWorker initvals.set_init(other_sig, init); } } - log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); + log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type, cell->name, module->name); module->remove(cell); total_count++; } diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 7522d716e..1a68776ff 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -109,13 +109,43 @@ struct CutpointPass : public Pass { SigMap sigmap(module); pool cutpoint_bits; + pool wire_drivers; + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + if (cell->output(conn.first) && !cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + if (bit.wire) + wire_drivers.insert(bit); + + for (auto wire : module->wires()) + if (wire->port_input) + for (auto bit : sigmap(wire)) + wire_drivers.insert(bit); + for (auto cell : module->selected_cells()) { if (cell->type == ID($anyseq)) continue; log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell)); for (auto &conn : cell->connections()) { - if (cell->output(conn.first)) - module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second))); + if (cell->output(conn.first)) { + bool do_cut = true; + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + if (wire_drivers.count(bit)) { + log_debug(" Treating inout port '%s' as input.\n", id2cstr(conn.first)); + do_cut = false; + break; + } + + if (do_cut) { + module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second))); + if (cell->input(conn.first)) { + log_debug(" Treating inout port '%s' as output.\n", id2cstr(conn.first)); + for (auto bit : sigmap(conn.second)) + wire_drivers.insert(bit); + } + } + } } RTLIL::Cell *scopeinfo = nullptr; diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index ac723fdbb..4449065f8 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -181,8 +181,10 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe for (std::string dont_use_cell : dont_use_cells) { dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } + bool first_lib = true; for (std::string liberty_file : liberty_files) { - abc9_script += stringf("read_lib %s -w \"%s\" ; ", dont_use_args, liberty_file); + abc9_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); + first_lib = false; } if (!constr_file.empty()) abc9_script += stringf("read_constr -v \"%s\"; ", constr_file); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index ecba519bf..2e762d7b9 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1600,7 +1600,6 @@ static void replace_zbufs(Design *design) sig[i] = w; } } - log("XXX %s -> %s\n", log_signal(cell->getPort(ID::A)), log_signal(sig)); cell->setPort(ID::A, sig); } diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index 132b47725..27426955a 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -85,7 +85,7 @@ static std::pair, std::optional> continue; } - log_debug("maybe valid icg: %s\n", cell_name.c_str()); + log_debug("maybe valid icg: %s\n", cell_name); ClockGateCell icg_interface; icg_interface.name = RTLIL::escape_id(cell_name); @@ -162,9 +162,9 @@ static std::pair, std::optional> winning = cost < goal; if (winning) - log_debug("%s beats %s\n", icg_interface.name.c_str(), icg_to_beat->name.c_str()); + log_debug("%s beats %s\n", icg_interface.name, icg_to_beat->name); } else { - log_debug("%s is the first of its polarity\n", icg_interface.name.c_str()); + log_debug("%s is the first of its polarity\n", icg_interface.name); winning = true; } if (winning) { @@ -396,7 +396,7 @@ struct ClockgatePass : public Pass { if (!it->second.new_net) continue; - log_debug("Fix up FF %s\n", cell->name.c_str()); + log_debug("Fix up FF %s\n", cell->name); // Now we start messing with the design ff.has_ce = false; // Construct the clock gate diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 062a63ec3..f3b96aeec 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -117,11 +117,11 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std // the next_state variable isn't just a pin name; perhaps this is an enable? auto helper = LibertyExpression::Lexer(expr); auto tree = LibertyExpression::parse(helper); - // log_debug("liberty expression:\n%s\n", tree.str().c_str()); + // log_debug("liberty expression:\n%s\n", tree.str()); if (tree.kind == LibertyExpression::Kind::EMPTY) { if (!warned_cells.count(cell_name)) { - log_debug("Invalid expression '%s' in next_state attribute of cell '%s' - skipping.\n", expr.c_str(), cell_name.c_str()); + log_debug("Invalid expression '%s' in next_state attribute of cell '%s' - skipping.\n", expr, cell_name); warned_cells.insert(cell_name); } return false; @@ -140,7 +140,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std // position that gives better diagnostics here. if (!pin_names.count(ff_output)) { if (!warned_cells.count(cell_name)) { - log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not contain ff output '%s' - skipping.\n", expr.c_str(), cell_name.c_str(), ff_output.c_str()); + log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not contain ff output '%s' - skipping.\n", expr, cell_name, ff_output); warned_cells.insert(cell_name); } return false; @@ -189,7 +189,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std } if (!warned_cells.count(cell_name)) { - log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not evaluate to an enable flop - skipping.\n", expr.c_str(), cell_name.c_str()); + log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not evaluate to an enable flop - skipping.\n", expr, cell_name); warned_cells.insert(cell_name); } return false; @@ -225,10 +225,10 @@ static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::strin For now, we'll simply produce a warning to let the user know something is up. */ if (pin_name.find_first_of("^*|&") == std::string::npos) { - log_debug("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str()); + log_debug("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name, cell->args[0]); } else { - log_debug("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str()); + log_debug("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name, cell->args[0]); } return false; diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 38ddb4516..224ef37b3 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -27,6 +27,14 @@ USING_YOSYS_NAMESPACE YOSYS_NAMESPACE_BEGIN +static void transfer_attr (Cell* to, const Cell* from, const IdString& attr) { + if (from->has_attribute(attr)) + to->attributes[attr] = from->attributes.at(attr); +} +static void transfer_src (Cell* to, const Cell* from) { + transfer_attr(to, from, ID::src); +} + void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort(ID::A); @@ -261,21 +269,21 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell) bool is_ne = cell->type.in(ID($ne), ID($nex)); RTLIL::SigSpec xor_out = module->addWire(NEW_ID2_SUFFIX("xor"), max(GetSize(sig_a), GetSize(sig_b))); // SILIMATE: Improve the naming - RTLIL::Cell *xor_cell = module->addXor(NEW_ID2, sig_a, sig_b, xor_out, is_signed, cell->get_src_attribute()); // SILIMATE: Improve the naming + RTLIL::Cell *xor_cell = module->addXor(NEW_ID2, sig_a, sig_b, xor_out, is_signed); // SILIMATE: Improve the naming xor_cell->attributes = cell->attributes; simplemap_bitop(module, xor_cell); module->remove(xor_cell); RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID2_SUFFIX("reduce_out")); // SILIMATE: Improve the naming - RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID2_SUFFIX("reduce_or"), xor_out, reduce_out, false, cell->get_src_attribute()); // SILIMATE: Improve the naming + RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID2_SUFFIX("reduce_or"), xor_out, reduce_out, false); // SILIMATE: Improve the naming reduce_cell->attributes = cell->attributes; simplemap_reduce(module, reduce_cell); module->remove(reduce_cell); if (!is_ne) { - RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID2_SUFFIX("not"), reduce_out, sig_y, false, cell->get_src_attribute()); // SILIMATE: Improve the naming + RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID2_SUFFIX("not"), reduce_out, sig_y, false); // SILIMATE: Improve the naming not_cell->attributes = cell->attributes; - simplemap_lognot(module, not_cell); + simplemap_lognot(module, not_cell); module->remove(not_cell); } } diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index a03bfe7c6..413413ffd 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -592,7 +592,7 @@ struct TechmapWorker log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); + log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); } else { @@ -601,7 +601,7 @@ struct TechmapWorker log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str()); + log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), extmapper_name); if (extmapper_name == "simplemap") { if (simplemap_mappers.count(cell->type) == 0) @@ -953,7 +953,7 @@ struct TechmapWorker module_queue.insert(m); } - log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name)); + log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(m_name)); cell->type = m_name; cell->parameters.clear(); } @@ -964,7 +964,7 @@ struct TechmapWorker log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); + log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); techmap_module_worker(design, module, cell, tpl); cell = nullptr; } @@ -1295,7 +1295,7 @@ struct TechmapPass : public Pass { std::string maps = ""; for (auto &map : i.second) maps += stringf(" %s", log_id(map)); - log_debug(" %s:%s\n", log_id(i.first), maps.c_str()); + log_debug(" %s:%s\n", log_id(i.first), maps); } log_debug("\n"); diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 9603956a8..73af155bd 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -1185,7 +1185,7 @@ struct TestCellPass : public Pass { // Expected to run once int num_cells_estimate = costs.get(uut); if (num_cells <= num_cells_estimate) { - log_debug("Correct upper bound for %s: %d <= %d\n", cell_type.c_str(), num_cells, num_cells_estimate); + log_debug("Correct upper bound for %s: %d <= %d\n", cell_type, num_cells, num_cells_estimate); } else { failed++; if (worst_abs < num_cells - num_cells_estimate) { diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 7a9ad7693..c3364e628 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -283,9 +283,16 @@ module _90_alu (A, B, CI, BI, X, Y, CO); \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO)); + (* force_downto *) + wire [Y_WIDTH-1:0] P; + wire [Y_WIDTH-1:0] G; + wire [Y_WIDTH-1:0] Cnull; + assign Cnull = 1'b0; - assign X = AA ^ BB; + \$fa #(.WIDTH(Y_WIDTH)) fa (.A(AA), .B(BB), .C(Cnull), .X(G), .Y(P)); + \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(CO)); + + assign X = P; assign Y = X ^ {CO, CI}; endmodule diff --git a/techlibs/quicklogic/ql_ioff.cc b/techlibs/quicklogic/ql_ioff.cc index 87b62e855..5574ef4a0 100644 --- a/techlibs/quicklogic/ql_ioff.cc +++ b/techlibs/quicklogic/ql_ioff.cc @@ -42,7 +42,7 @@ struct QlIoffPass : public Pass { for (auto cell : module->selected_cells()) { if (cell->type.in(ID(dffsre), ID(sdffsre))) { - log_debug("Checking cell %s.\n", cell->name.c_str()); + log_debug("Checking cell %s.\n", cell->name); bool e_const = cell->getPort(ID::E).is_fully_ones(); bool r_const = cell->getPort(ID::R).is_fully_ones(); bool s_const = cell->getPort(ID::S).is_fully_ones(); @@ -55,7 +55,7 @@ struct QlIoffPass : public Pass { SigSpec d = cell->getPort(ID::D); log_assert(GetSize(d) == 1); if (modwalker.has_inputs(d)) { - log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str()); + log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name); // check that d_sig has no other consumers pool portbits; modwalker.get_consumers(portbits, d); @@ -70,7 +70,7 @@ struct QlIoffPass : public Pass { SigSpec q = cell->getPort(ID::Q); log_assert(GetSize(q) == 1); if (modwalker.has_outputs(q) && !modwalker.has_consumers(q)) { - log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str()); + log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name); for (SigBit bit : output_bit_aliases[modwalker.sigmap(q)]) { log_assert(bit.is_wire()); output_ffs[bit.wire][bit.offset] = cell; diff --git a/tests/arch/gowin/mux.ys b/tests/arch/gowin/mux.ys index d5978f4ea..2ca973520 100644 --- a/tests/arch/gowin/mux.ys +++ b/tests/arch/gowin/mux.ys @@ -32,8 +32,8 @@ proc equiv_opt -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 1 t:LUT1 -select -assert-count 10 t:LUT3 +select -assert-count 3 t:LUT1 +select -assert-count 2 t:LUT3 select -assert-count 1 t:LUT4 select -assert-count 5 t:MUX2_LUT5 select -assert-count 2 t:MUX2_LUT6 diff --git a/tests/opt/README.md b/tests/opt/README.md deleted file mode 100644 index a63e16405..000000000 --- a/tests/opt/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Opt tests - -## Disabled - -- `opt_lut`: we do not support `abc9` diff --git a/tests/opt/opt_lut.ys.DISABLED b/tests/opt/opt_lut.ys similarity index 100% rename from tests/opt/opt_lut.ys.DISABLED rename to tests/opt/opt_lut.ys diff --git a/tests/unit/Makefile b/tests/unit/Makefile index 48635eb0d..eee60ef9f 100644 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile @@ -1,11 +1,27 @@ -GTESTFLAG := -lgtest -lgtest_main -RPATH := -Wl,-rpath -EXTRAFLAGS := -lyosys -pthreads +UNAME_S := $(shell uname -s) + +# GoogleTest flags +GTEST_PREFIX := $(shell brew --prefix googletest 2>/dev/null) +ifeq ($(GTEST_PREFIX),) + GTEST_CXXFLAGS := + GTEST_LDFLAGS := -lgtest -lgtest_main +else + GTEST_CXXFLAGS := -I$(GTEST_PREFIX)/include + GTEST_LDFLAGS := -L$(GTEST_PREFIX)/lib -lgtest -lgtest_main +endif + +ifeq ($(UNAME_S),Darwin) + RPATH = -Wl,-rpath,$(ROOTPATH) +else + RPATH = -Wl,-rpath=$(ROOTPATH) +endif + +EXTRAFLAGS := -lyosys -pthread OBJTEST := objtest BINTEST := bintest -ALLTESTFILE := $(shell find -name '*Test.cc' -printf '%P ') +ALLTESTFILE := $(shell find . -name '*Test.cc' | sed 's|^\./||' | tr '\n' ' ') TESTDIRS := $(sort $(dir $(ALLTESTFILE))) TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o))) @@ -15,16 +31,26 @@ TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o))) all: prepare $(TESTS) run-tests $(BINTEST)/%: $(OBJTEST)/%.o - $(CXX) -L$(ROOTPATH) $(RPATH)=$(ROOTPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \ - $(GTESTFLAG) $(EXTRAFLAGS) + $(CXX) -L$(ROOTPATH) $(RPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \ + $(GTEST_LDFLAGS) $(EXTRAFLAGS) $(OBJTEST)/%.o: $(basename $(subst $(OBJTEST),.,%)).cc - $(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $^ + $(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $(GTEST_CXXFLAGS) $^ .PHONY: prepare run-tests clean run-tests: $(TESTS) - $(subst Test ,Test&& ,$^) +ifeq ($(UNAME_S),Darwin) + @for t in $^; do \ + echo "Running $$t"; \ + DYLD_LIBRARY_PATH=$(ROOTPATH) $$t || exit 1; \ + done +else + @for t in $^; do \ + echo "Running $$t"; \ + $$t || exit 1; \ + done +endif prepare: mkdir -p $(addprefix $(BINTEST)/,$(TESTDIRS)) diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 97cc936de..557355ed9 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -20,6 +20,9 @@ namespace RTLIL { KernelRtlilTest() { if (log_files.empty()) log_files.emplace_back(stdout); } + virtual void SetUp() override { + IdString::ensure_prepopulated(); + } }; TEST_F(KernelRtlilTest, ConstAssignCompare) diff --git a/tests/various/README.md b/tests/various/README.md deleted file mode 100644 index 7320f697a..000000000 --- a/tests/various/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Various tests - -## Disabled - -- `abc9`: we do not support `abc9` -- `check`: we do not support memory initialization -- `ice40_mince_abc9`: we do not support `abc9` -- `plugin`: we do not support plugins - -## FIXME - -- `cutpoint_blackbox`: unknown issue, needs to be looked into diff --git a/tests/various/abc9.ys.DISABLED b/tests/various/abc9.ys similarity index 100% rename from tests/various/abc9.ys.DISABLED rename to tests/various/abc9.ys diff --git a/tests/various/autoname.ys b/tests/various/autoname.ys index f12fb7995..7df1571b2 100644 --- a/tests/various/autoname.ys +++ b/tests/various/autoname.ys @@ -1,10 +1,11 @@ +# prefer output name +design -reset read_rtlil <