From 750d536bbab93acd090bfce8453ae4d739a7e90d Mon Sep 17 00:00:00 2001 From: Tianji Liu Date: Wed, 4 Mar 2026 11:24:24 +0800 Subject: [PATCH 001/176] abc: new option to pass ABC read_lib args --- passes/techmap/abc.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 6e5b1fba8..3bc97b770 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -125,6 +125,7 @@ struct AbcConfig std::vector liberty_files; std::vector genlib_files; std::string constr_file; + std::string abc_liberty_args; vector lut_costs; std::string delay_target; std::string sop_inputs; @@ -1024,7 +1025,7 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module } bool first_lib = true; for (std::string liberty_file : config.liberty_files) { - abc_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); + abc_script += stringf("read_lib %s %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", config.abc_liberty_args, liberty_file); first_lib = false; } for (std::string liberty_file : config.genlib_files) @@ -2026,6 +2027,10 @@ struct AbcPass : public Pass { log(" preserve naming by an equivalence check between the original and\n"); log(" post-ABC netlists (experimental).\n"); log("\n"); + log(" -liberty_args \n"); + log(" when -liberty is used, also pass the specified arguments to ABC\n"); + log(" command \"read_lib\". Example: -liberty_args \"-G 250\"\n"); + log("\n"); log("When no target cell library is specified the Yosys standard cell library is\n"); log("loaded into ABC before the ABC script is executed.\n"); log("\n"); @@ -2217,6 +2222,14 @@ struct AbcPass : public Pass { config.markgroups = true; continue; } + if (arg == "-liberty_args" && argidx+1 < args.size()) { + config.abc_liberty_args = args[++argidx]; + if (!config.abc_liberty_args.empty()) { + if (config.abc_liberty_args[0] == '\"' && config.abc_liberty_args.back() == '\"') + config.abc_liberty_args = config.abc_liberty_args.substr(1, config.abc_liberty_args.size() - 2); + } + continue; + } break; } extra_args(args, argidx, design); From cdf549a49372f9a65be2df360e86cbccf9f95db3 Mon Sep 17 00:00:00 2001 From: Noah Van Dijk Date: Thu, 2 Apr 2026 10:23:13 -0500 Subject: [PATCH 002/176] Fix typos in GettingStarted Line 8: is a the > is the line 88: all this types > all these types --- guidelines/GettingStarted | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guidelines/GettingStarted b/guidelines/GettingStarted index 17fe32523..ea15df93f 100644 --- a/guidelines/GettingStarted +++ b/guidelines/GettingStarted @@ -5,7 +5,7 @@ Getting Started Outline of a Yosys command -------------------------- -Here is a the C++ code for a "hello_world" Yosys command (hello.cc): +Here is the C++ code for a "hello_world" Yosys command (hello.cc): #include "kernel/yosys.h" @@ -85,7 +85,7 @@ the declarations for the following types in kernel/rtlil.h: The module is a container with connected cells and wires in it. The design is a container with modules in it. -All this types are also available without the RTLIL:: prefix in the Yosys +All these types are also available without the RTLIL:: prefix in the Yosys namespace. 4. SigMap and other Helper Classes @@ -204,4 +204,4 @@ Notes on the existing codebase For historical reasons not all parts of Yosys adhere to the current coding style. When adding code to existing parts of the system, adhere to this guide -for the new code instead of trying to mimic the style of the surrounding code. \ No newline at end of file +for the new code instead of trying to mimic the style of the surrounding code. From 52243e10fb0187357614b6060c1ce0a45f5e0fa6 Mon Sep 17 00:00:00 2001 From: Noah Van Dijk Date: Thu, 2 Apr 2026 10:24:31 -0500 Subject: [PATCH 003/176] Fix typo in pmgen/README.md Line 161: calulated > calculated --- passes/pmgen/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 15569ebfc..542c2c0e8 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -158,7 +158,7 @@ in `select` lines. Index lines are using the `index expr1 === expr2` syntax. `expr1` is evaluated during matcher initialization and the same restrictions apply as for -`select` expressions. `expr2` is evaluated when the match is calulated. It is a +`select` expressions. `expr2` is evaluated when the match is calculated. It is a function of any state variables assigned to by previous blocks. Both expression are converted to the given type and compared for equality. Only cells for which all `index` statements in the block pass are considered by the match. From d75d513402e226ca80f4c5fd818584f28614fb37 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 16:50:37 +0100 Subject: [PATCH 004/176] contributing: reformulate HQ GmbH involvement --- .../yosys_internals/extending_yosys/contributing.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 458d7dc36..f2ee144c5 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -317,10 +317,12 @@ Reviewing PRs is a totally valid form of external contributing to the project! Who's the reviewer? ~~~~~~~~~~~~~~~~~~~ -Yosys HQ is a company with the inherited mandate to make decisions on behalf -of the open source project. As such, we at HQ are collectively the maintainers. -Within HQ, we allocate reviews based on expertise with the topic at hand -as well as member time constraints. +Yosys HQ GmbH is a company with a mandate to make decisions for the good +of Yosys HQ open source software. It was co-founded by Claire Xenia Wolf, +the original author of Yosys. +Within it, we allocate reviews based on expertise with the topic at hand +as well as member time constraints. However, decisions including reviews +are also contributed by people external to the company. If you're intimately acquainted with a part of the codebase, we will be happy to defer to your experience and have you review PRs. The official way we like From 8bf42c01ce3fed465af25039888a9fbf5eb5aa1b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 16:52:09 +0100 Subject: [PATCH 005/176] contributing: finish cut off sentence --- docs/source/yosys_internals/extending_yosys/contributing.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index f2ee144c5..c9d4c43e5 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -341,7 +341,8 @@ and stop being responsive, in the future, we might decide to remove such code if convenient and costly to maintain. It's simply more respectful of the users' time to explicitly cut something out than let it "bitrot". Larger projects like LLVM or linux could not survive without such things, but Yosys is far smaller, -and there are expectations +and there are implicit expectations of stability we aim to +relatively respect. .. TODO this deserves its own section elsewhere I think? But it would be distracting elsewhere From 342b0e5fc17f79f03b11c2da887ebeb05c807e9a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 16:56:02 +0100 Subject: [PATCH 006/176] contributing: require bug report inputs to pass check --- docs/source/yosys_internals/extending_yosys/contributing.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index c9d4c43e5..74cab2650 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -27,6 +27,8 @@ The reproduction steps should be a minimal, complete and verifiable example `MVCE`_. Providing an MVCE with your bug report drastically increases the likelihood that someone will be able to help resolve your issue. +Make sure that your report input is free of any problems as reported by the +`check_` command. One way to minimize a design is to use the `bugpoint_` command. You can learn more in the `how-to guide for bugpoint_`. @@ -86,6 +88,7 @@ Don't forget to mention: .. _MVCE: https://stackoverflow.com/help/minimal-reproducible-example .. _bugpoint: https://yosys.readthedocs.io/en/latest/cmd/bugpoint.html +.. _check: https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/index_passes_status.html#check-check-for-obvious-problems-in-the-design .. _how-to guide for bugpoint: https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html Expected Behaviour From d6518f1b9a552ecf1559c70d2eb2bac6222052be Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 16:59:21 +0100 Subject: [PATCH 007/176] contributing: fix links --- .../source/yosys_internals/extending_yosys/contributing.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 74cab2650..7fcbbc011 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -28,9 +28,9 @@ example `MVCE`_. Providing an MVCE with your bug report drastically increases the likelihood that someone will be able to help resolve your issue. Make sure that your report input is free of any problems as reported by the -`check_` command. -One way to minimize a design is to use the `bugpoint_` command. -You can learn more in the `how-to guide for bugpoint_`. +`check`_ command. +One way to minimize a design is to use the `bugpoint`_ command. +You can learn more in the `how-to guide for bugpoint`_. The reproduction steps are ideally a code-block (starting and ending with triple backquotes) containing From 9385928bc231d2c683efcf1a5426352ed9401705 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 17:00:14 +0100 Subject: [PATCH 008/176] contributing: Yosys HQ -> YosysHQ --- docs/source/yosys_internals/extending_yosys/contributing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 7fcbbc011..9ef86edd9 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -320,8 +320,8 @@ Reviewing PRs is a totally valid form of external contributing to the project! Who's the reviewer? ~~~~~~~~~~~~~~~~~~~ -Yosys HQ GmbH is a company with a mandate to make decisions for the good -of Yosys HQ open source software. It was co-founded by Claire Xenia Wolf, +YosysHQ GmbH is a company with a mandate to make decisions for the good +of YosysHQ open source software. It was co-founded by Claire Xenia Wolf, the original author of Yosys. Within it, we allocate reviews based on expertise with the topic at hand as well as member time constraints. However, decisions including reviews From 2572b1e3dfb7410754f76323bd09b9b3e1f91021 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 17:17:25 +0100 Subject: [PATCH 009/176] .github: fix label for links --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 2c1483345..2ed92c913 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -6,7 +6,7 @@ body: attributes: value: > - Learn more [here](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) about how to report bugs. We fix well-reported bugs the fastest. + Learn more in our [Reporting bugs](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) docs section. We fix well-reported bugs the fastest. If you have a general question, please ask it on the [Discourse forum](https://yosyshq.discourse.group/). From cc3827c80c812401a71c538020a3ea1efecfeb7d Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 26 Jan 2026 19:53:38 +0100 Subject: [PATCH 010/176] docs: consolidate contributing.md into contributing.rst harder --- CONTRIBUTING.md | 60 ++----------------- .../extending_yosys/contributing.rst | 39 ++++++++++-- 2 files changed, 40 insertions(+), 59 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6eadbec31..ab698b6ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,59 +5,11 @@ first time contributing to an open source project, please take a look at the following guide about the basics: https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project. -## Asking questions +Check out our [Contributing guidelines](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html) to learn the best ways to -If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/). -The Discourse is also a great place to ask questions about developing or -contributing to Yosys. ++ get help ++ report bugs ++ contribute code ++ review code -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. - -## Using the issue tracker - -The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for -tracking bugs or other problems with Yosys or its documentation. It is also the -place to go for requesting new features. - -### Bug reports - -Learn more [here](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) about how to report bugs. We fix well-reported bugs the fastest. - -## Contributing code - -If you're adding complex functionality, or modifying core parts of Yosys, -we highly recommend discussing your motivation and approach -ahead of time on the [Discourse forum](https://yosyshq.discourse.group/). - -### Using pull requests - -If you are working on something to add to Yosys, or fix something that isn't -working quite right, -make a [pull request (PR)](https://github.com/YosysHQ/yosys/pulls). - -An open PR, even as a draft, tells everyone that you're working on it and they -don't have to. It can also be a useful way to solicit feedback on in-progress -changes. See above to find the best way to [ask us questions](#asking-questions). - -### Continuous integration - -[Continuous Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools -automatically compile Yosys and run it with the full suite of tests. -If you're a first time contributor, a maintainer has to trigger a run for you. -We test on various platforms, compilers. Sanitizer builds are only tested -on the main branch. - -### Labels - -We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise -issues and PRs. If a label seems relevant to your work, please do add it; this -also includes the labels beginning with 'status-'. The 'merge-' labels are used -by maintainers for tracking and communicating which PRs are ready and pending -merge; please do not use these labels if you are not a maintainer. - - -### Coding style - -Learn more [here](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html). +If you're reading this file offline and don't have internet access, you can read the `contributing.rst` file [locally](docs/source/yosys_internals/extending_yosys/contributing.rst). diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 9ef86edd9..c19ef71da 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -4,8 +4,10 @@ Contributing to Yosys Reporting bugs -------------- -A good bug report includes the following information: +We fix well-reported bugs the fastest. A good bug report is an issue on the `issue tracker`_ +and includes the following information: +.. _`issue tracker`: https://github.com/YosysHQ/yosys/issues Title ~~~~~ @@ -28,9 +30,9 @@ example `MVCE`_. Providing an MVCE with your bug report drastically increases the likelihood that someone will be able to help resolve your issue. Make sure that your report input is free of any problems as reported by the -`check`_ command. -One way to minimize a design is to use the `bugpoint`_ command. -You can learn more in the `how-to guide for bugpoint`_. +`check` command. +One way to minimize a design is to use the `bugpoint` command. +You can learn more in the :doc:`how-to guide for bugpoint `. The reproduction steps are ideally a code-block (starting and ending with triple backquotes) containing @@ -87,7 +89,6 @@ Don't forget to mention: reproduction steps to just the Yosys part. .. _MVCE: https://stackoverflow.com/help/minimal-reproducible-example -.. _bugpoint: https://yosys.readthedocs.io/en/latest/cmd/bugpoint.html .. _check: https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/index_passes_status.html#check-check-for-obvious-problems-in-the-design .. _how-to guide for bugpoint: https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html @@ -179,6 +180,12 @@ based on their descriptions first, code second. Before you build or fix something, also search for existing `issues`_. +We have open `developer 'jour fixe' (Dev JF) meetings`_ +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. + +.. _`developer 'jour fixe' (Dev JF) meetings`: https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing .. _`Discourse forum`: https://yosyshq.discourse.group/ .. _`issues`: https://github.com/YosysHQ/yosys/issues @@ -300,6 +307,26 @@ Otherwise stick to the `Linux Kernel Coding Style`_. .. _Linux Kernel Coding Style: https://www.kernel.org/doc/Documentation/process/coding-style.rst +Pull requests (PRs) +~~~~~~~~~~~~~~~~~~~ + +If you are working on something to add to Yosys, or fix something that isn't +working quite right, +make a `pull request (PR)`_. + +An open PR, even as a draft, tells everyone that you're working on it and they +don't have to. It can also be a useful way to solicit feedback on in-progress +changes. + +We use `labels`_ to help categorise +issues and PRs. If a label seems relevant to your work, please do add it; this +also includes the labels beginning with 'status-'. The 'merge-' labels are used +by maintainers for tracking and communicating which PRs are ready and pending +merge; please do not use these labels if you are not a maintainer. + +.. _`pull request (PR)`: https://github.com/YosysHQ/yosys/pulls +.. _`labels`: https://github.com/YosysHQ/yosys/labels + Git style ~~~~~~~~~ @@ -381,3 +408,5 @@ they just are good enough to merge as-is. The CI is required to go green for merging. New contributors need a CI run to be triggered by a maintainer before their PRs take up computing resources. It's a single click from the github web interface. +We test on various platforms, compilers. Sanitizer builds are only tested +on the main branch. From 9b9e334c79ff668450cd93c69c9c9fe5d47e1e3a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 28 Jan 2026 11:47:19 +0100 Subject: [PATCH 011/176] contributing: small responses to feedback --- CONTRIBUTING.md | 2 +- .../yosys_internals/extending_yosys/contributing.rst | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab698b6ec..849d1fb00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,4 +12,4 @@ Check out our [Contributing guidelines](https://yosys.readthedocs.io/en/latest/y + contribute code + review code -If you're reading this file offline and don't have internet access, you can read the `contributing.rst` file [locally](docs/source/yosys_internals/extending_yosys/contributing.rst). +If you're reading this file offline and don't have internet access, you can [read the contributing.rst file locally](docs/source/yosys_internals/extending_yosys/contributing.rst). diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index c19ef71da..1ff77a1fd 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -89,7 +89,6 @@ Don't forget to mention: reproduction steps to just the Yosys part. .. _MVCE: https://stackoverflow.com/help/minimal-reproducible-example -.. _check: https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/index_passes_status.html#check-check-for-obvious-problems-in-the-design .. _how-to guide for bugpoint: https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html Expected Behaviour @@ -372,7 +371,7 @@ if convenient and costly to maintain. It's simply more respectful of the users' time to explicitly cut something out than let it "bitrot". Larger projects like LLVM or linux could not survive without such things, but Yosys is far smaller, and there are implicit expectations of stability we aim to -relatively respect. +respect within reason. .. TODO this deserves its own section elsewhere I think? But it would be distracting elsewhere @@ -408,5 +407,5 @@ they just are good enough to merge as-is. The CI is required to go green for merging. New contributors need a CI run to be triggered by a maintainer before their PRs take up computing resources. It's a single click from the github web interface. -We test on various platforms, compilers. Sanitizer builds are only tested -on the main branch. +We test on various platforms and compilers. Sanitizer builds are only +tested on the main branch. From f09afcf581bd55f7950b13ebde5ada07bb774cb2 Mon Sep 17 00:00:00 2001 From: Lofty Date: Wed, 8 Apr 2026 11:08:44 +0100 Subject: [PATCH 012/176] write_xaiger2: further cleanup --- backends/aiger2/aiger.cc | 125 ++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 53 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 96e1fe75f..2f28869d9 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -21,6 +21,9 @@ // - gracefully handling inout ports (an error message probably) // - undriven wires // - zero-width operands +// - decide how to unify this with cellaigs +// - break up Index into something smaller +// - (C++20) remove snprintf-into-std::ostream weirdness #include "kernel/register.h" #include "kernel/newcelltypes.h" @@ -179,6 +182,9 @@ struct Index { } else { // AigMaker::node2index + // In XAIGER, the ordering of inputs is used to distinguish between AND + // and XOR gates. AND gates have their first input literal be larger + // than their second, and vice-versa for XORs. if (a < b) std::swap(a, b); auto pair = std::make_pair(a, b); @@ -531,7 +537,7 @@ struct Index { Design *design = index.design; auto &minfo = leaf_minfo(index); if (!minfo.suboffsets.count(cell)) - log_error("Reached unsupport cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module)); + log_error("Reached unsupported cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module)); Module *def = design->module(cell->type); log_assert(def); levels.push_back(Level(index.modules.at(def), cell)); @@ -550,13 +556,13 @@ struct Index { { std::string ret; bool first = true; - for (auto pair : levels) { + for (auto [minfo, cell] : levels) { if (!first) ret += "."; - if (!pair.second) - ret += RTLIL::unescape_id(pair.first.module->name); + if (!cell) + ret += RTLIL::unescape_id(minfo.module->name); else - ret += RTLIL::unescape_id(pair.second->name); + ret += RTLIL::unescape_id(cell->name); first = false; } return ret; @@ -565,8 +571,8 @@ struct Index { int hash() const { int hash = 0; - for (auto pair : levels) - hash += (uintptr_t) pair.second; + for (auto [_, cell] : levels) + hash += (uintptr_t) cell; return hash; } @@ -575,9 +581,12 @@ struct Index { if (levels.size() != other.levels.size()) return false; - for (int i = 0; i < levels.size(); i++) - if (levels[i].second != other.levels[i].second) + for (int i = 0; i < levels.size(); i++) { + auto* cell = levels[i].second; + auto* other_cell = other.levels[i].second; + if (cell != other_cell) return false; + } return true; } @@ -740,6 +749,9 @@ struct AigerWriter : Index { nands++; lit_counter += 2; + // In XAIGER, the ordering of inputs is used to distinguish between AND + // and XOR gates. AND gates have their first input literal be larger + // than their second, and vice-versa for XORs. if (a < b) std::swap(a, b); encode(out - a); encode(a - b); @@ -756,7 +768,7 @@ struct AigerWriter : Index { log_assert(lit_counter == (Lit) (ninputs + nlatches + nands) * 2 + 2); char buf[128]; - snprintf(buf, sizeof(buf) - 1, "aig %08d %08d %08d %08d %08d\n", + snprintf(buf, sizeof(buf), "aig %08d %08d %08d %08d %08d\n", ninputs + nlatches + nands, ninputs, nlatches, noutputs, nands); f->write(buf, strlen(buf)); } @@ -773,8 +785,9 @@ struct AigerWriter : Index { log_assert(w); if (w->port_input && !w->port_output) for (int i = 0; i < w->width; i++) { - pi_literal(SigBit(w, i)) = lit_counter; - inputs.push_back(SigBit(w, i)); + auto bit = SigBit(w, i); + pi_literal(bit) = lit_counter; + inputs.push_back(bit); lit_counter += 2; ninputs++; } @@ -791,7 +804,7 @@ struct AigerWriter : Index { for (auto bit : SigSpec(w)) { (void) bit; char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", 0); + snprintf(buf, sizeof(buf), "%08d\n", 0); f->write(buf, strlen(buf)); noutputs++; } @@ -804,16 +817,19 @@ struct AigerWriter : Index { for (auto w : top->wires()) if (w->port_output) { for (auto bit : SigSpec(w)) + // Each call to eval_po eventually reaches emit_gate and + // encode which writes to f. outputs.push_back({bit, eval_po(bit)}); } + auto data_end = f->tellp(); // revisit header and the list of outputs f->seekp(file_start); write_header(); - for (auto pair : outputs) { + for (auto [_, po] : outputs) { char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", pair.second); + snprintf(buf, sizeof(buf), "%08d\n", po); f->write(buf, strlen(buf)); } // double check we arrived at the same offset for the @@ -822,12 +838,13 @@ struct AigerWriter : Index { f->seekp(data_end); int i = 0; - for (auto pair : outputs) { - if (SigSpec(pair.first).is_wire()) { + for (auto [bit, _] : outputs) { + if (SigSpec(bit).is_wire()) { + // primary output symbol char buf[32]; - snprintf(buf, sizeof(buf) - 1, "o%d ", i); + snprintf(buf, sizeof(buf), "o%d ", i); f->write(buf, strlen(buf)); - std::string name = RTLIL::unescape_id(pair.first.wire->name); + std::string name = RTLIL::unescape_id(bit.wire->name); f->write(name.data(), name.size()); f->put('\n'); } @@ -836,8 +853,9 @@ struct AigerWriter : Index { i = 0; for (auto bit : inputs) { if (SigSpec(bit).is_wire()) { + // primary input symbol char buf[32]; - snprintf(buf, sizeof(buf) - 1, "i%d ", i); + snprintf(buf, sizeof(buf), "i%d ", i); f->write(buf, strlen(buf)); std::string name = RTLIL::unescape_id(bit.wire->name); f->write(name.data(), name.size()); @@ -1242,29 +1260,29 @@ struct XAigerWriter : AigerWriter { reset_counters(); for (auto w : top->wires()) - if (w->port_input && !w->port_output) - for (int i = 0; i < w->width; i++) - ensure_pi(SigBit(w, i)); + if (w->port_input && !w->port_output) + for (int i = 0; i < w->width; i++) + ensure_pi(SigBit(w, i)); int proper_po_num = 0; for (auto w : top->wires()) - if (w->port_output) - proper_po_num += w->width; + if (w->port_output) + proper_po_num += w->width; prep_boxes(proper_po_num); for (auto w : top->wires()) - if (w->port_output) - for (int i = 0; i < w->width; i++) { - // When a module output is directly driven by an opaque box, we - // don't emit it to the mapping file to aid re-integration, but we - // do emit a proper PO. - if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) { - map_file << "po " << proper_pos_counter << " " << i - << " " << w->name.c_str() << "\n"; - } - proper_pos_counter++; - pos.push_back(std::make_pair(SigBit(w, i), HierCursor{})); - } + if (w->port_output) + for (int i = 0; i < w->width; i++) { + // When a module output is directly driven by an opaque box, we + // don't emit it to the mapping file to aid re-integration, but we + // do emit a proper PO. + if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) { + map_file << "po " << proper_pos_counter << " " << i + << " " << w->name.c_str() << "\n"; + } + proper_pos_counter++; + pos.push_back(std::make_pair(SigBit(w, i), HierCursor{})); + } this->f = f; // start with the header @@ -1274,7 +1292,7 @@ struct XAigerWriter : AigerWriter { // insert padding where output literals will go (once known) for (auto _ : pos) { char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", 0); + snprintf(buf, sizeof(buf), "%08d\n", 0); f->write(buf, strlen(buf)); } auto data_start = f->tellp(); @@ -1291,35 +1309,36 @@ struct XAigerWriter : AigerWriter { write_header(); for (auto lit : outlits) { char buf[16]; - snprintf(buf, sizeof(buf) - 1, "%08d\n", lit); + snprintf(buf, sizeof(buf), "%08d\n", lit); f->write(buf, strlen(buf)); } // double check we arrived at the same offset for the // main data section log_assert(data_start == f->tellp()); - // extensions + // XAIGER extensions f->seekp(0, std::ios::end); - f->put('c'); + f->put('c'); // 'c': comment (marks beginning of extensions) // insert empty 'r' and 's' sections (abc crashes if we provide 'a' without those) - f->put('r'); - write_be32(*f, 4); - write_be32(*f, 0); - f->put('s'); - write_be32(*f, 4); - write_be32(*f, 0); + f->put('r'); // 'r': register classes + write_be32(*f, 4); // length in bytes + write_be32(*f, 0); // no register classes - f->put('h'); + f->put('s'); // 's': register initial values + write_be32(*f, 4); // length in bytes + write_be32(*f, 0); // no register initial values + + f->put('h'); // 'h': hierarchy information // TODO: get rid of std::string copy std::string h_buffer_str = h_buffer.str(); - write_be32(*f, h_buffer_str.size()); - f->write(h_buffer_str.data(), h_buffer_str.size()); + write_be32(*f, h_buffer_str.size()); // length in bytes + f->write(h_buffer_str.data(), h_buffer_str.size()); // data #if 1 - f->put('a'); - write_be32(*f, 0); // size to be filled later + f->put('a'); // 'a': additional AIG (used for holes) + write_be32(*f, 0); // length in bytes (to be filled later) auto holes_aiger_start = f->tellp(); { AigerWriter holes_writer; @@ -1331,7 +1350,7 @@ struct XAigerWriter : AigerWriter { auto holes_aiger_size = f->tellp() - holes_aiger_start; f->seekp(holes_aiger_start, std::ios::beg); f->seekp(-4, std::ios::cur); - write_be32(*f, holes_aiger_size); + write_be32(*f, holes_aiger_size); // length in bytes #endif f->seekp(0, std::ios::end); From 6d715784cdaf7088cc11939a2d6d942d43f6a175 Mon Sep 17 00:00:00 2001 From: Lofty Date: Wed, 8 Apr 2026 11:08:59 +0100 Subject: [PATCH 013/176] read_xaiger2: further cleanup --- frontends/aiger2/xaiger.cc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/frontends/aiger2/xaiger.cc b/frontends/aiger2/xaiger.cc index 510da0be8..bbec47861 100644 --- a/frontends/aiger2/xaiger.cc +++ b/frontends/aiger2/xaiger.cc @@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN uint32_t read_be32(std::istream &f) { return ((uint32_t) f.get() << 24) | - ((uint32_t) f.get() << 16) | + ((uint32_t) f.get() << 16) | ((uint32_t) f.get() << 8) | (uint32_t) f.get(); } @@ -80,9 +80,9 @@ struct Xaiger2Frontend : public Frontend { extra_args(f, filename, args, argidx, true); if (map_filename.empty()) - log_error("A '-map2' argument required\n"); + log_error("A '-map2' argument is required\n"); if (module_name.empty()) - log_error("A '-module_name' argument required\n"); + log_error("A '-module_name' argument is required\n"); Module *module = design->module(module_name); if (!module) @@ -128,10 +128,10 @@ struct Xaiger2Frontend : public Frontend { int woffset; std::string name; if (!(map_file >> pi_idx >> woffset >> name)) - log_error("Bad map file (1)\n"); + log_error("Bad map file: couldn't read 'pi' line\n"); int lit = (2 * pi_idx) + 2; if (lit < 0 || lit >= (int) bits.size()) - log_error("Bad map file (2)\n"); + log_error("Bad map file: primary input literal out of range\n"); Wire *w = module->wire(name); if (!w || woffset < 0 || woffset >= w->width) log_error("Map file references non-existent signal bit %s[%d]\n", @@ -141,9 +141,9 @@ struct Xaiger2Frontend : public Frontend { int box_seq; std::string name; if (!(map_file >> box_seq >> name)) - log_error("Bad map file (20)\n"); + log_error("Bad map file: couldn't read 'box' line\n"); if (box_seq < 0) - log_error("Bad map file (21)\n"); + log_error("Bad map file: box out of range\n"); Cell *box = module->cell(RTLIL::escape_id(name)); if (!box) @@ -158,7 +158,7 @@ struct Xaiger2Frontend : public Frontend { } if (!def) - log_error("Bad map file (22)\n"); + log_error("Bad map file: no module found for box type '%s'\n", log_id(box->type)); if (box_seq >= (int) boxes.size()) { boxes.resize(box_seq + 1); @@ -403,15 +403,15 @@ struct Xaiger2Frontend : public Frontend { int woffset; std::string name; if (!(map_file >> po_idx >> woffset >> name)) - log_error("Bad map file (3)\n"); + log_error("Bad map file: couldn't read 'po' line\n"); po_idx += co_counter; if (po_idx < 0 || po_idx >= (int) outputs.size()) - log_error("Bad map file (4)\n"); + log_error("Bad map file: primary output index out of range\n"); int lit = outputs[po_idx]; if (lit < 0 || lit >= (int) bits.size()) - log_error("Bad map file (5)\n"); + log_error("Bad map file: primary output literal out of range\n"); if (bits[lit] == RTLIL::Sm) - log_error("Bad map file (6)\n"); + log_error("Bad map file: primary output literal is a marker\n"); Wire *w = module->wire(name); if (!w || woffset < 0 || woffset >= w->width) log_error("Map file references non-existent signal bit %s[%d]\n", @@ -423,15 +423,15 @@ struct Xaiger2Frontend : public Frontend { std::string box_name; std::string box_port; if (!(map_file >> po_idx >> poffset >> box_name >> box_port)) - log_error("Bad map file (7)\n"); + log_error("Bad map file: couldn't read 'pseudopo' line\n"); po_idx += co_counter; if (po_idx < 0 || po_idx >= (int) outputs.size()) - log_error("Bad map file (8)\n"); + log_error("Bad map file: pseudo primary output index out of range\n"); int lit = outputs[po_idx]; if (lit < 0 || lit >= (int) bits.size()) - log_error("Bad map file (9)\n"); + log_error("Bad map file: pseudo primary output literal out of range\n"); if (bits[lit] == RTLIL::Sm) - log_error("Bad map file (10)\n"); + log_error("Bad map file: pseudo primary output literal is a marker\n"); Cell *cell = module->cell(box_name); if (!cell || !cell->hasPort(box_port)) log_error("Map file references non-existent box port %s/%s\n", From 1f6559a5cfa7aef26c0b09aa9d0c2982f4c567a5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 8 Apr 2026 21:56:36 +0000 Subject: [PATCH 014/176] Avoid racing accesses to shards[0] in ShardedHashtable parallel destruction --- kernel/threading.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/threading.h b/kernel/threading.h index a041def2c..0008f97bb 100644 --- a/kernel/threading.h +++ b/kernel/threading.h @@ -567,7 +567,7 @@ public: // Call this for each shard to implement parallel destruction. For very large `ShardedHashtable`s, // deleting all elements of all shards on a single thread can be a performance bottleneck. void clear(const ThreadIndex &shard) { - AccumulatedValueEquality equality = shards[0].key_eq(); + AccumulatedValueEquality equality = shards[shard.thread_num].key_eq(); shards[shard.thread_num] = Shard(0, AccumulatedValueHashOp(), equality); } private: From 46df888191b2866238a4d04fe8f3aa252621fdba Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 11 Mar 2026 11:31:40 +0100 Subject: [PATCH 015/176] impl csa tree. --- passes/opt/Makefile.inc | 1 + passes/opt/csa_tree.cc | 357 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 passes/opt/csa_tree.cc diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index e7b62fc6a..1d7833b31 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -23,6 +23,7 @@ OBJS += passes/opt/opt_ffinv.o OBJS += passes/opt/pmux2shiftx.o OBJS += passes/opt/muxpack.o OBJS += passes/opt/opt_balance_tree.o +OBJS += passes/opt/csa_tree.o OBJS += passes/opt/peepopt.o GENFILES += passes/opt/peepopt_pm.h diff --git a/passes/opt/csa_tree.cc b/passes/opt/csa_tree.cc new file mode 100644 index 000000000..2328af3d8 --- /dev/null +++ b/passes/opt/csa_tree.cc @@ -0,0 +1,357 @@ +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct CsaTreeWorker +{ + RTLIL::Module *module; + SigMap sigmap; + int min_operands; + + dict sig_to_driver; + dict cell_fanout; + pool consumed; + + int stat_trees = 0; + int stat_fa_cells = 0; + int stat_removed_cells = 0; + + CsaTreeWorker(RTLIL::Module *module, int min_operands) : + module(module), sigmap(module), min_operands(min_operands) {} + + void build_maps() + { + dict sig_consumers; + + for (auto cell : module->cells()) + { + if (cell->type.in(ID($add), ID($sub))) + { + RTLIL::SigSpec y = sigmap(cell->getPort(ID::Y)); + for (auto bit : y) + if (bit.wire != nullptr) + sig_to_driver[bit] = cell; + } + + for (auto &conn : cell->connections()) + { + if (cell->input(conn.first)) + { + for (auto bit : sigmap(conn.second)) + if (bit.wire != nullptr) + sig_consumers[bit]++; + } + } + } + + for (auto wire : module->wires()) + if (wire->port_output) + for (auto bit : sigmap(wire)) + if (bit.wire != nullptr) + sig_consumers[bit]++; + + for (auto cell : module->cells()) + { + if (!cell->type.in(ID($add), ID($sub))) + continue; + int fo = 0; + for (auto bit : sigmap(cell->getPort(ID::Y))) + if (bit.wire != nullptr) + fo = std::max(fo, sig_consumers.count(bit) ? sig_consumers.at(bit) : 0); + cell_fanout[cell] = fo; + } + } + + struct Operand { + RTLIL::SigSpec sig; + bool is_signed; + bool do_subtract; + }; + + bool can_absorb(RTLIL::Cell *cell) + { + if (cell == nullptr) + return false; + if (!cell->type.in(ID($add), ID($sub))) + return false; + if (consumed.count(cell)) + return false; + if (cell_fanout.count(cell) ? cell_fanout.at(cell) != 1 : true) + return false; + return true; + } + + RTLIL::Cell *get_driver(RTLIL::SigSpec sig) + { + sig = sigmap(sig); + if (sig.empty()) + return nullptr; + + RTLIL::Cell *driver = nullptr; + for (auto bit : sig) + { + if (bit.wire == nullptr) + continue; + auto it = sig_to_driver.find(bit); + if (it == sig_to_driver.end()) + return nullptr; + if (driver == nullptr) + driver = it->second; + else if (driver != it->second) + return nullptr; // mixed + } + return driver; + } + + void collect_operands( + RTLIL::Cell *cell, + bool negate, + std::vector &operands, + std::vector &tree_cells + ) { + tree_cells.push_back(cell); + consumed.insert(cell); + + bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); + bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); + bool is_sub = (cell->type == ID($sub)); + + RTLIL::SigSpec sig_a = cell->getPort(ID::A); + RTLIL::SigSpec sig_b = cell->getPort(ID::B); + + RTLIL::Cell *driver_a = get_driver(sig_a); + if (can_absorb(driver_a)) { + collect_operands(driver_a, negate, operands, tree_cells); + } else { + operands.push_back({sig_a, a_signed, negate}); + } + + bool b_negate = negate ^ is_sub; + RTLIL::Cell *driver_b = get_driver(sig_b); + if (can_absorb(driver_b)) { + collect_operands(driver_b, b_negate, operands, tree_cells); + } else { + operands.push_back({sig_b, b_signed, b_negate}); + } + } + + void create_fa( + RTLIL::SigSpec a, + RTLIL::SigSpec b, + RTLIL::SigSpec c, + int width, + RTLIL::SigSpec &sum_out, + RTLIL::SigSpec &carry_out + ) { + RTLIL::Wire *w_sum = module->addWire(NEW_ID, width); + RTLIL::Wire *w_carry = module->addWire(NEW_ID, width); + + RTLIL::Cell *fa = module->addCell(NEW_ID, ID($fa)); + fa->setParam(ID::WIDTH, width); + fa->setPort(ID::A, a); + fa->setPort(ID::B, b); + fa->setPort(ID::C, c); + fa->setPort(ID::Y, w_sum); + fa->setPort(ID::X, w_carry); + + sum_out = w_sum; + carry_out = w_carry; + stat_fa_cells++; + } + + RTLIL::SigSpec extend_to(RTLIL::SigSpec sig, bool is_signed, int target_width) + { + if (GetSize(sig) >= target_width) + return sig.extract(0, target_width); + + RTLIL::SigSpec result = sig; + RTLIL::SigBit pad = is_signed ? sig[GetSize(sig) - 1] : RTLIL::S0; + while (GetSize(result) < target_width) + result.append(pad); + return result; + } + + RTLIL::SigSpec build_csa_tree(std::vector &operands, int output_width) + { + int width = output_width; + std::vector summands; + int sub_count = 0; + + for (auto &op : operands) + { + RTLIL::SigSpec sig = extend_to(op.sig, op.is_signed, width); + + if (op.do_subtract) { + sig = module->Not(NEW_ID, sig); + sub_count++; + } + + summands.push_back(sig); + } + + if (sub_count > 0) { + RTLIL::Const correction(sub_count, width); + summands.push_back(RTLIL::SigSpec(correction)); + } + + if (summands.empty()) + return RTLIL::SigSpec(0, width); + + if (summands.size() == 1) + return summands[0]; + + if (summands.size() == 2) { + RTLIL::Wire *result = module->addWire(NEW_ID, width); + module->addAdd(NEW_ID, summands[0], summands[1], result); + return result; + } + + while (summands.size() > 2) + { + std::vector next; + int i = 0; + + while (i + 2 < (int)summands.size()) + { + RTLIL::SigSpec a = summands[i]; + RTLIL::SigSpec b = summands[i + 1]; + RTLIL::SigSpec c = summands[i + 2]; + + RTLIL::SigSpec sum, carry; + create_fa(a, b, c, width, sum, carry); + + RTLIL::SigSpec carry_shifted; + carry_shifted.append(RTLIL::S0); + carry_shifted.append(carry.extract(0, width - 1)); + + next.push_back(sum); + next.push_back(carry_shifted); + i += 3; + } + + while (i < (int)summands.size()) + next.push_back(summands[i++]); + + summands.swap(next); + } + + RTLIL::Wire *result = module->addWire(NEW_ID, width); + module->addAdd(NEW_ID, summands[0], summands[1], result); + return result; + } + + void run() + { + build_maps(); + + std::vector roots; + for (auto cell : module->selected_cells()) + if (cell->type.in(ID($add), ID($sub))) + roots.push_back(cell); + + std::sort(roots.begin(), roots.end(), + [](RTLIL::Cell *a, RTLIL::Cell *b) { + return a->name < b->name; + }); + + std::sort(roots.begin(), roots.end(), + [&](RTLIL::Cell *a, RTLIL::Cell *b) { + return (cell_fanout.count(a) ? cell_fanout.at(a) : 0) > + (cell_fanout.count(b) ? cell_fanout.at(b) : 0); + }); + + for (auto root : roots) + { + if (consumed.count(root)) + continue; + + std::vector operands; + std::vector tree_cells; + + collect_operands(root, false, operands, tree_cells); + + if ((int)operands.size() < min_operands) { + for (auto c : tree_cells) + consumed.erase(c); + continue; + } + + int output_width = root->getParam(ID::Y_WIDTH).as_int(); + + log(" Found adder tree rooted at %s with %d operands (depth %d cells)\n", + log_id(root), (int)operands.size(), (int)tree_cells.size()); + + RTLIL::SigSpec new_output = build_csa_tree(operands, output_width); + RTLIL::SigSpec old_output = root->getPort(ID::Y); + module->connect(old_output, new_output); + + for (auto c : tree_cells) { + module->remove(c); + stat_removed_cells++; + } + + stat_trees++; + } + } +}; + +struct CsaTreePass : public Pass +{ + CsaTreePass() : Pass("csa_tree", + "convert adder chains to carry-save adder trees") {} + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" csa_tree [options] [selection]\n"); + log("\n"); + log("This pass converts chains of $add/$sub cells into carry-save adder trees using\n"); + log("$fa (full adder / 3:2 compressor) cells to reduce the critical path depth of\n"); + log("multi-operand addition.\n"); + log("\n"); + log("For N operands of width W, the critical path is reduced from\n"); + log("O(N * log W) to O(log_1.5(N) + log W).\n"); + log("\n"); + log(" -min_operands N\n"); + log(" Minimum number of operands to trigger CSA tree construction.\n"); + log(" Default: 3. Values below 3 are clamped to 3.\n"); + log("\n"); + } + + void execute(std::vector args, RTLIL::Design *design) override + { + int min_operands = 3; + + log_header(design, "Executing CSA_TREE pass (carry-save adder tree optimization).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-min_operands" && argidx + 1 < args.size()) { + min_operands = std::max(3, atoi(args[++argidx].c_str())); + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + log("Processing module %s...\n", log_id(module)); + + CsaTreeWorker worker(module, min_operands); + worker.run(); + + if (worker.stat_trees > 0) + log(" Converted %d adder tree(s): created %d $fa cells, " + "removed %d $add/$sub cells.\n", + worker.stat_trees, worker.stat_fa_cells, + worker.stat_removed_cells); + } + } +} CsaTreePass; + +PRIVATE_NAMESPACE_END From e69914b8beeae475783daf0b1729c927850313a8 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 11:06:48 +0100 Subject: [PATCH 016/176] better balancing. --- passes/opt/csa_tree.cc | 497 ++++++++++++++++++++--------------------- 1 file changed, 242 insertions(+), 255 deletions(-) diff --git a/passes/opt/csa_tree.cc b/passes/opt/csa_tree.cc index 2328af3d8..92f744a9f 100644 --- a/passes/opt/csa_tree.cc +++ b/passes/opt/csa_tree.cc @@ -1,355 +1,342 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct CsaTreeWorker { - RTLIL::Module *module; + Module *module; SigMap sigmap; - int min_operands; - dict sig_to_driver; - dict cell_fanout; - pool consumed; + dict> bit_consumers; + dict fanout; + pool all_adds; - int stat_trees = 0; - int stat_fa_cells = 0; - int stat_removed_cells = 0; + CsaTreeWorker(Module *module) : module(module), sigmap(module) {} - CsaTreeWorker(RTLIL::Module *module, int min_operands) : - module(module), sigmap(module), min_operands(min_operands) {} + struct DepthSig { + SigSpec sig; + int depth; + }; - void build_maps() + void find_adds() { - dict sig_consumers; - for (auto cell : module->cells()) - { - if (cell->type.in(ID($add), ID($sub))) - { - RTLIL::SigSpec y = sigmap(cell->getPort(ID::Y)); - for (auto bit : y) - if (bit.wire != nullptr) - sig_to_driver[bit] = cell; - } + if (cell->type == ID($add)) + all_adds.insert(cell); + } + void build_fanout_map() + { + for (auto cell : module->cells()) for (auto &conn : cell->connections()) - { if (cell->input(conn.first)) - { for (auto bit : sigmap(conn.second)) - if (bit.wire != nullptr) - sig_consumers[bit]++; - } - } - } + bit_consumers[bit].insert(cell); + + for (auto &pair : bit_consumers) + fanout[pair.first] = pair.second.size(); for (auto wire : module->wires()) if (wire->port_output) - for (auto bit : sigmap(wire)) - if (bit.wire != nullptr) - sig_consumers[bit]++; + for (auto bit : sigmap(SigSpec(wire))) + fanout[bit]++; + } - for (auto cell : module->cells()) - { - if (!cell->type.in(ID($add), ID($sub))) - continue; - int fo = 0; - for (auto bit : sigmap(cell->getPort(ID::Y))) - if (bit.wire != nullptr) - fo = std::max(fo, sig_consumers.count(bit) ? sig_consumers.at(bit) : 0); - cell_fanout[cell] = fo; + Cell*single_add_consumer(SigSpec sig) + { + Cell*consumer = nullptr; + + for (auto bit : sig) { + if (!fanout.count(bit) || fanout[bit] != 1) + return nullptr; + if (!bit_consumers.count(bit) || bit_consumers[bit].size() != 1) + return nullptr; + + Cell* c = *bit_consumers[bit].begin(); + if (!all_adds.count(c)) + return nullptr; + + if (consumer == nullptr) + consumer = c; + else if (consumer != c) + return nullptr; } + + return consumer; + } + + dict find_add_parents() + { + dict parent_of; + + for (auto cell : all_adds) { + SigSpec y = sigmap(cell->getPort(ID::Y)); + Cell* consumer = single_add_consumer(y); + if (consumer != nullptr && consumer != cell) + parent_of[cell] = consumer; + } + + return parent_of; + } + + pool collect_chain(Cell* root, const dict> &children_of) + { + pool chain; + std::queue worklist; + worklist.push(root); + + while (!worklist.empty()) { + Cell* cur = worklist.front(); + worklist.pop(); + + if (chain.count(cur)) + continue; + chain.insert(cur); + + if (children_of.count(cur)) + for (auto child : children_of.at(cur)) + worklist.push(child); + } + + return chain; + } + + bool is_chain_internal(SigSpec sig, const pool &chain_y_bits) + { + for (auto bit : sig) + if (chain_y_bits.count(bit)) + return true; + return false; + } + + pool collect_chain_outputs(const pool &chain) + { + pool bits; + for (auto cell : chain) + for (auto bit : sigmap(cell->getPort(ID::Y))) + bits.insert(bit); + return bits; } struct Operand { - RTLIL::SigSpec sig; + SigSpec sig; bool is_signed; - bool do_subtract; }; - bool can_absorb(RTLIL::Cell *cell) + std::vector collect_leaf_operands(const pool &chain, const pool &chain_y_bits) { - if (cell == nullptr) - return false; - if (!cell->type.in(ID($add), ID($sub))) - return false; - if (consumed.count(cell)) - return false; - if (cell_fanout.count(cell) ? cell_fanout.at(cell) != 1 : true) - return false; - return true; + std::vector operands; + + for (auto cell : chain) { + SigSpec a = sigmap(cell->getPort(ID::A)); + SigSpec b = sigmap(cell->getPort(ID::B)); + bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); + bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); + + if (!is_chain_internal(a, chain_y_bits)) + operands.push_back({a, a_signed}); + if (!is_chain_internal(b, chain_y_bits)) + operands.push_back({b, b_signed}); + } + + return operands; } - RTLIL::Cell *get_driver(RTLIL::SigSpec sig) + SigSpec extend_to(SigSpec sig, bool is_signed, int width) { - sig = sigmap(sig); - if (sig.empty()) - return nullptr; - - RTLIL::Cell *driver = nullptr; - for (auto bit : sig) - { - if (bit.wire == nullptr) - continue; - auto it = sig_to_driver.find(bit); - if (it == sig_to_driver.end()) - return nullptr; - if (driver == nullptr) - driver = it->second; - else if (driver != it->second) - return nullptr; // mixed + if (GetSize(sig) < width) { + SigBit pad = (is_signed && GetSize(sig) > 0) ? sig[GetSize(sig) - 1] : State::S0; + sig.append(SigSpec(pad, width - GetSize(sig))); } - return driver; + if (GetSize(sig) > width) + sig = sig.extract(0, width); + return sig; } - void collect_operands( - RTLIL::Cell *cell, - bool negate, - std::vector &operands, - std::vector &tree_cells - ) { - tree_cells.push_back(cell); - consumed.insert(cell); + std::pair emit_fa(SigSpec a, SigSpec b, SigSpec c, int width) + { + SigSpec sum = module->addWire(NEW_ID, width); + SigSpec cout = module->addWire(NEW_ID, width); - bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); - bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); - bool is_sub = (cell->type == ID($sub)); - - RTLIL::SigSpec sig_a = cell->getPort(ID::A); - RTLIL::SigSpec sig_b = cell->getPort(ID::B); - - RTLIL::Cell *driver_a = get_driver(sig_a); - if (can_absorb(driver_a)) { - collect_operands(driver_a, negate, operands, tree_cells); - } else { - operands.push_back({sig_a, a_signed, negate}); - } - - bool b_negate = negate ^ is_sub; - RTLIL::Cell *driver_b = get_driver(sig_b); - if (can_absorb(driver_b)) { - collect_operands(driver_b, b_negate, operands, tree_cells); - } else { - operands.push_back({sig_b, b_signed, b_negate}); - } - } - - void create_fa( - RTLIL::SigSpec a, - RTLIL::SigSpec b, - RTLIL::SigSpec c, - int width, - RTLIL::SigSpec &sum_out, - RTLIL::SigSpec &carry_out - ) { - RTLIL::Wire *w_sum = module->addWire(NEW_ID, width); - RTLIL::Wire *w_carry = module->addWire(NEW_ID, width); - - RTLIL::Cell *fa = module->addCell(NEW_ID, ID($fa)); + Cell* fa = module->addCell(NEW_ID, ID($fa)); fa->setParam(ID::WIDTH, width); fa->setPort(ID::A, a); fa->setPort(ID::B, b); fa->setPort(ID::C, c); - fa->setPort(ID::Y, w_sum); - fa->setPort(ID::X, w_carry); + fa->setPort(ID::X, cout); + fa->setPort(ID::Y, sum); - sum_out = w_sum; - carry_out = w_carry; - stat_fa_cells++; + SigSpec carry_shifted; + carry_shifted.append(State::S0); + carry_shifted.append(cout.extract(0, width - 1)); + + return {sum, carry_shifted}; } - RTLIL::SigSpec extend_to(RTLIL::SigSpec sig, bool is_signed, int target_width) + std::pair build_wallace_tree(std::vector &operands, int width, int &fa_count) { - if (GetSize(sig) >= target_width) - return sig.extract(0, target_width); + std::vector ops; + for (auto &s : operands) + ops.push_back({s, 0}); - RTLIL::SigSpec result = sig; - RTLIL::SigBit pad = is_signed ? sig[GetSize(sig) - 1] : RTLIL::S0; - while (GetSize(result) < target_width) - result.append(pad); - return result; - } + fa_count = 0; + int level = 0; - RTLIL::SigSpec build_csa_tree(std::vector &operands, int output_width) - { - int width = output_width; - std::vector summands; - int sub_count = 0; - - for (auto &op : operands) + while (ops.size() > 2) { - RTLIL::SigSpec sig = extend_to(op.sig, op.is_signed, width); - - if (op.do_subtract) { - sig = module->Not(NEW_ID, sig); - sub_count++; + std::vector ready, waiting; + for (auto &op : ops) { + if (op.depth <= level) + ready.push_back(op); + else + waiting.push_back(op); } - summands.push_back(sig); - } + if (ready.size() < 3) { + level++; + log_assert(level <= 100); + continue; + } - if (sub_count > 0) { - RTLIL::Const correction(sub_count, width); - summands.push_back(RTLIL::SigSpec(correction)); - } - - if (summands.empty()) - return RTLIL::SigSpec(0, width); - - if (summands.size() == 1) - return summands[0]; - - if (summands.size() == 2) { - RTLIL::Wire *result = module->addWire(NEW_ID, width); - module->addAdd(NEW_ID, summands[0], summands[1], result); - return result; - } - - while (summands.size() > 2) - { - std::vector next; - int i = 0; - - while (i + 2 < (int)summands.size()) - { - RTLIL::SigSpec a = summands[i]; - RTLIL::SigSpec b = summands[i + 1]; - RTLIL::SigSpec c = summands[i + 2]; - - RTLIL::SigSpec sum, carry; - create_fa(a, b, c, width, sum, carry); - - RTLIL::SigSpec carry_shifted; - carry_shifted.append(RTLIL::S0); - carry_shifted.append(carry.extract(0, width - 1)); - - next.push_back(sum); - next.push_back(carry_shifted); + std::vector next; + size_t i = 0; + while (i + 2 < ready.size()) { + auto [sum, carry] = emit_fa(ready[i].sig, ready[i+1].sig, ready[i+2].sig, width); + int d = std::max({ready[i].depth, ready[i+1].depth, ready[i+2].depth}) + 1; + next.push_back({sum, d}); + next.push_back({carry, d}); + fa_count++; i += 3; } - while (i < (int)summands.size()) - next.push_back(summands[i++]); + for (; i < ready.size(); i++) + next.push_back(ready[i]); - summands.swap(next); + for (auto &op : waiting) + next.push_back(op); + + ops = std::move(next); + level++; + log_assert(level <= 100); } - RTLIL::Wire *result = module->addWire(NEW_ID, width); - module->addAdd(NEW_ID, summands[0], summands[1], result); - return result; + log_assert(ops.size() == 2); + + int max_depth = std::max(ops[0].depth, ops[1].depth); + log(" Tree depth: %d FA levels + 1 final add\n", max_depth); + + return {ops[0].sig, ops[1].sig}; + } + + void emit_final_add(SigSpec a, SigSpec b, SigSpec y, int width) + { + Cell* add = module->addCell(NEW_ID, ID($add)); + add->setParam(ID::A_SIGNED, false); + add->setParam(ID::B_SIGNED, false); + add->setParam(ID::A_WIDTH, width); + add->setParam(ID::B_WIDTH, width); + add->setParam(ID::Y_WIDTH, width); + add->setPort(ID::A, a); + add->setPort(ID::B, b); + add->setPort(ID::Y, y); } void run() { - build_maps(); + find_adds(); + if (all_adds.empty()) + return; - std::vector roots; - for (auto cell : module->selected_cells()) - if (cell->type.in(ID($add), ID($sub))) - roots.push_back(cell); + build_fanout_map(); - std::sort(roots.begin(), roots.end(), - [](RTLIL::Cell *a, RTLIL::Cell *b) { - return a->name < b->name; - }); + auto parent_of = find_add_parents(); - std::sort(roots.begin(), roots.end(), - [&](RTLIL::Cell *a, RTLIL::Cell *b) { - return (cell_fanout.count(a) ? cell_fanout.at(a) : 0) > - (cell_fanout.count(b) ? cell_fanout.at(b) : 0); - }); + pool has_parent; + dict> children_of; + for (auto &pair : parent_of) { + has_parent.insert(pair.first); + children_of[pair.second].insert(pair.first); + } - for (auto root : roots) + pool processed; + + for (auto root : all_adds) { - if (consumed.count(root)) + if (has_parent.count(root)) + continue; + if (processed.count(root)) continue; - std::vector operands; - std::vector tree_cells; - - collect_operands(root, false, operands, tree_cells); - - if ((int)operands.size() < min_operands) { - for (auto c : tree_cells) - consumed.erase(c); + pool chain = collect_chain(root, children_of); + if (chain.size() < 2) continue; - } - int output_width = root->getParam(ID::Y_WIDTH).as_int(); + for (auto c : chain) + processed.insert(c); - log(" Found adder tree rooted at %s with %d operands (depth %d cells)\n", - log_id(root), (int)operands.size(), (int)tree_cells.size()); + pool chain_y_bits = collect_chain_outputs(chain); + auto operands = collect_leaf_operands(chain, chain_y_bits); - RTLIL::SigSpec new_output = build_csa_tree(operands, output_width); - RTLIL::SigSpec old_output = root->getPort(ID::Y); - module->connect(old_output, new_output); + if (operands.size() < 3) + continue; - for (auto c : tree_cells) { - module->remove(c); - stat_removed_cells++; - } + SigSpec root_y = root->getPort(ID::Y); + int width = GetSize(root_y); - stat_trees++; + std::vector extended; + for (auto &op : operands) + extended.push_back(extend_to(op.sig, op.is_signed, width)); + + int fa_count; + auto [final_a, final_b] = build_wallace_tree(extended, width, fa_count); + + log(" Replaced chain of %d $add cells with %d $fa + 1 $add (%d operands, module %s)\n", + (int)chain.size(), fa_count, (int)operands.size(), log_id(module)); + + emit_final_add(final_a, final_b, root_y, width); + + for (auto cell : chain) + module->remove(cell); } } }; -struct CsaTreePass : public Pass -{ - CsaTreePass() : Pass("csa_tree", - "convert adder chains to carry-save adder trees") {} +struct CsaTreePass : public Pass { + CsaTreePass() : Pass("csa_tree", "convert $add chains to carry-save adder trees") {} void help() override { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" csa_tree [options] [selection]\n"); + log(" csa_tree [selection]\n"); log("\n"); - log("This pass converts chains of $add/$sub cells into carry-save adder trees using\n"); - log("$fa (full adder / 3:2 compressor) cells to reduce the critical path depth of\n"); - log("multi-operand addition.\n"); + log("This pass finds chains of $add cells and replaces them with\n"); + log("carry-save adder (CSA) trees built from $fa cells, followed by\n"); + log("a single final $add for the carry-propagate step.\n"); log("\n"); - log("For N operands of width W, the critical path is reduced from\n"); - log("O(N * log W) to O(log_1.5(N) + log W).\n"); - log("\n"); - log(" -min_operands N\n"); - log(" Minimum number of operands to trigger CSA tree construction.\n"); - log(" Default: 3. Values below 3 are clamped to 3.\n"); + log("The tree uses Wallace-tree scheduling for optimal depth:\n"); + log("at each level, all ready operands are grouped into triplets\n"); + log("and compressed via full adders. This gives ceil(log_1.5(N))\n"); + log("FA levels for N input operands.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { - int min_operands = 3; - - log_header(design, "Executing CSA_TREE pass (carry-save adder tree optimization).\n"); + log_header(design, "Executing CSA_TREE pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-min_operands" && argidx + 1 < args.size()) { - min_operands = std::max(3, atoi(args[++argidx].c_str())); - continue; - } break; - } extra_args(args, argidx, design); - for (auto module : design->selected_modules()) - { - log("Processing module %s...\n", log_id(module)); - - CsaTreeWorker worker(module, min_operands); + for (auto module : design->selected_modules()) { + CsaTreeWorker worker(module); worker.run(); - - if (worker.stat_trees > 0) - log(" Converted %d adder tree(s): created %d $fa cells, " - "removed %d $add/$sub cells.\n", - worker.stat_trees, worker.stat_fa_cells, - worker.stat_removed_cells); } } } CsaTreePass; From 4c4c5cf15a268db9aea3667679adb9263ba877e3 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 12:09:50 +0100 Subject: [PATCH 017/176] Add structural tests for csa_tree. --- Makefile | 1 + tests/csa_tree/add_1bit.v | 9 +++++++++ tests/csa_tree/add_chain_16.v | 7 +++++++ tests/csa_tree/add_chain_2_neg.v | 8 ++++++++ tests/csa_tree/add_chain_3.v | 9 +++++++++ tests/csa_tree/add_chain_5.v | 7 +++++++ tests/csa_tree/add_chain_8.v | 7 +++++++ tests/csa_tree/add_mixed_widths.v | 10 ++++++++++ tests/csa_tree/add_multi_fanout.v | 10 ++++++++++ tests/csa_tree/add_signed.v | 6 ++++++ tests/csa_tree/add_two_chains.v | 9 +++++++++ tests/csa_tree/add_wide_output.v | 6 ++++++ tests/csa_tree/add_with_const.v | 7 +++++++ tests/csa_tree/csa_tree_16input.ys | 8 ++++++++ tests/csa_tree/csa_tree_1bit.ys | 8 ++++++++ tests/csa_tree/csa_tree_2input_neg.ys | 11 +++++++++++ tests/csa_tree/csa_tree_3input.ys | 11 +++++++++++ tests/csa_tree/csa_tree_5input.ys | 11 +++++++++++ tests/csa_tree/csa_tree_8input.ys | 9 +++++++++ tests/csa_tree/csa_tree_const.ys | 9 +++++++++ tests/csa_tree/csa_tree_fir.ys | 8 ++++++++ tests/csa_tree/csa_tree_mixed_widths.ys | 9 +++++++++ tests/csa_tree/csa_tree_multi_fanout.ys | 8 ++++++++ tests/csa_tree/csa_tree_signed.ys | 9 +++++++++ tests/csa_tree/csa_tree_two_chains.ys | 9 +++++++++ tests/csa_tree/csa_tree_wide_output.ys | 9 +++++++++ tests/csa_tree/fir_4tap.v | 24 ++++++++++++++++++++++++ tests/csa_tree/run-test.sh | 7 +++++++ 28 files changed, 246 insertions(+) create mode 100644 tests/csa_tree/add_1bit.v create mode 100644 tests/csa_tree/add_chain_16.v create mode 100644 tests/csa_tree/add_chain_2_neg.v create mode 100644 tests/csa_tree/add_chain_3.v create mode 100644 tests/csa_tree/add_chain_5.v create mode 100644 tests/csa_tree/add_chain_8.v create mode 100644 tests/csa_tree/add_mixed_widths.v create mode 100644 tests/csa_tree/add_multi_fanout.v create mode 100644 tests/csa_tree/add_signed.v create mode 100644 tests/csa_tree/add_two_chains.v create mode 100644 tests/csa_tree/add_wide_output.v create mode 100644 tests/csa_tree/add_with_const.v create mode 100644 tests/csa_tree/csa_tree_16input.ys create mode 100644 tests/csa_tree/csa_tree_1bit.ys create mode 100644 tests/csa_tree/csa_tree_2input_neg.ys create mode 100644 tests/csa_tree/csa_tree_3input.ys create mode 100644 tests/csa_tree/csa_tree_5input.ys create mode 100644 tests/csa_tree/csa_tree_8input.ys create mode 100644 tests/csa_tree/csa_tree_const.ys create mode 100644 tests/csa_tree/csa_tree_fir.ys create mode 100644 tests/csa_tree/csa_tree_mixed_widths.ys create mode 100644 tests/csa_tree/csa_tree_multi_fanout.ys create mode 100644 tests/csa_tree/csa_tree_signed.ys create mode 100644 tests/csa_tree/csa_tree_two_chains.ys create mode 100644 tests/csa_tree/csa_tree_wide_output.ys create mode 100644 tests/csa_tree/fir_4tap.v create mode 100755 tests/csa_tree/run-test.sh diff --git a/Makefile b/Makefile index fc5172cc0..ad8367eeb 100644 --- a/Makefile +++ b/Makefile @@ -953,6 +953,7 @@ MK_TEST_DIRS += tests/verilog # Tests that don't generate .mk SH_TEST_DIRS = +SH_TEST_DIRS += tests/csa_tree SH_TEST_DIRS += tests/simple SH_TEST_DIRS += tests/simple_abc9 SH_TEST_DIRS += tests/hana diff --git a/tests/csa_tree/add_1bit.v b/tests/csa_tree/add_1bit.v new file mode 100644 index 000000000..febb7afde --- /dev/null +++ b/tests/csa_tree/add_1bit.v @@ -0,0 +1,9 @@ +// edge case for carry shifting + +module add_1bit( + input a, b, c, + output [1:0] y +); + assign y = a + b + c; +endmodule + diff --git a/tests/csa_tree/add_chain_16.v b/tests/csa_tree/add_chain_16.v new file mode 100644 index 000000000..0a1f12f8c --- /dev/null +++ b/tests/csa_tree/add_chain_16.v @@ -0,0 +1,7 @@ +module add_chain_16( + input [15:0] a0, a1, a2, a3, a4, a5, a6, a7, + input [15:0] a8, a9, a10, a11, a12, a13, a14, a15, + output [15:0] y +); + assign y = a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15; +endmodule diff --git a/tests/csa_tree/add_chain_2_neg.v b/tests/csa_tree/add_chain_2_neg.v new file mode 100644 index 000000000..0e2896c78 --- /dev/null +++ b/tests/csa_tree/add_chain_2_neg.v @@ -0,0 +1,8 @@ +// Shouldnt generate csa tree + +module add_chain_2( + input [7:0] a, b, + output [7:0] y +); + assign y = a + b; +endmodule diff --git a/tests/csa_tree/add_chain_3.v b/tests/csa_tree/add_chain_3.v new file mode 100644 index 000000000..eea529ead --- /dev/null +++ b/tests/csa_tree/add_chain_3.v @@ -0,0 +1,9 @@ +// Min chain len + +module add_chain_3( + input [7:0] a, b, c, + output [7:0] y +); + assign y = a + b + c; +endmodule + diff --git a/tests/csa_tree/add_chain_5.v b/tests/csa_tree/add_chain_5.v new file mode 100644 index 000000000..25fb30e1d --- /dev/null +++ b/tests/csa_tree/add_chain_5.v @@ -0,0 +1,7 @@ +module add_chain_5( + input [11:0] a, b, c, d, e, + output [11:0] y +); + assign y = a + b + c + d + e; +endmodule + diff --git a/tests/csa_tree/add_chain_8.v b/tests/csa_tree/add_chain_8.v new file mode 100644 index 000000000..96adbc37e --- /dev/null +++ b/tests/csa_tree/add_chain_8.v @@ -0,0 +1,7 @@ +module add_chain_8( + input [15:0] a, b, c, d, e, f, g, h, + output [15:0] y +); + assign y = a + b + c + d + e + f + g + h; +endmodule + diff --git a/tests/csa_tree/add_mixed_widths.v b/tests/csa_tree/add_mixed_widths.v new file mode 100644 index 000000000..51836872a --- /dev/null +++ b/tests/csa_tree/add_mixed_widths.v @@ -0,0 +1,10 @@ +module add_mixed_widths( + input [7:0] a, + input [3:0] b, + input [15:0] c, + input [7:0] d, + output [15:0] y +); + assign y = a + b + c + d; +endmodule + diff --git a/tests/csa_tree/add_multi_fanout.v b/tests/csa_tree/add_multi_fanout.v new file mode 100644 index 000000000..4cc7ecab3 --- /dev/null +++ b/tests/csa_tree/add_multi_fanout.v @@ -0,0 +1,10 @@ +module add_multi_fanout( + input [7:0] a, b, c, + output [7:0] mid, + output [7:0] y +); + wire [7:0] ab = a + b; + assign mid = ab; + assign y = ab + c; +endmodule + diff --git a/tests/csa_tree/add_signed.v b/tests/csa_tree/add_signed.v new file mode 100644 index 000000000..42b9ca7fd --- /dev/null +++ b/tests/csa_tree/add_signed.v @@ -0,0 +1,6 @@ +module add_signed( + input signed [7:0] a, b, c, d, + output signed [9:0] y +); + assign y = a + b + c + d; +endmodule diff --git a/tests/csa_tree/add_two_chains.v b/tests/csa_tree/add_two_chains.v new file mode 100644 index 000000000..d79d9f3d6 --- /dev/null +++ b/tests/csa_tree/add_two_chains.v @@ -0,0 +1,9 @@ +module add_two_chains( + input [7:0] a, b, c, d, + input [7:0] e, f, g, h, + output [7:0] y1, + output [7:0] y2 +); + assign y1 = a + b + c + d; + assign y2 = e + f + g + h; +endmodule diff --git a/tests/csa_tree/add_wide_output.v b/tests/csa_tree/add_wide_output.v new file mode 100644 index 000000000..1f0342777 --- /dev/null +++ b/tests/csa_tree/add_wide_output.v @@ -0,0 +1,6 @@ +module add_wide_output( + input [7:0] a, b, c, d, + output [31:0] y +); + assign y = a + b + c + d; +endmodule diff --git a/tests/csa_tree/add_with_const.v b/tests/csa_tree/add_with_const.v new file mode 100644 index 000000000..570a399e4 --- /dev/null +++ b/tests/csa_tree/add_with_const.v @@ -0,0 +1,7 @@ +module add_with_const( + input [7:0] a, b, c, + output [7:0] y +); + assign y = a + b + c + 8'd42; +endmodule + diff --git a/tests/csa_tree/csa_tree_16input.ys b/tests/csa_tree/csa_tree_16input.ys new file mode 100644 index 000000000..230d5f845 --- /dev/null +++ b/tests/csa_tree/csa_tree_16input.ys @@ -0,0 +1,8 @@ +read_verilog add_chain_16.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 5 t:$fa +select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_1bit.ys b/tests/csa_tree/csa_tree_1bit.ys new file mode 100644 index 000000000..74d19c647 --- /dev/null +++ b/tests/csa_tree/csa_tree_1bit.ys @@ -0,0 +1,8 @@ +# Test csa_tree with single-bit operands — carry shift edge case + +read_verilog add_1bit.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + diff --git a/tests/csa_tree/csa_tree_2input_neg.ys b/tests/csa_tree/csa_tree_2input_neg.ys new file mode 100644 index 000000000..810d1d8d9 --- /dev/null +++ b/tests/csa_tree/csa_tree_2input_neg.ys @@ -0,0 +1,11 @@ +# Test csa_tree on 2-operand — should not trigger + +read_verilog add_chain_2_neg.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-none t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_3input.ys b/tests/csa_tree/csa_tree_3input.ys new file mode 100644 index 000000000..68ff2ff2e --- /dev/null +++ b/tests/csa_tree/csa_tree_3input.ys @@ -0,0 +1,11 @@ +# Test csa_tree on 3-operand chain — minimal trigger case + +read_verilog add_chain_3.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-count 1 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_5input.ys b/tests/csa_tree/csa_tree_5input.ys new file mode 100644 index 000000000..dadea092f --- /dev/null +++ b/tests/csa_tree/csa_tree_5input.ys @@ -0,0 +1,11 @@ +# Test csa_tree with 5 operands — tree with remainders + +read_verilog add_chain_5.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-min 2 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_8input.ys b/tests/csa_tree/csa_tree_8input.ys new file mode 100644 index 000000000..23d2d698a --- /dev/null +++ b/tests/csa_tree/csa_tree_8input.ys @@ -0,0 +1,9 @@ +read_verilog add_chain_8.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_const.ys b/tests/csa_tree/csa_tree_const.ys new file mode 100644 index 000000000..75d0bc1d7 --- /dev/null +++ b/tests/csa_tree/csa_tree_const.ys @@ -0,0 +1,9 @@ +read_verilog add_with_const.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_fir.ys b/tests/csa_tree/csa_tree_fir.ys new file mode 100644 index 000000000..59aac98b0 --- /dev/null +++ b/tests/csa_tree/csa_tree_fir.ys @@ -0,0 +1,8 @@ +read_verilog fir_4tap.v +hierarchy -auto-top +proc; opt_clean +equiv_opt -async2sync csa_tree +design -load postopt + +select -assert-min 1 t:$fa + diff --git a/tests/csa_tree/csa_tree_mixed_widths.ys b/tests/csa_tree/csa_tree_mixed_widths.ys new file mode 100644 index 000000000..1cecae201 --- /dev/null +++ b/tests/csa_tree/csa_tree_mixed_widths.ys @@ -0,0 +1,9 @@ +read_verilog add_mixed_widths.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_multi_fanout.ys b/tests/csa_tree/csa_tree_multi_fanout.ys new file mode 100644 index 000000000..0bce8d6bd --- /dev/null +++ b/tests/csa_tree/csa_tree_multi_fanout.ys @@ -0,0 +1,8 @@ +read_verilog add_multi_fanout.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-none t:$fa + diff --git a/tests/csa_tree/csa_tree_signed.ys b/tests/csa_tree/csa_tree_signed.ys new file mode 100644 index 000000000..7e29cc123 --- /dev/null +++ b/tests/csa_tree/csa_tree_signed.ys @@ -0,0 +1,9 @@ +read_verilog add_signed.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/csa_tree_two_chains.ys b/tests/csa_tree/csa_tree_two_chains.ys new file mode 100644 index 000000000..10fbe8b15 --- /dev/null +++ b/tests/csa_tree/csa_tree_two_chains.ys @@ -0,0 +1,9 @@ +read_verilog add_two_chains.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-min 2 t:$fa +select -assert-count 2 t:$add + diff --git a/tests/csa_tree/csa_tree_wide_output.ys b/tests/csa_tree/csa_tree_wide_output.ys new file mode 100644 index 000000000..84cd13bd7 --- /dev/null +++ b/tests/csa_tree/csa_tree_wide_output.ys @@ -0,0 +1,9 @@ +read_verilog add_wide_output.v +hierarchy -auto-top +proc; opt_clean +equiv_opt csa_tree +design -load postopt + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add + diff --git a/tests/csa_tree/fir_4tap.v b/tests/csa_tree/fir_4tap.v new file mode 100644 index 000000000..6c197dbd1 --- /dev/null +++ b/tests/csa_tree/fir_4tap.v @@ -0,0 +1,24 @@ +module fir_4tap( + input clk, + input [15:0] x, + input [15:0] c0, c1, c2, c3, + output reg [31:0] y +); + reg [15:0] x1, x2, x3; + always @(posedge clk) begin + x1 <= x; + x2 <= x1; + x3 <= x2; + end + + wire [31:0] p0 = x * c0; + wire [31:0] p1 = x1 * c1; + wire [31:0] p2 = x2 * c2; + wire [31:0] p3 = x3 * c3; + + wire [31:0] sum = p0 + p1 + p2 + p3; + + always @(posedge clk) + y <= sum; +endmodule + diff --git a/tests/csa_tree/run-test.sh b/tests/csa_tree/run-test.sh new file mode 100755 index 000000000..2e3f5235c --- /dev/null +++ b/tests/csa_tree/run-test.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +source ../common-env.sh +set -e +for x in *.ys; do + echo "Running $x.." + ../../yosys -ql ${x%.ys}.log $x +done From 1a4a41812cb75c49214317deac3a13af2d085ad2 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 12:23:26 +0100 Subject: [PATCH 018/176] Add csa synth tests. --- tests/csa_tree/abc_bench_add8.v | 6 +++++ tests/csa_tree/csa_tree_sim.ys | 23 ++++++++++++++++ tests/csa_tree/csa_tree_synth.ys | 45 ++++++++++++++++++++++++++++++++ tests/csa_tree/sim_add4.v | 6 +++++ 4 files changed, 80 insertions(+) create mode 100644 tests/csa_tree/abc_bench_add8.v create mode 100644 tests/csa_tree/csa_tree_sim.ys create mode 100644 tests/csa_tree/csa_tree_synth.ys create mode 100644 tests/csa_tree/sim_add4.v diff --git a/tests/csa_tree/abc_bench_add8.v b/tests/csa_tree/abc_bench_add8.v new file mode 100644 index 000000000..7e61007c5 --- /dev/null +++ b/tests/csa_tree/abc_bench_add8.v @@ -0,0 +1,6 @@ +module abc_bench_add8( + input [7:0] a, b, c, d, e, f, g, h, + output [7:0] y +); + assign y = a + b + c + d + e + f + g + h; +endmodule diff --git a/tests/csa_tree/csa_tree_sim.ys b/tests/csa_tree/csa_tree_sim.ys new file mode 100644 index 000000000..5a571c268 --- /dev/null +++ b/tests/csa_tree/csa_tree_sim.ys @@ -0,0 +1,23 @@ +read_verilog sim_add4.v +hierarchy -top sim_add4 +proc; opt_clean +csa_tree +opt_clean + +# 1 + 2 + 3 + 4 = 10 +sat -set a 1 -set b 2 -set c 3 -set d 4 -prove y 10 + +# 0 + 0 + 0 + 0 = 0 +sat -set a 0 -set b 0 -set c 0 -set d 0 -prove y 0 + +# 255 + 1 + 0 + 0 = 0 +sat -set a 255 -set b 1 -set c 0 -set d 0 -prove y 0 + +# 100 + 50 + 25 + 25 = 200 +sat -set a 100 -set b 50 -set c 25 -set d 25 -prove y 200 + +# 255 + 255 + 255 + 255 = 252 +sat -set a 255 -set b 255 -set c 255 -set d 255 -prove y 252 + +log "ok" + diff --git a/tests/csa_tree/csa_tree_synth.ys b/tests/csa_tree/csa_tree_synth.ys new file mode 100644 index 000000000..e03580217 --- /dev/null +++ b/tests/csa_tree/csa_tree_synth.ys @@ -0,0 +1,45 @@ +# Baseline: no csa_tree +read_verilog abc_bench_add8.v +hierarchy -top abc_bench_add8 +proc; opt + +# Baseline synth +techmap +abc -g AND,OR,XOR +opt_clean +stat +design -save baseline + +# With csa_tree +design -reset +read_verilog abc_bench_add8.v +hierarchy -top abc_bench_add8 +proc; opt +csa_tree +techmap +abc -g AND,OR,XOR +opt_clean +stat + +select -assert-max 250 t:$_AND_ t:$_OR_ t:$_XOR_ t:$_NOT_ %u +design -save csa_result + +# Depth comparison via ABC +design -reset +read_verilog abc_bench_add8.v +hierarchy -top abc_bench_add8 +proc; opt +techmap +abc -D 1 +stat +log "baseline depth mapping complete" + +design -reset +read_verilog abc_bench_add8.v +hierarchy -top abc_bench_add8 +proc; opt +csa_tree +techmap +abc -D 1 +stat +log "CSA depth mapping complete" diff --git a/tests/csa_tree/sim_add4.v b/tests/csa_tree/sim_add4.v new file mode 100644 index 000000000..589044889 --- /dev/null +++ b/tests/csa_tree/sim_add4.v @@ -0,0 +1,6 @@ +module sim_add4( + input [7:0] a, b, c, d, + output [7:0] y +); + assign y = a + b + c + d; +endmodule From 7183016910aa75002e942776cd2f204f2599b920 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 12:33:26 +0100 Subject: [PATCH 019/176] Edge case tests. --- tests/csa_tree/add_1bit_wide_out.v | 6 ++ tests/csa_tree/add_multi_const.v | 6 ++ tests/csa_tree/add_partial_chain.v | 9 +++ tests/csa_tree/add_repeated.v | 6 ++ tests/csa_tree/csa_tree_1bit_wide_out.ys | 8 +++ tests/csa_tree/csa_tree_equiv.ys | 80 ++++++++++++++++++++++++ tests/csa_tree/csa_tree_multi_const.ys | 9 +++ tests/csa_tree/csa_tree_partial_chain.ys | 8 +++ tests/csa_tree/csa_tree_repeated.ys | 8 +++ tests/csa_tree/equiv_narrow.v | 59 +++++++++++++++++ 10 files changed, 199 insertions(+) create mode 100644 tests/csa_tree/add_1bit_wide_out.v create mode 100644 tests/csa_tree/add_multi_const.v create mode 100644 tests/csa_tree/add_partial_chain.v create mode 100644 tests/csa_tree/add_repeated.v create mode 100644 tests/csa_tree/csa_tree_1bit_wide_out.ys create mode 100644 tests/csa_tree/csa_tree_equiv.ys create mode 100644 tests/csa_tree/csa_tree_multi_const.ys create mode 100644 tests/csa_tree/csa_tree_partial_chain.ys create mode 100644 tests/csa_tree/csa_tree_repeated.ys create mode 100644 tests/csa_tree/equiv_narrow.v diff --git a/tests/csa_tree/add_1bit_wide_out.v b/tests/csa_tree/add_1bit_wide_out.v new file mode 100644 index 000000000..e1a6ceb51 --- /dev/null +++ b/tests/csa_tree/add_1bit_wide_out.v @@ -0,0 +1,6 @@ +module add_1bit_wide_out( + input a, b, c, d, + output [3:0] y +); + assign y = a + b + c + d; +endmodule diff --git a/tests/csa_tree/add_multi_const.v b/tests/csa_tree/add_multi_const.v new file mode 100644 index 000000000..7da78f9de --- /dev/null +++ b/tests/csa_tree/add_multi_const.v @@ -0,0 +1,6 @@ +module add_multi_const( + input [7:0] x, + output [7:0] y +); + assign y = 8'd1 + 8'd2 + 8'd3 + x; +endmodule diff --git a/tests/csa_tree/add_partial_chain.v b/tests/csa_tree/add_partial_chain.v new file mode 100644 index 000000000..a4f20cfa4 --- /dev/null +++ b/tests/csa_tree/add_partial_chain.v @@ -0,0 +1,9 @@ +module add_partial_chain( + input [7:0] a, b, c, d, e, + output [7:0] mid, + output [7:0] y +); + wire [7:0] ab = a + b; + assign mid = ab; + assign y = ab + c + d + e; +endmodule diff --git a/tests/csa_tree/add_repeated.v b/tests/csa_tree/add_repeated.v new file mode 100644 index 000000000..e3337097b --- /dev/null +++ b/tests/csa_tree/add_repeated.v @@ -0,0 +1,6 @@ +module add_repeated( + input [7:0] a, + output [7:0] y +); + assign y = a + a + a + a; +endmodule diff --git a/tests/csa_tree/csa_tree_1bit_wide_out.ys b/tests/csa_tree/csa_tree_1bit_wide_out.ys new file mode 100644 index 000000000..5e2605340 --- /dev/null +++ b/tests/csa_tree/csa_tree_1bit_wide_out.ys @@ -0,0 +1,8 @@ +read_verilog add_1bit_wide_out.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_equiv.ys b/tests/csa_tree/csa_tree_equiv.ys new file mode 100644 index 000000000..9c5b4ab44 --- /dev/null +++ b/tests/csa_tree/csa_tree_equiv.ys @@ -0,0 +1,80 @@ +# Test bit correctness +read_verilog equiv_narrow.v +hierarchy -top equiv_add3 +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-count 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_add3: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_add4 +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_add4: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_add5 +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 2 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_add5: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_add8 +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_add8: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_signed +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_signed: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_mixed_w +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_mixed_w: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_repeated +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_repeated: ok" + +read_verilog equiv_narrow.v +hierarchy -top equiv_1bit_wide +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_1bit_wide: ok" diff --git a/tests/csa_tree/csa_tree_multi_const.ys b/tests/csa_tree/csa_tree_multi_const.ys new file mode 100644 index 000000000..a68b60e33 --- /dev/null +++ b/tests/csa_tree/csa_tree_multi_const.ys @@ -0,0 +1,9 @@ +read_verilog add_multi_const.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-none t:$fa +select -assert-max 1 t:$add + diff --git a/tests/csa_tree/csa_tree_partial_chain.ys b/tests/csa_tree/csa_tree_partial_chain.ys new file mode 100644 index 000000000..3852c4f9d --- /dev/null +++ b/tests/csa_tree/csa_tree_partial_chain.ys @@ -0,0 +1,8 @@ +read_verilog add_partial_chain.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-min 2 t:$add diff --git a/tests/csa_tree/csa_tree_repeated.ys b/tests/csa_tree/csa_tree_repeated.ys new file mode 100644 index 000000000..7e1c2ec51 --- /dev/null +++ b/tests/csa_tree/csa_tree_repeated.ys @@ -0,0 +1,8 @@ +read_verilog add_repeated.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add diff --git a/tests/csa_tree/equiv_narrow.v b/tests/csa_tree/equiv_narrow.v new file mode 100644 index 000000000..f4f7ef279 --- /dev/null +++ b/tests/csa_tree/equiv_narrow.v @@ -0,0 +1,59 @@ +// Narrow-width test designs for SAT equivalence (4-bit to keep SAT fast) + +module equiv_add3( + input [3:0] a, b, c, + output [3:0] y +); + assign y = a + b + c; +endmodule + +module equiv_add4( + input [3:0] a, b, c, d, + output [3:0] y +); + assign y = a + b + c + d; +endmodule + +module equiv_add5( + input [3:0] a, b, c, d, e, + output [3:0] y +); + assign y = a + b + c + d + e; +endmodule + +module equiv_add8( + input [3:0] a, b, c, d, e, f, g, h, + output [3:0] y +); + assign y = a + b + c + d + e + f + g + h; +endmodule + +module equiv_signed( + input signed [3:0] a, b, c, d, + output signed [5:0] y +); + assign y = a + b + c + d; +endmodule + +module equiv_mixed_w( + input [1:0] a, + input [3:0] b, + input [5:0] c, + output [5:0] y +); + assign y = a + b + c; +endmodule + +module equiv_repeated( + input [3:0] a, + output [3:0] y +); + assign y = a + a + a + a; +endmodule + +module equiv_1bit_wide( + input a, b, c, d, + output [3:0] y +); + assign y = a + b + c + d; +endmodule From 335cce4895e29376319309d682839e4239a760ed Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 12:54:58 +0100 Subject: [PATCH 020/176] Add sub chain support for csa trees. --- passes/opt/csa_tree.cc | 157 ++++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 34 deletions(-) diff --git a/passes/opt/csa_tree.cc b/passes/opt/csa_tree.cc index 92f744a9f..e1a4a9464 100644 --- a/passes/opt/csa_tree.cc +++ b/passes/opt/csa_tree.cc @@ -13,7 +13,7 @@ struct CsaTreeWorker dict> bit_consumers; dict fanout; - pool all_adds; + pool all_addsubs; CsaTreeWorker(Module *module) : module(module), sigmap(module) {} @@ -22,11 +22,11 @@ struct CsaTreeWorker int depth; }; - void find_adds() + void find_addsubs() { for (auto cell : module->cells()) - if (cell->type == ID($add)) - all_adds.insert(cell); + if (cell->type == ID($add) || cell->type == ID($sub)) + all_addsubs.insert(cell); } void build_fanout_map() @@ -46,9 +46,9 @@ struct CsaTreeWorker fanout[bit]++; } - Cell*single_add_consumer(SigSpec sig) + Cell* single_addsub_consumer(SigSpec sig) { - Cell*consumer = nullptr; + Cell* consumer = nullptr; for (auto bit : sig) { if (!fanout.count(bit) || fanout[bit] != 1) @@ -57,7 +57,7 @@ struct CsaTreeWorker return nullptr; Cell* c = *bit_consumers[bit].begin(); - if (!all_adds.count(c)) + if (!all_addsubs.count(c)) return nullptr; if (consumer == nullptr) @@ -69,13 +69,13 @@ struct CsaTreeWorker return consumer; } - dict find_add_parents() + dict find_addsub_parents() { dict parent_of; - for (auto cell : all_adds) { + for (auto cell : all_addsubs) { SigSpec y = sigmap(cell->getPort(ID::Y)); - Cell* consumer = single_add_consumer(y); + Cell* consumer = single_addsub_consumer(y); if (consumer != nullptr && consumer != cell) parent_of[cell] = consumer; } @@ -125,22 +125,78 @@ struct CsaTreeWorker struct Operand { SigSpec sig; bool is_signed; + bool negate; }; - std::vector collect_leaf_operands(const pool &chain, const pool &chain_y_bits) + bool is_subtracted_input(Cell* child, Cell* parent) { + if (parent->type != ID($sub)) + return false; + + SigSpec child_y = sigmap(child->getPort(ID::Y)); + SigSpec parent_b = sigmap(parent->getPort(ID::B)); + + for (auto bit : child_y) + for (auto pbit : parent_b) + if (bit == pbit) + return true; + + return false; + } + + std::vector collect_leaf_operands( + const pool &chain, + const pool &chain_y_bits, + Cell* root, + const dict &parent_of, + int &correction + ) { + dict negated; + negated[root] = false; + std::queue worklist; + worklist.push(root); + + while (!worklist.empty()) { + Cell* cur = worklist.front(); + worklist.pop(); + for (auto cell : chain) { + if (!parent_of.count(cell)) + continue; + if (parent_of.at(cell) != cur) + continue; + if (negated.count(cell)) + continue; + + bool sub_b = is_subtracted_input(cell, cur); + negated[cell] = negated[cur] ^ sub_b; + worklist.push(cell); + } + } + std::vector operands; + correction = 0; for (auto cell : chain) { + bool cell_neg = negated.count(cell) ? negated[cell] : false; SigSpec a = sigmap(cell->getPort(ID::A)); SigSpec b = sigmap(cell->getPort(ID::B)); bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); + bool b_subtracted = (cell->type == ID($sub)); - if (!is_chain_internal(a, chain_y_bits)) - operands.push_back({a, a_signed}); - if (!is_chain_internal(b, chain_y_bits)) - operands.push_back({b, b_signed}); + if (!is_chain_internal(a, chain_y_bits)) { + bool neg_a = cell_neg; + operands.push_back({a, a_signed, neg_a}); + if (neg_a) + correction++; + } + + if (!is_chain_internal(b, chain_y_bits)) { + bool neg_b = cell_neg ^ b_subtracted; + operands.push_back({b, b_signed, neg_b}); + if (neg_b) + correction++; + } } return operands; @@ -157,6 +213,23 @@ struct CsaTreeWorker return sig; } + SigSpec emit_not(SigSpec sig, int width) + { + SigSpec out = module->addWire(NEW_ID, width); + Cell* inv = module->addCell(NEW_ID, ID($not)); + inv->setParam(ID::A_SIGNED, false); + inv->setParam(ID::A_WIDTH, width); + inv->setParam(ID::Y_WIDTH, width); + inv->setPort(ID::A, sig); + inv->setPort(ID::Y, out); + return out; + } + + SigSpec make_constant(int value, int width) + { + return SigSpec(value, width); + } + std::pair emit_fa(SigSpec a, SigSpec b, SigSpec c, int width) { SigSpec sum = module->addWire(NEW_ID, width); @@ -247,13 +320,13 @@ struct CsaTreeWorker void run() { - find_adds(); - if (all_adds.empty()) + find_addsubs(); + if (all_addsubs.empty()) return; build_fanout_map(); - auto parent_of = find_add_parents(); + auto parent_of = find_addsub_parents(); pool has_parent; dict> children_of; @@ -264,7 +337,7 @@ struct CsaTreeWorker pool processed; - for (auto root : all_adds) + for (auto root : all_addsubs) { if (has_parent.count(root)) continue; @@ -279,23 +352,40 @@ struct CsaTreeWorker processed.insert(c); pool chain_y_bits = collect_chain_outputs(chain); - auto operands = collect_leaf_operands(chain, chain_y_bits); + int correction = 0; + auto operands = collect_leaf_operands(chain, chain_y_bits, root, parent_of, correction); if (operands.size() < 3) continue; SigSpec root_y = root->getPort(ID::Y); int width = GetSize(root_y); - std::vector extended; - for (auto &op : operands) - extended.push_back(extend_to(op.sig, op.is_signed, width)); + + for (auto &op : operands) { + SigSpec s = extend_to(op.sig, op.is_signed, width); + if (op.negate) + s = emit_not(s, width); + extended.push_back(s); + } + + if (correction > 0) + extended.push_back(make_constant(correction, width)); int fa_count; auto [final_a, final_b] = build_wallace_tree(extended, width, fa_count); + int num_subs = 0; - log(" Replaced chain of %d $add cells with %d $fa + 1 $add (%d operands, module %s)\n", - (int)chain.size(), fa_count, (int)operands.size(), log_id(module)); + for (auto cell : chain) + if (cell->type == ID($sub)) + num_subs++; + + if (num_subs > 0) + log(" Replaced chain of %d $add/%d $sub cells with %d $fa + 1 $add (%d operands, module %s)\n", + (int)chain.size() - num_subs, num_subs, fa_count, (int)operands.size(), log_id(module)); + else + log(" Replaced chain of %d $add cells with %d $fa + 1 $add (%d operands, module %s)\n", + (int)chain.size(), fa_count, (int)operands.size(), log_id(module)); emit_final_add(final_a, final_b, root_y, width); @@ -306,22 +396,21 @@ struct CsaTreeWorker }; struct CsaTreePass : public Pass { - CsaTreePass() : Pass("csa_tree", "convert $add chains to carry-save adder trees") {} + CsaTreePass() : Pass("csa_tree", "convert $add/$sub chains to carry-save adder trees") {} void help() override { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" csa_tree [selection]\n"); log("\n"); - log("This pass finds chains of $add cells and replaces them with\n"); - log("carry-save adder (CSA) trees built from $fa cells, followed by\n"); - log("a single final $add for the carry-propagate step.\n"); + log("This pass finds chains of $add and $sub cells and replaces them with carry-save\n"); + log("adder trees built from $fa cells, followed by a single final $add for the\n"); + log("carry-propagate step.\n"); log("\n"); - log("The tree uses Wallace-tree scheduling for optimal depth:\n"); - log("at each level, all ready operands are grouped into triplets\n"); - log("and compressed via full adders. This gives ceil(log_1.5(N))\n"); - log("FA levels for N input operands.\n"); + log("The tree uses Wallace-tree scheduling for optimal depth: at each level, all ready\n"); + log("operands are grouped into triplets and compressed via full adders. This\n"); + log("gives ceil(log_1.5(N)) FA levels for N input operands.\n"); log("\n"); } From 6b0caedcdd0a46a90538f83ef983a5bc149c0b6b Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 13:14:32 +0100 Subject: [PATCH 021/176] Add chain tests and tighten synthesis assertions for csa. --- tests/csa_tree/add_1bit.v | 2 +- tests/csa_tree/csa_tree_1bit.ys | 6 ++-- tests/csa_tree/csa_tree_equiv.ys | 1 + tests/csa_tree/csa_tree_sub_2op_neg.ys | 8 +++++ tests/csa_tree/csa_tree_sub_3op.ys | 11 +++++++ tests/csa_tree/csa_tree_sub_5op.ys | 9 ++++++ tests/csa_tree/csa_tree_sub_all.ys | 9 ++++++ tests/csa_tree/csa_tree_sub_equiv.ys | 41 ++++++++++++++++++++++++++ tests/csa_tree/csa_tree_sub_mixed.ys | 11 +++++++ tests/csa_tree/csa_tree_sub_signed.ys | 9 ++++++ tests/csa_tree/csa_tree_sub_sim.ys | 38 ++++++++++++++++++++++++ tests/csa_tree/csa_tree_synth.ys | 32 ++++++++++++++------ tests/csa_tree/csa_tree_two_chains.ys | 3 +- tests/csa_tree/csa_tree_wide_output.ys | 3 +- tests/csa_tree/equiv_sub_narrow.v | 27 +++++++++++++++++ tests/csa_tree/sub_2op_neg.v | 6 ++++ tests/csa_tree/sub_3op.v | 6 ++++ tests/csa_tree/sub_5op.v | 6 ++++ tests/csa_tree/sub_all.v | 6 ++++ tests/csa_tree/sub_mixed.v | 6 ++++ tests/csa_tree/sub_signed.v | 6 ++++ 21 files changed, 230 insertions(+), 16 deletions(-) create mode 100644 tests/csa_tree/csa_tree_sub_2op_neg.ys create mode 100644 tests/csa_tree/csa_tree_sub_3op.ys create mode 100644 tests/csa_tree/csa_tree_sub_5op.ys create mode 100644 tests/csa_tree/csa_tree_sub_all.ys create mode 100644 tests/csa_tree/csa_tree_sub_equiv.ys create mode 100644 tests/csa_tree/csa_tree_sub_mixed.ys create mode 100644 tests/csa_tree/csa_tree_sub_signed.ys create mode 100644 tests/csa_tree/csa_tree_sub_sim.ys create mode 100644 tests/csa_tree/equiv_sub_narrow.v create mode 100644 tests/csa_tree/sub_2op_neg.v create mode 100644 tests/csa_tree/sub_3op.v create mode 100644 tests/csa_tree/sub_5op.v create mode 100644 tests/csa_tree/sub_all.v create mode 100644 tests/csa_tree/sub_mixed.v create mode 100644 tests/csa_tree/sub_signed.v diff --git a/tests/csa_tree/add_1bit.v b/tests/csa_tree/add_1bit.v index febb7afde..e4b93e8c0 100644 --- a/tests/csa_tree/add_1bit.v +++ b/tests/csa_tree/add_1bit.v @@ -1,4 +1,4 @@ -// edge case for carry shifting +// Edge case for carry shifting module add_1bit( input a, b, c, diff --git a/tests/csa_tree/csa_tree_1bit.ys b/tests/csa_tree/csa_tree_1bit.ys index 74d19c647..4245f3d24 100644 --- a/tests/csa_tree/csa_tree_1bit.ys +++ b/tests/csa_tree/csa_tree_1bit.ys @@ -3,6 +3,8 @@ read_verilog add_1bit.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat +select -assert-min 1 t:$fa +select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_equiv.ys b/tests/csa_tree/csa_tree_equiv.ys index 9c5b4ab44..ac976e1b3 100644 --- a/tests/csa_tree/csa_tree_equiv.ys +++ b/tests/csa_tree/csa_tree_equiv.ys @@ -1,4 +1,5 @@ # Test bit correctness + read_verilog equiv_narrow.v hierarchy -top equiv_add3 proc; opt_clean diff --git a/tests/csa_tree/csa_tree_sub_2op_neg.ys b/tests/csa_tree/csa_tree_sub_2op_neg.ys new file mode 100644 index 000000000..e2ee89a50 --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_2op_neg.ys @@ -0,0 +1,8 @@ +read_verilog sub_2op_neg.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-none t:$fa +select -assert-count 1 t:$sub diff --git a/tests/csa_tree/csa_tree_sub_3op.ys b/tests/csa_tree/csa_tree_sub_3op.ys new file mode 100644 index 000000000..70801d30c --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_3op.ys @@ -0,0 +1,11 @@ +# Test minimal sub chain + +read_verilog sub_3op.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_5op.ys b/tests/csa_tree/csa_tree_sub_5op.ys new file mode 100644 index 000000000..62c4a80ff --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_5op.ys @@ -0,0 +1,9 @@ +read_verilog sub_5op.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 2 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_all.ys b/tests/csa_tree/csa_tree_sub_all.ys new file mode 100644 index 000000000..8e47bb0db --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_all.ys @@ -0,0 +1,9 @@ +read_verilog sub_all.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_equiv.ys b/tests/csa_tree/csa_tree_sub_equiv.ys new file mode 100644 index 000000000..b1be6bebe --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_equiv.ys @@ -0,0 +1,41 @@ +# Test equiv_opt on narrow sub designs + +read_verilog equiv_sub_narrow.v +hierarchy -top equiv_sub_mixed +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_sub_mixed: ok" + +read_verilog equiv_sub_narrow.v +hierarchy -top equiv_sub_all +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_sub_all: ok" + +read_verilog equiv_sub_narrow.v +hierarchy -top equiv_sub_3op +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_sub_3op: ok" + +read_verilog equiv_sub_narrow.v +hierarchy -top equiv_sub_signed +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset +log "equiv_sub_signed: ok" diff --git a/tests/csa_tree/csa_tree_sub_mixed.ys b/tests/csa_tree/csa_tree_sub_mixed.ys new file mode 100644 index 000000000..8fea5f0d2 --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_mixed.ys @@ -0,0 +1,11 @@ +# Test mixed csa chain + +read_verilog sub_mixed.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_signed.ys b/tests/csa_tree/csa_tree_sub_signed.ys new file mode 100644 index 000000000..78caf5a2e --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_signed.ys @@ -0,0 +1,9 @@ +read_verilog sub_signed.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_sim.ys b/tests/csa_tree/csa_tree_sub_sim.ys new file mode 100644 index 000000000..73ca5f3e1 --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_sim.ys @@ -0,0 +1,38 @@ +read_verilog sub_mixed.v +hierarchy -top sub_mixed +proc; opt_clean +csa_tree +opt_clean + +# 10 + 20 - 5 + 3 = 28 +sat -set a 10 -set b 20 -set c 5 -set d 3 -prove y 28 + +# 0 + 0 - 0 + 0 = 0 +sat -set a 0 -set b 0 -set c 0 -set d 0 -prove y 0 + +# 100 + 50 - 30 + 10 = 130 +sat -set a 100 -set b 50 -set c 30 -set d 10 -prove y 130 + +# 1 + 1 - 255 + 1 = 4 +sat -set a 1 -set b 1 -set c 255 -set d 1 -prove y 4 + +log "sub_mixed vectors: ok" + +design -reset + +read_verilog sub_all.v +hierarchy -top sub_all +proc; opt_clean +csa_tree +opt_clean + +# 100 - 10 - 20 - 30 = 40 +sat -set a 100 -set b 10 -set c 20 -set d 30 -prove y 40 + +# 0 - 0 - 0 - 0 = 0 +sat -set a 0 -set b 0 -set c 0 -set d 0 -prove y 0 + +# 255 - 1 - 1 - 1 = 252 +sat -set a 255 -set b 1 -set c 1 -set d 1 -prove y 252 + +log "sub_all vectors: ok" diff --git a/tests/csa_tree/csa_tree_synth.ys b/tests/csa_tree/csa_tree_synth.ys index e03580217..eb1e12a0f 100644 --- a/tests/csa_tree/csa_tree_synth.ys +++ b/tests/csa_tree/csa_tree_synth.ys @@ -1,17 +1,20 @@ +# ABC synthesis comparison: with vs without csa_tree + # Baseline: no csa_tree read_verilog abc_bench_add8.v hierarchy -top abc_bench_add8 proc; opt - -# Baseline synth techmap abc -g AND,OR,XOR opt_clean stat -design -save baseline + +# Baseline is typically 238 gates — assert it's above 235 +select -assert-min 236 t:$_AND_ t:$_OR_ t:$_XOR_ %u + +design -reset # With csa_tree -design -reset read_verilog abc_bench_add8.v hierarchy -top abc_bench_add8 proc; opt @@ -21,25 +24,36 @@ abc -g AND,OR,XOR opt_clean stat -select -assert-max 250 t:$_AND_ t:$_OR_ t:$_XOR_ t:$_NOT_ %u -design -save csa_result +# CSA was giving ~232 gates, assert rough equality +select -assert-max 235 t:$_AND_ t:$_OR_ t:$_XOR_ %u -# Depth comparison via ABC design -reset + +# Depth-optimal: baseline read_verilog abc_bench_add8.v hierarchy -top abc_bench_add8 proc; opt techmap abc -D 1 +opt_clean stat -log "baseline depth mapping complete" + +# Baseline depth-optimal is ~243 cells +select -assert-min 240 t:$_AND_ t:$_NAND_ t:$_OR_ t:$_NOR_ t:$_XOR_ t:$_XNOR_ t:$_NOT_ %u design -reset + +# Depth-optimal: with csa_tree read_verilog abc_bench_add8.v hierarchy -top abc_bench_add8 proc; opt csa_tree techmap abc -D 1 +opt_clean stat -log "CSA depth mapping complete" + +# CSA depth-optimal is ~232 cells, must be under baseline +select -assert-max 236 t:$_AND_ t:$_NAND_ t:$_OR_ t:$_NOR_ t:$_XOR_ t:$_XNOR_ t:$_NOT_ %u + +log "CSA depth and gate count: ok" diff --git a/tests/csa_tree/csa_tree_two_chains.ys b/tests/csa_tree/csa_tree_two_chains.ys index 10fbe8b15..bc852071b 100644 --- a/tests/csa_tree/csa_tree_two_chains.ys +++ b/tests/csa_tree/csa_tree_two_chains.ys @@ -5,5 +5,4 @@ equiv_opt csa_tree design -load postopt select -assert-min 2 t:$fa -select -assert-count 2 t:$add - +select -assert-count 2 t:$add \ No newline at end of file diff --git a/tests/csa_tree/csa_tree_wide_output.ys b/tests/csa_tree/csa_tree_wide_output.ys index 84cd13bd7..82003ff63 100644 --- a/tests/csa_tree/csa_tree_wide_output.ys +++ b/tests/csa_tree/csa_tree_wide_output.ys @@ -5,5 +5,4 @@ equiv_opt csa_tree design -load postopt select -assert-min 1 t:$fa -select -assert-count 1 t:$add - +select -assert-count 1 t:$add \ No newline at end of file diff --git a/tests/csa_tree/equiv_sub_narrow.v b/tests/csa_tree/equiv_sub_narrow.v new file mode 100644 index 000000000..3e40ee0bd --- /dev/null +++ b/tests/csa_tree/equiv_sub_narrow.v @@ -0,0 +1,27 @@ +module equiv_sub_mixed( + input [3:0] a, b, c, d, + output [3:0] y +); + assign y = a + b - c + d; +endmodule + +module equiv_sub_all( + input [3:0] a, b, c, d, + output [3:0] y +); + assign y = a - b - c - d; +endmodule + +module equiv_sub_3op( + input [3:0] a, b, c, + output [3:0] y +); + assign y = a - b + c; +endmodule + +module equiv_sub_signed( + input signed [3:0] a, b, c, d, + output signed [5:0] y +); + assign y = a + b - c - d; +endmodule diff --git a/tests/csa_tree/sub_2op_neg.v b/tests/csa_tree/sub_2op_neg.v new file mode 100644 index 000000000..33a320cef --- /dev/null +++ b/tests/csa_tree/sub_2op_neg.v @@ -0,0 +1,6 @@ +module sub_2op_neg( + input [7:0] a, b, + output [7:0] y +); + assign y = a - b; +endmodule diff --git a/tests/csa_tree/sub_3op.v b/tests/csa_tree/sub_3op.v new file mode 100644 index 000000000..270605e6f --- /dev/null +++ b/tests/csa_tree/sub_3op.v @@ -0,0 +1,6 @@ +module sub_3op( + input [7:0] a, b, c, + output [7:0] y +); + assign y = a - b + c; +endmodule diff --git a/tests/csa_tree/sub_5op.v b/tests/csa_tree/sub_5op.v new file mode 100644 index 000000000..1c18adab0 --- /dev/null +++ b/tests/csa_tree/sub_5op.v @@ -0,0 +1,6 @@ +module sub_5op( + input [11:0] a, b, c, d, e, + output [11:0] y +); + assign y = a - b + c - d + e; +endmodule diff --git a/tests/csa_tree/sub_all.v b/tests/csa_tree/sub_all.v new file mode 100644 index 000000000..33897159d --- /dev/null +++ b/tests/csa_tree/sub_all.v @@ -0,0 +1,6 @@ +module sub_all( + input [7:0] a, b, c, d, + output [7:0] y +); + assign y = a - b - c - d; +endmodule diff --git a/tests/csa_tree/sub_mixed.v b/tests/csa_tree/sub_mixed.v new file mode 100644 index 000000000..f711da3fc --- /dev/null +++ b/tests/csa_tree/sub_mixed.v @@ -0,0 +1,6 @@ +module sub_mixed( + input [7:0] a, b, c, d, + output [7:0] y +); + assign y = a + b - c + d; +endmodule diff --git a/tests/csa_tree/sub_signed.v b/tests/csa_tree/sub_signed.v new file mode 100644 index 000000000..6971840ab --- /dev/null +++ b/tests/csa_tree/sub_signed.v @@ -0,0 +1,6 @@ +module sub_signed( + input signed [7:0] a, b, c, d, + output signed [9:0] y +); + assign y = a + b - c - d; +endmodule From cfee6bb4af1c88e49bb19dbb21e8065fed42db93 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 13 Mar 2026 13:22:24 +0100 Subject: [PATCH 022/176] Add more robsutness tests. --- tests/csa_tree/csa_tree_idempotent.ys | 17 +++++++++ tests/csa_tree/csa_tree_sub_double_neg.ys | 44 +++++++++++++++++++++++ tests/csa_tree/equiv_sub_double_neg.v | 7 ++++ tests/csa_tree/sub_double_neg.v | 7 ++++ 4 files changed, 75 insertions(+) create mode 100644 tests/csa_tree/csa_tree_idempotent.ys create mode 100644 tests/csa_tree/csa_tree_sub_double_neg.ys create mode 100644 tests/csa_tree/equiv_sub_double_neg.v create mode 100644 tests/csa_tree/sub_double_neg.v diff --git a/tests/csa_tree/csa_tree_idempotent.ys b/tests/csa_tree/csa_tree_idempotent.ys new file mode 100644 index 000000000..4bc7dc354 --- /dev/null +++ b/tests/csa_tree/csa_tree_idempotent.ys @@ -0,0 +1,17 @@ +# Running csa_tree twice, verify nothing changes on second run + +read_verilog add_chain_8.v +hierarchy -auto-top +proc; opt_clean + +csa_tree +stat +select -assert-min 1 t:$fa +select -assert-count 1 t:$add + +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_double_neg.ys b/tests/csa_tree/csa_tree_sub_double_neg.ys new file mode 100644 index 000000000..f3911aee3 --- /dev/null +++ b/tests/csa_tree/csa_tree_sub_double_neg.ys @@ -0,0 +1,44 @@ +# Test double negation + +read_verilog sub_double_neg.v +hierarchy -auto-top +proc; opt_clean +csa_tree +stat + +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +select -assert-none t:$sub + +design -reset + +# equiv_opt on narrow version +read_verilog equiv_sub_double_neg.v +hierarchy -top equiv_sub_double_neg +proc; opt_clean +equiv_opt csa_tree +design -load postopt +select -assert-min 1 t:$fa +select -assert-count 1 t:$add +design -reset + +# sat-prove on full width +read_verilog sub_double_neg.v +hierarchy -top sub_double_neg +proc; opt_clean +csa_tree +opt_clean + +# 10 - (30 - 20) = 10 - 10 = 0 +sat -set a 30 -set b 20 -set c 10 -prove y 0 + +# 100 - (50 - 25) = 100 - 25 = 75 +sat -set a 50 -set b 25 -set c 100 -prove y 75 + +# 0 - (0 - 0) = 0 +sat -set a 0 -set b 0 -set c 0 -prove y 0 + +# 1 - (255 - 1) = 1 - 254 = 3 +sat -set a 255 -set b 1 -set c 1 -prove y 3 + +log "double negation: ok" diff --git a/tests/csa_tree/equiv_sub_double_neg.v b/tests/csa_tree/equiv_sub_double_neg.v new file mode 100644 index 000000000..8d03da23f --- /dev/null +++ b/tests/csa_tree/equiv_sub_double_neg.v @@ -0,0 +1,7 @@ +module equiv_sub_double_neg( + input [3:0] a, b, c, + output [3:0] y +); + wire [3:0] ab = a - b; + assign y = c - ab; +endmodule diff --git a/tests/csa_tree/sub_double_neg.v b/tests/csa_tree/sub_double_neg.v new file mode 100644 index 000000000..7172ccd09 --- /dev/null +++ b/tests/csa_tree/sub_double_neg.v @@ -0,0 +1,7 @@ +module sub_double_neg( + input [7:0] a, b, c, + output [7:0] y +); + wire [7:0] ab = a - b; + assign y = c - ab; +endmodule From b64b75db7a0838187964eeb5111ad8d45045acc0 Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 16 Mar 2026 15:39:54 +0100 Subject: [PATCH 023/176] Add csa to synth. --- techlibs/common/synth.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 0623bf43d..d073cd348 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -67,6 +67,10 @@ struct SynthPass : public ScriptPass { log(" -booth\n"); log(" run the booth pass to map $mul to Booth encoded multipliers\n"); log("\n"); + log(" -csa\n"); + log(" run the csa_tree pass to convert $add/$sub chains to\n"); + log(" carry-save adder trees.\n"); + log("\n"); log(" -noalumacc\n"); log(" do not run 'alumacc' pass. i.e. keep arithmetic operators in\n"); log(" their direct form ($add, $sub, etc.).\n"); @@ -108,7 +112,7 @@ struct SynthPass : public ScriptPass { } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, hieropt, relative_share; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, csa, hieropt, relative_share; int lut; std::vector techmap_maps; @@ -127,6 +131,7 @@ struct SynthPass : public ScriptPass { noshare = false; flowmap = false; booth = false; + csa = false; hieropt = false; relative_share = false; abc = "abc"; @@ -187,7 +192,10 @@ struct SynthPass : public ScriptPass { booth = true; continue; } - + if (args[argidx] == "-csa") { + csa = true; + continue; + } if (args[argidx] == "-nordff") { memory_opts += " -nordff"; continue; @@ -287,6 +295,8 @@ struct SynthPass : public ScriptPass { run(stringf("%s -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", techmap_cmd, lut)); if (booth || help_mode) run("booth", " (if -booth)"); + if (csa || help_mode) + run("csa_tree", " (if -csa)"); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); if (!noshare) @@ -301,7 +311,7 @@ struct SynthPass : public ScriptPass { run("memory_map"); run("opt -full"); if (help_mode) { - run(techmap_cmd, " (unless -extra-map)"); + run(techmap_cmd, " (unless -extra-map)"); run(techmap_cmd + " -map +/techmap.v -map ", " (if -extra-map)"); } else { std::string techmap_opts; From ab1c423692a723f4dc1f97394032132e30f757c2 Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 16 Mar 2026 16:23:42 +0100 Subject: [PATCH 024/176] Tighten csa tests. --- tests/csa_tree/csa_tree_16input.ys | 2 +- tests/csa_tree/csa_tree_1bit.ys | 4 +--- tests/csa_tree/csa_tree_1bit_wide_out.ys | 2 +- tests/csa_tree/csa_tree_3input.ys | 7 ++----- tests/csa_tree/csa_tree_5input.ys | 9 +++------ tests/csa_tree/csa_tree_8input.ys | 3 +-- tests/csa_tree/csa_tree_const.ys | 7 +++---- tests/csa_tree/csa_tree_equiv.ys | 22 +++++++++++----------- tests/csa_tree/csa_tree_fir.ys | 8 ++++---- tests/csa_tree/csa_tree_idempotent.ys | 6 ++---- tests/csa_tree/csa_tree_mixed_widths.ys | 7 +++---- tests/csa_tree/csa_tree_partial_chain.ys | 4 ++-- tests/csa_tree/csa_tree_repeated.ys | 2 +- tests/csa_tree/csa_tree_signed.ys | 7 +++---- tests/csa_tree/csa_tree_sub_3op.ys | 5 ++--- tests/csa_tree/csa_tree_sub_5op.ys | 3 ++- tests/csa_tree/csa_tree_sub_all.ys | 3 ++- tests/csa_tree/csa_tree_sub_double_neg.ys | 14 ++++++-------- tests/csa_tree/csa_tree_sub_equiv.ys | 10 ++++------ tests/csa_tree/csa_tree_sub_mixed.ys | 5 ++--- tests/csa_tree/csa_tree_sub_signed.ys | 3 ++- tests/csa_tree/csa_tree_two_chains.ys | 8 ++++---- tests/csa_tree/csa_tree_wide_output.ys | 8 ++++---- 23 files changed, 66 insertions(+), 83 deletions(-) diff --git a/tests/csa_tree/csa_tree_16input.ys b/tests/csa_tree/csa_tree_16input.ys index 230d5f845..46f51d44c 100644 --- a/tests/csa_tree/csa_tree_16input.ys +++ b/tests/csa_tree/csa_tree_16input.ys @@ -4,5 +4,5 @@ proc; opt_clean csa_tree stat -select -assert-min 5 t:$fa +select -assert-count 14 t:$fa select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_1bit.ys b/tests/csa_tree/csa_tree_1bit.ys index 4245f3d24..4c1f7745a 100644 --- a/tests/csa_tree/csa_tree_1bit.ys +++ b/tests/csa_tree/csa_tree_1bit.ys @@ -1,10 +1,8 @@ -# Test csa_tree with single-bit operands — carry shift edge case - read_verilog add_1bit.v hierarchy -auto-top proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 1 t:$fa select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_1bit_wide_out.ys b/tests/csa_tree/csa_tree_1bit_wide_out.ys index 5e2605340..675fbc0a3 100644 --- a/tests/csa_tree/csa_tree_1bit_wide_out.ys +++ b/tests/csa_tree/csa_tree_1bit_wide_out.ys @@ -4,5 +4,5 @@ proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_3input.ys b/tests/csa_tree/csa_tree_3input.ys index 68ff2ff2e..9e7c9aaf2 100644 --- a/tests/csa_tree/csa_tree_3input.ys +++ b/tests/csa_tree/csa_tree_3input.ys @@ -1,11 +1,8 @@ -# Test csa_tree on 3-operand chain — minimal trigger case - read_verilog add_chain_3.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat select -assert-count 1 t:$fa select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_5input.ys b/tests/csa_tree/csa_tree_5input.ys index dadea092f..ef26e21ce 100644 --- a/tests/csa_tree/csa_tree_5input.ys +++ b/tests/csa_tree/csa_tree_5input.ys @@ -1,11 +1,8 @@ -# Test csa_tree with 5 operands — tree with remainders - read_verilog add_chain_5.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat -select -assert-min 2 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_8input.ys b/tests/csa_tree/csa_tree_8input.ys index 23d2d698a..fc5148edf 100644 --- a/tests/csa_tree/csa_tree_8input.ys +++ b/tests/csa_tree/csa_tree_8input.ys @@ -4,6 +4,5 @@ proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 6 t:$fa select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_const.ys b/tests/csa_tree/csa_tree_const.ys index 75d0bc1d7..be53bba11 100644 --- a/tests/csa_tree/csa_tree_const.ys +++ b/tests/csa_tree/csa_tree_const.ys @@ -1,9 +1,8 @@ read_verilog add_with_const.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_equiv.ys b/tests/csa_tree/csa_tree_equiv.ys index ac976e1b3..360b9d30e 100644 --- a/tests/csa_tree/csa_tree_equiv.ys +++ b/tests/csa_tree/csa_tree_equiv.ys @@ -1,4 +1,4 @@ -# Test bit correctness +# Equivalence tests using narrow operands read_verilog equiv_narrow.v hierarchy -top equiv_add3 @@ -8,34 +8,34 @@ design -load postopt select -assert-count 1 t:$fa select -assert-count 1 t:$add design -reset -log "equiv_add3: ok" +log "equiv_add3" read_verilog equiv_narrow.v hierarchy -top equiv_add4 proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset -log "equiv_add4: ok" +log "equiv_add4" read_verilog equiv_narrow.v hierarchy -top equiv_add5 proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 2 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add design -reset -log "equiv_add5: ok" +log "equiv_add5" read_verilog equiv_narrow.v hierarchy -top equiv_add8 proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 6 t:$fa select -assert-count 1 t:$add design -reset log "equiv_add8: ok" @@ -45,7 +45,7 @@ hierarchy -top equiv_signed proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset log "equiv_signed: ok" @@ -55,7 +55,7 @@ hierarchy -top equiv_mixed_w proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 1 t:$fa select -assert-count 1 t:$add design -reset log "equiv_mixed_w: ok" @@ -65,7 +65,7 @@ hierarchy -top equiv_repeated proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset log "equiv_repeated: ok" @@ -75,7 +75,7 @@ hierarchy -top equiv_1bit_wide proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset log "equiv_1bit_wide: ok" diff --git a/tests/csa_tree/csa_tree_fir.ys b/tests/csa_tree/csa_tree_fir.ys index 59aac98b0..89d60af03 100644 --- a/tests/csa_tree/csa_tree_fir.ys +++ b/tests/csa_tree/csa_tree_fir.ys @@ -1,8 +1,8 @@ read_verilog fir_4tap.v hierarchy -auto-top proc; opt_clean -equiv_opt -async2sync csa_tree -design -load postopt - -select -assert-min 1 t:$fa +csa_tree +stat +select -assert-count 2 t:$fa +select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_idempotent.ys b/tests/csa_tree/csa_tree_idempotent.ys index 4bc7dc354..138edb4ae 100644 --- a/tests/csa_tree/csa_tree_idempotent.ys +++ b/tests/csa_tree/csa_tree_idempotent.ys @@ -1,17 +1,15 @@ -# Running csa_tree twice, verify nothing changes on second run - read_verilog add_chain_8.v hierarchy -auto-top proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 6 t:$fa select -assert-count 1 t:$add csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 6 t:$fa select -assert-count 1 t:$add select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_mixed_widths.ys b/tests/csa_tree/csa_tree_mixed_widths.ys index 1cecae201..e324c17ca 100644 --- a/tests/csa_tree/csa_tree_mixed_widths.ys +++ b/tests/csa_tree/csa_tree_mixed_widths.ys @@ -1,9 +1,8 @@ read_verilog add_mixed_widths.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_partial_chain.ys b/tests/csa_tree/csa_tree_partial_chain.ys index 3852c4f9d..ba857292e 100644 --- a/tests/csa_tree/csa_tree_partial_chain.ys +++ b/tests/csa_tree/csa_tree_partial_chain.ys @@ -4,5 +4,5 @@ proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa -select -assert-min 2 t:$add +select -assert-count 2 t:$fa +select -assert-count 2 t:$add diff --git a/tests/csa_tree/csa_tree_repeated.ys b/tests/csa_tree/csa_tree_repeated.ys index 7e1c2ec51..b4581d2b4 100644 --- a/tests/csa_tree/csa_tree_repeated.ys +++ b/tests/csa_tree/csa_tree_repeated.ys @@ -4,5 +4,5 @@ proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_signed.ys b/tests/csa_tree/csa_tree_signed.ys index 7e29cc123..1093f7330 100644 --- a/tests/csa_tree/csa_tree_signed.ys +++ b/tests/csa_tree/csa_tree_signed.ys @@ -1,9 +1,8 @@ read_verilog add_signed.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_sub_3op.ys b/tests/csa_tree/csa_tree_sub_3op.ys index 70801d30c..536f65bd7 100644 --- a/tests/csa_tree/csa_tree_sub_3op.ys +++ b/tests/csa_tree/csa_tree_sub_3op.ys @@ -1,11 +1,10 @@ -# Test minimal sub chain - read_verilog sub_3op.v hierarchy -auto-top proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add +select -assert-count 1 t:$not select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_5op.ys b/tests/csa_tree/csa_tree_sub_5op.ys index 62c4a80ff..b40c97084 100644 --- a/tests/csa_tree/csa_tree_sub_5op.ys +++ b/tests/csa_tree/csa_tree_sub_5op.ys @@ -4,6 +4,7 @@ proc; opt_clean csa_tree stat -select -assert-min 2 t:$fa +select -assert-count 4 t:$fa select -assert-count 1 t:$add +select -assert-count 2 t:$not select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_all.ys b/tests/csa_tree/csa_tree_sub_all.ys index 8e47bb0db..ba0503462 100644 --- a/tests/csa_tree/csa_tree_sub_all.ys +++ b/tests/csa_tree/csa_tree_sub_all.ys @@ -4,6 +4,7 @@ proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add +select -assert-count 3 t:$not select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_double_neg.ys b/tests/csa_tree/csa_tree_sub_double_neg.ys index f3911aee3..b3a524abb 100644 --- a/tests/csa_tree/csa_tree_sub_double_neg.ys +++ b/tests/csa_tree/csa_tree_sub_double_neg.ys @@ -1,13 +1,12 @@ -# Test double negation - read_verilog sub_double_neg.v hierarchy -auto-top proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add +select -assert-count 1 t:$not select -assert-none t:$sub design -reset @@ -18,27 +17,26 @@ hierarchy -top equiv_sub_double_neg proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset -# sat-prove on full width read_verilog sub_double_neg.v hierarchy -top sub_double_neg proc; opt_clean csa_tree opt_clean -# 10 - (30 - 20) = 10 - 10 = 0 +# 10 - (30 - 20) = 0 sat -set a 30 -set b 20 -set c 10 -prove y 0 -# 100 - (50 - 25) = 100 - 25 = 75 +# 100 - (50 - 25) = 75 sat -set a 50 -set b 25 -set c 100 -prove y 75 # 0 - (0 - 0) = 0 sat -set a 0 -set b 0 -set c 0 -prove y 0 -# 1 - (255 - 1) = 1 - 254 = 3 +# 1 - (255 - 1) = 3 sat -set a 255 -set b 1 -set c 1 -prove y 3 log "double negation: ok" diff --git a/tests/csa_tree/csa_tree_sub_equiv.ys b/tests/csa_tree/csa_tree_sub_equiv.ys index b1be6bebe..7138b010c 100644 --- a/tests/csa_tree/csa_tree_sub_equiv.ys +++ b/tests/csa_tree/csa_tree_sub_equiv.ys @@ -1,11 +1,9 @@ -# Test equiv_opt on narrow sub designs - read_verilog equiv_sub_narrow.v hierarchy -top equiv_sub_mixed proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add design -reset log "equiv_sub_mixed: ok" @@ -15,7 +13,7 @@ hierarchy -top equiv_sub_all proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add design -reset log "equiv_sub_all: ok" @@ -25,7 +23,7 @@ hierarchy -top equiv_sub_3op proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset log "equiv_sub_3op: ok" @@ -35,7 +33,7 @@ hierarchy -top equiv_sub_signed proc; opt_clean equiv_opt csa_tree design -load postopt -select -assert-min 1 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add design -reset log "equiv_sub_signed: ok" diff --git a/tests/csa_tree/csa_tree_sub_mixed.ys b/tests/csa_tree/csa_tree_sub_mixed.ys index 8fea5f0d2..92e0e1a0d 100644 --- a/tests/csa_tree/csa_tree_sub_mixed.ys +++ b/tests/csa_tree/csa_tree_sub_mixed.ys @@ -1,11 +1,10 @@ -# Test mixed csa chain - read_verilog sub_mixed.v hierarchy -auto-top proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add +select -assert-count 1 t:$not select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_sub_signed.ys b/tests/csa_tree/csa_tree_sub_signed.ys index 78caf5a2e..ad3b0cfb4 100644 --- a/tests/csa_tree/csa_tree_sub_signed.ys +++ b/tests/csa_tree/csa_tree_sub_signed.ys @@ -4,6 +4,7 @@ proc; opt_clean csa_tree stat -select -assert-min 1 t:$fa +select -assert-count 3 t:$fa select -assert-count 1 t:$add +select -assert-count 2 t:$not select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_two_chains.ys b/tests/csa_tree/csa_tree_two_chains.ys index bc852071b..42d5c87b9 100644 --- a/tests/csa_tree/csa_tree_two_chains.ys +++ b/tests/csa_tree/csa_tree_two_chains.ys @@ -1,8 +1,8 @@ read_verilog add_two_chains.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat -select -assert-min 2 t:$fa -select -assert-count 2 t:$add \ No newline at end of file +select -assert-count 4 t:$fa +select -assert-count 2 t:$add diff --git a/tests/csa_tree/csa_tree_wide_output.ys b/tests/csa_tree/csa_tree_wide_output.ys index 82003ff63..ccb160f5c 100644 --- a/tests/csa_tree/csa_tree_wide_output.ys +++ b/tests/csa_tree/csa_tree_wide_output.ys @@ -1,8 +1,8 @@ read_verilog add_wide_output.v hierarchy -auto-top proc; opt_clean -equiv_opt csa_tree -design -load postopt +csa_tree +stat -select -assert-min 1 t:$fa -select -assert-count 1 t:$add \ No newline at end of file +select -assert-count 2 t:$fa +select -assert-count 1 t:$add From fc9adae9a2770074ea4b51012e3cfef7edf15aa8 Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 18 Mar 2026 12:36:31 +0100 Subject: [PATCH 025/176] Consolidate csa tests. --- tests/csa_tree/abc_bench_add8.v | 6 - tests/csa_tree/add_1bit.v | 9 -- tests/csa_tree/add_1bit_wide_out.v | 6 - tests/csa_tree/add_chain_16.v | 7 - tests/csa_tree/add_chain_2_neg.v | 8 -- tests/csa_tree/add_chain_3.v | 9 -- tests/csa_tree/add_chain_5.v | 7 - tests/csa_tree/add_chain_8.v | 7 - tests/csa_tree/add_mixed_widths.v | 10 -- tests/csa_tree/add_multi_const.v | 6 - tests/csa_tree/add_multi_fanout.v | 10 -- tests/csa_tree/add_partial_chain.v | 9 -- tests/csa_tree/add_repeated.v | 6 - tests/csa_tree/add_signed.v | 6 - tests/csa_tree/add_two_chains.v | 9 -- tests/csa_tree/add_wide_output.v | 6 - tests/csa_tree/add_with_const.v | 7 - tests/csa_tree/csa_tree_16input.ys | 8 -- tests/csa_tree/csa_tree_1bit.ys | 8 -- tests/csa_tree/csa_tree_1bit_wide_out.ys | 8 -- tests/csa_tree/csa_tree_2input_neg.ys | 11 -- tests/csa_tree/csa_tree_3input.ys | 8 -- tests/csa_tree/csa_tree_5input.ys | 8 -- tests/csa_tree/csa_tree_8input.ys | 8 -- tests/csa_tree/csa_tree_add_chains.ys | 61 ++++++++ tests/csa_tree/csa_tree_const.ys | 8 -- tests/csa_tree/csa_tree_edge_cases.ys | 147 +++++++++++++++++++ tests/csa_tree/csa_tree_equiv.ys | 165 +++++++++++++++++----- tests/csa_tree/csa_tree_fir.ys | 8 -- tests/csa_tree/csa_tree_idempotent.ys | 14 +- tests/csa_tree/csa_tree_mixed_widths.ys | 8 -- tests/csa_tree/csa_tree_multi_const.ys | 9 -- tests/csa_tree/csa_tree_multi_fanout.ys | 8 -- tests/csa_tree/csa_tree_negative.ys | 77 ++++++++++ tests/csa_tree/csa_tree_partial_chain.ys | 8 -- tests/csa_tree/csa_tree_repeated.ys | 8 -- tests/csa_tree/csa_tree_signed.ys | 8 -- tests/csa_tree/csa_tree_sim.ys | 77 ++++++++-- tests/csa_tree/csa_tree_sub_2op_neg.ys | 8 -- tests/csa_tree/csa_tree_sub_3op.ys | 10 -- tests/csa_tree/csa_tree_sub_5op.ys | 10 -- tests/csa_tree/csa_tree_sub_all.ys | 10 -- tests/csa_tree/csa_tree_sub_chains.ys | 102 +++++++++++++ tests/csa_tree/csa_tree_sub_double_neg.ys | 42 ------ tests/csa_tree/csa_tree_sub_equiv.ys | 39 ----- tests/csa_tree/csa_tree_sub_mixed.ys | 10 -- tests/csa_tree/csa_tree_sub_signed.ys | 10 -- tests/csa_tree/csa_tree_sub_sim.ys | 38 ----- tests/csa_tree/csa_tree_synth.ys | 87 +++++++----- tests/csa_tree/csa_tree_two_chains.ys | 8 -- tests/csa_tree/csa_tree_wide_output.ys | 8 -- tests/csa_tree/equiv_narrow.v | 59 -------- tests/csa_tree/equiv_sub_double_neg.v | 7 - tests/csa_tree/equiv_sub_narrow.v | 27 ---- tests/csa_tree/fir_4tap.v | 24 ---- tests/csa_tree/run-test.sh | 4 +- tests/csa_tree/sim_add4.v | 6 - tests/csa_tree/sub_2op_neg.v | 6 - tests/csa_tree/sub_3op.v | 6 - tests/csa_tree/sub_5op.v | 6 - tests/csa_tree/sub_all.v | 6 - tests/csa_tree/sub_double_neg.v | 7 - tests/csa_tree/sub_mixed.v | 6 - tests/csa_tree/sub_signed.v | 6 - 64 files changed, 641 insertions(+), 704 deletions(-) delete mode 100644 tests/csa_tree/abc_bench_add8.v delete mode 100644 tests/csa_tree/add_1bit.v delete mode 100644 tests/csa_tree/add_1bit_wide_out.v delete mode 100644 tests/csa_tree/add_chain_16.v delete mode 100644 tests/csa_tree/add_chain_2_neg.v delete mode 100644 tests/csa_tree/add_chain_3.v delete mode 100644 tests/csa_tree/add_chain_5.v delete mode 100644 tests/csa_tree/add_chain_8.v delete mode 100644 tests/csa_tree/add_mixed_widths.v delete mode 100644 tests/csa_tree/add_multi_const.v delete mode 100644 tests/csa_tree/add_multi_fanout.v delete mode 100644 tests/csa_tree/add_partial_chain.v delete mode 100644 tests/csa_tree/add_repeated.v delete mode 100644 tests/csa_tree/add_signed.v delete mode 100644 tests/csa_tree/add_two_chains.v delete mode 100644 tests/csa_tree/add_wide_output.v delete mode 100644 tests/csa_tree/add_with_const.v delete mode 100644 tests/csa_tree/csa_tree_16input.ys delete mode 100644 tests/csa_tree/csa_tree_1bit.ys delete mode 100644 tests/csa_tree/csa_tree_1bit_wide_out.ys delete mode 100644 tests/csa_tree/csa_tree_2input_neg.ys delete mode 100644 tests/csa_tree/csa_tree_3input.ys delete mode 100644 tests/csa_tree/csa_tree_5input.ys delete mode 100644 tests/csa_tree/csa_tree_8input.ys create mode 100644 tests/csa_tree/csa_tree_add_chains.ys delete mode 100644 tests/csa_tree/csa_tree_const.ys create mode 100644 tests/csa_tree/csa_tree_edge_cases.ys delete mode 100644 tests/csa_tree/csa_tree_fir.ys delete mode 100644 tests/csa_tree/csa_tree_mixed_widths.ys delete mode 100644 tests/csa_tree/csa_tree_multi_const.ys delete mode 100644 tests/csa_tree/csa_tree_multi_fanout.ys create mode 100644 tests/csa_tree/csa_tree_negative.ys delete mode 100644 tests/csa_tree/csa_tree_partial_chain.ys delete mode 100644 tests/csa_tree/csa_tree_repeated.ys delete mode 100644 tests/csa_tree/csa_tree_signed.ys delete mode 100644 tests/csa_tree/csa_tree_sub_2op_neg.ys delete mode 100644 tests/csa_tree/csa_tree_sub_3op.ys delete mode 100644 tests/csa_tree/csa_tree_sub_5op.ys delete mode 100644 tests/csa_tree/csa_tree_sub_all.ys create mode 100644 tests/csa_tree/csa_tree_sub_chains.ys delete mode 100644 tests/csa_tree/csa_tree_sub_double_neg.ys delete mode 100644 tests/csa_tree/csa_tree_sub_equiv.ys delete mode 100644 tests/csa_tree/csa_tree_sub_mixed.ys delete mode 100644 tests/csa_tree/csa_tree_sub_signed.ys delete mode 100644 tests/csa_tree/csa_tree_sub_sim.ys delete mode 100644 tests/csa_tree/csa_tree_two_chains.ys delete mode 100644 tests/csa_tree/csa_tree_wide_output.ys delete mode 100644 tests/csa_tree/equiv_narrow.v delete mode 100644 tests/csa_tree/equiv_sub_double_neg.v delete mode 100644 tests/csa_tree/equiv_sub_narrow.v delete mode 100644 tests/csa_tree/fir_4tap.v delete mode 100644 tests/csa_tree/sim_add4.v delete mode 100644 tests/csa_tree/sub_2op_neg.v delete mode 100644 tests/csa_tree/sub_3op.v delete mode 100644 tests/csa_tree/sub_5op.v delete mode 100644 tests/csa_tree/sub_all.v delete mode 100644 tests/csa_tree/sub_double_neg.v delete mode 100644 tests/csa_tree/sub_mixed.v delete mode 100644 tests/csa_tree/sub_signed.v diff --git a/tests/csa_tree/abc_bench_add8.v b/tests/csa_tree/abc_bench_add8.v deleted file mode 100644 index 7e61007c5..000000000 --- a/tests/csa_tree/abc_bench_add8.v +++ /dev/null @@ -1,6 +0,0 @@ -module abc_bench_add8( - input [7:0] a, b, c, d, e, f, g, h, - output [7:0] y -); - assign y = a + b + c + d + e + f + g + h; -endmodule diff --git a/tests/csa_tree/add_1bit.v b/tests/csa_tree/add_1bit.v deleted file mode 100644 index e4b93e8c0..000000000 --- a/tests/csa_tree/add_1bit.v +++ /dev/null @@ -1,9 +0,0 @@ -// Edge case for carry shifting - -module add_1bit( - input a, b, c, - output [1:0] y -); - assign y = a + b + c; -endmodule - diff --git a/tests/csa_tree/add_1bit_wide_out.v b/tests/csa_tree/add_1bit_wide_out.v deleted file mode 100644 index e1a6ceb51..000000000 --- a/tests/csa_tree/add_1bit_wide_out.v +++ /dev/null @@ -1,6 +0,0 @@ -module add_1bit_wide_out( - input a, b, c, d, - output [3:0] y -); - assign y = a + b + c + d; -endmodule diff --git a/tests/csa_tree/add_chain_16.v b/tests/csa_tree/add_chain_16.v deleted file mode 100644 index 0a1f12f8c..000000000 --- a/tests/csa_tree/add_chain_16.v +++ /dev/null @@ -1,7 +0,0 @@ -module add_chain_16( - input [15:0] a0, a1, a2, a3, a4, a5, a6, a7, - input [15:0] a8, a9, a10, a11, a12, a13, a14, a15, - output [15:0] y -); - assign y = a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15; -endmodule diff --git a/tests/csa_tree/add_chain_2_neg.v b/tests/csa_tree/add_chain_2_neg.v deleted file mode 100644 index 0e2896c78..000000000 --- a/tests/csa_tree/add_chain_2_neg.v +++ /dev/null @@ -1,8 +0,0 @@ -// Shouldnt generate csa tree - -module add_chain_2( - input [7:0] a, b, - output [7:0] y -); - assign y = a + b; -endmodule diff --git a/tests/csa_tree/add_chain_3.v b/tests/csa_tree/add_chain_3.v deleted file mode 100644 index eea529ead..000000000 --- a/tests/csa_tree/add_chain_3.v +++ /dev/null @@ -1,9 +0,0 @@ -// Min chain len - -module add_chain_3( - input [7:0] a, b, c, - output [7:0] y -); - assign y = a + b + c; -endmodule - diff --git a/tests/csa_tree/add_chain_5.v b/tests/csa_tree/add_chain_5.v deleted file mode 100644 index 25fb30e1d..000000000 --- a/tests/csa_tree/add_chain_5.v +++ /dev/null @@ -1,7 +0,0 @@ -module add_chain_5( - input [11:0] a, b, c, d, e, - output [11:0] y -); - assign y = a + b + c + d + e; -endmodule - diff --git a/tests/csa_tree/add_chain_8.v b/tests/csa_tree/add_chain_8.v deleted file mode 100644 index 96adbc37e..000000000 --- a/tests/csa_tree/add_chain_8.v +++ /dev/null @@ -1,7 +0,0 @@ -module add_chain_8( - input [15:0] a, b, c, d, e, f, g, h, - output [15:0] y -); - assign y = a + b + c + d + e + f + g + h; -endmodule - diff --git a/tests/csa_tree/add_mixed_widths.v b/tests/csa_tree/add_mixed_widths.v deleted file mode 100644 index 51836872a..000000000 --- a/tests/csa_tree/add_mixed_widths.v +++ /dev/null @@ -1,10 +0,0 @@ -module add_mixed_widths( - input [7:0] a, - input [3:0] b, - input [15:0] c, - input [7:0] d, - output [15:0] y -); - assign y = a + b + c + d; -endmodule - diff --git a/tests/csa_tree/add_multi_const.v b/tests/csa_tree/add_multi_const.v deleted file mode 100644 index 7da78f9de..000000000 --- a/tests/csa_tree/add_multi_const.v +++ /dev/null @@ -1,6 +0,0 @@ -module add_multi_const( - input [7:0] x, - output [7:0] y -); - assign y = 8'd1 + 8'd2 + 8'd3 + x; -endmodule diff --git a/tests/csa_tree/add_multi_fanout.v b/tests/csa_tree/add_multi_fanout.v deleted file mode 100644 index 4cc7ecab3..000000000 --- a/tests/csa_tree/add_multi_fanout.v +++ /dev/null @@ -1,10 +0,0 @@ -module add_multi_fanout( - input [7:0] a, b, c, - output [7:0] mid, - output [7:0] y -); - wire [7:0] ab = a + b; - assign mid = ab; - assign y = ab + c; -endmodule - diff --git a/tests/csa_tree/add_partial_chain.v b/tests/csa_tree/add_partial_chain.v deleted file mode 100644 index a4f20cfa4..000000000 --- a/tests/csa_tree/add_partial_chain.v +++ /dev/null @@ -1,9 +0,0 @@ -module add_partial_chain( - input [7:0] a, b, c, d, e, - output [7:0] mid, - output [7:0] y -); - wire [7:0] ab = a + b; - assign mid = ab; - assign y = ab + c + d + e; -endmodule diff --git a/tests/csa_tree/add_repeated.v b/tests/csa_tree/add_repeated.v deleted file mode 100644 index e3337097b..000000000 --- a/tests/csa_tree/add_repeated.v +++ /dev/null @@ -1,6 +0,0 @@ -module add_repeated( - input [7:0] a, - output [7:0] y -); - assign y = a + a + a + a; -endmodule diff --git a/tests/csa_tree/add_signed.v b/tests/csa_tree/add_signed.v deleted file mode 100644 index 42b9ca7fd..000000000 --- a/tests/csa_tree/add_signed.v +++ /dev/null @@ -1,6 +0,0 @@ -module add_signed( - input signed [7:0] a, b, c, d, - output signed [9:0] y -); - assign y = a + b + c + d; -endmodule diff --git a/tests/csa_tree/add_two_chains.v b/tests/csa_tree/add_two_chains.v deleted file mode 100644 index d79d9f3d6..000000000 --- a/tests/csa_tree/add_two_chains.v +++ /dev/null @@ -1,9 +0,0 @@ -module add_two_chains( - input [7:0] a, b, c, d, - input [7:0] e, f, g, h, - output [7:0] y1, - output [7:0] y2 -); - assign y1 = a + b + c + d; - assign y2 = e + f + g + h; -endmodule diff --git a/tests/csa_tree/add_wide_output.v b/tests/csa_tree/add_wide_output.v deleted file mode 100644 index 1f0342777..000000000 --- a/tests/csa_tree/add_wide_output.v +++ /dev/null @@ -1,6 +0,0 @@ -module add_wide_output( - input [7:0] a, b, c, d, - output [31:0] y -); - assign y = a + b + c + d; -endmodule diff --git a/tests/csa_tree/add_with_const.v b/tests/csa_tree/add_with_const.v deleted file mode 100644 index 570a399e4..000000000 --- a/tests/csa_tree/add_with_const.v +++ /dev/null @@ -1,7 +0,0 @@ -module add_with_const( - input [7:0] a, b, c, - output [7:0] y -); - assign y = a + b + c + 8'd42; -endmodule - diff --git a/tests/csa_tree/csa_tree_16input.ys b/tests/csa_tree/csa_tree_16input.ys deleted file mode 100644 index 46f51d44c..000000000 --- a/tests/csa_tree/csa_tree_16input.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_chain_16.v -hierarchy -auto-top -proc; opt_clean -csa_tree -stat - -select -assert-count 14 t:$fa -select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_1bit.ys b/tests/csa_tree/csa_tree_1bit.ys deleted file mode 100644 index 4c1f7745a..000000000 --- a/tests/csa_tree/csa_tree_1bit.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_1bit.v -hierarchy -auto-top -proc; opt_clean -csa_tree -stat - -select -assert-count 1 t:$fa -select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_1bit_wide_out.ys b/tests/csa_tree/csa_tree_1bit_wide_out.ys deleted file mode 100644 index 675fbc0a3..000000000 --- a/tests/csa_tree/csa_tree_1bit_wide_out.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_1bit_wide_out.v -hierarchy -auto-top -proc; opt_clean -csa_tree -stat - -select -assert-count 2 t:$fa -select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_2input_neg.ys b/tests/csa_tree/csa_tree_2input_neg.ys deleted file mode 100644 index 810d1d8d9..000000000 --- a/tests/csa_tree/csa_tree_2input_neg.ys +++ /dev/null @@ -1,11 +0,0 @@ -# Test csa_tree on 2-operand — should not trigger - -read_verilog add_chain_2_neg.v -hierarchy -auto-top -proc; opt_clean -equiv_opt csa_tree -design -load postopt - -select -assert-none t:$fa -select -assert-count 1 t:$add - diff --git a/tests/csa_tree/csa_tree_3input.ys b/tests/csa_tree/csa_tree_3input.ys deleted file mode 100644 index 9e7c9aaf2..000000000 --- a/tests/csa_tree/csa_tree_3input.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_chain_3.v -hierarchy -auto-top -proc; opt_clean -csa_tree -stat - -select -assert-count 1 t:$fa -select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_5input.ys b/tests/csa_tree/csa_tree_5input.ys deleted file mode 100644 index ef26e21ce..000000000 --- a/tests/csa_tree/csa_tree_5input.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_chain_5.v -hierarchy -auto-top -proc; opt_clean -csa_tree -stat - -select -assert-count 3 t:$fa -select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_8input.ys b/tests/csa_tree/csa_tree_8input.ys deleted file mode 100644 index fc5148edf..000000000 --- a/tests/csa_tree/csa_tree_8input.ys +++ /dev/null @@ -1,8 +0,0 @@ -read_verilog add_chain_8.v -hierarchy -auto-top -proc; opt_clean -csa_tree -stat - -select -assert-count 6 t:$fa -select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_add_chains.ys b/tests/csa_tree/csa_tree_add_chains.ys new file mode 100644 index 000000000..46e5868a9 --- /dev/null +++ b/tests/csa_tree/csa_tree_add_chains.ys @@ -0,0 +1,61 @@ +read_verilog < Date: Thu, 19 Mar 2026 17:44:56 +0100 Subject: [PATCH 026/176] CSA add support for macc and alu cells. --- passes/opt/csa_tree.cc | 528 ++++++++++++++++++++++++----------------- 1 file changed, 306 insertions(+), 222 deletions(-) diff --git a/passes/opt/csa_tree.cc b/passes/opt/csa_tree.cc index e1a4a9464..de2e28901 100644 --- a/passes/opt/csa_tree.cc +++ b/passes/opt/csa_tree.cc @@ -1,43 +1,102 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/macc.h" #include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct Operand { + SigSpec sig; + bool is_signed; + bool negate; +}; + struct CsaTreeWorker { - Module *module; + Module* module; SigMap sigmap; dict> bit_consumers; dict fanout; - pool all_addsubs; - CsaTreeWorker(Module *module) : module(module), sigmap(module) {} + pool addsub_cells; + pool alu_cells; + pool macc_cells; - struct DepthSig { - SigSpec sig; - int depth; - }; + CsaTreeWorker(Module* module) : module(module), sigmap(module) {} - void find_addsubs() + static bool is_addsub(Cell* cell) { - for (auto cell : module->cells()) - if (cell->type == ID($add) || cell->type == ID($sub)) - all_addsubs.insert(cell); + return cell->type == ID($add) || cell->type == ID($sub); + } + + static bool is_alu(Cell* cell) + { + return cell->type == ID($alu); + } + + static bool is_macc(Cell* cell) + { + return cell->type == ID($macc) || cell->type == ID($macc_v2); + } + + bool alu_is_subtract(Cell* cell) + { + SigSpec bi = sigmap(cell->getPort(ID::BI)); + SigSpec ci = sigmap(cell->getPort(ID::CI)); + return GetSize(bi) == 1 && bi[0] == State::S1 && GetSize(ci) == 1 && ci[0] == State::S1; + } + + bool alu_is_add(Cell* cell) + { + SigSpec bi = sigmap(cell->getPort(ID::BI)); + SigSpec ci = sigmap(cell->getPort(ID::CI)); + return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0; + } + + bool alu_is_chainable(Cell* cell) + { + if (!(alu_is_add(cell) || alu_is_subtract(cell))) + return false; + + for (auto bit : sigmap(cell->getPort(ID::X))) + if (fanout.count(bit) && fanout[bit] > 0) + return false; + for (auto bit : sigmap(cell->getPort(ID::CO))) + if (fanout.count(bit) && fanout[bit] > 0) + return false; + + return true; + } + + bool is_chainable(Cell* cell) + { + return is_addsub(cell) || (is_alu(cell) && alu_is_chainable(cell)); + } + + void classify_cells() + { + for (auto cell : module->cells()) { + if (is_addsub(cell)) + addsub_cells.insert(cell); + else if (is_alu(cell)) + alu_cells.insert(cell); + else if (is_macc(cell)) + macc_cells.insert(cell); + } } void build_fanout_map() { for (auto cell : module->cells()) - for (auto &conn : cell->connections()) + for (auto& conn : cell->connections()) if (cell->input(conn.first)) for (auto bit : sigmap(conn.second)) bit_consumers[bit].insert(cell); - for (auto &pair : bit_consumers) + for (auto& pair : bit_consumers) fanout[pair.first] = pair.second.size(); for (auto wire : module->wires()) @@ -46,10 +105,9 @@ struct CsaTreeWorker fanout[bit]++; } - Cell* single_addsub_consumer(SigSpec sig) + Cell* sole_chainable_consumer(SigSpec sig, const pool& candidates) { Cell* consumer = nullptr; - for (auto bit : sig) { if (!fanout.count(bit) || fanout[bit] != 1) return nullptr; @@ -57,7 +115,7 @@ struct CsaTreeWorker return nullptr; Cell* c = *bit_consumers[bit].begin(); - if (!all_addsubs.count(c)) + if (!candidates.count(c)) return nullptr; if (consumer == nullptr) @@ -65,55 +123,39 @@ struct CsaTreeWorker else if (consumer != c) return nullptr; } - return consumer; } - dict find_addsub_parents() + dict find_parents(const pool& candidates) { dict parent_of; - - for (auto cell : all_addsubs) { - SigSpec y = sigmap(cell->getPort(ID::Y)); - Cell* consumer = single_addsub_consumer(y); - if (consumer != nullptr && consumer != cell) + for (auto cell : candidates) { + Cell* consumer = sole_chainable_consumer( + sigmap(cell->getPort(ID::Y)), candidates); + if (consumer && consumer != cell) parent_of[cell] = consumer; } - return parent_of; } - pool collect_chain(Cell* root, const dict> &children_of) + pool collect_chain(Cell* root, const dict>& children_of) { pool chain; - std::queue worklist; - worklist.push(root); - - while (!worklist.empty()) { - Cell* cur = worklist.front(); - worklist.pop(); - - if (chain.count(cur)) + std::queue q; + q.push(root); + while (!q.empty()) { + Cell* cur = q.front(); q.pop(); + if (!chain.insert(cur).second) continue; - chain.insert(cur); - - if (children_of.count(cur)) - for (auto child : children_of.at(cur)) - worklist.push(child); + auto it = children_of.find(cur); + if (it != children_of.end()) + for (auto child : it->second) + q.push(child); } - return chain; } - bool is_chain_internal(SigSpec sig, const pool &chain_y_bits) - { - for (auto bit : sig) - if (chain_y_bits.count(bit)) - return true; - return false; - } - - pool collect_chain_outputs(const pool &chain) + pool internal_bits(const pool& chain) { pool bits; for (auto cell : chain) @@ -122,54 +164,58 @@ struct CsaTreeWorker return bits; } - struct Operand { - SigSpec sig; - bool is_signed; - bool negate; - }; - - bool is_subtracted_input(Cell* child, Cell* parent) + static bool overlaps(SigSpec sig, const pool& bits) { - if (parent->type != ID($sub)) + for (auto bit : sig) + if (bits.count(bit)) + return true; + return false; + } + + bool feeds_subtracted_port(Cell* child, Cell* parent) + { + bool parent_subtracts; + if (parent->type == ID($sub)) + parent_subtracts = true; + else if (is_alu(parent)) + parent_subtracts = alu_is_subtract(parent); + else return false; - SigSpec child_y = sigmap(child->getPort(ID::Y)); - SigSpec parent_b = sigmap(parent->getPort(ID::B)); + if (!parent_subtracts) + return false; + SigSpec child_y = sigmap(child->getPort(ID::Y)); + SigSpec parent_b = sigmap(parent->getPort(ID::B)); for (auto bit : child_y) for (auto pbit : parent_b) if (bit == pbit) return true; - return false; } - std::vector collect_leaf_operands( - const pool &chain, - const pool &chain_y_bits, + std::vector extract_chain_operands( + const pool& chain, Cell* root, - const dict &parent_of, - int &correction + const dict& parent_of, + int& correction ) { + pool chain_bits = internal_bits(chain); dict negated; negated[root] = false; - std::queue worklist; - worklist.push(root); - - while (!worklist.empty()) { - Cell* cur = worklist.front(); - worklist.pop(); - for (auto cell : chain) { - if (!parent_of.count(cell)) - continue; - if (parent_of.at(cell) != cur) - continue; - if (negated.count(cell)) - continue; - - bool sub_b = is_subtracted_input(cell, cur); - negated[cell] = negated[cur] ^ sub_b; - worklist.push(cell); + { + std::queue q; + q.push(root); + while (!q.empty()) { + Cell* cur = q.front(); q.pop(); + for (auto cell : chain) { + if (!parent_of.count(cell) || parent_of.at(cell) != cur) + continue; + if (negated.count(cell)) + continue; + negated[cell] = negated[cur] ^ feeds_subtracted_port(cell, cur); + q.push(cell); + } } } @@ -177,35 +223,55 @@ struct CsaTreeWorker correction = 0; for (auto cell : chain) { - bool cell_neg = negated.count(cell) ? negated[cell] : false; + bool cell_neg; + if (negated.count(cell)) + cell_neg = negated[cell]; + else + cell_neg = false; + SigSpec a = sigmap(cell->getPort(ID::A)); SigSpec b = sigmap(cell->getPort(ID::B)); bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); - bool b_subtracted = (cell->type == ID($sub)); + bool b_sub = (cell->type == ID($sub)) || (is_alu(cell) && alu_is_subtract(cell)); - if (!is_chain_internal(a, chain_y_bits)) { - bool neg_a = cell_neg; - operands.push_back({a, a_signed, neg_a}); - if (neg_a) - correction++; + if (!overlaps(a, chain_bits)) { + bool neg = cell_neg; + operands.push_back({a, a_signed, neg}); + if (neg) correction++; } - - if (!is_chain_internal(b, chain_y_bits)) { - bool neg_b = cell_neg ^ b_subtracted; - operands.push_back({b, b_signed, neg_b}); - if (neg_b) - correction++; + if (!overlaps(b, chain_bits)) { + bool neg = cell_neg ^ b_sub; + operands.push_back({b, b_signed, neg}); + if (neg) correction++; } } - return operands; } - SigSpec extend_to(SigSpec sig, bool is_signed, int width) + bool extract_macc_operands(Cell* cell, std::vector& operands, int& correction) + { + Macc macc(cell); + correction = 0; + + for (auto& term : macc.terms) { + if (GetSize(term.in_b) != 0) + return false; + operands.push_back({term.in_a, term.is_signed, term.do_subtract}); + if (term.do_subtract) + correction++; + } + return true; + } + + SigSpec extend_operand(SigSpec sig, bool is_signed, int width) { if (GetSize(sig) < width) { - SigBit pad = (is_signed && GetSize(sig) > 0) ? sig[GetSize(sig) - 1] : State::S0; + SigBit pad; + if (is_signed && GetSize(sig) > 0) + pad = sig[GetSize(sig) - 1]; + else + pad = State::S0; sig.append(SigSpec(pad, width - GetSize(sig))); } if (GetSize(sig) > width) @@ -225,14 +291,9 @@ struct CsaTreeWorker return out; } - SigSpec make_constant(int value, int width) - { - return SigSpec(value, width); - } - std::pair emit_fa(SigSpec a, SigSpec b, SigSpec c, int width) { - SigSpec sum = module->addWire(NEW_ID, width); + SigSpec sum = module->addWire(NEW_ID, width); SigSpec cout = module->addWire(NEW_ID, width); Cell* fa = module->addCell(NEW_ID, ID($fa)); @@ -243,66 +304,10 @@ struct CsaTreeWorker fa->setPort(ID::X, cout); fa->setPort(ID::Y, sum); - SigSpec carry_shifted; - carry_shifted.append(State::S0); - carry_shifted.append(cout.extract(0, width - 1)); - - return {sum, carry_shifted}; - } - - std::pair build_wallace_tree(std::vector &operands, int width, int &fa_count) - { - std::vector ops; - for (auto &s : operands) - ops.push_back({s, 0}); - - fa_count = 0; - int level = 0; - - while (ops.size() > 2) - { - std::vector ready, waiting; - for (auto &op : ops) { - if (op.depth <= level) - ready.push_back(op); - else - waiting.push_back(op); - } - - if (ready.size() < 3) { - level++; - log_assert(level <= 100); - continue; - } - - std::vector next; - size_t i = 0; - while (i + 2 < ready.size()) { - auto [sum, carry] = emit_fa(ready[i].sig, ready[i+1].sig, ready[i+2].sig, width); - int d = std::max({ready[i].depth, ready[i+1].depth, ready[i+2].depth}) + 1; - next.push_back({sum, d}); - next.push_back({carry, d}); - fa_count++; - i += 3; - } - - for (; i < ready.size(); i++) - next.push_back(ready[i]); - - for (auto &op : waiting) - next.push_back(op); - - ops = std::move(next); - level++; - log_assert(level <= 100); - } - - log_assert(ops.size() == 2); - - int max_depth = std::max(ops[0].depth, ops[1].depth); - log(" Tree depth: %d FA levels + 1 final add\n", max_depth); - - return {ops[0].sig, ops[1].sig}; + SigSpec carry; + carry.append(State::S0); + carry.append(cout.extract(0, width - 1)); + return {sum, carry}; } void emit_final_add(SigSpec a, SigSpec b, SigSpec y, int width) @@ -318,30 +323,110 @@ struct CsaTreeWorker add->setPort(ID::Y, y); } - void run() + struct DepthSig { + SigSpec sig; + int depth; + }; + + std::pair reduce_wallace(std::vector& sigs, int width, int& fa_count) { - find_addsubs(); - if (all_addsubs.empty()) + std::vector ops; + ops.reserve(sigs.size()); + for (auto& s : sigs) + ops.push_back({s, 0}); + + fa_count = 0; + + for (int level = 0; ops.size() > 2; level++) { + log_assert(level <= 100); + + std::vector ready, waiting; + for (auto& op : ops) { + if (op.depth <= level) + ready.push_back(op); + else + waiting.push_back(op); + } + + if (ready.size() < 3) continue; + + std::vector next; + size_t i = 0; + while (i + 2 < ready.size()) { + auto [sum, carry] = emit_fa(ready[i].sig, ready[i + 1].sig, ready[i + 2].sig, width); + int d = std::max({ready[i].depth, ready[i + 1].depth,ready[i + 2].depth}) + 1; + next.push_back({sum, d}); + next.push_back({carry, d}); + fa_count++; + i += 3; + } + for (; i < ready.size(); i++) + next.push_back(ready[i]); + for (auto& op : waiting) + next.push_back(op); + + ops = std::move(next); + } + + log_assert(ops.size() == 2); + log(" Tree depth: %d FA levels + 1 final add\n", + std::max(ops[0].depth, ops[1].depth)); + return {ops[0].sig, ops[1].sig}; + } + + void replace_with_csa_tree( + std::vector& operands, + SigSpec result_y, + int correction, + const char* desc + ) { + int width = GetSize(result_y); + std::vector extended; + extended.reserve(operands.size() + 1); + + for (auto& op : operands) { + SigSpec s = extend_operand(op.sig, op.is_signed, width); + if (op.negate) + s = emit_not(s, width); + extended.push_back(s); + } + + if (correction > 0) + extended.push_back(SigSpec(correction, width)); + + int fa_count; + auto [a, b] = reduce_wallace(extended, width, fa_count); + + log(" %s → %d $fa + 1 $add (%d operands, module %s)\n", + desc, fa_count, (int)operands.size(), log_id(module)); + + emit_final_add(a, b, result_y, width); + } + + void process_chains() + { + pool candidates; + for (auto cell : addsub_cells) + candidates.insert(cell); + for (auto cell : alu_cells) + if (alu_is_chainable(cell)) + candidates.insert(cell); + + if (candidates.empty()) return; - build_fanout_map(); + auto parent_of = find_parents(candidates); - auto parent_of = find_addsub_parents(); - - pool has_parent; dict> children_of; - for (auto &pair : parent_of) { - has_parent.insert(pair.first); - children_of[pair.second].insert(pair.first); + pool has_parent; + for (auto& [child, parent] : parent_of) { + children_of[parent].insert(child); + has_parent.insert(child); } pool processed; - - for (auto root : all_addsubs) - { - if (has_parent.count(root)) - continue; - if (processed.count(root)) + for (auto root : candidates) { + if (has_parent.count(root) || processed.count(root)) continue; pool chain = collect_chain(root, children_of); @@ -351,52 +436,51 @@ struct CsaTreeWorker for (auto c : chain) processed.insert(c); - pool chain_y_bits = collect_chain_outputs(chain); - int correction = 0; - auto operands = collect_leaf_operands(chain, chain_y_bits, root, parent_of, correction); - + int correction; + auto operands = extract_chain_operands( + chain, root, parent_of, correction); if (operands.size() < 3) continue; - SigSpec root_y = root->getPort(ID::Y); - int width = GetSize(root_y); - std::vector extended; - - for (auto &op : operands) { - SigSpec s = extend_to(op.sig, op.is_signed, width); - if (op.negate) - s = emit_not(s, width); - extended.push_back(s); - } - - if (correction > 0) - extended.push_back(make_constant(correction, width)); - - int fa_count; - auto [final_a, final_b] = build_wallace_tree(extended, width, fa_count); - int num_subs = 0; - - for (auto cell : chain) - if (cell->type == ID($sub)) - num_subs++; - - if (num_subs > 0) - log(" Replaced chain of %d $add/%d $sub cells with %d $fa + 1 $add (%d operands, module %s)\n", - (int)chain.size() - num_subs, num_subs, fa_count, (int)operands.size(), log_id(module)); - else - log(" Replaced chain of %d $add cells with %d $fa + 1 $add (%d operands, module %s)\n", - (int)chain.size(), fa_count, (int)operands.size(), log_id(module)); - - emit_final_add(final_a, final_b, root_y, width); - + replace_with_csa_tree(operands, root->getPort(ID::Y), + correction, "Replaced add/sub chain"); for (auto cell : chain) module->remove(cell); } } + + void process_maccs() + { + for (auto cell : macc_cells) { + std::vector operands; + int correction; + if (!extract_macc_operands(cell, operands, correction)) + continue; + if (operands.size() < 3) + continue; + + replace_with_csa_tree(operands, cell->getPort(ID::Y), + correction, "Replaced $macc"); + module->remove(cell); + } + } + + void run() + { + classify_cells(); + + if (addsub_cells.empty() && alu_cells.empty() && macc_cells.empty()) + return; + + build_fanout_map(); + process_chains(); + process_maccs(); + } }; struct CsaTreePass : public Pass { - CsaTreePass() : Pass("csa_tree", "convert $add/$sub chains to carry-save adder trees") {} + CsaTreePass() : Pass("csa_tree", + "convert add/sub/macc chains to carry-save adder trees") {} void help() override { @@ -404,17 +488,17 @@ struct CsaTreePass : public Pass { log("\n"); log(" csa_tree [selection]\n"); log("\n"); - log("This pass finds chains of $add and $sub cells and replaces them with carry-save\n"); - log("adder trees built from $fa cells, followed by a single final $add for the\n"); - log("carry-propagate step.\n"); + log("This pass replaces chains of $add/$sub cells, $alu cells (with constant\n"); + log("BI/CI), and $macc/$macc_v2 cells (without multiplications) with carry-save\n"); + log("adder trees using $fa cells and a single final $add.\n"); log("\n"); - log("The tree uses Wallace-tree scheduling for optimal depth: at each level, all ready\n"); - log("operands are grouped into triplets and compressed via full adders. This\n"); - log("gives ceil(log_1.5(N)) FA levels for N input operands.\n"); + log("The tree uses Wallace-tree scheduling: at each level, ready operands are\n"); + log("grouped into triplets and compressed via full adders, giving\n"); + log("O(log_{1.5} N) depth for N input operands.\n"); log("\n"); } - void execute(std::vector args, RTLIL::Design *design) override + void execute(std::vector args, RTLIL::Design* design) override { log_header(design, "Executing CSA_TREE pass.\n"); From 9dc408eea7aa992d3bd2f0e1d1cc651ed7c2d29f Mon Sep 17 00:00:00 2001 From: nella Date: Thu, 19 Mar 2026 17:45:56 +0100 Subject: [PATCH 027/176] CSA add alumacc related tests. --- tests/csa_tree/csa_tree_alu_chains.ys | 96 ++++++ .../csa_tree/csa_tree_alu_macc_edge_cases.ys | 285 ++++++++++++++++++ tests/csa_tree/csa_tree_alu_macc_equiv.ys | 179 +++++++++++ tests/csa_tree/csa_tree_alu_macc_sim.ys | 116 +++++++ tests/csa_tree/csa_tree_alu_sub_chains.ys | 79 +++++ tests/csa_tree/csa_tree_macc.ys | 141 +++++++++ 6 files changed, 896 insertions(+) create mode 100644 tests/csa_tree/csa_tree_alu_chains.ys create mode 100644 tests/csa_tree/csa_tree_alu_macc_edge_cases.ys create mode 100644 tests/csa_tree/csa_tree_alu_macc_equiv.ys create mode 100644 tests/csa_tree/csa_tree_alu_macc_sim.ys create mode 100644 tests/csa_tree/csa_tree_alu_sub_chains.ys create mode 100644 tests/csa_tree/csa_tree_macc.ys diff --git a/tests/csa_tree/csa_tree_alu_chains.ys b/tests/csa_tree/csa_tree_alu_chains.ys new file mode 100644 index 000000000..ada1368dc --- /dev/null +++ b/tests/csa_tree/csa_tree_alu_chains.ys @@ -0,0 +1,96 @@ +read_verilog < Date: Fri, 20 Mar 2026 16:47:21 +0100 Subject: [PATCH 028/176] Move csa after alumacc. --- techlibs/common/synth.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index d073cd348..1490c6adc 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -68,7 +68,7 @@ struct SynthPass : public ScriptPass { log(" run the booth pass to map $mul to Booth encoded multipliers\n"); log("\n"); log(" -csa\n"); - log(" run the csa_tree pass to convert $add/$sub chains to\n"); + log(" run the csa_tree pass to convert $add/$sub chains and $macc cells to\n"); log(" carry-save adder trees.\n"); log("\n"); log(" -noalumacc\n"); @@ -295,10 +295,10 @@ struct SynthPass : public ScriptPass { run(stringf("%s -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", techmap_cmd, lut)); if (booth || help_mode) run("booth", " (if -booth)"); - if (csa || help_mode) - run("csa_tree", " (if -csa)"); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); + if (csa || help_mode) + run("csa_tree", " (if -csa)"); if (!noshare) run("share", " (unless -noshare)"); run("opt" + hieropt_flag); From 9cc2e7d95e20b9b77aae7b0624851d52c60d6313 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:56:07 +0100 Subject: [PATCH 029/176] rm misc comments. --- tests/csa_tree/csa_tree_macc.ys | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/csa_tree/csa_tree_macc.ys b/tests/csa_tree/csa_tree_macc.ys index 27684e0ed..4c2490e34 100644 --- a/tests/csa_tree/csa_tree_macc.ys +++ b/tests/csa_tree/csa_tree_macc.ys @@ -1,8 +1,3 @@ -# Tests for csa_tree operating on $macc cells (post-alumacc) -# After alumacc, chains of adds get merged into a single $macc cell. -# The csa_tree pass should decompose it into FA + final add. - -# 3-input add merged into $macc read_verilog < Date: Fri, 27 Mar 2026 16:14:07 +0100 Subject: [PATCH 030/176] Cleaned up CSA tests. --- tests/csa_tree/csa_tree_add_chains.ys | 173 +++++++++++ tests/csa_tree/csa_tree_alu_chains.ys | 96 ------ .../csa_tree/csa_tree_alu_macc_edge_cases.ys | 285 ------------------ tests/csa_tree/csa_tree_alu_macc_equiv.ys | 18 ++ tests/csa_tree/csa_tree_alu_macc_sim.ys | 116 ------- tests/csa_tree/csa_tree_alu_sub_chains.ys | 79 ----- tests/csa_tree/csa_tree_edge_cases.ys | 260 ++++++++++++++++ tests/csa_tree/csa_tree_equiv.ys | 36 +-- tests/csa_tree/csa_tree_idempotent.ys | 27 ++ tests/csa_tree/csa_tree_macc.ys | 133 -------- tests/csa_tree/csa_tree_sim.ys | 72 ----- tests/csa_tree/csa_tree_sub_chains.ys | 138 +++++++++ tests/csa_tree/csa_tree_synth.ys | 5 - tests/csa_tree/run-test.sh | 4 +- 14 files changed, 636 insertions(+), 806 deletions(-) delete mode 100644 tests/csa_tree/csa_tree_alu_chains.ys delete mode 100644 tests/csa_tree/csa_tree_alu_macc_edge_cases.ys delete mode 100644 tests/csa_tree/csa_tree_alu_macc_sim.ys delete mode 100644 tests/csa_tree/csa_tree_alu_sub_chains.ys delete mode 100644 tests/csa_tree/csa_tree_macc.ys delete mode 100644 tests/csa_tree/csa_tree_sim.ys diff --git a/tests/csa_tree/csa_tree_add_chains.ys b/tests/csa_tree/csa_tree_add_chains.ys index 46e5868a9..98067ce16 100644 --- a/tests/csa_tree/csa_tree_add_chains.ys +++ b/tests/csa_tree/csa_tree_add_chains.ys @@ -59,3 +59,176 @@ csa_tree select -assert-count 14 t:$fa select -assert-count 1 t:$add design -reset + +read_verilog < Date: Mon, 30 Mar 2026 15:47:34 +0200 Subject: [PATCH 031/176] Replace utf arrow with ascii arrow. --- passes/opt/csa_tree.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/csa_tree.cc b/passes/opt/csa_tree.cc index de2e28901..3be9fdc91 100644 --- a/passes/opt/csa_tree.cc +++ b/passes/opt/csa_tree.cc @@ -397,7 +397,7 @@ struct CsaTreeWorker int fa_count; auto [a, b] = reduce_wallace(extended, width, fa_count); - log(" %s → %d $fa + 1 $add (%d operands, module %s)\n", + log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, fa_count, (int)operands.size(), log_id(module)); emit_final_add(a, b, result_y, width); From b6a8feec2282995c0ab0f86b7813b241770ef05d Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 31 Mar 2026 11:56:12 +0200 Subject: [PATCH 032/176] csa_tree: refactor --- passes/opt/csa_tree.cc | 222 +++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 122 deletions(-) diff --git a/passes/opt/csa_tree.cc b/passes/opt/csa_tree.cc index 3be9fdc91..b58d65104 100644 --- a/passes/opt/csa_tree.cc +++ b/passes/opt/csa_tree.cc @@ -13,19 +13,32 @@ struct Operand { bool negate; }; -struct CsaTreeWorker +struct Traversal { - Module* module; SigMap sigmap; - dict> bit_consumers; dict fanout; + Traversal(Module* module) : sigmap(module) { + for (auto cell : module->cells()) + for (auto& conn : cell->connections()) + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + bit_consumers[bit].insert(cell); - pool addsub_cells; - pool alu_cells; - pool macc_cells; + for (auto& pair : bit_consumers) + fanout[pair.first] = pair.second.size(); - CsaTreeWorker(Module* module) : module(module), sigmap(module) {} + for (auto wire : module->wires()) + if (wire->port_output) + for (auto bit : sigmap(SigSpec(wire))) + fanout[bit]++; + } +}; + +struct Cells { + pool addsub; + pool alu; + pool macc; static bool is_addsub(Cell* cell) { @@ -42,79 +55,74 @@ struct CsaTreeWorker return cell->type == ID($macc) || cell->type == ID($macc_v2); } - bool alu_is_subtract(Cell* cell) + bool empty() { + return addsub.empty() && alu.empty() && macc.empty(); + } + + Cells(Module* module) { + for (auto cell : module->cells()) { + if (is_addsub(cell)) + addsub.insert(cell); + else if (is_alu(cell)) + alu.insert(cell); + else if (is_macc(cell)) + macc.insert(cell); + } + } +}; + +struct AluInfo { + Cells& cells; + Traversal& traversal; + bool is_subtract(Cell* cell) { - SigSpec bi = sigmap(cell->getPort(ID::BI)); - SigSpec ci = sigmap(cell->getPort(ID::CI)); + SigSpec bi = traversal.sigmap(cell->getPort(ID::BI)); + SigSpec ci = traversal.sigmap(cell->getPort(ID::CI)); return GetSize(bi) == 1 && bi[0] == State::S1 && GetSize(ci) == 1 && ci[0] == State::S1; } - bool alu_is_add(Cell* cell) + bool is_add(Cell* cell) { - SigSpec bi = sigmap(cell->getPort(ID::BI)); - SigSpec ci = sigmap(cell->getPort(ID::CI)); + SigSpec bi = traversal.sigmap(cell->getPort(ID::BI)); + SigSpec ci = traversal.sigmap(cell->getPort(ID::CI)); return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0; } - bool alu_is_chainable(Cell* cell) - { - if (!(alu_is_add(cell) || alu_is_subtract(cell))) - return false; - - for (auto bit : sigmap(cell->getPort(ID::X))) - if (fanout.count(bit) && fanout[bit] > 0) - return false; - for (auto bit : sigmap(cell->getPort(ID::CO))) - if (fanout.count(bit) && fanout[bit] > 0) - return false; - - return true; - } - bool is_chainable(Cell* cell) { - return is_addsub(cell) || (is_alu(cell) && alu_is_chainable(cell)); + if (!(is_add(cell) || is_subtract(cell))) + return false; + + for (auto bit : traversal.sigmap(cell->getPort(ID::X))) + if (traversal.fanout.count(bit) && traversal.fanout[bit] > 0) + return false; + for (auto bit : traversal.sigmap(cell->getPort(ID::CO))) + if (traversal.fanout.count(bit) && traversal.fanout[bit] > 0) + return false; + + return true; } +}; - void classify_cells() - { - for (auto cell : module->cells()) { - if (is_addsub(cell)) - addsub_cells.insert(cell); - else if (is_alu(cell)) - alu_cells.insert(cell); - else if (is_macc(cell)) - macc_cells.insert(cell); - } - } +struct Rewriter +{ + Module* module; + Cells& cells; + Traversal traversal; + AluInfo alu_info; - void build_fanout_map() - { - for (auto cell : module->cells()) - for (auto& conn : cell->connections()) - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) - bit_consumers[bit].insert(cell); - - for (auto& pair : bit_consumers) - fanout[pair.first] = pair.second.size(); - - for (auto wire : module->wires()) - if (wire->port_output) - for (auto bit : sigmap(SigSpec(wire))) - fanout[bit]++; - } + Rewriter(Module* module, Cells& cells) : module(module), cells(cells), traversal(module), alu_info{cells, traversal} {} Cell* sole_chainable_consumer(SigSpec sig, const pool& candidates) { Cell* consumer = nullptr; for (auto bit : sig) { - if (!fanout.count(bit) || fanout[bit] != 1) + if (!traversal.fanout.count(bit) || traversal.fanout[bit] != 1) return nullptr; - if (!bit_consumers.count(bit) || bit_consumers[bit].size() != 1) + if (!traversal.bit_consumers.count(bit) || traversal.bit_consumers[bit].size() != 1) return nullptr; - Cell* c = *bit_consumers[bit].begin(); + Cell* c = *traversal.bit_consumers[bit].begin(); if (!candidates.count(c)) return nullptr; @@ -131,7 +139,7 @@ struct CsaTreeWorker dict parent_of; for (auto cell : candidates) { Cell* consumer = sole_chainable_consumer( - sigmap(cell->getPort(ID::Y)), candidates); + traversal.sigmap(cell->getPort(ID::Y)), candidates); if (consumer && consumer != cell) parent_of[cell] = consumer; } @@ -144,7 +152,8 @@ struct CsaTreeWorker std::queue q; q.push(root); while (!q.empty()) { - Cell* cur = q.front(); q.pop(); + Cell* cur = q.front(); + q.pop(); if (!chain.insert(cur).second) continue; auto it = children_of.find(cur); @@ -159,7 +168,7 @@ struct CsaTreeWorker { pool bits; for (auto cell : chain) - for (auto bit : sigmap(cell->getPort(ID::Y))) + for (auto bit : traversal.sigmap(cell->getPort(ID::Y))) bits.insert(bit); return bits; } @@ -177,16 +186,16 @@ struct CsaTreeWorker bool parent_subtracts; if (parent->type == ID($sub)) parent_subtracts = true; - else if (is_alu(parent)) - parent_subtracts = alu_is_subtract(parent); + else if (cells.is_alu(parent)) + parent_subtracts = alu_info.is_subtract(parent); else return false; if (!parent_subtracts) return false; - SigSpec child_y = sigmap(child->getPort(ID::Y)); - SigSpec parent_b = sigmap(parent->getPort(ID::B)); + SigSpec child_y = traversal.sigmap(child->getPort(ID::Y)); + SigSpec parent_b = traversal.sigmap(parent->getPort(ID::B)); for (auto bit : child_y) for (auto pbit : parent_b) if (bit == pbit) @@ -229,11 +238,11 @@ struct CsaTreeWorker else cell_neg = false; - SigSpec a = sigmap(cell->getPort(ID::A)); - SigSpec b = sigmap(cell->getPort(ID::B)); + SigSpec a = traversal.sigmap(cell->getPort(ID::A)); + SigSpec b = traversal.sigmap(cell->getPort(ID::B)); bool a_signed = cell->getParam(ID::A_SIGNED).as_bool(); bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); - bool b_sub = (cell->type == ID($sub)) || (is_alu(cell) && alu_is_subtract(cell)); + bool b_sub = (cell->type == ID($sub)) || (cells.is_alu(cell) && alu_info.is_subtract(cell)); if (!overlaps(a, chain_bits)) { bool neg = cell_neg; @@ -255,6 +264,7 @@ struct CsaTreeWorker correction = 0; for (auto& term : macc.terms) { + // Bail on multiplication if (GetSize(term.in_b) != 0) return false; operands.push_back({term.in_a, term.is_signed, term.do_subtract}); @@ -279,30 +289,12 @@ struct CsaTreeWorker return sig; } - SigSpec emit_not(SigSpec sig, int width) - { - SigSpec out = module->addWire(NEW_ID, width); - Cell* inv = module->addCell(NEW_ID, ID($not)); - inv->setParam(ID::A_SIGNED, false); - inv->setParam(ID::A_WIDTH, width); - inv->setParam(ID::Y_WIDTH, width); - inv->setPort(ID::A, sig); - inv->setPort(ID::Y, out); - return out; - } - std::pair emit_fa(SigSpec a, SigSpec b, SigSpec c, int width) { SigSpec sum = module->addWire(NEW_ID, width); SigSpec cout = module->addWire(NEW_ID, width); - Cell* fa = module->addCell(NEW_ID, ID($fa)); - fa->setParam(ID::WIDTH, width); - fa->setPort(ID::A, a); - fa->setPort(ID::B, b); - fa->setPort(ID::C, c); - fa->setPort(ID::X, cout); - fa->setPort(ID::Y, sum); + module->addFa(NEW_ID, a, b, c, cout, sum); SigSpec carry; carry.append(State::S0); @@ -310,19 +302,6 @@ struct CsaTreeWorker return {sum, carry}; } - void emit_final_add(SigSpec a, SigSpec b, SigSpec y, int width) - { - Cell* add = module->addCell(NEW_ID, ID($add)); - add->setParam(ID::A_SIGNED, false); - add->setParam(ID::B_SIGNED, false); - add->setParam(ID::A_WIDTH, width); - add->setParam(ID::B_WIDTH, width); - add->setParam(ID::Y_WIDTH, width); - add->setPort(ID::A, a); - add->setPort(ID::B, b); - add->setPort(ID::Y, y); - } - struct DepthSig { SigSpec sig; int depth; @@ -387,7 +366,7 @@ struct CsaTreeWorker for (auto& op : operands) { SigSpec s = extend_operand(op.sig, op.is_signed, width); if (op.negate) - s = emit_not(s, width); + s = module->Not(NEW_ID, s); extended.push_back(s); } @@ -400,16 +379,17 @@ struct CsaTreeWorker log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, fa_count, (int)operands.size(), log_id(module)); - emit_final_add(a, b, result_y, width); + // Emit final add + module->addAdd(NEW_ID, a, b, result_y, false); } void process_chains() { pool candidates; - for (auto cell : addsub_cells) + for (auto cell : cells.addsub) candidates.insert(cell); - for (auto cell : alu_cells) - if (alu_is_chainable(cell)) + for (auto cell : cells.alu) + if (alu_info.is_chainable(cell)) candidates.insert(cell); if (candidates.empty()) @@ -427,7 +407,7 @@ struct CsaTreeWorker pool processed; for (auto root : candidates) { if (has_parent.count(root) || processed.count(root)) - continue; + continue; // Not a tree root pool chain = collect_chain(root, children_of); if (chain.size() < 2) @@ -451,7 +431,7 @@ struct CsaTreeWorker void process_maccs() { - for (auto cell : macc_cells) { + for (auto cell : cells.macc) { std::vector operands; int correction; if (!extract_macc_operands(cell, operands, correction)) @@ -464,20 +444,19 @@ struct CsaTreeWorker module->remove(cell); } } - - void run() - { - classify_cells(); - - if (addsub_cells.empty() && alu_cells.empty() && macc_cells.empty()) - return; - - build_fanout_map(); - process_chains(); - process_maccs(); - } }; +void run(Module* module) { + Cells cells(module); + + if (cells.empty()) + return; + + Rewriter rewriter {module, cells}; + rewriter.process_chains(); + rewriter.process_maccs(); +} + struct CsaTreePass : public Pass { CsaTreePass() : Pass("csa_tree", "convert add/sub/macc chains to carry-save adder trees") {} @@ -508,8 +487,7 @@ struct CsaTreePass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) { - CsaTreeWorker worker(module); - worker.run(); + run(module); } } } CsaTreePass; From b6d656e932f4f39891ad96a987458e9d70a5b02c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 31 Mar 2026 12:05:36 +0200 Subject: [PATCH 033/176] csa_tree: move to techmap --- passes/opt/Makefile.inc | 1 - passes/techmap/Makefile.inc | 1 + passes/{opt => techmap}/csa_tree.cc | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename passes/{opt => techmap}/csa_tree.cc (100%) diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 1d7833b31..e7b62fc6a 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -23,7 +23,6 @@ OBJS += passes/opt/opt_ffinv.o OBJS += passes/opt/pmux2shiftx.o OBJS += passes/opt/muxpack.o OBJS += passes/opt/opt_balance_tree.o -OBJS += passes/opt/csa_tree.o OBJS += passes/opt/peepopt.o GENFILES += passes/opt/peepopt_pm.h diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 083778d3c..190b93570 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -55,6 +55,7 @@ OBJS += passes/techmap/extractinv.o OBJS += passes/techmap/cellmatch.o OBJS += passes/techmap/clockgate.o OBJS += passes/techmap/constmap.o +OBJS += passes/techmap/csa_tree.o endif ifeq ($(DISABLE_SPAWN),0) diff --git a/passes/opt/csa_tree.cc b/passes/techmap/csa_tree.cc similarity index 100% rename from passes/opt/csa_tree.cc rename to passes/techmap/csa_tree.cc From 42c309347b02152b6f7cf4476c843ffab03cb06a Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 1 Apr 2026 08:55:20 +0200 Subject: [PATCH 034/176] Clarify. --- passes/techmap/csa_tree.cc | 44 ++++++++++----------- tests/csa_tree/csa_tree_synth.ys | 65 -------------------------------- 2 files changed, 23 insertions(+), 86 deletions(-) delete mode 100644 tests/csa_tree/csa_tree_synth.ys diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/csa_tree.cc index b58d65104..618abe0b5 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/csa_tree.cc @@ -1,3 +1,6 @@ +// Replaces chains of $add/$sub and $macc cells with carry-save adder trees, reducing multi-operand +// addition to logarithmic depth. ref. paper: Zimmermann, "Architectures for Adders" + #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/macc.h" @@ -88,6 +91,7 @@ struct AluInfo { return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0; } + // A cell is chainable if it's a plain add/sub with unused carries. bool is_chainable(Cell* cell) { if (!(is_add(cell) || is_subtract(cell))) @@ -134,6 +138,7 @@ struct Rewriter return consumer; } + // Find cells that consumes another cell's output. dict find_parents(const pool& candidates) { dict parent_of; @@ -207,7 +212,7 @@ struct Rewriter const pool& chain, Cell* root, const dict& parent_of, - int& correction + int& neg_compensation ) { pool chain_bits = internal_bits(chain); dict negated; @@ -229,7 +234,7 @@ struct Rewriter } std::vector operands; - correction = 0; + neg_compensation = 0; for (auto cell : chain) { bool cell_neg; @@ -247,21 +252,21 @@ struct Rewriter if (!overlaps(a, chain_bits)) { bool neg = cell_neg; operands.push_back({a, a_signed, neg}); - if (neg) correction++; + if (neg) neg_compensation++; } if (!overlaps(b, chain_bits)) { bool neg = cell_neg ^ b_sub; operands.push_back({b, b_signed, neg}); - if (neg) correction++; + if (neg) neg_compensation++; } } return operands; } - bool extract_macc_operands(Cell* cell, std::vector& operands, int& correction) + bool extract_macc_operands(Cell* cell, std::vector& operands, int& neg_compensation) { Macc macc(cell); - correction = 0; + neg_compensation = 0; for (auto& term : macc.terms) { // Bail on multiplication @@ -269,7 +274,7 @@ struct Rewriter return false; operands.push_back({term.in_a, term.is_signed, term.do_subtract}); if (term.do_subtract) - correction++; + neg_compensation++; } return true; } @@ -307,6 +312,7 @@ struct Rewriter int depth; }; + // Group ready operands into triplets and compress via full adders until two operands remain. std::pair reduce_wallace(std::vector& sigs, int width, int& fa_count) { std::vector ops; @@ -356,7 +362,7 @@ struct Rewriter void replace_with_csa_tree( std::vector& operands, SigSpec result_y, - int correction, + int neg_compensation, const char* desc ) { int width = GetSize(result_y); @@ -370,8 +376,8 @@ struct Rewriter extended.push_back(s); } - if (correction > 0) - extended.push_back(SigSpec(correction, width)); + if (neg_compensation > 0) + extended.push_back(SigSpec(neg_compensation, width)); int fa_count; auto [a, b] = reduce_wallace(extended, width, fa_count); @@ -416,14 +422,12 @@ struct Rewriter for (auto c : chain) processed.insert(c); - int correction; - auto operands = extract_chain_operands( - chain, root, parent_of, correction); + int neg_compensation; + auto operands = extract_chain_operands(chain, root, parent_of, neg_compensation); if (operands.size() < 3) continue; - replace_with_csa_tree(operands, root->getPort(ID::Y), - correction, "Replaced add/sub chain"); + replace_with_csa_tree(operands, root->getPort(ID::Y), neg_compensation, "Replaced add/sub chain"); for (auto cell : chain) module->remove(cell); } @@ -433,14 +437,13 @@ struct Rewriter { for (auto cell : cells.macc) { std::vector operands; - int correction; - if (!extract_macc_operands(cell, operands, correction)) + int neg_compensation; + if (!extract_macc_operands(cell, operands, neg_compensation)) continue; if (operands.size() < 3) continue; - replace_with_csa_tree(operands, cell->getPort(ID::Y), - correction, "Replaced $macc"); + replace_with_csa_tree(operands, cell->getPort(ID::Y), neg_compensation, "Replaced $macc"); module->remove(cell); } } @@ -458,8 +461,7 @@ void run(Module* module) { } struct CsaTreePass : public Pass { - CsaTreePass() : Pass("csa_tree", - "convert add/sub/macc chains to carry-save adder trees") {} + CsaTreePass() : Pass("csa_tree", "convert add/sub/macc chains to carry-save adder trees") {} void help() override { diff --git a/tests/csa_tree/csa_tree_synth.ys b/tests/csa_tree/csa_tree_synth.ys deleted file mode 100644 index c3be44f17..000000000 --- a/tests/csa_tree/csa_tree_synth.ys +++ /dev/null @@ -1,65 +0,0 @@ -read_verilog < Date: Wed, 1 Apr 2026 09:07:42 +0200 Subject: [PATCH 035/176] Invert. --- passes/techmap/csa_tree.cc | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/csa_tree.cc index 618abe0b5..b05586e58 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/csa_tree.cc @@ -91,7 +91,8 @@ struct AluInfo { return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0; } - // A cell is chainable if it's a plain add/sub with unused carries. + // Chainable cells are adds/subs with no carry usage, connected chainable + // cells form chains that can be replaced with CSA trees. bool is_chainable(Cell* cell) { if (!(is_add(cell) || is_subtract(cell))) @@ -138,7 +139,7 @@ struct Rewriter return consumer; } - // Find cells that consumes another cell's output. + // Find cells that consume another cell's output. dict find_parents(const pool& candidates) { dict parent_of; @@ -151,6 +152,17 @@ struct Rewriter return parent_of; } + std::pair>, pool> invert_parent_map(const dict& parent_of) + { + dict> children_of; + pool has_parent; + for (auto& [child, parent] : parent_of) { + children_of[parent].insert(child); + has_parent.insert(child); + } + return {children_of, has_parent}; + } + pool collect_chain(Cell* root, const dict>& children_of) { pool chain; @@ -376,6 +388,7 @@ struct Rewriter extended.push_back(s); } + // Add correction for negated operands (-x = ~x + 1 so 1 per negation) if (neg_compensation > 0) extended.push_back(SigSpec(neg_compensation, width)); @@ -402,13 +415,7 @@ struct Rewriter return; auto parent_of = find_parents(candidates); - - dict> children_of; - pool has_parent; - for (auto& [child, parent] : parent_of) { - children_of[parent].insert(child); - has_parent.insert(child); - } + auto [children_of, has_parent] = invert_parent_map(parent_of); pool processed; for (auto root : candidates) { From a02c238874713d763cf006222ab2283e403a5c0a Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 1 Apr 2026 11:03:41 +0200 Subject: [PATCH 036/176] Consolidate Wallace from booth and CSA. --- kernel/wallace_tree.h | 112 +++++++++++++++++++++++++++++++++++++ passes/techmap/booth.cc | 39 ++----------- passes/techmap/csa_tree.cc | 79 +++----------------------- 3 files changed, 124 insertions(+), 106 deletions(-) create mode 100644 kernel/wallace_tree.h diff --git a/kernel/wallace_tree.h b/kernel/wallace_tree.h new file mode 100644 index 000000000..eb3513803 --- /dev/null +++ b/kernel/wallace_tree.h @@ -0,0 +1,112 @@ +/** + * Wallace tree utilities for multi-operand addition using carry-save adders + * + * Terminology: + * - compressor: $fa viewed as reducing 3 inputs to 2 outputs (sum + shifted carry) (3:2 compressor) + * - level: A stage of parallel compression operations + * - depth: Maximum number of 3:2 compressor levels from any input to a signal + * + * References: + * - "Binary Adder Architectures for Cell-Based VLSI and their Synthesis" (https://iis-people.ee.ethz.ch/~zimmi/publications/adder_arch.pdf) + * - "A Suggestion for a Fast Multiplier" (https://www.ece.ucdavis.edu/~vojin/CLASSES/EEC280/Web-page/papers/Arithmetic/Wallace_mult.pdf) + */ + +#ifndef WALLACE_TREE_H +#define WALLACE_TREE_H + +#include "kernel/sigtools.h" +#include "kernel/yosys.h" + +YOSYS_NAMESPACE_BEGIN + +inline std::pair emit_fa(Module *module, SigSpec a, SigSpec b, SigSpec c, int width) +{ + SigSpec sum = module->addWire(NEW_ID, width); + SigSpec cout = module->addWire(NEW_ID, width); + + module->addFa(NEW_ID, a, b, c, cout, sum); + + SigSpec carry; + carry.append(State::S0); + carry.append(cout.extract(0, width - 1)); + return {sum, carry}; +} + +/** + * wallace_reduce_scheduled() - Reduce multiple operands to two using a Wallace tree + * @module: The Yosys module to which the compressors will be added + * @sigs: Vector of input signals (operands) to be reduced + * @width: Target bit-width to which all operands will be zero-extended + * @compressor_count: Optional pointer to return the number of $fa cells emitted + * + * Return: The final two reduced operands, that are to be fed into an adder + */ +inline std::pair wallace_reduce_scheduled(Module *module, std::vector &sigs, int width, int *compressor_count = nullptr) +{ + struct DepthSig { + SigSpec sig; + int depth; + }; + + for (auto &s : sigs) + s.extend_u0(width); + + std::vector operands; + operands.reserve(sigs.size()); + for (auto &s : sigs) + operands.push_back({s, 0}); + + // Number of $fa's emitted + if (compressor_count) + *compressor_count = 0; + + // Only compress operands ready at current level + for (int level = 0; operands.size() > 2; level++) { + // Partition operands into ready and waiting + std::vector ready, waiting; + for (auto &op : operands) { + if (op.depth <= level) + ready.push_back(op); + else + waiting.push_back(op); + } + + if (ready.size() < 3) + continue; + + // Apply compressors to ready operands + std::vector compressed; + size_t i = 0; + while (i + 2 < ready.size()) { + auto [sum, carry] = emit_fa(module, ready[i].sig, ready[i + 1].sig, ready[i + 2].sig, width); + int new_depth = std::max({ready[i].depth, ready[i + 1].depth, ready[i + 2].depth}) + 1; + compressed.push_back({sum, new_depth}); + compressed.push_back({carry, new_depth}); + if (compressor_count) + (*compressor_count)++; + i += 3; + } + // Uncompressed operands pass through to next level + for (; i < ready.size(); i++) + compressed.push_back(ready[i]); + // Merge compressed with waiting operands + for (auto &op : waiting) + compressed.push_back(op); + + operands = std::move(compressed); + } + + if (operands.size() == 0) + return {SigSpec(State::S0, width), SigSpec(State::S0, width)}; + else if (operands.size() == 1) + return {operands[0].sig, SigSpec(State::S0, width)}; + else { + log_assert(operands.size() == 2); + log(" Wallace tree depth: %d levels of $fa + 1 final $add\n", std::max(operands[0].depth, operands[1].depth)); + return {operands[0].sig, operands[1].sig}; + } +} + +YOSYS_NAMESPACE_END + +#endif diff --git a/passes/techmap/booth.cc b/passes/techmap/booth.cc index 11ff71b29..c0bad784a 100644 --- a/passes/techmap/booth.cc +++ b/passes/techmap/booth.cc @@ -58,6 +58,7 @@ synth -top my_design -booth #include "kernel/sigtools.h" #include "kernel/yosys.h" #include "kernel/macc.h" +#include "kernel/wallace_tree.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -317,36 +318,6 @@ struct BoothPassWorker { } } - SigSig WallaceSum(int width, std::vector summands) - { - for (auto &s : summands) - s.extend_u0(width); - - while (summands.size() > 2) { - std::vector new_summands; - int i; - for (i = 0; i < (int) summands.size() - 2; i += 3) { - SigSpec x = module->addWire(NEW_ID, width); - SigSpec y = module->addWire(NEW_ID, width); - BuildBitwiseFa(module, NEW_ID.str(), summands[i], summands[i + 1], - summands[i + 2], x, y); - new_summands.push_back(y); - new_summands.push_back({x.extract(0, width - 1), State::S0}); - } - - new_summands.insert(new_summands.begin(), summands.begin() + i, summands.end()); - - std::swap(summands, new_summands); - } - - if (!summands.size()) - return SigSig(SigSpec(width, State::S0), SigSpec(width, State::S0)); - else if (summands.size() == 1) - return SigSig(summands[0], SigSpec(width, State::S0)); - else - return SigSig(summands[0], summands[1]); - } - /* Build Multiplier. ------------------------- @@ -415,16 +386,16 @@ struct BoothPassWorker { // Later on yosys will clean up unused constants // DebugDumpAlignPP(aligned_pp); - SigSig wtree_sum = WallaceSum(z_sz, aligned_pp); + auto [wtree_a, wtree_b] = wallace_reduce_scheduled(module, aligned_pp, z_sz); // Debug code: Dump out the csa trees // DumpCSATrees(debug_csa_trees); // Build the CPA to do the final accumulation. - log_assert(wtree_sum.second[0] == State::S0); + log_assert(wtree_b[0] == State::S0); if (mapped_cpa) - BuildCPA(module, wtree_sum.first, {State::S0, wtree_sum.second.extract_end(1)}, Z); + BuildCPA(module, wtree_a, wtree_b, Z); else - module->addAdd(NEW_ID, wtree_sum.first, {wtree_sum.second.extract_end(1), State::S0}, Z); + module->addAdd(NEW_ID, wtree_a, wtree_b, Z); } /* diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/csa_tree.cc index b05586e58..4bd0b933f 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/csa_tree.cc @@ -1,9 +1,11 @@ -// Replaces chains of $add/$sub and $macc cells with carry-save adder trees, reducing multi-operand -// addition to logarithmic depth. ref. paper: Zimmermann, "Architectures for Adders" +/** + * Replaces chains of $add/$sub and $macc cells with carry-save adder trees + */ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/macc.h" +#include "kernel/wallace_tree.h" #include @@ -306,71 +308,6 @@ struct Rewriter return sig; } - std::pair emit_fa(SigSpec a, SigSpec b, SigSpec c, int width) - { - SigSpec sum = module->addWire(NEW_ID, width); - SigSpec cout = module->addWire(NEW_ID, width); - - module->addFa(NEW_ID, a, b, c, cout, sum); - - SigSpec carry; - carry.append(State::S0); - carry.append(cout.extract(0, width - 1)); - return {sum, carry}; - } - - struct DepthSig { - SigSpec sig; - int depth; - }; - - // Group ready operands into triplets and compress via full adders until two operands remain. - std::pair reduce_wallace(std::vector& sigs, int width, int& fa_count) - { - std::vector ops; - ops.reserve(sigs.size()); - for (auto& s : sigs) - ops.push_back({s, 0}); - - fa_count = 0; - - for (int level = 0; ops.size() > 2; level++) { - log_assert(level <= 100); - - std::vector ready, waiting; - for (auto& op : ops) { - if (op.depth <= level) - ready.push_back(op); - else - waiting.push_back(op); - } - - if (ready.size() < 3) continue; - - std::vector next; - size_t i = 0; - while (i + 2 < ready.size()) { - auto [sum, carry] = emit_fa(ready[i].sig, ready[i + 1].sig, ready[i + 2].sig, width); - int d = std::max({ready[i].depth, ready[i + 1].depth,ready[i + 2].depth}) + 1; - next.push_back({sum, d}); - next.push_back({carry, d}); - fa_count++; - i += 3; - } - for (; i < ready.size(); i++) - next.push_back(ready[i]); - for (auto& op : waiting) - next.push_back(op); - - ops = std::move(next); - } - - log_assert(ops.size() == 2); - log(" Tree depth: %d FA levels + 1 final add\n", - std::max(ops[0].depth, ops[1].depth)); - return {ops[0].sig, ops[1].sig}; - } - void replace_with_csa_tree( std::vector& operands, SigSpec result_y, @@ -392,11 +329,9 @@ struct Rewriter if (neg_compensation > 0) extended.push_back(SigSpec(neg_compensation, width)); - int fa_count; - auto [a, b] = reduce_wallace(extended, width, fa_count); - - log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", - desc, fa_count, (int)operands.size(), log_id(module)); + int compressor_count; + auto [a, b] = wallace_reduce_scheduled(module, extended, width, &compressor_count); + log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, compressor_count, (int)operands.size(), log_id(module)); // Emit final add module->addAdd(NEW_ID, a, b, result_y, false); From 847a8941e955caf4a83e45230a41539a420f9ae1 Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 1 Apr 2026 11:04:57 +0200 Subject: [PATCH 037/176] Clang-Format CSA tree. --- passes/techmap/csa_tree.cc | 155 +++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 85 deletions(-) diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/csa_tree.cc index 4bd0b933f..323fd6818 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/csa_tree.cc @@ -2,10 +2,10 @@ * Replaces chains of $add/$sub and $macc cells with carry-save adder trees */ -#include "kernel/yosys.h" -#include "kernel/sigtools.h" #include "kernel/macc.h" +#include "kernel/sigtools.h" #include "kernel/wallace_tree.h" +#include "kernel/yosys.h" #include @@ -18,19 +18,19 @@ struct Operand { bool negate; }; -struct Traversal -{ +struct Traversal { SigMap sigmap; - dict> bit_consumers; + dict> bit_consumers; dict fanout; - Traversal(Module* module) : sigmap(module) { + Traversal(Module *module) : sigmap(module) + { for (auto cell : module->cells()) - for (auto& conn : cell->connections()) + for (auto &conn : cell->connections()) if (cell->input(conn.first)) for (auto bit : sigmap(conn.second)) bit_consumers[bit].insert(cell); - for (auto& pair : bit_consumers) + for (auto &pair : bit_consumers) fanout[pair.first] = pair.second.size(); for (auto wire : module->wires()) @@ -41,30 +41,20 @@ struct Traversal }; struct Cells { - pool addsub; - pool alu; - pool macc; + pool addsub; + pool alu; + pool macc; - static bool is_addsub(Cell* cell) + static bool is_addsub(Cell *cell) { return cell->type == ID($add) || cell->type == ID($sub); } + + static bool is_alu(Cell *cell) { return cell->type == ID($alu); } + + static bool is_macc(Cell *cell) { return cell->type == ID($macc) || cell->type == ID($macc_v2); } + + bool empty() { return addsub.empty() && alu.empty() && macc.empty(); } + + Cells(Module *module) { - return cell->type == ID($add) || cell->type == ID($sub); - } - - static bool is_alu(Cell* cell) - { - return cell->type == ID($alu); - } - - static bool is_macc(Cell* cell) - { - return cell->type == ID($macc) || cell->type == ID($macc_v2); - } - - bool empty() { - return addsub.empty() && alu.empty() && macc.empty(); - } - - Cells(Module* module) { for (auto cell : module->cells()) { if (is_addsub(cell)) addsub.insert(cell); @@ -77,16 +67,16 @@ struct Cells { }; struct AluInfo { - Cells& cells; - Traversal& traversal; - bool is_subtract(Cell* cell) + Cells &cells; + Traversal &traversal; + bool is_subtract(Cell *cell) { SigSpec bi = traversal.sigmap(cell->getPort(ID::BI)); SigSpec ci = traversal.sigmap(cell->getPort(ID::CI)); return GetSize(bi) == 1 && bi[0] == State::S1 && GetSize(ci) == 1 && ci[0] == State::S1; } - bool is_add(Cell* cell) + bool is_add(Cell *cell) { SigSpec bi = traversal.sigmap(cell->getPort(ID::BI)); SigSpec ci = traversal.sigmap(cell->getPort(ID::CI)); @@ -95,7 +85,7 @@ struct AluInfo { // Chainable cells are adds/subs with no carry usage, connected chainable // cells form chains that can be replaced with CSA trees. - bool is_chainable(Cell* cell) + bool is_chainable(Cell *cell) { if (!(is_add(cell) || is_subtract(cell))) return false; @@ -111,25 +101,24 @@ struct AluInfo { } }; -struct Rewriter -{ - Module* module; - Cells& cells; +struct Rewriter { + Module *module; + Cells &cells; Traversal traversal; AluInfo alu_info; - Rewriter(Module* module, Cells& cells) : module(module), cells(cells), traversal(module), alu_info{cells, traversal} {} + Rewriter(Module *module, Cells &cells) : module(module), cells(cells), traversal(module), alu_info{cells, traversal} {} - Cell* sole_chainable_consumer(SigSpec sig, const pool& candidates) + Cell *sole_chainable_consumer(SigSpec sig, const pool &candidates) { - Cell* consumer = nullptr; + Cell *consumer = nullptr; for (auto bit : sig) { if (!traversal.fanout.count(bit) || traversal.fanout[bit] != 1) return nullptr; if (!traversal.bit_consumers.count(bit) || traversal.bit_consumers[bit].size() != 1) return nullptr; - Cell* c = *traversal.bit_consumers[bit].begin(); + Cell *c = *traversal.bit_consumers[bit].begin(); if (!candidates.count(c)) return nullptr; @@ -142,36 +131,35 @@ struct Rewriter } // Find cells that consume another cell's output. - dict find_parents(const pool& candidates) + dict find_parents(const pool &candidates) { - dict parent_of; + dict parent_of; for (auto cell : candidates) { - Cell* consumer = sole_chainable_consumer( - traversal.sigmap(cell->getPort(ID::Y)), candidates); + Cell *consumer = sole_chainable_consumer(traversal.sigmap(cell->getPort(ID::Y)), candidates); if (consumer && consumer != cell) parent_of[cell] = consumer; } return parent_of; } - std::pair>, pool> invert_parent_map(const dict& parent_of) + std::pair>, pool> invert_parent_map(const dict &parent_of) { - dict> children_of; - pool has_parent; - for (auto& [child, parent] : parent_of) { + dict> children_of; + pool has_parent; + for (auto &[child, parent] : parent_of) { children_of[parent].insert(child); has_parent.insert(child); } return {children_of, has_parent}; } - pool collect_chain(Cell* root, const dict>& children_of) + pool collect_chain(Cell *root, const dict> &children_of) { - pool chain; - std::queue q; + pool chain; + std::queue q; q.push(root); while (!q.empty()) { - Cell* cur = q.front(); + Cell *cur = q.front(); q.pop(); if (!chain.insert(cur).second) continue; @@ -183,7 +171,7 @@ struct Rewriter return chain; } - pool internal_bits(const pool& chain) + pool internal_bits(const pool &chain) { pool bits; for (auto cell : chain) @@ -192,7 +180,7 @@ struct Rewriter return bits; } - static bool overlaps(SigSpec sig, const pool& bits) + static bool overlaps(SigSpec sig, const pool &bits) { for (auto bit : sig) if (bits.count(bit)) @@ -200,7 +188,7 @@ struct Rewriter return false; } - bool feeds_subtracted_port(Cell* child, Cell* parent) + bool feeds_subtracted_port(Cell *child, Cell *parent) { bool parent_subtracts; if (parent->type == ID($sub)) @@ -213,7 +201,7 @@ struct Rewriter if (!parent_subtracts) return false; - SigSpec child_y = traversal.sigmap(child->getPort(ID::Y)); + SigSpec child_y = traversal.sigmap(child->getPort(ID::Y)); SigSpec parent_b = traversal.sigmap(parent->getPort(ID::B)); for (auto bit : child_y) for (auto pbit : parent_b) @@ -222,20 +210,18 @@ struct Rewriter return false; } - std::vector extract_chain_operands( - const pool& chain, - Cell* root, - const dict& parent_of, - int& neg_compensation - ) { + std::vector extract_chain_operands(const pool &chain, Cell *root, const dict &parent_of, + int &neg_compensation) + { pool chain_bits = internal_bits(chain); - dict negated; + dict negated; negated[root] = false; { - std::queue q; + std::queue q; q.push(root); while (!q.empty()) { - Cell* cur = q.front(); q.pop(); + Cell *cur = q.front(); + q.pop(); for (auto cell : chain) { if (!parent_of.count(cell) || parent_of.at(cell) != cur) continue; @@ -266,23 +252,25 @@ struct Rewriter if (!overlaps(a, chain_bits)) { bool neg = cell_neg; operands.push_back({a, a_signed, neg}); - if (neg) neg_compensation++; + if (neg) + neg_compensation++; } if (!overlaps(b, chain_bits)) { bool neg = cell_neg ^ b_sub; operands.push_back({b, b_signed, neg}); - if (neg) neg_compensation++; + if (neg) + neg_compensation++; } } return operands; } - bool extract_macc_operands(Cell* cell, std::vector& operands, int& neg_compensation) + bool extract_macc_operands(Cell *cell, std::vector &operands, int &neg_compensation) { Macc macc(cell); neg_compensation = 0; - for (auto& term : macc.terms) { + for (auto &term : macc.terms) { // Bail on multiplication if (GetSize(term.in_b) != 0) return false; @@ -308,17 +296,13 @@ struct Rewriter return sig; } - void replace_with_csa_tree( - std::vector& operands, - SigSpec result_y, - int neg_compensation, - const char* desc - ) { + void replace_with_csa_tree(std::vector &operands, SigSpec result_y, int neg_compensation, const char *desc) + { int width = GetSize(result_y); std::vector extended; extended.reserve(operands.size() + 1); - for (auto& op : operands) { + for (auto &op : operands) { SigSpec s = extend_operand(op.sig, op.is_signed, width); if (op.negate) s = module->Not(NEW_ID, s); @@ -339,7 +323,7 @@ struct Rewriter void process_chains() { - pool candidates; + pool candidates; for (auto cell : cells.addsub) candidates.insert(cell); for (auto cell : cells.alu) @@ -352,12 +336,12 @@ struct Rewriter auto parent_of = find_parents(candidates); auto [children_of, has_parent] = invert_parent_map(parent_of); - pool processed; + pool processed; for (auto root : candidates) { if (has_parent.count(root) || processed.count(root)) continue; // Not a tree root - pool chain = collect_chain(root, children_of); + pool chain = collect_chain(root, children_of); if (chain.size() < 2) continue; @@ -391,13 +375,14 @@ struct Rewriter } }; -void run(Module* module) { +void run(Module *module) +{ Cells cells(module); if (cells.empty()) return; - Rewriter rewriter {module, cells}; + Rewriter rewriter{module, cells}; rewriter.process_chains(); rewriter.process_maccs(); } @@ -421,7 +406,7 @@ struct CsaTreePass : public Pass { log("\n"); } - void execute(std::vector args, RTLIL::Design* design) override + void execute(std::vector args, RTLIL::Design *design) override { log_header(design, "Executing CSA_TREE pass.\n"); From 135812ab024d1dc3616df6f00a2042940171e5d1 Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 1 Apr 2026 13:30:34 +0200 Subject: [PATCH 038/176] Further CSA cleanup. --- passes/techmap/csa_tree.cc | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/csa_tree.cc index 323fd6818..110575a0e 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/csa_tree.cc @@ -1,5 +1,10 @@ /** * Replaces chains of $add/$sub and $macc cells with carry-save adder trees + * + * Terminology: + * - parent: Cells that consume another cell's output + * - chainable: Adds/subs with no carry-out usage + * - chain: Connected path of chainable cells */ #include "kernel/macc.h" @@ -83,8 +88,6 @@ struct AluInfo { return GetSize(bi) == 1 && bi[0] == State::S0 && GetSize(ci) == 1 && ci[0] == State::S0; } - // Chainable cells are adds/subs with no carry usage, connected chainable - // cells form chains that can be replaced with CSA trees. bool is_chainable(Cell *cell) { if (!(is_add(cell) || is_subtract(cell))) @@ -130,7 +133,6 @@ struct Rewriter { return consumer; } - // Find cells that consume another cell's output. dict find_parents(const pool &candidates) { dict parent_of; @@ -201,6 +203,7 @@ struct Rewriter { if (!parent_subtracts) return false; + // Check if any bit of child's Y connects to parent's B SigSpec child_y = traversal.sigmap(child->getPort(ID::Y)); SigSpec parent_b = traversal.sigmap(parent->getPort(ID::B)); for (auto bit : child_y) @@ -214,6 +217,8 @@ struct Rewriter { int &neg_compensation) { pool chain_bits = internal_bits(chain); + + // Propagate negation flags through chain dict negated; negated[root] = false; { @@ -233,15 +238,12 @@ struct Rewriter { } } + // Extract leaf operands std::vector operands; neg_compensation = 0; for (auto cell : chain) { - bool cell_neg; - if (negated.count(cell)) - cell_neg = negated[cell]; - else - cell_neg = false; + bool cell_neg = negated.count(cell) ? negated[cell] : false; SigSpec a = traversal.sigmap(cell->getPort(ID::A)); SigSpec b = traversal.sigmap(cell->getPort(ID::B)); @@ -249,10 +251,10 @@ struct Rewriter { bool b_signed = cell->getParam(ID::B_SIGNED).as_bool(); bool b_sub = (cell->type == ID($sub)) || (cells.is_alu(cell) && alu_info.is_subtract(cell)); + // Only add operands not produced by other chain cells if (!overlaps(a, chain_bits)) { - bool neg = cell_neg; - operands.push_back({a, a_signed, neg}); - if (neg) + operands.push_back({a, a_signed, cell_neg}); + if (cell_neg) neg_compensation++; } if (!overlaps(b, chain_bits)) { From c3c577f333a3a201bc757810de9ed3f87ac4d067 Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 1 Apr 2026 18:40:51 +0200 Subject: [PATCH 039/176] Fix test cases. --- passes/techmap/csa_tree.cc | 3 +- tests/csa_tree/csa_tree_add_chains.ys | 111 +++++++------------ tests/csa_tree/csa_tree_alu_macc_equiv.ys | 126 ++++------------------ tests/csa_tree/csa_tree_edge_cases.ys | 12 +-- tests/csa_tree/csa_tree_idempotent.ys | 2 +- tests/csa_tree/csa_tree_sub_chains.ys | 8 +- 6 files changed, 67 insertions(+), 195 deletions(-) diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/csa_tree.cc index 110575a0e..132b4bcc7 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/csa_tree.cc @@ -213,8 +213,7 @@ struct Rewriter { return false; } - std::vector extract_chain_operands(const pool &chain, Cell *root, const dict &parent_of, - int &neg_compensation) + std::vector extract_chain_operands(const pool &chain, Cell *root, const dict &parent_of, int &neg_compensation) { pool chain_bits = internal_bits(chain); diff --git a/tests/csa_tree/csa_tree_add_chains.ys b/tests/csa_tree/csa_tree_add_chains.ys index 98067ce16..ad9a1ddfa 100644 --- a/tests/csa_tree/csa_tree_add_chains.ys +++ b/tests/csa_tree/csa_tree_add_chains.ys @@ -60,18 +60,22 @@ select -assert-count 14 t:$fa select -assert-count 1 t:$add design -reset -read_verilog < Date: Wed, 8 Apr 2026 12:14:02 +0200 Subject: [PATCH 040/176] Rename csa_tree to arith_tree. --- Makefile | 2 +- passes/techmap/Makefile.inc | 2 +- passes/techmap/{csa_tree.cc => arith_tree.cc} | 16 +++---- techlibs/common/synth.cc | 16 +++---- .../arith_tree_add_chains.ys} | 20 ++++----- .../arith_tree_alu_macc_equiv.ys} | 14 +++--- .../arith_tree_edge_cases.ys} | 44 +++++++++---------- .../arith_tree_equiv.ys} | 22 +++++----- .../arith_tree_idempotent.ys} | 8 ++-- .../arith_tree_negative.ys} | 10 ++--- .../arith_tree_sub_chains.ys} | 26 +++++------ tests/{csa_tree => arith_tree}/run-test.sh | 0 12 files changed, 90 insertions(+), 90 deletions(-) rename passes/techmap/{csa_tree.cc => arith_tree.cc} (94%) rename tests/{csa_tree/csa_tree_add_chains.ys => arith_tree/arith_tree_add_chains.ys} (97%) rename tests/{csa_tree/csa_tree_alu_macc_equiv.ys => arith_tree/arith_tree_alu_macc_equiv.ys} (91%) rename tests/{csa_tree/csa_tree_edge_cases.ys => arith_tree/arith_tree_edge_cases.ys} (96%) rename tests/{csa_tree/csa_tree_equiv.ys => arith_tree/arith_tree_equiv.ys} (92%) rename tests/{csa_tree/csa_tree_idempotent.ys => arith_tree/arith_tree_idempotent.ys} (94%) rename tests/{csa_tree/csa_tree_negative.ys => arith_tree/arith_tree_negative.ys} (95%) rename tests/{csa_tree/csa_tree_sub_chains.ys => arith_tree/arith_tree_sub_chains.ys} (96%) rename tests/{csa_tree => arith_tree}/run-test.sh (100%) diff --git a/Makefile b/Makefile index ad8367eeb..8c5524d42 100644 --- a/Makefile +++ b/Makefile @@ -953,7 +953,7 @@ MK_TEST_DIRS += tests/verilog # Tests that don't generate .mk SH_TEST_DIRS = -SH_TEST_DIRS += tests/csa_tree +SH_TEST_DIRS += tests/arith_tree SH_TEST_DIRS += tests/simple SH_TEST_DIRS += tests/simple_abc9 SH_TEST_DIRS += tests/hana diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 190b93570..eccad8998 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -55,7 +55,7 @@ OBJS += passes/techmap/extractinv.o OBJS += passes/techmap/cellmatch.o OBJS += passes/techmap/clockgate.o OBJS += passes/techmap/constmap.o -OBJS += passes/techmap/csa_tree.o +OBJS += passes/techmap/arith_tree.o endif ifeq ($(DISABLE_SPAWN),0) diff --git a/passes/techmap/csa_tree.cc b/passes/techmap/arith_tree.cc similarity index 94% rename from passes/techmap/csa_tree.cc rename to passes/techmap/arith_tree.cc index 132b4bcc7..92e9239f6 100644 --- a/passes/techmap/csa_tree.cc +++ b/passes/techmap/arith_tree.cc @@ -297,7 +297,7 @@ struct Rewriter { return sig; } - void replace_with_csa_tree(std::vector &operands, SigSpec result_y, int neg_compensation, const char *desc) + void replace_with_carry_save_tree(std::vector &operands, SigSpec result_y, int neg_compensation, const char *desc) { int width = GetSize(result_y); std::vector extended; @@ -354,7 +354,7 @@ struct Rewriter { if (operands.size() < 3) continue; - replace_with_csa_tree(operands, root->getPort(ID::Y), neg_compensation, "Replaced add/sub chain"); + replace_with_carry_save_tree(operands, root->getPort(ID::Y), neg_compensation, "Replaced add/sub chain"); for (auto cell : chain) module->remove(cell); } @@ -370,7 +370,7 @@ struct Rewriter { if (operands.size() < 3) continue; - replace_with_csa_tree(operands, cell->getPort(ID::Y), neg_compensation, "Replaced $macc"); + replace_with_carry_save_tree(operands, cell->getPort(ID::Y), neg_compensation, "Replaced $macc"); module->remove(cell); } } @@ -388,14 +388,14 @@ void run(Module *module) rewriter.process_maccs(); } -struct CsaTreePass : public Pass { - CsaTreePass() : Pass("csa_tree", "convert add/sub/macc chains to carry-save adder trees") {} +struct ArithTreePass : public Pass { + ArithTreePass() : Pass("arith_tree", "convert add/sub/macc chains to carry-save adder trees") {} void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" csa_tree [selection]\n"); + log(" arith_tree [selection]\n"); log("\n"); log("This pass replaces chains of $add/$sub cells, $alu cells (with constant\n"); log("BI/CI), and $macc/$macc_v2 cells (without multiplications) with carry-save\n"); @@ -409,7 +409,7 @@ struct CsaTreePass : public Pass { void execute(std::vector args, RTLIL::Design *design) override { - log_header(design, "Executing CSA_TREE pass.\n"); + log_header(design, "Executing ARITH_TREE pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -420,6 +420,6 @@ struct CsaTreePass : public Pass { run(module); } } -} CsaTreePass; +} ArithTreePass; PRIVATE_NAMESPACE_END diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 1490c6adc..daebd789a 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -67,8 +67,8 @@ struct SynthPass : public ScriptPass { log(" -booth\n"); log(" run the booth pass to map $mul to Booth encoded multipliers\n"); log("\n"); - log(" -csa\n"); - log(" run the csa_tree pass to convert $add/$sub chains and $macc cells to\n"); + log(" -arith_tree\n"); + log(" run the arith_tree pass to convert $add/$sub chains and $macc cells to\n"); log(" carry-save adder trees.\n"); log("\n"); log(" -noalumacc\n"); @@ -112,7 +112,7 @@ struct SynthPass : public ScriptPass { } string top_module, fsm_opts, memory_opts, abc; - bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, csa, hieropt, relative_share; + bool autotop, flatten, noalumacc, nofsm, noabc, noshare, flowmap, booth, arith_tree, hieropt, relative_share; int lut; std::vector techmap_maps; @@ -131,7 +131,7 @@ struct SynthPass : public ScriptPass { noshare = false; flowmap = false; booth = false; - csa = false; + arith_tree = false; hieropt = false; relative_share = false; abc = "abc"; @@ -192,8 +192,8 @@ struct SynthPass : public ScriptPass { booth = true; continue; } - if (args[argidx] == "-csa") { - csa = true; + if (args[argidx] == "-arith_tree") { + arith_tree = true; continue; } if (args[argidx] == "-nordff") { @@ -297,8 +297,8 @@ struct SynthPass : public ScriptPass { run("booth", " (if -booth)"); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); - if (csa || help_mode) - run("csa_tree", " (if -csa)"); + if (arith_tree || help_mode) + run("arith_tree", " (if -arith_tree)"); if (!noshare) run("share", " (unless -noshare)"); run("opt" + hieropt_flag); diff --git a/tests/csa_tree/csa_tree_add_chains.ys b/tests/arith_tree/arith_tree_add_chains.ys similarity index 97% rename from tests/csa_tree/csa_tree_add_chains.ys rename to tests/arith_tree/arith_tree_add_chains.ys index ad9a1ddfa..f293ed9da 100644 --- a/tests/csa_tree/csa_tree_add_chains.ys +++ b/tests/arith_tree/arith_tree_add_chains.ys @@ -8,7 +8,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 1 t:$fa select -assert-count 1 t:$add design -reset @@ -23,7 +23,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 3 t:$fa select -assert-count 1 t:$add design -reset @@ -38,7 +38,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 6 t:$fa select -assert-count 1 t:$add design -reset @@ -55,7 +55,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 14 t:$fa select -assert-count 1 t:$add design -reset @@ -76,7 +76,7 @@ endmodule EOT hierarchy -auto-top select -assert-count 2 t:$alu -csa_tree +arith_tree opt_clean select -assert-count 1 t:$fa select -assert-count 1 t:$add @@ -102,7 +102,7 @@ endmodule EOT hierarchy -auto-top select -assert-count 3 t:$alu -csa_tree +arith_tree opt_clean select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -131,7 +131,7 @@ endmodule EOT hierarchy -auto-top select -assert-count 4 t:$alu -csa_tree +arith_tree opt_clean select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -151,7 +151,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-count 1 t:$fa select -assert-count 1 t:$add @@ -170,7 +170,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -189,7 +189,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-count 6 t:$fa select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_alu_macc_equiv.ys b/tests/arith_tree/arith_tree_alu_macc_equiv.ys similarity index 91% rename from tests/csa_tree/csa_tree_alu_macc_equiv.ys rename to tests/arith_tree/arith_tree_alu_macc_equiv.ys index 7e9e39ae2..95839d04f 100644 --- a/tests/csa_tree/csa_tree_alu_macc_equiv.ys +++ b/tests/arith_tree/arith_tree_alu_macc_equiv.ys @@ -10,7 +10,7 @@ hierarchy -auto-top proc alumacc opt -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 1 t:$fa select -assert-count 1 t:$add @@ -28,7 +28,7 @@ hierarchy -auto-top proc alumacc opt -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -46,7 +46,7 @@ hierarchy -auto-top proc alumacc opt -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 6 t:$fa select -assert-count 1 t:$add @@ -64,7 +64,7 @@ hierarchy -auto-top proc alumacc opt -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -82,7 +82,7 @@ hierarchy -auto-top proc alumacc opt -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-min 1 t:$fa select -assert-count 1 t:$add @@ -100,8 +100,8 @@ hierarchy -auto-top proc alumacc opt -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-min 1 t:$fa select -assert-count 1 t:$add -design -reset +design -reset \ No newline at end of file diff --git a/tests/csa_tree/csa_tree_edge_cases.ys b/tests/arith_tree/arith_tree_edge_cases.ys similarity index 96% rename from tests/csa_tree/csa_tree_edge_cases.ys rename to tests/arith_tree/arith_tree_edge_cases.ys index 97feb3f5c..fd40f2aa7 100644 --- a/tests/csa_tree/csa_tree_edge_cases.ys +++ b/tests/arith_tree/arith_tree_edge_cases.ys @@ -8,7 +8,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 1 t:$fa select -assert-count 1 t:$add design -reset @@ -23,7 +23,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -38,7 +38,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -56,7 +56,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -71,7 +71,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -86,7 +86,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -101,7 +101,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -117,7 +117,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 4 t:$fa select -assert-count 2 t:$add design -reset @@ -141,7 +141,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add design -reset @@ -158,7 +158,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree select -assert-none t:$fa select -assert-none t:$add select -assert-none t:$sub @@ -177,7 +177,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree select -assert-none t:$fa select -assert-none t:$add select -assert-none t:$sub @@ -196,7 +196,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree select -assert-none t:$fa select -assert-none t:$add select -assert-none t:$sub @@ -215,7 +215,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-none t:$fa select -assert-min 1 t:$macc t:$macc_v2 %u @@ -235,7 +235,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-none t:$fa select -assert-count 2 t:$alu @@ -253,7 +253,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-none t:$fa design -reset @@ -273,7 +273,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -293,7 +293,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -322,7 +322,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-min 1 t:$dff design -reset @@ -341,7 +341,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 1 t:$fa select -assert-count 1 t:$add @@ -361,7 +361,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -381,7 +381,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree select -assert-none t:$fa select -assert-none t:$add select -assert-none t:$sub @@ -400,7 +400,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-none t:$fa select -assert-min 1 t:$macc t:$macc_v2 %u diff --git a/tests/csa_tree/csa_tree_equiv.ys b/tests/arith_tree/arith_tree_equiv.ys similarity index 92% rename from tests/csa_tree/csa_tree_equiv.ys rename to tests/arith_tree/arith_tree_equiv.ys index 966f8ccff..9595d3070 100644 --- a/tests/csa_tree/csa_tree_equiv.ys +++ b/tests/arith_tree/arith_tree_equiv.ys @@ -8,7 +8,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 1 t:$fa select -assert-count 1 t:$add @@ -24,7 +24,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -40,7 +40,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -56,7 +56,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 6 t:$fa select -assert-count 1 t:$add @@ -72,7 +72,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -90,7 +90,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 1 t:$fa select -assert-count 1 t:$add @@ -106,7 +106,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -122,7 +122,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-min 1 t:$fa select -assert-count 1 t:$add @@ -138,7 +138,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-min 1 t:$fa select -assert-count 1 t:$add @@ -154,7 +154,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -171,7 +171,7 @@ endmodule EOT hierarchy -auto-top proc -equiv_opt csa_tree +equiv_opt arith_tree design -load postopt select -assert-count 2 t:$fa select -assert-count 1 t:$add diff --git a/tests/csa_tree/csa_tree_idempotent.ys b/tests/arith_tree/arith_tree_idempotent.ys similarity index 94% rename from tests/csa_tree/csa_tree_idempotent.ys rename to tests/arith_tree/arith_tree_idempotent.ys index f4d9f7836..3ca0fcc90 100644 --- a/tests/csa_tree/csa_tree_idempotent.ys +++ b/tests/arith_tree/arith_tree_idempotent.ys @@ -9,11 +9,11 @@ EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 6 t:$fa select -assert-count 1 t:$add -csa_tree +arith_tree select -assert-count 6 t:$fa select -assert-count 1 t:$add select -assert-none t:$sub @@ -32,13 +32,13 @@ proc alumacc opt_clean -csa_tree +arith_tree select -assert-count 6 t:$fa select -assert-count 1 t:$add select -assert-none t:$sub select -assert-none t:$alu -csa_tree +arith_tree select -assert-count 6 t:$fa select -assert-count 1 t:$add select -assert-none t:$sub diff --git a/tests/csa_tree/csa_tree_negative.ys b/tests/arith_tree/arith_tree_negative.ys similarity index 95% rename from tests/csa_tree/csa_tree_negative.ys rename to tests/arith_tree/arith_tree_negative.ys index 1cdcf3deb..beb540dd9 100644 --- a/tests/csa_tree/csa_tree_negative.ys +++ b/tests/arith_tree/arith_tree_negative.ys @@ -8,7 +8,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-none t:$fa select -assert-count 1 t:$add design -reset @@ -25,7 +25,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-none t:$fa design -reset @@ -39,7 +39,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-none t:$fa select -assert-count 1 t:$sub design -reset @@ -54,7 +54,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-none t:$fa select -assert-max 1 t:$add design -reset @@ -71,7 +71,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 2 t:$add design -reset diff --git a/tests/csa_tree/csa_tree_sub_chains.ys b/tests/arith_tree/arith_tree_sub_chains.ys similarity index 96% rename from tests/csa_tree/csa_tree_sub_chains.ys rename to tests/arith_tree/arith_tree_sub_chains.ys index 3652e5c90..a34cb3868 100644 --- a/tests/csa_tree/csa_tree_sub_chains.ys +++ b/tests/arith_tree/arith_tree_sub_chains.ys @@ -8,7 +8,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add select -assert-count 1 t:$not @@ -25,7 +25,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 3 t:$fa select -assert-count 1 t:$add select -assert-count 1 t:$not @@ -42,7 +42,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 3 t:$fa select -assert-count 1 t:$add select -assert-count 3 t:$not @@ -59,7 +59,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 4 t:$fa select -assert-count 1 t:$add select -assert-count 2 t:$not @@ -76,7 +76,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 3 t:$fa select -assert-count 1 t:$add select -assert-count 2 t:$not @@ -94,7 +94,7 @@ endmodule EOT hierarchy -auto-top proc -csa_tree +arith_tree select -assert-count 2 t:$fa select -assert-count 1 t:$add select -assert-count 1 t:$not @@ -113,7 +113,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 2 t:$fa select -assert-count 1 t:$add @@ -133,7 +133,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -153,7 +153,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -173,7 +173,7 @@ hierarchy -auto-top proc alumacc opt_clean -csa_tree +arith_tree opt_clean select -assert-count 3 t:$fa select -assert-count 1 t:$add @@ -193,7 +193,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-none t:$macc t:$macc_v2 %u select -assert-min 1 t:$fa @@ -212,7 +212,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-none t:$macc t:$macc_v2 %u select -assert-min 1 t:$fa @@ -232,7 +232,7 @@ hierarchy -auto-top proc alumacc opt -csa_tree +arith_tree opt_clean select -assert-none t:$macc t:$macc_v2 %u select -assert-count 4 t:$fa diff --git a/tests/csa_tree/run-test.sh b/tests/arith_tree/run-test.sh similarity index 100% rename from tests/csa_tree/run-test.sh rename to tests/arith_tree/run-test.sh From 4506dffa9f3f99fbbc5280026439046a910ad78a Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 13 Apr 2026 12:45:55 +0200 Subject: [PATCH 041/176] Fix use after free. --- passes/techmap/arith_tree.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/passes/techmap/arith_tree.cc b/passes/techmap/arith_tree.cc index 92e9239f6..9494fa958 100644 --- a/passes/techmap/arith_tree.cc +++ b/passes/techmap/arith_tree.cc @@ -337,27 +337,28 @@ struct Rewriter { auto parent_of = find_parents(candidates); auto [children_of, has_parent] = invert_parent_map(parent_of); - pool processed; + pool to_remove; for (auto root : candidates) { - if (has_parent.count(root) || processed.count(root)) + if (has_parent.count(root) || to_remove.count(root)) continue; // Not a tree root pool chain = collect_chain(root, children_of); if (chain.size() < 2) continue; - for (auto c : chain) - processed.insert(c); - int neg_compensation; auto operands = extract_chain_operands(chain, root, parent_of, neg_compensation); if (operands.size() < 3) continue; + for (auto c : chain) + to_remove.insert(c); + replace_with_carry_save_tree(operands, root->getPort(ID::Y), neg_compensation, "Replaced add/sub chain"); - for (auto cell : chain) - module->remove(cell); } + + for (auto cell : to_remove) + module->remove(cell); } void process_maccs() From 3e45f9729ed8bc0962d614c8d0c69144dbace273 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 13 Apr 2026 16:48:27 +0200 Subject: [PATCH 042/176] fix $specrule port naming --- kernel/celltypes.h | 2 +- kernel/constids.inc | 2 -- techlibs/common/simlib.v | 4 ++-- tests/functional/rtlil_cells.py | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 50dee573e..ceff0bd1a 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -103,7 +103,7 @@ struct CellTypes setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}); setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool()); setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool()); - setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool()); + setup_type(ID($specrule), {ID::SRC_EN, ID::DST_EN, ID::SRC, ID::DST}, pool()); setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool()); setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool()); setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}); diff --git a/kernel/constids.inc b/kernel/constids.inc index c99aa788d..61c9b3a8c 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -459,9 +459,7 @@ X(EDGE_POL) X(EFX_ADD) X(EN) X(ENPOL) -X(EN_DST) X(EN_POLARITY) -X(EN_SRC) X(EQN) X(F) X(FDCE) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index e0fb9fbfa..3f34bfd22 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1976,7 +1976,7 @@ endmodule // -------------------------------------------------------- //* group spec -module \$specrule (EN_SRC, EN_DST, SRC, DST); +module \$specrule (SRC_EN, DST_EN, SRC, DST); parameter TYPE = ""; parameter T_LIMIT = 0; @@ -1991,7 +1991,7 @@ parameter SRC_POL = 0; parameter DST_PEN = 0; parameter DST_POL = 0; -input EN_SRC, EN_DST; +input SRC_EN, DST_EN; input [SRC_WIDTH-1:0] SRC; input [DST_WIDTH-1:0] DST; diff --git a/tests/functional/rtlil_cells.py b/tests/functional/rtlil_cells.py index 964d81ddf..9a44821d3 100644 --- a/tests/functional/rtlil_cells.py +++ b/tests/functional/rtlil_cells.py @@ -337,7 +337,7 @@ rtlil_cells = [ # ("tribuf", ["A", "EN", "Y"]), # ("specify2", ["EN", "SRC", "DST"]), # ("specify3", ["EN", "SRC", "DST", "DAT"]), -# ("specrule", ["EN_SRC", "EN_DST", "SRC", "DST"]), +# ("specrule", ["SRC_EN", "DST_EN", "SRC", "DST"]), BWCell("bweqx", [10, 16, 40]), BWCell("bwmux", [10, 16, 40]), FFCell("ff", [10, 20, 40]), From 0b3d03e69ccf25aa69e9f9ae01a669204541a30f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 13 Apr 2026 16:48:51 +0200 Subject: [PATCH 043/176] newcelltypes: fix $specrule port naming --- kernel/newcelltypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/newcelltypes.h b/kernel/newcelltypes.h index bb14293a3..eb42019af 100644 --- a/kernel/newcelltypes.h +++ b/kernel/newcelltypes.h @@ -80,7 +80,7 @@ struct CellTableBuilder { setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, features); setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, {}, features); setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, {}, features); - setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, {}, features); + setup_type(ID($specrule), {ID::SRC_EN, ID::DST_EN, ID::SRC, ID::DST}, {}, features); setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, {}, features); setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, {}, features); setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y}, features); From c99855535ae57ae82ff216dda29bffadba760c23 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 09:41:39 +0100 Subject: [PATCH 044/176] Split vanilla-test to separate Makefile --- Makefile | 109 +++---------------------------------------------- tests/Makefile | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 103 deletions(-) create mode 100644 tests/Makefile diff --git a/Makefile b/Makefile index 8c5524d42..cc5a736f2 100644 --- a/Makefile +++ b/Makefile @@ -918,111 +918,14 @@ else ABCOPT="" endif -# Tests that generate .mk with tests/gen-tests-makefile.sh -MK_TEST_DIRS = -MK_TEST_DIRS += tests/arch/analogdevices -MK_TEST_DIRS += tests/arch/anlogic -MK_TEST_DIRS += tests/arch/ecp5 -MK_TEST_DIRS += tests/arch/efinix -MK_TEST_DIRS += tests/arch/gatemate -MK_TEST_DIRS += tests/arch/gowin -MK_TEST_DIRS += tests/arch/ice40 -MK_TEST_DIRS += tests/arch/intel_alm -MK_TEST_DIRS += tests/arch/machxo2 -MK_TEST_DIRS += tests/arch/microchip -MK_TEST_DIRS += tests/arch/nanoxplore -MK_TEST_DIRS += tests/arch/nexus -MK_TEST_DIRS += tests/arch/quicklogic/pp3 -MK_TEST_DIRS += tests/arch/quicklogic/qlf_k6n10f -MK_TEST_DIRS += tests/arch/xilinx -MK_TEST_DIRS += tests/bugpoint -MK_TEST_DIRS += tests/opt -MK_TEST_DIRS += tests/sat -MK_TEST_DIRS += tests/sdc -MK_TEST_DIRS += tests/sim -MK_TEST_DIRS += tests/svtypes -MK_TEST_DIRS += tests/techmap -MK_TEST_DIRS += tests/various -MK_TEST_DIRS += tests/rtlil -ifeq ($(ENABLE_VERIFIC),1) -ifneq ($(YOSYS_NOVERIFIC),1) -MK_TEST_DIRS += tests/verific -endif -endif -MK_TEST_DIRS += tests/verilog - -# Tests that don't generate .mk -SH_TEST_DIRS = -SH_TEST_DIRS += tests/arith_tree -SH_TEST_DIRS += tests/simple -SH_TEST_DIRS += tests/simple_abc9 -SH_TEST_DIRS += tests/hana -SH_TEST_DIRS += tests/asicworld -# SH_TEST_DIRS += tests/realmath -SH_TEST_DIRS += tests/share -SH_TEST_DIRS += tests/opt_share -SH_TEST_DIRS += tests/fsm -SH_TEST_DIRS += tests/memlib -SH_TEST_DIRS += tests/bram -SH_TEST_DIRS += tests/svinterfaces -SH_TEST_DIRS += tests/xprop -SH_TEST_DIRS += tests/select -SH_TEST_DIRS += tests/peepopt -SH_TEST_DIRS += tests/proc -SH_TEST_DIRS += tests/blif -SH_TEST_DIRS += tests/arch -SH_TEST_DIRS += tests/rpc -SH_TEST_DIRS += tests/memfile -SH_TEST_DIRS += tests/fmt -SH_TEST_DIRS += tests/cxxrtl -SH_TEST_DIRS += tests/liberty -ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -SH_TEST_DIRS += tests/functional -endif - -# Tests that don't generate .mk and need special args -SH_ABC_TEST_DIRS = -SH_ABC_TEST_DIRS += tests/memories -SH_ABC_TEST_DIRS += tests/aiger -SH_ABC_TEST_DIRS += tests/alumacc - -# seed-tests/ is a dummy string, not a directory -.PHONY: seed-tests -seed-tests: $(SH_TEST_DIRS:%=seed-tests/%) -.PHONY: seed-tests/% -seed-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) - +cd $* && bash run-test.sh $(SEEDOPT) - +@echo "...passed tests in $*" - -# abcopt-tests/ is a dummy string, not a directory -.PHONY: abcopt-tests -abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-tests/%) -abcopt-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) - +@echo "...passed tests in $*" - -# makefile-tests/ is a dummy string, not a directory -.PHONY: makefile-tests -makefile-tests: $(MK_TEST_DIRS:%=makefile-tests/%) -# this target actually emits .mk files -%.mk: - +cd $(dir $*) && bash run-test.sh -# this one spawns submake on each -makefile-tests/%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) - $(MAKE) -C $* -f run-test.mk - +@echo "...passed tests in $*" - test: vanilla-test unit-test -vanilla-test: makefile-tests abcopt-tests seed-tests - @echo "" - @echo " Passed \"make vanilla-test\"." -ifeq ($(ENABLE_VERIFIC),1) -ifeq ($(YOSYS_NOVERIFIC),1) - @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." -endif -endif - @echo "" +.PHONY: vanilla-test + +vanilla-test: + @$(MAKE) -C tests vanilla-test \ + $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ + $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 000000000..3ec125e48 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,105 @@ +# Tests that generate .mk with ./gen-tests-makefile.sh +MK_TEST_DIRS = +MK_TEST_DIRS += ./arch/analogdevices +MK_TEST_DIRS += ./arch/anlogic +MK_TEST_DIRS += ./arch/ecp5 +MK_TEST_DIRS += ./arch/efinix +MK_TEST_DIRS += ./arch/gatemate +MK_TEST_DIRS += ./arch/gowin +MK_TEST_DIRS += ./arch/ice40 +MK_TEST_DIRS += ./arch/intel_alm +MK_TEST_DIRS += ./arch/machxo2 +MK_TEST_DIRS += ./arch/microchip +MK_TEST_DIRS += ./arch/nanoxplore +MK_TEST_DIRS += ./arch/nexus +MK_TEST_DIRS += ./arch/quicklogic/pp3 +MK_TEST_DIRS += ./arch/quicklogic/qlf_k6n10f +MK_TEST_DIRS += ./arch/xilinx +MK_TEST_DIRS += ./bugpoint +MK_TEST_DIRS += ./opt +MK_TEST_DIRS += ./sat +MK_TEST_DIRS += ./sdc +MK_TEST_DIRS += ./sim +MK_TEST_DIRS += ./svtypes +MK_TEST_DIRS += ./techmap +MK_TEST_DIRS += ./various +MK_TEST_DIRS += ./rtlil +ifeq ($(ENABLE_VERIFIC),1) +ifneq ($(YOSYS_NOVERIFIC),1) +MK_TEST_DIRS += ./verific +endif +endif +MK_TEST_DIRS += ./verilog + +# Tests that don't generate .mk +SH_TEST_DIRS = +SH_TEST_DIRS += ./simple +SH_TEST_DIRS += ./simple_abc9 +SH_TEST_DIRS += ./hana +SH_TEST_DIRS += ./asicworld +# SH_TEST_DIRS += ./realmath +SH_TEST_DIRS += ./share +SH_TEST_DIRS += ./opt_share +SH_TEST_DIRS += ./fsm +SH_TEST_DIRS += ./memlib +SH_TEST_DIRS += ./bram +SH_TEST_DIRS += ./svinterfaces +SH_TEST_DIRS += ./xprop +SH_TEST_DIRS += ./select +SH_TEST_DIRS += ./peepopt +SH_TEST_DIRS += ./proc +SH_TEST_DIRS += ./blif +SH_TEST_DIRS += ./arch +SH_TEST_DIRS += ./rpc +SH_TEST_DIRS += ./memfile +SH_TEST_DIRS += ./fmt +SH_TEST_DIRS += ./cxxrtl +SH_TEST_DIRS += ./liberty +ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +SH_TEST_DIRS += ./functional +endif + +# Tests that don't generate .mk and need special args +SH_ABC_TEST_DIRS = +SH_ABC_TEST_DIRS += ./memories +SH_ABC_TEST_DIRS += ./aiger +SH_ABC_TEST_DIRS += ./alumacc + +all: vanilla-test + +# seed-./ is a dummy string, not a directory +.PHONY: seed-tests +seed-tests: $(SH_TEST_DIRS:%=seed-./%) +.PHONY: seed-./% +seed-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) + +cd $* && bash run-test.sh $(SEEDOPT) + +@echo "...passed tests in $*" + +# abcopt-./ is a dummy string, not a directory +.PHONY: abcopt-tests +abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) +abcopt-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) + +@echo "...passed tests in $*" + +# makefile-./ is a dummy string, not a directory +.PHONY: makefile-tests +makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) +# this target actually emits .mk files +%.mk: + +cd $(dir $*) && bash run-test.sh +# this one spawns submake on each +makefile-./%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) + $(MAKE) -C $* -f run-test.mk + +@echo "...passed tests in $*" + +vanilla-test: makefile-tests abcopt-tests seed-tests + @echo "" + @echo " Passed \"make vanilla-test\"." +ifeq ($(ENABLE_VERIFIC),1) +ifeq ($(YOSYS_NOVERIFIC),1) + @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." +endif +endif + @echo "" + From 5494000fd79a5ec28d30af0c38df261592ba1331 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 10:01:23 +0100 Subject: [PATCH 045/176] Move clean for tests in proper Makefile --- Makefile | 10 +--------- tests/Makefile | 10 ++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index cc5a736f2..6b4d45ba9 100644 --- a/Makefile +++ b/Makefile @@ -1091,16 +1091,8 @@ clean: clean-py clean-unit-test rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) rm -f kernel/version_*.o kernel/version_*.cc rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d - rm -rf tests/asicworld/*.out tests/asicworld/*.log - rm -rf tests/hana/*.out tests/hana/*.log - rm -rf tests/simple/*.out tests/simple/*.log - rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp - rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log - rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp tests/various/temp rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_* - rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff - rm -f tests/tools/cmp_tbdata - rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + -$(MAKE) -C $(YOSYS_SRC)/tests clean -$(MAKE) -C $(YOSYS_SRC)/docs clean rm -rf docs/util/__pycache__ rm -f libyosys.so diff --git a/tests/Makefile b/tests/Makefile index 3ec125e48..7f4e0f739 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -103,3 +103,13 @@ endif endif @echo "" +clean: + rm -rf ./asicworld/*.out ./asicworld/*.log + rm -rf ./hana/*.out ./hana/*.log + rm -rf ./simple/*.out ./simple/*.log + rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp + rm -rf ./sat/*.log ./techmap/*.log ./various/*.log + rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp + rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff + rm -f ./tools/cmp_tbdata + rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) From 8f7e5e944905642ef5aa930ff9c5e279a03f475b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 10:08:52 +0100 Subject: [PATCH 046/176] Make sure targets are built for tests --- Makefile | 2 +- tests/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6b4d45ba9..aad5130f6 100644 --- a/Makefile +++ b/Makefile @@ -922,7 +922,7 @@ test: vanilla-test unit-test .PHONY: vanilla-test -vanilla-test: +vanilla-test: $(TARGETS) $(EXTRA_TARGETS) @$(MAKE) -C tests vanilla-test \ $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) diff --git a/tests/Makefile b/tests/Makefile index 7f4e0f739..e82c2f718 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -71,14 +71,14 @@ all: vanilla-test .PHONY: seed-tests seed-tests: $(SH_TEST_DIRS:%=seed-./%) .PHONY: seed-./% -seed-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) +seed-./%: %/run-test.sh +cd $* && bash run-test.sh $(SEEDOPT) +@echo "...passed tests in $*" # abcopt-./ is a dummy string, not a directory .PHONY: abcopt-tests abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) -abcopt-./%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) +abcopt-./%: %/run-test.sh +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) +@echo "...passed tests in $*" @@ -89,7 +89,7 @@ makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) %.mk: +cd $(dir $*) && bash run-test.sh # this one spawns submake on each -makefile-./%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) +makefile-./%: %/run-test.mk $(MAKE) -C $* -f run-test.mk +@echo "...passed tests in $*" From ff2dcef53fcb05bab7aa59f386059b9c2c13cb7c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 10:15:27 +0100 Subject: [PATCH 047/176] Propagate ABCOPT and SEEDOPT --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index aad5130f6..97e51633b 100644 --- a/Makefile +++ b/Makefile @@ -925,7 +925,8 @@ test: vanilla-test unit-test vanilla-test: $(TARGETS) $(EXTRA_TARGETS) @$(MAKE) -C tests vanilla-test \ $(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \ - $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) + $(if $(YOSYS_NOVERIFIC),YOSYS_NOVERIFIC=$(YOSYS_NOVERIFIC)) \ + SEEDOPT=$(SEEDOPT) ABCOPT=$(ABCOPT) VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all From 3c2adfb523517d248600490589d5a724e0b7b36b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:02:20 +0100 Subject: [PATCH 048/176] Do not write to console for makefile-tests --- tests/Makefile | 27 ++++++++++++++------------- tests/gen-tests-makefile.sh | 4 ++-- tests/sim/run-test.sh | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index e82c2f718..aaa921ab3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -79,19 +79,20 @@ seed-./%: %/run-test.sh .PHONY: abcopt-tests abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) abcopt-./%: %/run-test.sh - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) >/dev/null 2>&1 +@echo "...passed tests in $*" # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests +#.SILENT: $(MK_TEST_DIRS:%=%/run-test.mk) makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) # this target actually emits .mk files %.mk: - +cd $(dir $*) && bash run-test.sh + +@cd $(dir $*) && bash run-test.sh # this one spawns submake on each makefile-./%: %/run-test.mk - $(MAKE) -C $* -f run-test.mk - +@echo "...passed tests in $*" + @$(MAKE) -C $* -f run-test.mk + @echo "...passed tests in $*" vanilla-test: makefile-tests abcopt-tests seed-tests @echo "" @@ -104,12 +105,12 @@ endif @echo "" clean: - rm -rf ./asicworld/*.out ./asicworld/*.log - rm -rf ./hana/*.out ./hana/*.log - rm -rf ./simple/*.out ./simple/*.log - rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp - rm -rf ./sat/*.log ./techmap/*.log ./various/*.log - rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp - rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff - rm -f ./tools/cmp_tbdata - rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + @rm -rf ./asicworld/*.out ./asicworld/*.log + @rm -rf ./hana/*.out ./hana/*.log + @rm -rf ./simple/*.out ./simple/*.log + @rm -rf ./memories/*.out ./memories/*.log ./memories/*.dmp + @rm -rf ./sat/*.log ./techmap/*.log ./various/*.log + @rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp + @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff + @rm -f ./tools/cmp_tbdata + @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) diff --git a/tests/gen-tests-makefile.sh b/tests/gen-tests-makefile.sh index a0fb23ac3..07d70c2a8 100755 --- a/tests/gen-tests-makefile.sh +++ b/tests/gen-tests-makefile.sh @@ -17,14 +17,14 @@ generate_target() { generate_ys_test() { ys_file=$1 yosys_args_=${2:-} - generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file && mv ${ys_file}.err ${ys_file}.log" + generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file >/dev/null 2>&1 && mv ${ys_file}.err ${ys_file}.log" } # $ generate_tcl_test tcl_file [yosys_args] generate_tcl_test() { tcl_file=$1 yosys_args_=${2:-} - generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file && mv ${tcl_file}.err ${tcl_file}.log" + generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file >/dev/null 2>&1 && mv ${tcl_file}.err ${tcl_file}.log" } # $ generate_bash_test bash_file diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh index 43571e057..cff85eb65 100755 --- a/tests/sim/run-test.sh +++ b/tests/sim/run-test.sh @@ -6,7 +6,7 @@ find tb/* -name tb*.v | while read name; do test_name=$(basename $name .v) echo "Test $test_name" verilog_name=${test_name:3}.v - iverilog -o tb/$test_name.out $name $verilog_name - ./tb/$test_name.out -fst + iverilog -o tb/$test_name.out $name $verilog_name >/dev/null 2>&1 + ./tb/$test_name.out -fst >/dev/null 2>&1 done generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" From fc55f16fae80c601ac84f6a76cbad74d967f367c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:05:47 +0100 Subject: [PATCH 049/176] Ignore some generated files --- tests/various/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/various/.gitignore b/tests/various/.gitignore index 9296a04c0..1431c4096 100644 --- a/tests/various/.gitignore +++ b/tests/various/.gitignore @@ -9,3 +9,4 @@ /temp /smtlib2_module.smt2 /smtlib2_module-filtered.smt2 +/*.aig From 27746713463669afb2db6004773661a29e7e98a6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:18:05 +0100 Subject: [PATCH 050/176] Cleanup for abcopt-tests --- tests/Makefile | 2 +- tests/aiger/run-test.sh | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index aaa921ab3..d34db2100 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -79,7 +79,7 @@ seed-./%: %/run-test.sh .PHONY: abcopt-tests abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) abcopt-./%: %/run-test.sh - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) >/dev/null 2>&1 + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) +@echo "...passed tests in $*" # makefile-./ is a dummy string, not a directory diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index 94d83ede4..5208fa030 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -22,7 +22,7 @@ for aag in *.aag; do # (which would have been created by the reference aig2aig utility, # available from http://fmv.jku.at/aiger/) echo "Checking $aag." - $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" + $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" >/dev/null 2>&1 ../../yosys -qp " read_verilog ${aag%.*}_ref.v prep @@ -34,12 +34,12 @@ design -import gold -as gold design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aag}.log +" -l ${aag}.log >/dev/null 2>&1 done for aig in *.aig; do echo "Checking $aig." - $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" + $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" >/dev/null 2>&1 ../../yosys -qp " read_verilog ${aig%.*}_ref.v prep @@ -51,18 +51,18 @@ design -import gold -as gold design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aig}.log +" -l ${aig}.log >/dev/null 2>&1 done for y in *.ys; do echo "Running $y." - ../../yosys -ql ${y%.*}.log $y + ../../yosys -ql ${y%.*}.log $y >/dev/null 2>&1 done # compare aigmap with reference # make gold with: rm gold/*; yosys --no-version -p "test_cell -aigmap -w gold/ -n 1 -s 1 all" rm -rf gate; mkdir gate -../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" +../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1 ( set -o pipefail diff --brief gold gate | tee aigmap.err From 999255e40cbc2f669eb9a7402c1bb8736ea2c218 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 11:50:30 +0100 Subject: [PATCH 051/176] Clean some seed-tests outputs --- tests/arch/run-test.sh | 6 +++--- tests/blif/run-test.sh | 2 +- tests/cxxrtl/run-test.sh | 2 +- tests/memfile/run-test.sh | 20 ++++++++++---------- tests/proc/run-test.sh | 2 +- tests/select/run-test.sh | 2 +- tests/svinterfaces/runone.sh | 14 +++++++------- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh index 7602717d2..087abf536 100755 --- a/tests/arch/run-test.sh +++ b/tests/arch/run-test.sh @@ -12,12 +12,12 @@ for arch in ../../techlibs/*; do if [ "${defines[$arch_name]}" ]; then for def in ${defines[$arch_name]}; do echo -n "Test $path -D$def ->" - iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path + iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path >/dev/null 2>&1 echo " ok" done else echo -n "Test $path ->" - iverilog -t null -I$arch -g2005-sv $path + iverilog -t null -I$arch -g2005-sv $path >/dev/null 2>&1 echo " ok" fi done @@ -25,6 +25,6 @@ done for path in "../../techlibs/common/simcells.v" "../../techlibs/common/simlib.v"; do echo -n "Test $path ->" - iverilog -t null $path + iverilog -t null $path >/dev/null 2>&1 echo " ok" done diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh index 14b9ead8e..97f12d288 100755 --- a/tests/blif/run-test.sh +++ b/tests/blif/run-test.sh @@ -3,7 +3,7 @@ source ../common-env.sh set -e for x in *.ys; do echo "Running $x.." - ../../yosys --no-version -ql ${x%.ys}.log $x + ../../yosys --no-version -ql ${x%.ys}.log $x >/dev/null 2>&1 done for x in *.blif; do diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh index aa7a0c26c..b21c79899 100755 --- a/tests/cxxrtl/run-test.sh +++ b/tests/cxxrtl/run-test.sh @@ -14,5 +14,5 @@ run_subtest value run_subtest value_fuzz # Compile-only test. -../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" +../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" >/dev/null 2>&1 ${CXX:-g++} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc diff --git a/tests/memfile/run-test.sh b/tests/memfile/run-test.sh index 44c1e4821..e2583ef3b 100755 --- a/tests/memfile/run-test.sh +++ b/tests/memfile/run-test.sh @@ -9,32 +9,32 @@ cp content1.dat temp/content2.dat cd .. echo "Running from the parent directory with content1.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 echo "Running from the parent directory with temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 echo "Running from the parent directory with memfile/temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" >/dev/null 2>&1 cd memfile echo "Running from the same directory with content1.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" +../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 echo "Running from the same directory with temp/content2.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 cd temp echo "Running from a child directory with content1.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 echo "Running from a child directory with temp/content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 echo "Running from a child directory with content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 cd .. echo "Checking a failure when zero length filename is provided" -if ../../yosys -qp "read_verilog memory.v"; then +if ../../yosys -qp "read_verilog memory.v" >/dev/null 2>&1; then echo "The execution should fail but it didn't happen, which is WRONG." exit 1 else @@ -42,7 +42,7 @@ else fi echo "Checking a failure when not existing filename is provided" -if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory"; then +if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory" >/dev/null 2>&1; then echo "The execution should fail but it didn't happen, which is WRONG." exit 1 else diff --git a/tests/proc/run-test.sh b/tests/proc/run-test.sh index 2e3f5235c..241b32295 100755 --- a/tests/proc/run-test.sh +++ b/tests/proc/run-test.sh @@ -3,5 +3,5 @@ source ../common-env.sh set -e for x in *.ys; do echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x + ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 done diff --git a/tests/select/run-test.sh b/tests/select/run-test.sh index 2e3f5235c..241b32295 100755 --- a/tests/select/run-test.sh +++ b/tests/select/run-test.sh @@ -3,5 +3,5 @@ source ../common-env.sh set -e for x in *.ys; do echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x + ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 done diff --git a/tests/svinterfaces/runone.sh b/tests/svinterfaces/runone.sh index 2d6e0463d..598517db9 100755 --- a/tests/svinterfaces/runone.sh +++ b/tests/svinterfaces/runone.sh @@ -18,19 +18,19 @@ $PWD/../../yosys -p "read_verilog -sv ${TESTNAME}_ref.v ; hierarchy -check -top rm -f a.out reference_result.txt dut_result.txt -iverilog -g2012 ${TESTNAME}_syn.v -iverilog -g2012 ${TESTNAME}_ref_syn.v +iverilog -g2012 ${TESTNAME}_syn.v >/dev/null 2>&1 +iverilog -g2012 ${TESTNAME}_ref_syn.v >/dev/null 2>&1 set +e -iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v -./a.out +iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v >/dev/null 2>&1 +./a.out >/dev/null 2>&1 mv output.txt reference_result.txt if [ -f ${TESTNAME}_wrapper.v ] ; then - iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v + iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v >/dev/null 2>&1 else - iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v + iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v >/dev/null 2>&1 fi -./a.out +./a.out >/dev/null 2>&1 mv output.txt dut_result.txt diff reference_result.txt dut_result.txt > ${TESTNAME}.diff From 712ce93501c9baf784f0527464dcc44b36b64c3f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 15:57:24 +0100 Subject: [PATCH 052/176] Clean some seed-tests outputs --- tests/cxxrtl/run-test.sh | 2 +- tests/fmt/run-test.sh | 34 +++++++++++++++++----------------- tests/fsm/run-test.sh | 2 +- tests/liberty/run-test.sh | 4 ++-- tests/opt_share/run-test.sh | 2 +- tests/share/run-test.sh | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh index b21c79899..6a0bd2355 100755 --- a/tests/cxxrtl/run-test.sh +++ b/tests/cxxrtl/run-test.sh @@ -1,7 +1,7 @@ #!/bin/bash source ../common-env.sh -set -ex +set -e run_subtest () { local subtest=$1; shift diff --git a/tests/fmt/run-test.sh b/tests/fmt/run-test.sh index a3402f953..094f52a2f 100644 --- a/tests/fmt/run-test.sh +++ b/tests/fmt/run-test.sh @@ -1,17 +1,17 @@ #!/usr/bin/env bash source ../common-env.sh -set -ex +set -e -../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $0}' >yosys-initial_display.log +../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $0}' >yosys-initial_display.log 2>&1 iverilog -o iverilog-initial_display initial_display.v ./iverilog-initial_display >iverilog-initial_display.log diff yosys-initial_display.log iverilog-initial_display.log test_always_display () { local subtest=$1; shift - ../../yosys -p "read_verilog $* always_display.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-1.v - ../../yosys -p "read_verilog yosys-always_display-${subtest}-1.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-2.v + ../../yosys -p "read_verilog $* always_display.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-1.v >/dev/null 2>&1 + ../../yosys -p "read_verilog yosys-always_display-${subtest}-1.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-2.v >/dev/null 2>&1 diff yosys-always_display-${subtest}-1.v yosys-always_display-${subtest}-2.v } @@ -25,15 +25,15 @@ test_always_display star_en -DEVENT_STAR -DCOND_EN test_roundtrip () { local subtest=$1; shift - ../../yosys -p "read_verilog $* roundtrip.v; proc; clean" -o yosys-roundtrip-${subtest}-1.v - ../../yosys -p "read_verilog yosys-roundtrip-${subtest}-1.v; proc; clean" -o yosys-roundtrip-${subtest}-2.v + ../../yosys -p "read_verilog $* roundtrip.v; proc; clean" -o yosys-roundtrip-${subtest}-1.v >/dev/null 2>&1 + ../../yosys -p "read_verilog yosys-roundtrip-${subtest}-1.v; proc; clean" -o yosys-roundtrip-${subtest}-2.v >/dev/null 2>&1 diff yosys-roundtrip-${subtest}-1.v yosys-roundtrip-${subtest}-2.v - iverilog $* -o iverilog-roundtrip-${subtest} roundtrip.v roundtrip_tb.v + iverilog $* -o iverilog-roundtrip-${subtest} roundtrip.v roundtrip_tb.v >/dev/null 2>&1 ./iverilog-roundtrip-${subtest} >iverilog-roundtrip-${subtest}.log - iverilog $* -o iverilog-roundtrip-${subtest}-1 yosys-roundtrip-${subtest}-1.v roundtrip_tb.v + iverilog $* -o iverilog-roundtrip-${subtest}-1 yosys-roundtrip-${subtest}-1.v roundtrip_tb.v >/dev/null 2>&1 ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-1.log - iverilog $* -o iverilog-roundtrip-${subtest}-2 yosys-roundtrip-${subtest}-2.v roundtrip_tb.v + iverilog $* -o iverilog-roundtrip-${subtest}-2 yosys-roundtrip-${subtest}-2.v roundtrip_tb.v >/dev/null 2>&1 ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-2.log diff iverilog-roundtrip-${subtest}.log iverilog-roundtrip-${subtest}-1.log diff iverilog-roundtrip-${subtest}-1.log iverilog-roundtrip-${subtest}-2.log @@ -51,10 +51,10 @@ test_roundtrip bin_signed -DBASE_HEX -DSIGN="signed" test_cxxrtl () { local subtest=$1; shift - ../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" + ../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" >/dev/null 2>&1 ${CXX:-g++} -std=c++11 -o yosys-${subtest} -I../../backends/cxxrtl/runtime ${subtest}_tb.cc -lstdc++ ./yosys-${subtest} 2>yosys-${subtest}.log - iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v + iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v >/dev/null 2>&1 ./iverilog-${subtest} |grep -v '\$finish called' >iverilog-${subtest}.log diff iverilog-${subtest}.log yosys-${subtest}.log } @@ -63,16 +63,16 @@ test_cxxrtl always_full test_cxxrtl always_comb # Ensure Verilog backend preserves behaviour of always block with multiple $displays. -../../yosys -p "read_verilog always_full.v; prep; clean" -o yosys-always_full-1.v -iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v +../../yosys -p "read_verilog always_full.v; prep; clean" -o yosys-always_full-1.v >/dev/null 2>&1 +iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v >/dev/null 2>&1 ./iverilog-always_full-1 |grep -v '\$finish called' >iverilog-always_full-1.log diff iverilog-always_full.log iverilog-always_full-1.log -../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log -../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc" +../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log 2>&1 +../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc" >/dev/null 2>&1 ${CXX:-g++} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++ ./yosys-display_lm_cc >yosys-display_lm_cc.log for log in yosys-display_lm.log yosys-display_lm_cc.log; do - grep "^%l: \\\\bot\$" "$log" - grep "^%m: \\\\bot\$" "$log" + grep "^%l: \\\\bot\$" "$log" >/dev/null 2>&1 + grep "^%m: \\\\bot\$" "$log" >/dev/null 2>&1 done diff --git a/tests/fsm/run-test.sh b/tests/fsm/run-test.sh index 139ea8261..304242126 100755 --- a/tests/fsm/run-test.sh +++ b/tests/fsm/run-test.sh @@ -31,7 +31,7 @@ python3 generate.py -c $count $seed idx=$( printf "%05d" $i ) echo "temp/uut_${idx}.log: temp/uut_${idx}.ys temp/uut_${idx}.v" echo " @echo -n '[$i]'" - echo " @../../yosys -ql temp/uut_${idx}.out temp/uut_${idx}.ys" + echo " @../../yosys -ql temp/uut_${idx}.out temp/uut_${idx}.ys >/dev/null 2>&1" echo " @mv temp/uut_${idx}.out temp/uut_${idx}.log" echo " @grep -q 'SAT proof finished' temp/uut_${idx}.log && echo -n K || echo -n T" all_targets="$all_targets temp/uut_${idx}.log" diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh index d5fb65e16..1b6873f26 100755 --- a/tests/liberty/run-test.sh +++ b/tests/liberty/run-test.sh @@ -10,13 +10,13 @@ for x in *.lib; do diff $x.filtered $x.filtered.ok diff $x.verilogsim $x.verilogsim.ok if [[ -e ${x%.lib}.log.ok ]]; then - ../../yosys -p "dfflibmap -info -liberty ${x}" -TqqQl ${x%.lib}.log + ../../yosys -p "dfflibmap -info -liberty ${x}" -TqqQl ${x%.lib}.log >/dev/null 2>&1 diff ${x%.lib}.log ${x%.lib}.log.ok fi done for x in *.ys; do echo "Running $x.." - ../../yosys -q -s $x -l ${x%.ys}.log + ../../yosys -q -s $x -l ${x%.ys}.log >/dev/null 2>&1 done diff --git a/tests/opt_share/run-test.sh b/tests/opt_share/run-test.sh index e3a6e8b7b..e33399567 100755 --- a/tests/opt_share/run-test.sh +++ b/tests/opt_share/run-test.sh @@ -34,7 +34,7 @@ python3 generate.py -c $count $seed echo "test-$idx:" printf "\t@%s\n" \ "echo -n [$i]" \ - "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys" + "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1" done } > temp/makefile diff --git a/tests/share/run-test.sh b/tests/share/run-test.sh index 0cef580a7..36349baad 100755 --- a/tests/share/run-test.sh +++ b/tests/share/run-test.sh @@ -27,7 +27,7 @@ echo "running tests.." for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do echo -n "[$i]" idx=$( printf "%05d" $i ) - ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys + ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1 done echo From 2f9e35acb89e643c2051f5e2351b29b9c36e5772 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 10 Mar 2026 16:15:07 +0100 Subject: [PATCH 053/176] Fix deprecation warning --- tests/tools/autotest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index c9a12b66b..e19a8d5af 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -148,7 +148,7 @@ do rm -f ${bn}_ref.fir if [[ "$ext" == "v" ]]; then - egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} + grep -Ev '^\s*`timescale' ../$fn > ${bn}_ref.${ext} elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then $abcprog -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" else From a2e1fbcfc6eec058e7ede007bfce65304e315aed Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 11 Mar 2026 08:02:11 +0100 Subject: [PATCH 054/176] Enabled realmath that was disabled for some reason --- tests/Makefile | 2 +- tests/realmath/run-test.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index d34db2100..6742b6076 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -37,7 +37,7 @@ SH_TEST_DIRS += ./simple SH_TEST_DIRS += ./simple_abc9 SH_TEST_DIRS += ./hana SH_TEST_DIRS += ./asicworld -# SH_TEST_DIRS += ./realmath +SH_TEST_DIRS += ./realmath SH_TEST_DIRS += ./share SH_TEST_DIRS += ./opt_share SH_TEST_DIRS += ./fsm diff --git a/tests/realmath/run-test.sh b/tests/realmath/run-test.sh index 833e8c3f4..918c93a9f 100755 --- a/tests/realmath/run-test.sh +++ b/tests/realmath/run-test.sh @@ -23,8 +23,8 @@ echo "running tests.." for ((i = 0; i < $count; i++)); do echo -n "[$i]" idx=$( printf "%05d" $i ) - ../../../yosys -qq uut_${idx}.ys - iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v + ../../../yosys -qq uut_${idx}.ys >/dev/null 2>&1 + iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v >/dev/null 2>&1 ./uut_${idx}_tb | tee uut_${idx}.err if test -s uut_${idx}.err; then echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." From ced2521b03520848500977174900fa5761e6bf49 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 08:38:05 +0100 Subject: [PATCH 055/176] Convert gen-tests shell script to python --- tests/.gitignore | 1 + tests/Makefile | 17 +-- tests/aiger/generate_mk.py | 68 +++++++++++ tests/alumacc/generate_mk.py | 8 ++ tests/arch/analogdevices/generate_mk.py | 9 ++ tests/arch/analogdevices/run-test.sh | 5 - tests/arch/anlogic/generate_mk.py | 8 ++ tests/arch/anlogic/run-test.sh | 4 - tests/arch/ecp5/generate_mk.py | 8 ++ tests/arch/ecp5/run-test.sh | 4 - tests/arch/efinix/generate_mk.py | 8 ++ tests/arch/efinix/run-test.sh | 4 - tests/arch/fabulous/fsm.ys | 8 +- tests/arch/fabulous/generate_mk.py | 8 ++ tests/arch/gatemate/generate_mk.py | 8 ++ tests/arch/gatemate/run-test.sh | 4 - tests/arch/gowin/generate_mk.py | 8 ++ tests/arch/gowin/run-test.sh | 4 - tests/arch/ice40/generate_mk.py | 8 ++ tests/arch/ice40/run-test.sh | 4 - tests/arch/intel_alm/generate_mk.py | 8 ++ tests/arch/intel_alm/run-test.sh | 4 - tests/arch/machxo2/generate_mk.py | 8 ++ tests/arch/machxo2/run-test.sh | 4 - tests/arch/microchip/generate_mk.py | 8 ++ tests/arch/microchip/run-test.sh | 4 - tests/arch/nanoxplore/generate_mk.py | 8 ++ tests/arch/nanoxplore/run-test.sh | 4 - tests/arch/nexus/generate_mk.py | 8 ++ tests/arch/nexus/run-test.sh | 4 - tests/arch/quicklogic/pp3/generate_mk.py | 8 ++ tests/arch/quicklogic/pp3/run-test.sh | 4 - .../arch/quicklogic/qlf_k6n10f/generate_mk.py | 9 ++ tests/arch/quicklogic/qlf_k6n10f/run-test.sh | 5 - tests/arch/xilinx/generate_mk.py | 8 ++ tests/arch/xilinx/run-test.sh | 4 - tests/bugpoint/generate_mk.py | 8 ++ tests/bugpoint/run-test.sh | 4 - tests/gen-tests-makefile.sh | 110 ------------------ tests/gen_tests_makefile.py | 86 ++++++++++++++ tests/opt/generate_mk.py | 8 ++ tests/opt/run-test.sh | 4 - tests/rtlil/generate_mk.py | 8 ++ tests/rtlil/run-test.sh | 4 - tests/sat/generate_mk.py | 8 ++ tests/sat/run-test.sh | 4 - tests/sdc/generate_mk.py | 8 ++ tests/sdc/run-test.sh | 4 - tests/sim/generate_mk.py | 35 ++++++ tests/sim/run-test.sh | 12 -- tests/svtypes/generate_mk.py | 8 ++ tests/svtypes/run-test.sh | 4 - tests/techmap/generate_mk.py | 8 ++ tests/techmap/run-test.sh | 4 - tests/various/generate_mk.py | 8 ++ tests/various/run-test.sh | 4 - tests/verific/generate_mk.py | 8 ++ tests/verific/run-test.sh | 5 - tests/verilog/generate_mk.py | 8 ++ tests/verilog/run-test.sh | 4 - 60 files changed, 421 insertions(+), 237 deletions(-) create mode 100644 tests/aiger/generate_mk.py create mode 100644 tests/alumacc/generate_mk.py create mode 100644 tests/arch/analogdevices/generate_mk.py delete mode 100755 tests/arch/analogdevices/run-test.sh create mode 100644 tests/arch/anlogic/generate_mk.py delete mode 100755 tests/arch/anlogic/run-test.sh create mode 100644 tests/arch/ecp5/generate_mk.py delete mode 100755 tests/arch/ecp5/run-test.sh create mode 100644 tests/arch/efinix/generate_mk.py delete mode 100755 tests/arch/efinix/run-test.sh create mode 100644 tests/arch/fabulous/generate_mk.py create mode 100644 tests/arch/gatemate/generate_mk.py delete mode 100755 tests/arch/gatemate/run-test.sh create mode 100644 tests/arch/gowin/generate_mk.py delete mode 100755 tests/arch/gowin/run-test.sh create mode 100644 tests/arch/ice40/generate_mk.py delete mode 100755 tests/arch/ice40/run-test.sh create mode 100644 tests/arch/intel_alm/generate_mk.py delete mode 100755 tests/arch/intel_alm/run-test.sh create mode 100644 tests/arch/machxo2/generate_mk.py delete mode 100644 tests/arch/machxo2/run-test.sh create mode 100644 tests/arch/microchip/generate_mk.py delete mode 100755 tests/arch/microchip/run-test.sh create mode 100644 tests/arch/nanoxplore/generate_mk.py delete mode 100755 tests/arch/nanoxplore/run-test.sh create mode 100644 tests/arch/nexus/generate_mk.py delete mode 100644 tests/arch/nexus/run-test.sh create mode 100644 tests/arch/quicklogic/pp3/generate_mk.py delete mode 100755 tests/arch/quicklogic/pp3/run-test.sh create mode 100644 tests/arch/quicklogic/qlf_k6n10f/generate_mk.py delete mode 100755 tests/arch/quicklogic/qlf_k6n10f/run-test.sh create mode 100644 tests/arch/xilinx/generate_mk.py delete mode 100755 tests/arch/xilinx/run-test.sh create mode 100644 tests/bugpoint/generate_mk.py delete mode 100755 tests/bugpoint/run-test.sh delete mode 100755 tests/gen-tests-makefile.sh create mode 100644 tests/gen_tests_makefile.py create mode 100644 tests/opt/generate_mk.py delete mode 100755 tests/opt/run-test.sh create mode 100644 tests/rtlil/generate_mk.py delete mode 100755 tests/rtlil/run-test.sh create mode 100644 tests/sat/generate_mk.py delete mode 100755 tests/sat/run-test.sh create mode 100644 tests/sdc/generate_mk.py delete mode 100755 tests/sdc/run-test.sh create mode 100644 tests/sim/generate_mk.py delete mode 100755 tests/sim/run-test.sh create mode 100644 tests/svtypes/generate_mk.py delete mode 100755 tests/svtypes/run-test.sh create mode 100644 tests/techmap/generate_mk.py delete mode 100755 tests/techmap/run-test.sh create mode 100644 tests/various/generate_mk.py delete mode 100755 tests/various/run-test.sh create mode 100644 tests/verific/generate_mk.py delete mode 100755 tests/verific/run-test.sh create mode 100644 tests/verilog/generate_mk.py delete mode 100755 tests/verilog/run-test.sh diff --git a/tests/.gitignore b/tests/.gitignore index d8e01e026..da4350076 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,3 +2,4 @@ *.out *.err run-test.mk +**/Makefile diff --git a/tests/Makefile b/tests/Makefile index 6742b6076..5ec699417 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,10 @@ -# Tests that generate .mk with ./gen-tests-makefile.sh +# Tests that generate Makefile with gen_tests_makefile.py MK_TEST_DIRS = MK_TEST_DIRS += ./arch/analogdevices MK_TEST_DIRS += ./arch/anlogic MK_TEST_DIRS += ./arch/ecp5 MK_TEST_DIRS += ./arch/efinix +MK_TEST_DIRS += ./arch/fabulous MK_TEST_DIRS += ./arch/gatemate MK_TEST_DIRS += ./arch/gowin MK_TEST_DIRS += ./arch/ice40 @@ -84,14 +85,14 @@ abcopt-./%: %/run-test.sh # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests -#.SILENT: $(MK_TEST_DIRS:%=%/run-test.mk) +.SILENT: $(MK_TEST_DIRS:%=%/Makefile) makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) -# this target actually emits .mk files -%.mk: - +@cd $(dir $*) && bash run-test.sh -# this one spawns submake on each -makefile-./%: %/run-test.mk - @$(MAKE) -C $* -f run-test.mk +# this target actually emits Makefile files +%/Makefile: + +@cd $* && python3 generate_mk.py + +makefile-./%: %/Makefile + @$(MAKE) -C $* @echo "...passed tests in $*" vanilla-test: makefile-tests abcopt-tests seed-tests diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py new file mode 100644 index 000000000..e0a15332e --- /dev/null +++ b/tests/aiger/generate_mk.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +import glob +import os + +yosys = "../../yosys" +default_abc = "../../yosys-abc" + +aags = sorted(glob.glob("*.aag")) +yss = sorted(glob.glob("*.ys")) + +print("ABC ?= " + default_abc) +print("YOSYS ?= " + yosys) +print() + +def base(fn): + return os.path.splitext(fn)[0] + +# NB: *.aag and *.aig must contain a symbol table naming the primary +# inputs and outputs, otherwise ABC and Yosys will name them +# arbitrarily (and inconsistently with each other). + +# Since ABC cannot read *.aag, read the *.aig instead +# (which would have been created by the reference aig2aig utility, +# available from http://fmv.jku.at/aiger/) + +for aag in aags: + b = base(aag) + + print(f"all: {aag}") + print(f".PHONY: {aag}") + print(f"{aag}:") + print(f"\t@echo Checking {aag}.") + print(f"\t@$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1") + print("\t@$(YOSYS) -qp \"\\") + print(f"\tread_verilog {b}_ref.v; \\") + print("\tprep; \\") + print("\tdesign -stash gold; \\") + print(f"\tread_aiger -clk_name clock {aag}; \\") + print("\tprep; \\") + print("\tdesign -stash gate; \\") + print("\tdesign -import gold -as gold; \\") + print("\tdesign -import gate -as gate; \\") + print("\tmiter -equiv -flatten -make_assert -make_outputs gold gate miter; \\") + print("\tsat -verify -prove-asserts -show-ports -seq 16 miter; \\") + print(f"\t\" -l {aag}.log >/dev/null 2>&1") + print() + +# ---- Yosys script tests ---- +for ys in yss: + b = base(ys) + print(f"all: {ys}") + print(f".PHONY: {ys}") + print(f"{ys}: ") + print(f"\t@echo Running {ys}.") + print(f"\t@$(YOSYS) -ql {b}.log {ys} >/dev/null 2>&1") + print() + +# ---- aigmap test ---- +print(f"all: aigmap") +print(f".PHONY: aigmap") +print("aigmap:") +print("\t@echo Running aigmap.") +print("\t@rm -rf gate; mkdir gate") +print('\t@$(YOSYS) --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1') +print("\t@set -o pipefail; diff --brief gold gate | tee aigmap.err") +print("\t@rm -f aigmap.err") +print() diff --git a/tests/alumacc/generate_mk.py b/tests/alumacc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/alumacc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/arch/analogdevices/generate_mk.py b/tests/arch/analogdevices/generate_mk.py new file mode 100644 index 000000000..b453168c0 --- /dev/null +++ b/tests/arch/analogdevices/generate_mk.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile +import mem_gen + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/analogdevices/run-test.sh b/tests/arch/analogdevices/run-test.sh deleted file mode 100755 index 9b5e2f7f4..000000000 --- a/tests/arch/analogdevices/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -python3 mem_gen.py -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/arch/anlogic/generate_mk.py b/tests/arch/anlogic/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/anlogic/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/anlogic/run-test.sh b/tests/arch/anlogic/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/anlogic/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/ecp5/generate_mk.py b/tests/arch/ecp5/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/ecp5/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/ecp5/run-test.sh b/tests/arch/ecp5/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/ecp5/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/efinix/generate_mk.py b/tests/arch/efinix/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/efinix/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/efinix/run-test.sh b/tests/arch/efinix/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/efinix/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/fabulous/fsm.ys b/tests/arch/fabulous/fsm.ys index 9c3831682..15fd19247 100644 --- a/tests/arch/fabulous/fsm.ys +++ b/tests/arch/fabulous/fsm.ys @@ -11,9 +11,9 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module - +stat select -assert-count 6 t:LUTFF -select -assert-max 4 t:LUT2 -select -assert-max 2 t:LUT3 -select -assert-max 9 t:LUT4 +select -assert-max 5 t:LUT2 +select -assert-max 4 t:LUT3 +select -assert-max 8 t:LUT4 select -assert-none t:LUT2 t:LUT3 t:LUT4 t:LUTFF %% t:* %D diff --git a/tests/arch/fabulous/generate_mk.py b/tests/arch/fabulous/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/fabulous/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gatemate/generate_mk.py b/tests/arch/gatemate/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/gatemate/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gatemate/run-test.sh b/tests/arch/gatemate/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/gatemate/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/gowin/generate_mk.py b/tests/arch/gowin/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/gowin/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/gowin/run-test.sh b/tests/arch/gowin/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/gowin/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/ice40/generate_mk.py b/tests/arch/ice40/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/ice40/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/ice40/run-test.sh b/tests/arch/ice40/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/ice40/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/intel_alm/generate_mk.py b/tests/arch/intel_alm/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/intel_alm/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/intel_alm/run-test.sh b/tests/arch/intel_alm/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/intel_alm/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/machxo2/generate_mk.py b/tests/arch/machxo2/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/machxo2/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/machxo2/run-test.sh b/tests/arch/machxo2/run-test.sh deleted file mode 100644 index 691b70966..000000000 --- a/tests/arch/machxo2/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/microchip/generate_mk.py b/tests/arch/microchip/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/microchip/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/microchip/run-test.sh b/tests/arch/microchip/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/microchip/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/nanoxplore/generate_mk.py b/tests/arch/nanoxplore/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/nanoxplore/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/nanoxplore/run-test.sh b/tests/arch/nanoxplore/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/nanoxplore/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/nexus/generate_mk.py b/tests/arch/nexus/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/nexus/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/nexus/run-test.sh b/tests/arch/nexus/run-test.sh deleted file mode 100644 index 691b70966..000000000 --- a/tests/arch/nexus/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/pp3/generate_mk.py b/tests/arch/quicklogic/pp3/generate_mk.py new file mode 100644 index 000000000..e001d7e4a --- /dev/null +++ b/tests/arch/quicklogic/pp3/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/quicklogic/pp3/run-test.sh b/tests/arch/quicklogic/pp3/run-test.sh deleted file mode 100755 index 43a7874b2..000000000 --- a/tests/arch/quicklogic/pp3/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py b/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py new file mode 100644 index 000000000..e9abad21a --- /dev/null +++ b/tests/arch/quicklogic/qlf_k6n10f/generate_mk.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../../..") + +import gen_tests_makefile +import mem_gen + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/quicklogic/qlf_k6n10f/run-test.sh b/tests/arch/quicklogic/qlf_k6n10f/run-test.sh deleted file mode 100755 index c7daba12d..000000000 --- a/tests/arch/quicklogic/qlf_k6n10f/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -python3 mem_gen.py -source ../../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/arch/xilinx/generate_mk.py b/tests/arch/xilinx/generate_mk.py new file mode 100644 index 000000000..06a6040ad --- /dev/null +++ b/tests/arch/xilinx/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("../..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/arch/xilinx/run-test.sh b/tests/arch/xilinx/run-test.sh deleted file mode 100755 index 691b70966..000000000 --- a/tests/arch/xilinx/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/bugpoint/generate_mk.py b/tests/bugpoint/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/bugpoint/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/bugpoint/run-test.sh b/tests/bugpoint/run-test.sh deleted file mode 100755 index 006c731e3..000000000 --- a/tests/bugpoint/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts diff --git a/tests/gen-tests-makefile.sh b/tests/gen-tests-makefile.sh deleted file mode 100755 index 07d70c2a8..000000000 --- a/tests/gen-tests-makefile.sh +++ /dev/null @@ -1,110 +0,0 @@ -set -eu - -YOSYS_BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../ >/dev/null 2>&1 && pwd)" - -# $ generate_target target_name test_command -generate_target() { - target_name=$(basename $PWD)-$1 - test_command=$2 - echo "all: $target_name" - echo ".PHONY: $target_name" - echo "$target_name:" - printf "\t@YOSYS_MAX_THREADS=4 %s\n" "$test_command" - printf "\t@echo 'Passed %s'\n" "$target_name" -} - -# $ generate_ys_test ys_file [yosys_args] -generate_ys_test() { - ys_file=$1 - yosys_args_=${2:-} - generate_target "$ys_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${ys_file}.err $yosys_args_ $ys_file >/dev/null 2>&1 && mv ${ys_file}.err ${ys_file}.log" -} - -# $ generate_tcl_test tcl_file [yosys_args] -generate_tcl_test() { - tcl_file=$1 - yosys_args_=${2:-} - generate_target "$tcl_file" "\"$YOSYS_BASEDIR/yosys\" -ql ${tcl_file}.err $yosys_args_ $tcl_file >/dev/null 2>&1 && mv ${tcl_file}.err ${tcl_file}.log" -} - -# $ generate_bash_test bash_file -generate_bash_test() { - bash_file=$1 - generate_target "$bash_file" "bash -v $bash_file >${bash_file}.err 2>&1 && mv ${bash_file}.err ${bash_file}.log" -} - -# $ generate_tests [-y|--yosys-scripts] [-s|--prove-sv] [-b|--bash] [-a|--yosys-args yosys_args] -generate_tests() { - do_ys=false - do_tcl=false - do_sv=false - do_sh=false - yosys_args="" - - while [[ $# -gt 0 ]]; do - arg="$1" - case "$arg" in - -y|--yosys-scripts) - do_ys=true - shift - ;; - -t|--tcl-scripts) - do_tcl=true - shift - ;; - -s|--prove-sv) - do_sv=true - shift - ;; - -b|--bash) - do_sh=true - shift - ;; - -a|--yosys-args) - yosys_args+="$2" - shift - shift - ;; - *) - echo >&2 "Unknown argument: $1" - exit 1 - esac - done - - if [[ ! ( $do_ys = true || $do_tcl = true || $do_sv = true || $do_sh = true ) ]]; then - echo >&2 "Error: No file types selected" - exit 1 - fi - - echo ".PHONY: all" - echo "all:" - - if [[ $do_ys = true ]]; then - for x in *.ys; do - generate_ys_test "$x" "$yosys_args" - done - fi; - if [[ $do_tcl = true ]]; then - for x in *.tcl; do - generate_tcl_test "$x" "$yosys_args" - done - fi; - if [[ $do_sv = true ]]; then - for x in *.sv; do - if [ ! -f "${x%.sv}.ys" ]; then - generate_ys_test "$x" "-p \"prep -top top; async2sync; sat -enable_undef -verify -prove-asserts\" $yosys_args" - fi; - done - fi; - if [[ $do_sh == true ]]; then - for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - generate_bash_test "$s" - fi - done - fi -} - -generate_mk() { - generate_tests "$@" > run-test.mk -} diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py new file mode 100644 index 000000000..dbd7a2bc9 --- /dev/null +++ b/tests/gen_tests_makefile.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 + +import glob +import os +import sys +import argparse + +yosys_basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + +def _cwd_base(): + return os.path.basename(os.getcwd()) + +def generate_target(name, command): + target = f"{_cwd_base()}-{name}" + print(f"all: {target}") + print(f".PHONY: {target}") + print(f"{target}:") + print(f"\t@YOSYS_MAX_THREADS=4 {command}") + print(f"\t@echo 'Passed {target}'") + +def generate_ys_test(ys_file, yosys_args=""): + cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' + generate_target(ys_file, cmd) + +def generate_tcl_test(tcl_file, yosys_args=""): + cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} >/dev/null 2>&1 && mv {tcl_file}.err {tcl_file}.log' + generate_target(tcl_file, cmd) + +def generate_sv_test(sv_file, yosys_args=""): + base = os.path.splitext(sv_file)[0] + if not os.path.exists(base + ".ys"): + yosys_cmd = '-p "prep -top top; async2sync; sat -enable_undef -verify -prove-asserts"' + cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} >/dev/null 2>&1 && mv {sv_file}.err {sv_file}.log' + generate_target(sv_file, cmd) + +def generate_bash_test(sh_file): + cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" + generate_target(sh_file, cmd) + +def generate_tests(argv): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("-y", "--yosys-scripts", action="store_true") + parser.add_argument("-t", "--tcl-scripts", action="store_true") + parser.add_argument("-s", "--prove-sv", action="store_true") + parser.add_argument("-b", "--bash", action="store_true") + parser.add_argument("-a", "--yosys-args", default="") + + args = parser.parse_args(argv) + + if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): + raise RuntimeError("No file types selected") + + print(f"YOSYS ?= {yosys_basedir}/yosys") + print() + + print(".PHONY: all") + print("all:") + + if args.yosys_scripts: + for f in sorted(glob.glob("*.ys")): + generate_ys_test(f, args.yosys_args) + + if args.tcl_scripts: + for f in sorted(glob.glob("*.tcl")): + generate_tcl_test(f, args.yosys_args) + + if args.prove_sv: + for f in sorted(glob.glob("*.sv")): + generate_sv_test(f, args.yosys_args) + + if args.bash: + for f in sorted(glob.glob("*.sh")): + if f != "run-test.sh": + generate_bash_test(f) + +def generate(argv, extra=None): + with open("Makefile", "w") as f: + old = sys.stdout + sys.stdout = f + try: + if extra: + for line in extra: + print(line) + generate_tests(argv) + finally: + sys.stdout = old diff --git a/tests/opt/generate_mk.py b/tests/opt/generate_mk.py new file mode 100644 index 000000000..4c31c5a2b --- /dev/null +++ b/tests/opt/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--tcl-scripts"]) diff --git a/tests/opt/run-test.sh b/tests/opt/run-test.sh deleted file mode 100755 index 1d1d9b7a6..000000000 --- a/tests/opt/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --tcl-scripts diff --git a/tests/rtlil/generate_mk.py b/tests/rtlil/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/rtlil/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/rtlil/run-test.sh b/tests/rtlil/run-test.sh deleted file mode 100755 index 83cdf8aeb..000000000 --- a/tests/rtlil/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --bash --yosys-scripts diff --git a/tests/sat/generate_mk.py b/tests/sat/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/sat/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/sat/run-test.sh b/tests/sat/run-test.sh deleted file mode 100755 index 006c731e3..000000000 --- a/tests/sat/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts diff --git a/tests/sdc/generate_mk.py b/tests/sdc/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/sdc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/sdc/run-test.sh b/tests/sdc/run-test.sh deleted file mode 100755 index 971664bdb..000000000 --- a/tests/sdc/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash \ No newline at end of file diff --git a/tests/sim/generate_mk.py b/tests/sim/generate_mk.py new file mode 100644 index 000000000..57138762d --- /dev/null +++ b/tests/sim/generate_mk.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +import subprocess +from pathlib import Path + +print("Generate FST for sim models") + +for name in Path("tb").rglob("tb*.v"): + test_name = name.stem + print(f"Test {test_name}") + + verilog_name = f"{test_name[3:]}.v" + + out_file = Path("tb") / f"{test_name}.out" + + subprocess.run( + ["iverilog", "-o", str(out_file), str(name), verilog_name], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + + subprocess.run( + [str(out_file), "-fst"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=True + ) + +gen_tests_makefile.generate(["--yosys-scripts", "--bash", "--yosys-args", "-w 'Yosys has only limited support for tri-state logic at the moment.'" ]) diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh deleted file mode 100755 index cff85eb65..000000000 --- a/tests/sim/run-test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -echo "Generate FST for sim models" -find tb/* -name tb*.v | while read name; do - test_name=$(basename $name .v) - echo "Test $test_name" - verilog_name=${test_name:3}.v - iverilog -o tb/$test_name.out $name $verilog_name >/dev/null 2>&1 - ./tb/$test_name.out -fst >/dev/null 2>&1 -done -generate_mk --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'" diff --git a/tests/svtypes/generate_mk.py b/tests/svtypes/generate_mk.py new file mode 100644 index 000000000..618163cca --- /dev/null +++ b/tests/svtypes/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--prove-sv"]) diff --git a/tests/svtypes/run-test.sh b/tests/svtypes/run-test.sh deleted file mode 100755 index 8b0333f27..000000000 --- a/tests/svtypes/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --prove-sv diff --git a/tests/techmap/generate_mk.py b/tests/techmap/generate_mk.py new file mode 100644 index 000000000..c8a4fe054 --- /dev/null +++ b/tests/techmap/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--tcl-scripts", "--bash", "--yosys-args", "-e 'select out of bounds'"]) diff --git a/tests/techmap/run-test.sh b/tests/techmap/run-test.sh deleted file mode 100755 index 0766db999..000000000 --- a/tests/techmap/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --tcl-scripts --bash --yosys-args "-e 'select out of bounds'" diff --git a/tests/various/generate_mk.py b/tests/various/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/various/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/various/run-test.sh b/tests/various/run-test.sh deleted file mode 100755 index dee032827..000000000 --- a/tests/various/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash diff --git a/tests/verific/generate_mk.py b/tests/verific/generate_mk.py new file mode 100644 index 000000000..c8c8c53c3 --- /dev/null +++ b/tests/verific/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"],["export ASAN_OPTIONS=halt_on_error=0"]) diff --git a/tests/verific/run-test.sh b/tests/verific/run-test.sh deleted file mode 100755 index 1666ee1f9..000000000 --- a/tests/verific/run-test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash -{ echo 'export ASAN_OPTIONS=halt_on_error=0'; cat run-test.mk; } > run-test.mk.tmp && mv run-test.mk.tmp run-test.mk diff --git a/tests/verilog/generate_mk.py b/tests/verilog/generate_mk.py new file mode 100644 index 000000000..aa88bca13 --- /dev/null +++ b/tests/verilog/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts", "--bash"]) diff --git a/tests/verilog/run-test.sh b/tests/verilog/run-test.sh deleted file mode 100755 index dee032827..000000000 --- a/tests/verilog/run-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu -source ../gen-tests-makefile.sh -generate_mk --yosys-scripts --bash From b361569abfa2f83d7ec4a2658bbcbbe01de017bf Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 09:51:15 +0100 Subject: [PATCH 056/176] Save results, and create summary and report --- tests/.gitignore | 1 + tests/Makefile | 76 +++++++++++++++++++++++-------------- tests/gen_tests_makefile.py | 17 +++++++-- 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/tests/.gitignore b/tests/.gitignore index da4350076..8fa73e3d6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,3 +3,4 @@ *.err run-test.mk **/Makefile +*.result diff --git a/tests/Makefile b/tests/Makefile index 5ec699417..237cf6ec0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -34,37 +34,37 @@ MK_TEST_DIRS += ./verilog # Tests that don't generate .mk SH_TEST_DIRS = -SH_TEST_DIRS += ./simple -SH_TEST_DIRS += ./simple_abc9 -SH_TEST_DIRS += ./hana -SH_TEST_DIRS += ./asicworld -SH_TEST_DIRS += ./realmath -SH_TEST_DIRS += ./share -SH_TEST_DIRS += ./opt_share -SH_TEST_DIRS += ./fsm -SH_TEST_DIRS += ./memlib -SH_TEST_DIRS += ./bram -SH_TEST_DIRS += ./svinterfaces -SH_TEST_DIRS += ./xprop -SH_TEST_DIRS += ./select -SH_TEST_DIRS += ./peepopt -SH_TEST_DIRS += ./proc -SH_TEST_DIRS += ./blif -SH_TEST_DIRS += ./arch -SH_TEST_DIRS += ./rpc -SH_TEST_DIRS += ./memfile -SH_TEST_DIRS += ./fmt -SH_TEST_DIRS += ./cxxrtl -SH_TEST_DIRS += ./liberty -ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -SH_TEST_DIRS += ./functional -endif +#SH_TEST_DIRS += ./simple +#SH_TEST_DIRS += ./simple_abc9 +#SH_TEST_DIRS += ./hana +#SH_TEST_DIRS += ./asicworld +#SH_TEST_DIRS += ./realmath +#SH_TEST_DIRS += ./share +#SH_TEST_DIRS += ./opt_share +#SH_TEST_DIRS += ./fsm +#SH_TEST_DIRS += ./memlib +#SH_TEST_DIRS += ./bram +#SH_TEST_DIRS += ./svinterfaces +#SH_TEST_DIRS += ./xprop +#SH_TEST_DIRS += ./select +#SH_TEST_DIRS += ./peepopt +#SH_TEST_DIRS += ./proc +#SH_TEST_DIRS += ./blif +#SH_TEST_DIRS += ./arch +#SH_TEST_DIRS += ./rpc +#SH_TEST_DIRS += ./memfile +#SH_TEST_DIRS += ./fmt +#SH_TEST_DIRS += ./cxxrtl +#SH_TEST_DIRS += ./liberty +#ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +#SH_TEST_DIRS += ./functional +#endif # Tests that don't generate .mk and need special args SH_ABC_TEST_DIRS = -SH_ABC_TEST_DIRS += ./memories -SH_ABC_TEST_DIRS += ./aiger -SH_ABC_TEST_DIRS += ./alumacc +#SH_ABC_TEST_DIRS += ./memories +#SH_ABC_TEST_DIRS += ./aiger +#SH_ABC_TEST_DIRS += ./alumacc all: vanilla-test @@ -104,6 +104,15 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" + @pass=$$(grep -h PASS **/*.result 2>/dev/null | wc -l); \ + fail=$$(grep -h FAIL **/*.result 2>/dev/null | wc -l); \ + total=$$((pass + fail)); \ + echo "=========================="; \ + echo "Tests: $$total"; \ + echo "Passed: $$pass"; \ + echo "Failed: $$fail"; \ + echo "=========================="; \ + test $$fail -eq 0 clean: @rm -rf ./asicworld/*.out ./asicworld/*.log @@ -115,3 +124,14 @@ clean: @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff @rm -f ./tools/cmp_tbdata @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + @find . -name '*.result' -type f -exec rm -f {} + + @find . -mindepth 2 \( -path './sva*' -o -path './unit*' \) -prune -o -name 'Makefile' -type f -exec rm -f {} + + +.PHONY: report +report: + @echo "==========================" + @echo "Failing tests:" + @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ + | cut -d: -f1 \ + | sed 's|^\./||; s|\.result$$||' + @echo "==========================" diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index dbd7a2bc9..dea815174 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -15,8 +15,8 @@ def generate_target(name, command): print(f"all: {target}") print(f".PHONY: {target}") print(f"{target}:") - print(f"\t@YOSYS_MAX_THREADS=4 {command}") - print(f"\t@echo 'Passed {target}'") + print(f"\t@@$(call run_test,{target}, \\") + print(f"\tYOSYS_MAX_THREADS=4 {command})") def generate_ys_test(ys_file, yosys_args=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -52,7 +52,18 @@ def generate_tests(argv): print(f"YOSYS ?= {yosys_basedir}/yosys") print() - + print("define run_test") + print(" rc=0; \\") + print(" $(2) || rc=$$?; \\") + print(" if [ $$rc -eq 0 ]; then \\") + print(" echo \"PASS $1\"; \\") + print(" echo PASS > $1.result; \\") + print(" else \\") + print(" echo \"FAIL $1\"; \\") + print(" echo FAIL > $1.result; \\") + print(" fi") + print("endef") + print() print(".PHONY: all") print("all:") From 45bb0413bfffd4948fa89a1968adb93b78fc4b3f Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 10:10:34 +0100 Subject: [PATCH 057/176] Look for all result files --- tests/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 237cf6ec0..55276e730 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -104,8 +104,12 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" - @pass=$$(grep -h PASS **/*.result 2>/dev/null | wc -l); \ - fail=$$(grep -h FAIL **/*.result 2>/dev/null | wc -l); \ + -@$(MAKE) summary + +.PHONY: summary +summary: + @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ + fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ total=$$((pass + fail)); \ echo "=========================="; \ echo "Tests: $$total"; \ From c04d72433700d8c6680a51994e5f5a1fe388bc6b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 10:15:17 +0100 Subject: [PATCH 058/176] report on summary --- tests/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 55276e730..5b32bc51d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -104,7 +104,7 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" - -@$(MAKE) summary + -@$(MAKE) --no-print-directory summary .PHONY: summary summary: @@ -116,6 +116,10 @@ summary: echo "Passed: $$pass"; \ echo "Failed: $$fail"; \ echo "=========================="; \ + if [ $$fail -ne 0 ]; then \ + echo; \ + $(MAKE) --no-print-directory report; \ + fi; \ test $$fail -eq 0 clean: From 336a06d0914fb662908dbd0e086f0d02da29a3b3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 11:00:08 +0100 Subject: [PATCH 059/176] Add common.mk --- tests/Makefile | 32 ++++++--------------------- tests/common.mk | 43 +++++++++++++++++++++++++++++++++++++ tests/gen_tests_makefile.py | 16 +++----------- 3 files changed, 53 insertions(+), 38 deletions(-) create mode 100644 tests/common.mk diff --git a/tests/Makefile b/tests/Makefile index 5b32bc51d..d22e0bf50 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,3 +1,10 @@ +ifneq ($(wildcard ../Makefile.conf),) +include ../Makefile.conf +endif + +OVERRIDE_MAIN=1 +include ./common.mk + # Tests that generate Makefile with gen_tests_makefile.py MK_TEST_DIRS = MK_TEST_DIRS += ./arch/analogdevices @@ -106,22 +113,6 @@ endif @echo "" -@$(MAKE) --no-print-directory summary -.PHONY: summary -summary: - @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ - fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ - total=$$((pass + fail)); \ - echo "=========================="; \ - echo "Tests: $$total"; \ - echo "Passed: $$pass"; \ - echo "Failed: $$fail"; \ - echo "=========================="; \ - if [ $$fail -ne 0 ]; then \ - echo; \ - $(MAKE) --no-print-directory report; \ - fi; \ - test $$fail -eq 0 - clean: @rm -rf ./asicworld/*.out ./asicworld/*.log @rm -rf ./hana/*.out ./hana/*.log @@ -134,12 +125,3 @@ clean: @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) @find . -name '*.result' -type f -exec rm -f {} + @find . -mindepth 2 \( -path './sva*' -o -path './unit*' \) -prune -o -name 'Makefile' -type f -exec rm -f {} + - -.PHONY: report -report: - @echo "==========================" - @echo "Failing tests:" - @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ - | cut -d: -f1 \ - | sed 's|^\./||; s|\.result$$||' - @echo "==========================" diff --git a/tests/common.mk b/tests/common.mk new file mode 100644 index 000000000..ee4c5dee7 --- /dev/null +++ b/tests/common.mk @@ -0,0 +1,43 @@ +all: + +ifndef OVERRIDE_MAIN +clean: + @rm -f *.log *.result +endif + +define run_test + rc=0; \ + $(2) || rc=$$?; \ + if [ $$rc -eq 0 ]; then \ + echo "PASS $1"; \ + echo PASS > $1.result; \ + else \ + echo "FAIL $1"; \ + echo FAIL > $1.result; \ + fi +endef + +.PHONY: summary +summary: + @pass=$$(find . -type f -name '*.result' -exec grep '^PASS$$' {} + | wc -l); \ + fail=$$(find . -type f -name '*.result' -exec grep '^FAIL$$' {} + | wc -l); \ + total=$$((pass + fail)); \ + echo "=========================="; \ + echo "Tests: $$total"; \ + echo "Passed: $$pass"; \ + echo "Failed: $$fail"; \ + echo "=========================="; \ + if [ $$fail -ne 0 ]; then \ + echo; \ + $(MAKE) --no-print-directory report; \ + fi; \ + test $$fail -eq 0 + +.PHONY: report +report: + @echo "==========================" + @echo "Failing tests:" + @find . -name '*.result' -type f -exec grep -H '^FAIL$$' {} + \ + | cut -d: -f1 \ + | sed 's|^\./||; s|\.result$$||' + @echo "==========================" diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index dea815174..b61e4917d 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -5,7 +5,8 @@ import os import sys import argparse -yosys_basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +yosys_basedir = os.path.relpath(os.path.join(os.path.dirname(__file__), "..")) +common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk")) def _cwd_base(): return os.path.basename(os.getcwd()) @@ -50,20 +51,9 @@ def generate_tests(argv): if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): raise RuntimeError("No file types selected") + print(f"include {common_mk}") print(f"YOSYS ?= {yosys_basedir}/yosys") print() - print("define run_test") - print(" rc=0; \\") - print(" $(2) || rc=$$?; \\") - print(" if [ $$rc -eq 0 ]; then \\") - print(" echo \"PASS $1\"; \\") - print(" echo PASS > $1.result; \\") - print(" else \\") - print(" echo \"FAIL $1\"; \\") - print(" echo FAIL > $1.result; \\") - print(" fi") - print("endef") - print() print(".PHONY: all") print("all:") From 8ff28a2a8634a2990b08a2fa27a29a5fe7a54f9e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 11:15:21 +0100 Subject: [PATCH 060/176] add prep --- tests/Makefile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index d22e0bf50..152b9b1dd 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -94,8 +94,13 @@ abcopt-./%: %/run-test.sh .PHONY: makefile-tests .SILENT: $(MK_TEST_DIRS:%=%/Makefile) makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) +prep: $(MK_TEST_DIRS:%=%/Makefile) + @echo "All Makefiles generated." # this target actually emits Makefile files -%/Makefile: +.PHONY: force-create +force-create: + +%/Makefile: force-create +@cd $* && python3 generate_mk.py makefile-./%: %/Makefile @@ -122,6 +127,5 @@ clean: @rm -rf ./bram/temp ./fsm/temp ./realmath/temp ./share/temp ./smv/temp ./various/temp @rm -f ./svinterfaces/*.log_stdout ./svinterfaces/*.log_stderr ./svinterfaces/dut_result.txt ./svinterfaces/reference_result.txt ./svinterfaces/a.out ./svinterfaces/*_syn.v ./svinterfaces/*.diff @rm -f ./tools/cmp_tbdata - @rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) + @rm -f $(addsuffix /Makefile,$(MK_TEST_DIRS)) @find . -name '*.result' -type f -exec rm -f {} + - @find . -mindepth 2 \( -path './sva*' -o -path './unit*' \) -prune -o -name 'Makefile' -type f -exec rm -f {} + From f96fa5ff009880a391fe42dcc5af4f6d05cd0941 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Mar 2026 11:18:03 +0100 Subject: [PATCH 061/176] cleanup --- tests/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 152b9b1dd..1974462c2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -96,10 +96,9 @@ abcopt-./%: %/run-test.sh makefile-tests: $(MK_TEST_DIRS:%=makefile-./%) prep: $(MK_TEST_DIRS:%=%/Makefile) @echo "All Makefiles generated." -# this target actually emits Makefile files -.PHONY: force-create -force-create: +.PHONY: force-create +# this target actually emits Makefile files %/Makefile: force-create +@cd $* && python3 generate_mk.py From 8953007483d4eb230d40a154cf43e24203aa4185 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 10:13:10 +0100 Subject: [PATCH 062/176] Use generic testing on few more places --- tests/Makefile | 5 ++- tests/aiger/generate_mk.py | 88 ++++++++++++++++--------------------- tests/aiger/run-test.sh | 70 ----------------------------- tests/alumacc/run-test.sh | 7 --- tests/bind/generate_mk.py | 8 ++++ tests/bind/run-test.sh | 20 --------- tests/gen_tests_makefile.py | 34 +++++++++++++- 7 files changed, 82 insertions(+), 150 deletions(-) delete mode 100755 tests/aiger/run-test.sh delete mode 100644 tests/alumacc/run-test.sh create mode 100644 tests/bind/generate_mk.py delete mode 100755 tests/bind/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 1974462c2..117399cd2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -23,6 +23,7 @@ MK_TEST_DIRS += ./arch/nexus MK_TEST_DIRS += ./arch/quicklogic/pp3 MK_TEST_DIRS += ./arch/quicklogic/qlf_k6n10f MK_TEST_DIRS += ./arch/xilinx +MK_TEST_DIRS += ./bind MK_TEST_DIRS += ./bugpoint MK_TEST_DIRS += ./opt MK_TEST_DIRS += ./sat @@ -70,8 +71,8 @@ SH_TEST_DIRS = # Tests that don't generate .mk and need special args SH_ABC_TEST_DIRS = #SH_ABC_TEST_DIRS += ./memories -#SH_ABC_TEST_DIRS += ./aiger -#SH_ABC_TEST_DIRS += ./alumacc +MK_TEST_DIRS += ./aiger +MK_TEST_DIRS += ./alumacc all: vanilla-test diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py index e0a15332e..00be5b5f9 100644 --- a/tests/aiger/generate_mk.py +++ b/tests/aiger/generate_mk.py @@ -1,18 +1,13 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import glob import os -yosys = "../../yosys" -default_abc = "../../yosys-abc" - -aags = sorted(glob.glob("*.aag")) -yss = sorted(glob.glob("*.ys")) - -print("ABC ?= " + default_abc) -print("YOSYS ?= " + yosys) -print() - def base(fn): return os.path.splitext(fn)[0] @@ -23,46 +18,41 @@ def base(fn): # Since ABC cannot read *.aag, read the *.aig instead # (which would have been created by the reference aig2aig utility, # available from http://fmv.jku.at/aiger/) +def create_tests(): + aags = sorted(glob.glob("*.aag")) + yss = sorted(glob.glob("*.ys")) + for aag in aags: + b = base(aag) -for aag in aags: - b = base(aag) + cmd = [ + f"$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1;", + "$(YOSYS) -qp \"", + f"read_verilog {b}_ref.v;", + "prep;", + "design -stash gold;", + f"read_aiger -clk_name clock {aag};", + "prep;", + "design -stash gate;", + "design -import gold -as gold;", + "design -import gate -as gate;", + "miter -equiv -flatten -make_assert -make_outputs gold gate miter;", + "sat -verify -prove-asserts -show-ports -seq 16 miter;", + f"\" -l {aag}.log >/dev/null 2>&1" + ] - print(f"all: {aag}") - print(f".PHONY: {aag}") - print(f"{aag}:") - print(f"\t@echo Checking {aag}.") - print(f"\t@$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1") - print("\t@$(YOSYS) -qp \"\\") - print(f"\tread_verilog {b}_ref.v; \\") - print("\tprep; \\") - print("\tdesign -stash gold; \\") - print(f"\tread_aiger -clk_name clock {aag}; \\") - print("\tprep; \\") - print("\tdesign -stash gate; \\") - print("\tdesign -import gold -as gold; \\") - print("\tdesign -import gate -as gate; \\") - print("\tmiter -equiv -flatten -make_assert -make_outputs gold gate miter; \\") - print("\tsat -verify -prove-asserts -show-ports -seq 16 miter; \\") - print(f"\t\" -l {aag}.log >/dev/null 2>&1") - print() + gen_tests_makefile.generate_cmd_test(aag, cmd) -# ---- Yosys script tests ---- -for ys in yss: - b = base(ys) - print(f"all: {ys}") - print(f".PHONY: {ys}") - print(f"{ys}: ") - print(f"\t@echo Running {ys}.") - print(f"\t@$(YOSYS) -ql {b}.log {ys} >/dev/null 2>&1") - print() + # ---- Yosys script tests ---- + for ys in yss: + gen_tests_makefile.generate_ys_test(ys) -# ---- aigmap test ---- -print(f"all: aigmap") -print(f".PHONY: aigmap") -print("aigmap:") -print("\t@echo Running aigmap.") -print("\t@rm -rf gate; mkdir gate") -print('\t@$(YOSYS) --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1') -print("\t@set -o pipefail; diff --brief gold gate | tee aigmap.err") -print("\t@rm -f aigmap.err") -print() + cmd = [ "rm -rf gate; mkdir gate;", + "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\" >/dev/null 2>&1;", + "set -o pipefail; diff --brief gold gate | tee aigmap.err;", + "rm -f aigmap.err" ] + + gen_tests_makefile.generate_cmd_test("aigmap", cmd) + +extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc" ] + +gen_tests_makefile.generate_custom(create_tests, extra) diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh deleted file mode 100755 index 5208fa030..000000000 --- a/tests/aiger/run-test.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -OPTIND=1 -abcprog="../../yosys-abc" # default to built-in version of abc -while getopts "A:" opt -do - case "$opt" in - A) abcprog="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -# NB: *.aag and *.aig must contain a symbol table naming the primary -# inputs and outputs, otherwise ABC and Yosys will name them -# arbitrarily (and inconsistently with each other). - -for aag in *.aag; do - # Since ABC cannot read *.aag, read the *.aig instead - # (which would have been created by the reference aig2aig utility, - # available from http://fmv.jku.at/aiger/) - echo "Checking $aag." - $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" >/dev/null 2>&1 - ../../yosys -qp " -read_verilog ${aag%.*}_ref.v -prep -design -stash gold -read_aiger -clk_name clock $aag -prep -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aag}.log >/dev/null 2>&1 -done - -for aig in *.aig; do - echo "Checking $aig." - $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" >/dev/null 2>&1 - ../../yosys -qp " -read_verilog ${aig%.*}_ref.v -prep -design -stash gold -read_aiger -clk_name clock $aig -prep -design -stash gate -design -import gold -as gold -design -import gate -as gate -miter -equiv -flatten -make_assert -make_outputs gold gate miter -sat -verify -prove-asserts -show-ports -seq 16 miter -" -l ${aig}.log >/dev/null 2>&1 -done - -for y in *.ys; do - echo "Running $y." - ../../yosys -ql ${y%.*}.log $y >/dev/null 2>&1 -done - -# compare aigmap with reference -# make gold with: rm gold/*; yosys --no-version -p "test_cell -aigmap -w gold/ -n 1 -s 1 all" -rm -rf gate; mkdir gate -../../yosys --no-version -p "test_cell -aigmap -w gate/ -n 1 -s 1 all" >/dev/null 2>&1 -( - set -o pipefail - diff --brief gold gate | tee aigmap.err -) -rm aigmap.err diff --git a/tests/alumacc/run-test.sh b/tests/alumacc/run-test.sh deleted file mode 100644 index 2e3f5235c..000000000 --- a/tests/alumacc/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/bind/generate_mk.py b/tests/bind/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/bind/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/bind/run-test.sh b/tests/bind/run-test.sh deleted file mode 100755 index ea56b70f0..000000000 --- a/tests/bind/run-test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -set -e -{ -echo "all::" -for x in *.ys; do - echo "all:: run-$x" - echo "run-$x:" - echo " @echo 'Running $x..'" - echo " @../../yosys -ql ${x%.ys}.log $x" -done -for s in *.sh; do - if [ "$s" != "run-test.sh" ]; then - echo "all:: run-$s" - echo "run-$s:" - echo " @echo 'Running $s..'" - echo " @bash $s" - fi -done -} > run-test.mk -exec ${MAKE:-make} -f run-test.mk diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index b61e4917d..747603737 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -12,11 +12,12 @@ def _cwd_base(): return os.path.basename(os.getcwd()) def generate_target(name, command): - target = f"{_cwd_base()}-{name}" + #target = f"{_cwd_base()}-{name}" + target = f"{name}" print(f"all: {target}") print(f".PHONY: {target}") print(f"{target}:") - print(f"\t@@$(call run_test,{target}, \\") + print(f"\t@$(call run_test,{target}, \\") print(f"\tYOSYS_MAX_THREADS=4 {command})") def generate_ys_test(ys_file, yosys_args=""): @@ -38,6 +39,16 @@ def generate_bash_test(sh_file): cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" generate_target(sh_file, cmd) +def unpack_cmd(cmd): + if isinstance(cmd, str): + return cmd + if isinstance(cmd, (list, tuple)): + return " \\\n".join(cmd) + raise TypeError("cmd must be a string or a list/tuple of strings") + +def generate_cmd_test(test_name, cmd, yosys_args=""): + generate_target(test_name, unpack_cmd(cmd)) + def generate_tests(argv): parser = argparse.ArgumentParser(add_help=False) parser.add_argument("-y", "--yosys-scripts", action="store_true") @@ -85,3 +96,22 @@ def generate(argv, extra=None): generate_tests(argv) finally: sys.stdout = old + +def generate_custom(callback, extra=None): + with open("Makefile", "w") as f: + old = sys.stdout + sys.stdout = f + try: + print(f"include {common_mk}") + print(f"YOSYS ?= {yosys_basedir}/yosys") + if extra: + for line in extra: + print(line) + print() + print(".PHONY: all") + print("all:") + print() + + callback() + finally: + sys.stdout = old From 474d0d7b2e12a979337625c25e0bbf8593ca5c59 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 10:48:10 +0100 Subject: [PATCH 063/176] cleanup --- tests/gen_tests_makefile.py | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 747603737..0f106a7db 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -18,7 +18,7 @@ def generate_target(name, command): print(f".PHONY: {target}") print(f"{target}:") print(f"\t@$(call run_test,{target}, \\") - print(f"\tYOSYS_MAX_THREADS=4 {command})") + print(f"\t{command})") def generate_ys_test(ys_file, yosys_args=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -62,12 +62,6 @@ def generate_tests(argv): if not (args.yosys_scripts or args.tcl_scripts or args.prove_sv or args.bash): raise RuntimeError("No file types selected") - print(f"include {common_mk}") - print(f"YOSYS ?= {yosys_basedir}/yosys") - print() - print(".PHONY: all") - print("all:") - if args.yosys_scripts: for f in sorted(glob.glob("*.ys")): generate_ys_test(f, args.yosys_args) @@ -85,14 +79,24 @@ def generate_tests(argv): if f != "run-test.sh": generate_bash_test(f) +def print_header(extra=None): + print(f"include {common_mk}") + print(f"YOSYS ?= {yosys_basedir}/yosys") + print() + print("export YOSYS_MAX_THREADS := 4") + if extra: + for line in extra: + print(line) + print() + print(".PHONY: all") + print("all:") + def generate(argv, extra=None): with open("Makefile", "w") as f: old = sys.stdout sys.stdout = f try: - if extra: - for line in extra: - print(line) + print_header(extra) generate_tests(argv) finally: sys.stdout = old @@ -102,16 +106,7 @@ def generate_custom(callback, extra=None): old = sys.stdout sys.stdout = f try: - print(f"include {common_mk}") - print(f"YOSYS ?= {yosys_basedir}/yosys") - if extra: - for line in extra: - print(line) - print() - print(".PHONY: all") - print("all:") - print() - + print_header(extra) callback() finally: sys.stdout = old From 1bfb95513c8c940160cb8fc4cf2579a681146ef5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 13:07:11 +0100 Subject: [PATCH 064/176] Convert autotest script wrapper --- tests/Makefile | 8 ++--- tests/asicworld/generate_mk.py | 8 +++++ tests/asicworld/run-test.sh | 15 --------- tests/gen_tests_makefile.py | 20 ++++++++++++ tests/hana/generate_mk.py | 8 +++++ tests/hana/run-test.sh | 15 --------- tests/simple/generate_mk.py | 17 ++++++++++ tests/simple/run-test.sh | 21 ------------ tests/simple_abc9/generate_mk.py | 44 +++++++++++++++++++++++++ tests/simple_abc9/run-test.sh | 55 -------------------------------- 10 files changed, 101 insertions(+), 110 deletions(-) create mode 100644 tests/asicworld/generate_mk.py delete mode 100755 tests/asicworld/run-test.sh create mode 100644 tests/hana/generate_mk.py delete mode 100755 tests/hana/run-test.sh create mode 100644 tests/simple/generate_mk.py delete mode 100755 tests/simple/run-test.sh create mode 100644 tests/simple_abc9/generate_mk.py delete mode 100755 tests/simple_abc9/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 117399cd2..29f44e554 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -42,10 +42,10 @@ MK_TEST_DIRS += ./verilog # Tests that don't generate .mk SH_TEST_DIRS = -#SH_TEST_DIRS += ./simple -#SH_TEST_DIRS += ./simple_abc9 -#SH_TEST_DIRS += ./hana -#SH_TEST_DIRS += ./asicworld +MK_TEST_DIRS += ./simple +MK_TEST_DIRS += ./simple_abc9 +MK_TEST_DIRS += ./hana +MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./realmath #SH_TEST_DIRS += ./share #SH_TEST_DIRS += ./opt_share diff --git a/tests/asicworld/generate_mk.py b/tests/asicworld/generate_mk.py new file mode 100644 index 000000000..2f1df0646 --- /dev/null +++ b/tests/asicworld/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.v", "-e") diff --git a/tests/asicworld/run-test.sh b/tests/asicworld/run-test.sh deleted file mode 100755 index c9b4118a7..000000000 --- a/tests/asicworld/run-test.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS+="-e" *.v diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 0f106a7db..a01653c19 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -110,3 +110,23 @@ def generate_custom(callback, extra=None): callback() finally: sys.stdout = old + +def generate_autotest_file(test_file): + cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1" + generate_target(test_file, cmd) + +def generate_autotest(pattern, extra_flags): + with open("Makefile", "w") as f: + old = sys.stdout + sys.stdout = f + try: + print_header([ f"EXTRA_FLAGS = {extra_flags}", + "SEED ?=", + "ifneq ($(strip $(SEED)),)", + " SEEDOPT=-S$(SEED)", + "endif" + ]) + for f in sorted(glob.glob(pattern)): + generate_autotest_file(f) + finally: + sys.stdout = old diff --git a/tests/hana/generate_mk.py b/tests/hana/generate_mk.py new file mode 100644 index 000000000..0068c590a --- /dev/null +++ b/tests/hana/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("test_*.v", "-l hana_vlib.v -n 300 -e") diff --git a/tests/hana/run-test.sh b/tests/hana/run-test.sh deleted file mode 100755 index 8533e5544..000000000 --- a/tests/hana/run-test.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS="-l hana_vlib.v -n 300 -e" test_*.v diff --git a/tests/simple/generate_mk.py b/tests/simple/generate_mk.py new file mode 100644 index 000000000..f8e79bcaf --- /dev/null +++ b/tests/simple/generate_mk.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import shutil + +# ---------------------- +# Check if iverilog is installed +# ---------------------- +if shutil.which("iverilog") is None: + print("Error: Icarus Verilog 'iverilog' not found.", file=sys.stderr) + sys.exit(1) + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.*v", "") diff --git a/tests/simple/run-test.sh b/tests/simple/run-test.sh deleted file mode 100755 index c3711fe3e..000000000 --- a/tests/simple/run-test.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! command -v iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.{sv,v} diff --git a/tests/simple_abc9/generate_mk.py b/tests/simple_abc9/generate_mk.py new file mode 100644 index 000000000..44dd7e2b4 --- /dev/null +++ b/tests/simple_abc9/generate_mk.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import shutil +import os +from pathlib import Path + +# ---------------------- +# Check if iverilog is installed +# ---------------------- +if shutil.which("iverilog") is None: + print("Error: Icarus Verilog 'iverilog' not found.", file=sys.stderr) + sys.exit(1) + +src_dir = Path("../simple") +# ---------------------- +# Copy all files from ../simple to current directory +# ---------------------- +for file in src_dir.glob("*.v"): + shutil.copy(file, os.path.join(".", file.name)) + +for file in src_dir.glob("*.sv"): + shutil.copy(file, os.path.join(".", file.name)) + +# bug 2675 +bug_file = os.path.join(".", "specify.v") +if os.path.exists(bug_file): + os.remove(bug_file) + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.*v", "-f \"verilog -noblackbox -specify\" -n 300 -p '\ + read_verilog -icells -lib +/abc9_model.v; \ + hierarchy; \ + synth -run coarse; \ + opt -full; \ + techmap; \ + abc9 -lut 4; \ + clean; \ + check -assert * abc9_test037 %d; \ + select -assert-none t:?_NOT_ t:?_AND_ %%; \ + setattr -mod -unset blackbox -unset whitebox =*'") diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh deleted file mode 100755 index 0b3e5061f..000000000 --- a/tests/simple_abc9/run-test.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) arg="${OPTARG#"${OPTARG%%[![:space:]]*}"}" # remove leading space - seed="SEED=$arg" ;; - esac -done -shift "$((OPTIND-1))" - -# check for Icarus Verilog -if ! command -v iverilog > /dev/null ; then - echo "$0: Error: Icarus Verilog 'iverilog' not found." - exit 1 -fi - -for file in `ls *.v *.sv`; do - if [ ! -f "../simple/$file" -a "$file" != "abc9.v" ]; then - echo "Warning: $file is in simple_abc9/, but not in simple/" - backup="$file.bak" - if [ -f "$backup" ]; then - if cmp "$file" "$backup" > /dev/null; then - echo " => $backup already exists and matches; removing $file" - rm "$file" - else - echo " => $backup already exists but differs; leaving $file in place" - fi - else - echo " => moving $file to $backup" - mv -i "$file" "$backup" - fi - fi -done - -cp ../simple/*.v . -cp ../simple/*.sv . -rm specify.v # bug 2675 -DOLLAR='?' -exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-f \"verilog -noblackbox -specify\" -n 300 -p '\ - read_verilog -icells -lib +/abc9_model.v; \ - hierarchy; \ - synth -run coarse; \ - opt -full; \ - techmap; \ - abc9 -lut 4; \ - clean; \ - check -assert * abc9_test037 %d; \ - select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ - setattr -mod -unset blackbox -unset whitebox =*'" - -# NOTE: Skip 'check -assert' on abc9_test037 because it intentionally has a combinatorial loop From 2a8d369be3406f5404d607a1ba389b9d4bdbcf82 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 16 Mar 2026 15:45:59 +0100 Subject: [PATCH 065/176] Document not covered --- tests/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Makefile b/tests/Makefile index 29f44e554..c5bae2a92 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,6 +5,16 @@ endif OVERRIDE_MAIN=1 include ./common.mk +# Directories with tests not run: +# errors +# lut +# pyosys +# smv +# sva +# tools +# unit +# vloghtb + # Tests that generate Makefile with gen_tests_makefile.py MK_TEST_DIRS = MK_TEST_DIRS += ./arch/analogdevices From 5a06a79c0c007ec78a37d55b6b40983d5c41b9b6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 08:46:34 +0100 Subject: [PATCH 066/176] Correctly handle errors --- tests/common.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/common.mk b/tests/common.mk index ee4c5dee7..9d45e3762 100644 --- a/tests/common.mk +++ b/tests/common.mk @@ -6,8 +6,9 @@ clean: endif define run_test + @set -e; \ rc=0; \ - $(2) || rc=$$?; \ + ( set -e; $(2) ) || rc=$$?; \ if [ $$rc -eq 0 ]; then \ echo "PASS $1"; \ echo PASS > $1.result; \ From 1231bd53970b2a0f133d77cc01d7d0228ed93932 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 08:46:58 +0100 Subject: [PATCH 067/176] Convert memories tests --- tests/Makefile | 12 +----- tests/gen_tests_makefile.py | 10 ++--- tests/memories/generate_mk.py | 58 ++++++++++++++++++++++++++++ tests/memories/run-test.sh | 73 ----------------------------------- tests/tools/autotest.mk | 13 ------- 5 files changed, 65 insertions(+), 101 deletions(-) create mode 100644 tests/memories/generate_mk.py delete mode 100755 tests/memories/run-test.sh delete mode 100644 tests/tools/autotest.mk diff --git a/tests/Makefile b/tests/Makefile index c5bae2a92..864fa973d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -79,8 +79,7 @@ MK_TEST_DIRS += ./asicworld #endif # Tests that don't generate .mk and need special args -SH_ABC_TEST_DIRS = -#SH_ABC_TEST_DIRS += ./memories +MK_TEST_DIRS += ./memories MK_TEST_DIRS += ./aiger MK_TEST_DIRS += ./alumacc @@ -94,13 +93,6 @@ seed-./%: %/run-test.sh +cd $* && bash run-test.sh $(SEEDOPT) +@echo "...passed tests in $*" -# abcopt-./ is a dummy string, not a directory -.PHONY: abcopt-tests -abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-./%) -abcopt-./%: %/run-test.sh - +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) - +@echo "...passed tests in $*" - # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests .SILENT: $(MK_TEST_DIRS:%=%/Makefile) @@ -117,7 +109,7 @@ makefile-./%: %/Makefile @$(MAKE) -C $* @echo "...passed tests in $*" -vanilla-test: makefile-tests abcopt-tests seed-tests +vanilla-test: makefile-tests seed-tests @echo "" @echo " Passed \"make vanilla-test\"." ifeq ($(ENABLE_VERIFIC),1) diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index a01653c19..d714820e5 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -111,11 +111,11 @@ def generate_custom(callback, extra=None): finally: sys.stdout = old -def generate_autotest_file(test_file): - cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1" +def generate_autotest_file(test_file, commands): + cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1; \\\n{commands}" generate_target(test_file, cmd) -def generate_autotest(pattern, extra_flags): +def generate_autotest(pattern, extra_flags, cmds=""): with open("Makefile", "w") as f: old = sys.stdout sys.stdout = f @@ -124,9 +124,9 @@ def generate_autotest(pattern, extra_flags): "SEED ?=", "ifneq ($(strip $(SEED)),)", " SEEDOPT=-S$(SEED)", - "endif" + "endif", ]) for f in sorted(glob.glob(pattern)): - generate_autotest_file(f) + generate_autotest_file(f, cmds) finally: sys.stdout = old diff --git a/tests/memories/generate_mk.py b/tests/memories/generate_mk.py new file mode 100644 index 000000000..0df27bc5e --- /dev/null +++ b/tests/memories/generate_mk.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate_autotest("*.v", "", +"""if grep -Eq 'expect-(wr-ports|rd-ports|rd-clk)' $@; then \\ + $(YOSYS) -f verilog -qp "proc; opt; memory -nomap; dump -outfile $(@:.v=).dmp t:\\$$mem_v2" $@; \\ + if grep -q expect-wr-ports $@; then \\ + val=$$(gawk '/expect-wr-ports/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\WR_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of write ports."; exit 1; }; \\ + fi; \\ + if grep -q expect-wr-wide-continuation $@; then \\ + val=$$(gawk '/expect-wr-wide-continuation/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\WR_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected write wide continuation."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-ports $@; then \\ + val=$$(gawk '/expect-rd-ports/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_PORTS $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected number of read ports."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-clk $@; then \\ + val=$$(gawk '/expect-rd-clk/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_CLK $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read clock."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-en $@; then \\ + val=$$(gawk '/expect-rd-en/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_EN $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read enable."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-srst-sig $@; then \\ + val=$$(gawk '/expect-rd-srst-sig/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_SRST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-srst-val $@; then \\ + val=$$(gawk '/expect-rd-srst-val/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_SRST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read sync reset value."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-arst-sig $@; then \\ + val=$$(gawk '/expect-rd-arst-sig/ { print $$3; }' $@); \\ + grep -Fq "connect \\\\RD_ARST $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-arst-val $@; then \\ + val=$$(gawk '/expect-rd-arst-val/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_ARST_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read async reset value."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-init-val $@; then \\ + val=$$(gawk '/expect-rd-init-val/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_INIT_VALUE $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read init value."; exit 1; }; \\ + fi; \\ + if grep -q expect-rd-wide-continuation $@; then \\ + val=$$(gawk '/expect-rd-wide-continuation/ { print $$3; }' $@); \\ + grep -Fq "parameter \\\\RD_WIDE_CONTINUATION $$val" $(@:.v=).dmp || { echo " ERROR: Unexpected read wide continuation."; exit 1; }; \\ + fi; \\ + if grep -q expect-no-rd-clk $@; then \\ + grep -Fq "connect \\\\RD_CLK 1'x" $(@:.v=).dmp || { echo " ERROR: Expected no read clock."; exit 1; }; \\ + fi; \\ +fi""") \ No newline at end of file diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh deleted file mode 100755 index 8f83e11a1..000000000 --- a/tests/memories/run-test.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -OPTIND=1 -seed="" # default to no seed specified -abcopt="" -while getopts "A:S:" opt -do - case "$opt" in - A) abcopt="-A $OPTARG" ;; - S) seed="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -${MAKE:-make} -f ../tools/autotest.mk SEED="$seed" EXTRA_FLAGS="$abcopt" *.v - -for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do - echo -n "Testing expectations for $f .." - ../../yosys -f verilog -qp "proc; opt; memory -nomap;; dump -outfile ${f%.v}.dmp t:\$mem_v2" $f - if grep -q expect-wr-ports $f; then - grep -q "parameter \\\\WR_PORTS $(gawk '/expect-wr-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected number of write ports."; false; } - fi - if grep -q expect-wr-wide-continuation $f; then - grep -q "parameter \\\\WR_WIDE_CONTINUATION $(gawk '/expect-wr-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected write wide continuation."; false; } - fi - if grep -q expect-rd-ports $f; then - grep -q "parameter \\\\RD_PORTS $(gawk '/expect-rd-ports/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected number of read ports."; false; } - fi - if grep -q expect-rd-clk $f; then - grep -q "connect \\\\RD_CLK \\$(gawk '/expect-rd-clk/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read clock."; false; } - fi - if grep -q expect-rd-en $f; then - grep -q "connect \\\\RD_EN \\$(gawk '/expect-rd-en/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read enable."; false; } - fi - if grep -q expect-rd-srst-sig $f; then - grep -q "connect \\\\RD_SRST \\$(gawk '/expect-rd-srst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read sync reset."; false; } - fi - if grep -q expect-rd-srst-val $f; then - grep -q "parameter \\\\RD_SRST_VALUE $(gawk '/expect-rd-srst-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read sync reset value."; false; } - fi - if grep -q expect-rd-arst-sig $f; then - grep -q "connect \\\\RD_ARST \\$(gawk '/expect-rd-arst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read async reset."; false; } - fi - if grep -q expect-rd-arst-val $f; then - grep -q "parameter \\\\RD_ARST_VALUE $(gawk '/expect-rd-arst-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read async reset value."; false; } - fi - if grep -q expect-rd-init-val $f; then - grep -q "parameter \\\\RD_INIT_VALUE $(gawk '/expect-rd-init-val/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read init value."; false; } - fi - if grep -q expect-rd-wide-continuation $f; then - grep -q "parameter \\\\RD_WIDE_CONTINUATION $(gawk '/expect-rd-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp || - { echo " ERROR: Unexpected read wide continuation."; false; } - fi - if grep -q expect-no-rd-clk $f; then - grep -q "connect \\\\RD_CLK 1'x\$" ${f%.v}.dmp || - { echo " ERROR: Expected no read clock."; false; } - fi - echo " ok." -done - diff --git a/tests/tools/autotest.mk b/tests/tools/autotest.mk deleted file mode 100644 index e0f2bcdc1..000000000 --- a/tests/tools/autotest.mk +++ /dev/null @@ -1,13 +0,0 @@ - -# Don't bother defining default values for SEED and EXTRA_FLAGS. -# Their "natural" default values should be sufficient, -# and they may be overridden in the environment. -ifneq ($(strip $(SEED)),) -SEEDOPT=-S$(SEED) -endif - -$(MAKECMDGOALS): - @$(basename $(MAKEFILE_LIST)).sh -G -j $(SEEDOPT) $(EXTRA_FLAGS) $@ - -.PHONY: $(MAKECMDGOALS) - From 2bc46e77c82984e92035af5bb261cf5f390eafb9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 09:45:33 +0100 Subject: [PATCH 068/176] Converted blif tests --- tests/Makefile | 2 +- tests/blif/generate_mk.py | 11 +++++++++++ tests/blif/run-test.sh | 11 ----------- tests/gen_tests_makefile.py | 30 +++++++++++++++++++----------- 4 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 tests/blif/generate_mk.py delete mode 100755 tests/blif/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 864fa973d..6b8535822 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -67,7 +67,7 @@ MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./select #SH_TEST_DIRS += ./peepopt #SH_TEST_DIRS += ./proc -#SH_TEST_DIRS += ./blif +MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch #SH_TEST_DIRS += ./rpc #SH_TEST_DIRS += ./memfile diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py new file mode 100644 index 000000000..41f2d769d --- /dev/null +++ b/tests/blif/generate_mk.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"], [], +"""if [ -f $(@:.ys=.blif) ]; then \\ + diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1; \\ +fi""") \ No newline at end of file diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh deleted file mode 100755 index 97f12d288..000000000 --- a/tests/blif/run-test.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys --no-version -ql ${x%.ys}.log $x >/dev/null 2>&1 -done - -for x in *.blif; do - diff $x.out $x.ok -done \ No newline at end of file diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index d714820e5..84640780b 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -20,23 +20,31 @@ def generate_target(name, command): print(f"\t@$(call run_test,{target}, \\") print(f"\t{command})") -def generate_ys_test(ys_file, yosys_args=""): +def generate_ys_test(ys_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' + if commands: + cmd += f"; \\\n{commands}" generate_target(ys_file, cmd) -def generate_tcl_test(tcl_file, yosys_args=""): +def generate_tcl_test(tcl_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} >/dev/null 2>&1 && mv {tcl_file}.err {tcl_file}.log' + if commands: + cmd += f"; \\\n{commands}" generate_target(tcl_file, cmd) -def generate_sv_test(sv_file, yosys_args=""): +def generate_sv_test(sv_file, yosys_args="", commands=""): base = os.path.splitext(sv_file)[0] if not os.path.exists(base + ".ys"): yosys_cmd = '-p "prep -top top; async2sync; sat -enable_undef -verify -prove-asserts"' cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} >/dev/null 2>&1 && mv {sv_file}.err {sv_file}.log' + if commands: + cmd += f"; \\\n{commands}" generate_target(sv_file, cmd) -def generate_bash_test(sh_file): +def generate_bash_test(sh_file, commands=""): cmd = f"bash -v {sh_file} >{sh_file}.err 2>&1 && mv {sh_file}.err {sh_file}.log" + if commands: + cmd += f"; \\\n{commands}" generate_target(sh_file, cmd) def unpack_cmd(cmd): @@ -49,7 +57,7 @@ def unpack_cmd(cmd): def generate_cmd_test(test_name, cmd, yosys_args=""): generate_target(test_name, unpack_cmd(cmd)) -def generate_tests(argv): +def generate_tests(argv, cmds): parser = argparse.ArgumentParser(add_help=False) parser.add_argument("-y", "--yosys-scripts", action="store_true") parser.add_argument("-t", "--tcl-scripts", action="store_true") @@ -64,20 +72,20 @@ def generate_tests(argv): if args.yosys_scripts: for f in sorted(glob.glob("*.ys")): - generate_ys_test(f, args.yosys_args) + generate_ys_test(f, args.yosys_args, cmds) if args.tcl_scripts: for f in sorted(glob.glob("*.tcl")): - generate_tcl_test(f, args.yosys_args) + generate_tcl_test(f, args.yosys_args, cmds) if args.prove_sv: for f in sorted(glob.glob("*.sv")): - generate_sv_test(f, args.yosys_args) + generate_sv_test(f, args.yosys_args, cmds) if args.bash: for f in sorted(glob.glob("*.sh")): if f != "run-test.sh": - generate_bash_test(f) + generate_bash_test(f, cmds) def print_header(extra=None): print(f"include {common_mk}") @@ -91,13 +99,13 @@ def print_header(extra=None): print(".PHONY: all") print("all:") -def generate(argv, extra=None): +def generate(argv, extra=None, cmds=""): with open("Makefile", "w") as f: old = sys.stdout sys.stdout = f try: print_header(extra) - generate_tests(argv) + generate_tests(argv, cmds) finally: sys.stdout = old From 68e01a03d78e62bf298fba22d23b89696f108fdd Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 09:54:33 +0100 Subject: [PATCH 069/176] Converted some more --- tests/Makefile | 6 +++--- tests/peepopt/generate_mk.py | 8 ++++++++ tests/peepopt/run-test.sh | 7 ------- tests/proc/generate_mk.py | 8 ++++++++ tests/proc/run-test.sh | 7 ------- tests/select/generate_mk.py | 8 ++++++++ tests/select/run-test.sh | 7 ------- 7 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 tests/peepopt/generate_mk.py delete mode 100644 tests/peepopt/run-test.sh create mode 100644 tests/proc/generate_mk.py delete mode 100755 tests/proc/run-test.sh create mode 100644 tests/select/generate_mk.py delete mode 100755 tests/select/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 6b8535822..23d152bd7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -64,9 +64,9 @@ MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces #SH_TEST_DIRS += ./xprop -#SH_TEST_DIRS += ./select -#SH_TEST_DIRS += ./peepopt -#SH_TEST_DIRS += ./proc +MK_TEST_DIRS += ./select +MK_TEST_DIRS += ./peepopt +MK_TEST_DIRS += ./proc MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch #SH_TEST_DIRS += ./rpc diff --git a/tests/peepopt/generate_mk.py b/tests/peepopt/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/peepopt/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/peepopt/run-test.sh b/tests/peepopt/run-test.sh deleted file mode 100644 index 2e3f5235c..000000000 --- a/tests/peepopt/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done diff --git a/tests/proc/generate_mk.py b/tests/proc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/proc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/proc/run-test.sh b/tests/proc/run-test.sh deleted file mode 100755 index 241b32295..000000000 --- a/tests/proc/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 -done diff --git a/tests/select/generate_mk.py b/tests/select/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/select/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/select/run-test.sh b/tests/select/run-test.sh deleted file mode 100755 index 241b32295..000000000 --- a/tests/select/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x >/dev/null 2>&1 -done From 652bbd2b41dcb78addeb6cad6d9f909cd94a2014 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 18 Mar 2026 15:25:28 +0100 Subject: [PATCH 070/176] Convert xprop tests --- tests/Makefile | 2 +- tests/gen_tests_makefile.py | 33 +++++++++++---------- tests/xprop/{generate.py => generate_mk.py} | 29 ++++++++---------- tests/xprop/run-test.sh | 6 ---- 4 files changed, 32 insertions(+), 38 deletions(-) rename tests/xprop/{generate.py => generate_mk.py} (94%) delete mode 100755 tests/xprop/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 23d152bd7..f5642c940 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -63,7 +63,7 @@ MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./memlib #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces -#SH_TEST_DIRS += ./xprop +MK_TEST_DIRS += ./xprop MK_TEST_DIRS += ./select MK_TEST_DIRS += ./peepopt MK_TEST_DIRS += ./proc diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 84640780b..2f842f570 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -11,14 +11,17 @@ common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk") def _cwd_base(): return os.path.basename(os.getcwd()) -def generate_target(name, command): +def generate_target(name, command, out=sys.stdout): #target = f"{_cwd_base()}-{name}" target = f"{name}" - print(f"all: {target}") - print(f".PHONY: {target}") - print(f"{target}:") - print(f"\t@$(call run_test,{target}, \\") - print(f"\t{command})") + print(f"all: {target}", file=out) + print(f".PHONY: {target}", file=out) + print(f"{target}:", file=out) + if command: + print(f"\t@$(call run_test,{target}, \\", file=out) + print(f"\t{command})", file=out) + else: + print(f"\t@$(call run_test,{target})", file=out) def generate_ys_test(ys_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -87,17 +90,17 @@ def generate_tests(argv, cmds): if f != "run-test.sh": generate_bash_test(f, cmds) -def print_header(extra=None): - print(f"include {common_mk}") - print(f"YOSYS ?= {yosys_basedir}/yosys") - print() - print("export YOSYS_MAX_THREADS := 4") +def print_header(extra=None, out=sys.stdout): + print(f"include {common_mk}", file=out) + print(f"YOSYS ?= {yosys_basedir}/yosys", file=out) + print("", file=out) + print("export YOSYS_MAX_THREADS := 4", file=out) if extra: for line in extra: - print(line) - print() - print(".PHONY: all") - print("all:") + print(line, file=out) + print("", file=out) + print(".PHONY: all", file=out) + print("all:", file=out) def generate(argv, extra=None, cmds=""): with open("Makefile", "w") as f: diff --git a/tests/xprop/generate.py b/tests/xprop/generate_mk.py similarity index 94% rename from tests/xprop/generate.py rename to tests/xprop/generate_mk.py index 484f1661c..67ab26bda 100644 --- a/tests/xprop/generate.py +++ b/tests/xprop/generate_mk.py @@ -1,6 +1,12 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + import os import re -import sys import random import argparse @@ -16,7 +22,9 @@ if args.seed is None: print(f"xprop PRNG seed: {args.seed}") -makefile = open("run-test.mk", "w") +makefile = open("Makefile", "w") + +gen_tests_makefile.print_header(out = makefile) def add_test(name, src, seq=False): if not re.search(args.filter, name): @@ -26,17 +34,10 @@ def add_test(name, src, seq=False): os.makedirs(workdir, exist_ok=True) with open(f"{workdir}/uut.v", "w") as uut: print(src, file=uut) - print(f"all: {workdir}", file=makefile) - print(f".PHONY: {workdir}", file=makefile) - print(f"{workdir}:", file=makefile) seq_arg = " -s" if seq else "" - print( - f"\t@cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1 || echo {workdir}: failed > status\n" - f"\t@cat {workdir}/status\n" - f"\t@grep '^.*: ok' {workdir}/status\n" - , - file=makefile, - ) + gen_tests_makefile.generate_target(workdir, + f"cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1", + out=makefile) def cell_test(name, cell, inputs, outputs, params, initial={}, defclock=False, seq=False): ports = [] @@ -119,10 +120,6 @@ def dff_test(width, pol, defclock): def dffe_test(width, pol, enpol, defclock): cell_test(f"dffe_{width}{'np'[pol]}{'np'[enpol]}{'xd'[defclock]}", 'dffe', {"CLK": 1, "EN": 1, "D": width}, {"Q": width}, {"WIDTH": width, "CLK_POLARITY": int(pol), "EN_POLARITY": int(enpol)}, defclock=defclock, seq=True) - -print(".PHONY: all", file=makefile) -print("all:\n\t@echo done\n", file=makefile) - for cell in ["not", "pos", "neg"]: if args.more: unary_test(cell, 1, False, 1) diff --git a/tests/xprop/run-test.sh b/tests/xprop/run-test.sh deleted file mode 100755 index 303c0bb3b..000000000 --- a/tests/xprop/run-test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e - -python3 generate.py $@ -${MAKE:-make} -f run-test.mk From d1dc23d9f89b02e8dbedfca9c95279ba7a0c947d Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 12:47:15 +0100 Subject: [PATCH 071/176] Did share, opt_share and fsm --- tests/Makefile | 6 +- tests/fsm/.gitignore | 2 +- tests/fsm/{generate.py => generate_mk.py} | 36 ++++++----- tests/fsm/run-test.sh | 45 ------------- tests/gen_tests_makefile.py | 63 +++++++++---------- tests/opt_share/.gitignore | 2 +- .../opt_share/{generate.py => generate_mk.py} | 62 +++++++++--------- tests/opt_share/run-test.sh | 51 --------------- tests/rpc/generate_mk.py | 8 +++ tests/share/.gitignore | 2 +- tests/share/{generate.py => generate_mk.py} | 47 +++++++------- tests/share/run-test.sh | 40 ------------ tests/xprop/generate_mk.py | 11 ++-- 13 files changed, 122 insertions(+), 253 deletions(-) rename tests/fsm/{generate.py => generate_mk.py} (89%) delete mode 100755 tests/fsm/run-test.sh rename tests/opt_share/{generate.py => generate_mk.py} (61%) delete mode 100755 tests/opt_share/run-test.sh create mode 100644 tests/rpc/generate_mk.py rename tests/share/{generate.py => generate_mk.py} (80%) delete mode 100755 tests/share/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index f5642c940..aa82ccc61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -57,9 +57,9 @@ MK_TEST_DIRS += ./simple_abc9 MK_TEST_DIRS += ./hana MK_TEST_DIRS += ./asicworld #SH_TEST_DIRS += ./realmath -#SH_TEST_DIRS += ./share -#SH_TEST_DIRS += ./opt_share -#SH_TEST_DIRS += ./fsm +MK_TEST_DIRS += ./share +MK_TEST_DIRS += ./opt_share +MK_TEST_DIRS += ./fsm #SH_TEST_DIRS += ./memlib #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces diff --git a/tests/fsm/.gitignore b/tests/fsm/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/fsm/.gitignore +++ b/tests/fsm/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/fsm/generate.py b/tests/fsm/generate_mk.py similarity index 89% rename from tests/fsm/generate.py rename to tests/fsm/generate_mk.py index 784e5a054..dc3518009 100644 --- a/tests/fsm/generate.py +++ b/tests/fsm/generate_mk.py @@ -1,21 +1,18 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager +from pathlib import Path # set to 'True' to compare verific with yosys test_verific = False -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - def random_expr(variables): c = random.choice(['bin', 'uni', 'var', 'const']) if c == 'bin': @@ -39,12 +36,16 @@ args = parser.parse_args() seed = args.seed if seed is None: seed = random.randrange(sys.maxsize) -print("PRNG seed: %d" % seed) +print("fsm PRNG seed: %d" % seed) random.seed(seed) +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() + for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): rst2 = random.choice([False, True]) if rst2: print('module uut_%05d(clk, rst1, rst2, rst, a, b, c, x, y, z);' % (idx)) @@ -99,16 +100,16 @@ for idx in range(args.count): print(' end') print(' end') print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): if test_verific: - print('read_verilog temp/uut_%05d.v' % idx) + print('read_verilog uut_%05d.v' % idx) print('proc;; rename uut_%05d gold' % idx) - print('verific -vlog2k temp/uut_%05d.v' % idx) + print('verific -vlog2k uut_%05d.v' % idx) print('verific -import uut_%05d' % idx) print('rename uut_%05d gate' % idx) else: - print('read_verilog temp/uut_%05d.v' % idx) + print('read_verilog uut_%05d.v' % idx) print('proc;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) @@ -118,3 +119,4 @@ for idx in range(args.count): print('miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter') print('sat -verify-no-timeout -timeout 20 -seq 5 -set-at 1 %s_rst 1 -prove trigger 0 -prove-skip 1 -show-inputs -show-outputs miter' % ('gold' if rst2 else 'in')) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/fsm/run-test.sh b/tests/fsm/run-test.sh deleted file mode 100755 index 304242126..000000000 --- a/tests/fsm/run-test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=50 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -{ - all_targets="all_targets:" - echo "all: all_targets" - echo " @echo" - for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - idx=$( printf "%05d" $i ) - echo "temp/uut_${idx}.log: temp/uut_${idx}.ys temp/uut_${idx}.v" - echo " @echo -n '[$i]'" - echo " @../../yosys -ql temp/uut_${idx}.out temp/uut_${idx}.ys >/dev/null 2>&1" - echo " @mv temp/uut_${idx}.out temp/uut_${idx}.log" - echo " @grep -q 'SAT proof finished' temp/uut_${idx}.log && echo -n K || echo -n T" - all_targets="$all_targets temp/uut_${idx}.log" - done - echo "$all_targets" -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile - -exit 0 diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 2f842f570..969a0f41a 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -4,6 +4,7 @@ import glob import os import sys import argparse +from contextlib import contextmanager yosys_basedir = os.path.relpath(os.path.join(os.path.dirname(__file__), "..")) common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk")) @@ -11,17 +12,17 @@ common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk") def _cwd_base(): return os.path.basename(os.getcwd()) -def generate_target(name, command, out=sys.stdout): +def generate_target(name, command): #target = f"{_cwd_base()}-{name}" target = f"{name}" - print(f"all: {target}", file=out) - print(f".PHONY: {target}", file=out) - print(f"{target}:", file=out) + print(f"all: {target}") + print(f".PHONY: {target}") + print(f"{target}:") if command: - print(f"\t@$(call run_test,{target}, \\", file=out) - print(f"\t{command})", file=out) + print(f"\t@$(call run_test,{target}, \\") + print(f"\t{command})") else: - print(f"\t@$(call run_test,{target})", file=out) + print(f"\t@$(call run_test,{target})") def generate_ys_test(ys_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' @@ -90,37 +91,37 @@ def generate_tests(argv, cmds): if f != "run-test.sh": generate_bash_test(f, cmds) -def print_header(extra=None, out=sys.stdout): - print(f"include {common_mk}", file=out) - print(f"YOSYS ?= {yosys_basedir}/yosys", file=out) - print("", file=out) - print("export YOSYS_MAX_THREADS := 4", file=out) +def print_header(extra=None): + print(f"include {common_mk}") + print(f"YOSYS ?= {yosys_basedir}/yosys") + print("") + print("export YOSYS_MAX_THREADS := 4") if extra: for line in extra: - print(line, file=out) - print("", file=out) - print(".PHONY: all", file=out) - print("all:", file=out) + print(line) + print("") + print(".PHONY: all") + print("all:") + +@contextmanager +def redirect_stdout(new_target): + old_target, sys.stdout = sys.stdout, new_target + try: + yield new_target + finally: + sys.stdout = old_target def generate(argv, extra=None, cmds=""): with open("Makefile", "w") as f: - old = sys.stdout - sys.stdout = f - try: + with redirect_stdout(f): print_header(extra) generate_tests(argv, cmds) - finally: - sys.stdout = old def generate_custom(callback, extra=None): with open("Makefile", "w") as f: - old = sys.stdout - sys.stdout = f - try: + with redirect_stdout(f): print_header(extra) callback() - finally: - sys.stdout = old def generate_autotest_file(test_file, commands): cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1; \\\n{commands}" @@ -128,16 +129,12 @@ def generate_autotest_file(test_file, commands): def generate_autotest(pattern, extra_flags, cmds=""): with open("Makefile", "w") as f: - old = sys.stdout - sys.stdout = f - try: + with redirect_stdout(f): print_header([ f"EXTRA_FLAGS = {extra_flags}", "SEED ?=", "ifneq ($(strip $(SEED)),)", " SEEDOPT=-S$(SEED)", "endif", ]) - for f in sorted(glob.glob(pattern)): - generate_autotest_file(f, cmds) - finally: - sys.stdout = old + for fn in sorted(glob.glob(pattern)): + generate_autotest_file(fn, cmds) diff --git a/tests/opt_share/.gitignore b/tests/opt_share/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/opt_share/.gitignore +++ b/tests/opt_share/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/opt_share/generate.py b/tests/opt_share/generate_mk.py similarity index 61% rename from tests/opt_share/generate.py rename to tests/opt_share/generate_mk.py index 2ec92f7de..0d7e494e9 100644 --- a/tests/opt_share/generate.py +++ b/tests/opt_share/generate_mk.py @@ -1,48 +1,42 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager - - -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target - +from pathlib import Path def random_plus_x(): return "%s x" % random.choice(['+', '+', '+', '-', '-', '|', '&', '^']) - def maybe_plus_x(expr): if random.randint(0, 4) == 0: return "(%s %s)" % (expr, random_plus_x()) else: return expr - -parser = argparse.ArgumentParser( - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument('-S', '--seed', type=int, help='seed for PRNG') -parser.add_argument('-c', - '--count', - type=int, - default=100, - help='number of test cases to generate') +parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') +parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("opt_share PRNG seed: %d" % seed) +random.seed(seed) + +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d(a, b, c, s, y);' % (idx)) op = random.choice([ random.choice(['+', '-', '*', '/', '%']), @@ -67,20 +61,20 @@ for idx in range(args.count): cast2, ops2[0], op, ops2[1])) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): - print('read_verilog temp/uut_%05d.v' % idx) + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): + print('read_verilog uut_%05d.v' % idx) print('proc;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) - print('tee -a temp/all_share_log.txt log') - print('tee -a temp/all_share_log.txt log #job# uut_%05d' % idx) - print('tee -a temp/all_share_log.txt opt gate') - print('tee -a temp/all_share_log.txt opt_share gate') - print('tee -a temp/all_share_log.txt opt_clean gate') + print('tee -o uut_%05d.txt opt gate' % idx) + print('tee -o uut_%05d.txt opt_share gate' % idx) + print('tee -o uut_%05d.txt opt_clean gate' % idx) print( 'miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter' ) print( 'sat -set-def-inputs -verify -prove trigger 0 -show-inputs -show-outputs miter' ) + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/opt_share/run-test.sh b/tests/opt_share/run-test.sh deleted file mode 100755 index e33399567..000000000 --- a/tests/opt_share/run-test.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -{ - echo ".PHONY: all" - echo "all:" - - for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - idx=$( printf "%05d" $i ) - echo ".PHONY: test-$idx" - echo "all: test-$idx" - echo "test-$idx:" - printf "\t@%s\n" \ - "echo -n [$i]" \ - "../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1" - done -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile -echo - -failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) ) -if [ -n "$failed_share" ]; then - echo "Resource sharing failed for the following test cases: $failed_share" - false -fi - -exit 0 diff --git a/tests/rpc/generate_mk.py b/tests/rpc/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/rpc/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/share/.gitignore b/tests/share/.gitignore index 9c595a6fb..90ea6e92a 100644 --- a/tests/share/.gitignore +++ b/tests/share/.gitignore @@ -1 +1 @@ -temp +uut_*.* diff --git a/tests/share/generate.py b/tests/share/generate_mk.py similarity index 80% rename from tests/share/generate.py rename to tests/share/generate_mk.py index 7e87bd648..6a40758e1 100644 --- a/tests/share/generate.py +++ b/tests/share/generate_mk.py @@ -1,17 +1,14 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") + +import gen_tests_makefile + import argparse import sys import random -from contextlib import contextmanager - -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target +from pathlib import Path def random_plus_x(): return "%s x" % random.choice(['+', '+', '+', '-', '-', '|', '&', '^']) @@ -27,13 +24,19 @@ parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("share PRNG seed: %d" % seed) +random.seed(seed) + +for path in Path(".").glob("uut_*.*"): + if path.is_file(): + path.unlink() for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): if random.choice(['bin', 'uni']) == 'bin': print('module uut_%05d(a, b, c, d, x, s, y);' % (idx)) op = random.choice([ @@ -67,16 +70,16 @@ for idx in range(args.count): random.choice(['', '$signed', '$unsigned']), op, maybe_plus_x('b'), random_plus_x() if random.randint(0, 4) == 0 else '')) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): - print('read_verilog temp/uut_%05d.v' % idx) - print('proc;;') + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): + print('read_verilog uut_%05d.v' % idx) + print('proc -noopt;;') print('copy uut_%05d gold' % idx) print('rename uut_%05d gate' % idx) - print('tee -a temp/all_share_log.txt log') - print('tee -a temp/all_share_log.txt log #job# uut_%05d' % idx) - print('tee -a temp/all_share_log.txt wreduce') - print('tee -a temp/all_share_log.txt share -aggressive gate') + print('tee -o uut_%05d.txt wreduce' % idx) + print('tee -a uut_%05d.txt share -aggressive gate' % idx) print('miter -equiv -flatten -ignore_gold_x -make_outputs -make_outcmp gold gate miter') print('sat -set-def-inputs -verify -prove trigger 0 -show-inputs -show-outputs miter') + print('! grep -q \'^Removing [246] cells\' uut_%05d.txt' % idx) +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/share/run-test.sh b/tests/share/run-test.sh deleted file mode 100755 index 36349baad..000000000 --- a/tests/share/run-test.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -echo "running tests.." -for i in $( ls temp/*.ys | sed 's,[^0-9],,g; s,^0*\(.\),\1,g;' ); do - echo -n "[$i]" - idx=$( printf "%05d" $i ) - ../../yosys -ql temp/uut_${idx}.log temp/uut_${idx}.ys >/dev/null 2>&1 -done -echo - -failed_share=$( echo $( gawk '/^#job#/ { j=$2; db[j]=0; } /^Removing [246] cells/ { delete db[j]; } END { for (j in db) print(j); }' temp/all_share_log.txt ) ) -if [ -n "$failed_share" ]; then - echo "Resource sharing failed for the following test cases: $failed_share" - false -fi - -exit 0 diff --git a/tests/xprop/generate_mk.py b/tests/xprop/generate_mk.py index 67ab26bda..c4a351247 100644 --- a/tests/xprop/generate_mk.py +++ b/tests/xprop/generate_mk.py @@ -22,9 +22,10 @@ if args.seed is None: print(f"xprop PRNG seed: {args.seed}") -makefile = open("Makefile", "w") -gen_tests_makefile.print_header(out = makefile) +makefile = open("Makefile", "w") +with gen_tests_makefile.redirect_stdout(makefile): + gen_tests_makefile.print_header() def add_test(name, src, seq=False): if not re.search(args.filter, name): @@ -35,9 +36,9 @@ def add_test(name, src, seq=False): with open(f"{workdir}/uut.v", "w") as uut: print(src, file=uut) seq_arg = " -s" if seq else "" - gen_tests_makefile.generate_target(workdir, - f"cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1", - out=makefile) + with gen_tests_makefile.redirect_stdout(makefile): + gen_tests_makefile.generate_target(workdir, + f"cd {workdir} && python3 -u ../test.py -S {args.seed} -c {args.count}{seq_arg} > test.log 2>&1") def cell_test(name, cell, inputs, outputs, params, initial={}, defclock=False, seq=False): ports = [] From 0ba9a0fb16d8fb1c3ac9d095315e04e81ffd2a29 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 15:12:51 +0100 Subject: [PATCH 072/176] Try fixing tests --- tests/blif/generate_mk.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index 41f2d769d..47cb9accd 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -6,6 +6,6 @@ sys.path.append("..") import gen_tests_makefile gen_tests_makefile.generate(["--yosys-scripts"], [], -"""if [ -f $(@:.ys=.blif) ]; then \\ - diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1; \\ -fi""") \ No newline at end of file +"""[ ! -f $(@:.ys=.blif) ] || \\ + diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ +""") \ No newline at end of file From c15bcca25a7f52dee469a3ca0f2a8586cc5bee11 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 15:38:24 +0100 Subject: [PATCH 073/176] Better fix --- tests/blif/generate_mk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index 47cb9accd..bd6d74fd9 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -7,5 +7,5 @@ import gen_tests_makefile gen_tests_makefile.generate(["--yosys-scripts"], [], """[ ! -f $(@:.ys=.blif) ] || \\ - diff <(tail -n +2 $(@:.ys=.blif).out) <(tail -n +2 $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ + sed '1d' $(@:.ys=.blif).out | diff - <(sed '1d' $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ """) \ No newline at end of file From 1effec202913b7e565c56552efaf515c5976ac05 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Mar 2026 16:16:58 +0100 Subject: [PATCH 074/176] Make test simple --- tests/blif/gatesi.blif.ok | 1 - tests/blif/gatesi.ys | 4 +++- tests/blif/generate_mk.py | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/blif/gatesi.blif.ok b/tests/blif/gatesi.blif.ok index e99d7906f..8213a8a89 100644 --- a/tests/blif/gatesi.blif.ok +++ b/tests/blif/gatesi.blif.ok @@ -1,4 +1,3 @@ -# Generated by Yosys .model test .inputs clk in_a_var[0] in_a_var[1] in_a_var[2] in_a_var[3] in_a_var[4] in_a_var[5] in_a_var[6] in_a_var[7] in_b_var[0] in_b_var[1] in_b_var[2] in_b_var[3] in_b_var[4] in_b_var[5] in_b_var[6] in_b_var[7] diff --git a/tests/blif/gatesi.ys b/tests/blif/gatesi.ys index 44c022bb9..0f1ebd911 100644 --- a/tests/blif/gatesi.ys +++ b/tests/blif/gatesi.ys @@ -1,2 +1,4 @@ read_blif gatesi.blif -write_blif -gatesi gatesi.blif.out \ No newline at end of file +write_blif -gatesi gatesi.blif.out +! tail -n +2 gatesi.blif.out > gatesi.blif.out.tmp && mv gatesi.blif.out.tmp gatesi.blif.out +! diff gatesi.blif.out gatesi.blif.ok diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index bd6d74fd9..96aa6be79 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -5,7 +5,4 @@ sys.path.append("..") import gen_tests_makefile -gen_tests_makefile.generate(["--yosys-scripts"], [], -"""[ ! -f $(@:.ys=.blif) ] || \\ - sed '1d' $(@:.ys=.blif).out | diff - <(sed '1d' $(@:.ys=.blif).ok) >/dev/null 2>&1 || exit 1; \\ -""") \ No newline at end of file +gen_tests_makefile.generate(["--yosys-scripts"]) \ No newline at end of file From 4a9dc33098d9b797e8f110a5eeb5cd38691775e5 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:00:40 +0100 Subject: [PATCH 075/176] Convert memlib tests --- tests/Makefile | 2 +- tests/memlib/generate.py | 82 +++++++++++++++---------------------- tests/memlib/generate_mk.py | 28 +++++++++++++ tests/memlib/run-test.sh | 16 -------- 4 files changed, 62 insertions(+), 66 deletions(-) create mode 100644 tests/memlib/generate_mk.py delete mode 100755 tests/memlib/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index aa82ccc61..37d4bdbf2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -60,7 +60,7 @@ MK_TEST_DIRS += ./asicworld MK_TEST_DIRS += ./share MK_TEST_DIRS += ./opt_share MK_TEST_DIRS += ./fsm -#SH_TEST_DIRS += ./memlib +MK_TEST_DIRS += ./memlib #SH_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces MK_TEST_DIRS += ./xprop diff --git a/tests/memlib/generate.py b/tests/memlib/generate.py index 46eff6b43..0b6c27b1a 100644 --- a/tests/memlib/generate.py +++ b/tests/memlib/generate.py @@ -319,8 +319,8 @@ if (OFFSET > 0) begin always @(mem_read, subaddr_r) rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; -end -else +end +else begin always @(posedge clk) case (OFFSET) @@ -970,7 +970,7 @@ for (abits, wbits, words, defs, cells) in [ name, ENABLES.format(abits=abits, wbits=wbits, words=words), ["wren"], defs, cells )) - + # abits/dbits determination (aka general geometry picking) GEOMETRIC = """ module top(clk, rwa, rd, wd, we); @@ -991,7 +991,7 @@ always @(posedge clk) if (we) mem[rwa] <= wd; else - rd <= mem[rwa]; + rd <= mem[rwa]; endmodule """ @@ -1372,7 +1372,7 @@ for (abits, wbits, rwords, cntquad, cntoct) in [ (4, 2, 4, 1, 1), (4, 2, 5, 2, 1), (4, 2, 6, 2, 1), - (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read + (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) (4, 2, 9, 3, 2), (4, 4, 1, 2, 2), @@ -1440,7 +1440,7 @@ for (testname, reset_gate, rdwr, clk_en, add_logic) in [ write = "if (wren) \n\t\tmem[addr] <= wdata;" if rdwr == "new": - read = """if (rden) + read = """if (rden) if (wren) rdata <= wdata; else @@ -1466,7 +1466,7 @@ end""" TESTS.append(Test( testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), - ["block_sp_full"], ["USE_SRST"], + ["block_sp_full"], ["USE_SRST"], {"RAM_BLOCK_SP": 1, "$*": add_logic} )) @@ -1510,10 +1510,10 @@ end""" TESTS.append(Test( testname, PRIORITY.format(code=code, abits=4, wbits=1, words=2), - ["block_sp_full"], defs, + ["block_sp_full"], defs, {"RAM_BLOCK_SP": 1, "$*": add_logic} )) - + ROM_CASE = """ module rom(input clk, input [2:0] addr, {attr}output reg [7:0] data); @@ -1536,44 +1536,28 @@ endmodule TESTS.append(Test("rom_case", ROM_CASE.format(attr=""), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 0})) TESTS.append(Test("rom_case_block", ROM_CASE.format(attr="(* rom_style = \"block\" *) "), ["block_sdp"], [], {"RAM_BLOCK_SDP" : 1})) -with open("run-test.mk", "w") as mf: - mf.write("ifneq ($(strip $(SEED)),)\n") - mf.write("SEEDOPT=-S$(SEED)\n") - mf.write("endif\n") - mf.write("all:") - for t in TESTS: - mf.write(" " + t.name) - mf.write("\n") - mf.write(".PHONY: all\n") - - - for t in TESTS: - with open("t_{}.v".format(t.name), "w") as tf: - tf.write(t.src) - with open("t_{}.ys".format(t.name), "w") as sf: - sf.write("proc\n") - sf.write("opt\n") - sf.write("opt -full\n") - sf.write("memory -nomap\n") - sf.write("dump\n") - sf.write("memory_libmap") - for lib in t.libs: - sf.write(" -lib ../memlib_{}.txt".format(lib)) - for d in t.defs: - sf.write(" -D {}".format(d)) - sf.write("\n") - sf.write("memory_map\n") - for k, v in t.cells.items(): - if isinstance(v, tuple): - (cc, ca) = v - sf.write("select -assert-count {} t:{}\n".format(cc, k)) - for kk, vv in ca.items(): - sf.write("select -assert-count {} t:{} r:{}={} %i\n".format(cc, k, kk, vv)) - else: - sf.write("select -assert-count {} t:{}\n".format(v, k)) - mf.write("{}:\n".format(t.name)) - mf.write("\t@../tools/autotest.sh -G -j $(SEEDOPT) $(EXTRA_FLAGS) -p 'script ../t_{}.ys'".format(t.name)) +for t in TESTS: + with open("t_{}.v".format(t.name), "w") as tf: + tf.write(t.src) + with open("t_{}.ys".format(t.name), "w") as sf: + sf.write("proc\n") + sf.write("opt\n") + sf.write("opt -full\n") + sf.write("memory -nomap\n") + sf.write("dump\n") + sf.write("memory_libmap") for lib in t.libs: - mf.write(" -l memlib_{}.v".format(lib)) - mf.write(" t_{}.v || (cat t_{}.err; exit 1)\n".format(t.name, t.name)) - mf.write(".PHONY: {}\n".format(t.name)) + sf.write(" -lib ../memlib_{}.txt".format(lib)) + for d in t.defs: + sf.write(" -D {}".format(d)) + sf.write("\n") + sf.write("memory_map\n") + for k, v in t.cells.items(): + if isinstance(v, tuple): + (cc, ca) = v + sf.write("select -assert-count {} t:{}\n".format(cc, k)) + for kk, vv in ca.items(): + sf.write("select -assert-count {} t:{} r:{}={} %i\n".format(cc, k, kk, vv)) + else: + sf.write("select -assert-count {} t:{}\n".format(v, k)) + diff --git a/tests/memlib/generate_mk.py b/tests/memlib/generate_mk.py new file mode 100644 index 000000000..3cc20b614 --- /dev/null +++ b/tests/memlib/generate_mk.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile +from generate import TESTS + +def create_tests(): + for t in TESTS: + libs_args = "" + for lib in t.libs: + libs_args += f" -l memlib_{lib}.v" + cmd = ( + f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} " + f"-p 'script ../t_{t.name}.ys'" + f"{libs_args} " + f"t_{t.name}.v >/dev/null 2>&1 || (cat t_{t.name}.err; exit 1)" + ) + gen_tests_makefile.generate_target(t.name, cmd) + +extra = [ + "SEED ?=", + "ifneq ($(strip $(SEED)),)", + " SEEDOPT=-S$(SEED)", + "endif", +] +gen_tests_makefile.generate_custom(create_tests, extra) diff --git a/tests/memlib/run-test.sh b/tests/memlib/run-test.sh deleted file mode 100755 index 9e95fb255..000000000 --- a/tests/memlib/run-test.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -eu - -OPTIND=1 -seed="" # default to no seed specified -while getopts "S:" opt -do - case "$opt" in - S) seed="$OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -python3 generate.py -exec ${MAKE:-make} -f run-test.mk SEED="$seed" From ee31950770892df09d90b7ef89b16fab0a8e7527 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:08:27 +0100 Subject: [PATCH 076/176] Convert memfile tests --- tests/Makefile | 2 +- tests/memfile/generate_mk.py | 69 ++++++++++++++++++++++++++++++++++++ tests/memfile/run-test.sh | 50 -------------------------- 3 files changed, 70 insertions(+), 51 deletions(-) create mode 100644 tests/memfile/generate_mk.py delete mode 100755 tests/memfile/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 37d4bdbf2..19e79718e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -70,7 +70,7 @@ MK_TEST_DIRS += ./proc MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch #SH_TEST_DIRS += ./rpc -#SH_TEST_DIRS += ./memfile +MK_TEST_DIRS += ./memfile #SH_TEST_DIRS += ./fmt #SH_TEST_DIRS += ./cxxrtl #SH_TEST_DIRS += ./liberty diff --git a/tests/memfile/generate_mk.py b/tests/memfile/generate_mk.py new file mode 100644 index 000000000..a40f99ad0 --- /dev/null +++ b/tests/memfile/generate_mk.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def create_tests(): + setup = "mkdir -p temp && cp content1.dat temp/content2.dat" + + gen_tests_makefile.generate_cmd_test("parent_content1", [ + f"{setup};", + '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("parent_content2_temp", [ + f"{setup};", + '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("parent_content2_full", [ + f"{setup};", + '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("same_content1", [ + f"{setup};", + '$(YOSYS) -qp "read_verilog -defer memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory" >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("same_content2", [ + f"{setup};", + '$(YOSYS) -qp "read_verilog -defer memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory" >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("child_content1", [ + f"{setup};", + '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("child_content2_temp", [ + f"{setup};", + '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("child_content2_direct", [ + f"{setup};", + '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + ]) + + gen_tests_makefile.generate_cmd_test("fail_empty_filename", + '! $(YOSYS) -qp "read_verilog memory.v" >/dev/null 2>&1') + + gen_tests_makefile.generate_cmd_test("fail_missing_file", [ + '! $(YOSYS) -qp "read_verilog -defer memory.v;', + 'chparam -set MEMFILE \\"content3.dat\\" memory" >/dev/null 2>&1', + ]) + +extra = ["YOSYS_ABS := $(abspath $(YOSYS))"] +gen_tests_makefile.generate_custom(create_tests, extra) + diff --git a/tests/memfile/run-test.sh b/tests/memfile/run-test.sh deleted file mode 100755 index e2583ef3b..000000000 --- a/tests/memfile/run-test.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -mkdir -p temp -cp content1.dat temp/content2.dat - -cd .. - -echo "Running from the parent directory with content1.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 -echo "Running from the parent directory with temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 -echo "Running from the parent directory with memfile/temp/content2.dat" -../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" >/dev/null 2>&1 - -cd memfile - -echo "Running from the same directory with content1.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 -echo "Running from the same directory with temp/content2.dat" -../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 - -cd temp - -echo "Running from a child directory with content1.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" >/dev/null 2>&1 -echo "Running from a child directory with temp/content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 -echo "Running from a child directory with content2.dat" -../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" >/dev/null 2>&1 - -cd .. - -echo "Checking a failure when zero length filename is provided" -if ../../yosys -qp "read_verilog memory.v" >/dev/null 2>&1; then - echo "The execution should fail but it didn't happen, which is WRONG." - exit 1 -else - echo "Execution failed, which is OK." -fi - -echo "Checking a failure when not existing filename is provided" -if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory" >/dev/null 2>&1; then - echo "The execution should fail but it didn't happen, which is WRONG." - exit 1 -else - echo "Execution failed, which is OK." -fi From 58e0473e29a3717373963d26aef8604def3d0a8c Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:24:54 +0100 Subject: [PATCH 077/176] Convert bram tests --- tests/Makefile | 2 +- tests/bram/{generate.py => generate_mk.py} | 24 ++++++++++- tests/bram/run-test.sh | 48 ---------------------- 3 files changed, 24 insertions(+), 50 deletions(-) rename tests/bram/{generate.py => generate_mk.py} (95%) delete mode 100755 tests/bram/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 19e79718e..48ea1774f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -61,7 +61,7 @@ MK_TEST_DIRS += ./share MK_TEST_DIRS += ./opt_share MK_TEST_DIRS += ./fsm MK_TEST_DIRS += ./memlib -#SH_TEST_DIRS += ./bram +MK_TEST_DIRS += ./bram #SH_TEST_DIRS += ./svinterfaces MK_TEST_DIRS += ./xprop MK_TEST_DIRS += ./select diff --git a/tests/bram/generate.py b/tests/bram/generate_mk.py similarity index 95% rename from tests/bram/generate.py rename to tests/bram/generate_mk.py index 79dd500a3..a18972703 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate_mk.py @@ -4,6 +4,10 @@ import argparse import os import sys import random +import glob + +sys.path.append("..") +import gen_tests_makefile debug_mode = False @@ -287,9 +291,11 @@ if args.seed is not None: else: seed = (int(os.times()[4]*100) + os.getpid()) % 900000 + 100000 -print("PRNG seed: %d" % seed) +print("bram PRNG seed: %d" % seed) random.seed(seed) +os.makedirs("temp", exist_ok=True) + for k1 in range(args.count): dsc_f = open("temp/brams_%02d.txt" % k1, "w") sim_f = open("temp/brams_%02d.v" % k1, "w") @@ -303,3 +309,19 @@ for k1 in range(args.count): for k2 in range(lenk2): create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, random.randrange(2 if k2+1 < lenk2 else 1)) +configs = sorted(set( + os.path.basename(f).replace("brams_", "").replace(".txt", "") + for f in glob.glob("temp/brams_*.txt") +)) + +def create_tests(): + for i in configs: + for j in configs: + if i != j: + gen_tests_makefile.generate_cmd_test( + f"bram_{i}_{j}", + f"bash run-single.sh {i} {j} >/dev/null 2>&1" + ) + +gen_tests_makefile.generate_custom(create_tests) + diff --git a/tests/bram/run-test.sh b/tests/bram/run-test.sh deleted file mode 100755 index 47f24f5dd..000000000 --- a/tests/bram/run-test.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -# run this test many times: -# MAKE="make -j8" time bash -c 'for ((i=0; i<100; i++)); do echo "-- $i --"; bash run-test.sh || exit 1; done' - -set -e - -OPTIND=1 -count=5 -seed="" # default to no seed specified -debug="" -while getopts "c:dS:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - d) debug="-d" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp - -echo "generating tests.." -python3 generate.py $debug -c $count $seed - -{ - echo -n "all:" - for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do - for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo -n " temp/job_${i}_${j}.ok" - done; done - echo - for i in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' ); do - for j in $( ls temp/brams_*.txt | sed 's,.*_,,; s,\..*,,;' | grep -v $i ); do - echo "temp/job_${i}_${j}.ok:" - echo " @bash run-single.sh ${i} ${j}" - echo " @echo 'Passed memory_bram test ${i}_${j}.'" - echo " @touch \$@" - done; done -} > temp/makefile - -echo "running tests.." -${MAKE:-make} -f temp/makefile - -exit 0 From 3ceeb3b00ce6a27a631e31661c2ffd21b7f35138 Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 20 Mar 2026 16:31:47 +0100 Subject: [PATCH 078/176] Consolidated memlib generate script --- tests/memlib/generate.py | 1563 ---------------------------------- tests/memlib/generate_mk.py | 1567 ++++++++++++++++++++++++++++++++++- 2 files changed, 1565 insertions(+), 1565 deletions(-) delete mode 100644 tests/memlib/generate.py diff --git a/tests/memlib/generate.py b/tests/memlib/generate.py deleted file mode 100644 index 0b6c27b1a..000000000 --- a/tests/memlib/generate.py +++ /dev/null @@ -1,1563 +0,0 @@ -# TODO: - -# - priority logic -# - swizzles for weird width progressions - - -class Test: - def __init__(self, name, src, libs, defs, cells): - self.name = name - self.src = src - self.libs = libs - self.defs = defs - self.cells = cells - -TESTS = [] - -### basic sanity tests -# Asynchronous-read RAM - -ASYNC = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output wire [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -assign rd = mem[ra]; - -endmodule -""" - -ASYNC_SMALL = ASYNC.format(abits=6, dbits=6) -ASYNC_BIG = ASYNC.format(abits=11, dbits=10) - -TESTS += [ - Test("async_big", ASYNC_BIG, ["lut", "block_tdp"], [], {"RAM_LUT": 384}), - Test("async_big_block", ASYNC_BIG, ["block_tdp"], [], {"RAM_BLOCK_TDP": 0}), - Test("async_small", ASYNC_SMALL, ["lut", "block_tdp"], [], {"RAM_LUT": 8}), - Test("async_small_block", ASYNC_SMALL, ["block_tdp"], [], {"RAM_BLOCK_TDP": 0}), -] - -# Synchronous SDP read first -SYNC = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -{attr} -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" - -SYNC_SMALL = SYNC.format(abits=6, dbits=6, attr="") -SYNC_SMALL_BLOCK = SYNC.format(abits=6, dbits=6, attr='(* ram_style="block" *)') -SYNC_BIG = SYNC.format(abits=11, dbits=10, attr="") -SYNC_MID = SYNC.format(abits=6, dbits=16, attr="") - -TESTS += [ - Test("sync_big", SYNC_BIG, ["lut", "block_tdp"], [], {"RAM_BLOCK_TDP": 20}), - Test("sync_big_sdp", SYNC_BIG, ["lut", "block_sdp"], [], {"RAM_BLOCK_SDP": 20}), - Test("sync_big_lut", SYNC_BIG, ["lut"], [], {"RAM_LUT": 384}), - Test("sync_small", SYNC_SMALL, ["lut", "block_tdp"], [], {"RAM_LUT": 8}), - Test("sync_small_block", SYNC_SMALL, ["block_tdp"], [], {"RAM_BLOCK_TDP": 1}), - Test("sync_small_block_attr", SYNC_SMALL_BLOCK, ["lut", "block_tdp"], [], {"RAM_BLOCK_TDP": 1}), -] - -### initialization values testing -LUT_INIT = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output wire [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -integer i; -initial - for (i = 0; i < 2**ABITS-1; i = i + 1) - mem[i] = {ival}; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -assign rd = mem[ra]; - -endmodule -""" - -INIT_LUT_ZEROS = LUT_INIT.format(abits=4, dbits=4, ival=0); -INIT_LUT_VAL = LUT_INIT.format(abits=4, dbits=4, ival=5); -INIT_LUT_VAL2 = LUT_INIT.format(abits=6, dbits=6, ival="6'h12"); -INIT_LUT_X = LUT_INIT.format(abits=4, dbits=4, ival="4'hx") - -TESTS += [ - Test("init_lut_zeros_zero", INIT_LUT_ZEROS, ["lut"], ["INIT_ZERO"], {"RAM_LUT":1}), - Test("init_lut_zeros_any", INIT_LUT_ZEROS, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), - Test("init_lut_val_zero", INIT_LUT_VAL, ["lut"], ["INIT_ZERO"], {"RAM_LUT":0}), #CHECK: no emulation? - Test("init_lut_val_any", INIT_LUT_VAL, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), - Test("init_lut_val_no_undef", INIT_LUT_VAL, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":1}), - Test("init_lut_val2_any", INIT_LUT_VAL2, ["lut"], ["INIT_ANY"], {"RAM_LUT":8}), - Test("init_lut_val2_no_undef", INIT_LUT_VAL2, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":8}), - Test("init_lut_x_none", INIT_LUT_X, ["lut"], ["INIT_NONE"], {"RAM_LUT":1}), - Test("init_lut_x_zero", INIT_LUT_X, ["lut"], ["INIT_ZERO"], {"RAM_LUT":1}), - Test("init_lut_x_any", INIT_LUT_X, ["lut"], ["INIT_ANY"], {"RAM_LUT":1}), - Test("init_lut_x_no_undef", INIT_LUT_X, ["lut"], ["INIT_NO_UNDEF"], {"RAM_LUT":1}), -] - -### width testing 9-bit-per-byte -RAM_9b1B = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" - -RAM_18b2B = RAM_9b1B.format(abits=3, dbits=18); -RAM_9b1B = RAM_9b1B.format(abits=4, dbits=9); -RAM_4b1B = RAM_9b1B.format(abits=5, dbits=4); -RAM_2b1B = RAM_9b1B.format(abits=6, dbits=2); -RAM_1b1B = RAM_9b1B.format(abits=7, dbits=1); - -TESTS += [ - Test("ram_18b2B", RAM_18b2B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_9b1B", RAM_9b1B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_4b1B", RAM_4b1B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_2b1B", RAM_2b1B, ["9b1B"], [], {"RAM_9b1B":1}), - Test("ram_1b1B", RAM_1b1B, ["9b1B"], [], {"RAM_9b1B":1}), -] - -### initializing 9-bits-per-byte -RAM_9b1B_init = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -integer i; -initial - for (i = 0; i < 2**ABITS-1; i = i + 1) - mem[i] = {ival}; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" - -INIT_9b1B_ZEROS = RAM_9b1B_init.format(abits=4, dbits=9, ival=0); -INIT_9b1B_VAL = RAM_9b1B_init.format(abits=4, dbits=9, ival=275); -INIT_13b2B_VAL = RAM_9b1B_init.format(abits=3, dbits=13, ival="13'h01f3") -INIT_18b2B_VAL = RAM_9b1B_init.format(abits=4, dbits=18, ival="18'h1f39a"); -INIT_4b1B_X = RAM_9b1B_init.format(abits=5, dbits=4, ival="4'hx") - -TESTS += [ - Test("init_9b1B_zeros_zero", INIT_9b1B_ZEROS, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":1}), - Test("init_9b1B_zeros_any", INIT_9b1B_ZEROS, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_9b1B_val_zero", INIT_9b1B_VAL, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":0}), #CHECK: no emulation? - Test("init_9b1B_val_any", INIT_9b1B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_9b1B_val_no_undef", INIT_9b1B_VAL, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":1}), - Test("init_13b2B_val_any", INIT_13b2B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_18b2B_val_any", INIT_18b2B_VAL, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":2}), - Test("init_18b2B_val_no_undef", INIT_18b2B_VAL, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":2}), - Test("init_4b1B_x_none", INIT_4b1B_X, ["9b1B"], ["INIT_NONE"], {"RAM_9b1B":1}), - Test("init_4b1B_x_zero", INIT_4b1B_X, ["9b1B"], ["INIT_ZERO"], {"RAM_9b1B":1}), - Test("init_4b1B_x_any", INIT_4b1B_X, ["9b1B"], ["INIT_ANY"], {"RAM_9b1B":1}), - Test("init_4b1B_x_no_undef", INIT_4b1B_X, ["9b1B"], ["INIT_NO_UNDEF"], {"RAM_9b1B":1}), -] - -### Clock polarity combinations -# I'm not entirely convinced auto-test is correctly testing clock edging -# but they do at least all gen/synth -SYNCCLOCK = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = 8; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -always @(posedge clk) - rd <= mem[ra]; - -endmodule -""" -for (abits, cnt, wclk, rclk, shared) in [ - (4, 1, "ANY","ANY", False), - (4, 1, "ANY","NEG", False), - (4, 1, "ANY","POS", False), - (4, 1, "NEG","ANY", False), - (4, 1, "NEG","POS", False), - (4, 1, "NEG","NEG", False), - (4, 1, "POS","ANY", False), - (4, 1, "POS","NEG", False), - (4, 1, "POS","POS", False), - (4, 1, "ANY","ANY", True), - (4, 0, "NEG","POS", True), # FF mapping - (4, 1, "NEG","NEG", True), - (4, 0, "POS","NEG", True), # FF mapping - (4, 1, "POS","POS", True), - # cannot combine "ANY" with "POS|NEG" when using shared clock -]: - name = f"clock_a{abits}_w{wclk}r{rclk}s{shared}" - defs = ["WCLK_" + wclk, "RCLK_" + rclk] - if (shared): - defs.append("SHARED_CLK") - TESTS.append(Test( - name, SYNCCLOCK.format(abits=abits), - ["clock_sdp"], defs, {"RAM_CLOCK_SDP": cnt} - )) - -### mixed width testing -# Wide write port -MIXED_WRITE = """ -module top(clk, ra, wa, rd, wd, we); - -localparam WABITS = {wabits}; -localparam WDBITS = {wdbits}; - -localparam RABITS = {rabits}; -localparam RDBITS = {rdbits}; - -input wire clk; -input wire we; -input wire [WABITS-1:0] wa; -input wire [WDBITS-1:0] wd; -input wire [RABITS-1:0] ra; -output reg [RDBITS-1:0] rd; - -localparam DEPTH = (2**WABITS); - -localparam OFFSET = RABITS-WABITS; - -(* syn_ramstyle = "block_ram" *) -reg [WDBITS-1:0] mem [0:DEPTH-1]; - -always @(posedge clk) - if (we) - mem[wa] <= wd; - -if (OFFSET > 0) begin - reg [WDBITS-1:0] mem_read; - reg [OFFSET-1:0] subaddr_r; - always @(posedge clk) begin - mem_read <= mem[ra[RABITS-1:OFFSET]]; - subaddr_r <= ra[OFFSET-1:0]; - end - - always @(mem_read, subaddr_r) - rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; -end -else -begin - always @(posedge clk) - case (OFFSET) - 0: rd <= mem[ra]; - -1: rd <= {{ mem[ra], mem[ra+1] }}; - endcase -end -endmodule -""" - -UNMIXED = MIXED_WRITE.format(wabits=4, wdbits=9, rabits=4, rdbits=9) -MIXED_9_18 = MIXED_WRITE.format(wabits=5, wdbits=9, rabits=4, rdbits=18) -MIXED_18_9 = MIXED_WRITE.format(wabits=3, wdbits=18, rabits=4, rdbits=9) -MIXED_36_9 = MIXED_WRITE.format(wabits=3, wdbits=36, rabits=5, rdbits=9) -MIXED_4_2 = MIXED_WRITE.format(wabits=5, wdbits=4, rabits=6, rdbits=2); - -TESTS += [ - Test("unmixed", UNMIXED, ["9b1B"], [], {"RAM_9b1B":1}), - Test("mixed_9_18", MIXED_9_18, ["9b1B"], [], {"RAM_9b1B":4}), #CHECK: only using half the memory - Test("mixed_18_9", MIXED_18_9, ["9b1B"], [], {"RAM_9b1B":1}), - Test("mixed_36_9", MIXED_36_9, ["9b1B"], [], {"RAM_9b1B":2}), - Test("mixed_4_2", MIXED_4_2, ["9b1B"], [], {"RAM_9b1B":1}), -] - -### basic TDP test - -TDP = """ -module top(clka, clkb, addra, addrb, rda, rdb, wda, wdb, wea, web); - -localparam ABITS = 6; -localparam DBITS = 6; - -input wire clka, clkb; -input wire wea, web; -input wire [ABITS-1:0] addra, addrb; -input wire [DBITS-1:0] wda, wdb; -output reg [DBITS-1:0] rda, rdb; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clka) - if (wea) - mem[addra] <= wda; - else - rda <= mem[addra]; - -always @(posedge clkb) - if (web) - mem[addrb] <= wdb; - else - rdb <= mem[addrb]; - -endmodule -""" - -TESTS += [ - Test("tdp", TDP, ["block_tdp", "block_sdp"], [], {"RAM_BLOCK_TDP": 1}), -] - -# shared clock -# Synchronous SDP with clock domain crossing -SYNC_2CLK = """ -module top(rclk, wclk, ra, wa, rd, wd, we); - -localparam ABITS = 6; -localparam DBITS = 16; - -input wire rclk, wclk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge wclk) - if (we) - mem[wa] <= wd; - -always @(posedge rclk) - rd <= mem[ra]; - -endmodule -""" - -TESTS += [ - Test("sync_2clk", SYNC_2CLK, ["block_sdp"], [], {"RAM_BLOCK_SDP": 1}), - Test("sync_shared", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_2clk_shared", SYNC_2CLK, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 0}), -] - -# inter-port transparency -# Synchronous SDP with write-first behaviour -SYNC_TRANS = """ -module top(clk, ra, wa, rd, wd, we); - -localparam ABITS = 6; -localparam DBITS = 16; - -input wire clk; -input wire we; -input wire [ABITS-1:0] ra, wa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(negedge clk) - if (we) - mem[wa] <= wd; - -always @(negedge clk) begin - rd <= mem[ra]; - if (we && ra == wa) - rd <= wd; -end - -endmodule -""" - -TESTS += [ - Test("sync_trans_old_old", SYNC_MID, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 0})}), - Test("sync_trans_old_new", SYNC_MID, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_trans_old_none", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_trans_new_old", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": 1}), - Test("sync_trans_new_new", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 1})}), - Test("sync_trans_new_none", SYNC_TRANS, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), -] - -# rdwr checks -# Synchronous single-port RAM with mutually exclusive read/write -SP_NO_CHANGE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) - mem[addr] <= wd; - else - rd <= mem[addr]; -end - -endmodule -""" - -SP_NO_CHANGE_BE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire [1:0] we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) begin - if (we[0]) - mem[addr][7:0] <= wd[7:0]; - if (we[1]) - mem[addr][15:8] <= wd[15:8]; - end else - rd <= mem[addr]; -end - -endmodule -""" - -# Synchronous single-port RAM with write-first behaviour -SP_NEW = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) begin - mem[addr] <= wd; - rd <= wd; - end else - rd <= mem[addr]; -end - -endmodule -""" - -SP_NEW_BE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire [1:0] we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - rd <= mem[addr]; - if (we[0]) begin - mem[addr][7:0] <= wd[7:0]; - rd[7:0] <= wd[7:0]; - end - if (we[1]) begin - mem[addr][15:8] <= wd[15:8]; - rd[15:8] <= wd[15:8]; - end -end - -endmodule -""" - -# Synchronous single-port RAM with read-first behaviour -SP_OLD = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we) - mem[addr] <= wd; - rd <= mem[addr]; -end - -endmodule -""" - -SP_OLD_BE = """ -module top(clk, addr, rd, wd, we); - -input wire clk; -input wire [1:0] we; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -always @(negedge clk) begin - if (we[0]) - mem[addr][7:0] <= wd[7:0]; - if (we[1]) - mem[addr][15:8] <= wd[15:8]; - rd <= mem[addr]; -end - -endmodule -""" - -TESTS += [ - Test("sp_nc_none", SP_NO_CHANGE, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), - Test("sp_new_none", SP_NEW, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), - Test("sp_old_none", SP_OLD, ["block_sp"], [], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_nc", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_nc", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_nc", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_new", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new", SP_NEW, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_new", SP_OLD, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_old", SP_NO_CHANGE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_old", SP_NEW, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_old", SP_OLD, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_nc_new_only", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new_only", SP_NEW, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_new_only", SP_OLD, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_new_only_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new_only_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 2}), - Test("sp_old_new_only_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_new_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_new_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_new_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_old_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_old_be", SP_NEW_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_old_old_be", SP_OLD_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_nc_nc_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_nc_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 2}), - Test("sp_old_nc_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), - Test("sp_nc_auto", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_auto", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), - Test("sp_old_auto", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), - Test("sp_nc_auto_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), - Test("sp_new_auto_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), - Test("sp_old_auto_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), -] - -# Synchronous read port with initial value -SP_INIT = """ -module top(clk, addr, rd, wd, we, re); - -input wire clk; -input wire we, re; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; - if (re) - rd <= mem[addr]; -end - -endmodule -""" - -SP_INIT_X = SP_INIT.format(ival="16'hxxxx") -SP_INIT_0 = SP_INIT.format(ival="16'h0000") -SP_INIT_V = SP_INIT.format(ival="16'h55aa") - -TESTS += [ - Test("sp_init_x_x", SP_INIT_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_x_x_re", SP_INIT_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_x_x_ce", SP_INIT_X, ["block_sp"], ["CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_x", SP_INIT_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_x_re", SP_INIT_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_0", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_0_re", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_any", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_0_any_re", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_x", SP_INIT_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_x_re", SP_INIT_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_0", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_0_re", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_any", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_init_v_any_re", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), -] - -# Synchronous read port with asynchronous reset -SP_ARST = """ -module top(clk, addr, rd, wd, we, re, ar); - -input wire clk; -input wire we, re, ar; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; -end -always @(posedge clk, posedge ar) begin - if (ar) - rd <= {aval}; - else if (re) - rd <= mem[addr]; -end - -endmodule -""" - -SP_ARST_X = SP_ARST.format(ival="16'hxxxx", aval="16'hxxxx") -SP_ARST_0 = SP_ARST.format(ival="16'hxxxx", aval="16'h0000") -SP_ARST_V = SP_ARST.format(ival="16'hxxxx", aval="16'h55aa") -SP_ARST_E = SP_ARST.format(ival="16'h55aa", aval="16'h55aa") -SP_ARST_N = SP_ARST.format(ival="16'h1234", aval="16'h55aa") - -TESTS += [ - Test("sp_arst_x_x", SP_ARST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_x_x_re", SP_ARST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_x", SP_ARST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_x_re", SP_ARST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_0", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_0_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_any", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_any_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_init", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_0_init_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_x", SP_ARST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_x_re", SP_ARST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_0", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_0_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_any", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_any_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_init", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_v_init_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_x", SP_ARST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_x_re", SP_ARST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_0", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_0_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_any", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_any_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_init", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_e_init_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_x", SP_ARST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_x_re", SP_ARST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_0", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_0_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_any", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_any_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_init", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_arst_n_init_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), -] - -# Synchronous read port with synchronous reset (reset priority over enable) -SP_SRST = """ -module top(clk, addr, rd, wd, we, re, sr); - -input wire clk; -input wire we, re, sr; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; -end -always @(posedge clk) begin - if (sr) - rd <= {sval}; - else if (re) - rd <= mem[addr]; -end - -endmodule -""" - -# Synchronous read port with synchronous reet (enable priority over reset) -SP_SRST_G = """ -module top(clk, addr, rd, wd, we, re, sr); - -input wire clk; -input wire we, re, sr; -input wire [3:0] addr; -input wire [15:0] wd; -output reg [15:0] rd; - -reg [15:0] mem [0:15]; - -initial rd = {ival}; - -always @(posedge clk) begin - if (we) - mem[addr] <= wd; -end -always @(posedge clk) begin - if (re) begin - if (sr) - rd <= {sval}; - else - rd <= mem[addr]; - end -end - -endmodule -""" - -SP_SRST_X = SP_SRST.format(ival="16'hxxxx", sval="16'hxxxx") -SP_SRST_0 = SP_SRST.format(ival="16'hxxxx", sval="16'h0000") -SP_SRST_V = SP_SRST.format(ival="16'hxxxx", sval="16'h55aa") -SP_SRST_E = SP_SRST.format(ival="16'h55aa", sval="16'h55aa") -SP_SRST_N = SP_SRST.format(ival="16'h1234", sval="16'h55aa") -SP_SRST_GV = SP_SRST_G.format(ival="16'hxxxx", sval="16'h55aa") - -TESTS += [ - Test("sp_srst_x_x", SP_SRST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_x_x_re", SP_SRST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_x", SP_SRST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_x_re", SP_SRST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_0", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_0_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_any", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_any_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_init", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_0_init_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_x", SP_SRST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_x_re", SP_SRST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_0", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_0_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_re_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_ce", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_any_ce_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_init", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_v_init_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_x", SP_SRST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_x_re", SP_SRST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_0", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_0_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_any", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_any_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_init", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_e_init_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_x", SP_SRST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_x_re", SP_SRST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_0", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_0_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_any", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_any_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_init", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_n_init_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_x", SP_SRST_GV, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_x_re", SP_SRST_GV, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_0", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_0_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_re_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_ce", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_any_ce_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_init", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), - Test("sp_srst_gv_init_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), -] - -# Byte enables, wrbe_separate -SYNC_ENABLE = """ -module top(clk, rwa, rd, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] rwa; -input wire [DBITS-1:0] wd; -output reg [DBITS-1:0] rd; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) begin - if (we) - mem[rwa] <= wd; - else - rd <= mem[rwa]; -end - -endmodule -""" - -for (abits, dbits, sep, defs, cells) in [ - (4, 4, False, ["NO_BYTE"], {"RAM_WREN": 1}), - (5, 4, False, ["NO_BYTE"], {"RAM_WREN": 2}), - (6, 4, False, ["NO_BYTE"], {"RAM_WREN": 4}), - # (4, 4, True, ["NO_BYTE"], {"RAM_WREN": 1}), # should throw an error - (3, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), # needs two write ports - (4, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), - (4, 4, False, ["W4_B4"], {"RAM_WREN": 1}), - (4, 8, True, ["W4_B4"], {"RAM_WREN": 2}), - (4, 8, False, ["W8_B4"], {"RAM_WREN": 1}), - (4, 8, True, ["W8_B4"], {"RAM_WREN": 1}), - (4, 8, False, ["W8_B8"], {"RAM_WREN": 1}), - (4, 8, True, ["W8_B8"], {"RAM_WREN": 1}), - -]: - name = f"wren_a{abits}d{dbits}_{defs[0]}" - if (sep): - defs.append("WRBE_SEPARATE") - name += "_separate" - - TESTS.append(Test( - name, SYNC_ENABLE.format(abits=abits, dbits=dbits), - ["wren"], defs, cells - )) - -# Write port with byte enables -ENABLES = """ -module top(clk, we, be, rwa, wd, rd); - -localparam ABITS = {abits}; -localparam WBITS = {wbits}; -localparam WORDS = {words}; - -input wire clk; -input wire we; -input wire [WORDS-1:0] be; -input wire [ABITS-1:0] rwa; -input wire [(WBITS*WORDS)-1:0] wd; -output reg [(WBITS*WORDS)-1:0] rd; - -reg [(WBITS*WORDS)-1:0] mem [0:2**ABITS-1]; - -integer i; -always @(posedge clk) - for (i=0; i> {bw}]) - for (j = 0; j < 2**{bw}; j = j + 1) - mem[wa << {ww} | i | j] <= wd[i | j]; - -always @(posedge rclk) - if (rr) - rd <= {sval}; - else if (re) - for (i = 0; i < 2**{rw}; i = i + 1) - rd[i] <= mem[ra << {rw} | i]; - -endmodule -""" - -for (aw, rw, ww, bw, xw, sval, cnt) in [ - (6, 1, 1, 1, 1, "2'h1", 1), - (7, 1, 1, 1, 1, "2'h2", 2), - (8, 1, 1, 1, 1, "2'h3", 4), - (6, 0, 0, 0, 0, "2'h0", 1), - (6, 1, 0, 0, 0, "2'h0", 1), - (6, 2, 0, 0, 0, "2'h0", 1), - (6, 3, 0, 0, 0, "2'h0", 1), - (6, 4, 0, 0, 0, "2'h0", 1), - (6, 5, 0, 0, 0, "2'h0", 2), - (6, 0, 1, 0, 0, "2'h0", 2), - (6, 0, 1, 1, 0, "2'h0", 1), - (6, 0, 2, 0, 0, "2'h0", 4), - (6, 0, 2, 2, 0, "2'h0", 1), - (6, 0, 3, 2, 0, "2'h0", 1), - (6, 0, 4, 2, 0, "2'h0", 1), - (6, 0, 5, 2, 0, "2'h0", 2), - (7, 0, 0, 0, 0, "2'h0", 2), - (7, 1, 0, 0, 0, "2'h0", 2), - (7, 2, 0, 0, 0, "2'h0", 2), - (7, 3, 0, 0, 0, "2'h0", 2), - (7, 4, 0, 0, 0, "2'h0", 2), - (7, 5, 0, 0, 0, "2'h0", 2), - (7, 0, 1, 0, 0, "2'h0", 2), - (7, 0, 1, 1, 0, "2'h0", 2), - (7, 0, 2, 0, 0, "2'h0", 4), - (7, 0, 2, 2, 0, "2'h0", 2), - (7, 0, 3, 2, 0, "2'h0", 2), - (7, 0, 4, 2, 0, "2'h0", 2), - (7, 0, 5, 2, 0, "2'h0", 2), -]: - TESTS.append(Test( - f"wide_sdp_a{aw}r{rw}w{ww}b{bw}x{xw}", - WIDE_SDP.format(aw=aw, rw=rw, ww=ww, bw=bw, xw=xw, sval=sval), - ["wide_sdp"], [], - {"RAM_WIDE_SDP": cnt} - )) - -WIDE_SP = """ -module top(clk, a, rd, re, rr, wd, we); - -input wire clk, re, rr; -input wire [2**({ww}-{bw})-1:0] we; -input wire [{aw}-1:0] a; -input wire [2**{ww}-1:0] wd; -output reg [2**{rw}-1:0] rd; - -reg mem [0:2**{aw}-1]; - -initial mem[3] = 0; -initial mem[17] = 1; -initial mem[23] = 0; -initial mem[24] = 1; - -integer i, j; -always @(posedge clk) begin - for (i = 0; i < 2**{ww}; i = i + 2**{bw}) - if (we[i >> {bw}]) - for (j = 0; j < 2**{bw}; j = j + 1) - mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; - if (rr) - rd <= {sval}; - else if (re) - for (i = 0; i < 2**{rw}; i = i + 1) - rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; -end - -endmodule -""" - -for (aw, rw, ww, bw, sval, cnt) in [ - (6, 1, 1, 1, "2'h1", 1), - (7, 1, 1, 1, "2'h2", 2), - (8, 1, 1, 1, "2'h3", 4), - (6, 0, 0, 0, "2'h0", 1), - (6, 1, 0, 0, "2'h0", 1), - (6, 2, 0, 0, "2'h0", 1), - (6, 3, 0, 0, "2'h0", 1), - (6, 4, 0, 0, "2'h0", 1), - (6, 5, 0, 0, "2'h0", 2), - (6, 0, 1, 0, "2'h0", 2), - (6, 0, 1, 1, "2'h0", 1), - (6, 0, 2, 0, "2'h0", 4), - (6, 0, 2, 2, "2'h0", 1), - (6, 0, 3, 2, "2'h0", 1), - (6, 0, 4, 2, "2'h0", 1), - (6, 0, 5, 2, "2'h0", 2), - (7, 0, 0, 0, "2'h0", 2), - (7, 1, 0, 0, "2'h0", 2), - (7, 2, 0, 0, "2'h0", 2), - (7, 3, 0, 0, "2'h0", 2), - (7, 4, 0, 0, "2'h0", 2), - (7, 5, 0, 0, "2'h0", 2), - (7, 0, 1, 0, "2'h0", 2), - (7, 0, 1, 1, "2'h0", 2), - (7, 0, 2, 0, "2'h0", 4), - (7, 0, 2, 2, "2'h0", 2), - (7, 0, 3, 2, "2'h0", 2), - (7, 0, 4, 2, "2'h0", 2), - (7, 0, 5, 2, "2'h0", 2), -]: - TESTS.append(Test( - f"wide_sp_mix_a{aw}r{rw}w{ww}b{bw}", - WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), - ["wide_sp"], ["WIDTH_MIX"], - {"RAM_WIDE_SP": cnt} - )) - -for (aw, rw, ww, bw, sval, cnt) in [ - (6, 1, 1, 1, "2'h1", 1), - (7, 1, 1, 1, "2'h2", 2), - (8, 1, 1, 1, "2'h3", 4), - (6, 0, 0, 0, "2'h0", 1), - (6, 1, 0, 0, "2'h0", 2), - (6, 2, 0, 0, "2'h0", 4), - (6, 3, 0, 0, "2'h0", 4), - (6, 4, 0, 0, "2'h0", 4), - (6, 5, 0, 0, "2'h0", 8), - (6, 0, 1, 0, "2'h0", 2), - (6, 0, 1, 1, "2'h0", 1), - (6, 0, 2, 0, "2'h0", 4), - (6, 0, 2, 2, "2'h0", 1), - (6, 0, 3, 2, "2'h0", 1), - (6, 0, 4, 2, "2'h0", 1), - (6, 0, 5, 2, "2'h0", 2), - (7, 0, 0, 0, "2'h0", 2), - (7, 1, 0, 0, "2'h0", 2), - (7, 2, 0, 0, "2'h0", 4), - (7, 3, 0, 0, "2'h0", 8), - (7, 4, 0, 0, "2'h0", 8), - (7, 5, 0, 0, "2'h0", 8), - (7, 0, 1, 0, "2'h0", 2), - (7, 0, 1, 1, "2'h0", 2), - (7, 0, 2, 0, "2'h0", 4), - (7, 0, 2, 2, "2'h0", 2), - (7, 0, 3, 2, "2'h0", 2), - (7, 0, 4, 2, "2'h0", 2), - (7, 0, 5, 2, "2'h0", 2), -]: - TESTS.append(Test( - f"wide_sp_tied_a{aw}r{rw}w{ww}b{bw}", - WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), - ["wide_sp"], [], - {"RAM_WIDE_SP": cnt} - )) - -WIDE_RW = """ -module top(clk, a, rd, re, wd, we); - -input wire clk, re; -input wire [2**({ww}-{bw})-1:0] we; -input wire [{aw}-1:0] a; -input wire [2**{ww}-1:0] wd; -output reg [2**{rw}-1:0] rd; - -(* ram_block *) -reg mem [0:2**{aw}-1]; - -initial mem[3] = 0; -initial mem[17] = 1; -initial mem[23] = 0; -initial mem[24] = 1; - -integer i, j; -always @(posedge clk) begin - for (i = 0; i < 2**{ww}; i = i + 2**{bw}) - if (we[i >> {bw}]) - for (j = 0; j < 2**{bw}; j = j + 1) - mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; - if (re) - for (i = 0; i < 2**{rw}; i = i + 1) - rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; -end - -endmodule -""" - -for (aw, rw, ww, bw, cntww, cntwr) in [ - (6, 1, 1, 1, 2, 1), - (7, 1, 1, 1, 4, 2), - (8, 1, 1, 1, 8, 4), - (6, 0, 0, 0, 4, 2), - (6, 1, 0, 0, 4, 2), - (6, 2, 0, 0, 4, 2), - (6, 3, 0, 0, 8, 2), - (6, 4, 0, 0, 16, 4), - (6, 5, 0, 0, 32, 8), - (6, 0, 1, 0, 4, 2), - (6, 0, 1, 1, 2, 1), - (6, 0, 2, 0, 4, 4), - (6, 0, 2, 2, 1, 2), - (6, 0, 3, 2, 1, 4), - (6, 0, 4, 2, 2, 8), - (6, 0, 5, 2, 4, 16), - (7, 0, 0, 0, 8, 4), - (7, 1, 0, 0, 8, 4), - (7, 2, 0, 0, 8, 4), - (7, 3, 0, 0, 8, 4), - (7, 4, 0, 0, 16, 4), - (7, 5, 0, 0, 32, 8), - (7, 0, 1, 0, 8, 4), - (7, 0, 1, 1, 4, 2), - (7, 0, 2, 0, 8, 4), - (7, 0, 2, 2, 2, 2), - (7, 0, 3, 2, 2, 4), - (7, 0, 4, 2, 2, 8), - (7, 0, 5, 2, 4, 16), -]: - TESTS.append(Test( - f"wide_read_a{aw}r{rw}w{ww}b{bw}", - WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), - ["wide_read"], [], - {"RAM_WIDE_READ": cntwr} - )) - TESTS.append(Test( - f"wide_write_a{aw}r{rw}w{ww}b{bw}", - WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), - ["wide_write"], [], - {"RAM_WIDE_WRITE": cntww} - )) - -# Multiple read ports -# 1rw port plus 3 (or 7) r ports -QUAD_PORT = """ -module top(clk, rwa, r0a, r1a, r2a, rd, r0d, r1d, r2d, wd, we); - -localparam ABITS = {abits}; -localparam DBITS = {dbits}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] rwa; -input wire [ABITS-1:0] r0a; -input wire [ABITS-1:0] r1a; -input wire [ABITS-1:0] r2a; -input wire [DBITS-1:0] wd; -output wire [DBITS-1:0] rd; -output wire [DBITS-1:0] r0d; -output wire [DBITS-1:0] r1d; -output wire [DBITS-1:0] r2d; - -reg [DBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[rwa] <= wd; - -assign rd = mem[rwa]; -assign r0d = mem[r0a]; -assign r1d = mem[r1a]; -assign r2d = mem[r2a]; - -endmodule -""" - -for (abits, dbits, cnt) in [ - (2, 2, 1), - (4, 2, 1), - (5, 2, 2), - (4, 4, 2), - (6, 2, 4), - (4, 8, 4), -]: - TESTS.append(Test( - f"quad_port_a{abits}d{dbits}", - QUAD_PORT.format(abits=abits, dbits=dbits), - ["multilut"], ["PORTS_QUAD"], - {"LUT_MULTI": cnt} - )) - -# Wide asynchronous read port -WIDE_READ = """ -module top(clk, we, rwa, wd, rd); - -localparam ABITS = {abits}; -localparam WBITS = {wbits}; -localparam RWORDS = {rwords}; - -input wire clk; -input wire we; -input wire [ABITS-1:0] rwa; -input wire [WBITS-1:0] wd; -output wire [(WBITS*RWORDS)-1:0] rd; - -reg [WBITS-1:0] mem [0:2**ABITS-1]; - -always @(posedge clk) - if (we) - mem[rwa] <= wd; - -genvar i; -generate - for (i = 0; i < RWORDS; i = i + 1) - assign rd[i*WBITS+:WBITS] = mem[rwa + i]; -endgenerate - -endmodule -""" - -for (abits, wbits, rwords, cntquad, cntoct) in [ - (4, 2, 1, 1, 1), - (4, 2, 2, 1, 1), - (4, 2, 3, 1, 1), - (4, 2, 4, 1, 1), - (4, 2, 5, 2, 1), - (4, 2, 6, 2, 1), - (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read - (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) - (4, 2, 9, 3, 2), - (4, 4, 1, 2, 2), - (4, 4, 4, 2, 2), - (4, 4, 6, 4, 2), - (4, 4, 9, 6, 4), - (5, 2, 1, 2, 2), - (5, 2, 4, 2, 2), - (5, 2, 9, 6, 4), -]: - TESTS.append(Test( - f"wide_quad_a{abits}w{wbits}r{rwords}", - WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), - ["multilut"], ["PORTS_QUAD"], - {"LUT_MULTI": cntquad} - )) - TESTS.append(Test( - f"wide_oct_a{abits}w{wbits}r{rwords}", - WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), - ["multilut"], ["PORTS_OCT"], - {"LUT_MULTI": cntoct} - )) - -# signal priorities & pattern testing -PRIORITY = """ -module top(clk, clken, wren, wben, rden, rst, addr, wdata, rdata); - -localparam ABITS = {abits}; -localparam WBITS = {wbits}; -localparam WORDS = {words}; - -localparam BITS = WBITS * WORDS; - -input wire clk, clken; -input wire wren, rden, rst; -input wire [WORDS-1:0] wben; -input wire [ABITS-1:0] addr; -input wire [BITS-1:0] wdata; -output reg [BITS-1:0] rdata; - -reg [BITS-1:0] mem [0:2**ABITS-1]; - -integer i; -always @(posedge clk) begin -{code} -end -endmodule -""" -#reset_gate in ["ungated", "rst", "rden && rst"] -#clk_en in [True, False] -#rdwr in ["nc", "old", "new", "undef", "newdef"] - -for (testname, reset_gate, rdwr, clk_en, add_logic) in [ - ("no_reset", "", "old", False, 0), - ("gclken", "rst", "old", False, 0), - ("ungated", "ungated", "old", False, 1), # muxes wren with rst - ("gclken_ce", "rst", "old", True, 3), # AND to simulate CLK_EN - ("grden", "rden && rst", "old", False, 1), # selects _clken, simulates _rden - ("grden_ce", "rden && rst", "old", True, 4), # both of the above - ("exclwr", "", "nc", False, 2), # selects new_only and simulates - ("excl_rst", "rst", "nc", False, 3), # as above, extra gate for rst - ("transwr", "", "new", False, 0), - ("trans_rst", "rst", "new", False, 0), -]: - write = "if (wren) \n\t\tmem[addr] <= wdata;" - - if rdwr == "new": - read = """if (rden) - if (wren) - rdata <= wdata; - else - rdata <= mem[addr];""" - else: - read = "if (rden) \n\t\trdata <= mem[addr];" - - if "rst" in reset_gate: - read = f"if ({reset_gate})\n\t\trdata <= 0; \n\telse {read}" - - if reset_gate == "ungated": - outer = "if (rst)\n\trdata <= 0;\nelse " - else: - outer = "" - - if clk_en: - outer = f"{outer}if (clken) " - - code = f"""{outer}begin - {write} - {"else " if rdwr == "nc" else ""}{read} -end""" - - TESTS.append(Test( - testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), - ["block_sp_full"], ["USE_SRST"], - {"RAM_BLOCK_SP": 1, "$*": add_logic} - )) - -for (testname, reset_gate, defs, rdwr, add_logic) in [ - ("wr_byte", "", ["USE_SRST_BLOCKING"], "old", 0), - ("trans_byte", "", ["USE_SRST_BLOCKING"], "new", 0), - ("wr_rst_byte", "rst", ["USE_SRST"], "old", 2), # expected mux to emulate blocking - ("rst_wr_byte", "rst", ["USE_SRST_BLOCKING"], "old", 2), # should use hardware blocking, doesn't - ("rdenrst_wr_byte", "rden && rst", ["USE_SRST"], "old", 3), -]: - wordsloop = "for (i=0; i 0) begin + reg [WDBITS-1:0] mem_read; + reg [OFFSET-1:0] subaddr_r; + always @(posedge clk) begin + mem_read <= mem[ra[RABITS-1:OFFSET]]; + subaddr_r <= ra[OFFSET-1:0]; + end + + always @(mem_read, subaddr_r) + rd <= mem_read[subaddr_r*RDBITS+:RDBITS]; +end +else +begin + always @(posedge clk) + case (OFFSET) + 0: rd <= mem[ra]; + -1: rd <= {{ mem[ra], mem[ra+1] }}; + endcase +end +endmodule +""" + +UNMIXED = MIXED_WRITE.format(wabits=4, wdbits=9, rabits=4, rdbits=9) +MIXED_9_18 = MIXED_WRITE.format(wabits=5, wdbits=9, rabits=4, rdbits=18) +MIXED_18_9 = MIXED_WRITE.format(wabits=3, wdbits=18, rabits=4, rdbits=9) +MIXED_36_9 = MIXED_WRITE.format(wabits=3, wdbits=36, rabits=5, rdbits=9) +MIXED_4_2 = MIXED_WRITE.format(wabits=5, wdbits=4, rabits=6, rdbits=2); + +TESTS += [ + Test("unmixed", UNMIXED, ["9b1B"], [], {"RAM_9b1B":1}), + Test("mixed_9_18", MIXED_9_18, ["9b1B"], [], {"RAM_9b1B":4}), #CHECK: only using half the memory + Test("mixed_18_9", MIXED_18_9, ["9b1B"], [], {"RAM_9b1B":1}), + Test("mixed_36_9", MIXED_36_9, ["9b1B"], [], {"RAM_9b1B":2}), + Test("mixed_4_2", MIXED_4_2, ["9b1B"], [], {"RAM_9b1B":1}), +] + +### basic TDP test + +TDP = """ +module top(clka, clkb, addra, addrb, rda, rdb, wda, wdb, wea, web); + +localparam ABITS = 6; +localparam DBITS = 6; + +input wire clka, clkb; +input wire wea, web; +input wire [ABITS-1:0] addra, addrb; +input wire [DBITS-1:0] wda, wdb; +output reg [DBITS-1:0] rda, rdb; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clka) + if (wea) + mem[addra] <= wda; + else + rda <= mem[addra]; + +always @(posedge clkb) + if (web) + mem[addrb] <= wdb; + else + rdb <= mem[addrb]; + +endmodule +""" + +TESTS += [ + Test("tdp", TDP, ["block_tdp", "block_sdp"], [], {"RAM_BLOCK_TDP": 1}), +] + +# shared clock +# Synchronous SDP with clock domain crossing +SYNC_2CLK = """ +module top(rclk, wclk, ra, wa, rd, wd, we); + +localparam ABITS = 6; +localparam DBITS = 16; + +input wire rclk, wclk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge wclk) + if (we) + mem[wa] <= wd; + +always @(posedge rclk) + rd <= mem[ra]; + +endmodule +""" + +TESTS += [ + Test("sync_2clk", SYNC_2CLK, ["block_sdp"], [], {"RAM_BLOCK_SDP": 1}), + Test("sync_shared", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_2clk_shared", SYNC_2CLK, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 0}), +] + +# inter-port transparency +# Synchronous SDP with write-first behaviour +SYNC_TRANS = """ +module top(clk, ra, wa, rd, wd, we); + +localparam ABITS = 6; +localparam DBITS = 16; + +input wire clk; +input wire we; +input wire [ABITS-1:0] ra, wa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(negedge clk) + if (we) + mem[wa] <= wd; + +always @(negedge clk) begin + rd <= mem[ra]; + if (we && ra == wa) + rd <= wd; +end + +endmodule +""" + +TESTS += [ + Test("sync_trans_old_old", SYNC_MID, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 0})}), + Test("sync_trans_old_new", SYNC_MID, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_trans_old_none", SYNC_MID, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_trans_new_old", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_OLD"], {"RAM_BLOCK_SDP_1CLK": 1}), + Test("sync_trans_new_new", SYNC_TRANS, ["block_sdp_1clk"], ["TRANS_NEW"], {"RAM_BLOCK_SDP_1CLK": (1, {"OPTION_TRANS": 1})}), + Test("sync_trans_new_none", SYNC_TRANS, ["block_sdp_1clk"], [], {"RAM_BLOCK_SDP_1CLK": 1}), +] + +# rdwr checks +# Synchronous single-port RAM with mutually exclusive read/write +SP_NO_CHANGE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) + mem[addr] <= wd; + else + rd <= mem[addr]; +end + +endmodule +""" + +SP_NO_CHANGE_BE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire [1:0] we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) begin + if (we[0]) + mem[addr][7:0] <= wd[7:0]; + if (we[1]) + mem[addr][15:8] <= wd[15:8]; + end else + rd <= mem[addr]; +end + +endmodule +""" + +# Synchronous single-port RAM with write-first behaviour +SP_NEW = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) begin + mem[addr] <= wd; + rd <= wd; + end else + rd <= mem[addr]; +end + +endmodule +""" + +SP_NEW_BE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire [1:0] we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + rd <= mem[addr]; + if (we[0]) begin + mem[addr][7:0] <= wd[7:0]; + rd[7:0] <= wd[7:0]; + end + if (we[1]) begin + mem[addr][15:8] <= wd[15:8]; + rd[15:8] <= wd[15:8]; + end +end + +endmodule +""" + +# Synchronous single-port RAM with read-first behaviour +SP_OLD = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we) + mem[addr] <= wd; + rd <= mem[addr]; +end + +endmodule +""" + +SP_OLD_BE = """ +module top(clk, addr, rd, wd, we); + +input wire clk; +input wire [1:0] we; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +always @(negedge clk) begin + if (we[0]) + mem[addr][7:0] <= wd[7:0]; + if (we[1]) + mem[addr][15:8] <= wd[15:8]; + rd <= mem[addr]; +end + +endmodule +""" + +TESTS += [ + Test("sp_nc_none", SP_NO_CHANGE, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), + Test("sp_new_none", SP_NEW, ["block_sp"], [], {"RAM_BLOCK_SP": 1}), + Test("sp_old_none", SP_OLD, ["block_sp"], [], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_nc", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_nc", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_nc", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_new", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new", SP_NEW, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_new", SP_OLD, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_old", SP_NO_CHANGE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_old", SP_NEW, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_old", SP_OLD, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_nc_new_only", SP_NO_CHANGE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new_only", SP_NEW, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_new_only", SP_OLD, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_new_only_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new_only_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 2}), + Test("sp_old_new_only_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW_ONLY"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_new_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_new_be", SP_NEW_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_new_be", SP_OLD_BE, ["block_sp"], ["RDWR_NEW"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_old_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_old_be", SP_NEW_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_old_old_be", SP_OLD_BE, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_nc_nc_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_nc_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 2}), + Test("sp_old_nc_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE"], {"RAM_BLOCK_SP": 0}), + Test("sp_nc_auto", SP_NO_CHANGE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_auto", SP_NEW, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), + Test("sp_old_auto", SP_OLD, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), + Test("sp_nc_auto_be", SP_NO_CHANGE_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": 1}), + Test("sp_new_auto_be", SP_NEW_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "NEW"})}), + Test("sp_old_auto_be", SP_OLD_BE, ["block_sp"], ["RDWR_NO_CHANGE", "RDWR_OLD", "RDWR_NEW"], {"RAM_BLOCK_SP": (1, {"OPTION_RDWR": "OLD"})}), +] + +# Synchronous read port with initial value +SP_INIT = """ +module top(clk, addr, rd, wd, we, re); + +input wire clk; +input wire we, re; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; + if (re) + rd <= mem[addr]; +end + +endmodule +""" + +SP_INIT_X = SP_INIT.format(ival="16'hxxxx") +SP_INIT_0 = SP_INIT.format(ival="16'h0000") +SP_INIT_V = SP_INIT.format(ival="16'h55aa") + +TESTS += [ + Test("sp_init_x_x", SP_INIT_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_x_x_re", SP_INIT_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_x_x_ce", SP_INIT_X, ["block_sp"], ["CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_x", SP_INIT_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_x_re", SP_INIT_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_0", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_0_re", SP_INIT_0, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_any", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_0_any_re", SP_INIT_0, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_x", SP_INIT_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_x_re", SP_INIT_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_0", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_0_re", SP_INIT_V, ["block_sp"], ["RDINIT_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_any", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_init_v_any_re", SP_INIT_V, ["block_sp"], ["RDINIT_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), +] + +# Synchronous read port with asynchronous reset +SP_ARST = """ +module top(clk, addr, rd, wd, we, re, ar); + +input wire clk; +input wire we, re, ar; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; +end +always @(posedge clk, posedge ar) begin + if (ar) + rd <= {aval}; + else if (re) + rd <= mem[addr]; +end + +endmodule +""" + +SP_ARST_X = SP_ARST.format(ival="16'hxxxx", aval="16'hxxxx") +SP_ARST_0 = SP_ARST.format(ival="16'hxxxx", aval="16'h0000") +SP_ARST_V = SP_ARST.format(ival="16'hxxxx", aval="16'h55aa") +SP_ARST_E = SP_ARST.format(ival="16'h55aa", aval="16'h55aa") +SP_ARST_N = SP_ARST.format(ival="16'h1234", aval="16'h55aa") + +TESTS += [ + Test("sp_arst_x_x", SP_ARST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_x_x_re", SP_ARST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_x", SP_ARST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_x_re", SP_ARST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_0", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_0_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_any", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_any_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_init", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_0_init_re", SP_ARST_0, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_x", SP_ARST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_x_re", SP_ARST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_0", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_0_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_any", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_any_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_init", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_v_init_re", SP_ARST_V, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_x", SP_ARST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_x_re", SP_ARST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_0", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_0_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_any", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_any_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_init", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_e_init_re", SP_ARST_E, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_x", SP_ARST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_x_re", SP_ARST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_0", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_0_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_any", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_any_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_init", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_arst_n_init_re", SP_ARST_N, ["block_sp"], ["RDINIT_ANY", "RDARST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), +] + +# Synchronous read port with synchronous reset (reset priority over enable) +SP_SRST = """ +module top(clk, addr, rd, wd, we, re, sr); + +input wire clk; +input wire we, re, sr; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; +end +always @(posedge clk) begin + if (sr) + rd <= {sval}; + else if (re) + rd <= mem[addr]; +end + +endmodule +""" + +# Synchronous read port with synchronous reet (enable priority over reset) +SP_SRST_G = """ +module top(clk, addr, rd, wd, we, re, sr); + +input wire clk; +input wire we, re, sr; +input wire [3:0] addr; +input wire [15:0] wd; +output reg [15:0] rd; + +reg [15:0] mem [0:15]; + +initial rd = {ival}; + +always @(posedge clk) begin + if (we) + mem[addr] <= wd; +end +always @(posedge clk) begin + if (re) begin + if (sr) + rd <= {sval}; + else + rd <= mem[addr]; + end +end + +endmodule +""" + +SP_SRST_X = SP_SRST.format(ival="16'hxxxx", sval="16'hxxxx") +SP_SRST_0 = SP_SRST.format(ival="16'hxxxx", sval="16'h0000") +SP_SRST_V = SP_SRST.format(ival="16'hxxxx", sval="16'h55aa") +SP_SRST_E = SP_SRST.format(ival="16'h55aa", sval="16'h55aa") +SP_SRST_N = SP_SRST.format(ival="16'h1234", sval="16'h55aa") +SP_SRST_GV = SP_SRST_G.format(ival="16'hxxxx", sval="16'h55aa") + +TESTS += [ + Test("sp_srst_x_x", SP_SRST_X, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_x_x_re", SP_SRST_X, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_x", SP_SRST_0, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_x_re", SP_SRST_0, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_0", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_0_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_any", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_any_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_init", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_0_init_re", SP_SRST_0, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_x", SP_SRST_V, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_x_re", SP_SRST_V, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_0", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_0_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_re_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_ce", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_any_ce_gated", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_init", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_v_init_re", SP_SRST_V, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_x", SP_SRST_E, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_x_re", SP_SRST_E, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_0", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_0_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_any", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_any_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_init", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_e_init_re", SP_SRST_E, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_x", SP_SRST_N, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_x_re", SP_SRST_N, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_0", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_0_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_any", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_any_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_init", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_n_init_re", SP_SRST_N, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_x", SP_SRST_GV, ["block_sp"], ["RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_x_re", SP_SRST_GV, ["block_sp"], ["RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_0", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_0_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_0", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_re_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_RE", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_ce", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_any_ce_gated", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_ANY_CE", "CLKEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_init", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), + Test("sp_srst_gv_init_re", SP_SRST_GV, ["block_sp"], ["RDINIT_ANY", "RDSRST_INIT", "RDEN", "RDWR_OLD"], {"RAM_BLOCK_SP": 1}), +] + +# Byte enables, wrbe_separate +SYNC_ENABLE = """ +module top(clk, rwa, rd, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [DBITS-1:0] wd; +output reg [DBITS-1:0] rd; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) begin + if (we) + mem[rwa] <= wd; + else + rd <= mem[rwa]; +end + +endmodule +""" + +for (abits, dbits, sep, defs, cells) in [ + (4, 4, False, ["NO_BYTE"], {"RAM_WREN": 1}), + (5, 4, False, ["NO_BYTE"], {"RAM_WREN": 2}), + (6, 4, False, ["NO_BYTE"], {"RAM_WREN": 4}), + # (4, 4, True, ["NO_BYTE"], {"RAM_WREN": 1}), # should throw an error + (3, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), # needs two write ports + (4, 8, False, ["NO_BYTE"], {"RAM_WREN": 2}), + (4, 4, False, ["W4_B4"], {"RAM_WREN": 1}), + (4, 8, True, ["W4_B4"], {"RAM_WREN": 2}), + (4, 8, False, ["W8_B4"], {"RAM_WREN": 1}), + (4, 8, True, ["W8_B4"], {"RAM_WREN": 1}), + (4, 8, False, ["W8_B8"], {"RAM_WREN": 1}), + (4, 8, True, ["W8_B8"], {"RAM_WREN": 1}), + +]: + name = f"wren_a{abits}d{dbits}_{defs[0]}" + if (sep): + defs.append("WRBE_SEPARATE") + name += "_separate" + + TESTS.append(Test( + name, SYNC_ENABLE.format(abits=abits, dbits=dbits), + ["wren"], defs, cells + )) + +# Write port with byte enables +ENABLES = """ +module top(clk, we, be, rwa, wd, rd); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam WORDS = {words}; + +input wire clk; +input wire we; +input wire [WORDS-1:0] be; +input wire [ABITS-1:0] rwa; +input wire [(WBITS*WORDS)-1:0] wd; +output reg [(WBITS*WORDS)-1:0] rd; + +reg [(WBITS*WORDS)-1:0] mem [0:2**ABITS-1]; + +integer i; +always @(posedge clk) + for (i=0; i> {bw}]) + for (j = 0; j < 2**{bw}; j = j + 1) + mem[wa << {ww} | i | j] <= wd[i | j]; + +always @(posedge rclk) + if (rr) + rd <= {sval}; + else if (re) + for (i = 0; i < 2**{rw}; i = i + 1) + rd[i] <= mem[ra << {rw} | i]; + +endmodule +""" + +for (aw, rw, ww, bw, xw, sval, cnt) in [ + (6, 1, 1, 1, 1, "2'h1", 1), + (7, 1, 1, 1, 1, "2'h2", 2), + (8, 1, 1, 1, 1, "2'h3", 4), + (6, 0, 0, 0, 0, "2'h0", 1), + (6, 1, 0, 0, 0, "2'h0", 1), + (6, 2, 0, 0, 0, "2'h0", 1), + (6, 3, 0, 0, 0, "2'h0", 1), + (6, 4, 0, 0, 0, "2'h0", 1), + (6, 5, 0, 0, 0, "2'h0", 2), + (6, 0, 1, 0, 0, "2'h0", 2), + (6, 0, 1, 1, 0, "2'h0", 1), + (6, 0, 2, 0, 0, "2'h0", 4), + (6, 0, 2, 2, 0, "2'h0", 1), + (6, 0, 3, 2, 0, "2'h0", 1), + (6, 0, 4, 2, 0, "2'h0", 1), + (6, 0, 5, 2, 0, "2'h0", 2), + (7, 0, 0, 0, 0, "2'h0", 2), + (7, 1, 0, 0, 0, "2'h0", 2), + (7, 2, 0, 0, 0, "2'h0", 2), + (7, 3, 0, 0, 0, "2'h0", 2), + (7, 4, 0, 0, 0, "2'h0", 2), + (7, 5, 0, 0, 0, "2'h0", 2), + (7, 0, 1, 0, 0, "2'h0", 2), + (7, 0, 1, 1, 0, "2'h0", 2), + (7, 0, 2, 0, 0, "2'h0", 4), + (7, 0, 2, 2, 0, "2'h0", 2), + (7, 0, 3, 2, 0, "2'h0", 2), + (7, 0, 4, 2, 0, "2'h0", 2), + (7, 0, 5, 2, 0, "2'h0", 2), +]: + TESTS.append(Test( + f"wide_sdp_a{aw}r{rw}w{ww}b{bw}x{xw}", + WIDE_SDP.format(aw=aw, rw=rw, ww=ww, bw=bw, xw=xw, sval=sval), + ["wide_sdp"], [], + {"RAM_WIDE_SDP": cnt} + )) + +WIDE_SP = """ +module top(clk, a, rd, re, rr, wd, we); + +input wire clk, re, rr; +input wire [2**({ww}-{bw})-1:0] we; +input wire [{aw}-1:0] a; +input wire [2**{ww}-1:0] wd; +output reg [2**{rw}-1:0] rd; + +reg mem [0:2**{aw}-1]; + +initial mem[3] = 0; +initial mem[17] = 1; +initial mem[23] = 0; +initial mem[24] = 1; + +integer i, j; +always @(posedge clk) begin + for (i = 0; i < 2**{ww}; i = i + 2**{bw}) + if (we[i >> {bw}]) + for (j = 0; j < 2**{bw}; j = j + 1) + mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; + if (rr) + rd <= {sval}; + else if (re) + for (i = 0; i < 2**{rw}; i = i + 1) + rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; +end + +endmodule +""" + +for (aw, rw, ww, bw, sval, cnt) in [ + (6, 1, 1, 1, "2'h1", 1), + (7, 1, 1, 1, "2'h2", 2), + (8, 1, 1, 1, "2'h3", 4), + (6, 0, 0, 0, "2'h0", 1), + (6, 1, 0, 0, "2'h0", 1), + (6, 2, 0, 0, "2'h0", 1), + (6, 3, 0, 0, "2'h0", 1), + (6, 4, 0, 0, "2'h0", 1), + (6, 5, 0, 0, "2'h0", 2), + (6, 0, 1, 0, "2'h0", 2), + (6, 0, 1, 1, "2'h0", 1), + (6, 0, 2, 0, "2'h0", 4), + (6, 0, 2, 2, "2'h0", 1), + (6, 0, 3, 2, "2'h0", 1), + (6, 0, 4, 2, "2'h0", 1), + (6, 0, 5, 2, "2'h0", 2), + (7, 0, 0, 0, "2'h0", 2), + (7, 1, 0, 0, "2'h0", 2), + (7, 2, 0, 0, "2'h0", 2), + (7, 3, 0, 0, "2'h0", 2), + (7, 4, 0, 0, "2'h0", 2), + (7, 5, 0, 0, "2'h0", 2), + (7, 0, 1, 0, "2'h0", 2), + (7, 0, 1, 1, "2'h0", 2), + (7, 0, 2, 0, "2'h0", 4), + (7, 0, 2, 2, "2'h0", 2), + (7, 0, 3, 2, "2'h0", 2), + (7, 0, 4, 2, "2'h0", 2), + (7, 0, 5, 2, "2'h0", 2), +]: + TESTS.append(Test( + f"wide_sp_mix_a{aw}r{rw}w{ww}b{bw}", + WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), + ["wide_sp"], ["WIDTH_MIX"], + {"RAM_WIDE_SP": cnt} + )) + +for (aw, rw, ww, bw, sval, cnt) in [ + (6, 1, 1, 1, "2'h1", 1), + (7, 1, 1, 1, "2'h2", 2), + (8, 1, 1, 1, "2'h3", 4), + (6, 0, 0, 0, "2'h0", 1), + (6, 1, 0, 0, "2'h0", 2), + (6, 2, 0, 0, "2'h0", 4), + (6, 3, 0, 0, "2'h0", 4), + (6, 4, 0, 0, "2'h0", 4), + (6, 5, 0, 0, "2'h0", 8), + (6, 0, 1, 0, "2'h0", 2), + (6, 0, 1, 1, "2'h0", 1), + (6, 0, 2, 0, "2'h0", 4), + (6, 0, 2, 2, "2'h0", 1), + (6, 0, 3, 2, "2'h0", 1), + (6, 0, 4, 2, "2'h0", 1), + (6, 0, 5, 2, "2'h0", 2), + (7, 0, 0, 0, "2'h0", 2), + (7, 1, 0, 0, "2'h0", 2), + (7, 2, 0, 0, "2'h0", 4), + (7, 3, 0, 0, "2'h0", 8), + (7, 4, 0, 0, "2'h0", 8), + (7, 5, 0, 0, "2'h0", 8), + (7, 0, 1, 0, "2'h0", 2), + (7, 0, 1, 1, "2'h0", 2), + (7, 0, 2, 0, "2'h0", 4), + (7, 0, 2, 2, "2'h0", 2), + (7, 0, 3, 2, "2'h0", 2), + (7, 0, 4, 2, "2'h0", 2), + (7, 0, 5, 2, "2'h0", 2), +]: + TESTS.append(Test( + f"wide_sp_tied_a{aw}r{rw}w{ww}b{bw}", + WIDE_SP.format(aw=aw, rw=rw, ww=ww, bw=bw, sval=sval), + ["wide_sp"], [], + {"RAM_WIDE_SP": cnt} + )) + +WIDE_RW = """ +module top(clk, a, rd, re, wd, we); + +input wire clk, re; +input wire [2**({ww}-{bw})-1:0] we; +input wire [{aw}-1:0] a; +input wire [2**{ww}-1:0] wd; +output reg [2**{rw}-1:0] rd; + +(* ram_block *) +reg mem [0:2**{aw}-1]; + +initial mem[3] = 0; +initial mem[17] = 1; +initial mem[23] = 0; +initial mem[24] = 1; + +integer i, j; +always @(posedge clk) begin + for (i = 0; i < 2**{ww}; i = i + 2**{bw}) + if (we[i >> {bw}]) + for (j = 0; j < 2**{bw}; j = j + 1) + mem[a & ~((1 << {ww}) - 1) | i | j] <= wd[i | j]; + if (re) + for (i = 0; i < 2**{rw}; i = i + 1) + rd[i] <= mem[a & ~((1 << {rw}) - 1) | i]; +end + +endmodule +""" + +for (aw, rw, ww, bw, cntww, cntwr) in [ + (6, 1, 1, 1, 2, 1), + (7, 1, 1, 1, 4, 2), + (8, 1, 1, 1, 8, 4), + (6, 0, 0, 0, 4, 2), + (6, 1, 0, 0, 4, 2), + (6, 2, 0, 0, 4, 2), + (6, 3, 0, 0, 8, 2), + (6, 4, 0, 0, 16, 4), + (6, 5, 0, 0, 32, 8), + (6, 0, 1, 0, 4, 2), + (6, 0, 1, 1, 2, 1), + (6, 0, 2, 0, 4, 4), + (6, 0, 2, 2, 1, 2), + (6, 0, 3, 2, 1, 4), + (6, 0, 4, 2, 2, 8), + (6, 0, 5, 2, 4, 16), + (7, 0, 0, 0, 8, 4), + (7, 1, 0, 0, 8, 4), + (7, 2, 0, 0, 8, 4), + (7, 3, 0, 0, 8, 4), + (7, 4, 0, 0, 16, 4), + (7, 5, 0, 0, 32, 8), + (7, 0, 1, 0, 8, 4), + (7, 0, 1, 1, 4, 2), + (7, 0, 2, 0, 8, 4), + (7, 0, 2, 2, 2, 2), + (7, 0, 3, 2, 2, 4), + (7, 0, 4, 2, 2, 8), + (7, 0, 5, 2, 4, 16), +]: + TESTS.append(Test( + f"wide_read_a{aw}r{rw}w{ww}b{bw}", + WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), + ["wide_read"], [], + {"RAM_WIDE_READ": cntwr} + )) + TESTS.append(Test( + f"wide_write_a{aw}r{rw}w{ww}b{bw}", + WIDE_RW.format(aw=aw, rw=rw, ww=ww, bw=bw), + ["wide_write"], [], + {"RAM_WIDE_WRITE": cntww} + )) + +# Multiple read ports +# 1rw port plus 3 (or 7) r ports +QUAD_PORT = """ +module top(clk, rwa, r0a, r1a, r2a, rd, r0d, r1d, r2d, wd, we); + +localparam ABITS = {abits}; +localparam DBITS = {dbits}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [ABITS-1:0] r0a; +input wire [ABITS-1:0] r1a; +input wire [ABITS-1:0] r2a; +input wire [DBITS-1:0] wd; +output wire [DBITS-1:0] rd; +output wire [DBITS-1:0] r0d; +output wire [DBITS-1:0] r1d; +output wire [DBITS-1:0] r2d; + +reg [DBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) + if (we) + mem[rwa] <= wd; + +assign rd = mem[rwa]; +assign r0d = mem[r0a]; +assign r1d = mem[r1a]; +assign r2d = mem[r2a]; + +endmodule +""" + +for (abits, dbits, cnt) in [ + (2, 2, 1), + (4, 2, 1), + (5, 2, 2), + (4, 4, 2), + (6, 2, 4), + (4, 8, 4), +]: + TESTS.append(Test( + f"quad_port_a{abits}d{dbits}", + QUAD_PORT.format(abits=abits, dbits=dbits), + ["multilut"], ["PORTS_QUAD"], + {"LUT_MULTI": cnt} + )) + +# Wide asynchronous read port +WIDE_READ = """ +module top(clk, we, rwa, wd, rd); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam RWORDS = {rwords}; + +input wire clk; +input wire we; +input wire [ABITS-1:0] rwa; +input wire [WBITS-1:0] wd; +output wire [(WBITS*RWORDS)-1:0] rd; + +reg [WBITS-1:0] mem [0:2**ABITS-1]; + +always @(posedge clk) + if (we) + mem[rwa] <= wd; + +genvar i; +generate + for (i = 0; i < RWORDS; i = i + 1) + assign rd[i*WBITS+:WBITS] = mem[rwa + i]; +endgenerate + +endmodule +""" + +for (abits, wbits, rwords, cntquad, cntoct) in [ + (4, 2, 1, 1, 1), + (4, 2, 2, 1, 1), + (4, 2, 3, 1, 1), + (4, 2, 4, 1, 1), + (4, 2, 5, 2, 1), + (4, 2, 6, 2, 1), + (4, 2, 7, 2, 1), # Write port needs to be duplicated, so only 3 extra read + (4, 2, 8, 3, 1), # ports per quad port LUT (i.e. 7 ports in 2, 8 ports in 3) + (4, 2, 9, 3, 2), + (4, 4, 1, 2, 2), + (4, 4, 4, 2, 2), + (4, 4, 6, 4, 2), + (4, 4, 9, 6, 4), + (5, 2, 1, 2, 2), + (5, 2, 4, 2, 2), + (5, 2, 9, 6, 4), +]: + TESTS.append(Test( + f"wide_quad_a{abits}w{wbits}r{rwords}", + WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), + ["multilut"], ["PORTS_QUAD"], + {"LUT_MULTI": cntquad} + )) + TESTS.append(Test( + f"wide_oct_a{abits}w{wbits}r{rwords}", + WIDE_READ.format(abits=abits, wbits=wbits, rwords=rwords), + ["multilut"], ["PORTS_OCT"], + {"LUT_MULTI": cntoct} + )) + +# signal priorities & pattern testing +PRIORITY = """ +module top(clk, clken, wren, wben, rden, rst, addr, wdata, rdata); + +localparam ABITS = {abits}; +localparam WBITS = {wbits}; +localparam WORDS = {words}; + +localparam BITS = WBITS * WORDS; + +input wire clk, clken; +input wire wren, rden, rst; +input wire [WORDS-1:0] wben; +input wire [ABITS-1:0] addr; +input wire [BITS-1:0] wdata; +output reg [BITS-1:0] rdata; + +reg [BITS-1:0] mem [0:2**ABITS-1]; + +integer i; +always @(posedge clk) begin +{code} +end +endmodule +""" +#reset_gate in ["ungated", "rst", "rden && rst"] +#clk_en in [True, False] +#rdwr in ["nc", "old", "new", "undef", "newdef"] + +for (testname, reset_gate, rdwr, clk_en, add_logic) in [ + ("no_reset", "", "old", False, 0), + ("gclken", "rst", "old", False, 0), + ("ungated", "ungated", "old", False, 1), # muxes wren with rst + ("gclken_ce", "rst", "old", True, 3), # AND to simulate CLK_EN + ("grden", "rden && rst", "old", False, 1), # selects _clken, simulates _rden + ("grden_ce", "rden && rst", "old", True, 4), # both of the above + ("exclwr", "", "nc", False, 2), # selects new_only and simulates + ("excl_rst", "rst", "nc", False, 3), # as above, extra gate for rst + ("transwr", "", "new", False, 0), + ("trans_rst", "rst", "new", False, 0), +]: + write = "if (wren) \n\t\tmem[addr] <= wdata;" + + if rdwr == "new": + read = """if (rden) + if (wren) + rdata <= wdata; + else + rdata <= mem[addr];""" + else: + read = "if (rden) \n\t\trdata <= mem[addr];" + + if "rst" in reset_gate: + read = f"if ({reset_gate})\n\t\trdata <= 0; \n\telse {read}" + + if reset_gate == "ungated": + outer = "if (rst)\n\trdata <= 0;\nelse " + else: + outer = "" + + if clk_en: + outer = f"{outer}if (clken) " + + code = f"""{outer}begin + {write} + {"else " if rdwr == "nc" else ""}{read} +end""" + + TESTS.append(Test( + testname, PRIORITY.format(code=code, abits=4, wbits=8, words=2), + ["block_sp_full"], ["USE_SRST"], + {"RAM_BLOCK_SP": 1, "$*": add_logic} + )) + +for (testname, reset_gate, defs, rdwr, add_logic) in [ + ("wr_byte", "", ["USE_SRST_BLOCKING"], "old", 0), + ("trans_byte", "", ["USE_SRST_BLOCKING"], "new", 0), + ("wr_rst_byte", "rst", ["USE_SRST"], "old", 2), # expected mux to emulate blocking + ("rst_wr_byte", "rst", ["USE_SRST_BLOCKING"], "old", 2), # should use hardware blocking, doesn't + ("rdenrst_wr_byte", "rden && rst", ["USE_SRST"], "old", 3), +]: + wordsloop = "for (i=0; i Date: Fri, 20 Mar 2026 16:36:36 +0100 Subject: [PATCH 079/176] Fix yml for verific tests --- .github/workflows/test-verific.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-verific.yml b/.github/workflows/test-verific.yml index 65efca79f..132aac589 100644 --- a/.github/workflows/test-verific.yml +++ b/.github/workflows/test-verific.yml @@ -78,7 +78,7 @@ jobs: - name: Run Verific specific Yosys tests run: | make -C tests/sva - cd tests/svtypes && bash run-test.sh + make -C tests/svtypes - name: Run SBY tests if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }} From fdccbe584d054626647baa393f01616491a0c877 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 23 Mar 2026 09:16:08 +0100 Subject: [PATCH 080/176] Convert realmath --- tests/Makefile | 2 +- tests/realmath/.gitignore | 2 +- .../realmath/{generate.py => generate_mk.py} | 48 ++++++++++++------- tests/realmath/run-test.sh | 36 -------------- 4 files changed, 33 insertions(+), 55 deletions(-) rename tests/realmath/{generate.py => generate_mk.py} (77%) delete mode 100755 tests/realmath/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 48ea1774f..63551ecaa 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -56,7 +56,7 @@ MK_TEST_DIRS += ./simple MK_TEST_DIRS += ./simple_abc9 MK_TEST_DIRS += ./hana MK_TEST_DIRS += ./asicworld -#SH_TEST_DIRS += ./realmath +MK_TEST_DIRS += ./realmath MK_TEST_DIRS += ./share MK_TEST_DIRS += ./opt_share MK_TEST_DIRS += ./fsm diff --git a/tests/realmath/.gitignore b/tests/realmath/.gitignore index 9c595a6fb..941856205 100644 --- a/tests/realmath/.gitignore +++ b/tests/realmath/.gitignore @@ -1 +1 @@ -temp +uut_* diff --git a/tests/realmath/generate.py b/tests/realmath/generate_mk.py similarity index 77% rename from tests/realmath/generate.py rename to tests/realmath/generate_mk.py index 2bedf38e4..b56340335 100644 --- a/tests/realmath/generate.py +++ b/tests/realmath/generate_mk.py @@ -1,17 +1,12 @@ #!/usr/bin/env python3 +import sys +sys.path.append("..") +import gen_tests_makefile import argparse import sys import random -from contextlib import contextmanager -@contextmanager -def redirect_stdout(new_target): - old_target, sys.stdout = sys.stdout, new_target - try: - yield new_target - finally: - sys.stdout = old_target def random_expression(depth = 3, maxparam = 0): def recursion(): @@ -42,13 +37,15 @@ parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') args = parser.parse_args() -if args.seed is not None: - print("PRNG seed: %d" % args.seed) - random.seed(args.seed) +seed = args.seed +if seed is None: + seed = random.randrange(sys.maxsize) +print("realmath PRNG seed: %d" % seed) +random.seed(seed) for idx in range(args.count): - with open('temp/uut_%05d.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d(output [63:0] %s);\n' % (idx, ', '.join(['y%02d' % i for i in range(100)]))) for i in range(30): if idx < 10: @@ -63,13 +60,13 @@ for idx in range(args.count): for i in range(100): print('assign y%02d = 65536 * (%s);' % (i, random_expression(maxparam = 60))) print('endmodule') - with open('temp/uut_%05d.ys' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d.ys' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('read_verilog uut_%05d.v' % idx) print('rename uut_%05d uut_%05d_syn' % (idx, idx)) print('write_verilog uut_%05d_syn.v' % idx) - with open('temp/uut_%05d_tb.v' % idx, 'w') as f: - with redirect_stdout(f): + with open('uut_%05d_tb.v' % idx, 'w') as f: + with gen_tests_makefile.redirect_stdout(f): print('module uut_%05d_tb;\n' % idx) print('wire [63:0] %s;' % (', '.join(['r%02d' % i for i in range(100)]))) print('wire [63:0] %s;' % (', '.join(['s%02d' % i for i in range(100)]))) @@ -99,3 +96,20 @@ for idx in range(args.count): print('end') print('endmodule') + +def create_tests(): + for idx in range(args.count): + cmd = [ + f"$(YOSYS) -qq uut_{idx:05d}.ys >/dev/null 2>&1 &&", + f"iverilog -o uut_{idx:05d}_tb uut_{idx:05d}_tb.v uut_{idx:05d}.v uut_{idx:05d}_syn.v >/dev/null 2>&1 &&", + f"./uut_{idx:05d}_tb" +# f"./uut_{idx:05d}_tb | tee uut_{idx:05d}.err;", +# f"if test -s uut_{idx:05d}.err; then", +# " echo \"Note: Make sure that iverilog is an up-to-date git checkout of Icarus Verilog.\";", +# " exit 1;", +# "fi;", +# f"rm -f uut_{idx:05d}.err" + ] + gen_tests_makefile.generate_cmd_test(f"uut_{idx:05d}", cmd) + +gen_tests_makefile.generate_custom(create_tests) diff --git a/tests/realmath/run-test.sh b/tests/realmath/run-test.sh deleted file mode 100755 index 918c93a9f..000000000 --- a/tests/realmath/run-test.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -set -e - -OPTIND=1 -count=100 -seed="" # default to no seed specified -while getopts "c:S:" opt -do - case "$opt" in - c) count="$OPTARG" ;; - S) seed="-S $OPTARG" ;; - esac -done -shift "$((OPTIND-1))" - -rm -rf temp -mkdir -p temp -echo "generating tests.." -python3 generate.py -c $count $seed - -cd temp -echo "running tests.." -for ((i = 0; i < $count; i++)); do - echo -n "[$i]" - idx=$( printf "%05d" $i ) - ../../../yosys -qq uut_${idx}.ys >/dev/null 2>&1 - iverilog -o uut_${idx}_tb uut_${idx}_tb.v uut_${idx}.v uut_${idx}_syn.v >/dev/null 2>&1 - ./uut_${idx}_tb | tee uut_${idx}.err - if test -s uut_${idx}.err; then - echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." - exit 1 - fi - rm -f uut_${idx}.err -done -echo - From 1c76cadac7a6d1dfe8313fe401f375e927cb8850 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 23 Mar 2026 09:22:47 +0100 Subject: [PATCH 081/176] Converted rpc --- tests/Makefile | 2 +- tests/rpc/generate_mk.py | 11 ++++++++++- tests/rpc/run-test.sh | 8 -------- 3 files changed, 11 insertions(+), 10 deletions(-) delete mode 100755 tests/rpc/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 63551ecaa..cba84b11d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -69,7 +69,7 @@ MK_TEST_DIRS += ./peepopt MK_TEST_DIRS += ./proc MK_TEST_DIRS += ./blif #SH_TEST_DIRS += ./arch -#SH_TEST_DIRS += ./rpc +MK_TEST_DIRS += ./rpc MK_TEST_DIRS += ./memfile #SH_TEST_DIRS += ./fmt #SH_TEST_DIRS += ./cxxrtl diff --git a/tests/rpc/generate_mk.py b/tests/rpc/generate_mk.py index 6a921d5a0..95ab05a7d 100644 --- a/tests/rpc/generate_mk.py +++ b/tests/rpc/generate_mk.py @@ -4,5 +4,14 @@ import sys sys.path.append("..") import gen_tests_makefile +import glob -gen_tests_makefile.generate(["--yosys-scripts"]) +def create_tests(): + yss = sorted(glob.glob("*.ys")) + for ys in yss: + gen_tests_makefile.generate_ys_test(ys) + + cmd = [ "python3 frontend.py unix-socket frontend.sock >/dev/null 2>&1" ] + gen_tests_makefile.generate_cmd_test("frontend.py", cmd) + +gen_tests_makefile.generate_custom(create_tests) diff --git a/tests/rpc/run-test.sh b/tests/rpc/run-test.sh deleted file mode 100755 index 0d58b0de2..000000000 --- a/tests/rpc/run-test.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done -python3 frontend.py unix-socket frontend.sock From 4a89ae66ffd7053e85833e7c6613942327340eb2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 23 Mar 2026 09:31:55 +0100 Subject: [PATCH 082/176] Small fix --- tests/Makefile | 2 +- tests/aiger/generate_mk.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index cba84b11d..064f60bba 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -118,7 +118,7 @@ ifeq ($(YOSYS_NOVERIFIC),1) endif endif @echo "" - -@$(MAKE) --no-print-directory summary + @$(MAKE) --no-print-directory summary clean: @rm -rf ./asicworld/*.out ./asicworld/*.log diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py index 00be5b5f9..0e0200d6d 100644 --- a/tests/aiger/generate_mk.py +++ b/tests/aiger/generate_mk.py @@ -53,6 +53,6 @@ def create_tests(): gen_tests_makefile.generate_cmd_test("aigmap", cmd) -extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc" ] +extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc", "SHELL := /bin/bash" ] gen_tests_makefile.generate_custom(create_tests, extra) From 149e2f343a709e1088c765a471c4065ccc96a7af Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 07:43:30 +0100 Subject: [PATCH 083/176] Converted cxxrtl --- tests/Makefile | 2 +- tests/cxxrtl/generate_mk.py | 29 +++++++++ tests/cxxrtl/run-test.sh | 18 ------ tests/fmt/generate_mk.py | 118 ++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 tests/cxxrtl/generate_mk.py delete mode 100755 tests/cxxrtl/run-test.sh create mode 100644 tests/fmt/generate_mk.py diff --git a/tests/Makefile b/tests/Makefile index 064f60bba..21ef440f6 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -72,7 +72,7 @@ MK_TEST_DIRS += ./blif MK_TEST_DIRS += ./rpc MK_TEST_DIRS += ./memfile #SH_TEST_DIRS += ./fmt -#SH_TEST_DIRS += ./cxxrtl +MK_TEST_DIRS += ./cxxrtl #SH_TEST_DIRS += ./liberty #ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) #SH_TEST_DIRS += ./functional diff --git a/tests/cxxrtl/generate_mk.py b/tests/cxxrtl/generate_mk.py new file mode 100644 index 000000000..a23e08a43 --- /dev/null +++ b/tests/cxxrtl/generate_mk.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def run_subtest(name): + gen_tests_makefile.generate_cmd_test(f"cxxrtl_{name}", [ + f"$${{CXX:-g++}} -std=c++11 -O2 -o cxxrtl-test-{name} -I../../backends/cxxrtl/runtime test_{name}.cc -lstdc++;", + f"./cxxrtl-test-{name} >/dev/null 2>&1", + ]) + +def compile_only(): + gen_tests_makefile.generate_cmd_test("cxxrtl_unconnected_output", [ + '$(YOSYS) -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" >/dev/null 2>&1;', + f'$${{CXX:-g++}} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc', + ]) + +def main(): + def callback(): + run_subtest("value") + run_subtest("value_fuzz") + compile_only() + + gen_tests_makefile.generate_custom(callback) + +if __name__ == "__main__": + main() diff --git a/tests/cxxrtl/run-test.sh b/tests/cxxrtl/run-test.sh deleted file mode 100755 index 6a0bd2355..000000000 --- a/tests/cxxrtl/run-test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -source ../common-env.sh - -set -e - -run_subtest () { - local subtest=$1; shift - - ${CXX:-g++} -std=c++11 -O2 -o cxxrtl-test-${subtest} -I../../backends/cxxrtl/runtime test_${subtest}.cc -lstdc++ - ./cxxrtl-test-${subtest} -} - -run_subtest value -run_subtest value_fuzz - -# Compile-only test. -../../yosys -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" >/dev/null 2>&1 -${CXX:-g++} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py new file mode 100644 index 000000000..0ae06732b --- /dev/null +++ b/tests/fmt/generate_mk.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def cmd(lines): + return " ; \\\n".join(lines) + +def initial_display(): + gen_tests_makefile.generate_target("initial_display", cmd([ + "../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $$0}' >yosys-initial_display.log 2>&1", + "iverilog -o iverilog-initial_display initial_display.v", + "./iverilog-initial_display >iverilog-initial_display.log", + "diff yosys-initial_display.log iverilog-initial_display.log", + ])) + + +def always_display(): + cases = [ + ("clk", "-DEVENT_CLK"), + ("clk_rst", "-DEVENT_CLK_RST"), + ("star", "-DEVENT_STAR"), + ("clk_en", "-DEVENT_CLK -DCOND_EN"), + ("clk_rst_en", "-DEVENT_CLK_RST -DCOND_EN"), + ("star_en", "-DEVENT_STAR -DCOND_EN"), + ] + + for name, defs in cases: + gen_tests_makefile.generate_target(f"always_display_{name}", cmd([ + f"../../yosys -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v >/dev/null 2>&1", + f"../../yosys -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v >/dev/null 2>&1", + f"diff yosys-always_display-{name}-1.v yosys-always_display-{name}-2.v", + ])) + + +def roundtrip(): + cases = [ + ("dec_unsigned", '-DBASE_DEC -DSIGN=""'), + ("dec_signed", '-DBASE_DEC -DSIGN="signed"'), + ("hex_unsigned", '-DBASE_HEX -DSIGN=""'), + ("hex_signed", '-DBASE_HEX -DSIGN="signed"'), + ("oct_unsigned", '-DBASE_HEX -DSIGN=""'), + ("oct_signed", '-DBASE_HEX -DSIGN="signed"'), + ("bin_unsigned", '-DBASE_HEX -DSIGN=""'), + ("bin_signed", '-DBASE_HEX -DSIGN="signed"'), + ] + + for name, defs in cases: + gen_tests_makefile.generate_target(f"roundtrip_{name}", cmd([ + f"../../yosys -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v >/dev/null 2>&1", + f"../../yosys -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v >/dev/null 2>&1", + f"diff yosys-roundtrip-{name}-1.v yosys-roundtrip-{name}-2.v", + + f"iverilog {defs} -o iverilog-roundtrip-{name} roundtrip.v roundtrip_tb.v >/dev/null 2>&1", + f"./iverilog-roundtrip-{name} >iverilog-roundtrip-{name}.log", + + f"iverilog {defs} -o iverilog-roundtrip-{name}-1 yosys-roundtrip-{name}-1.v roundtrip_tb.v >/dev/null 2>&1", + f"./iverilog-roundtrip-{name}-1 >iverilog-roundtrip-{name}-1.log", + + f"iverilog {defs} -o iverilog-roundtrip-{name}-2 yosys-roundtrip-{name}-2.v roundtrip_tb.v >/dev/null 2>&1", + f"./iverilog-roundtrip-{name}-2 >iverilog-roundtrip-{name}-2.log", + + f"diff iverilog-roundtrip-{name}.log iverilog-roundtrip-{name}-1.log", + f"diff iverilog-roundtrip-{name}-1.log iverilog-roundtrip-{name}-2.log", + ])) + + +def cxxrtl(): + cases = ["always_full", "always_comb"] + + for name in cases: + gen_tests_makefile.generate_target(f"cxxrtl_{name}", cmd([ + f"../../yosys -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\" >/dev/null 2>&1", + f"$${{CXX:-g++}} -std=c++11 -o yosys-{name} -I../../backends/cxxrtl/runtime {name}_tb.cc -lstdc++", + f"./yosys-{name} 2>yosys-{name}.log", + + f"iverilog -o iverilog-{name} {name}.v {name}_tb.v >/dev/null 2>&1", + f"./iverilog-{name} | grep -v '\\$finish called' >iverilog-{name}.log", + + f"diff iverilog-{name}.log yosys-{name}.log", + ])) + + +def extra(): + gen_tests_makefile.generate_target("always_full_equiv", cmd([ + "../../yosys -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v >/dev/null 2>&1", + "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v >/dev/null 2>&1", + "./iverilog-always_full-1 | grep -v '\\$finish called' >iverilog-always_full-1.log", + "diff iverilog-always_full.log iverilog-always_full-1.log", + ])) + + gen_tests_makefile.generate_target("display_lm", cmd([ + "../../yosys -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", + "../../yosys -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\" >/dev/null 2>&1", + "$${CXX:-g++} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", + "./yosys-display_lm_cc >yosys-display_lm_cc.log", + "for log in yosys-display_lm.log yosys-display_lm_cc.log; do " + "grep \"^%l: \\\\bot\\$\" \"$log\" >/dev/null 2>&1; " + "grep \"^%m: \\\\bot\\$\" \"$log\" >/dev/null 2>&1; " + "done", + ])) + + +def main(): + def callback(): + #initial_display() + always_display() + roundtrip() + cxxrtl() + extra() + + gen_tests_makefile.generate_custom(callback) + + +if __name__ == "__main__": + main() From c272bfbdc3b01b14bfc57442b060861d6966d63a Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 07:53:06 +0100 Subject: [PATCH 084/176] Convert liberty --- tests/Makefile | 2 +- tests/liberty/generate_mk.py | 43 ++++++++++++++++++++++++++++++++++++ tests/liberty/run-test.sh | 22 ------------------ 3 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 tests/liberty/generate_mk.py delete mode 100755 tests/liberty/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 21ef440f6..f971ec5e5 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -73,7 +73,7 @@ MK_TEST_DIRS += ./rpc MK_TEST_DIRS += ./memfile #SH_TEST_DIRS += ./fmt MK_TEST_DIRS += ./cxxrtl -#SH_TEST_DIRS += ./liberty +MK_TEST_DIRS += ./liberty #ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) #SH_TEST_DIRS += ./functional #endif diff --git a/tests/liberty/generate_mk.py b/tests/liberty/generate_mk.py new file mode 100644 index 000000000..35bd9335b --- /dev/null +++ b/tests/liberty/generate_mk.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import glob +import os +import sys +sys.path.append("..") + +import gen_tests_makefile + +def lib_tests(): + for lib in sorted(glob.glob("*.lib")): + base = os.path.splitext(lib)[0] + + gen_tests_makefile.generate_cmd_test(lib, [ + f'$(YOSYS) -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty {lib}" -ql {base}.log;', + + f'../../yosys-filterlib - {lib} 2>/dev/null > {lib}.filtered;', + f'../../yosys-filterlib -verilogsim {lib} > {lib}.verilogsim;', + + f'diff {lib}.filtered {lib}.filtered.ok;', + f'diff {lib}.verilogsim {lib}.verilogsim.ok;', + + f'if [ -e {base}.log.ok ]; then ' + f'$(YOSYS) -p "dfflibmap -info -liberty {lib}" -TqqQl {base}.log >/dev/null 2>&1; ' + f'diff {base}.log {base}.log.ok; ' + f'fi', + ]) + + +def ys_tests(): + for ys in sorted(glob.glob("*.ys")): + gen_tests_makefile.generate_ys_test(ys) + +def main(): + def callback(): + lib_tests() + ys_tests() + + gen_tests_makefile.generate_custom(callback) + + +if __name__ == "__main__": + main() diff --git a/tests/liberty/run-test.sh b/tests/liberty/run-test.sh deleted file mode 100755 index 1b6873f26..000000000 --- a/tests/liberty/run-test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -eo pipefail - -for x in *.lib; do - echo "Testing on $x.." - ../../yosys -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty ${x}" -ql ${x%.lib}.log - ../../yosys-filterlib - $x 2>/dev/null > $x.filtered - ../../yosys-filterlib -verilogsim $x > $x.verilogsim - diff $x.filtered $x.filtered.ok - diff $x.verilogsim $x.verilogsim.ok - if [[ -e ${x%.lib}.log.ok ]]; then - ../../yosys -p "dfflibmap -info -liberty ${x}" -TqqQl ${x%.lib}.log >/dev/null 2>&1 - diff ${x%.lib}.log ${x%.lib}.log.ok - fi -done - -for x in *.ys; do - echo "Running $x.." - ../../yosys -q -s $x -l ${x%.ys}.log >/dev/null 2>&1 -done - From f42800d4d3d539bbd9b79028fcaf591c3d561243 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 08:47:57 +0100 Subject: [PATCH 085/176] Convert arch --- tests/Makefile | 2 +- tests/arch/generate_mk.py | 52 +++++++++++++++++++++++++++++++++++++++ tests/arch/run-test.sh | 30 ---------------------- 3 files changed, 53 insertions(+), 31 deletions(-) create mode 100644 tests/arch/generate_mk.py delete mode 100755 tests/arch/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index f971ec5e5..832bdc716 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -68,7 +68,7 @@ MK_TEST_DIRS += ./select MK_TEST_DIRS += ./peepopt MK_TEST_DIRS += ./proc MK_TEST_DIRS += ./blif -#SH_TEST_DIRS += ./arch +MK_TEST_DIRS += ./arch MK_TEST_DIRS += ./rpc MK_TEST_DIRS += ./memfile #SH_TEST_DIRS += ./fmt diff --git a/tests/arch/generate_mk.py b/tests/arch/generate_mk.py new file mode 100644 index 000000000..3ea1f1c44 --- /dev/null +++ b/tests/arch/generate_mk.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import sys +sys.path.append("..") + +import gen_tests_makefile + +techlibs_dir = Path("../../techlibs") + +# Architecture-specific defines +defines = { + "ice40": ["ICE40_HX", "ICE40_LP", "ICE40_U"] +} + +def archs(): + # Loop over architectures + for arch in techlibs_dir.iterdir(): + if not arch.is_dir(): + continue + arch_name = arch.name + + for path in arch.rglob("cells_sim.v"): + rel_parts = path.relative_to(techlibs_dir).parts + target_base = "_".join(rel_parts[-len(rel_parts):]).replace(".v", "") + path_str = str(path) + if arch_name in defines: + for defn in defines[arch_name]: + target_name = f"{target_base}_{defn}" + cmd = f"iverilog -t null -I{arch} -D{defn} -DNO_ICE40_DEFAULT_ASSIGNMENTS {path_str} >/dev/null 2>&1" + gen_tests_makefile.generate_target(target_name, cmd) + else: + target_name = f"{target_base}" + cmd = f"iverilog -t null -I{arch} -g2005-sv {path_str} >/dev/null 2>&1" + gen_tests_makefile.generate_target(target_name, cmd) + +def common(): + for path in ["../../techlibs/common/simcells.v", "../../techlibs/common/simlib.v"]: + path_obj = Path(path) + target_name = path_obj.stem + cmd = f"iverilog -t null {path} >/dev/null 2>&1" + gen_tests_makefile.generate_target(target_name, cmd) + +def main(): + def callback(): + archs() + common() + + gen_tests_makefile.generate_custom(callback) + +if __name__ == "__main__": + main() diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh deleted file mode 100755 index 087abf536..000000000 --- a/tests/arch/run-test.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -declare -A defines=( ["ice40"]="ICE40_HX ICE40_LP ICE40_U" ) - -echo "Running syntax check on arch sim models" -for arch in ../../techlibs/*; do - find $arch -name cells_sim.v | while read path; do - arch_name=$(basename -- $arch) - if [ "${defines[$arch_name]}" ]; then - for def in ${defines[$arch_name]}; do - echo -n "Test $path -D$def ->" - iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path >/dev/null 2>&1 - echo " ok" - done - else - echo -n "Test $path ->" - iverilog -t null -I$arch -g2005-sv $path >/dev/null 2>&1 - echo " ok" - fi - done -done - -for path in "../../techlibs/common/simcells.v" "../../techlibs/common/simlib.v"; do - echo -n "Test $path ->" - iverilog -t null $path >/dev/null 2>&1 - echo " ok" -done From f087a944707c40eaf1a2670a383d3d6dc64d61cf Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 12:31:45 +0100 Subject: [PATCH 086/176] Convert svinterfaces --- tests/Makefile | 2 +- tests/svinterfaces/generate_mk.py | 46 +++++++++++++++++++++++++++++++ tests/svinterfaces/run-test.sh | 9 ------ tests/svinterfaces/run_simple.sh | 15 ---------- tests/svinterfaces/runone.sh | 44 ----------------------------- 5 files changed, 47 insertions(+), 69 deletions(-) create mode 100644 tests/svinterfaces/generate_mk.py delete mode 100755 tests/svinterfaces/run-test.sh delete mode 100755 tests/svinterfaces/run_simple.sh delete mode 100755 tests/svinterfaces/runone.sh diff --git a/tests/Makefile b/tests/Makefile index 832bdc716..1e1c18092 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -62,7 +62,7 @@ MK_TEST_DIRS += ./opt_share MK_TEST_DIRS += ./fsm MK_TEST_DIRS += ./memlib MK_TEST_DIRS += ./bram -#SH_TEST_DIRS += ./svinterfaces +MK_TEST_DIRS += ./svinterfaces MK_TEST_DIRS += ./xprop MK_TEST_DIRS += ./select MK_TEST_DIRS += ./peepopt diff --git a/tests/svinterfaces/generate_mk.py b/tests/svinterfaces/generate_mk.py new file mode 100644 index 000000000..a9d0f4d0d --- /dev/null +++ b/tests/svinterfaces/generate_mk.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import glob +import sys +sys.path.append("..") + +import gen_tests_makefile + +runone_tests = [ + "svinterface1", + "svinterface_at_top" +] + +def run_one(): + for testname in runone_tests: + cmd_lines = [ + f'../../yosys -p "read_verilog -sv {testname}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', + f'../../yosys -p "read_verilog -sv {testname}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_ref_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', + f'rm -f a.out reference_result.txt dut_result.txt;', + f'iverilog -g2012 {testname}_syn.v >/dev/null 2>&1;', + f'iverilog -g2012 {testname}_ref_syn.v >/dev/null 2>&1;', + f'iverilog -g2012 {testname}_tb.v {testname}_ref_syn.v >/dev/null 2>&1;', + f'./a.out >/dev/null 2>&1;', + f'mv output.txt reference_result.txt;', + f'iverilog -g2012 {testname}_tb_wrapper.v {testname}_syn.v >/dev/null 2>&1;' if testname=="svinterface_at_top" else + f'iverilog -g2012 {testname}_tb.v {testname}_syn.v >/dev/null 2>&1;', + f'./a.out >/dev/null 2>&1;', + f'mv output.txt dut_result.txt;', + f'diff reference_result.txt dut_result.txt > {testname}.diff', + ] + gen_tests_makefile.generate_cmd_test(testname, cmd_lines) + +def run_simple(): + for f in sorted(glob.glob("*.ys")): + gen_tests_makefile.generate_ys_test(f) + +def main(): + def callback(): + run_one() + run_simple() + + gen_tests_makefile.generate_custom(callback) + +if __name__ == "__main__": + main() diff --git a/tests/svinterfaces/run-test.sh b/tests/svinterfaces/run-test.sh deleted file mode 100755 index 28ce627d9..000000000 --- a/tests/svinterfaces/run-test.sh +++ /dev/null @@ -1,9 +0,0 @@ -#/bin/bash -e -source ../common-env.sh - -./runone.sh svinterface1 -./runone.sh svinterface_at_top - -./run_simple.sh load_and_derive -./run_simple.sh resolve_types -./run_simple.sh positional_args diff --git a/tests/svinterfaces/run_simple.sh b/tests/svinterfaces/run_simple.sh deleted file mode 100755 index 5bf044373..000000000 --- a/tests/svinterfaces/run_simple.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -# Run a simple test with a .ys file - -if [ $# != 1 ]; then - echo >&2 "Expected 1 argument" - exit 1 -fi - -echo -n "Test: $1 ->" -../../yosys $1.ys >$1.log_stdout 2>$1.log_stderr || { - echo "ERROR!" - exit 1 -} -echo "ok" diff --git a/tests/svinterfaces/runone.sh b/tests/svinterfaces/runone.sh deleted file mode 100755 index 598517db9..000000000 --- a/tests/svinterfaces/runone.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - - -TESTNAME=$1 - -STDOUTFILE=${TESTNAME}.log_stdout -STDERRFILE=${TESTNAME}.log_stderr - -echo "" > $STDOUTFILE -echo "" > $STDERRFILE - -echo -n "Test: ${TESTNAME} -> " - -set -e - -$PWD/../../yosys -p "read_verilog -sv ${TESTNAME}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog ${TESTNAME}_syn.v" >> $STDOUTFILE 2>> $STDERRFILE -$PWD/../../yosys -p "read_verilog -sv ${TESTNAME}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog ${TESTNAME}_ref_syn.v" >> $STDOUTFILE 2>> $STDERRFILE - -rm -f a.out reference_result.txt dut_result.txt - -iverilog -g2012 ${TESTNAME}_syn.v >/dev/null 2>&1 -iverilog -g2012 ${TESTNAME}_ref_syn.v >/dev/null 2>&1 - -set +e -iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v >/dev/null 2>&1 -./a.out >/dev/null 2>&1 -mv output.txt reference_result.txt -if [ -f ${TESTNAME}_wrapper.v ] ; then - iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v >/dev/null 2>&1 -else - iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v >/dev/null 2>&1 -fi -./a.out >/dev/null 2>&1 -mv output.txt dut_result.txt - -diff reference_result.txt dut_result.txt > ${TESTNAME}.diff -RET=$? -if [ "$RET" != "0" ] ; then - echo "ERROR!" - exit -1 -fi - -echo "ok" -exit 0 From bfd639f6a02738f6fc48fa75bd9253cc5e12df06 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 12:32:09 +0100 Subject: [PATCH 087/176] Disable failing test for now --- tests/svinterfaces/generate_mk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/svinterfaces/generate_mk.py b/tests/svinterfaces/generate_mk.py index a9d0f4d0d..e27091e12 100644 --- a/tests/svinterfaces/generate_mk.py +++ b/tests/svinterfaces/generate_mk.py @@ -9,7 +9,7 @@ import gen_tests_makefile runone_tests = [ "svinterface1", - "svinterface_at_top" + #"svinterface_at_top" ] def run_one(): From 686267ea812c90291f7f856f8df23f563ca5302e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 12:53:43 +0100 Subject: [PATCH 088/176] Convert functional --- tests/Makefile | 23 +++++------------------ tests/functional/generate_mk.py | 11 +++++++++++ 2 files changed, 16 insertions(+), 18 deletions(-) create mode 100644 tests/functional/generate_mk.py diff --git a/tests/Makefile b/tests/Makefile index 1e1c18092..ecc5129a2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -49,9 +49,6 @@ MK_TEST_DIRS += ./verific endif endif MK_TEST_DIRS += ./verilog - -# Tests that don't generate .mk -SH_TEST_DIRS = MK_TEST_DIRS += ./simple MK_TEST_DIRS += ./simple_abc9 MK_TEST_DIRS += ./hana @@ -71,28 +68,18 @@ MK_TEST_DIRS += ./blif MK_TEST_DIRS += ./arch MK_TEST_DIRS += ./rpc MK_TEST_DIRS += ./memfile -#SH_TEST_DIRS += ./fmt +#MK_TEST_DIRS += ./fmt MK_TEST_DIRS += ./cxxrtl MK_TEST_DIRS += ./liberty -#ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -#SH_TEST_DIRS += ./functional -#endif - -# Tests that don't generate .mk and need special args +ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +MK_TEST_DIRS += ./functional +endif MK_TEST_DIRS += ./memories MK_TEST_DIRS += ./aiger MK_TEST_DIRS += ./alumacc all: vanilla-test -# seed-./ is a dummy string, not a directory -.PHONY: seed-tests -seed-tests: $(SH_TEST_DIRS:%=seed-./%) -.PHONY: seed-./% -seed-./%: %/run-test.sh - +cd $* && bash run-test.sh $(SEEDOPT) - +@echo "...passed tests in $*" - # makefile-./ is a dummy string, not a directory .PHONY: makefile-tests .SILENT: $(MK_TEST_DIRS:%=%/Makefile) @@ -109,7 +96,7 @@ makefile-./%: %/Makefile @$(MAKE) -C $* @echo "...passed tests in $*" -vanilla-test: makefile-tests seed-tests +vanilla-test: prep makefile-tests @echo "" @echo " Passed \"make vanilla-test\"." ifeq ($(ENABLE_VERIFIC),1) diff --git a/tests/functional/generate_mk.py b/tests/functional/generate_mk.py new file mode 100644 index 000000000..3d63d1fe9 --- /dev/null +++ b/tests/functional/generate_mk.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +def callback(): + gen_tests_makefile.generate_cmd_test("functional",f'pytest -v -m "not smt and not rkt" . "$$@"') + +gen_tests_makefile.generate_custom(callback) From 5ffa0b1dd71d1c5f8fef77997cfcdf758ab4fcb9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Mar 2026 12:54:40 +0100 Subject: [PATCH 089/176] Disabled some in fmt for now --- tests/Makefile | 2 +- tests/fmt/generate_mk.py | 26 +++++++------- tests/fmt/run-test.sh | 78 ---------------------------------------- 3 files changed, 14 insertions(+), 92 deletions(-) delete mode 100644 tests/fmt/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index ecc5129a2..cf46444f8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -68,7 +68,7 @@ MK_TEST_DIRS += ./blif MK_TEST_DIRS += ./arch MK_TEST_DIRS += ./rpc MK_TEST_DIRS += ./memfile -#MK_TEST_DIRS += ./fmt +MK_TEST_DIRS += ./fmt MK_TEST_DIRS += ./cxxrtl MK_TEST_DIRS += ./liberty ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py index 0ae06732b..04ed56c35 100644 --- a/tests/fmt/generate_mk.py +++ b/tests/fmt/generate_mk.py @@ -10,7 +10,7 @@ def cmd(lines): def initial_display(): gen_tests_makefile.generate_target("initial_display", cmd([ - "../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $$0}' >yosys-initial_display.log 2>&1", + f"$(YOSYS) -p \"read_verilog initial_display.v\" | awk \"/<<>>/,/<<>>/ {{print $$0}}\" >yosys-initial_display.log 2>&1", "iverilog -o iverilog-initial_display initial_display.v", "./iverilog-initial_display >iverilog-initial_display.log", "diff yosys-initial_display.log iverilog-initial_display.log", @@ -29,8 +29,8 @@ def always_display(): for name, defs in cases: gen_tests_makefile.generate_target(f"always_display_{name}", cmd([ - f"../../yosys -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v >/dev/null 2>&1", - f"../../yosys -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v >/dev/null 2>&1", f"diff yosys-always_display-{name}-1.v yosys-always_display-{name}-2.v", ])) @@ -49,8 +49,8 @@ def roundtrip(): for name, defs in cases: gen_tests_makefile.generate_target(f"roundtrip_{name}", cmd([ - f"../../yosys -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v >/dev/null 2>&1", - f"../../yosys -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v >/dev/null 2>&1", f"diff yosys-roundtrip-{name}-1.v yosys-roundtrip-{name}-2.v", f"iverilog {defs} -o iverilog-roundtrip-{name} roundtrip.v roundtrip_tb.v >/dev/null 2>&1", @@ -72,12 +72,12 @@ def cxxrtl(): for name in cases: gen_tests_makefile.generate_target(f"cxxrtl_{name}", cmd([ - f"../../yosys -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\" >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\" >/dev/null 2>&1", f"$${{CXX:-g++}} -std=c++11 -o yosys-{name} -I../../backends/cxxrtl/runtime {name}_tb.cc -lstdc++", f"./yosys-{name} 2>yosys-{name}.log", f"iverilog -o iverilog-{name} {name}.v {name}_tb.v >/dev/null 2>&1", - f"./iverilog-{name} | grep -v '\\$finish called' >iverilog-{name}.log", + f"./iverilog-{name} | grep -v \"$finish called\" >iverilog-{name}.log", f"diff iverilog-{name}.log yosys-{name}.log", ])) @@ -85,16 +85,16 @@ def cxxrtl(): def extra(): gen_tests_makefile.generate_target("always_full_equiv", cmd([ - "../../yosys -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v >/dev/null 2>&1", + "$(YOSYS) -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v >/dev/null 2>&1", "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v >/dev/null 2>&1", - "./iverilog-always_full-1 | grep -v '\\$finish called' >iverilog-always_full-1.log", + "./iverilog-always_full-1 | grep -v \"$finish called\" >iverilog-always_full-1.log", "diff iverilog-always_full.log iverilog-always_full-1.log", ])) gen_tests_makefile.generate_target("display_lm", cmd([ - "../../yosys -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", - "../../yosys -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\" >/dev/null 2>&1", - "$${CXX:-g++} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", + "$(YOSYS) -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", + "$(YOSYS) -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\" >/dev/null 2>&1", + f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", "./yosys-display_lm_cc >yosys-display_lm_cc.log", "for log in yosys-display_lm.log yosys-display_lm_cc.log; do " "grep \"^%l: \\\\bot\\$\" \"$log\" >/dev/null 2>&1; " @@ -109,7 +109,7 @@ def main(): always_display() roundtrip() cxxrtl() - extra() + #extra() gen_tests_makefile.generate_custom(callback) diff --git a/tests/fmt/run-test.sh b/tests/fmt/run-test.sh deleted file mode 100644 index 094f52a2f..000000000 --- a/tests/fmt/run-test.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -set -e - -../../yosys -p 'read_verilog initial_display.v' | awk '/<<>>/,/<<>>/ {print $0}' >yosys-initial_display.log 2>&1 -iverilog -o iverilog-initial_display initial_display.v -./iverilog-initial_display >iverilog-initial_display.log -diff yosys-initial_display.log iverilog-initial_display.log - -test_always_display () { - local subtest=$1; shift - ../../yosys -p "read_verilog $* always_display.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-1.v >/dev/null 2>&1 - ../../yosys -p "read_verilog yosys-always_display-${subtest}-1.v; proc; opt_expr -mux_bool; clean" -o yosys-always_display-${subtest}-2.v >/dev/null 2>&1 - diff yosys-always_display-${subtest}-1.v yosys-always_display-${subtest}-2.v -} - -test_always_display clk -DEVENT_CLK -test_always_display clk_rst -DEVENT_CLK_RST -test_always_display star -DEVENT_STAR - -test_always_display clk_en -DEVENT_CLK -DCOND_EN -test_always_display clk_rst_en -DEVENT_CLK_RST -DCOND_EN -test_always_display star_en -DEVENT_STAR -DCOND_EN - -test_roundtrip () { - local subtest=$1; shift - ../../yosys -p "read_verilog $* roundtrip.v; proc; clean" -o yosys-roundtrip-${subtest}-1.v >/dev/null 2>&1 - ../../yosys -p "read_verilog yosys-roundtrip-${subtest}-1.v; proc; clean" -o yosys-roundtrip-${subtest}-2.v >/dev/null 2>&1 - diff yosys-roundtrip-${subtest}-1.v yosys-roundtrip-${subtest}-2.v - - iverilog $* -o iverilog-roundtrip-${subtest} roundtrip.v roundtrip_tb.v >/dev/null 2>&1 - ./iverilog-roundtrip-${subtest} >iverilog-roundtrip-${subtest}.log - iverilog $* -o iverilog-roundtrip-${subtest}-1 yosys-roundtrip-${subtest}-1.v roundtrip_tb.v >/dev/null 2>&1 - ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-1.log - iverilog $* -o iverilog-roundtrip-${subtest}-2 yosys-roundtrip-${subtest}-2.v roundtrip_tb.v >/dev/null 2>&1 - ./iverilog-roundtrip-${subtest}-1 >iverilog-roundtrip-${subtest}-2.log - diff iverilog-roundtrip-${subtest}.log iverilog-roundtrip-${subtest}-1.log - diff iverilog-roundtrip-${subtest}-1.log iverilog-roundtrip-${subtest}-2.log -} - -test_roundtrip dec_unsigned -DBASE_DEC -DSIGN="" -test_roundtrip dec_signed -DBASE_DEC -DSIGN="signed" -test_roundtrip hex_unsigned -DBASE_HEX -DSIGN="" -test_roundtrip hex_signed -DBASE_HEX -DSIGN="signed" -test_roundtrip oct_unsigned -DBASE_HEX -DSIGN="" -test_roundtrip oct_signed -DBASE_HEX -DSIGN="signed" -test_roundtrip bin_unsigned -DBASE_HEX -DSIGN="" -test_roundtrip bin_signed -DBASE_HEX -DSIGN="signed" - -test_cxxrtl () { - local subtest=$1; shift - - ../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" >/dev/null 2>&1 - ${CXX:-g++} -std=c++11 -o yosys-${subtest} -I../../backends/cxxrtl/runtime ${subtest}_tb.cc -lstdc++ - ./yosys-${subtest} 2>yosys-${subtest}.log - iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v >/dev/null 2>&1 - ./iverilog-${subtest} |grep -v '\$finish called' >iverilog-${subtest}.log - diff iverilog-${subtest}.log yosys-${subtest}.log -} - -test_cxxrtl always_full -test_cxxrtl always_comb - -# Ensure Verilog backend preserves behaviour of always block with multiple $displays. -../../yosys -p "read_verilog always_full.v; prep; clean" -o yosys-always_full-1.v >/dev/null 2>&1 -iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v >/dev/null 2>&1 -./iverilog-always_full-1 |grep -v '\$finish called' >iverilog-always_full-1.log -diff iverilog-always_full.log iverilog-always_full-1.log - -../../yosys -p "read_verilog display_lm.v" >yosys-display_lm.log 2>&1 -../../yosys -p "read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc" >/dev/null 2>&1 -${CXX:-g++} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++ -./yosys-display_lm_cc >yosys-display_lm_cc.log -for log in yosys-display_lm.log yosys-display_lm_cc.log; do - grep "^%l: \\\\bot\$" "$log" >/dev/null 2>&1 - grep "^%m: \\\\bot\$" "$log" >/dev/null 2>&1 -done From 1aad357370f29ac8513618fbe0efe9a9b5be6839 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 25 Mar 2026 09:41:39 +0100 Subject: [PATCH 090/176] Fix some escaping with different approach --- tests/fmt/generate_mk.py | 20 ++++++++++---------- tests/gen_tests_makefile.py | 7 ++----- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py index 04ed56c35..e4b32f9e3 100644 --- a/tests/fmt/generate_mk.py +++ b/tests/fmt/generate_mk.py @@ -6,11 +6,11 @@ sys.path.append("..") import gen_tests_makefile def cmd(lines): - return " ; \\\n".join(lines) + return " && \\\n".join(lines) def initial_display(): gen_tests_makefile.generate_target("initial_display", cmd([ - f"$(YOSYS) -p \"read_verilog initial_display.v\" | awk \"/<<>>/,/<<>>/ {{print $$0}}\" >yosys-initial_display.log 2>&1", + f"$(YOSYS) -p \"read_verilog initial_display.v\" | awk '/<<>>/,/<<>>/ {{print $$0}}' >yosys-initial_display.log 2>&1", "iverilog -o iverilog-initial_display initial_display.v", "./iverilog-initial_display >iverilog-initial_display.log", "diff yosys-initial_display.log iverilog-initial_display.log", @@ -94,22 +94,22 @@ def extra(): gen_tests_makefile.generate_target("display_lm", cmd([ "$(YOSYS) -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", "$(YOSYS) -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\" >/dev/null 2>&1", - f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", - "./yosys-display_lm_cc >yosys-display_lm_cc.log", - "for log in yosys-display_lm.log yosys-display_lm_cc.log; do " - "grep \"^%l: \\\\bot\\$\" \"$log\" >/dev/null 2>&1; " - "grep \"^%m: \\\\bot\\$\" \"$log\" >/dev/null 2>&1; " - "done", + f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++ >/dev/null 2>&1", + "./yosys-display_lm_cc >yosys-display_lm_cc.log 2>/dev/null", + "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm.log\" >/dev/null 2>&1", + "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm.log\" >/dev/null 2>&1", + "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\" >/dev/null 2>&1", + "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\" >/dev/null 2>&1", ])) def main(): def callback(): - #initial_display() + initial_display() always_display() roundtrip() cxxrtl() - #extra() + extra() gen_tests_makefile.generate_custom(callback) diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 969a0f41a..b81855693 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -17,12 +17,9 @@ def generate_target(name, command): target = f"{name}" print(f"all: {target}") print(f".PHONY: {target}") + print(f"{target}_cmd={command}") print(f"{target}:") - if command: - print(f"\t@$(call run_test,{target}, \\") - print(f"\t{command})") - else: - print(f"\t@$(call run_test,{target})") + print(f"\t@$(call run_test,{target}, $({target}_cmd))") def generate_ys_test(ys_file, yosys_args="", commands=""): cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' From 9c3d79b04141abc38ccf1acc5ed558a41d037a60 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 25 Mar 2026 09:49:44 +0100 Subject: [PATCH 091/176] Cleanup --- tests/common-env.sh | 1 - tests/functional/run-test.sh | 6 ------ 2 files changed, 7 deletions(-) delete mode 100644 tests/common-env.sh delete mode 100755 tests/functional/run-test.sh diff --git a/tests/common-env.sh b/tests/common-env.sh deleted file mode 100644 index f3a411280..000000000 --- a/tests/common-env.sh +++ /dev/null @@ -1 +0,0 @@ -export YOSYS_MAX_THREADS=4 diff --git a/tests/functional/run-test.sh b/tests/functional/run-test.sh deleted file mode 100755 index 7c38f3190..000000000 --- a/tests/functional/run-test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh - -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) - -pytest -v -m "not smt and not rkt" "$SCRIPT_DIR" "$@" From a490f1c3c44d173309705dd97282692a48660272 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 25 Mar 2026 11:46:08 +0100 Subject: [PATCH 092/176] Move output redirect to one place --- tests/aiger/generate_mk.py | 6 +++--- tests/arch/generate_mk.py | 6 +++--- tests/bram/generate_mk.py | 2 +- tests/common.mk | 2 +- tests/cxxrtl/generate_mk.py | 4 ++-- tests/fmt/generate_mk.py | 36 +++++++++++++++---------------- tests/gen_tests_makefile.py | 8 +++---- tests/liberty/generate_mk.py | 4 ++-- tests/memfile/generate_mk.py | 33 ++++++++++++++-------------- tests/memlib/generate_mk.py | 2 +- tests/realmath/generate_mk.py | 4 ++-- tests/rpc/generate_mk.py | 2 +- tests/svinterfaces/generate_mk.py | 18 ++++++++-------- 13 files changed, 63 insertions(+), 64 deletions(-) diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py index 0e0200d6d..eecee82fa 100644 --- a/tests/aiger/generate_mk.py +++ b/tests/aiger/generate_mk.py @@ -25,7 +25,7 @@ def create_tests(): b = base(aag) cmd = [ - f"$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\" >/dev/null 2>&1;", + f"$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\";", "$(YOSYS) -qp \"", f"read_verilog {b}_ref.v;", "prep;", @@ -37,7 +37,7 @@ def create_tests(): "design -import gate -as gate;", "miter -equiv -flatten -make_assert -make_outputs gold gate miter;", "sat -verify -prove-asserts -show-ports -seq 16 miter;", - f"\" -l {aag}.log >/dev/null 2>&1" + f"\" -l {aag}.log" ] gen_tests_makefile.generate_cmd_test(aag, cmd) @@ -47,7 +47,7 @@ def create_tests(): gen_tests_makefile.generate_ys_test(ys) cmd = [ "rm -rf gate; mkdir gate;", - "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\" >/dev/null 2>&1;", + "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\";", "set -o pipefail; diff --brief gold gate | tee aigmap.err;", "rm -f aigmap.err" ] diff --git a/tests/arch/generate_mk.py b/tests/arch/generate_mk.py index 3ea1f1c44..4c12a497c 100644 --- a/tests/arch/generate_mk.py +++ b/tests/arch/generate_mk.py @@ -27,18 +27,18 @@ def archs(): if arch_name in defines: for defn in defines[arch_name]: target_name = f"{target_base}_{defn}" - cmd = f"iverilog -t null -I{arch} -D{defn} -DNO_ICE40_DEFAULT_ASSIGNMENTS {path_str} >/dev/null 2>&1" + cmd = f"iverilog -t null -I{arch} -D{defn} -DNO_ICE40_DEFAULT_ASSIGNMENTS {path_str}" gen_tests_makefile.generate_target(target_name, cmd) else: target_name = f"{target_base}" - cmd = f"iverilog -t null -I{arch} -g2005-sv {path_str} >/dev/null 2>&1" + cmd = f"iverilog -t null -I{arch} -g2005-sv {path_str}" gen_tests_makefile.generate_target(target_name, cmd) def common(): for path in ["../../techlibs/common/simcells.v", "../../techlibs/common/simlib.v"]: path_obj = Path(path) target_name = path_obj.stem - cmd = f"iverilog -t null {path} >/dev/null 2>&1" + cmd = f"iverilog -t null {path}" gen_tests_makefile.generate_target(target_name, cmd) def main(): diff --git a/tests/bram/generate_mk.py b/tests/bram/generate_mk.py index a18972703..09f5c650b 100644 --- a/tests/bram/generate_mk.py +++ b/tests/bram/generate_mk.py @@ -320,7 +320,7 @@ def create_tests(): if i != j: gen_tests_makefile.generate_cmd_test( f"bram_{i}_{j}", - f"bash run-single.sh {i} {j} >/dev/null 2>&1" + f"bash run-single.sh {i} {j}" ) gen_tests_makefile.generate_custom(create_tests) diff --git a/tests/common.mk b/tests/common.mk index 9d45e3762..044054e0c 100644 --- a/tests/common.mk +++ b/tests/common.mk @@ -8,7 +8,7 @@ endif define run_test @set -e; \ rc=0; \ - ( set -e; $(2) ) || rc=$$?; \ + ( set -e; $(2) ) >/dev/null 2>&1 || rc=$$?; \ if [ $$rc -eq 0 ]; then \ echo "PASS $1"; \ echo PASS > $1.result; \ diff --git a/tests/cxxrtl/generate_mk.py b/tests/cxxrtl/generate_mk.py index a23e08a43..fceeb5188 100644 --- a/tests/cxxrtl/generate_mk.py +++ b/tests/cxxrtl/generate_mk.py @@ -8,12 +8,12 @@ import gen_tests_makefile def run_subtest(name): gen_tests_makefile.generate_cmd_test(f"cxxrtl_{name}", [ f"$${{CXX:-g++}} -std=c++11 -O2 -o cxxrtl-test-{name} -I../../backends/cxxrtl/runtime test_{name}.cc -lstdc++;", - f"./cxxrtl-test-{name} >/dev/null 2>&1", + f"./cxxrtl-test-{name}", ]) def compile_only(): gen_tests_makefile.generate_cmd_test("cxxrtl_unconnected_output", [ - '$(YOSYS) -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc" >/dev/null 2>&1;', + '$(YOSYS) -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc";', f'$${{CXX:-g++}} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc', ]) diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py index e4b32f9e3..61f78c6af 100644 --- a/tests/fmt/generate_mk.py +++ b/tests/fmt/generate_mk.py @@ -29,8 +29,8 @@ def always_display(): for name, defs in cases: gen_tests_makefile.generate_target(f"always_display_{name}", cmd([ - f"$(YOSYS) -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v >/dev/null 2>&1", - f"$(YOSYS) -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v", + f"$(YOSYS) -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v", f"diff yosys-always_display-{name}-1.v yosys-always_display-{name}-2.v", ])) @@ -49,17 +49,17 @@ def roundtrip(): for name, defs in cases: gen_tests_makefile.generate_target(f"roundtrip_{name}", cmd([ - f"$(YOSYS) -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v >/dev/null 2>&1", - f"$(YOSYS) -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v", + f"$(YOSYS) -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v", f"diff yosys-roundtrip-{name}-1.v yosys-roundtrip-{name}-2.v", - f"iverilog {defs} -o iverilog-roundtrip-{name} roundtrip.v roundtrip_tb.v >/dev/null 2>&1", + f"iverilog {defs} -o iverilog-roundtrip-{name} roundtrip.v roundtrip_tb.v", f"./iverilog-roundtrip-{name} >iverilog-roundtrip-{name}.log", - f"iverilog {defs} -o iverilog-roundtrip-{name}-1 yosys-roundtrip-{name}-1.v roundtrip_tb.v >/dev/null 2>&1", + f"iverilog {defs} -o iverilog-roundtrip-{name}-1 yosys-roundtrip-{name}-1.v roundtrip_tb.v", f"./iverilog-roundtrip-{name}-1 >iverilog-roundtrip-{name}-1.log", - f"iverilog {defs} -o iverilog-roundtrip-{name}-2 yosys-roundtrip-{name}-2.v roundtrip_tb.v >/dev/null 2>&1", + f"iverilog {defs} -o iverilog-roundtrip-{name}-2 yosys-roundtrip-{name}-2.v roundtrip_tb.v", f"./iverilog-roundtrip-{name}-2 >iverilog-roundtrip-{name}-2.log", f"diff iverilog-roundtrip-{name}.log iverilog-roundtrip-{name}-1.log", @@ -72,11 +72,11 @@ def cxxrtl(): for name in cases: gen_tests_makefile.generate_target(f"cxxrtl_{name}", cmd([ - f"$(YOSYS) -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\" >/dev/null 2>&1", + f"$(YOSYS) -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\"", f"$${{CXX:-g++}} -std=c++11 -o yosys-{name} -I../../backends/cxxrtl/runtime {name}_tb.cc -lstdc++", f"./yosys-{name} 2>yosys-{name}.log", - f"iverilog -o iverilog-{name} {name}.v {name}_tb.v >/dev/null 2>&1", + f"iverilog -o iverilog-{name} {name}.v {name}_tb.v", f"./iverilog-{name} | grep -v \"$finish called\" >iverilog-{name}.log", f"diff iverilog-{name}.log yosys-{name}.log", @@ -85,21 +85,21 @@ def cxxrtl(): def extra(): gen_tests_makefile.generate_target("always_full_equiv", cmd([ - "$(YOSYS) -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v >/dev/null 2>&1", - "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v >/dev/null 2>&1", + "$(YOSYS) -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v", + "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v", "./iverilog-always_full-1 | grep -v \"$finish called\" >iverilog-always_full-1.log", "diff iverilog-always_full.log iverilog-always_full-1.log", ])) gen_tests_makefile.generate_target("display_lm", cmd([ "$(YOSYS) -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", - "$(YOSYS) -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\" >/dev/null 2>&1", - f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++ >/dev/null 2>&1", - "./yosys-display_lm_cc >yosys-display_lm_cc.log 2>/dev/null", - "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm.log\" >/dev/null 2>&1", - "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm.log\" >/dev/null 2>&1", - "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\" >/dev/null 2>&1", - "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\" >/dev/null 2>&1", + "$(YOSYS) -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\"", + f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", + "./yosys-display_lm_cc >yosys-display_lm_cc.log", + "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm.log\"", + "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm.log\"", + "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\"", + "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\"", ])) diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index b81855693..34b9aaedb 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -22,13 +22,13 @@ def generate_target(name, command): print(f"\t@$(call run_test,{target}, $({target}_cmd))") def generate_ys_test(ys_file, yosys_args="", commands=""): - cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} >/dev/null 2>&1 && mv {ys_file}.err {ys_file}.log' + cmd = f'$(YOSYS) -ql {ys_file}.err {yosys_args} {ys_file} && mv {ys_file}.err {ys_file}.log' if commands: cmd += f"; \\\n{commands}" generate_target(ys_file, cmd) def generate_tcl_test(tcl_file, yosys_args="", commands=""): - cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} >/dev/null 2>&1 && mv {tcl_file}.err {tcl_file}.log' + cmd = f'$(YOSYS) -ql {tcl_file}.err {yosys_args} {tcl_file} && mv {tcl_file}.err {tcl_file}.log' if commands: cmd += f"; \\\n{commands}" generate_target(tcl_file, cmd) @@ -37,7 +37,7 @@ def generate_sv_test(sv_file, yosys_args="", commands=""): base = os.path.splitext(sv_file)[0] if not os.path.exists(base + ".ys"): yosys_cmd = '-p "prep -top top; async2sync; sat -enable_undef -verify -prove-asserts"' - cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} >/dev/null 2>&1 && mv {sv_file}.err {sv_file}.log' + cmd = f'$(YOSYS) -ql {sv_file}.err {yosys_cmd} {yosys_args} {sv_file} && mv {sv_file}.err {sv_file}.log' if commands: cmd += f"; \\\n{commands}" generate_target(sv_file, cmd) @@ -121,7 +121,7 @@ def generate_custom(callback, extra=None): callback() def generate_autotest_file(test_file, commands): - cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file} >/dev/null 2>&1; \\\n{commands}" + cmd = f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} {test_file}; \\\n{commands}" generate_target(test_file, cmd) def generate_autotest(pattern, extra_flags, cmds=""): diff --git a/tests/liberty/generate_mk.py b/tests/liberty/generate_mk.py index 35bd9335b..64ceec873 100644 --- a/tests/liberty/generate_mk.py +++ b/tests/liberty/generate_mk.py @@ -14,14 +14,14 @@ def lib_tests(): gen_tests_makefile.generate_cmd_test(lib, [ f'$(YOSYS) -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty {lib}" -ql {base}.log;', - f'../../yosys-filterlib - {lib} 2>/dev/null > {lib}.filtered;', + f'../../yosys-filterlib - {lib} > {lib}.filtered;', f'../../yosys-filterlib -verilogsim {lib} > {lib}.verilogsim;', f'diff {lib}.filtered {lib}.filtered.ok;', f'diff {lib}.verilogsim {lib}.verilogsim.ok;', f'if [ -e {base}.log.ok ]; then ' - f'$(YOSYS) -p "dfflibmap -info -liberty {lib}" -TqqQl {base}.log >/dev/null 2>&1; ' + f'$(YOSYS) -p "dfflibmap -info -liberty {lib}" -TqqQl {base}.log; ' f'diff {base}.log {base}.log.ok; ' f'fi', ]) diff --git a/tests/memfile/generate_mk.py b/tests/memfile/generate_mk.py index a40f99ad0..1388961ab 100644 --- a/tests/memfile/generate_mk.py +++ b/tests/memfile/generate_mk.py @@ -10,60 +10,59 @@ def create_tests(): gen_tests_makefile.generate_cmd_test("parent_content1", [ f"{setup};", - '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', - 'chparam -set MEMFILE \\"content1.dat\\" memory") >/dev/null 2>&1', + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("parent_content2_temp", [ f"{setup};", - '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("parent_content2_full", [ f"{setup};", - '(cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', - 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory") >/dev/null 2>&1', + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', + 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("same_content1", [ f"{setup};", '$(YOSYS) -qp "read_verilog -defer memory.v;', - 'chparam -set MEMFILE \\"content1.dat\\" memory" >/dev/null 2>&1', + 'chparam -set MEMFILE \\"content1.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("same_content2", [ f"{setup};", '$(YOSYS) -qp "read_verilog -defer memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory" >/dev/null 2>&1', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("child_content1", [ f"{setup};", - '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', - 'chparam -set MEMFILE \\"content1.dat\\" memory") >/dev/null 2>&1', + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"content1.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("child_content2_temp", [ f"{setup};", - '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("child_content2_direct", [ f"{setup};", - '(cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory") >/dev/null 2>&1', + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', ]) gen_tests_makefile.generate_cmd_test("fail_empty_filename", - '! $(YOSYS) -qp "read_verilog memory.v" >/dev/null 2>&1') + '! $(YOSYS) -qp "read_verilog memory.v"') gen_tests_makefile.generate_cmd_test("fail_missing_file", [ '! $(YOSYS) -qp "read_verilog -defer memory.v;', - 'chparam -set MEMFILE \\"content3.dat\\" memory" >/dev/null 2>&1', + 'chparam -set MEMFILE \\"content3.dat\\" memory"', ]) extra = ["YOSYS_ABS := $(abspath $(YOSYS))"] gen_tests_makefile.generate_custom(create_tests, extra) - diff --git a/tests/memlib/generate_mk.py b/tests/memlib/generate_mk.py index e91580b7d..5f846a573 100644 --- a/tests/memlib/generate_mk.py +++ b/tests/memlib/generate_mk.py @@ -1577,7 +1577,7 @@ def create_tests(): f"../tools/autotest.sh -G -j ${{SEEDOPT}} ${{EXTRA_FLAGS}} " f"-p 'script ../t_{t.name}.ys'" f"{libs_args} " - f"t_{t.name}.v >/dev/null 2>&1 || (cat t_{t.name}.err; exit 1)" + f"t_{t.name}.v || (cat t_{t.name}.err; exit 1)" ) gen_tests_makefile.generate_target(t.name, cmd) diff --git a/tests/realmath/generate_mk.py b/tests/realmath/generate_mk.py index b56340335..98cb0f186 100644 --- a/tests/realmath/generate_mk.py +++ b/tests/realmath/generate_mk.py @@ -100,8 +100,8 @@ for idx in range(args.count): def create_tests(): for idx in range(args.count): cmd = [ - f"$(YOSYS) -qq uut_{idx:05d}.ys >/dev/null 2>&1 &&", - f"iverilog -o uut_{idx:05d}_tb uut_{idx:05d}_tb.v uut_{idx:05d}.v uut_{idx:05d}_syn.v >/dev/null 2>&1 &&", + f"$(YOSYS) -qq uut_{idx:05d}.ys &&", + f"iverilog -o uut_{idx:05d}_tb uut_{idx:05d}_tb.v uut_{idx:05d}.v uut_{idx:05d}_syn.v &&", f"./uut_{idx:05d}_tb" # f"./uut_{idx:05d}_tb | tee uut_{idx:05d}.err;", # f"if test -s uut_{idx:05d}.err; then", diff --git a/tests/rpc/generate_mk.py b/tests/rpc/generate_mk.py index 95ab05a7d..aca802ebe 100644 --- a/tests/rpc/generate_mk.py +++ b/tests/rpc/generate_mk.py @@ -11,7 +11,7 @@ def create_tests(): for ys in yss: gen_tests_makefile.generate_ys_test(ys) - cmd = [ "python3 frontend.py unix-socket frontend.sock >/dev/null 2>&1" ] + cmd = [ "python3 frontend.py unix-socket frontend.sock" ] gen_tests_makefile.generate_cmd_test("frontend.py", cmd) gen_tests_makefile.generate_custom(create_tests) diff --git a/tests/svinterfaces/generate_mk.py b/tests/svinterfaces/generate_mk.py index e27091e12..7ea337b2b 100644 --- a/tests/svinterfaces/generate_mk.py +++ b/tests/svinterfaces/generate_mk.py @@ -15,17 +15,17 @@ runone_tests = [ def run_one(): for testname in runone_tests: cmd_lines = [ - f'../../yosys -p "read_verilog -sv {testname}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', - f'../../yosys -p "read_verilog -sv {testname}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_ref_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', + f'$(YOSYS) -p "read_verilog -sv {testname}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', + f'$(YOSYS) -p "read_verilog -sv {testname}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_ref_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', f'rm -f a.out reference_result.txt dut_result.txt;', - f'iverilog -g2012 {testname}_syn.v >/dev/null 2>&1;', - f'iverilog -g2012 {testname}_ref_syn.v >/dev/null 2>&1;', - f'iverilog -g2012 {testname}_tb.v {testname}_ref_syn.v >/dev/null 2>&1;', - f'./a.out >/dev/null 2>&1;', + f'iverilog -g2012 {testname}_syn.v;', + f'iverilog -g2012 {testname}_ref_syn.v;', + f'iverilog -g2012 {testname}_tb.v {testname}_ref_syn.v;', + f'./a.out;', f'mv output.txt reference_result.txt;', - f'iverilog -g2012 {testname}_tb_wrapper.v {testname}_syn.v >/dev/null 2>&1;' if testname=="svinterface_at_top" else - f'iverilog -g2012 {testname}_tb.v {testname}_syn.v >/dev/null 2>&1;', - f'./a.out >/dev/null 2>&1;', + f'iverilog -g2012 {testname}_tb_wrapper.v {testname}_syn.v;' if testname=="svinterface_at_top" else + f'iverilog -g2012 {testname}_tb.v {testname}_syn.v;', + f'./a.out;', f'mv output.txt dut_result.txt;', f'diff reference_result.txt dut_result.txt > {testname}.diff', ] From 8bed9bd824a96a7d3202ff8eb1447bc523660684 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 25 Mar 2026 11:48:54 +0100 Subject: [PATCH 093/176] Use this for now so we can see actual output of functional tests --- tests/Makefile | 14 ++++++++++---- tests/functional/run-test.sh | 4 ++++ 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100755 tests/functional/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index cf46444f8..077f11c41 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -71,9 +71,9 @@ MK_TEST_DIRS += ./memfile MK_TEST_DIRS += ./fmt MK_TEST_DIRS += ./cxxrtl MK_TEST_DIRS += ./liberty -ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) -MK_TEST_DIRS += ./functional -endif +#ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +#MK_TEST_DIRS += ./functional +#endif MK_TEST_DIRS += ./memories MK_TEST_DIRS += ./aiger MK_TEST_DIRS += ./alumacc @@ -96,7 +96,13 @@ makefile-./%: %/Makefile @$(MAKE) -C $* @echo "...passed tests in $*" -vanilla-test: prep makefile-tests +.PHONY: functional +functional: +ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) + @cd functional && ./run-test.sh +endif + +vanilla-test: prep makefile-tests functional @echo "" @echo " Passed \"make vanilla-test\"." ifeq ($(ENABLE_VERIFIC),1) diff --git a/tests/functional/run-test.sh b/tests/functional/run-test.sh new file mode 100755 index 000000000..8f72f7c1b --- /dev/null +++ b/tests/functional/run-test.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +pytest -v -m "not smt and not rkt" "$SCRIPT_DIR" "$@" From f04532bbac7f182412c121944c1616abd953083b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 25 Mar 2026 11:59:33 +0100 Subject: [PATCH 094/176] Try to make it more stable --- tests/fmt/generate_mk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py index 61f78c6af..821ad289a 100644 --- a/tests/fmt/generate_mk.py +++ b/tests/fmt/generate_mk.py @@ -87,7 +87,8 @@ def extra(): gen_tests_makefile.generate_target("always_full_equiv", cmd([ "$(YOSYS) -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v", "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v", - "./iverilog-always_full-1 | grep -v \"$finish called\" >iverilog-always_full-1.log", + "./iverilog-always_full-1 > tmp.log", + "grep -v '\\$finish called' tmp.log > iverilog-always_full-1.log", "diff iverilog-always_full.log iverilog-always_full-1.log", ])) From bfd3e150fa66a0645ac39a1ee08dc63b6e602bc9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 25 Mar 2026 13:22:47 +0100 Subject: [PATCH 095/176] Add proper deps --- tests/fmt/generate_mk.py | 2 +- tests/gen_tests_makefile.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py index 821ad289a..8c8bfbd6e 100644 --- a/tests/fmt/generate_mk.py +++ b/tests/fmt/generate_mk.py @@ -90,7 +90,7 @@ def extra(): "./iverilog-always_full-1 > tmp.log", "grep -v '\\$finish called' tmp.log > iverilog-always_full-1.log", "diff iverilog-always_full.log iverilog-always_full-1.log", - ])) + ]), deps=["cxxrtl_always_full"]) gen_tests_makefile.generate_target("display_lm", cmd([ "$(YOSYS) -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 34b9aaedb..55f351211 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -12,13 +12,17 @@ common_mk = os.path.relpath(os.path.join(os.path.dirname(__file__), "common.mk") def _cwd_base(): return os.path.basename(os.getcwd()) -def generate_target(name, command): +def generate_target(name, command, deps = None): #target = f"{_cwd_base()}-{name}" target = f"{name}" print(f"all: {target}") print(f".PHONY: {target}") print(f"{target}_cmd={command}") - print(f"{target}:") + if deps: + print(f"{target}: {' '.join(deps)}") + else: + print(f"{target}:") + print(f"\t@$(call run_test,{target}, $({target}_cmd))") def generate_ys_test(ys_file, yosys_args="", commands=""): From 76732497b9b5f461cb7b06d7f8402edae427e935 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 26 Mar 2026 08:14:16 +0100 Subject: [PATCH 096/176] Cleanup --- tests/aiger/generate_mk.py | 21 +++++++------ tests/cxxrtl/generate_mk.py | 4 +-- tests/fmt/generate_mk.py | 27 +++++++--------- tests/gen_tests_makefile.py | 6 ++-- tests/liberty/generate_mk.py | 13 ++++---- tests/memfile/generate_mk.py | 52 +++++++++++++++---------------- tests/realmath/generate_mk.py | 4 +-- tests/svinterfaces/generate_mk.py | 24 +++++++------- 8 files changed, 75 insertions(+), 76 deletions(-) diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py index eecee82fa..6c27455b9 100644 --- a/tests/aiger/generate_mk.py +++ b/tests/aiger/generate_mk.py @@ -11,6 +11,9 @@ import os def base(fn): return os.path.splitext(fn)[0] +def cmd(lines): + return " \\\n".join(lines) + # NB: *.aag and *.aig must contain a symbol table naming the primary # inputs and outputs, otherwise ABC and Yosys will name them # arbitrarily (and inconsistently with each other). @@ -24,7 +27,7 @@ def create_tests(): for aag in aags: b = base(aag) - cmd = [ + gen_tests_makefile.generate_target(aag, cmd([ f"$(ABC) -q \"read -c {b}.aig; write {b}_ref.v\";", "$(YOSYS) -qp \"", f"read_verilog {b}_ref.v;", @@ -38,20 +41,18 @@ def create_tests(): "miter -equiv -flatten -make_assert -make_outputs gold gate miter;", "sat -verify -prove-asserts -show-ports -seq 16 miter;", f"\" -l {aag}.log" - ] - - gen_tests_makefile.generate_cmd_test(aag, cmd) + ])) # ---- Yosys script tests ---- for ys in yss: gen_tests_makefile.generate_ys_test(ys) - cmd = [ "rm -rf gate; mkdir gate;", - "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\";", - "set -o pipefail; diff --brief gold gate | tee aigmap.err;", - "rm -f aigmap.err" ] - - gen_tests_makefile.generate_cmd_test("aigmap", cmd) + gen_tests_makefile.generate_target("aigmap", cmd([ + "rm -rf gate; mkdir gate;", + "$(YOSYS) --no-version -p \"test_cell -aigmap -w gate/ -n 1 -s 1 all\";", + "set -o pipefail; diff --brief gold gate | tee aigmap.err;", + "rm -f aigmap.err" + ])) extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc", "SHELL := /bin/bash" ] diff --git a/tests/cxxrtl/generate_mk.py b/tests/cxxrtl/generate_mk.py index fceeb5188..b75c78e97 100644 --- a/tests/cxxrtl/generate_mk.py +++ b/tests/cxxrtl/generate_mk.py @@ -7,13 +7,13 @@ import gen_tests_makefile def run_subtest(name): gen_tests_makefile.generate_cmd_test(f"cxxrtl_{name}", [ - f"$${{CXX:-g++}} -std=c++11 -O2 -o cxxrtl-test-{name} -I../../backends/cxxrtl/runtime test_{name}.cc -lstdc++;", + f"$${{CXX:-g++}} -std=c++11 -O2 -o cxxrtl-test-{name} -I../../backends/cxxrtl/runtime test_{name}.cc -lstdc++", f"./cxxrtl-test-{name}", ]) def compile_only(): gen_tests_makefile.generate_cmd_test("cxxrtl_unconnected_output", [ - '$(YOSYS) -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc";', + '$(YOSYS) -p "read_verilog test_unconnected_output.v; select =*; proc; clean; write_cxxrtl cxxrtl-test-unconnected_output.cc"', f'$${{CXX:-g++}} -std=c++11 -c -o cxxrtl-test-unconnected_output -I../../backends/cxxrtl/runtime cxxrtl-test-unconnected_output.cc', ]) diff --git a/tests/fmt/generate_mk.py b/tests/fmt/generate_mk.py index 8c8bfbd6e..2e94d4500 100644 --- a/tests/fmt/generate_mk.py +++ b/tests/fmt/generate_mk.py @@ -5,16 +5,13 @@ sys.path.append("..") import gen_tests_makefile -def cmd(lines): - return " && \\\n".join(lines) - def initial_display(): - gen_tests_makefile.generate_target("initial_display", cmd([ + gen_tests_makefile.generate_cmd_test("initial_display", [ f"$(YOSYS) -p \"read_verilog initial_display.v\" | awk '/<<>>/,/<<>>/ {{print $$0}}' >yosys-initial_display.log 2>&1", "iverilog -o iverilog-initial_display initial_display.v", "./iverilog-initial_display >iverilog-initial_display.log", "diff yosys-initial_display.log iverilog-initial_display.log", - ])) + ]) def always_display(): @@ -28,11 +25,11 @@ def always_display(): ] for name, defs in cases: - gen_tests_makefile.generate_target(f"always_display_{name}", cmd([ + gen_tests_makefile.generate_cmd_test(f"always_display_{name}", [ f"$(YOSYS) -p \"read_verilog {defs} always_display.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-1.v", f"$(YOSYS) -p \"read_verilog yosys-always_display-{name}-1.v; proc; opt_expr -mux_bool; clean\" -o yosys-always_display-{name}-2.v", f"diff yosys-always_display-{name}-1.v yosys-always_display-{name}-2.v", - ])) + ]) def roundtrip(): @@ -48,7 +45,7 @@ def roundtrip(): ] for name, defs in cases: - gen_tests_makefile.generate_target(f"roundtrip_{name}", cmd([ + gen_tests_makefile.generate_cmd_test(f"roundtrip_{name}", [ f"$(YOSYS) -p \"read_verilog {defs} roundtrip.v; proc; clean\" -o yosys-roundtrip-{name}-1.v", f"$(YOSYS) -p \"read_verilog yosys-roundtrip-{name}-1.v; proc; clean\" -o yosys-roundtrip-{name}-2.v", f"diff yosys-roundtrip-{name}-1.v yosys-roundtrip-{name}-2.v", @@ -64,14 +61,14 @@ def roundtrip(): f"diff iverilog-roundtrip-{name}.log iverilog-roundtrip-{name}-1.log", f"diff iverilog-roundtrip-{name}-1.log iverilog-roundtrip-{name}-2.log", - ])) + ]) def cxxrtl(): cases = ["always_full", "always_comb"] for name in cases: - gen_tests_makefile.generate_target(f"cxxrtl_{name}", cmd([ + gen_tests_makefile.generate_cmd_test(f"cxxrtl_{name}", [ f"$(YOSYS) -p \"read_verilog {name}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-{name}.cc\"", f"$${{CXX:-g++}} -std=c++11 -o yosys-{name} -I../../backends/cxxrtl/runtime {name}_tb.cc -lstdc++", f"./yosys-{name} 2>yosys-{name}.log", @@ -80,19 +77,19 @@ def cxxrtl(): f"./iverilog-{name} | grep -v \"$finish called\" >iverilog-{name}.log", f"diff iverilog-{name}.log yosys-{name}.log", - ])) + ]) def extra(): - gen_tests_makefile.generate_target("always_full_equiv", cmd([ + gen_tests_makefile.generate_cmd_test("always_full_equiv", [ "$(YOSYS) -p \"read_verilog always_full.v; prep; clean\" -o yosys-always_full-1.v", "iverilog -o iverilog-always_full-1 yosys-always_full-1.v always_full_tb.v", "./iverilog-always_full-1 > tmp.log", "grep -v '\\$finish called' tmp.log > iverilog-always_full-1.log", "diff iverilog-always_full.log iverilog-always_full-1.log", - ]), deps=["cxxrtl_always_full"]) + ], deps=["cxxrtl_always_full"]) - gen_tests_makefile.generate_target("display_lm", cmd([ + gen_tests_makefile.generate_cmd_test("display_lm", [ "$(YOSYS) -p \"read_verilog display_lm.v\" >yosys-display_lm.log 2>&1", "$(YOSYS) -p \"read_verilog display_lm.v; write_cxxrtl yosys-display_lm.cc\"", f"$${{CXX:-g++}} -std=c++11 -o yosys-display_lm_cc -I../../backends/cxxrtl/runtime display_lm_tb.cc -lstdc++", @@ -101,7 +98,7 @@ def extra(): "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm.log\"", "grep \"^%l: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\"", "grep \"^%m: \\\\\\bot\\$$\" \"yosys-display_lm_cc.log\"", - ])) + ]) def main(): diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 55f351211..38596f63b 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -56,11 +56,11 @@ def unpack_cmd(cmd): if isinstance(cmd, str): return cmd if isinstance(cmd, (list, tuple)): - return " \\\n".join(cmd) + return " && \\\n".join(cmd) raise TypeError("cmd must be a string or a list/tuple of strings") -def generate_cmd_test(test_name, cmd, yosys_args=""): - generate_target(test_name, unpack_cmd(cmd)) +def generate_cmd_test(test_name, cmd, yosys_args="", deps = None): + generate_target(test_name, unpack_cmd(cmd), deps) def generate_tests(argv, cmds): parser = argparse.ArgumentParser(add_help=False) diff --git a/tests/liberty/generate_mk.py b/tests/liberty/generate_mk.py index 64ceec873..b2559cced 100644 --- a/tests/liberty/generate_mk.py +++ b/tests/liberty/generate_mk.py @@ -12,13 +12,13 @@ def lib_tests(): base = os.path.splitext(lib)[0] gen_tests_makefile.generate_cmd_test(lib, [ - f'$(YOSYS) -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty {lib}" -ql {base}.log;', + f'$(YOSYS) -p "read_verilog small.v; synth -top small; dfflibmap -info -liberty {lib}" -ql {base}.log', - f'../../yosys-filterlib - {lib} > {lib}.filtered;', - f'../../yosys-filterlib -verilogsim {lib} > {lib}.verilogsim;', + f'$(YOSYS_FILTERLIB) - {lib} > {lib}.filtered', + f'$(YOSYS_FILTERLIB) -verilogsim {lib} > {lib}.verilogsim', - f'diff {lib}.filtered {lib}.filtered.ok;', - f'diff {lib}.verilogsim {lib}.verilogsim.ok;', + f'diff {lib}.filtered {lib}.filtered.ok', + f'diff {lib}.verilogsim {lib}.verilogsim.ok', f'if [ -e {base}.log.ok ]; then ' f'$(YOSYS) -p "dfflibmap -info -liberty {lib}" -TqqQl {base}.log; ' @@ -36,7 +36,8 @@ def main(): lib_tests() ys_tests() - gen_tests_makefile.generate_custom(callback) + gen_tests_makefile.generate_custom(callback, + [f"YOSYS_FILTERLIB ?= {gen_tests_makefile.yosys_basedir}/yosys-filterlib"]) if __name__ == "__main__": diff --git a/tests/memfile/generate_mk.py b/tests/memfile/generate_mk.py index 1388961ab..e6351bc51 100644 --- a/tests/memfile/generate_mk.py +++ b/tests/memfile/generate_mk.py @@ -9,59 +9,59 @@ def create_tests(): setup = "mkdir -p temp && cp content1.dat temp/content2.dat" gen_tests_makefile.generate_cmd_test("parent_content1", [ - f"{setup};", - 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', - 'chparam -set MEMFILE \\"content1.dat\\" memory"', + f"{setup}", + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v; ' + 'chparam -set MEMFILE \\"content1.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("parent_content2_temp", [ - f"{setup};", - 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', + f"{setup}", + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("parent_content2_full", [ - f"{setup};", - 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v;', - 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory"', + f"{setup}", + 'cd .. && $(YOSYS_ABS) -qp "read_verilog -defer memfile/memory.v; ' + 'chparam -set MEMFILE \\"memfile/temp/content2.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("same_content1", [ - f"{setup};", - '$(YOSYS) -qp "read_verilog -defer memory.v;', - 'chparam -set MEMFILE \\"content1.dat\\" memory"', + f"{setup}", + '$(YOSYS) -qp "read_verilog -defer memory.v; ' + 'chparam -set MEMFILE \\"content1.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("same_content2", [ - f"{setup};", - '$(YOSYS) -qp "read_verilog -defer memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', + f"{setup}", + '$(YOSYS) -qp "read_verilog -defer memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("child_content1", [ - f"{setup};", - 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', - 'chparam -set MEMFILE \\"content1.dat\\" memory"', + f"{setup}", + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' + 'chparam -set MEMFILE \\"content1.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("child_content2_temp", [ - f"{setup};", - 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', + f"{setup}", + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("child_content2_direct", [ - f"{setup};", - 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v;', - 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"', + f"{setup}", + 'cd temp && ../$(YOSYS) -qp "read_verilog -defer ../memory.v; ' + 'chparam -set MEMFILE \\"temp/content2.dat\\" memory"' ]) gen_tests_makefile.generate_cmd_test("fail_empty_filename", '! $(YOSYS) -qp "read_verilog memory.v"') gen_tests_makefile.generate_cmd_test("fail_missing_file", [ - '! $(YOSYS) -qp "read_verilog -defer memory.v;', - 'chparam -set MEMFILE \\"content3.dat\\" memory"', + '! $(YOSYS) -qp "read_verilog -defer memory.v; ' + 'chparam -set MEMFILE \\"content3.dat\\" memory"' ]) extra = ["YOSYS_ABS := $(abspath $(YOSYS))"] diff --git a/tests/realmath/generate_mk.py b/tests/realmath/generate_mk.py index 98cb0f186..bee55816e 100644 --- a/tests/realmath/generate_mk.py +++ b/tests/realmath/generate_mk.py @@ -100,8 +100,8 @@ for idx in range(args.count): def create_tests(): for idx in range(args.count): cmd = [ - f"$(YOSYS) -qq uut_{idx:05d}.ys &&", - f"iverilog -o uut_{idx:05d}_tb uut_{idx:05d}_tb.v uut_{idx:05d}.v uut_{idx:05d}_syn.v &&", + f"$(YOSYS) -qq uut_{idx:05d}.ys", + f"iverilog -o uut_{idx:05d}_tb uut_{idx:05d}_tb.v uut_{idx:05d}.v uut_{idx:05d}_syn.v", f"./uut_{idx:05d}_tb" # f"./uut_{idx:05d}_tb | tee uut_{idx:05d}.err;", # f"if test -s uut_{idx:05d}.err; then", diff --git a/tests/svinterfaces/generate_mk.py b/tests/svinterfaces/generate_mk.py index 7ea337b2b..4703e9c9e 100644 --- a/tests/svinterfaces/generate_mk.py +++ b/tests/svinterfaces/generate_mk.py @@ -15,18 +15,18 @@ runone_tests = [ def run_one(): for testname in runone_tests: cmd_lines = [ - f'$(YOSYS) -p "read_verilog -sv {testname}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', - f'$(YOSYS) -p "read_verilog -sv {testname}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_ref_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr;', - f'rm -f a.out reference_result.txt dut_result.txt;', - f'iverilog -g2012 {testname}_syn.v;', - f'iverilog -g2012 {testname}_ref_syn.v;', - f'iverilog -g2012 {testname}_tb.v {testname}_ref_syn.v;', - f'./a.out;', - f'mv output.txt reference_result.txt;', - f'iverilog -g2012 {testname}_tb_wrapper.v {testname}_syn.v;' if testname=="svinterface_at_top" else - f'iverilog -g2012 {testname}_tb.v {testname}_syn.v;', - f'./a.out;', - f'mv output.txt dut_result.txt;', + f'$(YOSYS) -p "read_verilog -sv {testname}.sv ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr', + f'$(YOSYS) -p "read_verilog -sv {testname}_ref.v ; hierarchy -check -top TopModule ; synth ; write_verilog {testname}_ref_syn.v" >> {testname}.log_stdout 2>> {testname}.log_stderr', + f'rm -f a.out reference_result.txt dut_result.txt', + f'iverilog -g2012 {testname}_syn.v', + f'iverilog -g2012 {testname}_ref_syn.v', + f'iverilog -g2012 {testname}_tb.v {testname}_ref_syn.v', + f'./a.out', + f'mv output.txt reference_result.txt', + f'iverilog -g2012 {testname}_tb_wrapper.v {testname}_syn.v' if testname=="svinterface_at_top" else + f'iverilog -g2012 {testname}_tb.v {testname}_syn.v', + f'./a.out', + f'mv output.txt dut_result.txt', f'diff reference_result.txt dut_result.txt > {testname}.diff', ] gen_tests_makefile.generate_cmd_test(testname, cmd_lines) From 5737d2db35dfbade675a1ac7c24b75e6540bb60c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 26 Mar 2026 08:24:06 +0100 Subject: [PATCH 097/176] Cleanup --- tests/arch/fabulous/fsm.ys | 2 +- tests/blif/generate_mk.py | 2 +- tests/memories/generate_mk.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/arch/fabulous/fsm.ys b/tests/arch/fabulous/fsm.ys index 15fd19247..5f7ae28dd 100644 --- a/tests/arch/fabulous/fsm.ys +++ b/tests/arch/fabulous/fsm.ys @@ -11,7 +11,7 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd fsm # Constrain all select calls below inside the top module -stat + select -assert-count 6 t:LUTFF select -assert-max 5 t:LUT2 select -assert-max 4 t:LUT3 diff --git a/tests/blif/generate_mk.py b/tests/blif/generate_mk.py index 96aa6be79..6a921d5a0 100644 --- a/tests/blif/generate_mk.py +++ b/tests/blif/generate_mk.py @@ -5,4 +5,4 @@ sys.path.append("..") import gen_tests_makefile -gen_tests_makefile.generate(["--yosys-scripts"]) \ No newline at end of file +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/memories/generate_mk.py b/tests/memories/generate_mk.py index 0df27bc5e..cfb29acb9 100644 --- a/tests/memories/generate_mk.py +++ b/tests/memories/generate_mk.py @@ -55,4 +55,4 @@ gen_tests_makefile.generate_autotest("*.v", "", if grep -q expect-no-rd-clk $@; then \\ grep -Fq "connect \\\\RD_CLK 1'x" $(@:.v=).dmp || { echo " ERROR: Expected no read clock."; exit 1; }; \\ fi; \\ -fi""") \ No newline at end of file +fi""") From a66671268776d92232e6bde671666d93164af105 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 16 Apr 2026 11:04:14 +0200 Subject: [PATCH 098/176] Update arith_tree tests --- tests/Makefile | 1 + tests/arith_tree/generate_mk.py | 8 ++++++++ tests/arith_tree/run-test.sh | 7 ------- 3 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 tests/arith_tree/generate_mk.py delete mode 100755 tests/arith_tree/run-test.sh diff --git a/tests/Makefile b/tests/Makefile index 077f11c41..794e99c46 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -49,6 +49,7 @@ MK_TEST_DIRS += ./verific endif endif MK_TEST_DIRS += ./verilog +MK_TEST_DIRS += ./arith_tree MK_TEST_DIRS += ./simple MK_TEST_DIRS += ./simple_abc9 MK_TEST_DIRS += ./hana diff --git a/tests/arith_tree/generate_mk.py b/tests/arith_tree/generate_mk.py new file mode 100644 index 000000000..6a921d5a0 --- /dev/null +++ b/tests/arith_tree/generate_mk.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +import sys +sys.path.append("..") + +import gen_tests_makefile + +gen_tests_makefile.generate(["--yosys-scripts"]) diff --git a/tests/arith_tree/run-test.sh b/tests/arith_tree/run-test.sh deleted file mode 100755 index 2e3f5235c..000000000 --- a/tests/arith_tree/run-test.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash -source ../common-env.sh -set -e -for x in *.ys; do - echo "Running $x.." - ../../yosys -ql ${x%.ys}.log $x -done From b4c081c70b6b34ea131563fa89277be2be7e5639 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 17 Apr 2026 13:35:47 +0200 Subject: [PATCH 099/176] abc: fix deferred logs --- passes/techmap/abc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index d58f6b355..8e333f7cb 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1349,7 +1349,7 @@ void RunAbcState::run(ConcurrentStack &) logs.log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n", count_gates, GetSize(signal_list), count_input, count_output); if (count_output == 0) { - log("Don't call ABC as there is nothing to map.\n"); + logs.log("Don't call ABC as there is nothing to map.\n"); return; } int ret; @@ -1363,7 +1363,7 @@ void RunAbcState::run(ConcurrentStack &) string temp_stdouterr_name = stringf("%s/stdouterr.txt", per_run_tempdir_name); FILE *temp_stdouterr_w = fopen(temp_stdouterr_name.c_str(), "w"); if (temp_stdouterr_w == NULL) - log_error("ABC: cannot open a temporary file for output redirection"); + logs.log_error("ABC: cannot open a temporary file for output redirection"); fflush(stdout); fflush(stderr); FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering From aba5b279c6ea3c7ef0867f43d2f7d8dc23d9f440 Mon Sep 17 00:00:00 2001 From: George Haworth Date: Fri, 17 Apr 2026 02:10:05 +0300 Subject: [PATCH 100/176] Fix RAMB36E1/E2 SDP parity port mapping typo DIPBDIP/DINPBDINP condition checked PORT_W_WIDTH == 71, which never matches any valid SDP width. Should be 72, matching the DIBDI/DINBDIN condition on the line above. This caused data bits 68-69 to be silently overwritten with copies of bits 64-65 on every write. Affects both xc6v (RAMB36E1, Artix-7/Kintex-7/Virtex-7) and xcu (RAMB36E2, UltraScale/UltraScale+) mapping templates. The RAMB18E1/E2 equivalents correctly use == 36. --- techlibs/xilinx/brams_xc6v_map.v | 2 +- techlibs/xilinx/brams_xcu_map.v | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/techlibs/xilinx/brams_xc6v_map.v b/techlibs/xilinx/brams_xc6v_map.v index b2698a3aa..dfd6dfc9e 100644 --- a/techlibs/xilinx/brams_xc6v_map.v +++ b/techlibs/xilinx/brams_xc6v_map.v @@ -275,7 +275,7 @@ end else if (OPTION_MODE == "FULL") begin .DIADI(DI[31:0]), .DIBDI(PORT_W_WIDTH == 72 ? DI[63:32] : DI[31:0]), .DIPADIP(DIP[3:0]), - .DIPBDIP(PORT_W_WIDTH == 71 ? DIP[7:4] : DIP[3:0]), + .DIPBDIP(PORT_W_WIDTH == 72 ? DIP[7:4] : DIP[3:0]), ); end diff --git a/techlibs/xilinx/brams_xcu_map.v b/techlibs/xilinx/brams_xcu_map.v index d48c21a59..01ee8a953 100644 --- a/techlibs/xilinx/brams_xcu_map.v +++ b/techlibs/xilinx/brams_xcu_map.v @@ -215,7 +215,7 @@ end else if (OPTION_MODE == "FULL") begin .DINADIN(DI[31:0]), .DINBDIN(PORT_W_WIDTH == 72 ? DI[63:32] : DI[31:0]), .DINPADINP(DIP[3:0]), - .DINPBDINP(PORT_W_WIDTH == 71 ? DIP[7:4] : DIP[3:0]), + .DINPBDINP(PORT_W_WIDTH == 72 ? DIP[7:4] : DIP[3:0]), ); end From 89d360aa4ab9cb56e2d81542c5957eb6fcb15055 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Sun, 19 Apr 2026 06:21:50 +0200 Subject: [PATCH 101/176] Rewrote Linux edition of proc_self_dirname() to handle any symlink length. This make sure the method work also when the program is located in deep or long file paths, longer than both PATH_MAX and "getconf PATH_MAX .". Use the same code on GNU Hurd, where it now work. I am not sure how to test this in a platform independent way. --- kernel/yosys.cc | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 29fcd48d8..b3688b77b 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -471,17 +471,30 @@ struct TclPass : public Pass { #endif -#if defined(__linux__) || defined(__CYGWIN__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(__gnu_hurd__) std::string proc_self_dirname() { - char path[PATH_MAX]; - ssize_t buflen = readlink("/proc/self/exe", path, sizeof(path)); + std::string path(4096, '\0'); + ssize_t buflen = -1; + // Double until sucess, while avoiding endless loop. Give up + // when symlink is longer than 4096*(2^30) = 4398046511104 + // bytes. + for (int tries = 30; 0 < tries; tries--) { + buflen = readlink("/proc/self/exe", path.data(), path.size()); + if (buflen < (ssize_t)path.size()) + break; + else + path.resize(path.size() * 2); + } if (buflen < 0) { log_error("readlink(\"/proc/self/exe\") failed: %s\n", strerror(errno)); + path.resize(0); + } else { + while (buflen > 0 && path[buflen-1] != '/') + buflen--; + path.resize(buflen); } - while (buflen > 0 && path[buflen-1] != '/') - buflen--; - return std::string(path, buflen); + return path; } #elif defined(__FreeBSD__) || defined(__NetBSD__) std::string proc_self_dirname() From 240f7030b2382c0b4f87f58e245792200b7b9934 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Tue, 21 Apr 2026 10:52:50 +0200 Subject: [PATCH 102/176] xprop: ignore $scopeinfo cells --- passes/cmds/xprop.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/cmds/xprop.cc b/passes/cmds/xprop.cc index 7291bb859..3f40e72ab 100644 --- a/passes/cmds/xprop.cc +++ b/passes/cmds/xprop.cc @@ -463,6 +463,10 @@ struct XpropWorker return; } + if (cell->type.in(ID($scopeinfo))) { + return; + } + log_warning("Unhandled cell %s (%s) during maybe-x marking\n", log_id(cell), log_id(cell->type)); mark_outputs_maybe_x(cell); } From a89e8fd8691accfc2f67080b4ca1ad678c3f5f81 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Wed, 22 Apr 2026 04:28:51 +0200 Subject: [PATCH 103/176] Fixed spelling error in message of frontends/ast/genrtlil.cc. Patch by Ruben Undheim via the Debian project. The patch originated as 0009-Some-spelling-errors-fixed.patch and was dated 2018-07-12 there. See also issue #5805. --- frontends/ast/genrtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 5e0356fd3..966fe563a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -798,7 +798,7 @@ struct AST_INTERNAL::ProcessGenerator break; case AST_ASSIGN: - ast->input_error("Found continous assignment in always/initial block!\n"); + ast->input_error("Found continuous assignment in always/initial block!\n"); break; case AST_PARAMETER: From f213a34427d6b0b99feb3e39d140f13934322468 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 22 Apr 2026 10:39:19 +0200 Subject: [PATCH 104/176] Remove FHS dependency by replacing /bin/bash with /usr/bin/env bash everywhere --- .github/workflows/wheels/cibw_before_all.sh | 2 +- docs/source/using_yosys/bugpoint.rst | 4 ++-- examples/aiger/README | 2 +- examples/aiger/demo.sh | 2 +- examples/anlogic/build.sh | 2 +- examples/basys3/run.sh | 2 +- examples/cmos/testbench.sh | 2 +- examples/cmos/testbench_digital.sh | 2 +- examples/gowin/run.sh | 2 +- examples/igloo2/runme.sh | 2 +- examples/intel/DE2i-150/quartus_compile/runme_quartus | 2 +- examples/intel/MAX10/runme_postsynth | 2 +- examples/intel/asicworld_lfsr/runme_postsynth | 2 +- examples/intel/asicworld_lfsr/runme_presynth | 2 +- misc/create_vcxsrc.sh | 2 +- tests/aiger/generate_mk.py | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/wheels/cibw_before_all.sh b/.github/workflows/wheels/cibw_before_all.sh index 1aef650d7..6450ce273 100644 --- a/.github/workflows/wheels/cibw_before_all.sh +++ b/.github/workflows/wheels/cibw_before_all.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e -x # Build-time dependencies diff --git a/docs/source/using_yosys/bugpoint.rst b/docs/source/using_yosys/bugpoint.rst index c524470af..71ec3b68d 100644 --- a/docs/source/using_yosys/bugpoint.rst +++ b/docs/source/using_yosys/bugpoint.rst @@ -293,7 +293,7 @@ is still valid. :caption: Example test.sh for C-Reduce :name: egtest - #!/bin/bash + #!/usr/bin/env bash verilator --lint-only test.v &&/ yosys -p 'logger -expect error "unsupported" 1; read_verilog test.v' @@ -333,7 +333,7 @@ an input argument: ``sv-bugpoint outDir/ test.sh test.v`` .. code-block:: bash :caption: Example test.sh for sv-bugpoint - #!/bin/bash + #!/usr/bin/env bash verilator --lint-only $1 &&/ yosys -p "logger -expect error \"unsupported\" 1; read_verilog $1" diff --git a/examples/aiger/README b/examples/aiger/README index 4e7694e95..13dce2035 100644 --- a/examples/aiger/README +++ b/examples/aiger/README @@ -14,7 +14,7 @@ in the PATH. E.g. extract the release to /usr/local/libexec/super_prove and then create a /usr/local/bin/super_prove file with the following contents (and "chmod +x" that file): - #!/bin/bash + #!/usr/bin/env bash exec /usr/local/libexec/super_prove/bin/super_prove.sh "$@" The "demo.sh" script also expects the "z3" SMT2 solver in the PATH for diff --git a/examples/aiger/demo.sh b/examples/aiger/demo.sh index 8728b6722..a1217bbd2 100644 --- a/examples/aiger/demo.sh +++ b/examples/aiger/demo.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys -p ' read_verilog -formal demo.v diff --git a/examples/anlogic/build.sh b/examples/anlogic/build.sh index e0f6b4cfe..9b6e8c479 100755 --- a/examples/anlogic/build.sh +++ b/examples/anlogic/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys demo.ys $TD_HOME/bin/td build.tcl diff --git a/examples/basys3/run.sh b/examples/basys3/run.sh index 10f059103..deb68d432 100644 --- a/examples/basys3/run.sh +++ b/examples/basys3/run.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash yosys run_yosys.ys vivado -nolog -nojournal -mode batch -source run_vivado.tcl vivado -nolog -nojournal -mode batch -source run_prog.tcl diff --git a/examples/cmos/testbench.sh b/examples/cmos/testbench.sh index 061704b64..856169ab9 100644 --- a/examples/cmos/testbench.sh +++ b/examples/cmos/testbench.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/examples/cmos/testbench_digital.sh b/examples/cmos/testbench_digital.sh index d7ab0fe1f..2e70e874c 100644 --- a/examples/cmos/testbench_digital.sh +++ b/examples/cmos/testbench_digital.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/examples/gowin/run.sh b/examples/gowin/run.sh index cd260101e..960624464 100644 --- a/examples/gowin/run.sh +++ b/examples/gowin/run.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v $GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW1NR-9-QFN88-6 -pn GW1NR-LV9QN88C6/I5 -cfg device.cfg -bit -tr -ph -timing -gpa -rpt -warning_all diff --git a/examples/igloo2/runme.sh b/examples/igloo2/runme.sh index a08894e0a..7349ff603 100644 --- a/examples/igloo2/runme.sh +++ b/examples/igloo2/runme.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost} diff --git a/examples/intel/DE2i-150/quartus_compile/runme_quartus b/examples/intel/DE2i-150/quartus_compile/runme_quartus index 83aa3b609..2bc29582c 100644 --- a/examples/intel/DE2i-150/quartus_compile/runme_quartus +++ b/examples/intel/DE2i-150/quartus_compile/runme_quartus @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash export REV="de2i" diff --git a/examples/intel/MAX10/runme_postsynth b/examples/intel/MAX10/runme_postsynth index f16210540..657c05fa8 100644 --- a/examples/intel/MAX10/runme_postsynth +++ b/examples/intel/MAX10/runme_postsynth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash iverilog -D POST_IMPL -o verif_post -s tb_top tb_top.v top.vqm $(yosys-config --datdir/altera_intel/max10/cells_comb_max10.v) vvp -N verif_post diff --git a/examples/intel/asicworld_lfsr/runme_postsynth b/examples/intel/asicworld_lfsr/runme_postsynth index c3b26b034..ad5ca39d4 100755 --- a/examples/intel/asicworld_lfsr/runme_postsynth +++ b/examples/intel/asicworld_lfsr/runme_postsynth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash iverilog -D POST_IMPL -o verif_post -s tb lfsr_updown_tb.v top.vqm $(yosys-config --datdir/altera_intel/max10/cells_comb_max10.v) vvp -N verif_post diff --git a/examples/intel/asicworld_lfsr/runme_presynth b/examples/intel/asicworld_lfsr/runme_presynth index 51118bb4b..3ed6618d3 100755 --- a/examples/intel/asicworld_lfsr/runme_presynth +++ b/examples/intel/asicworld_lfsr/runme_presynth @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash iverilog -o presynth lfsr_updown_tb.v lfsr_updown.v &&\ diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh index 42a690ce6..98c1817bd 100644 --- a/misc/create_vcxsrc.sh +++ b/misc/create_vcxsrc.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex vcxsrc="$1" diff --git a/tests/aiger/generate_mk.py b/tests/aiger/generate_mk.py index 6c27455b9..a90a63527 100644 --- a/tests/aiger/generate_mk.py +++ b/tests/aiger/generate_mk.py @@ -54,6 +54,6 @@ def create_tests(): "rm -f aigmap.err" ])) -extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc", "SHELL := /bin/bash" ] +extra = [ f"ABC ?= {gen_tests_makefile.yosys_basedir}/yosys-abc", "SHELL := /usr/bin/env bash" ] gen_tests_makefile.generate_custom(create_tests, extra) From bc83311dd88c3d6042d2a90303c28733771441e4 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 22 Apr 2026 17:37:25 +0200 Subject: [PATCH 105/176] Update ABC as per 2026-04-22 --- abc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abc b/abc index 180a6adb6..405511f85 160000 --- a/abc +++ b/abc @@ -1 +1 @@ -Subproject commit 180a6adb68e855942e859f3646eff7762c7bc3e6 +Subproject commit 405511f850328ca05c08b1a77cdfd60464d5cb1d From 9143178343e6b973e4896c4cd6687ca661e2e3cf Mon Sep 17 00:00:00 2001 From: nella Date: Fri, 17 Apr 2026 19:39:56 +0200 Subject: [PATCH 106/176] Merge liberty files into stripped scl files. --- passes/techmap/abc.cc | 166 ++++++++++++++++++++++++++++++++---------- 1 file changed, 126 insertions(+), 40 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 8e333f7cb..dc670eaa9 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -63,10 +63,12 @@ # include # include # include +# include #endif #ifndef _WIN32 # include # include +# include #endif #include "frontends/blif/blifparse.h" @@ -278,6 +280,80 @@ std::optional spawn_abc(const char* abc_exe, DeferredLogs &logs) { struct AbcProcess {}; #endif +std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &abc_exe) { + if (liberty_files.empty()) + return ""; + + // Sort filenames to ensure consistent hash regardless of order + std::vector sorted_files = liberty_files; + std::sort(sorted_files.begin(), sorted_files.end()); + std::string hash_input; + time_t newest_mtime = 0; + + for (const std::string &liberty_file : sorted_files) { + struct stat liberty_stat; + if (stat(liberty_file.c_str(), &liberty_stat) != 0) { + log_error("Cannot stat Liberty file: %s\n", liberty_file.c_str()); + return ""; + } + hash_input += liberty_file + "|"; + if (liberty_stat.st_mtime > newest_mtime) + newest_mtime = liberty_stat.st_mtime; + } + + // scl filename + std::string first_dir; + size_t last_slash = liberty_files[0].find_last_of("/\\"); + unsigned int hash = 0; + + if (last_slash == std::string::npos) { + first_dir = "."; + } else { + first_dir = liberty_files[0].substr(0, last_slash); + } + + for (char c : hash_input) + hash = hash * 31 + c; + + std::string merged_scl = stringf("%s/.yosys_merged_%08x.scl", first_dir.c_str(), hash); + bool need_convert = true; + struct stat scl_stat; + + // Check if merged SCL exists and is newer than all liberty files + if (stat(merged_scl.c_str(), &scl_stat) == 0) { + if (scl_stat.st_mtime >= newest_mtime) { + log("ABC: Using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size()); + need_convert = false; + } + } + + if (need_convert) { + // read_lib file1 ; read_lib -m file2 ; ... ; write_scl merged.scl + std::string abc_script; + bool first = true; + + for (const std::string &liberty_file : liberty_files) { + abc_script += stringf("read_lib %s-w \\\"%s\\\" ; ", first ? "" : "-m ", liberty_file.c_str()); + first = false; + } + + abc_script += stringf("write_scl \\\"%s\\\"", merged_scl.c_str()); + std::string cmd = stringf("\"%s\" -c \"%s\" 2>&1", abc_exe.c_str(), abc_script.c_str()); + std::string abc_output; + int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; }); + + if (ret != 0) { + log_warning("ABC: Merged scl conversion failed, falling back to Liberty format\n"); + if (!abc_output.empty()) { + log("ABC conversion output:\n%s", abc_output.c_str()); + } + return ""; + } + } + + return merged_scl; +} + using AbcSigMap = SigValMap; // Used by off-main-threads. Contains no direct or indirect access to RTLIL. @@ -290,6 +366,8 @@ struct RunAbcState { bool err = false; DeferredLogs logs; dict pi_map, po_map; + std::string abc_script; + std::string dont_use_args; RunAbcState(const AbcConfig &config) : config(config) {} void run(ConcurrentStack &process_pool); @@ -1014,87 +1092,95 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n", module->name.c_str(), replace_tempdir(run_abc.per_run_tempdir_name, config.global_tempdir_name, run_abc.per_run_tempdir_name, config.show_tempdir).c_str()); - std::string abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name); + run_abc.abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name); if (!config.liberty_files.empty() || !config.genlib_files.empty()) { - std::string dont_use_args; + run_abc.dont_use_args = ""; for (std::string dont_use_cell : config.dont_use_cells) { - dont_use_args += stringf("-X \"%s\" ", dont_use_cell); + run_abc.dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } - bool first_lib = true; - for (std::string liberty_file : config.liberty_files) { - abc_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); - first_lib = false; + + std::string merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, config.exe_file); + if (!merged_scl.empty()) { + run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); + } else { + log_warning("ABC: Merged scl conversion failed, using liberty format\n"); + bool first_lib = true; + for (std::string liberty_file : config.liberty_files) { + run_abc.abc_script += stringf("read_lib %s %s -w \"%s\" ; ", run_abc.dont_use_args, first_lib ? "" : "-m", liberty_file); + first_lib = false; + } } + for (std::string liberty_file : config.genlib_files) - abc_script += stringf("read_library \"%s\"; ", liberty_file); + run_abc.abc_script += stringf("read_library \"%s\"; ", liberty_file); if (!config.constr_file.empty()) - abc_script += stringf("read_constr -v \"%s\"; ", config.constr_file); + run_abc.abc_script += stringf("read_constr -v \"%s\"; ", config.constr_file); } else if (!config.lut_costs.empty()) - abc_script += stringf("read_lut %s/lutdefs.txt; ", config.global_tempdir_name); + run_abc.abc_script += stringf("read_lut %s/lutdefs.txt; ", config.global_tempdir_name); else - abc_script += stringf("read_library %s/stdcells.genlib; ", config.global_tempdir_name); + run_abc.abc_script += stringf("read_library %s/stdcells.genlib; ", config.global_tempdir_name); if (!config.script_file.empty()) { const std::string &script_file = config.script_file; if (script_file[0] == '+') { for (size_t i = 1; i < script_file.size(); i++) if (script_file[i] == '\'') - abc_script += "'\\''"; + run_abc.abc_script += "'\\''"; else if (script_file[i] == ',') - abc_script += " "; + run_abc.abc_script += " "; else - abc_script += script_file[i]; + run_abc.abc_script += script_file[i]; } else - abc_script += stringf("source %s", script_file); + run_abc.abc_script += stringf("source %s", script_file); } else if (!config.lut_costs.empty()) { bool all_luts_cost_same = true; for (int this_cost : config.lut_costs) if (this_cost != config.lut_costs.front()) all_luts_cost_same = false; - abc_script += config.fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; if (all_luts_cost_same && !config.fast_mode) - abc_script += "; lutpack -S 1"; + run_abc.abc_script += "; lutpack -S 1"; } else if (!config.liberty_files.empty() || !config.genlib_files.empty()) - abc_script += config.constr_file.empty() ? + run_abc.abc_script += config.constr_file.empty() ? (config.fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (config.fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR); else if (config.sop_mode) - abc_script += config.fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP; + run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP; else - abc_script += config.fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; + run_abc.abc_script += config.fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; if (config.script_file.empty() && !config.delay_target.empty()) - for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) - abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); + for (size_t pos = run_abc.abc_script.find("dretime;"); pos != std::string::npos; pos = run_abc.abc_script.find("dretime;", pos+1)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + "dretime; retime -o {D};" + run_abc.abc_script.substr(pos+8); - for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) - abc_script = abc_script.substr(0, pos) + config.delay_target + abc_script.substr(pos+3); + for (size_t pos = run_abc.abc_script.find("{D}"); pos != std::string::npos; pos = run_abc.abc_script.find("{D}", pos)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.delay_target + run_abc.abc_script.substr(pos+3); - for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{I}", pos)) - abc_script = abc_script.substr(0, pos) + config.sop_inputs + abc_script.substr(pos+3); + for (size_t pos = run_abc.abc_script.find("{I}"); pos != std::string::npos; pos = run_abc.abc_script.find("{I}", pos)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.sop_inputs + run_abc.abc_script.substr(pos+3); - for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{P}", pos)) - abc_script = abc_script.substr(0, pos) + config.sop_products + abc_script.substr(pos+3); + for (size_t pos = run_abc.abc_script.find("{P}"); pos != std::string::npos; pos = run_abc.abc_script.find("{P}", pos)) + run_abc.abc_script = run_abc.abc_script.substr(0, pos) + config.sop_products + run_abc.abc_script.substr(pos+3); if (config.abc_dress) - abc_script += stringf("; dress \"%s/input.blif\"", run_abc.per_run_tempdir_name); - abc_script += stringf("; write_blif %s/output.blif", run_abc.per_run_tempdir_name); - abc_script = add_echos_to_abc_cmd(abc_script); + run_abc.abc_script += stringf("; dress \"%s/input.blif\"", run_abc.per_run_tempdir_name); + run_abc.abc_script += stringf("; write_blif %s/output.blif", run_abc.per_run_tempdir_name); + run_abc.abc_script = add_echos_to_abc_cmd(run_abc.abc_script); #if defined(REUSE_YOSYS_ABC_PROCESSES) if (config.is_yosys_abc()) - abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n"; + run_abc.abc_script += "; echo; echo \"YOSYS_ABC_DONE\"\n"; #endif - for (size_t i = 0; i+1 < abc_script.size(); i++) - if (abc_script[i] == ';' && abc_script[i+1] == ' ') - abc_script[i+1] = '\n'; + for (size_t i = 0; i+1 < run_abc.abc_script.size(); i++) + if (run_abc.abc_script[i] == ';' && run_abc.abc_script[i+1] == ' ') + run_abc.abc_script[i+1] = '\n'; std::string buffer = stringf("%s/abc.script", run_abc.per_run_tempdir_name); FILE *f = fopen(buffer.c_str(), "wt"); if (f == nullptr) log_error("Opening %s for writing failed: %s\n", buffer, strerror(errno)); - fprintf(f, "%s\n", abc_script.c_str()); + fprintf(f, "%s\n", run_abc.abc_script.c_str()); fclose(f); if (dff_mode || !clk_str.empty()) @@ -1408,10 +1494,10 @@ void RunAbcState::run(ConcurrentStack &) if (std::optional process_opt = process_pool.try_pop_back()) { process = std::move(process_opt.value()); } else if (std::optional process_opt = spawn_abc(config.exe_file.c_str(), logs)) { - process = std::move(process_opt.value()); - } else { - return; - } + process = std::move(process_opt.value()); + } else { + return; + } std::string cmd = stringf( "empty\n" "source %s\n", tmp_script_name); From edd3ad525e6023b7457eb8029f9f916d7767f524 Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 20 Apr 2026 13:55:58 +0200 Subject: [PATCH 107/176] Add scl caching to abc_new. --- passes/techmap/abc.cc | 75 +------------------------- passes/techmap/abc9_exe.cc | 19 +++++-- passes/techmap/liberty_cache.h | 96 ++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 78 deletions(-) create mode 100644 passes/techmap/liberty_cache.h diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index dc670eaa9..af8d02c5c 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -72,6 +72,7 @@ #endif #include "frontends/blif/blifparse.h" +#include "liberty_cache.h" #ifdef YOSYS_LINK_ABC namespace abc { @@ -280,80 +281,6 @@ std::optional spawn_abc(const char* abc_exe, DeferredLogs &logs) { struct AbcProcess {}; #endif -std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &abc_exe) { - if (liberty_files.empty()) - return ""; - - // Sort filenames to ensure consistent hash regardless of order - std::vector sorted_files = liberty_files; - std::sort(sorted_files.begin(), sorted_files.end()); - std::string hash_input; - time_t newest_mtime = 0; - - for (const std::string &liberty_file : sorted_files) { - struct stat liberty_stat; - if (stat(liberty_file.c_str(), &liberty_stat) != 0) { - log_error("Cannot stat Liberty file: %s\n", liberty_file.c_str()); - return ""; - } - hash_input += liberty_file + "|"; - if (liberty_stat.st_mtime > newest_mtime) - newest_mtime = liberty_stat.st_mtime; - } - - // scl filename - std::string first_dir; - size_t last_slash = liberty_files[0].find_last_of("/\\"); - unsigned int hash = 0; - - if (last_slash == std::string::npos) { - first_dir = "."; - } else { - first_dir = liberty_files[0].substr(0, last_slash); - } - - for (char c : hash_input) - hash = hash * 31 + c; - - std::string merged_scl = stringf("%s/.yosys_merged_%08x.scl", first_dir.c_str(), hash); - bool need_convert = true; - struct stat scl_stat; - - // Check if merged SCL exists and is newer than all liberty files - if (stat(merged_scl.c_str(), &scl_stat) == 0) { - if (scl_stat.st_mtime >= newest_mtime) { - log("ABC: Using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size()); - need_convert = false; - } - } - - if (need_convert) { - // read_lib file1 ; read_lib -m file2 ; ... ; write_scl merged.scl - std::string abc_script; - bool first = true; - - for (const std::string &liberty_file : liberty_files) { - abc_script += stringf("read_lib %s-w \\\"%s\\\" ; ", first ? "" : "-m ", liberty_file.c_str()); - first = false; - } - - abc_script += stringf("write_scl \\\"%s\\\"", merged_scl.c_str()); - std::string cmd = stringf("\"%s\" -c \"%s\" 2>&1", abc_exe.c_str(), abc_script.c_str()); - std::string abc_output; - int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; }); - - if (ret != 0) { - log_warning("ABC: Merged scl conversion failed, falling back to Liberty format\n"); - if (!abc_output.empty()) { - log("ABC conversion output:\n%s", abc_output.c_str()); - } - return ""; - } - } - - return merged_scl; -} - using AbcSigMap = SigValMap; // Used by off-main-threads. Contains no direct or indirect access to RTLIL. diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index 592f717c1..29d7ec309 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -24,6 +24,7 @@ #include "kernel/register.h" #include "kernel/log.h" +#include "liberty_cache.h" #ifndef _WIN32 # include @@ -181,11 +182,19 @@ 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 %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); - first_lib = false; + + std::string merged_scl = convert_liberty_files_to_merged_scl(liberty_files, exe_file); + if (!merged_scl.empty()) { + abc9_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); + } else { + log_warning("ABC: Merged scl conversion failed, using liberty format\n"); + bool first_lib = true; + for (std::string liberty_file : liberty_files) { + 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); } else if (!genlib_files.empty()) { @@ -211,6 +220,8 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe abc9_script += stringf("source %s", script_file); } else if (!lut_costs.empty() || !lut_file.empty()) { abc9_script += RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos); + } else if (!liberty_files.empty() || !genlib_files.empty()) { + abc9_script += RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos); } else log_abort(); diff --git a/passes/techmap/liberty_cache.h b/passes/techmap/liberty_cache.h new file mode 100644 index 000000000..9cf4259eb --- /dev/null +++ b/passes/techmap/liberty_cache.h @@ -0,0 +1,96 @@ +#ifndef LIBERTY_CACHE_H +#define LIBERTY_CACHE_H + +#include "kernel/yosys.h" +#include +#include +#include +#include + +YOSYS_NAMESPACE_BEGIN + +/* + * convert_liberty_files_to_merged_scl() - Convert multiple Liberty files to a single merged SCL cache file. + * @liberty_files - Vector of liberty file paths to merge + * @abc_exe - Path to ABC executable for conversion + * + * Return: Path to merged SCL cache file, or empty string if conversion fails + */ +inline std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &abc_exe) +{ + if (liberty_files.empty()) + return ""; + + // Sort filenames to ensure consistent hash regardless of order + std::vector sorted_files = liberty_files; + std::sort(sorted_files.begin(), sorted_files.end()); + std::string hash_input; + time_t newest_mtime = 0; + + for (const std::string &liberty_file : sorted_files) { + struct stat liberty_stat; + if (stat(liberty_file.c_str(), &liberty_stat) != 0) { + log_error("Cannot stat Liberty file: %s\n", liberty_file.c_str()); + return ""; + } + hash_input += liberty_file + "|"; + if (liberty_stat.st_mtime > newest_mtime) + newest_mtime = liberty_stat.st_mtime; + } + + // SCL filename + std::string first_dir; + size_t last_slash = liberty_files[0].find_last_of("/\\"); + unsigned int hash = 0; + + if (last_slash == std::string::npos) { + first_dir = "."; + } else { + first_dir = liberty_files[0].substr(0, last_slash); + } + + for (char c : hash_input) + hash = hash * 31 + c; + + std::string merged_scl = stringf("%s/.yosys_merged_%08x.scl", first_dir.c_str(), hash); + bool need_convert = true; + struct stat scl_stat; + + // Check if merged SCL exists and is newer than all liberty files + if (stat(merged_scl.c_str(), &scl_stat) == 0) { + if (scl_stat.st_mtime >= newest_mtime) { + log("ABC: Using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size()); + need_convert = false; + } + } + + if (need_convert) { + // read_lib file1 ; read_lib -m file2 ; ... ; write_scl merged.scl + std::string abc_script; + bool first = true; + + for (const std::string &liberty_file : liberty_files) { + abc_script += stringf("read_lib %s-w \\\"%s\\\" ; ", first ? "" : "-m ", liberty_file.c_str()); + first = false; + } + + abc_script += stringf("write_scl \\\"%s\\\"", merged_scl.c_str()); + std::string cmd = stringf("\"%s\" -c \"%s\" 2>&1", abc_exe.c_str(), abc_script.c_str()); + std::string abc_output; + int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; }); + + if (ret != 0) { + log_warning("ABC: Merged SCL conversion failed, falling back to liberty format\n"); + if (!abc_output.empty()) { + log("ABC conversion output:\n%s", abc_output.c_str()); + } + return ""; + } + } + + return merged_scl; +} + +YOSYS_NAMESPACE_END + +#endif // LIBERTY_CACHE_H From 94a215b4f7c9b57b0530231b3628fecf1285a386 Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 20 Apr 2026 20:25:37 +0200 Subject: [PATCH 108/176] Add dont_use_cells to scl cache. --- passes/techmap/abc.cc | 2 +- passes/techmap/abc9_exe.cc | 2 +- passes/techmap/liberty_cache.h | 25 ++++++++++++++++++------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index af8d02c5c..9be02cacd 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1027,7 +1027,7 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module run_abc.dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } - std::string merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, config.exe_file); + std::string merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, run_abc.dont_use_args, config.exe_file); if (!merged_scl.empty()) { run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); } else { diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index 29d7ec309..a67807909 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -183,7 +183,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } - std::string merged_scl = convert_liberty_files_to_merged_scl(liberty_files, exe_file); + std::string merged_scl = convert_liberty_files_to_merged_scl(liberty_files, dont_use_args, exe_file); if (!merged_scl.empty()) { abc9_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); } else { diff --git a/passes/techmap/liberty_cache.h b/passes/techmap/liberty_cache.h index 9cf4259eb..391aa6344 100644 --- a/passes/techmap/liberty_cache.h +++ b/passes/techmap/liberty_cache.h @@ -11,17 +11,18 @@ YOSYS_NAMESPACE_BEGIN /* * convert_liberty_files_to_merged_scl() - Convert multiple Liberty files to a single merged SCL cache file. - * @liberty_files - Vector of liberty file paths to merge - * @abc_exe - Path to ABC executable for conversion + * @liberty_files: Vector of liberty file paths to merge + * @dont_use_args: Pre-built ABC -X flags string + * @abc_exe: Path to ABC executable for conversion * * Return: Path to merged SCL cache file, or empty string if conversion fails */ -inline std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &abc_exe) +inline std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &dont_use_args, const std::string &abc_exe) { if (liberty_files.empty()) return ""; - // Sort filenames to ensure consistent hash regardless of order + // Sort to ensure consistent hash regardless of order std::vector sorted_files = liberty_files; std::sort(sorted_files.begin(), sorted_files.end()); std::string hash_input; @@ -38,6 +39,8 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector&1", abc_exe.c_str(), abc_script.c_str()); std::string abc_output; int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; }); @@ -84,6 +88,13 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector Date: Wed, 22 Apr 2026 10:17:20 +0200 Subject: [PATCH 109/176] Fix mac compile. --- passes/techmap/liberty_cache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/liberty_cache.h b/passes/techmap/liberty_cache.h index 391aa6344..9f5602356 100644 --- a/passes/techmap/liberty_cache.h +++ b/passes/techmap/liberty_cache.h @@ -88,13 +88,13 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector Date: Wed, 22 Apr 2026 16:30:50 +0200 Subject: [PATCH 110/176] Fix WASI build. --- passes/techmap/liberty_cache.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/techmap/liberty_cache.h b/passes/techmap/liberty_cache.h index 9f5602356..2197f9125 100644 --- a/passes/techmap/liberty_cache.h +++ b/passes/techmap/liberty_cache.h @@ -17,6 +17,9 @@ YOSYS_NAMESPACE_BEGIN * * Return: Path to merged SCL cache file, or empty string if conversion fails */ +#if defined(YOSYS_LINK_ABC) +inline std::string convert_liberty_files_to_merged_scl(const std::vector &, const std::string &, const std::string &) { return ""; } +#else inline std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &dont_use_args, const std::string &abc_exe) { if (liberty_files.empty()) @@ -101,6 +104,7 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector Date: Thu, 23 Apr 2026 12:03:10 +0200 Subject: [PATCH 111/176] Fix WASI, store in temp dir. --- passes/techmap/liberty_cache.h | 88 +++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/passes/techmap/liberty_cache.h b/passes/techmap/liberty_cache.h index 2197f9125..8ae89947f 100644 --- a/passes/techmap/liberty_cache.h +++ b/passes/techmap/liberty_cache.h @@ -2,10 +2,12 @@ #define LIBERTY_CACHE_H #include "kernel/yosys.h" -#include -#include -#include -#include + +#ifdef YOSYS_LINK_ABC +namespace abc { + int Abc_RealMain(int argc, char *argv[]); +} +#endif YOSYS_NAMESPACE_BEGIN @@ -17,14 +19,18 @@ YOSYS_NAMESPACE_BEGIN * * Return: Path to merged SCL cache file, or empty string if conversion fails */ -#if defined(YOSYS_LINK_ABC) -inline std::string convert_liberty_files_to_merged_scl(const std::vector &, const std::string &, const std::string &) { return ""; } -#else inline std::string convert_liberty_files_to_merged_scl(const std::vector &liberty_files, const std::string &dont_use_args, const std::string &abc_exe) { if (liberty_files.empty()) return ""; + std::string cache_dir = get_base_tmpdir() + "/yosys-liberty-scl-cache"; + + if (!create_directory(cache_dir)) { + log_warning("ABC: cannot create cache directory %s, falling back to liberty format\n", cache_dir.c_str()); + return ""; + } + // Sort to ensure consistent hash regardless of order std::vector sorted_files = liberty_files; std::sort(sorted_files.begin(), sorted_files.end()); @@ -34,7 +40,7 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector= newest_mtime) { - log("ABC: Using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size()); + log("ABC: using cached merged SCL: %s (%zu files)\n", merged_scl.c_str(), liberty_files.size()); need_convert = false; } } if (need_convert) { // read_lib -X cell1 -X cell2 file1 ; read_lib -X cell1 -X cell2 -m file2 ; ... ; write_scl merged.scl + std::string temp_scl = merged_scl + ".tmp"; + +#ifdef YOSYS_LINK_ABC + std::string script_path = stringf("%s/yosys_merged_scl_convert_%08x.script", cache_dir.c_str(), hash); + FILE *f = fopen(script_path.c_str(), "w"); + + if (f == NULL) { + log_warning("ABC: cannot open %s for writing, falling back to liberty format\n", script_path.c_str()); + return ""; + } + + bool first = true; + + for (const std::string &liberty_file : liberty_files) { + fprintf(f, "read_lib %s%s-w \"%s\"\n", dont_use_args.c_str(), first ? "" : "-m ", liberty_file.c_str()); + first = false; + } + + fprintf(f, "write_scl \"%s\"\n", temp_scl.c_str()); + fclose(f); + + char *abc_argv[5]; + abc_argv[0] = strdup(abc_exe.empty() ? "yosys-abc" : abc_exe.c_str()); + abc_argv[1] = strdup("-s"); + abc_argv[2] = strdup("-f"); + abc_argv[3] = strdup(script_path.c_str()); + abc_argv[4] = 0; + int ret = abc::Abc_RealMain(4, abc_argv); + free(abc_argv[0]); + free(abc_argv[1]); + free(abc_argv[2]); + free(abc_argv[3]); + remove(script_path.c_str()); + + if (ret != 0) { + log_warning("ABC: merged SCL conversion failed (ret=%d), falling back to liberty format\n", ret); + remove(temp_scl.c_str()); + return ""; + } +#else std::string abc_script; bool first = true; @@ -80,23 +116,22 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector&1", abc_exe.c_str(), abc_script.c_str()); std::string abc_output; int ret = run_command(cmd, [&abc_output](const std::string &line) { abc_output += line + "\n"; }); if (ret != 0) { - log_warning("ABC: Merged SCL conversion failed, falling back to liberty format\n"); + log_warning("ABC: merged SCL conversion failed, falling back to liberty format\n"); if (!abc_output.empty()) { - log("ABC conversion output:\n%s", abc_output.c_str()); + log("ABC: conversion output:\n%s", abc_output.c_str()); } remove(temp_scl.c_str()); return ""; } - +#endif if (rename(temp_scl.c_str(), merged_scl.c_str()) != 0) { - log_warning("ABC: Failed to rename %s to %s, falling back to liberty format\n", temp_scl.c_str(), merged_scl.c_str()); + log_warning("ABC: failed to rename %s to %s, falling back to liberty format\n", temp_scl.c_str(), merged_scl.c_str()); remove(temp_scl.c_str()); return ""; } @@ -104,8 +139,7 @@ inline std::string convert_liberty_files_to_merged_scl(const std::vector Date: Thu, 23 Apr 2026 13:58:20 +0200 Subject: [PATCH 112/176] rtlil: simplify extract for performance --- kernel/rtlil.cc | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2badd20c3..c0f6e0d81 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -5272,25 +5272,9 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const log_assert(length >= 0); log_assert(offset + length <= size()); - SigSpec extracted; - Chunks cs = chunks(); - auto it = cs.begin(); - for (; offset; offset -= it->width, ++it) { - if (offset < it->width) { - int chunk_length = min(it->width - offset, length); - extracted.append(it->extract(offset, chunk_length)); - length -= chunk_length; - ++it; - break; - } - } - for (; length; length -= it->width, ++it) { - if (length >= it->width) { - extracted.append(*it); - } else { - extracted.append(it->extract(0, length)); - break; - } + std::vector extracted; + for (int i = offset; i < offset + length; i++) { + extracted.push_back((*this)[i]); } return extracted; } From dc570e3d5525834364172f52056505424a26f3b1 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 23 Apr 2026 15:48:33 +0200 Subject: [PATCH 113/176] Remove FHS dependency by replacing /bin/env with /usr/bin/env --- examples/intel/asicworld_lfsr/run_cycloneiv | 2 +- examples/intel/asicworld_lfsr/run_max10 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/intel/asicworld_lfsr/run_cycloneiv b/examples/intel/asicworld_lfsr/run_cycloneiv index c7498bded..077b7fbde 100755 --- a/examples/intel/asicworld_lfsr/run_cycloneiv +++ b/examples/intel/asicworld_lfsr/run_cycloneiv @@ -1,2 +1,2 @@ -#!/bin/env bash +#!/usr/bin/env bash yosys -p "synth_intel -family cycloneiv -top lfsr_updown -vqm top.vqm" lfsr_updown.v diff --git a/examples/intel/asicworld_lfsr/run_max10 b/examples/intel/asicworld_lfsr/run_max10 index b75d552bb..8fccb57f8 100755 --- a/examples/intel/asicworld_lfsr/run_max10 +++ b/examples/intel/asicworld_lfsr/run_max10 @@ -1,2 +1,2 @@ -#!/bin/env bash +#!/usr/bin/env bash yosys -p "synth_intel -family max10 -top lfsr_updown -vqm top.vqm" lfsr_updown.v From 14d0138d0cfbb96302991e3b9d9a934ad705491e Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 23 Apr 2026 15:55:11 +0200 Subject: [PATCH 114/176] Remove FHS dependency by replacing /bin/sh with /usr/bin/env sh --- examples/mimas2/run.sh | 2 +- techlibs/sf2/NOTES.txt | 2 +- tests/various/ezcmdline_dummy_solver | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/mimas2/run.sh b/examples/mimas2/run.sh index aafde78ed..b16341ece 100644 --- a/examples/mimas2/run.sh +++ b/examples/mimas2/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env sh set -e yosys run_yosys.ys edif2ngd example.edif diff --git a/techlibs/sf2/NOTES.txt b/techlibs/sf2/NOTES.txt index 67784b546..6204d8fee 100644 --- a/techlibs/sf2/NOTES.txt +++ b/techlibs/sf2/NOTES.txt @@ -12,7 +12,7 @@ You'd better to write a simple script, like this one (assuming the top module is top): ----------- run_yosys.sh -------------- -#!/bin/sh +#!/usr/bin/env sh set -e diff --git a/tests/various/ezcmdline_dummy_solver b/tests/various/ezcmdline_dummy_solver index db5b21b8e..d0377f9af 100755 --- a/tests/various/ezcmdline_dummy_solver +++ b/tests/various/ezcmdline_dummy_solver @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env sh # Dummy SAT solver for ezCmdlineSAT tests. # Accepts exactly two CNF shapes: # - SAT: p cnf 1 1; clause: "1 0" -> exits 10 with v 1 From e69341cd5f088f3775777b42d6ea14248af5e71a Mon Sep 17 00:00:00 2001 From: Scott Ashcroft Date: Thu, 23 Apr 2026 13:55:08 +0100 Subject: [PATCH 115/176] Make sure co-simulation only uses integer arithmetic --- kernel/fstdata.cc | 3 +-- kernel/fstdata.h | 4 ++-- passes/sat/sim.cc | 56 +++++++++++++++++++++++++++++------------------ 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index f0f00181c..8b724e69b 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -45,8 +45,7 @@ FstData::FstData(std::string filename) : ctx(nullptr) ctx = (fstReaderContext *)fstReaderOpen(filename.c_str()); if (!ctx) log_error("Error opening '%s' as FST file\n", filename); - int scale = (int)fstReaderGetTimescale(ctx); - timescale = pow(10.0, scale); + scale = (int)fstReaderGetTimescale(ctx); timescale_str = ""; int unit = 0; int zeros = 0; diff --git a/kernel/fstdata.h b/kernel/fstdata.h index a8ae40301..7f763b621 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -55,7 +55,7 @@ class FstData std::string valueOf(fstHandle signal); fstHandle getHandle(std::string name); dict getMemoryHandles(std::string name); - double getTimescale() { return timescale; } + int getScale() { return scale; } const char *getTimescaleString() { return timescale_str.c_str(); } private: void extractVarNames(); @@ -69,7 +69,7 @@ private: uint64_t last_time; std::map past_data; uint64_t past_time; - double timescale; + int scale; std::string timescale_str; uint64_t start_time; uint64_t end_time; diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index f237daeff..23bb076f2 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -53,9 +53,23 @@ static const std::map g_units = { "zs", -21 }, }; -static double stringToTime(std::string str) +struct scaled_time { + uint64_t time; + int scale; + bool end; +}; + +static uint64_t pow10(int n) { - if (str=="END") return -1; + int r = 1; + while (n--) + r *= 10; + return r; +} + +static scaled_time stringToTime(std::string str) +{ + if (str=="END") return {1, 0, true}; char *endptr; long value = strtol(str.c_str(), &endptr, 10); @@ -66,7 +80,7 @@ static double stringToTime(std::string str) if (value < 0) log_error("Time value '%s' must be positive\n", str); - return value * pow(10.0, g_units.at(endptr)); + return {(unsigned long)value, g_units.at(endptr), false}; } struct SimWorker; @@ -110,8 +124,8 @@ struct SimShared bool hdlname = false; int rstlen = 1; FstData *fst = nullptr; - double start_time = 0; - double stop_time = -1; + scaled_time start_time = {0, 0, false}; + scaled_time stop_time = {1, 0, true}; SimulationMode sim_mode = SimulationMode::sim; bool cycles_set = false; std::vector> outputfiles; @@ -1514,27 +1528,27 @@ struct SimWorker : SimShared uint64_t startCount = 0; uint64_t stopCount = 0; - if (start_time==0) { - if (start_time < fst->getStartTime()) + if (start_time.time == 0) { + if (start_time.time < fst->getStartTime()) log_warning("Start time is before simulation file start time\n"); startCount = fst->getStartTime(); - } else if (start_time==-1) + } else if (start_time.end) startCount = fst->getEndTime(); else { - startCount = start_time / fst->getTimescale(); + startCount = start_time.time * pow10(start_time.scale - fst->getScale()); if (startCount > fst->getEndTime()) { startCount = fst->getEndTime(); log_warning("Start time is after simulation file end time\n"); } } - if (stop_time==0) { - if (stop_time < fst->getStartTime()) + if (stop_time.time == 0) { + if (stop_time.time < fst->getStartTime()) log_warning("Stop time is before simulation file start time\n"); stopCount = fst->getStartTime(); - } else if (stop_time==-1) + } else if (stop_time.end) stopCount = fst->getEndTime(); else { - stopCount = stop_time / fst->getTimescale(); + stopCount = stop_time.time * pow10(stop_time.scale - fst->getScale()); if (stopCount > fst->getEndTime()) { stopCount = fst->getEndTime(); log_warning("Stop time is after simulation file end time\n"); @@ -2174,27 +2188,27 @@ struct SimWorker : SimShared uint64_t startCount = 0; uint64_t stopCount = 0; - if (start_time==0) { - if (start_time < fst->getStartTime()) + if (start_time.time == 0) { + if (start_time.time < fst->getStartTime()) log_warning("Start time is before simulation file start time\n"); startCount = fst->getStartTime(); - } else if (start_time==-1) + } else if (start_time.end) startCount = fst->getEndTime(); else { - startCount = start_time / fst->getTimescale(); + startCount = start_time.time * pow10(start_time.scale - fst->getScale()); if (startCount > fst->getEndTime()) { startCount = fst->getEndTime(); log_warning("Start time is after simulation file end time\n"); } } - if (stop_time==0) { - if (stop_time < fst->getStartTime()) + if (stop_time.time == 0) { + if (stop_time.time < fst->getStartTime()) log_warning("Stop time is before simulation file start time\n"); stopCount = fst->getStartTime(); - } else if (stop_time==-1) + } else if (stop_time.end) stopCount = fst->getEndTime(); else { - stopCount = stop_time / fst->getTimescale(); + stopCount = stop_time.time * pow10(stop_time.scale - fst->getScale()); if (stopCount > fst->getEndTime()) { stopCount = fst->getEndTime(); log_warning("Stop time is after simulation file end time\n"); From 23a05fcf356993e9995b609e49bf6dd294b6a146 Mon Sep 17 00:00:00 2001 From: Scott Ashcroft Date: Thu, 23 Apr 2026 17:18:24 +0100 Subject: [PATCH 116/176] Add comments to make sure it is clear scale is an exponent of 10 --- kernel/fstdata.h | 2 +- passes/sat/sim.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/fstdata.h b/kernel/fstdata.h index 7f763b621..43f779cb5 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -69,7 +69,7 @@ private: uint64_t last_time; std::map past_data; uint64_t past_time; - int scale; + int scale; // exponent of 10, e.g. -6 = us, -9 = ns std::string timescale_str; uint64_t start_time; uint64_t end_time; diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 23bb076f2..1be993154 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -55,7 +55,7 @@ static const std::map g_units = struct scaled_time { uint64_t time; - int scale; + int scale; // exponent of 10, e.g. -6 = us, -9 = ns bool end; }; From 390f09b89ae742c417d22ac080c2656d55700696 Mon Sep 17 00:00:00 2001 From: "Christopher D. Leary" Date: Tue, 21 Apr 2026 22:29:53 -0700 Subject: [PATCH 117/176] Support positional assignment patterns for unpacked arrays --- frontends/ast/ast.cc | 11 ++ frontends/ast/ast.h | 1 + frontends/ast/genrtlil.cc | 12 ++ frontends/ast/simplify.cc | 186 +++++++++++++++--- frontends/verilog/verilog_parser.y | 17 +- tests/svtypes/array_assign.sv | 81 ++++++++ .../array_assign_flat_multidim_pattern.ys | 10 + 7 files changed, 286 insertions(+), 32 deletions(-) create mode 100644 tests/svtypes/array_assign_flat_multidim_pattern.ys diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 984c4294c..c190bc7d4 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -100,6 +100,7 @@ std::string AST::type2str(AstNodeType type) X(AST_CAST_SIZE) X(AST_CONCAT) X(AST_REPLICATE) + X(AST_ASSIGN_PATTERN) X(AST_BIT_NOT) X(AST_BIT_AND) X(AST_BIT_OR) @@ -696,6 +697,16 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const fprintf(f, "}}"); break; + case AST_ASSIGN_PATTERN: + fprintf(f, "'{"); + for (int i = 0; i < GetSize(children); i++) { + if (i != 0) + fprintf(f, ", "); + children[i]->dumpVlog(f, ""); + } + fprintf(f, "}"); + break; + if (0) { case AST_BIT_NOT: txt = "~"; } if (0) { case AST_REDUCE_AND: txt = "&"; } if (0) { case AST_REDUCE_OR: txt = "|"; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index fd8ecddd7..f92b4a5b8 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -78,6 +78,7 @@ namespace AST AST_CAST_SIZE, AST_CONCAT, AST_REPLICATE, + AST_ASSIGN_PATTERN, AST_BIT_NOT, AST_BIT_AND, AST_BIT_OR, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 966fe563a..d9bafcd3a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1212,6 +1212,15 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun sign_hint = false; break; + case AST_ASSIGN_PATTERN: + for (auto& child : children) { + sub_width_hint = 0; + sub_sign_hint = true; + child->detectSignWidthWorker(sub_width_hint, sub_sign_hint); + } + sign_hint = false; + break; + case AST_NEG: case AST_BIT_NOT: case AST_POS: @@ -1824,6 +1833,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) return sig; } + case AST_ASSIGN_PATTERN: + input_error("Assignment pattern is only supported for whole unpacked array assignments.\n"); + // generate cells for unary operations: $not, $pos, $neg if (0) { case AST_BIT_NOT: type_name = ID($not); } if (0) { case AST_POS: type_name = ID($pos); } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f314ff3d5..48a4291d2 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -91,6 +91,11 @@ void AstNode::fixup_hierarchy_flags(bool force_descend) children[0]->set_in_param_flag(true, force_descend); break; + case AST_ASSIGN_PATTERN: + for (auto& child : children) + child->set_in_param_flag(in_param, force_descend); + break; + case AST_GENFOR: case AST_FOR: for (auto& child : children) { @@ -297,6 +302,23 @@ static bool arrays_have_compatible_dims(AstNode *mem_a, AstNode *mem_b) return a_width == b_width; } +// Check if mem_b matches mem_a's unpacked dimensions starting at first_dim. +static bool arrays_have_compatible_dims_from(AstNode *mem_a, int first_dim, AstNode *mem_b) +{ + if (mem_b->unpacked_dimensions != mem_a->unpacked_dimensions - first_dim) + return false; + for (int i = 0; i < mem_b->unpacked_dimensions; i++) { + if (mem_a->dimensions[first_dim + i].range_width != mem_b->dimensions[i].range_width) + return false; + } + // Also check packed dimensions (element width) + int a_width, a_size, a_bits; + int b_width, b_size, b_bits; + mem_a->meminfo(a_width, a_size, a_bits); + mem_b->meminfo(b_width, b_size, b_bits); + return a_width == b_width; +} + // Convert per-dimension element positions to declared index values. // Position 0 is the first declared element for each unpacked dimension. static std::vector array_indices_from_position(AstNode *mem, const std::vector &position) @@ -1730,6 +1752,12 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin children_are_self_determined = true; break; + case AST_ASSIGN_PATTERN: + // Assignment pattern elements are context-determined by the target element type. + // Keep child width context intact until whole-array assignment expansion creates scalar assignments. + detect_width_simple = true; + break; + case AST_NEG: case AST_BIT_NOT: case AST_POS: @@ -3277,7 +3305,7 @@ skip_dynamic_range_lvalue_expansion:; } } - // Expand array assignment: arr_out = arr_in OR arr_out = cond ? arr_a : arr_b + // Expand array assignment: arr_out = arr_in OR arr_out = cond ? arr_a : arr_b OR arr_out = '{a, b} // Supports multi-dimensional unpacked arrays if ((type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE || type == AST_ASSIGN) && is_unexpanded_array_ref(children[0].get())) @@ -3294,30 +3322,27 @@ skip_dynamic_range_lvalue_expansion:; is_unexpanded_array_ref(rhs->children[1].get()) && is_unexpanded_array_ref(rhs->children[2].get())); - if (is_direct_assign || is_ternary_assign) + // Case 3: Positional assignment pattern (out = '{a, b}) + bool is_pattern_assign = rhs->type == AST_ASSIGN_PATTERN; + + if (is_direct_assign || is_ternary_assign || is_pattern_assign) { AstNode *direct_rhs_mem = nullptr; AstNode *true_mem = nullptr; AstNode *false_mem = nullptr; - // Validate array compatibility - if (is_direct_assign) { - direct_rhs_mem = rhs->id2ast; - if (!arrays_have_compatible_dims(lhs_mem, direct_rhs_mem)) - input_error("Array dimension mismatch in assignment\n"); - } else { - true_mem = rhs->children[1]->id2ast; - false_mem = rhs->children[2]->id2ast; - if (!arrays_have_compatible_dims(lhs_mem, true_mem) || - !arrays_have_compatible_dims(lhs_mem, false_mem)) - input_error("Array dimension mismatch in ternary expression\n"); - } - int num_dims = lhs_mem->unpacked_dimensions; + int total_elements = 1; + for (int d = 0; d < num_dims; d++) + total_elements *= lhs_mem->dimensions[d].range_width; + int element_width, mem_size, addr_bits; + lhs_mem->meminfo(element_width, mem_size, addr_bits); + bool pattern_is_flat = false; - // Helper to add index to an identifier clone + // Helper to add indices to an array identifier clone. auto add_indices_to_id = [&](std::unique_ptr id, const std::vector& indices) { - if (num_dims == 1) { + int indexed_dims = GetSize(indices); + if (indexed_dims == 1) { // Single dimension: use AST_RANGE id->children.push_back(std::make_unique(location, AST_RANGE, mkconst_int(location, indices[0], true))); @@ -3330,44 +3355,139 @@ skip_dynamic_range_lvalue_expansion:; } id->children.push_back(std::move(multirange)); } - id->integer = num_dims; + id->integer = indexed_dims; // Reset basic_prep so multirange gets resolved during subsequent simplify passes id->basic_prep = false; return id; }; - // Calculate total number of elements and warn if large - int total_elements = 1; - for (int d = 0; d < num_dims; d++) - total_elements *= lhs_mem->dimensions[d].range_width; + auto add_position_to_id = [&](std::unique_ptr id, AstNode *mem, const std::vector& position) { + return add_indices_to_id(std::move(id), array_indices_from_position(mem, position)); + }; + + // Validate nested assignment pattern shape against unpacked dimensions. + std::function validate_pattern_shape = [&](AstNode *pattern, int dim) { + log_assert(pattern->type == AST_ASSIGN_PATTERN); + + int expected = lhs_mem->dimensions[dim].range_width; + if (GetSize(pattern->children) != expected) + input_error("Assignment pattern element count mismatch at dimension %d: got %d, expected %d\n", + dim + 1, GetSize(pattern->children), expected); + + if (dim + 1 == num_dims) + return; + + for (auto& child : pattern->children) { + if (child->type == AST_ASSIGN_PATTERN) { + validate_pattern_shape(child.get(), dim + 1); + } else if (is_unexpanded_array_ref(child.get()) && + arrays_have_compatible_dims_from(lhs_mem, dim + 1, child->id2ast)) { + continue; + } else { + input_error("Nested assignment pattern or compatible array expression required for dimension %d\n", dim + 2); + } + } + }; + + // Select the assignment pattern element for an unpacked array position. + auto pattern_element_at_position = [&](const std::vector& position, int flat_index) { + if (pattern_is_flat) + return rhs->children[flat_index]->clone(); + + AstNode *pattern = rhs; + for (int d = 0; d < num_dims; d++) { + log_assert(pattern->type == AST_ASSIGN_PATTERN); + AstNode *element = pattern->children[position[d]].get(); + + if (d + 1 == num_dims) + return element->clone(); + + if (element->type == AST_ASSIGN_PATTERN) { + pattern = element; + } else { + std::vector subposition(position.begin() + d + 1, position.end()); + return add_position_to_id(element->clone(), element->id2ast, subposition); + } + } + log_abort(); + }; + + // Validate array compatibility + if (is_direct_assign) { + direct_rhs_mem = rhs->id2ast; + if (!arrays_have_compatible_dims(lhs_mem, direct_rhs_mem)) + input_error("Array dimension mismatch in assignment\n"); + } else if (is_ternary_assign) { + true_mem = rhs->children[1]->id2ast; + false_mem = rhs->children[2]->id2ast; + if (!arrays_have_compatible_dims(lhs_mem, true_mem) || + !arrays_have_compatible_dims(lhs_mem, false_mem)) + input_error("Array dimension mismatch in ternary expression\n"); + } else { + if (num_dims > 1 && GetSize(rhs->children) == lhs_mem->dimensions[0].range_width) { + validate_pattern_shape(rhs, 0); + } else if (num_dims == 1 && GetSize(rhs->children) == total_elements) { + pattern_is_flat = true; + } else { + if (num_dims > 1 && GetSize(rhs->children) == lhs_mem->dimensions[0].range_width) + validate_pattern_shape(rhs, 0); + int expected = num_dims > 1 ? lhs_mem->dimensions[0].range_width : total_elements; + input_error("Assignment pattern element count mismatch: got %d, expected %d\n", GetSize(rhs->children), expected); + } + } + + // Warn if array assignment expansion is large. if (total_elements > 10000) log_warning("Expanding array assignment with %d elements at %s, this may be slow.\n", total_elements, location.to_string().c_str()); // Collect all assignments std::vector> assignments; + std::vector> pattern_temp_assignments; foreach_array_position(lhs_mem, [&](const std::vector& position) { - auto lhs_indices = array_indices_from_position(lhs_mem, position); - auto lhs_idx = add_indices_to_id(lhs->clone(), lhs_indices); + auto lhs_idx = add_position_to_id(lhs->clone(), lhs_mem, position); std::unique_ptr rhs_expr; if (is_direct_assign) { - auto rhs_indices = array_indices_from_position(direct_rhs_mem, position); - rhs_expr = add_indices_to_id(rhs->clone(), rhs_indices); - } else { + rhs_expr = add_position_to_id(rhs->clone(), direct_rhs_mem, position); + } else if (is_ternary_assign) { // Ternary case AstNode *cond = rhs->children[0].get(); AstNode *true_val = rhs->children[1].get(); AstNode *false_val = rhs->children[2].get(); - auto true_indices = array_indices_from_position(true_mem, position); - auto false_indices = array_indices_from_position(false_mem, position); - auto true_idx = add_indices_to_id(true_val->clone(), true_indices); - auto false_idx = add_indices_to_id(false_val->clone(), false_indices); + auto true_idx = add_position_to_id(true_val->clone(), true_mem, position); + auto false_idx = add_position_to_id(false_val->clone(), false_mem, position); rhs_expr = std::make_unique(location, AST_TERNARY, cond->clone(), std::move(true_idx), std::move(false_idx)); + } else { + auto pattern_rhs = pattern_element_at_position(position, GetSize(assignments)); + + if (type == AST_ASSIGN_EQ) { + auto wire_tmp_owned = std::make_unique(location, AST_WIRE, + std::make_unique(location, AST_RANGE, + mkconst_int(location, element_width - 1, true), + mkconst_int(location, 0, true))); + auto wire_tmp = wire_tmp_owned.get(); + wire_tmp->str = stringf("$assignpattern$%s:%d$%d", + RTLIL::encode_filename(*location.begin.filename), location.begin.line, autoidx++); + current_scope[wire_tmp->str] = wire_tmp; + current_ast_mod->children.push_back(std::move(wire_tmp_owned)); + wire_tmp->set_attribute(ID::nosync, AstNode::mkconst_int(location, 1, false)); + while (wire_tmp->simplify(true, 1, -1, false)) { } + wire_tmp->is_logic = true; + wire_tmp->is_signed = lhs_mem->is_signed; + + auto tmp_id = std::make_unique(location, AST_IDENTIFIER); + tmp_id->str = wire_tmp->str; + pattern_temp_assignments.push_back(std::make_unique(location, AST_ASSIGN_EQ, + tmp_id->clone(), std::move(pattern_rhs))); + rhs_expr = std::move(tmp_id); + } else { + rhs_expr = std::move(pattern_rhs); + } } auto assign = std::make_unique(location, type, @@ -3386,6 +3506,8 @@ skip_dynamic_range_lvalue_expansion:; } else { // Wrap in AST_BLOCK for procedural newNode = std::make_unique(location, AST_BLOCK); + for (auto& assign : pattern_temp_assignments) + newNode->children.push_back(std::move(assign)); for (auto& assign : assignments) newNode->children.push_back(std::move(assign)); } @@ -4652,6 +4774,8 @@ replace_fcall_later:; tmp_bits.insert(tmp_bits.end(), children.at(1)->bits.begin(), children.at(1)->bits.end()); newNode = children.at(1)->is_string ? mkconst_str(location, tmp_bits) : mkconst_bits(location, tmp_bits, false); break; + case AST_ASSIGN_PATTERN: + goto not_const; default: not_const: break; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 148a6cc63..b394ce074 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -546,7 +546,7 @@ %token TOK_z "'z'" %type range range_or_multirange non_opt_range non_opt_multirange -%type wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type +%type wire_type expr basic_expr concat_list assignment_pattern_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type %type opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number %type type_name %type opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type @@ -3349,6 +3349,11 @@ basic_expr: TOK_LCURL concat_list TOK_RCURL { $$ = std::move($2); } | + OP_CAST TOK_LCURL assignment_pattern_list optional_comma TOK_RCURL { + if (!mode->sv) + err_at_loc(@1, "Assignment patterns are only supported in SystemVerilog mode."); + $$ = std::move($3); + } | TOK_LCURL expr TOK_LCURL concat_list TOK_RCURL TOK_RCURL { $$ = std::make_unique(@$, AST_REPLICATE, std::move($2), std::move($4)); } | @@ -3580,6 +3585,16 @@ concat_list: $$->children.push_back(std::move($1)); }; +assignment_pattern_list: + expr { + $$ = std::make_unique(@$, AST_ASSIGN_PATTERN); + $$->children.push_back(std::move($1)); + } | + assignment_pattern_list TOK_COMMA expr { + $$ = std::move($1); + $$->children.push_back(std::move($3)); + }; + integral_number: TOK_CONSTVAL { $$ = std::move($1); } | TOK_UNBASED_UNSIZED_CONSTVAL { $$ = std::move($1); } | diff --git a/tests/svtypes/array_assign.sv b/tests/svtypes/array_assign.sv index a5ca6363c..f23a08d27 100644 --- a/tests/svtypes/array_assign.sv +++ b/tests/svtypes/array_assign.sv @@ -84,4 +84,85 @@ module top; assert(pt_o[0] == 1'b0); assert(pt_o[1] == 1'b1); end + + // Test 9: Positional assignment pattern on a whole unpacked array + // Covers the parser and continuous assignment expansion path for `'{...}. + wire ap_table [1]; + wire ap_i = 1'b0; + wire ap_out; + assign ap_table = '{1'h1}; + assign ap_out = ap_table[ap_i > 1'h0 ? 1'h0 : ap_i]; + always_comb begin + assert(ap_out == 1'b1); + end + + // Test 10: Positional assignment pattern preserves left-to-right element order. + wire ap_order [2]; + assign ap_order = '{1'b0, 1'b1}; + always_comb begin + assert(ap_order[0] == 1'b0); + assert(ap_order[1] == 1'b1); + end + + function automatic logic ap_identity(input logic value); + ap_identity = value; + endfunction + + // Test 11: The first assignment pattern element is a runtime expression. + wire ap_runtime_in = 1'b1; + wire ap_runtime [2]; + assign ap_runtime = '{ap_identity(ap_runtime_in), 1'b0}; + always_comb begin + assert(ap_runtime[0] == 1'b1); + assert(ap_runtime[1] == 1'b0); + end + + // Test 12: Nested positional assignment pattern on a multidimensional array. + wire ap_nested [2][2]; + assign ap_nested = '{'{1'b1, 1'b0}, '{1'b0, 1'b1}}; + always_comb begin + assert(ap_nested[0][0] == 1'b1); + assert(ap_nested[0][1] == 1'b0); + assert(ap_nested[1][0] == 1'b0); + assert(ap_nested[1][1] == 1'b1); + end + + // Test 13: Multidimensional assignment pattern with row expressions. + wire ap_row0 [2]; + wire ap_row1 [2]; + wire ap_rows [2][2]; + assign ap_row0 = '{1'b1, 1'b0}; + assign ap_row1 = '{1'b0, 1'b1}; + assign ap_rows = '{ap_row0, ap_row1}; + always_comb begin + assert(ap_rows[0][0] == 1'b1); + assert(ap_rows[0][1] == 1'b0); + assert(ap_rows[1][0] == 1'b0); + assert(ap_rows[1][1] == 1'b1); + end + + // Test 14: Procedural blocking assignment pattern preserves RHS values. + logic ap_swap [2]; + always_comb begin + ap_swap[0] = 1'b0; + ap_swap[1] = 1'b1; + ap_swap = '{ap_swap[1], ap_swap[0]}; + + assert(ap_swap[0] == 1'b1); + assert(ap_swap[1] == 1'b0); + end + + // Test 15: Assignment pattern elements use the target element width context. + logic [4:0] ap_width_ctx [1]; + assign ap_width_ctx = '{4'hf + 4'h1}; + always_comb begin + assert(ap_width_ctx[0] == 5'h10); + end + + // Test 16: Nested assignment pattern elements also use the target element width context. + logic [4:0] ap_nested_width_ctx [1][1]; + assign ap_nested_width_ctx = '{'{4'hf + 4'h1}}; + always_comb begin + assert(ap_nested_width_ctx[0][0] == 5'h10); + end endmodule diff --git a/tests/svtypes/array_assign_flat_multidim_pattern.ys b/tests/svtypes/array_assign_flat_multidim_pattern.ys new file mode 100644 index 000000000..a2e57e2f5 --- /dev/null +++ b/tests/svtypes/array_assign_flat_multidim_pattern.ys @@ -0,0 +1,10 @@ +logger -expect error "Assignment pattern element count mismatch: got 4, expected 2" 1 + +read_verilog -sv < Date: Thu, 23 Apr 2026 17:47:17 +0200 Subject: [PATCH 118/176] rtlil: complicate extract again for packing --- kernel/rtlil.cc | 24 +++++++- kernel/rtlil.h | 3 + tests/unit/kernel/rtlilHelpers.h | 71 ++++++++++++++++++++++++ tests/unit/kernel/sigspecExtract2Test.cc | 57 +++++++++++++++++++ tests/unit/kernel/sigspecRemove2Test.cc | 26 ++++----- 5 files changed, 167 insertions(+), 14 deletions(-) create mode 100644 tests/unit/kernel/rtlilHelpers.h create mode 100644 tests/unit/kernel/sigspecExtract2Test.cc diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c0f6e0d81..a99f0803e 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -5273,9 +5273,31 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const log_assert(offset + length <= size()); std::vector extracted; + SigBit first; + bool is_packing = true; for (int i = offset; i < offset + length; i++) { - extracted.push_back((*this)[i]); + bool was_packing_before = is_packing; + SigBit bit = (*this)[i]; + if (i == offset) { + first = bit; + if (!bit.wire) + is_packing = false; + } else { + if (bit.wire != first.wire) + is_packing = false; + if (bit.wire) + if (bit.offset != first.offset + (i - offset)) + is_packing = false; + } + if (was_packing_before && !is_packing) + for (int j = offset; j < i; j++) + extracted.push_back((*this)[j]); + if (!is_packing) + extracted.push_back((*this)[i]); } + if (is_packing) + return SigChunk(first.wire, first.offset, length); + return extracted; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index b9d86b91c..c10fd7df9 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1400,6 +1400,9 @@ struct RTLIL::SigSpecConstIterator struct RTLIL::SigSpec { private: + friend class SigSpecRepTest; + FRIEND_TEST(SigSpecRepTest, ExtractWires); + FRIEND_TEST(SigSpecRepTest, ExtractConsts); enum Representation : char { CHUNK, BITS, diff --git a/tests/unit/kernel/rtlilHelpers.h b/tests/unit/kernel/rtlilHelpers.h new file mode 100644 index 000000000..99585f23b --- /dev/null +++ b/tests/unit/kernel/rtlilHelpers.h @@ -0,0 +1,71 @@ +#ifndef RTLIL_HELPERS_H +#define RTLIL_HELPERS_H + +#include + +#include "kernel/rtlil.h" + +YOSYS_NAMESPACE_BEGIN + +class SigSpecRepTest : public ::testing::Test { +protected: + Design* d; + Module* m; + + void SetUp() override { + d = new Design; + m = d->addModule("$test"); + } + + void TearDown() override { + delete d; + } + + // Create n wires with given width + std::vector createWires(int count, int width = 4) { + std::vector wires; + for (int i = 0; i < count; i++) { + Wire* w = m->addWire(stringf("$w%d", i), width); + wires.push_back(w); + } + return wires; + } + + // Append all wires to a SigSpec + SigSpec wiresAsSigSpec(const std::vector& wires) { + SigSpec sig; + for (auto w : wires) + sig.append(w); + return sig; + } + + // Create a SigSpec of constants + SigSpec constsAsSigSpec(int count, int width = 4) { + SigSpec sig; + for (int i = 0; i < count; i++) + sig.append(Const(i, width)); + return sig; + } + + // Convert wires to pool of SigBits + pool wiresToPool(const std::vector& wires) { + pool pool; + for (auto w : wires) + for (auto &bit : SigSpec(w)) + pool.insert(bit); + return pool; + } + + // Convert wires to set of SigBits + std::set wiresToSet(const std::vector& wires) { + std::set set; + for (auto w : wires) + for (auto &bit : SigSpec(w)) + set.insert(bit); + return set; + } +}; + +YOSYS_NAMESPACE_END + +#endif /* RTLIL_HELPERS_H */ diff --git a/tests/unit/kernel/sigspecExtract2Test.cc b/tests/unit/kernel/sigspecExtract2Test.cc new file mode 100644 index 000000000..a38ff1ba6 --- /dev/null +++ b/tests/unit/kernel/sigspecExtract2Test.cc @@ -0,0 +1,57 @@ +#include + +#include "kernel/rtlil.h" +#include "tests/unit/kernel/rtlilHelpers.h" + +YOSYS_NAMESPACE_BEGIN + +namespace RTLIL { + TEST_F(SigSpecRepTest, ExtractWires) + { + auto wires = createWires(4, 4); + SigSpec sig = wiresAsSigSpec(wires); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(12, 4); + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + } + + TEST_F(SigSpecRepTest, ExtractConsts) + { + { + SigSpec sig = constsAsSigSpec(4, 4); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(12, 4); + std::cout << log_signal(extractedFirst) << "\n"; + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + } + + { + SigSpec sig; + sig.append(Const(0, 4)); + sig.append(m->addWire("$foo", 4)); + sig.append(Const(0, 4)); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(8, 4); + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + + SigSpec extractedFirstTwo = sig.extract(0, 8); + EXPECT_EQ(extractedFirstTwo.rep_, SigSpec::Representation::BITS); + SigSpec extractedLastTwo = sig.extract(0, 8); + EXPECT_EQ(extractedLastTwo.rep_, SigSpec::Representation::BITS); + } + } +}; + +YOSYS_NAMESPACE_END diff --git a/tests/unit/kernel/sigspecRemove2Test.cc b/tests/unit/kernel/sigspecRemove2Test.cc index a6789c774..9d7bf4863 100644 --- a/tests/unit/kernel/sigspecRemove2Test.cc +++ b/tests/unit/kernel/sigspecRemove2Test.cc @@ -5,7 +5,7 @@ YOSYS_NAMESPACE_BEGIN // Test fixture with helper functions -class SigSpecRemove2Test : public ::testing::Test { +class SigSpecRepTest : public ::testing::Test { protected: Design* d; Module* m; @@ -64,7 +64,7 @@ protected: } }; -TEST_F(SigSpecRemove2Test, WithSigSpecPattern) +TEST_F(SigSpecRepTest, WithSigSpecPattern) { auto wires = createWires(4); SigSpec sig = wiresAsSigSpec(wires); @@ -84,7 +84,7 @@ TEST_F(SigSpecRemove2Test, WithSigSpecPattern) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, WithPoolPattern) +TEST_F(SigSpecRepTest, WithPoolPattern) { auto wires = createWires(3); SigSpec sig = wiresAsSigSpec(wires); @@ -103,7 +103,7 @@ TEST_F(SigSpecRemove2Test, WithPoolPattern) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, WithSetPattern) +TEST_F(SigSpecRepTest, WithSetPattern) { auto wires = createWires(3); SigSpec sig = wiresAsSigSpec(wires); @@ -122,7 +122,7 @@ TEST_F(SigSpecRemove2Test, WithSetPattern) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, ManyElements) +TEST_F(SigSpecRepTest, ManyElements) { const int num_wires = 100; auto wires = createWires(num_wires); @@ -146,7 +146,7 @@ TEST_F(SigSpecRemove2Test, ManyElements) } // Test remove2 with very large dataset to check scaling -TEST_F(SigSpecRemove2Test, VeryLargeScalingTest) +TEST_F(SigSpecRepTest, VeryLargeScalingTest) { const int num_wires = 50000; auto wires = createWires(num_wires); @@ -173,7 +173,7 @@ TEST_F(SigSpecRemove2Test, VeryLargeScalingTest) } // Test multiple sequential removals (simulates removeSignalFromCaseTree) -TEST_F(SigSpecRemove2Test, MultipleSequentialRemovals) +TEST_F(SigSpecRepTest, MultipleSequentialRemovals) { const int num_wires = 512; auto wires = createWires(num_wires); @@ -204,7 +204,7 @@ TEST_F(SigSpecRemove2Test, MultipleSequentialRemovals) } // Test remove2 with very large dataset to check scaling -TEST_F(SigSpecRemove2Test, PoolOverloadLargeDataset) +TEST_F(SigSpecRepTest, PoolOverloadLargeDataset) { const int num_wires = 50000; auto wires = createWires(num_wires, 1); @@ -228,7 +228,7 @@ TEST_F(SigSpecRemove2Test, PoolOverloadLargeDataset) } // Test set overload (same perf characteristics as pool) -TEST_F(SigSpecRemove2Test, SetOverloadLargeDataset) +TEST_F(SigSpecRepTest, SetOverloadLargeDataset) { const int num_wires = 50000; auto wires = createWires(num_wires, 1); @@ -252,7 +252,7 @@ TEST_F(SigSpecRemove2Test, SetOverloadLargeDataset) } // Worst case: remove almost all elements -TEST_F(SigSpecRemove2Test, RemoveAlmostAllElements) +TEST_F(SigSpecRepTest, RemoveAlmostAllElements) { const int num_wires = 10000; auto wires = createWires(num_wires, 1); @@ -269,7 +269,7 @@ TEST_F(SigSpecRemove2Test, RemoveAlmostAllElements) EXPECT_EQ(sig[0].wire, wires[num_wires - 1]); } -TEST_F(SigSpecRemove2Test, EmptyPattern) +TEST_F(SigSpecRepTest, EmptyPattern) { auto wires = createWires(1); SigSpec sig(wires[0]); @@ -285,7 +285,7 @@ TEST_F(SigSpecRemove2Test, EmptyPattern) } // Test that NULL wire bits (constants) are not removed -TEST_F(SigSpecRemove2Test, NullWireBitsStay) +TEST_F(SigSpecRepTest, NullWireBitsStay) { auto wires = createWires(1); SigSpec sig; @@ -309,7 +309,7 @@ TEST_F(SigSpecRemove2Test, NullWireBitsStay) EXPECT_EQ(sig, expected); } -TEST_F(SigSpecRemove2Test, PartialBitRemoval) +TEST_F(SigSpecRepTest, PartialBitRemoval) { Wire* w = m->addWire("$w1", 8); SigSpec sig(w); From a2dafce910a463d0d622aa20b3f328953cbf641c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 24 Apr 2026 10:48:12 +0200 Subject: [PATCH 119/176] unit tests: rename SigSpec::extract test --- .../unit/kernel/{sigspecExtract2Test.cc => sigspecExtractTest.cc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/unit/kernel/{sigspecExtract2Test.cc => sigspecExtractTest.cc} (100%) diff --git a/tests/unit/kernel/sigspecExtract2Test.cc b/tests/unit/kernel/sigspecExtractTest.cc similarity index 100% rename from tests/unit/kernel/sigspecExtract2Test.cc rename to tests/unit/kernel/sigspecExtractTest.cc From 10bbda93f74ff788d7f16d27e38d9f63c6532e51 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 24 Apr 2026 11:03:02 +0200 Subject: [PATCH 120/176] rtlil: extend SigSpec::extract test --- kernel/rtlil.h | 3 +- tests/unit/kernel/sigspecExtractTest.cc | 70 ++++++++++++++++++------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c10fd7df9..b32f9ea76 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1401,8 +1401,7 @@ struct RTLIL::SigSpec { private: friend class SigSpecRepTest; - FRIEND_TEST(SigSpecRepTest, ExtractWires); - FRIEND_TEST(SigSpecRepTest, ExtractConsts); + FRIEND_TEST(SigSpecRepTest, Extract); enum Representation : char { CHUNK, BITS, diff --git a/tests/unit/kernel/sigspecExtractTest.cc b/tests/unit/kernel/sigspecExtractTest.cc index a38ff1ba6..87bd4f6da 100644 --- a/tests/unit/kernel/sigspecExtractTest.cc +++ b/tests/unit/kernel/sigspecExtractTest.cc @@ -6,38 +6,52 @@ YOSYS_NAMESPACE_BEGIN namespace RTLIL { - TEST_F(SigSpecRepTest, ExtractWires) - { - auto wires = createWires(4, 4); - SigSpec sig = wiresAsSigSpec(wires); - - SigSpec extractedFirst = sig.extract(0, 4); - SigSpec extractedSecond = sig.extract(4, 4); - SigSpec extractedLast = sig.extract(12, 4); - EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); - EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); - EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); - } - - TEST_F(SigSpecRepTest, ExtractConsts) + TEST_F(SigSpecRepTest, Extract) { { - SigSpec sig = constsAsSigSpec(4, 4); + std::vector wires; + SigSpec sig; + for (int i = 0; i < 4; i++) + wires.push_back(m->addWire(stringf("$w%d", i), 4)); + for (auto w : wires) + sig.append(w); SigSpec extractedFirst = sig.extract(0, 4); SigSpec extractedSecond = sig.extract(4, 4); SigSpec extractedLast = sig.extract(12, 4); - std::cout << log_signal(extractedFirst) << "\n"; EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedFirst.as_wire(), wires[0]); + EXPECT_EQ(extractedSecond.as_wire(), wires[1]); + EXPECT_EQ(extractedLast.as_wire(), wires[3]); + } + + { + std::vector consts; + SigSpec sig; + for (int i = 0; i < 4; i++) + consts.push_back(Const(i, 4)); + for (auto c : consts) + sig.append(c); + + SigSpec extractedFirst = sig.extract(0, 4); + SigSpec extractedSecond = sig.extract(4, 4); + SigSpec extractedLast = sig.extract(12, 4); + EXPECT_EQ(extractedFirst.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedSecond.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedLast.rep_, SigSpec::Representation::CHUNK); + EXPECT_EQ(extractedFirst, consts[0]); + EXPECT_EQ(extractedSecond, consts[1]); + EXPECT_EQ(extractedLast, consts[3]); } { SigSpec sig; sig.append(Const(0, 4)); - sig.append(m->addWire("$foo", 4)); - sig.append(Const(0, 4)); + Wire* w = m->addWire("$foo", 4); + sig.append(w); + sig.append(Const(15, 4)); SigSpec extractedFirst = sig.extract(0, 4); SigSpec extractedSecond = sig.extract(4, 4); @@ -48,8 +62,26 @@ namespace RTLIL { SigSpec extractedFirstTwo = sig.extract(0, 8); EXPECT_EQ(extractedFirstTwo.rep_, SigSpec::Representation::BITS); - SigSpec extractedLastTwo = sig.extract(0, 8); + SigSpec extractedLastTwo = sig.extract(4, 8); EXPECT_EQ(extractedLastTwo.rep_, SigSpec::Representation::BITS); + + EXPECT_EQ(extractedFirstTwo[0], State::S0); + EXPECT_EQ(extractedFirstTwo[1], State::S0); + EXPECT_EQ(extractedFirstTwo[2], State::S0); + EXPECT_EQ(extractedFirstTwo[3], State::S0); + EXPECT_EQ(extractedFirstTwo[4], SigBit(w, 0)); + EXPECT_EQ(extractedFirstTwo[5], SigBit(w, 1)); + EXPECT_EQ(extractedFirstTwo[6], SigBit(w, 2)); + EXPECT_EQ(extractedFirstTwo[7], SigBit(w, 3)); + + EXPECT_EQ(extractedLastTwo[0], SigBit(w, 0)); + EXPECT_EQ(extractedLastTwo[1], SigBit(w, 1)); + EXPECT_EQ(extractedLastTwo[2], SigBit(w, 2)); + EXPECT_EQ(extractedLastTwo[3], SigBit(w, 3)); + EXPECT_EQ(extractedLastTwo[4], State::S1); + EXPECT_EQ(extractedLastTwo[5], State::S1); + EXPECT_EQ(extractedLastTwo[6], State::S1); + EXPECT_EQ(extractedLastTwo[7], State::S1); } } }; From 4abaca273ebe7d581100954031ed2c7443c74fd7 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 23 Apr 2026 16:42:44 +0200 Subject: [PATCH 121/176] opt_reduce: further optimization --- passes/opt/opt_reduce.cc | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index 6d6cadfe7..b4592038b 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -110,22 +110,20 @@ struct OptReduceWorker RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S)); RTLIL::SigSpec new_sig_b, new_sig_s; - pool handled_sig; + dict> grouped_b_to_s; - handled_sig.insert(sig_a); - for (int i = 0; i < sig_s.size(); i++) - { - RTLIL::SigSpec this_b = sig_b.extract(i*sig_a.size(), sig_a.size()); - if (handled_sig.count(this_b) > 0) - continue; - - RTLIL::SigSpec this_s = sig_s.extract(i, 1); - for (int j = i+1; j < sig_s.size(); j++) { - RTLIL::SigSpec that_b = sig_b.extract(j*sig_a.size(), sig_a.size()); - if (this_b == that_b) - this_s.append(sig_s.extract(j, 1)); + int port_width = sig_a.size(); + for (int i = 0; i < sig_s.size(); i++) { + RTLIL::SigSpec this_b = sig_b.extract(i*port_width, port_width); + if (grouped_b_to_s.count(this_b)) { + grouped_b_to_s[this_b].push_back(sig_s[i]); + } else { + grouped_b_to_s[this_b] = {sig_s[i]}; } + } + for (auto &[this_b, this_s_bit] : grouped_b_to_s) { + RTLIL::SigSpec this_s{this_s_bit}; if (this_s.size() > 1) { RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or)); @@ -141,7 +139,6 @@ struct OptReduceWorker new_sig_b.append(this_b); new_sig_s.append(this_s); - handled_sig.insert(this_b); } if (new_sig_s.size() == 0) From e0b833ac1ab5c8d75c2995a05340d432e20d4ce7 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 24 Apr 2026 10:33:36 +0200 Subject: [PATCH 122/176] opt_muxtree: dense knowledge --- passes/opt/opt_muxtree.cc | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 0020af09f..8bf151e71 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -21,11 +21,9 @@ #include "kernel/sigtools.h" #include "kernel/log.h" #include "kernel/celltypes.h" +#include #include #include -#include -#include -#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -128,7 +126,7 @@ struct OptMuxtreeWorker // In case of $pmux, port B is multiple slices, concatenated, one per bit of port S for (int i = 0; i < GetSize(sig_s); i++) { RTLIL::SigSpec sig = sig_b.extract(i*GetSize(sig_a), GetSize(sig_a)); - RTLIL::SigSpec ctrl_sig = assign_map(sig_s.extract(i, 1)); + RTLIL::SigSpec ctrl_sig = assign_map(SigSpec{sig_s[i]}); portinfo_t portinfo = used_port_bit(sig, this_mux_idx); portinfo.ctrl_sig = sig2bits(ctrl_sig, false).front(); portinfo.const_activated = ctrl_sig.is_fully_const() && ctrl_sig.as_bool(); @@ -342,14 +340,21 @@ struct OptMuxtreeWorker // The payload is a reference counter used to manage the list // When it is non-zero, the signal in known to be inactive // When it reaches zero, the map element is removed - std::unordered_map known_inactive; + std::vector known_inactive; // database of known active signals - std::unordered_map known_active; + std::vector known_active; // this is just used to keep track of visited muxes in order to prohibit // endless recursion in mux loops - std::unordered_set visited_muxes; + std::vector visited_muxes; + + // Initialize with the maximum possible sizes + knowledge_t(int num_bits, int num_muxes) { + known_inactive.assign(num_bits, 0); + known_active.assign(num_bits, 0); + visited_muxes.assign(num_muxes, false); + } }; static void activate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) { @@ -366,11 +371,10 @@ struct OptMuxtreeWorker } static void deactivate_port(knowledge_t &knowledge, int port_idx, const muxinfo_t &muxinfo) { - auto unlearn = [](std::unordered_map& knowns, int i) { - auto it = knowns.find(i); - if (it != knowns.end()) - if (--it->second == 0) - knowns.erase(it); + auto unlearn = [](std::vector& knowns, int bit_idx) { + if (knowns[bit_idx] > 0) { + --knowns[bit_idx]; + } }; if (port_idx < GetSize(muxinfo.ports)-1 && !muxinfo.ports[port_idx].const_activated) @@ -418,9 +422,9 @@ struct OptMuxtreeWorker vector input_mux_queue; for (int m : muxinfo.ports[port_idx].input_muxes) { - if (knowledge.visited_muxes.count(m)) + if (knowledge.visited_muxes[m]) continue; - knowledge.visited_muxes.insert(m); + knowledge.visited_muxes[m] = true; input_mux_queue.push_back(m); } for (int m : input_mux_queue) { @@ -453,7 +457,7 @@ struct OptMuxtreeWorker // Allow revisiting input muxes, since evaluating other ports should // revisit these input muxes with different activation assumptions for (int m : input_mux_queue) - knowledge.visited_muxes.erase(m); + knowledge.visited_muxes[m] = false; // Undo our assumptions that the port is active deactivate_port(knowledge, port_idx, muxinfo); @@ -475,11 +479,11 @@ struct OptMuxtreeWorker vector bits = sig2bits(sig, false); for (int i = 0; i < GetSize(bits); i++) { if (bits[i] >= 0) { - if (knowledge.known_inactive.count(bits[i]) > 0) { + if (knowledge.known_inactive[bits[i]] > 0) { sig[i] = State::S0; did_something = true; } else - if (knowledge.known_active.count(bits[i]) > 0) { + if (knowledge.known_active[bits[i]] > 0) { sig[i] = State::S1; did_something = true; } @@ -552,7 +556,7 @@ struct OptMuxtreeWorker portinfo_t &portinfo = muxinfo.ports[port_idx]; if (portinfo.const_deactivated) continue; - if (knowledge.known_active.count(portinfo.ctrl_sig) > 0) { + if (knowledge.known_active[portinfo.ctrl_sig] > 0) { eval_mux_port(knowledge, mux_idx, port_idx, limits); return; } @@ -566,7 +570,7 @@ struct OptMuxtreeWorker if (portinfo.const_deactivated) continue; if (port_idx < GetSize(muxinfo.ports)-1) - if (knowledge.known_inactive.count(portinfo.ctrl_sig) > 0) + if (knowledge.known_inactive[portinfo.ctrl_sig] > 0) continue; eval_mux_port(knowledge, mux_idx, port_idx, limits); @@ -578,8 +582,8 @@ struct OptMuxtreeWorker void eval_root_mux(int mux_idx) { log_assert(glob_evals_left > 0); - knowledge_t knowledge; - knowledge.visited_muxes.insert(mux_idx); + knowledge_t knowledge(GetSize(bit2info), GetSize(mux2info)); + knowledge.visited_muxes[mux_idx] = true; limits_t limits = {}; limits.do_mark_ports_observable = root_enable_muxes.at(mux_idx); eval_mux(knowledge, mux_idx, limits); From c5a8c3cca502bc8d610e84c5f168f2e61b14ee79 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Wed, 22 Apr 2026 06:49:52 +0200 Subject: [PATCH 123/176] Made autotest.sh print log on error for easier debugging in CI setups. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Daniel Gröber via Debian. See also issue #5805. --- tests/tools/autotest.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index e19a8d5af..1dd3f1175 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -235,6 +235,7 @@ do echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog." fi fi + sed -e "s,^,${bn}: ," ${bn}.err $keeprunning || exit 1 fi done From 59b3b6d4e41a3483ef21bf10c4fdcd094f00473d Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Wed, 22 Apr 2026 05:51:48 +0200 Subject: [PATCH 124/176] Added locking around compiling in autotest.sh to avoid text busy race. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Daniel Gröber via Debian. See also issue #5805. --- tests/tools/autotest.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index e19a8d5af..782681a5e 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -25,9 +25,11 @@ firrtl2verilog="" xfirrtl="../xfirrtl" abcprog="$toolsdir/../../yosys-abc" +exec {lock}<"$toolsdir"; flock "$lock" 1>&2 if [ ! -f "$toolsdir/cmp_tbdata" -o "$toolsdir/cmp_tbdata.c" -nt "$toolsdir/cmp_tbdata" ]; then ( set -ex; ${CXX:-g++} -Wall -o "$toolsdir/cmp_tbdata" "$toolsdir/cmp_tbdata.c"; ) || exit 1 fi +flock -u "$lock"; exec {lock}>&- while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do case "$opt" in From c03c0d5f9d999a73ec36675aef5f9367005c2eea Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Thu, 16 Apr 2026 17:59:56 +0200 Subject: [PATCH 125/176] Adjusted dot call to avoid pdflatex rejecting input due to too high resolution. Set fairly randomly picked size when generating dot graphs based on example I came across, to avoid the following error from pdflatex when building documentation: [46 <./rdata_map_luts.pdf>] ! Dimension too large. I am not sure which size make sense, nor how to decide which value are best. This issue is a fix for a build problem reported in , which include a link to the build log of the failed build. --- docs/source/_images/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/_images/Makefile b/docs/source/_images/Makefile index 71f52c578..086821c60 100644 --- a/docs/source/_images/Makefile +++ b/docs/source/_images/Makefile @@ -33,7 +33,7 @@ TEX_FILES := $(shell find . -name *.tex) all_tex: $(TEX_FILES:.tex=.pdf) $(TEX_FILES:.tex=.svg) %.pdf: %.dot - $(FAKETIME) dot -Tpdf -o $@ $< + $(FAKETIME) dot -Tpdf -Gsize="9x15!" -o $@ $< %.pdf: %.tex cd $(@D) && $(FAKETIME) pdflatex $( Date: Wed, 22 Apr 2026 05:29:01 +0200 Subject: [PATCH 126/176] Use CPPFLAGS and CXXFLAGS when compiling in autotest.sh. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensure the build flags used elsewhere are included also during testing. Patch based on change from Daniel Gröber via Debian. See also issue #5805. --- tests/tools/autotest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index e19a8d5af..24bf4b449 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -26,7 +26,7 @@ xfirrtl="../xfirrtl" abcprog="$toolsdir/../../yosys-abc" if [ ! -f "$toolsdir/cmp_tbdata" -o "$toolsdir/cmp_tbdata.c" -nt "$toolsdir/cmp_tbdata" ]; then - ( set -ex; ${CXX:-g++} -Wall -o "$toolsdir/cmp_tbdata" "$toolsdir/cmp_tbdata.c"; ) || exit 1 + ( set -ex; ${CXX:-g++} -Wall ${CPPFLAGS} ${CXXFLAGS:-} -o "$toolsdir/cmp_tbdata" "$toolsdir/cmp_tbdata.c"; ) || exit 1 fi while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do From 0d3923d0868d0e2be7886854984016bc48451615 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 28 Apr 2026 12:33:21 +0100 Subject: [PATCH 127/176] abc_new: use default script if not specified --- passes/techmap/abc_new.cc | 16 ++++++++++++++ tests/techmap/abc_speed_gia_only.script | 28 ------------------------- tests/techmap/xaiger2-5169.ys | 2 +- 3 files changed, 17 insertions(+), 29 deletions(-) delete mode 100644 tests/techmap/abc_speed_gia_only.script diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 0afabce11..9850ff609 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -50,6 +50,17 @@ struct AbcNewPass : public ScriptPass { experimental(); } + void on_register() override + { + RTLIL::constpad["abc_new.script.speed"] = "+&st; &dch -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf; &st; &syn2; &if -g -K 6; &synch2 -r;" \ + "&nf"; + } + void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -110,6 +121,11 @@ struct AbcNewPass : public ScriptPass { } extra_args(args, argidx, d); + // If no script provided, use a default. + if (abc_exe_options.find("-script") == std::string::npos) { + d->scratchpad_set_string("abc9.script", RTLIL::constpad["abc_new.script.speed"]); + } + log_header(d, "Executing ABC_NEW pass.\n"); log_push(); run_script(d, run_from, run_to); diff --git a/tests/techmap/abc_speed_gia_only.script b/tests/techmap/abc_speed_gia_only.script deleted file mode 100644 index d3730fdb5..000000000 --- a/tests/techmap/abc_speed_gia_only.script +++ /dev/null @@ -1,28 +0,0 @@ -&st -&dch -r -&nf -&st -&syn2 -&if -g -K 6 -&synch2 -r -&nf -&st -&syn2 -&if -g -K 6 -&synch2 -r -&nf -&st -&syn2 -&if -g -K 6 -&synch2 -r -&nf -&st -&syn2 -&if -g -K 6 -&synch2 -r -&nf -&st -&syn2 -&if -g -K 6 -&synch2 -r -&nf diff --git a/tests/techmap/xaiger2-5169.ys b/tests/techmap/xaiger2-5169.ys index 110f17346..1678d56ac 100644 --- a/tests/techmap/xaiger2-5169.ys +++ b/tests/techmap/xaiger2-5169.ys @@ -57,4 +57,4 @@ endmodule EOF logger -expect error "Malformed design" 1 -abc_new -script abc_speed_gia_only.script -liberty ../../tests/liberty/normal.lib -liberty ../../tests/liberty/dff.lib +abc_new -liberty ../../tests/liberty/normal.lib -liberty ../../tests/liberty/dff.lib From d2f7fecef506a89e1abd94f1764b1f485e52b79e Mon Sep 17 00:00:00 2001 From: nella Date: Tue, 28 Apr 2026 15:21:54 +0200 Subject: [PATCH 128/176] Fix liberty cache warning with -genlib. --- passes/techmap/abc.cc | 2 +- passes/techmap/abc9_exe.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 9be02cacd..780df2b23 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1030,7 +1030,7 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module std::string merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, run_abc.dont_use_args, config.exe_file); if (!merged_scl.empty()) { run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); - } else { + } else if(!config.liberty_files.empty()) { log_warning("ABC: Merged scl conversion failed, using liberty format\n"); bool first_lib = true; for (std::string liberty_file : config.liberty_files) { diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index a67807909..e4c4e7529 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -186,7 +186,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe std::string merged_scl = convert_liberty_files_to_merged_scl(liberty_files, dont_use_args, exe_file); if (!merged_scl.empty()) { abc9_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); - } else { + } else if(!liberty_files.empty()) { log_warning("ABC: Merged scl conversion failed, using liberty format\n"); bool first_lib = true; for (std::string liberty_file : liberty_files) { From 805c3024114bffd4769391a5bec9a3752904673c Mon Sep 17 00:00:00 2001 From: Ethan Mahintorabi Date: Wed, 29 Apr 2026 20:48:14 +0000 Subject: [PATCH 129/176] simplemap: Moves $pmux mapping from techmap.v to simple map This Fixes the slow downs I observed in techmap.v, which we attempted to fix via the simplify ast.h route originally. This turned out to be rather complex though. By moving $pmux to simplemap we can just avoid that code. My test case now runs in 310s which is 40s faster than the baseline change. B:507898959 Signed-off-by: Ethan Mahintorabi --- passes/techmap/simplemap.cc | 45 ++++++++++++++++++++++++++++++++++++- techlibs/common/techmap.v | 44 +----------------------------------- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 0c7d1930e..93001df35 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -438,6 +438,48 @@ void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell) } } +void simplemap_pmux(RTLIL::Module *module, RTLIL::Cell *cell) +{ + RTLIL::SigSpec sig_a = cell->getPort(ID::A); + RTLIL::SigSpec sig_b = cell->getPort(ID::B); + RTLIL::SigSpec sig_s = cell->getPort(ID::S); + RTLIL::SigSpec sig_y = cell->getPort(ID::Y); + + int width = GetSize(sig_a); + int s_width = GetSize(sig_s); + + // Implement: |S + RTLIL::SigSpec any_s = sig_s; + logic_reduce(module, any_s, cell); + + for (int i = 0; i < width; i++) { + RTLIL::SigSpec b_and_bits; + + // Implement: B_AND_BITS = B_AND_S[WIDTH*j+i] + for (int j = 0; j < s_width; j++) { + RTLIL::Cell *and_gate = module->addCell(NEW_ID, ID($_AND_)); + transfer_src(and_gate, cell); + and_gate->setPort(ID::A, sig_b[j * width + i]); + and_gate->setPort(ID::B, sig_s[j]); + + RTLIL::SigSpec and_y = module->addWire(NEW_ID, 1); + and_gate->setPort(ID::Y, and_y); + b_and_bits.append(and_y); + } + + // Implement: Y_B[i] = |B_AND_BITS + logic_reduce(module, b_and_bits, cell); + + // Implement: Y[i] = |S ? Y_B[i] : A[i] + RTLIL::Cell *mux_gate = module->addCell(NEW_ID, ID($_MUX_)); + transfer_src(mux_gate, cell); + mux_gate->setPort(ID::A, sig_a[i]); + mux_gate->setPort(ID::B, b_and_bits); + mux_gate->setPort(ID::S, any_s); + mux_gate->setPort(ID::Y, sig_y[i]); + } +} + void simplemap_get_mappers(dict &mappers) { mappers[ID($not)] = simplemap_not; @@ -461,6 +503,7 @@ void simplemap_get_mappers(dict mappers[ID($ne)] = simplemap_eqne; mappers[ID($nex)] = simplemap_eqne; mappers[ID($mux)] = simplemap_mux; + mappers[ID($pmux)] = simplemap_pmux; mappers[ID($bwmux)] = simplemap_bwmux; mappers[ID($tribuf)] = simplemap_tribuf; mappers[ID($bmux)] = simplemap_bmux; @@ -515,7 +558,7 @@ struct SimplemapPass : public Pass { log("\n"); log(" $not, $pos, $and, $or, $xor, $xnor\n"); log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n"); - log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n"); + log(" $logic_not, $logic_and, $logic_or, $mux, $pmux, $tribuf\n"); log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff,\n"); log(" $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n"); log("\n"); diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index c3364e628..8061b2e81 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -59,7 +59,7 @@ module _90_simplemap_compare_ops; endmodule (* techmap_simplemap *) -(* techmap_celltype = "$buf $pos $slice $concat $mux $tribuf $bmux $bwmux $bweqx" *) +(* techmap_celltype = "$buf $pos $slice $concat $mux $pmux $tribuf $bmux $bwmux $bweqx" *) module _90_simplemap_various; endmodule @@ -563,48 +563,6 @@ module _90_pow (A, B, Y); wire _TECHMAP_FAIL_ = 1; endmodule - -// -------------------------------------------------------- -// Parallel Multiplexers -// -------------------------------------------------------- - -(* techmap_celltype = "$pmux" *) -module _90_pmux (A, B, S, Y); - parameter WIDTH = 1; - parameter S_WIDTH = 1; - - (* force_downto *) - input [WIDTH-1:0] A; - (* force_downto *) - input [WIDTH*S_WIDTH-1:0] B; - (* force_downto *) - input [S_WIDTH-1:0] S; - (* force_downto *) - output [WIDTH-1:0] Y; - - (* force_downto *) - wire [WIDTH-1:0] Y_B; - - genvar i, j; - generate - (* force_downto *) - wire [WIDTH*S_WIDTH-1:0] B_AND_S; - for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND - assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; - end:B_AND - for (i = 0; i < WIDTH; i = i + 1) begin:B_OR - (* force_downto *) - wire [S_WIDTH-1:0] B_AND_BITS; - for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT - assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; - end:B_AND_BITS_COLLECT - assign Y_B[i] = |B_AND_BITS; - end:B_OR - endgenerate - - assign Y = |S ? Y_B : A; -endmodule - // -------------------------------------------------------- // Demultiplexers // -------------------------------------------------------- From 5dfe1937a04cca1d8e087eb89c4ddfa6785dd560 Mon Sep 17 00:00:00 2001 From: bin Date: Fri, 1 May 2026 13:26:28 -0400 Subject: [PATCH 130/176] Upgrade to WASI SDK 33 and enable exceptions --- .github/workflows/extra-builds.yml | 4 ++-- Makefile | 7 ++++--- kernel/driver.cc | 13 ------------- passes/techmap/abc.cc | 5 ++++- passes/techmap/abc9_exe.cc | 5 ++++- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/.github/workflows/extra-builds.yml b/.github/workflows/extra-builds.yml index d6bf5226c..7209b3645 100644 --- a/.github/workflows/extra-builds.yml +++ b/.github/workflows/extra-builds.yml @@ -79,8 +79,8 @@ jobs: persist-credentials: false - name: Build run: | - WASI_SDK=wasi-sdk-27.0-x86_64-linux - WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz + WASI_SDK=wasi-sdk-33.0-x86_64-linux + WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-33/wasi-sdk-33.0-x86_64-linux.tar.gz if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi FLEX_VER=2.6.4 diff --git a/Makefile b/Makefile index 97e51633b..0a0c65a3e 100644 --- a/Makefile +++ b/Makefile @@ -291,18 +291,19 @@ ifeq ($(WASI_SDK),) CXX = clang++ AR = llvm-ar RANLIB = llvm-ranlib -WASIFLAGS := -target wasm32-wasi $(WASIFLAGS) +WASIFLAGS := -target wasm32-wasip1 $(WASIFLAGS) else CXX = $(WASI_SDK)/bin/clang++ AR = $(WASI_SDK)/bin/ar RANLIB = $(WASI_SDK)/bin/ranlib endif -CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS $(filter-out -fPIC,$(CXXFLAGS)) -LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS)) +CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS -fwasm-exceptions -mllvm -wasm-use-legacy-eh=false $(filter-out -fPIC,$(CXXFLAGS)) +LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS)) -fwasm-exceptions -lunwind LIBS := -lwasi-emulated-process-clocks $(filter-out -lrt,$(LIBS)) ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)" ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -D_WASI_EMULATED_PROCESS_CLOCKS -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING -DABC_NO_RLIMIT" ABCMKARGS += OPTFLAGS="-Os" +LTOFLAGS = EXE = .wasm DISABLE_SPAWN := 1 diff --git a/kernel/driver.cc b/kernel/driver.cc index d76841909..30c9a285f 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -144,19 +144,6 @@ int yosys_history_offset = 0; std::string yosys_history_file; #endif -#if defined(__wasm) -extern "C" { - // FIXME: WASI does not currently support exceptions. - void* __cxa_allocate_exception(size_t thrown_size) throw() { - return malloc(thrown_size); - } - bool __cxa_uncaught_exception() throw(); - void __cxa_throw(void* thrown_exception, struct std::type_info * tinfo, void (*dest)(void*)) { - std::terminate(); - } -} -#endif - void yosys_atexit() { #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 780df2b23..71c238ec7 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -70,6 +70,9 @@ # include # include #endif +#if defined(__wasm) +#include +#endif #include "frontends/blif/blifparse.h" #include "liberty_cache.h" @@ -1382,7 +1385,7 @@ void RunAbcState::run(ConcurrentStack &) FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering #if defined(__wasm) -#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to) +#define fd_renumber(from, to) (void)__wasilibc_fd_renumber(from, to) #else #define fd_renumber(from, to) dup2(from, to) #endif diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index e4c4e7529..a32816612 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -30,6 +30,9 @@ # include # include #endif +#if defined(__wasm) +#include +#endif #ifdef YOSYS_LINK_ABC namespace abc { @@ -296,7 +299,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering #if defined(__wasm) -#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to) +#define fd_renumber(from, to) (void)__wasilibc_fd_renumber(from, to) #else #define fd_renumber(from, to) dup2(from, to) #endif From df1fb14b0c20b98d8b7a95c97abc9393a7094d50 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 May 2026 10:26:58 +0200 Subject: [PATCH 131/176] Use latest brew LLVM on macOS --- Brewfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Brewfile b/Brewfile index 917f1bdb4..2530b323c 100644 --- a/Brewfile +++ b/Brewfile @@ -9,6 +9,6 @@ brew "python3" brew "uv" brew "xdot" brew "bash" -brew "llvm@20" +brew "llvm" brew "lld" brew "googletest" From 6cd784e52cb327f5c262695835ac89f69c7d9356 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 4 May 2026 15:47:40 +0200 Subject: [PATCH 132/176] Strip windows binaries --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 0a0c65a3e..543ec7f44 100644 --- a/Makefile +++ b/Makefile @@ -968,14 +968,14 @@ install-dev: $(PROGRAM_PREFIX)yosys-config share install: $(TARGETS) $(EXTRA_TARGETS) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR) $(INSTALL_SUDO) cp $(filter-out libyosys.so libyosys.a,$(TARGETS)) $(DESTDIR)$(BINDIR) -ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),) - if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys; fi +ifneq ($(filter $(PROGRAM_PREFIX)yosys$(EXE),$(TARGETS)),) + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys$(EXE); fi endif -ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),) - if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc; fi +ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc$(EXE),$(TARGETS)),) + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc$(EXE); fi endif -ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),) - if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib; fi +ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib$(EXE),$(TARGETS)),) + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib$(EXE); fi endif $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR) $(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/. From 16b893bd8816a98c5a243ebf7b8b213f1121fff2 Mon Sep 17 00:00:00 2001 From: nella Date: Mon, 4 May 2026 18:58:56 +0200 Subject: [PATCH 133/176] Add check before flatten in synth. --- techlibs/common/synth.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index daebd789a..76f048495 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -277,6 +277,7 @@ struct SynthPass : public ScriptPass { if (check_label("coarse")) { run("proc"); + run("check"); if (flatten || help_mode) run("flatten", " (if -flatten)"); run("opt_expr"); From 7fa660fc607b96ee4ccded97b6c2401fbce7ed7b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 4 May 2026 21:34:19 +0200 Subject: [PATCH 134/176] share: remove -force --- passes/opt/share.cc | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/passes/opt/share.cc b/passes/opt/share.cc index f7843cc08..bc363e251 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -36,7 +36,6 @@ struct ShareWorkerConfig { int limit; size_t pattern_limit; - bool opt_force; bool opt_aggressive; bool opt_fast; StaticCellTypes::Categories::Category generic_uni_ops, generic_bin_ops, generic_cbin_ops, generic_other_ops; @@ -363,11 +362,6 @@ struct ShareWorker not_a_muxed_cell: continue; - if (config.opt_force) { - shareable_cells.insert(cell); - continue; - } - if (cell->type.in(ID($memrd), ID($memrd_v2))) { if (cell->parameters.at(ID::CLK_ENABLE).as_bool()) continue; @@ -1509,14 +1503,6 @@ struct SharePass : public Pass { log("This pass merges shareable resources into a single resource. A SAT solver\n"); log("is used to determine if two resources are share-able.\n"); log("\n"); - log(" -force\n"); - log(" Per default the selection of cells that is considered for sharing is\n"); - log(" narrowed using a list of cell types. With this option all selected\n"); - log(" cells are considered for resource sharing.\n"); - log("\n"); - log(" IMPORTANT NOTE: If the -all option is used then no cells with internal\n"); - log(" state must be selected!\n"); - log("\n"); log(" -aggressive\n"); log(" Per default some heuristics are used to reduce the number of cells\n"); log(" considered for resource sharing to only large resources. This options\n"); @@ -1543,7 +1529,6 @@ struct SharePass : public Pass { config.limit = -1; config.pattern_limit = design->scratchpad_get_int("share.pattern_limit", 1000); - config.opt_force = false; config.opt_aggressive = false; config.opt_fast = false; @@ -1591,10 +1576,6 @@ struct SharePass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-force") { - config.opt_force = true; - continue; - } if (args[argidx] == "-aggressive") { config.opt_aggressive = true; continue; From 67fac1879c7bca1dfe99000618df6ed8e7c83842 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Tue, 5 May 2026 10:24:04 +1200 Subject: [PATCH 135/176] fixup dot pdf size limit Use US letter size as (a less arbitrary) max, since the final latexpdf size is the same. Drop the ! since smaller images are fine. Fix `x` -> `,` for `x,y` separator. --- docs/source/_images/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/_images/Makefile b/docs/source/_images/Makefile index 086821c60..dc75c97c9 100644 --- a/docs/source/_images/Makefile +++ b/docs/source/_images/Makefile @@ -32,8 +32,9 @@ FORCE: TEX_FILES := $(shell find . -name *.tex) all_tex: $(TEX_FILES:.tex=.pdf) $(TEX_FILES:.tex=.svg) +# limit output size to US letter (same as latexpdf output) to avoid oversize error %.pdf: %.dot - $(FAKETIME) dot -Tpdf -Gsize="9x15!" -o $@ $< + $(FAKETIME) dot -Tpdf -Gsize="8.5,11" -o $@ $< %.pdf: %.tex cd $(@D) && $(FAKETIME) pdflatex $( Date: Tue, 5 May 2026 13:06:20 +0200 Subject: [PATCH 136/176] Update ABC with 050-no-128-bit-archs.patch --- abc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abc b/abc index 405511f85..d217b3519 160000 --- a/abc +++ b/abc @@ -1 +1 @@ -Subproject commit 405511f850328ca05c08b1a77cdfd60464d5cb1d +Subproject commit d217b351925ffc5e3036073776fef1810d258499 From fff034d2f8b0d1d3a54ddde125881598fb93b3e5 Mon Sep 17 00:00:00 2001 From: nella Date: Tue, 5 May 2026 14:04:46 +0200 Subject: [PATCH 137/176] Add check before flatten in synth_*. --- techlibs/achronix/synth_achronix.cc | 1 + techlibs/analogdevices/synth_analogdevices.cc | 8 ++++++-- techlibs/anlogic/synth_anlogic.cc | 1 + techlibs/common/synth.cc | 5 +++-- techlibs/coolrunner2/synth_coolrunner2.cc | 1 + techlibs/easic/synth_easic.cc | 1 + techlibs/efinix/synth_efinix.cc | 1 + techlibs/fabulous/synth_fabulous.cc | 1 + techlibs/gatemate/synth_gatemate.cc | 1 + techlibs/gowin/synth_gowin.cc | 4 +++- techlibs/greenpak4/synth_greenpak4.cc | 1 + techlibs/ice40/synth_ice40.cc | 1 + techlibs/intel/synth_intel.cc | 6 ++++-- techlibs/intel_alm/synth_intel_alm.cc | 4 +++- techlibs/lattice/synth_lattice.cc | 4 +++- techlibs/microchip/synth_microchip.cc | 4 +++- techlibs/nanoxplore/synth_nanoxplore.cc | 4 +++- techlibs/quicklogic/synth_quicklogic.cc | 4 +++- techlibs/sf2/synth_sf2.cc | 1 + techlibs/xilinx/synth_xilinx.cc | 8 ++++++-- 20 files changed, 47 insertions(+), 14 deletions(-) diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc index 1b48f426b..f8993de91 100644 --- a/techlibs/achronix/synth_achronix.cc +++ b/techlibs/achronix/synth_achronix.cc @@ -129,6 +129,7 @@ struct SynthAchronixPass : public ScriptPass { if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/analogdevices/synth_analogdevices.cc b/techlibs/analogdevices/synth_analogdevices.cc index 00d2e18d6..aa27c78b6 100644 --- a/techlibs/analogdevices/synth_analogdevices.cc +++ b/techlibs/analogdevices/synth_analogdevices.cc @@ -277,8 +277,10 @@ struct SynthAnalogDevicesPass : public ScriptPass if (check_label("prepare")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(with '-flatten')"); + } if (active_design) active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); @@ -447,8 +449,10 @@ struct SynthAnalogDevicesPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef -noclkinv"); - if (flatten_before_abc) + if (flatten_before_abc) { + run("check"); run("flatten"); + } if (help_mode) run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); else if (abc9) { diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index a03374fb0..5c7c0b532 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -156,6 +156,7 @@ struct SynthAnlogicPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 76f048495..00d884107 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -277,9 +277,10 @@ struct SynthPass : public ScriptPass { if (check_label("coarse")) { run("proc"); - run("check"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", " (if -flatten)"); + } run("opt_expr"); run("opt_clean"); run("check"); diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index 7ee1393be..1b30f51bc 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -132,6 +132,7 @@ struct SynthCoolrunner2Pass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); } diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc index 6c5df7beb..aea517cc5 100644 --- a/techlibs/easic/synth_easic.cc +++ b/techlibs/easic/synth_easic.cc @@ -142,6 +142,7 @@ struct SynthEasicPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); } diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index ef245e755..14457c64b 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -148,6 +148,7 @@ struct SynthEfinixPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index f74dc8e26..0074a52af 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -286,6 +286,7 @@ struct SynthPass : public ScriptPass if (check_label("flatten", "(unless -noflatten)")) { if (flatten) { + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc index 7726e7a15..409b07964 100644 --- a/techlibs/gatemate/synth_gatemate.cc +++ b/techlibs/gatemate/synth_gatemate.cc @@ -210,6 +210,7 @@ struct SynthGateMatePass : public ScriptPass { run("proc"); if (!noflatten) { + run("check"); run("flatten"); } run("tribuf -logic"); diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index ac028e2a6..d5ebdafea 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -265,8 +265,10 @@ struct SynthGowinPass : public ScriptPass if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(unless -noflatten)"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index fa52ecfc6..7f91d6332 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -144,6 +144,7 @@ struct SynthGreenPAK4Pass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); } diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 0a4144451..86189c848 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -309,6 +309,7 @@ struct SynthIce40Pass : public ScriptPass if (check_label("flatten", "(unless -noflatten)")) { if (flatten) { + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index e02885cd0..0b0eb6ae9 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -198,9 +198,11 @@ struct SynthIntelPass : public ScriptPass { if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(skip if -noflatten)"); - run("tribuf -logic"); + } + run("tribuf -logic"); run("deminout"); run("opt_expr"); run("opt_clean"); diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc index 28852d7df..95dbb6e35 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -184,8 +184,10 @@ struct SynthIntelALMPass : public ScriptPass { if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(skip if -noflatten)"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/lattice/synth_lattice.cc b/techlibs/lattice/synth_lattice.cc index 744beb650..382dae3d8 100644 --- a/techlibs/lattice/synth_lattice.cc +++ b/techlibs/lattice/synth_lattice.cc @@ -402,8 +402,10 @@ struct SynthLatticePass : public ScriptPass if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/microchip/synth_microchip.cc b/techlibs/microchip/synth_microchip.cc index e1d3c393a..218ed310f 100644 --- a/techlibs/microchip/synth_microchip.cc +++ b/techlibs/microchip/synth_microchip.cc @@ -267,8 +267,10 @@ struct SynthMicrochipPass : public ScriptPass { if (check_label("prepare")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(with '-flatten')"); + } if (active_design) active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); diff --git a/techlibs/nanoxplore/synth_nanoxplore.cc b/techlibs/nanoxplore/synth_nanoxplore.cc index 3445ea1be..0b87c98c7 100644 --- a/techlibs/nanoxplore/synth_nanoxplore.cc +++ b/techlibs/nanoxplore/synth_nanoxplore.cc @@ -250,8 +250,10 @@ struct SynthNanoXplorePass : public ScriptPass if (check_label("coarse")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(skip if -noflatten)"); + } run("tribuf -logic"); run("deminout"); run("opt_expr"); diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 1026dc233..e65be1c58 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -212,8 +212,10 @@ struct SynthQuickLogicPass : public ScriptPass { if (check_label("prepare")) { run("proc"); - if (flatten) + if (flatten) { + run("check"); run("flatten", "(unless -noflatten)"); + } if (help_mode || family == "pp3") { run("tribuf -logic", " (for pp3)"); } diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc index ad335536b..7a7f87466 100644 --- a/techlibs/sf2/synth_sf2.cc +++ b/techlibs/sf2/synth_sf2.cc @@ -172,6 +172,7 @@ struct SynthSf2Pass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); + run("check"); run("flatten"); run("tribuf -logic"); run("deminout"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index c487206db..b08fbe499 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -355,8 +355,10 @@ struct SynthXilinxPass : public ScriptPass if (check_label("prepare")) { run("proc"); - if (flatten || help_mode) + if (flatten || help_mode) { + run("check"); run("flatten", "(with '-flatten')"); + } if (active_design) active_design->scratchpad_unset("tribuf.added_something"); run("tribuf -logic"); @@ -637,8 +639,10 @@ struct SynthXilinxPass : public ScriptPass if (check_label("map_luts")) { run("opt_expr -mux_undef -noclkinv"); - if (flatten_before_abc) + if (flatten_before_abc) { + run("check"); run("flatten"); + } if (help_mode) run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); else if (abc9) { From 7de7d04d7cc48d51bdd975fa6ba13dfae6bdafe0 Mon Sep 17 00:00:00 2001 From: nella Date: Tue, 5 May 2026 14:53:31 +0200 Subject: [PATCH 138/176] Update macro order. --- docs/source/code_examples/macro_commands/synth_ice40.ys | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/code_examples/macro_commands/synth_ice40.ys b/docs/source/code_examples/macro_commands/synth_ice40.ys index 443b8e0b0..07d960a64 100644 --- a/docs/source/code_examples/macro_commands/synth_ice40.ys +++ b/docs/source/code_examples/macro_commands/synth_ice40.ys @@ -6,6 +6,7 @@ begin: proc flatten: + check flatten tribuf -logic deminout From fecea911ff5cc6440a2381605ec435bc42239822 Mon Sep 17 00:00:00 2001 From: Lofty Date: Thu, 30 Apr 2026 11:35:03 +0100 Subject: [PATCH 139/176] synth_gatemate: add -abc_new option --- techlibs/gatemate/synth_gatemate.cc | 19 +++++++++++-- tests/arch/gatemate/add_sub.ys | 20 +++++++++++++ tests/arch/gatemate/adffs.ys | 44 +++++++++++++++++++++++++++++ tests/arch/gatemate/counter.ys | 25 ++++++++++++++++ tests/arch/gatemate/fsm.ys | 41 +++++++++++++++++++++++++++ tests/arch/gatemate/latches.ys | 20 +++++++++++++ tests/arch/gatemate/logic.ys | 23 +++++++++++++++ tests/arch/gatemate/luttrees.ys | 21 ++++++++++++++ tests/arch/gatemate/mul.ys | 26 +++++++++++++++++ tests/arch/gatemate/mux.ys | 37 ++++++++++++++++++++++++ 10 files changed, 273 insertions(+), 3 deletions(-) diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc index 7726e7a15..7e968228e 100644 --- a/techlibs/gatemate/synth_gatemate.cc +++ b/techlibs/gatemate/synth_gatemate.cc @@ -69,7 +69,8 @@ struct SynthGateMatePass : public ScriptPass log(" do not use CC_MX{8,4} multiplexer cells in output netlist.\n"); log("\n"); log(" -luttree\n"); - log(" use new LUT tree mapping approach (EXPERIMENTAL).\n"); + log(" use LUT tree mapping for output to nextpnr. Do not use this if targeting\n"); + log(" legacy p_r.\n"); log("\n"); log(" -dff\n"); log(" run 'abc' with -dff option\n"); @@ -77,6 +78,9 @@ struct SynthGateMatePass : public ScriptPass log(" -retime\n"); log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); + log(" -abc_new\n"); + log(" use 'abc_new' instead of 'abc' for mapping. (EXPERIMENTAL)\n"); + log("\n"); log(" -noiopad\n"); log(" disable I/O buffer insertion (useful for hierarchical or \n"); log(" out-of-context flows).\n"); @@ -90,7 +94,7 @@ struct SynthGateMatePass : public ScriptPass } string top_opt, vlog_file, json_file; - bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf; + bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf, abc_new; void clear_flags() override { @@ -108,6 +112,7 @@ struct SynthGateMatePass : public ScriptPass retime = false; noiopad = false; noclkbuf = false; + abc_new = false; } void execute(std::vector args, RTLIL::Design *design) override @@ -182,6 +187,10 @@ struct SynthGateMatePass : public ScriptPass noclkbuf = true; continue; } + if (args[argidx] == "-abc_new") { + abc_new = true; + continue; + } break; } extra_args(args, argidx, design); @@ -312,7 +321,11 @@ struct SynthGateMatePass : public ScriptPass if (dff) { abc_args += " -dff"; } - run("abc " + abc_args, "(with -luttree)"); + if (abc_new) { + run("abc_new " + abc_args, "(with -luttree and -abc_new)"); + } else { + run("abc " + abc_args, "(with -luttree, without -abc_new)"); + } run("techmap -map +/gatemate/lut_tree_map.v", "(with -luttree)"); run("gatemate_foldinv", "(with -luttree)"); run("techmap -map +/gatemate/inv_map.v", "(with -luttree)"); diff --git a/tests/arch/gatemate/add_sub.ys b/tests/arch/gatemate/add_sub.ys index bf261ba5a..6720e08a0 100644 --- a/tests/arch/gatemate/add_sub.ys +++ b/tests/arch/gatemate/add_sub.ys @@ -1,9 +1,29 @@ read_verilog ../common/add_sub.v hierarchy -top top proc +design -save orig + equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module select -assert-count 8 t:CC_ADDF select -assert-max 4 t:CC_LUT1 select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 8 t:CC_ADDF +select -assert-max 4 t:CC_LUT1 +select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 8 t:CC_ADDF +select -assert-max 4 t:CC_LUT1 +select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D diff --git a/tests/arch/gatemate/adffs.ys b/tests/arch/gatemate/adffs.ys index b2ded6e9d..0a80a4b48 100644 --- a/tests/arch/gatemate/adffs.ys +++ b/tests/arch/gatemate/adffs.ys @@ -31,6 +31,28 @@ select -assert-count 1 t:CC_DFF select -assert-max 1 t:CC_LUT2 select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + +design -load read +hierarchy -top dffs +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd dffs # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + design -load read hierarchy -top ndffnr proc @@ -41,3 +63,25 @@ select -assert-count 1 t:CC_BUFG select -assert-count 1 t:CC_DFF select -assert-max 1 t:CC_LUT2 select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D + +design -load read +hierarchy -top ndffnr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd ndffnr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_BUFG +select -assert-count 1 t:CC_DFF +select -assert-max 1 t:CC_LUT2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D diff --git a/tests/arch/gatemate/counter.ys b/tests/arch/gatemate/counter.ys index 77ed858b3..8aa04e5cb 100644 --- a/tests/arch/gatemate/counter.ys +++ b/tests/arch/gatemate/counter.ys @@ -2,6 +2,9 @@ read_verilog ../common/counter.v hierarchy -top top proc flatten + +design -save orig + equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module @@ -10,3 +13,25 @@ select -assert-count 8 t:CC_ADDF select -assert-count 1 t:CC_BUFG select -assert-count 8 t:CC_DFF select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D + +design -load orig + +equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 8 t:CC_ADDF +select -assert-count 1 t:CC_BUFG +select -assert-count 8 t:CC_DFF +select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D + +design -load orig + +equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module + +select -assert-count 8 t:CC_ADDF +select -assert-count 1 t:CC_BUFG +select -assert-count 8 t:CC_DFF +select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D diff --git a/tests/arch/gatemate/fsm.ys b/tests/arch/gatemate/fsm.ys index 506862c90..8af1a0a47 100644 --- a/tests/arch/gatemate/fsm.ys +++ b/tests/arch/gatemate/fsm.ys @@ -3,6 +3,8 @@ hierarchy -top fsm proc flatten +design -save orig + equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad async2sync miter -equiv -make_assert -flatten gold gate miter @@ -18,3 +20,42 @@ select -assert-max 5 t:CC_LUT2 select -assert-max 6 t:CC_LUT3 select -assert-max 9 t:CC_LUT4 select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 t:CC_LUT3 t:CC_LUT4 %% t:* %D + +design -load orig + +equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree +async2sync +miter -equiv -make_assert -flatten gold gate miter +stat +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 1 t:CC_BUFG +select -assert-count 6 t:CC_DFF +select -assert-max 2 t:CC_LUT1 +select -assert-count 1 t:CC_LUT2 +select -assert-max 14 t:CC_L2T4 +select -assert-max 5 t:CC_L2T5 +select -assert-max 1 t:CC_MX2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 t:CC_MX2 %% t:* %D + +design -load orig + +equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new +async2sync +miter -equiv -make_assert -flatten gold gate miter +stat +sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter + +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd fsm # Constrain all select calls below inside the top module + +select -assert-count 1 t:CC_BUFG +select -assert-count 6 t:CC_DFF +select -assert-count 2 t:CC_LUT2 +select -assert-count 9 t:CC_L2T4 +select -assert-count 6 t:CC_L2T5 +select -assert-count 1 t:CC_MX2 +select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 t:CC_MX2 %% t:* %D diff --git a/tests/arch/gatemate/latches.ys b/tests/arch/gatemate/latches.ys index 5f64c6db5..a044bf5d6 100644 --- a/tests/arch/gatemate/latches.ys +++ b/tests/arch/gatemate/latches.ys @@ -27,3 +27,23 @@ cd latchsr # Constrain all select calls below inside the top module select -assert-count 1 t:CC_DLT select -assert-max 2 t:CC_LUT3 select -assert-none t:CC_DLT t:CC_LUT3 %% t:* %D + +design -load read +hierarchy -top latchsr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd latchsr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_DLT +select -assert-max 2 t:CC_L2T4 +select -assert-none t:CC_DLT t:CC_L2T4 %% t:* %D + +design -load read +hierarchy -top latchsr +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd latchsr # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_DLT +select -assert-max 2 t:CC_L2T4 +select -assert-none t:CC_DLT t:CC_L2T4 %% t:* %D diff --git a/tests/arch/gatemate/logic.ys b/tests/arch/gatemate/logic.ys index 026406bc8..e6204cdca 100644 --- a/tests/arch/gatemate/logic.ys +++ b/tests/arch/gatemate/logic.ys @@ -1,6 +1,9 @@ read_verilog ../common/logic.v hierarchy -top top proc + +design -save orig + equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module @@ -8,3 +11,23 @@ select -assert-max 1 t:CC_LUT1 select -assert-max 6 t:CC_LUT2 select -assert-max 2 t:CC_LUT4 select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_LUT4 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_LUT1 +select -assert-count 6 t:CC_LUT2 +select -assert-count 2 t:CC_L2T4 +select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 %% t:* %D + +design -load orig + +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd top # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_LUT1 +select -assert-count 6 t:CC_LUT2 +select -assert-count 2 t:CC_L2T4 +select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_L2T4 %% t:* %D diff --git a/tests/arch/gatemate/luttrees.ys b/tests/arch/gatemate/luttrees.ys index 545643226..f3a61ee60 100644 --- a/tests/arch/gatemate/luttrees.ys +++ b/tests/arch/gatemate/luttrees.ys @@ -11,3 +11,24 @@ cd luttrees # Constrain all select calls below inside the top module select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D +design -load read + +hierarchy -top luttrees +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -nomx4 -nomx8 -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd luttrees # Constrain all select calls below inside the top module + +select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% +select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D + +design -load read + +hierarchy -top luttrees +proc +equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -nomx4 -nomx8 -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd luttrees # Constrain all select calls below inside the top module + +select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% +select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D diff --git a/tests/arch/gatemate/mul.ys b/tests/arch/gatemate/mul.ys index ded5fe729..ef2255a76 100644 --- a/tests/arch/gatemate/mul.ys +++ b/tests/arch/gatemate/mul.ys @@ -31,3 +31,29 @@ select -assert-count 1 t:CC_BUFG select -assert-max 18 t:CC_LUT4 select -assert-count 18 t:CC_DFF select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT4 t:CC_DFF %% t:* %D + +design -load read +hierarchy -top mul_unsigned_sync +proc +equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mul_unsigned_sync # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_MULT +select -assert-count 1 t:CC_BUFG +select -assert-count 18 t:CC_LUT2 +select -assert-count 18 t:CC_MX2 +select -assert-count 18 t:CC_DFF +select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT2 t:CC_MX2 t:CC_DFF %% t:* %D + +design -load read +hierarchy -top mul_unsigned_sync +proc +# equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check (fails) +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mul_unsigned_sync # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_MULT +select -assert-count 1 t:CC_BUFG +select -assert-count 18 t:CC_LUT2 +select -assert-count 18 t:CC_MX2 +select -assert-count 18 t:CC_DFF +select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT2 t:CC_MX2 t:CC_DFF %% t:* %D diff --git a/tests/arch/gatemate/mux.ys b/tests/arch/gatemate/mux.ys index 320ff33d7..51c3b5daf 100644 --- a/tests/arch/gatemate/mux.ys +++ b/tests/arch/gatemate/mux.ys @@ -12,6 +12,25 @@ select -assert-max 2 t:CC_LUT4 select -assert-max 1 t:CC_MX2 select -assert-none t:CC_LUT2 t:CC_LUT4 t:CC_MX2 %% t:* %D +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 3 t:CC_MX2 +select -assert-none t:CC_MX2 %% t:* %D + +design -load read +hierarchy -top mux4 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # equivalency check +design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) +cd mux4 # Constrain all select calls below inside the top module +select -assert-count 1 t:CC_LUT1 +select -assert-count 3 t:CC_MX2 +select -assert-none t:CC_LUT1 t:CC_MX2 %% t:* %D + design -load read hierarchy -top mux8 proc @@ -22,3 +41,21 @@ select -assert-max 1 t:CC_LUT3 select -assert-max 5 t:CC_LUT4 select -assert-max 1 t:CC_MX2 select -assert-none t:CC_LUT3 t:CC_LUT4 t:CC_MX2 %% t:* %D + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree # 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 7 t:CC_MX2 +select -assert-none t:CC_MX2 %% t:* %D + +design -load read +hierarchy -top mux8 +proc +equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -abc_new # 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 7 t:CC_MX2 +select -assert-none t:CC_MX2 %% t:* %D From de1dd3b1c5ac6f95323a56a6c456632d5623320a Mon Sep 17 00:00:00 2001 From: Lofty Date: Wed, 6 May 2026 14:03:07 +0100 Subject: [PATCH 140/176] add aiger2_zbuf to constids --- kernel/constids.inc | 1 + passes/techmap/abc9_ops.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/constids.inc b/kernel/constids.inc index 61c9b3a8c..cfd12e3fb 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -833,6 +833,7 @@ X(abcgroup) X(acc_fir) X(acc_fir_i) X(add_carry) +X(aiger2_zbuf) X(allconst) X(allseq) X(always_comb) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index dda3858da..e7cf8c637 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1652,7 +1652,7 @@ static void replace_zbufs(Design *design) if (sig[i] == State::Sz) { Wire *w = mod->addWire(NEW_ID); Cell *ud = mod->addCell(NEW_ID, ID($tribuf)); - ud->set_bool_attribute(ID(aiger2_zbuf)); + ud->set_bool_attribute(ID::aiger2_zbuf); ud->setParam(ID::WIDTH, 1); ud->setPort(ID::Y, w); ud->setPort(ID::EN, State::S0); From 3b26a9e45e2b960b9bd186178e1f425023180d63 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Thu, 7 May 2026 17:38:30 +1200 Subject: [PATCH 141/176] Docs: Update synth starter for check before flatten --- docs/source/getting_started/example_synth.rst | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/source/getting_started/example_synth.rst b/docs/source/getting_started/example_synth.rst index ccf0d252b..ebfaa542b 100644 --- a/docs/source/getting_started/example_synth.rst +++ b/docs/source/getting_started/example_synth.rst @@ -291,7 +291,10 @@ In `synth_ice40` we get these: :name: synth_flatten :caption: ``flatten`` section -First off is `flatten`. Flattening the design like this can allow for +We start by runnning `check`. This doesn't affect the design, but it can +identify a few obvious problems which will cause errors later. Calling it here +lets us fail faster rather than wasting time on something we know is impossible. +Next up is `flatten`. Flattening the design like this can allow for optimizations between modules which would otherwise be missed. Let's run :yoscrypt:`flatten;;` on our design. @@ -363,17 +366,14 @@ In the iCE40 flow, we start with the following commands: :caption: ``coarse`` section (part 1) :name: synth_coarse1 -We've already come across `opt_expr`, and `opt_clean` is the same as `clean` but -with more verbose output. The `check` pass identifies a few obvious problems -which will cause errors later. Calling it here lets us fail faster rather than -wasting time on something we know is impossible. - -Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple -optimizations on the design. This command also ensures that only a specific -subset of FF types are included, in preparation for the next command: -:cmd:title:`fsm`. Both `opt` and `fsm` are macro commands which are explored in -more detail in :doc:`/using_yosys/synthesis/opt` and -:doc:`/using_yosys/synthesis/fsm` respectively. +We've already come across `opt_expr` and `check`, and `opt_clean` is the same as +`clean` but with more verbose output. Next up is :yoscrypt:`opt -nodffe +-nosdff` performing a set of simple optimizations on the design. This command +also ensures that only a specific subset of FF types are included, in +preparation for the next command: :cmd:title:`fsm`. Both `opt` and `fsm` are +macro commands which are explored in more detail in +:doc:`/using_yosys/synthesis/opt` and :doc:`/using_yosys/synthesis/fsm` +respectively. Up until now, the data path for ``rdata`` has remained the same since :ref:`rdata_flat`. However the next call to `opt` does cause a change. From cb6209506ed83e992d0d9104e5d06a1948ab0db2 Mon Sep 17 00:00:00 2001 From: Tianji Liu Date: Thu, 7 May 2026 18:45:35 +0800 Subject: [PATCH 142/176] abc: disable scl merge if extra read_lib args provided --- passes/techmap/abc.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 95c70c73a..dd0364fe5 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1031,11 +1031,14 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module run_abc.dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } - std::string merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, run_abc.dont_use_args, config.exe_file); + std::string merged_scl; + if (config.abc_liberty_args.empty()) { + merged_scl = convert_liberty_files_to_merged_scl(config.liberty_files, run_abc.dont_use_args, config.exe_file); + } if (!merged_scl.empty()) { run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); } else if(!config.liberty_files.empty()) { - log_warning("ABC: Merged scl conversion failed, using liberty format\n"); + log_warning("ABC: Merged scl conversion failed, or abc_liberty_args provided, using liberty format\n"); bool first_lib = true; for (std::string liberty_file : config.liberty_files) { run_abc.abc_script += stringf("read_lib %s %s %s -w \"%s\" ; ", run_abc.dont_use_args, first_lib ? "" : "-m", config.abc_liberty_args, liberty_file); From f4a10a4808737db87b1de5fcbdb5e8638bf30197 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 20 Apr 2026 16:52:53 +0200 Subject: [PATCH 143/176] clockgate: reject $sdffe for correct priority handling --- passes/techmap/clockgate.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index b68e5d93d..650719cd5 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -337,6 +337,8 @@ struct ClockgatePass : public Pass { FfData ff(nullptr, cell); // It would be odd to get constants, but we better handle it if (ff.has_ce) { + if (ff.has_srst && !ff.ce_over_srst) + continue; if (!ff.sig_clk.is_bit() || !ff.sig_ce.is_bit()) continue; if (!ff.sig_clk[0].is_wire() || !ff.sig_ce[0].is_wire()) From 687e5442f2ce3c8a1031a35641453cf678b7a0ac Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 7 May 2026 16:08:55 +0200 Subject: [PATCH 144/176] clockgate: formal liberty tests --- tests/techmap/clockgate.lib | 6 + tests/techmap/{clockgate.ys => clockgate.tcl} | 118 +++--------------- tests/techmap/clockgate.v | 44 +++++++ tests/techmap/clockgate_bad.il | 31 +++++ tests/techmap/clockgate_wide.v | 8 ++ 5 files changed, 107 insertions(+), 100 deletions(-) rename tests/techmap/{clockgate.ys => clockgate.tcl} (81%) create mode 100644 tests/techmap/clockgate.v create mode 100644 tests/techmap/clockgate_bad.il create mode 100644 tests/techmap/clockgate_wide.v diff --git a/tests/techmap/clockgate.lib b/tests/techmap/clockgate.lib index 9f83baa55..584325108 100644 --- a/tests/techmap/clockgate.lib +++ b/tests/techmap/clockgate.lib @@ -6,6 +6,7 @@ library(test) { pin (GCLK) { clock_gate_out_pin : true; direction : output; + function : "CLK&CE"; } pin (CLK) { clock_gate_clock_pin : true; @@ -26,6 +27,7 @@ library(test) { pin (GCLK) { clock_gate_out_pin : true; direction : output; + function : "CLK&CE"; } pin (CLK) { clock_gate_clock_pin : true; @@ -42,6 +44,7 @@ library(test) { pin (GCLK) { clock_gate_out_pin : true; direction : output; + function : "CLK&CE"; } pin (CLK) { clock_gate_clock_pin : true; @@ -58,6 +61,7 @@ library(test) { pin (GCLK) { clock_gate_out_pin : true; direction : output; + function : "CLK|!CE"; } pin (CLK) { clock_gate_clock_pin : true; @@ -74,6 +78,7 @@ library(test) { pin (GCLK) { clock_gate_out_pin : true; direction : output; + function : "CLK|!CE"; } pin (CLK) { clock_gate_clock_pin : true; @@ -94,6 +99,7 @@ library(test) { pin (GCLK) { clock_gate_out_pin : true; direction : output; + function : "CLK|!CE"; } pin (CLK) { clock_gate_clock_pin : true; diff --git a/tests/techmap/clockgate.ys b/tests/techmap/clockgate.tcl similarity index 81% rename from tests/techmap/clockgate.ys rename to tests/techmap/clockgate.tcl index c28852ef8..c856babe5 100644 --- a/tests/techmap/clockgate.ys +++ b/tests/techmap/clockgate.tcl @@ -1,53 +1,6 @@ -read_verilog << EOT - -module dffe_00( input clk, en, - input d1, output reg q1, - ); - always @( negedge clk ) begin - if ( ~en ) - q1 <= d1; - end -endmodule - -module dffe_01( input clk, en, - input d1, output reg q1, - ); - always @( negedge clk ) begin - if ( en ) - q1 <= d1; - end -endmodule - -module dffe_10( input clk, en, - input d1, output reg q1, - ); - always @( posedge clk ) begin - if ( ~en ) - q1 <= d1; - end -endmodule - -module dffe_11( input clk, en, - input d1, output reg q1, - ); - always @( posedge clk ) begin - if ( en ) - q1 <= d1; - end -endmodule - -module dffe_wide_11( input clk, en, - input [3:0] d1, output reg [3:0] q1, - ); - always @( posedge clk ) begin - if ( en ) - q1 <= d1; - end -endmodule - -EOT - -proc +yosys -import +read_verilog clockgate.v +yosys proc opt design -save before @@ -128,41 +81,7 @@ select -module dffe_11 -assert-count 0 t:\\pdk_icg #------------------------------------------------------------------------------ design -reset -read_rtlil << EOT - -module \bad1 - wire input 1 \clk - wire input 3 \d1 - wire input 2 \en - wire output 4 \q1 - cell $dffe $auto$ff.cc:266:slice$27 - parameter \CLK_POLARITY 1 - parameter \EN_POLARITY 1 - parameter \WIDTH 1 - connect \CLK \clk - connect \D \d1 - connect \EN 1'1 - connect \Q \q1 - end -end - -module \bad2 - wire input 1 \clk - wire input 3 \d1 - wire input 2 \en - wire output 4 \q1 - cell $dffe $auto$ff.cc:266:slice$27 - parameter \CLK_POLARITY 1 - parameter \EN_POLARITY 1 - parameter \WIDTH 1 - connect \CLK 1'1 - connect \D \d1 - connect \EN \en - connect \Q \q1 - end -end - -EOT +read_rtlil clockgate_bad.il # Check we don't choke on constants clockgate -pos pdk_icg ce:clkin:clkout -tie_lo scanen @@ -173,19 +92,8 @@ select -module bad2 -assert-count 0 t:\\pdk_icg # Regression test: EN is a bit from a multi-bit wire design -reset -read_verilog << EOT -module dffe_wide_11( input clk, input [1:0] en, - input [3:0] d1, output reg [3:0] q1, - ); - always @( posedge clk ) begin - if ( en[0] ) - q1 <= d1; - end -endmodule - -EOT - -proc +read_verilog clockgate_wide.v +yosys proc opt clockgate -pos pdk_icg ce:clkin:clkout -tie_lo scanen @@ -193,8 +101,18 @@ select -assert-count 1 t:\\pdk_icg #------------------------------------------------------------------------------ -design -load before -clockgate -liberty c*ckgate.lib +design -reset +read_liberty c*ckgate.lib +design -save map +foreach mod {dffe_00 dffe_01 dffe_10 dffe_11} { + design -load before + hierarchy -top $mod + read_liberty -lib c*ckgate.lib + equiv_opt -map %map -multiclock clockgate -liberty c*ckgate.lib + design -load postopt + design -copy-to final $mod +} +design -load final # rising edge ICGs select -module dffe_00 -assert-count 0 t:\\pos_small diff --git a/tests/techmap/clockgate.v b/tests/techmap/clockgate.v new file mode 100644 index 000000000..3b4936852 --- /dev/null +++ b/tests/techmap/clockgate.v @@ -0,0 +1,44 @@ +module dffe_00( input clk, en, + input d1, output reg q1, + ); + always @( negedge clk ) begin + if ( ~en ) + q1 <= d1; + end +endmodule + +module dffe_01( input clk, en, + input d1, output reg q1, + ); + always @( negedge clk ) begin + if ( en ) + q1 <= d1; + end +endmodule + +module dffe_10( input clk, en, + input d1, output reg q1, + ); + always @( posedge clk ) begin + if ( ~en ) + q1 <= d1; + end +endmodule + +module dffe_11( input clk, en, + input d1, output reg q1, + ); + always @( posedge clk ) begin + if ( en ) + q1 <= d1; + end +endmodule + +module dffe_wide_11( input clk, en, + input [3:0] d1, output reg [3:0] q1, + ); + always @( posedge clk ) begin + if ( en ) + q1 <= d1; + end +endmodule \ No newline at end of file diff --git a/tests/techmap/clockgate_bad.il b/tests/techmap/clockgate_bad.il new file mode 100644 index 000000000..c967b04e6 --- /dev/null +++ b/tests/techmap/clockgate_bad.il @@ -0,0 +1,31 @@ +module \bad1 + wire input 1 \clk + wire input 3 \d1 + wire input 2 \en + wire output 4 \q1 + cell $dffe $auto$ff.cc:266:slice$27 + parameter \CLK_POLARITY 1 + parameter \EN_POLARITY 1 + parameter \WIDTH 1 + connect \CLK \clk + connect \D \d1 + connect \EN 1'1 + connect \Q \q1 + end +end + +module \bad2 + wire input 1 \clk + wire input 3 \d1 + wire input 2 \en + wire output 4 \q1 + cell $dffe $auto$ff.cc:266:slice$27 + parameter \CLK_POLARITY 1 + parameter \EN_POLARITY 1 + parameter \WIDTH 1 + connect \CLK 1'1 + connect \D \d1 + connect \EN \en + connect \Q \q1 + end +end \ No newline at end of file diff --git a/tests/techmap/clockgate_wide.v b/tests/techmap/clockgate_wide.v new file mode 100644 index 000000000..687fd7104 --- /dev/null +++ b/tests/techmap/clockgate_wide.v @@ -0,0 +1,8 @@ +module dffe_wide_11( input clk, input [1:0] en, + input [3:0] d1, output reg [3:0] q1, + ); + always @( posedge clk ) begin + if ( en[0] ) + q1 <= d1; + end +endmodule \ No newline at end of file From 425d47ad2c5d8e2acdca4604cffa12df8fcfc87c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 7 May 2026 16:13:14 +0200 Subject: [PATCH 145/176] clockgate: test $sdffe rejected --- tests/techmap/clockgate.tcl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/techmap/clockgate.tcl b/tests/techmap/clockgate.tcl index c856babe5..84682f780 100644 --- a/tests/techmap/clockgate.tcl +++ b/tests/techmap/clockgate.tcl @@ -1,5 +1,6 @@ yosys -import read_verilog clockgate.v +read_verilog ../sim/sdffe.v yosys proc opt @@ -194,6 +195,9 @@ select -module dffe_11 -assert-count 0 t:\\neg_small_tielo select -module dffe_10 -assert-count 1 t:\$_NOT_ select -module dffe_11 -assert-count 0 t:\$_NOT_ +# $sdffe is not gated +select -module sdffe -assert-count 0 sdffe t:* t:\$sdffe %d + #------------------------------------------------------------------------------ design -load before From 3f354eb03be6cc46fd6d97a85df2c531a2e41ab9 Mon Sep 17 00:00:00 2001 From: Tianji Liu Date: Fri, 8 May 2026 07:17:29 +0800 Subject: [PATCH 146/176] abc: update log for extra read_lib args --- passes/techmap/abc.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index dd0364fe5..1ed0c867d 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1038,7 +1038,11 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module if (!merged_scl.empty()) { run_abc.abc_script += stringf("read_scl \"%s\" ; ", merged_scl.c_str()); } else if(!config.liberty_files.empty()) { - log_warning("ABC: Merged scl conversion failed, or abc_liberty_args provided, using liberty format\n"); + if (!config.abc_liberty_args.empty()) { + log("ABC: abc_liberty_args provided, using liberty format\n"); + } else { + log_warning("ABC: Merged scl conversion failed, using liberty format\n"); + } bool first_lib = true; for (std::string liberty_file : config.liberty_files) { run_abc.abc_script += stringf("read_lib %s %s %s -w \"%s\" ; ", run_abc.dont_use_args, first_lib ? "" : "-m", config.abc_liberty_args, liberty_file); From 89d83a34104f0cf5e6010494e6debbcc6a15f3b6 Mon Sep 17 00:00:00 2001 From: Codexplorer Date: Fri, 9 Jan 2026 15:44:14 -0800 Subject: [PATCH 147/176] Logging now handles classes with an IdString "name" member --- kernel/io.h | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/kernel/io.h b/kernel/io.h index 171f47a80..1585987b8 100644 --- a/kernel/io.h +++ b/kernel/io.h @@ -197,6 +197,28 @@ check_format(std::string_view fmt, int fmt_start, bool *has_escapes, FoundFormat ensure_no_format_spec(fmt, fmt_start, has_escapes); } +template +static auto has_name_member_imp(int) + -> decltype(static_cast(std::declval().name), std::true_type{}); + +template +static auto has_name_member_imp(long) + -> std::false_type; + +template +struct has_name_member : decltype(has_name_member_imp(0)){}; + +template +static auto ptr_has_name_member_imp(int) + -> decltype(static_cast(std::declval()->name), std::true_type{}); + +template +static auto ptr_has_name_member_imp(long) + -> std::false_type; + +template +struct ptr_has_name_member : decltype(ptr_has_name_member_imp(0)){}; + // Check that the format string `fmt.substr(fmt_start)` is valid for the given type arguments. // Fills `specs` with the FoundFormatSpecs found in the format string. // `int_args_consumed` is the number of int arguments already consumed to satisfy the @@ -245,7 +267,9 @@ constexpr void check_format(std::string_view fmt, int fmt_start, bool *has_escap if constexpr (!std::is_convertible_v && !std::is_convertible_v && !std::is_convertible_v && - !std::is_convertible_v) { + !std::is_convertible_v && + !has_name_member() && + !ptr_has_name_member()) { YOSYS_ABORT("Expected type convertible to char *"); } *specs = found; @@ -343,6 +367,16 @@ inline void format_emit_one(std::string &result, std::string_view fmt, const Fou format_emit_idstring(result, spec, dynamic_ints, num_dynamic_ints, s); return; } + if constexpr (has_name_member()) { + const std::string &s = arg.name.unescape(); + format_emit_string(result, spec, dynamic_ints, num_dynamic_ints, s); + return; + } + if constexpr (ptr_has_name_member()) { + const std::string &s = arg->name.unescape(); + format_emit_string(result, spec, dynamic_ints, num_dynamic_ints, s); + return; + } break; case CONVSPEC_VOID_PTR: if constexpr (std::is_convertible_v) { From e41b969da25fee5ccd8542b8c4c45824ddae568b Mon Sep 17 00:00:00 2001 From: Codexplorer Date: Fri, 8 May 2026 00:01:43 -0700 Subject: [PATCH 148/176] Refactored uses of log_id() --- backends/aiger/aiger.cc | 40 ++++---- backends/aiger/xaiger.cc | 28 +++--- backends/aiger2/aiger.cc | 30 +++--- backends/blif/blif.cc | 6 +- backends/btor/btor.cc | 59 ++++++------ backends/cxxrtl/cxxrtl_backend.cc | 30 +++--- backends/edif/edif.cc | 10 +- backends/firrtl/firrtl.cc | 28 +++--- backends/intersynth/intersynth.cc | 30 +++--- backends/json/json.cc | 6 +- backends/simplec/simplec.cc | 46 +++++----- backends/smt2/smt2.cc | 56 +++++------ backends/smv/smv.cc | 14 +-- backends/spice/spice.cc | 6 +- backends/table/table.cc | 12 +-- backends/verilog/verilog_backend.cc | 4 +- .../source/code_examples/extensions/my_cmd.cc | 4 +- examples/cxx-api/scopeinfo_example.cc | 12 +-- frontends/aiger/aigerparse.cc | 16 ++-- frontends/aiger2/xaiger.cc | 8 +- frontends/ast/ast.cc | 10 +- frontends/ast/genrtlil.cc | 4 +- frontends/ast/simplify.cc | 2 +- frontends/blif/blifparse.cc | 2 +- frontends/json/jsonparse.cc | 54 +++++------ frontends/rpc/rpc_frontend.cc | 2 +- frontends/rtlil/rtlil_frontend.cc | 2 +- frontends/verific/verific.cc | 12 +-- kernel/cost.cc | 2 +- kernel/drivertools.cc | 6 +- kernel/ff.cc | 2 +- kernel/functional.cc | 8 +- kernel/log.cc | 2 +- kernel/mem.cc | 8 +- kernel/modtools.h | 4 +- kernel/rtlil.cc | 32 +++---- kernel/rtlil_bufnorm.cc | 12 +-- kernel/satgen.cc | 4 +- kernel/scopeinfo.h | 2 +- kernel/timinginfo.h | 22 ++--- kernel/yosys.cc | 12 +-- passes/cmds/abstract.cc | 8 +- passes/cmds/autoname.cc | 10 +- passes/cmds/box_derive.cc | 4 +- passes/cmds/bugpoint.cc | 20 ++-- passes/cmds/check.cc | 32 +++---- passes/cmds/chformal.cc | 4 +- passes/cmds/connect.cc | 2 +- passes/cmds/connwrappers.cc | 4 +- passes/cmds/design.cc | 4 +- passes/cmds/design_equal.cc | 72 +++++++-------- passes/cmds/dft_tag.cc | 12 +-- passes/cmds/edgetypes.cc | 8 +- passes/cmds/example_dt.cc | 10 +- passes/cmds/future.cc | 4 +- passes/cmds/linecoverage.cc | 6 +- passes/cmds/ltp.cc | 8 +- passes/cmds/portarcs.cc | 6 +- passes/cmds/portlist.cc | 4 +- passes/cmds/printattrs.cc | 10 +- passes/cmds/rename.cc | 8 +- passes/cmds/sdc/sdc.cc | 2 +- passes/cmds/select.cc | 2 +- passes/cmds/setattr.cc | 4 +- passes/cmds/show.cc | 8 +- passes/cmds/splice.cc | 2 +- passes/cmds/splitcells.cc | 10 +- passes/cmds/sta.cc | 16 ++-- passes/cmds/stat.cc | 22 ++--- passes/cmds/timeest.cc | 16 ++-- passes/cmds/torder.cc | 6 +- passes/cmds/trace.cc | 12 +-- passes/cmds/viz.cc | 8 +- passes/cmds/wrapcell.cc | 8 +- passes/cmds/xprop.cc | 12 +-- passes/equiv/equiv_induct.cc | 4 +- passes/equiv/equiv_make.cc | 14 +-- passes/equiv/equiv_mark.cc | 2 +- passes/equiv/equiv_miter.cc | 12 +-- passes/equiv/equiv_purge.cc | 6 +- passes/equiv/equiv_remove.cc | 2 +- passes/equiv/equiv_simple.cc | 10 +- passes/equiv/equiv_status.cc | 6 +- passes/equiv/equiv_struct.cc | 14 +-- passes/fsm/fsm_detect.cc | 10 +- passes/fsm/fsm_expand.cc | 6 +- passes/fsm/fsm_export.cc | 2 +- passes/fsm/fsm_info.cc | 2 +- passes/fsm/fsm_recode.cc | 2 +- passes/hierarchy/flatten.cc | 10 +- passes/hierarchy/hierarchy.cc | 40 ++++---- passes/hierarchy/keep_hierarchy.cc | 8 +- passes/hierarchy/uniquify.cc | 6 +- passes/memory/memory_bram.cc | 66 ++++++------- passes/memory/memory_libmap.cc | 34 +++---- passes/memory/memory_memx.cc | 2 +- passes/memory/memory_share.cc | 6 +- passes/opt/muxpack.cc | 4 +- passes/opt/opt_balance_tree.cc | 4 +- passes/opt/opt_clean/inits.cc | 2 +- passes/opt/opt_demorgan.cc | 2 +- passes/opt/opt_dff.cc | 44 ++++----- passes/opt/opt_expr.cc | 54 +++++------ passes/opt/opt_hier.cc | 26 +++--- passes/opt/opt_lut.cc | 12 +-- passes/opt/opt_lut_ins.cc | 4 +- passes/opt/opt_mem.cc | 6 +- passes/opt/opt_mem_feedback.cc | 4 +- passes/opt/opt_mem_widen.cc | 2 +- passes/opt/opt_muxtree.cc | 12 +-- passes/opt/opt_share.cc | 4 +- passes/opt/pmux2shiftx.cc | 12 +-- passes/opt/share.cc | 38 ++++---- passes/opt/wreduce.cc | 30 +++--- passes/pmgen/generate.h | 4 +- passes/pmgen/test_pmgen.cc | 16 ++-- passes/proc/proc_arst.cc | 2 +- passes/proc/proc_clean.cc | 2 +- passes/proc/proc_dlatch.cc | 2 +- passes/proc/proc_memwr.cc | 2 +- passes/proc/proc_rmdead.cc | 4 +- passes/sat/assertpmux.cc | 2 +- passes/sat/async2sync.cc | 10 +- passes/sat/clk2fflogic.cc | 18 ++-- passes/sat/cutpoint.cc | 8 +- passes/sat/eval.cc | 20 ++-- passes/sat/expose.cc | 4 +- passes/sat/fmcombine.cc | 16 ++-- passes/sat/formalff.cc | 62 ++++++------- passes/sat/mutate.cc | 38 ++++---- passes/sat/qbfsat.cc | 2 +- passes/sat/recover_names.cc | 6 +- passes/sat/sat.cc | 2 +- passes/sat/sim.cc | 92 +++++++++---------- passes/sat/supercover.cc | 2 +- passes/sat/synthprop.cc | 10 +- passes/techmap/abc.cc | 2 +- passes/techmap/abc9.cc | 8 +- passes/techmap/abc9_ops.cc | 78 ++++++++-------- passes/techmap/abc_new.cc | 2 +- passes/techmap/aigmap.cc | 6 +- passes/techmap/alumacc.cc | 24 ++--- passes/techmap/arith_tree.cc | 2 +- passes/techmap/attrmap.cc | 14 +-- passes/techmap/attrmvcp.cc | 4 +- passes/techmap/booth.cc | 6 +- passes/techmap/bufnorm.cc | 8 +- passes/techmap/cellmatch.cc | 18 ++-- passes/techmap/clkbufmap.cc | 4 +- passes/techmap/deminout.cc | 2 +- passes/techmap/dffinit.cc | 8 +- passes/techmap/dfflegalize.cc | 8 +- passes/techmap/extract.cc | 12 +-- passes/techmap/extract_counter.cc | 14 +-- passes/techmap/extract_fa.cc | 14 +-- passes/techmap/extractinv.cc | 4 +- passes/techmap/flowmap.cc | 18 ++-- passes/techmap/insbuf.cc | 8 +- passes/techmap/iopadmap.cc | 18 ++-- passes/techmap/lut2bmux.cc | 2 +- passes/techmap/lut2mux.cc | 2 +- passes/techmap/maccmap.cc | 2 +- passes/techmap/muxcover.cc | 2 +- passes/techmap/shregmap.cc | 2 +- passes/techmap/simplemap.cc | 2 +- passes/techmap/techmap.cc | 88 +++++++++--------- passes/techmap/tribuf.cc | 2 +- passes/techmap/zinit.cc | 2 +- passes/tests/raise_error.cc | 2 +- passes/tests/test_cell.cc | 32 +++---- techlibs/anlogic/anlogic_fixcarry.cc | 4 +- techlibs/efinix/efinix_fixcarry.cc | 4 +- techlibs/greenpak4/greenpak4_dffinv.cc | 2 +- techlibs/ice40/ice40_dsp.cc | 20 ++-- techlibs/ice40/ice40_opt.cc | 6 +- techlibs/lattice/lattice_gsr.cc | 8 +- techlibs/microchip/microchip_dffopt.cc | 4 +- techlibs/microchip/microchip_dsp.cc | 18 ++-- techlibs/quicklogic/ql_bram_merge.cc | 6 +- techlibs/quicklogic/ql_bram_types.cc | 2 +- techlibs/quicklogic/ql_dsp_io_regs.cc | 6 +- techlibs/quicklogic/ql_dsp_macc.cc | 4 +- techlibs/quicklogic/ql_dsp_simd.cc | 6 +- techlibs/xilinx/xilinx_dffopt.cc | 4 +- techlibs/xilinx/xilinx_dsp.cc | 52 +++++------ techlibs/xilinx/xilinx_srl.cc | 12 +-- 186 files changed, 1219 insertions(+), 1220 deletions(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 0c49e84b8..1320937a0 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -340,7 +340,7 @@ struct AigerWriter if (cell->type == ID($scopeinfo)) continue; - log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + log_error("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell); } for (auto bit : unused_bits) @@ -349,10 +349,10 @@ struct AigerWriter if (!undriven_bits.empty()) { undriven_bits.sort(); for (auto bit : undriven_bits) { - log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit)); + log_warning("Treating undriven bit %s.%s like $anyseq.\n", module, log_signal(bit)); input_bits.insert(bit); } - log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module)); + log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), module); } init_map.sort(); @@ -635,35 +635,35 @@ struct AigerWriter int a = aig_map.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i)); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", wire, i)); else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire))); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", wire)); } if (wire->port_output) { int o = ordered_outputs.at(SigSpec(wire, i)); if (GetSize(wire) != 1) - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i)); + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", wire, i)); else - symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire))); + symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", wire)); } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); if (GetSize(wire) != 1) - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i)); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", wire, i)); else - symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire))); + symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", wire)); } if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : ""; if (GetSize(wire) != 1) - symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i)); + symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, wire, i)); else - symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire))); + symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, wire)); } } } @@ -705,30 +705,30 @@ struct AigerWriter int index = no_startoffset ? i : (wire->start_offset+i); if (verbose_map) - wire_lines[a] += stringf("wire %d %d %s\n", a, index, log_id(wire)); + wire_lines[a] += stringf("wire %d %d %s\n", a, index, wire); if (wire->port_input) { log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, log_id(wire)); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, wire); } if (wire->port_output) { int o = ordered_outputs.at(SigSpec(wire, i)); - output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o, index, wire); } if (init_inputs.count(sig[i])) { int a = init_inputs.at(sig[i]); log_assert((a & 1) == 0); - init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, log_id(wire)); + init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, wire); } if (ordered_latches.count(sig[i])) { int l = ordered_latches.at(sig[i]); if (zinit_mode && (aig_latchinit.at(l) == 1)) - latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, log_id(wire)); + latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, wire); else - latch_lines[l] += stringf("latch %d %d %s\n", l, index, log_id(wire)); + latch_lines[l] += stringf("latch %d %d %s\n", l, index, wire); } } } @@ -1027,12 +1027,12 @@ struct AigerBackend : public Backend { log_error("Can't find top module in current design!\n"); if (!design->selected_whole_module(top_module)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); + log_cmd_error("Can't handle partially selected module %s!\n", top_module); if (!top_module->processes.empty()) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", log_id(top_module)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", top_module); if (!top_module->memories.empty()) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", top_module); AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 988bc558b..cc1085f96 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -268,7 +268,7 @@ struct XAigerWriter if (ys_debug(1)) { static pool> seen; if (seen.emplace(inst_module->name, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n", - log_id(cell->type), log_id(i.first.name), offset, d); + cell->type.unescape(), i.first.name.unescape(), offset, d); } #endif arrival_times[rhs[offset]] = d; @@ -285,7 +285,7 @@ struct XAigerWriter auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first); auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first); if (!is_input && !is_output) - log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type)); + log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", c.first.unescape(), cell, cell->type.unescape()); if (is_input) for (auto b : c.second) { @@ -303,7 +303,7 @@ struct XAigerWriter } } - //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell)); + //log_warning("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell); } dict> box_ports; @@ -325,12 +325,12 @@ struct XAigerWriter if (w->get_bool_attribute(ID::abc9_carry)) { if (w->port_input) { if (carry_in != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module)); + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", box_module); carry_in = port_name; } if (w->port_output) { if (carry_out != IdString()) - log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module)); + log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", box_module); carry_out = port_name; } } @@ -339,9 +339,9 @@ struct XAigerWriter } if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module)); + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", box_module); if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module)); + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", box_module); if (carry_in != IdString()) { r.first->second.push_back(carry_in); r.first->second.push_back(carry_out); @@ -612,7 +612,7 @@ struct XAigerWriter write_r_buffer(mergeability); State init = init_map.at(q, State::Sx); - log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init)); + log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", cell, cell->type.unescape(), log_signal(init)); if (init == State::S1) write_s_buffer(1); else if (init == State::S0) @@ -692,12 +692,12 @@ struct XAigerWriter if (input_bits.count(b)) { int a = aig_map.at(b); log_assert((a & 1) == 0); - input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire)); + input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, wire); } if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire)); + output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, wire); } } } @@ -709,7 +709,7 @@ struct XAigerWriter int box_count = 0; for (auto cell : box_list) - f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name)); + f << stringf("box %d %d %s\n", box_count++, 0, cell->name.unescape()); output_lines.sort(); for (auto &it : output_lines) @@ -774,12 +774,12 @@ struct XAigerBackend : public Backend { log_error("Can't find top module in current design!\n"); if (!design->selected_whole_module(top_module)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module)); + log_cmd_error("Can't handle partially selected module %s!\n", top_module); if (!top_module->processes.empty()) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", top_module); if (!top_module->memories.empty()) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", top_module); XAigerWriter writer(top_module, dff_mode); writer.write_aiger(*f, ascii_mode); diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 2f28869d9..c0ab8a65c 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -132,7 +132,7 @@ struct Index { continue; if (!submodule || submodule->get_blackbox_attribute()) log_error("Unsupported cell type: %s (%s in %s)\n", - log_id(cell->type), log_id(cell), log_id(m)); + cell->type.unescape(), cell, m); } } } @@ -537,7 +537,7 @@ struct Index { Design *design = index.design; auto &minfo = leaf_minfo(index); if (!minfo.suboffsets.count(cell)) - log_error("Reached unsupported cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module)); + log_error("Reached unsupported cell %s (%s in %s)\n", cell->type.unescape(), cell, cell->module); Module *def = design->module(cell->type); log_assert(def); levels.push_back(Level(index.modules.at(def), cell)); @@ -636,10 +636,10 @@ struct Index { Wire *w = def->wire(portname); if (!w) log_error("Output port %s on instance %s of %s doesn't exist\n", - log_id(portname), log_id(driver), log_id(def)); + portname.unescape(), driver, def); if (bit.offset >= w->width) log_error("Bit position %d of output port %s on instance %s of %s is out of range (port has width %d)\n", - bit.offset, log_id(portname), log_id(driver), log_id(def), w->width); + bit.offset, portname.unescape(), driver, def, w->width); ret = visit(cursor, SigBit(w, bit.offset)); } cursor.exit(*this); @@ -655,11 +655,11 @@ struct Index { IdString portname = bit.wire->name; if (!instance->hasPort(portname)) log_error("Input port %s on instance %s of %s unconnected\n", - log_id(portname), log_id(instance), log_id(instance->type)); + portname.unescape(), instance, instance->type); auto &port = instance->getPort(portname); if (bit.offset >= port.size()) log_error("Bit %d of input port %s on instance %s of %s unconnected\n", - bit.offset, log_id(portname), log_id(instance), log_id(instance->type)); + bit.offset, portname.unescape(), instance, instance->type.unescape()); ret = visit(cursor, port[bit.offset]); } cursor.enter(*this, instance); @@ -1048,7 +1048,7 @@ struct XAigerWriter : AigerWriter { } else if (!is_input && !inputs) { for (auto &bit : conn.second) { if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output)) - log_error("Bad connection %s/%s ~ %s\n", log_id(box), log_id(conn.first), log_signal(conn.second)); + log_error("Bad connection %s/%s ~ %s\n", box, conn.first.unescape(), conn.second); ensure_pi(bit, cursor); @@ -1073,9 +1073,9 @@ struct XAigerWriter : AigerWriter { void prep_boxes(int pending_pos_num) { XAigerAnalysis analysis; - log_debug("preforming analysis on '%s'\n", log_id(top)); + log_debug("preforming analysis on '%s'\n", top); analysis.analyze(top); - log_debug("analysis on '%s' done\n", log_id(top)); + log_debug("analysis on '%s' done\n", top); // boxes which have timing data, maybe a whitebox model std::vector> nonopaque_boxes; @@ -1089,7 +1089,7 @@ struct XAigerWriter : AigerWriter { for (auto box : minfo.found_blackboxes) { log_debug(" - %s.%s (type %s): ", cursor.path(), RTLIL::unescape_id(box->name), - log_id(box->type)); + box->type.unescape()); Module *box_module = design->module(box->type), *box_derived; @@ -1158,7 +1158,7 @@ struct XAigerWriter : AigerWriter { } else { // FIXME: hierarchical path log_warning("connection on port %s[%d] of instance %s (type %s) missing, using 1'bx\n", - log_id(port_id), i, log_id(box), log_id(box->type)); + port_id.unescape(), i, box, box->type.unescape()); bit = RTLIL::Sx; } @@ -1193,7 +1193,7 @@ struct XAigerWriter : AigerWriter { } else { // FIXME: hierarchical path log_warning("connection on port %s[%d] of instance %s (type %s) missing\n", - log_id(port_id), i, log_id(box), log_id(box->type)); + port_id.unescape(), i, box, box->type.unescape()); pad_pi(); continue; } @@ -1210,7 +1210,7 @@ struct XAigerWriter : AigerWriter { holes_wb->setPort(port_id, w); } else { log_error("Ambiguous port direction on %s/%s\n", - log_id(box->type), log_id(port_id)); + box->type.unescape(), port_id.unescape()); } } } @@ -1405,7 +1405,7 @@ struct Aiger2Backend : Backend { continue; if (known_ops(cell.type)) continue; - std::string name = log_id(cell.type); + std::string name = cell.type.unescape(); if (col + name.size() + 2 > 72) { log("\n "); col = 0; @@ -1427,7 +1427,7 @@ struct Aiger2Backend : Backend { continue; if (known_ops(cell.type)) continue; - std::string name = log_id(cell.type); + std::string name = cell.type.unescape(); if (col + name.size() + 2 > 72) { log("\n "); col = 0; diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index cc339bcbc..d16d39e5e 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -150,7 +150,7 @@ struct BlifDumper void dump_params(const char *command, dict ¶ms) { for (auto ¶m : params) { - f << stringf("%s %s ", command, log_id(param.first)); + f << stringf("%s %s ", command, param.first.unescape()); if (param.second.flags & RTLIL::CONST_FLAG_STRING) { std::string str = param.second.decode_string(); f << stringf("\""); @@ -678,9 +678,9 @@ struct BlifBackend : public Backend { continue; if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", log_id(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", module->name.unescape()); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", log_id(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", module->name.unescape()); if (module->name == RTLIL::escape_id(top_module_name)) { BlifDumper::dump(*f, module, design, config); diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index ca7cf8a7f..497ecc954 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -119,7 +119,7 @@ struct BtorWorker template string getinfo(T *obj, bool srcsym = false) { - string infostr = log_id(obj); + string infostr = obj->name.unescape(); if (!srcsym && !print_internal_names && infostr[0] == '$') return ""; if (obj->attributes.count(ID::src)) { string src = obj->attributes.at(ID::src).decode_string().c_str(); @@ -243,12 +243,12 @@ struct BtorWorker if (cell_recursion_guard.count(cell)) { string cell_list; for (auto c : cell_recursion_guard) - cell_list += stringf("\n %s", log_id(c)); - log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list); + cell_list += stringf("\n %s", c); + log_error("Found topological loop while processing cell %s. Active cells:%s\n", cell, cell_list); } cell_recursion_guard.insert(cell); - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx), ID($concat), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_))) @@ -726,7 +726,7 @@ struct BtorWorker if (symbol.empty() || (!print_internal_names && symbol[0] == '$')) btorf("%d state %d\n", nid, sid); else - btorf("%d state %d %s\n", nid, sid, log_id(symbol)); + btorf("%d state %d %s\n", nid, sid, symbol.unescape()); if (cell->get_bool_attribute(ID(clk2fflogic))) ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output @@ -804,12 +804,12 @@ struct BtorWorker if (asyncwr && syncwr) log_error("Memory %s.%s has mixed async/sync write ports.\n", - log_id(module), log_id(mem->memid)); + module, mem->memid.unescape()); for (auto &port : mem->rd_ports) { if (port.clk_enable) log_error("Memory %s.%s has sync read ports. Please use memory_nordff to convert them first.\n", - log_id(module), log_id(mem->memid)); + module, mem->memid.unescape()); } int data_sid = get_bv_sid(mem->width); @@ -871,7 +871,7 @@ struct BtorWorker if (mem->memid[0] == '$') btorf("%d state %d\n", nid, sid); else - btorf("%d state %d %s\n", nid, sid, log_id(mem->memid)); + btorf("%d state %d %s\n", nid, sid, mem->memid.unescape()); ywmap_state(cell); @@ -948,21 +948,20 @@ struct BtorWorker if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) { log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") { log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") { log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } log_error("Unsupported cell type %s for cell %s.%s.\n", - log_id(cell->type), log_id(module), log_id(cell)); - + cell->type.unescape(), module, cell); okay: - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); cell_recursion_guard.erase(cell); } @@ -1167,7 +1166,7 @@ struct BtorWorker f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename) { if (!info_filename.empty()) - infof("name %s\n", log_id(module)); + infof("name %s\n", module); if (!ywmap_filename.empty()) ywmap_json.write_to_file(ywmap_filename); @@ -1257,19 +1256,19 @@ struct BtorWorker if (!wire->port_id || !wire->port_output) continue; - btorf_push(stringf("output %s", log_id(wire))); + btorf_push(stringf("output %s", wire)); int nid = get_sig_nid(wire); btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire)); - btorf_pop(stringf("output %s", log_id(wire))); + btorf_pop(stringf("output %s", wire)); } for (auto cell : module->cells()) { if (cell->type == ID($assume)) { - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort(ID::A)); @@ -1284,12 +1283,12 @@ struct BtorWorker if (ywmap_json.active()) ywmap_assumes.emplace_back(cell); - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); } if (cell->type == ID($assert)) { - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort(ID::A)); @@ -1313,12 +1312,12 @@ struct BtorWorker } } - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); } if (cell->type == ID($cover) && cover_mode) { - btorf_push(log_id(cell)); + btorf_push(cell->name.unescape()); int sid = get_bv_sid(1); int nid_a = get_sig_nid(cell->getPort(ID::A)); @@ -1334,7 +1333,7 @@ struct BtorWorker btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true)); } - btorf_pop(log_id(cell)); + btorf_pop(cell->name.unescape()); } } @@ -1343,7 +1342,7 @@ struct BtorWorker if (wire->port_id || wire->name[0] == '$') continue; - btorf_push(stringf("wire %s", log_id(wire))); + btorf_push(stringf("wire %s", wire)); int sid = get_bv_sid(GetSize(wire)); int nid = get_sig_nid(sigmap(wire)); @@ -1356,7 +1355,7 @@ struct BtorWorker if (info_clocks.count(nid)) info_clocks[this_nid] |= info_clocks[nid]; - btorf_pop(stringf("wire %s", log_id(wire))); + btorf_pop(stringf("wire %s", wire)); continue; } @@ -1370,14 +1369,14 @@ struct BtorWorker int nid = it.first; Cell *cell = it.second; - btorf_push(stringf("next %s", log_id(cell))); + btorf_push(stringf("next %s", cell)); SigSpec sig = sigmap(cell->getPort(ID::D)); int nid_q = get_sig_nid(sig); int sid = get_bv_sid(GetSize(sig)); btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell)); - btorf_pop(stringf("next %s", log_id(cell))); + btorf_pop(stringf("next %s", cell)); } vector> mtodo; @@ -1388,7 +1387,7 @@ struct BtorWorker int nid = it.first; Mem *mem = it.second; - btorf_push(stringf("next %s", log_id(mem->memid))); + btorf_push(stringf("next %s", mem->memid.unescape())); int abits = ceil_log2(mem->size); @@ -1436,7 +1435,7 @@ struct BtorWorker int nid2 = next_nid++; btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, (mem->cell ? getinfo(mem->cell) : getinfo(mem->mem))); - btorf_pop(stringf("next %s", log_id(mem->memid))); + btorf_pop(stringf("next %s", mem->memid.unescape())); } } @@ -1630,7 +1629,7 @@ struct BtorBackend : public Backend { log_cmd_error("No top module found.\n"); *f << stringf("; BTOR description generated by %s for module %s.\n", - yosys_maybe_version(), log_id(topmod)); + yosys_maybe_version(), topmod); BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename); diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index ab5576e43..3ebe62b90 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -251,7 +251,7 @@ CxxrtlPortType cxxrtl_port_type(RTLIL::Module *module, RTLIL::IdString port) bool is_sync = output_wire->get_bool_attribute(ID(cxxrtl_sync)); if (is_comb && is_sync) log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n", - log_id(module), log_signal(output_wire)); + module, log_signal(output_wire)); else if (is_comb) return CxxrtlPortType::COMB; else if (is_sync) @@ -851,7 +851,7 @@ struct CxxrtlWorker { return {}; if (!(module->attributes.at(ID(cxxrtl_template)).flags & RTLIL::CONST_FLAG_STRING)) - log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", log_id(module)); + log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", module); std::vector param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t"); for (const auto ¶m_name : param_names) { @@ -861,7 +861,7 @@ struct CxxrtlWorker { if (!isupper(param_name[0])) log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', " "which does not start with an uppercase letter.\n", - log_id(module), param_name.c_str()); + module, param_name.c_str()); } return param_names; } @@ -907,12 +907,12 @@ struct CxxrtlWorker { RTLIL::IdString id_param_name = '\\' + param_name; if (!cell->hasParam(id_param_name)) log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n", - log_id(cell->module), log_id(cell), param_name.c_str(), log_id(cell_module)); + cell->module, cell, param_name.c_str(), cell_module); RTLIL::Const param_value = cell->getParam(id_param_name); if (((param_value.flags & ~RTLIL::CONST_FLAG_SIGNED) != 0) || param_value.as_int() < 0) log_cmd_error("Parameter `%s' of cell `%s.%s', which is required by the templated module `%s', " "is not a positive integer.\n", - param_name.c_str(), log_id(cell->module), log_id(cell), log_id(cell_module)); + param_name.c_str(), cell->module, cell, cell_module); params += std::to_string(cell->getParam(id_param_name).as_int()); } params += ">"; @@ -2576,7 +2576,7 @@ struct CxxrtlWorker { } dec_indent(); - log_debug("Debug information statistics for module `%s':\n", log_id(module)); + log_debug("Debug information statistics for module `%s':\n", module); log_debug(" Scopes: %zu", count_scopes); log_debug(" Public wires: %zu, of which:\n", count_public_wires); log_debug(" Member wires: %zu, of which:\n", count_member_wires); @@ -2940,7 +2940,7 @@ struct CxxrtlWorker { RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)]; if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire)) log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n", - log_id(module), log_signal(wire)); + module, log_signal(wire)); std::string edges = wire->get_string_attribute(ID(cxxrtl_edge)); for (int i = 0; i < GetSize(wire); i++) { @@ -2953,7 +2953,7 @@ struct CxxrtlWorker { default: log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers " "other than '-', 'p', 'n', or 'a'.\n", - log_id(module), log_signal(wire)); + module, log_signal(wire)); } } } @@ -2978,7 +2978,7 @@ struct CxxrtlWorker { for (auto cell : module->cells()) { if (!cell->known()) - log_cmd_error("Unknown cell `%s'.\n", log_id(cell->type)); + log_cmd_error("Unknown cell `%s'.\n", cell->type.unescape()); if (cell->is_mem_cell()) continue; @@ -2987,7 +2987,7 @@ struct CxxrtlWorker { if (cell_module && cell_module->get_blackbox_attribute() && !cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) - log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", log_id(cell->type)); + log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", cell->type.unescape()); if (cell_module && cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) && @@ -3116,9 +3116,9 @@ struct CxxrtlWorker { } if (!feedback_wires.empty()) { has_feedback_arcs = true; - log("Module `%s' contains feedback arcs through wires:\n", log_id(module)); + log("Module `%s' contains feedback arcs through wires:\n", module); for (auto wire : feedback_wires) - log(" %s\n", log_id(wire)); + log(" %s\n", wire); } // Conservatively assign wire types. Assignment of types BUFFERED and MEMBER is final, but assignment @@ -3189,7 +3189,7 @@ struct CxxrtlWorker { if (wire->name.isPublic() && !inline_public) continue; if (flow.is_inlinable(wire, live_wires[wire])) { if (flow.wire_comb_defs[wire].size() > 1) - log_cmd_error("Wire %s.%s has multiple drivers!\n", log_id(module), log_id(wire)); + log_cmd_error("Wire %s.%s has multiple drivers!\n", module, wire); log_assert(flow.wire_comb_defs[wire].size() == 1); FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin(); switch (node->type) { @@ -3237,9 +3237,9 @@ struct CxxrtlWorker { buffered_comb_wires.insert(wire); if (!buffered_comb_wires.empty()) { has_buffered_comb_wires = true; - log("Module `%s' contains buffered combinatorial wires:\n", log_id(module)); + log("Module `%s' contains buffered combinatorial wires:\n", module); for (auto wire : buffered_comb_wires) - log(" %s\n", log_id(wire)); + log(" %s\n", wire); } // Record whether eval() requires only one delta cycle in this module. diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 145477b6b..180c3739b 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -207,9 +207,9 @@ struct EdifBackend : public Backend { top_module_name = module->name.str(); if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", module->name.unescape()); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", module->name.unescape()); for (auto cell : module->cells()) { @@ -317,12 +317,12 @@ struct EdifBackend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", log_id(it.first->name)); + // log("Next in topological sort: %s\n", it.first->name.unescape()); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape()); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -486,7 +486,7 @@ struct EdifBackend : public Backend { for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1) log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n", - i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i])); + i, module, cell, p.first.unescape(), log_signal(sig[i])); else { int member_idx = lsbidx ? i : GetSize(sig)-i-1; auto m = design->module(cell->type); diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 577d95ad7..db5036552 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -82,7 +82,7 @@ const char *make_id(IdString id) if (namecache.count(id) != 0) return namecache.at(id).c_str(); - string new_id = log_id(id); + string new_id = id.unescape(); for (int i = 0; i < GetSize(new_id); i++) { @@ -263,7 +263,7 @@ void emit_extmodule(RTLIL::Cell *cell, RTLIL::Module *mod_instance, std::ostream if (wire->port_input && wire->port_output) { - log_error("Module port %s.%s is inout!\n", log_id(mod_instance), log_id(wire)); + log_error("Module port %s.%s is inout!\n", mod_instance, wire); } const std::string portDecl = stringf("%s%s %s: UInt<%d> %s\n", @@ -559,12 +559,12 @@ struct FirrtlWorker if (wire->attributes.count(ID::init)) { log_warning("Initial value (%s) for (%s.%s) not supported\n", wire->attributes.at(ID::init).as_string().c_str(), - log_id(module), log_id(wire)); + module, wire); } if (wire->port_id) { if (wire->port_input && wire->port_output) - log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); + log_error("Module port %s.%s is inout!\n", module, wire); port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent, wire->port_input ? "input" : "output", wireName, wire->width, wireFileinfo.c_str())); } @@ -833,7 +833,7 @@ struct FirrtlWorker primop = "shl"; int shiftAmount = b_sig.as_int(); if (shiftAmount < 0) { - log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell)); + log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, module, cell); } b_expr = std::to_string(shiftAmount); firrtl_width = a_width + shiftAmount; @@ -844,7 +844,7 @@ struct FirrtlWorker firrtl_width = a_width + (1 << b_width) - 1; } } else { - log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell)); + log_error("Non power 2: %s.%s\n", module, cell); } } @@ -905,7 +905,7 @@ struct FirrtlWorker { bool clkpol = cell->parameters.at(ID::CLK_POLARITY).as_bool(); if (clkpol == false) - log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); + log_error("Negative edge clock on FF %s.%s.\n", module, cell); int width = cell->parameters.at(ID::WIDTH).as_int(); string expr = make_expr(cell->getPort(ID::D)); @@ -983,7 +983,7 @@ struct FirrtlWorker if (cell->type == ID($scopeinfo)) continue; - log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_error("Cell type not supported: %s (%s.%s)\n", cell->type.unescape(), module, cell); } for (auto &mem : memories) { @@ -991,10 +991,10 @@ struct FirrtlWorker Const init_data = mem.get_init_data(); if (!init_data.is_fully_undef()) - log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(mem.memid)); + log_error("Memory with initialization data: %s.%s\n", module, mem.memid.unescape()); if (mem.start_offset != 0) - log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(mem.memid)); + log_error("Memory with nonzero offset: %s.%s\n", module, mem.memid.unescape()); for (int i = 0; i < GetSize(mem.rd_ports); i++) { @@ -1002,7 +1002,7 @@ struct FirrtlWorker string port_name(stringf("%s.r%d", mem_id, i)); if (port.clk_enable) - log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Clocked read port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); std::ostringstream rpe; @@ -1023,12 +1023,12 @@ struct FirrtlWorker string port_name(stringf("%s.w%d", mem_id, i)); if (!port.clk_enable) - log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Unclocked write port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); if (!port.clk_polarity) - log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Negedge write port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); for (int i = 1; i < GetSize(port.en); i++) if (port.en[0] != port.en[i]) - log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid)); + log_error("Complex write enable on port %d on memory %s.%s.\n", i, module, mem.memid.unescape()); std::ostringstream wpe; diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index ad16d50ab..5e1a3fc8d 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -133,26 +133,26 @@ struct IntersynthBackend : public Backend { if (selected && !design->selected_whole_module(module->name)) { if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); + log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape()); continue; } - log("Generating netlist %s.\n", log_id(module->name)); + log("Generating netlist %s.\n", module->name.unescape()); if (module->memories.size() != 0 || module->processes.size() != 0) log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n"); std::set constcells_code; - netlists_code += stringf("# Netlist of module %s\n", log_id(module->name)); - netlists_code += stringf("netlist %s\n", log_id(module->name)); + netlists_code += stringf("# Netlist of module %s\n", module->name.unescape()); + netlists_code += stringf("netlist %s\n", module->name.unescape()); // Module Ports: "std::set celltypes_code" prevents duplicate top level ports for (auto wire : module->wires()) { if (wire->port_input || wire->port_output) { celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n", - log_id(wire->name), wire->width, wire->port_input ? "*" : "", - wire->port_input ? "input" : "output", log_id(wire->name), wire->width, log_id(wire->name))); - netlists_code += stringf("node %s %s PORT %s\n", log_id(wire->name), log_id(wire->name), + wire->name.unescape(), wire->width, wire->port_input ? "*" : "", + wire->port_input ? "input" : "output", wire->name.unescape(), wire->width, wire->name.unescape())); + netlists_code += stringf("node %s %s PORT %s\n", wire->name.unescape(), wire->name.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str()); } } @@ -163,26 +163,26 @@ struct IntersynthBackend : public Backend { std::string celltype_code, node_code; if (!ct.cell_known(cell->type)) - log_error("Found unknown cell type %s in module!\n", log_id(cell->type)); + log_error("Found unknown cell type %s in module!\n", cell->type.unescape()); - celltype_code = stringf("celltype %s", log_id(cell->type)); - node_code = stringf("node %s %s", log_id(cell->name), log_id(cell->type)); + celltype_code = stringf("celltype %s", cell->type.unescape()); + node_code = stringf("node %s %s", cell->name.unescape(), cell->type.unescape()); for (auto &port : cell->connections()) { RTLIL::SigSpec sig = sigmap(port.second); if (sig.size() != 0) { conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); - celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", log_id(port.first)); - node_code += stringf(" %s %s", log_id(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig)); + celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", port.first.unescape()); + node_code += stringf(" %s %s", port.first.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sig)); } } for (auto ¶m : cell->parameters) { - celltype_code += stringf(" cfg:%d %s", int(param.second.size()), log_id(param.first)); + celltype_code += stringf(" cfg:%d %s", int(param.second.size()), param.first.unescape()); if (param.second.size() != 32) { - node_code += stringf(" %s '", log_id(param.first)); + node_code += stringf(" %s '", param.first.unescape()); for (int i = param.second.size()-1; i >= 0; i--) node_code += param.second[i] == State::S1 ? "1" : "0"; } else - node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int()); + node_code += stringf(" %s 0x%x", param.first.unescape(), param.second.as_int()); } celltypes_code.insert(celltype_code + "\n"); diff --git a/backends/json/json.cc b/backends/json/json.cc index b04083622..234574ed1 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -152,7 +152,7 @@ struct JsonWriter sigidcounter = 2; if (module->has_processes()) { - log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module)); + log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", module); } f << stringf(" %s: {\n", get_name(module->name)); @@ -316,13 +316,13 @@ struct JsonWriter f << stringf(" /* %3d */ [ ", node_idx); if (node.portbit >= 0) f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "", - log_id(node.portname), node.portbit); + node.portname.unescape(), node.portbit); else if (node.left_parent < 0 && node.right_parent < 0) f << stringf("\"%s\"", node.inverter ? "true" : "false"); else f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent); for (auto &op : node.outports) - f << stringf(", \"%s\", %d", log_id(op.first), op.second); + f << stringf(", \"%s\", %d", op.first.unescape(), op.second); f << stringf(" ]"); node_idx++; } diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index 8ebc685f0..baf5aa006 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -78,7 +78,7 @@ struct HierDirtyFlags for (Cell *cell : module->cells()) { Module *mod = module->design->module(cell->type); if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this, - prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name)); + prefix + cid(cell->name) + ".", log_prefix + "." + prefix + cell->name.unescape()); } } @@ -354,23 +354,23 @@ struct SimplecWorker struct_declarations.push_back(" // Input Ports"); for (Wire *w : mod->wires()) if (w->port_input) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w))); + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w)); struct_declarations.push_back(""); struct_declarations.push_back(" // Output Ports"); for (Wire *w : mod->wires()) if (!w->port_input && w->port_output) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w))); + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w)); struct_declarations.push_back(""); struct_declarations.push_back(" // Internal Wires"); for (Wire *w : mod->wires()) if (!w->port_input && !w->port_output) - struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w))); + struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w)); for (Cell *c : mod->cells()) if (design->module(c->type)) - struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), log_id(c))); + struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), c)); struct_declarations.push_back(stringf("};")); struct_declarations.push_back("#endif"); @@ -391,7 +391,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -418,7 +418,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -441,7 +441,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -466,7 +466,7 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; @@ -490,13 +490,13 @@ struct SimplecWorker log_assert(y.wire); funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) + - stringf(" // %s (%s)", log_id(cell), log_id(cell->type))); + stringf(" // %s (%s)", cell, cell->type.unescape())); work->set_dirty(y); return; } - log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type)); + log_error("No C model for %s available at the moment (FIXME).\n", cell->type.unescape()); } void eval_dirty(HierDirtyFlags *work) @@ -517,7 +517,7 @@ struct SimplecWorker if (chunk.wire == nullptr) continue; if (verbose) - log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset); + log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, chunk.wire, chunk.offset+chunk.width-1, chunk.offset); funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix, log_signal(chunk))); } @@ -539,8 +539,8 @@ struct SimplecWorker work->parent->set_dirty(parent_bit); if (verbose) - log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset, - work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset); + log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset, + work->parent->log_prefix.c_str(), parent_bit.wire, parent_bit.offset); } for (auto &port : bit2cell[work->module][bit]) @@ -556,12 +556,12 @@ struct SimplecWorker child->set_dirty(child_bit); if (verbose) - log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset, - work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset); + log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset, + work->log_prefix.c_str(), std::get<0>(port), child_bit.wire, child_bit.offset); } else { if (verbose) - log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, log_id(std::get<0>(port)), - work->log_prefix.c_str(), log_id(bit.wire), bit.offset); + log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, std::get<0>(port), + work->log_prefix.c_str(), bit.wire, bit.offset); work->set_dirty(std::get<0>(port)); } } @@ -576,10 +576,10 @@ struct SimplecWorker if (cell == nullptr || topoidx.at(cell) < topoidx.at(c)) cell = c; - string hiername = work->log_prefix + "." + log_id(cell); + string hiername = work->log_prefix + "." + cell->name.unescape(); if (verbose) - log(" Evaluating %s (%s, best of %d).\n", hiername, log_id(cell->type), GetSize(work->dirty_cells)); + log(" Evaluating %s (%s, best of %d).\n", hiername, cell->type.unescape(), GetSize(work->dirty_cells)); if (activated_cells.count(hiername)) reactivated_cells.insert(hiername); @@ -618,8 +618,8 @@ struct SimplecWorker if (verbose) log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n", - work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset, - work->log_prefix.c_str(), log_id(bit.wire), bit.offset); + work->log_prefix.c_str(), canonical_bit.wire, canonical_bit.offset, + work->log_prefix.c_str(), bit.wire, bit.offset); } work->sticky_dirty_bits.clear(); @@ -716,7 +716,7 @@ struct SimplecWorker { create_module_struct(mod); - HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name)); + HierDirtyFlags work(mod, IdString(), nullptr, "state->", mod->name.unescape()); make_init_func(&work); make_eval_func(&work); diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 9d0ebc2aa..a9030e18a 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -60,7 +60,7 @@ struct Smt2Worker const char *get_id(IdString n) { if (ids.count(n) == 0) { - std::string str = log_id(n); + std::string str = n.unescape(); for (int i = 0; i < GetSize(str); i++) { if (str[i] == '\\') str[i] = '/'; @@ -207,7 +207,7 @@ struct Smt2Worker } else if (is_output || !is_input) log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n", - log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type)); + conn.first.unescape(), module, cell, cell->type.unescape()); if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C)) { @@ -448,7 +448,7 @@ struct Smt2Worker } if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(bit))); @@ -498,7 +498,7 @@ struct Smt2Worker processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr); if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); if (type == 'b') { decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", @@ -529,7 +529,7 @@ struct Smt2Worker processed_expr += ch; if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n", get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(sig_y))); @@ -541,7 +541,7 @@ struct Smt2Worker { if (verbose) log("%*s=> export_cell %s (%s) [%s]\n", 2+2*GetSize(recursive_cells), "", - log_id(cell), log_id(cell->type), exported_cells.count(cell) ? "old" : "new"); + cell, cell->type.unescape(), exported_cells.count(cell) ? "old" : "new"); if (recursive_cells.count(cell)) log_error("Found logic loop in module %s! See cell %s.\n", get_id(module), get_id(cell)); @@ -750,7 +750,7 @@ struct Smt2Worker get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str()); if (verbose) - log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell)); + log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell); RTLIL::SigSpec sig = sigmap(cell->getPort(ID::Y)); decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", @@ -786,9 +786,9 @@ struct Smt2Worker has_async_wr = true; } if (has_async_wr && has_sync_wr) - log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module)); + log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", cell, module); - decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(mem->memid), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync")); + decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", mem->memid.unescape(), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync")); decls.push_back(witness_memory(get_id(mem->memid), cell, mem)); string memstate; @@ -813,7 +813,7 @@ struct Smt2Worker if (port.clk_enable) log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " - "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module)); + "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module); decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); @@ -857,7 +857,7 @@ struct Smt2Worker if (port.clk_enable) log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! " - "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module)); + "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module); decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n", get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig))); @@ -928,30 +928,30 @@ struct Smt2Worker if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) { log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") { log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") { log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type, module, cell); } log_error("Unsupported cell type %s for cell %s.%s.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type, module, cell); } void verify_smtlib2_module() { if (!module->get_blackbox_attribute()) - log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", log_id(module)); + log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", module); if (module->cells().size() > 0) - log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", log_id(module)); + log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", module); for (auto wire : module->wires()) if (!wire->port_id) - log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", log_id(module), - log_id(wire)); + log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", module, + wire); } void run() @@ -991,8 +991,8 @@ struct Smt2Worker } bool is_smtlib2_comb_expr = wire->has_attribute(ID::smtlib2_comb_expr); if (is_smtlib2_comb_expr && !is_smtlib2_module) - log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", log_id(module), - log_id(wire)); + log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", module, + wire); if (wire->port_id || is_register || contains_clock || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) { RTLIL::SigSpec sig = sigmap(wire); std::vector comments; @@ -1023,10 +1023,10 @@ struct Smt2Worker smtlib2_comb_expr = "(let (\n" + smtlib2_inputs + ")\n" + wire->get_string_attribute(ID::smtlib2_comb_expr) + "\n)"; if (wire->port_input || !wire->port_output) - log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", log_id(module), log_id(wire)); + log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", module, wire); if (!bvmode && GetSize(sig) > 1) log_error("smtlib2_comb_expr is unsupported on multi-bit wires when -nobv is specified: wire %s.%s", - log_id(module), log_id(wire)); + module, wire); comments.push_back(witness_signal("blackbox", wire->width, 0, get_id(wire), -1, wire)); } @@ -1075,7 +1075,7 @@ struct Smt2Worker if (wire->attributes.count(ID::init)) { if (is_smtlib2_module) log_error("init attribute not allowed on wires in module with smtlib2_module attribute: wire %s.%s", - log_id(module), log_id(wire)); + module, wire); RTLIL::SigSpec sig = sigmap(wire); Const val = wire->attributes.at(ID::init); @@ -1381,7 +1381,7 @@ struct Smt2Worker } } - if (verbose) log("=> finalizing SMT2 representation of %s.\n", log_id(module)); + if (verbose) log("=> finalizing SMT2 representation of %s.\n", module); for (auto c : hiercells) { assert_list.push_back(stringf("(|%s_a| (|%s_h %s| state))", get_id(c->type), get_id(module), get_id(c->name))); @@ -1867,12 +1867,12 @@ struct Smt2Backend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", log_id(it.first->name)); + // log("Next in topological sort: %s\n", it.first->name.unescape()); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape()); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -1902,7 +1902,7 @@ struct Smt2Backend : public Backend { if (module->has_processes_warn()) continue; - log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); + log("Creating SMT-LIBv2 representation of module %s.\n", module); Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache); worker.run(); diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index acefad060..01f95ef45 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -217,7 +217,7 @@ struct SmvWorker partial_assignment_wires.insert(wire); if (wire->port_input) - inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire))); + inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, wire)); if (wire->attributes.count(ID::init)) assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at(ID::init)))); @@ -579,18 +579,18 @@ struct SmvWorker if (cell->type[0] == '$') { if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) { log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") { log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") { log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } log_error("Unsupported cell type %s for cell %s.%s.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); } // f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type)); @@ -799,7 +799,7 @@ struct SmvBackend : public Backend { *f << stringf("-- SMV description generated by %s\n", yosys_maybe_version()); - log("Creating SMV representation of module %s.\n", log_id(module)); + log("Creating SMV representation of module %s.\n", module); SmvWorker worker(module, verbose, *f); worker.run(); @@ -819,7 +819,7 @@ struct SmvBackend : public Backend { *f << stringf("-- SMV description generated by %s\n", yosys_maybe_version()); for (auto module : modules) { - log("Creating SMV representation of module %s.\n", log_id(module)); + log("Creating SMV representation of module %s.\n", module); SmvWorker worker(module, verbose, *f); worker.run(); } diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 16458d647..36caf6359 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -82,7 +82,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De if (design->module(cell->type) == nullptr) { log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", - log_id(cell->type), log_id(module), log_id(cell)); + cell->type.unescape(), module, cell); for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); port_sigs.push_back(sig); @@ -224,9 +224,9 @@ struct SpiceBackend : public Backend { continue; if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", log_id(module)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", module); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", log_id(module)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", module); if (module->name == RTLIL::escape_id(top_module_name)) { top_module = module; diff --git a/backends/table/table.cc b/backends/table/table.cc index 2bf64e7b1..bbb533965 100644 --- a/backends/table/table.cc +++ b/backends/table/table.cc @@ -77,8 +77,8 @@ struct TableBackend : public Backend { if (wire->port_id == 0) continue; - *f << log_id(module) << "\t"; - *f << log_id(wire) << "\t"; + *f << module->name.unescape() << "\t"; + *f << wire->name.unescape() << "\t"; *f << "-" << "\t"; *f << "-" << "\t"; @@ -97,10 +97,10 @@ struct TableBackend : public Backend { for (auto cell : module->cells()) for (auto conn : cell->connections()) { - *f << log_id(module) << "\t"; - *f << log_id(cell) << "\t"; - *f << log_id(cell->type) << "\t"; - *f << log_id(conn.first) << "\t"; + *f << module->name.unescape() << "\t"; + *f << cell->name.unescape() << "\t"; + *f << cell->type.unescape() << "\t"; + *f << conn.first.unescape() << "\t"; if (cell->input(conn.first) && cell->output(conn.first)) *f << "inout" << "\t"; diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 73ffcbf3e..473918264 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -2388,7 +2388,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) log_warning("Module %s contains RTLIL processes with sync rules. Such RTLIL " "processes can't always be mapped directly to Verilog always blocks. " "unintended changes in simulation behavior are possible! Use \"proc\" " - "to convert processes to logic networks and registers.\n", log_id(module)); + "to convert processes to logic networks and registers.\n", module); f << stringf("\n"); for (auto it = module->processes.begin(); it != module->processes.end(); ++it) @@ -2714,7 +2714,7 @@ struct VerilogBackend : public Backend { continue; if (selected && !design->selected_whole_module(module->name)) { if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); + log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape()); continue; } log("Dumping module `%s'.\n", module->name); diff --git a/docs/source/code_examples/extensions/my_cmd.cc b/docs/source/code_examples/extensions/my_cmd.cc index d52268b4a..742697b6e 100644 --- a/docs/source/code_examples/extensions/my_cmd.cc +++ b/docs/source/code_examples/extensions/my_cmd.cc @@ -14,7 +14,7 @@ struct MyPass : public Pass { log("Modules in current design:\n"); for (auto mod : design->modules()) - log(" %s (%d wires, %d cells)\n", log_id(mod), + log(" %s (%d wires, %d cells)\n", mod, GetSize(mod->wires()), GetSize(mod->cells())); } } MyPass; @@ -28,7 +28,7 @@ struct Test1Pass : public Pass { log_error("A module with the name absval already exists!\n"); RTLIL::Module *module = design->addModule("\\absval"); - log("Name of this module: %s\n", log_id(module)); + log("Name of this module: %s\n", module); RTLIL::Wire *a = module->addWire("\\a", 4); a->port_input = true; diff --git a/examples/cxx-api/scopeinfo_example.cc b/examples/cxx-api/scopeinfo_example.cc index fd5d2a781..edbd1533f 100644 --- a/examples/cxx-api/scopeinfo_example.cc +++ b/examples/cxx-api/scopeinfo_example.cc @@ -61,7 +61,7 @@ struct ScopeinfoExamplePass : public Pass { if (do_wires) { for (auto module : design->selected_modules()) { - log("Source hierarchy for all selected wires within %s:\n", log_id(module)); + log("Source hierarchy for all selected wires within %s:\n", module); ModuleHdlnameIndex index(module); index.index_scopeinfo_cells(); @@ -73,11 +73,11 @@ struct ScopeinfoExamplePass : public Pass { auto wire_scope = index.containing_scope(wire); if (!wire_scope.first.valid()) { - log_warning("Couldn't find containing scope for %s in index\n", log_id(wire)); + log_warning("Couldn't find containing scope for %s in index\n", wire); continue; } - log("%s %s\n", wire_scope.first.path_str(), log_id(wire_scope.second)); + log("%s %s\n", wire_scope.first.path_str(), wire_scope.second.unescape()); for (auto src : index.sources(wire)) log(" - %s\n", src); } @@ -127,9 +127,9 @@ struct ScopeinfoExamplePass : public Pass { continue; log("common_ancestor(%s %s%s%s, %s %s%s%s) = %s %s\n", - log_id(module), scope_i.first.path_str().c_str(), scope_i.first.is_root() ? "" : " ", log_id(scope_i.second), - log_id(module), scope_j.first.path_str().c_str(), scope_j.first.is_root() ? "" : " ", log_id(scope_j.second), - log_id(module), common.path_str().c_str() + module, scope_i.first.path_str().c_str(), scope_i.first.is_root() ? "" : " ", scope_i.second.unescape(), + module, scope_j.first.path_str().c_str(), scope_j.first.is_root() ? "" : " ", scope_j.second.unescape(), + module, common.path_str().c_str() ); if (++limit == 10) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 9931ef78f..b2cc613f2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -224,7 +224,7 @@ AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module = new RTLIL::Module; module->name = module_name; if (design->module(module->name)) - log_error("Duplicate definition of module %s!\n", log_id(module->name)); + log_error("Duplicate definition of module %s!\n", module->name.unescape()); } void AigerReader::parse_aiger() @@ -821,7 +821,7 @@ void AigerReader::post_process() RTLIL::Wire* wire = inputs[variable]; log_assert(wire); log_assert(wire->port_input); - log_debug("Renaming input %s", log_id(wire)); + log_debug("Renaming input %s", wire); RTLIL::Wire *existing = nullptr; if (index == 0) { @@ -835,7 +835,7 @@ void AigerReader::post_process() wire->port_input = false; module->connect(wire, existing); } - log_debug(" -> %s\n", log_id(escaped_s)); + log_debug(" -> %s\n", escaped_s.unescape()); } else { RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index); @@ -846,7 +846,7 @@ void AigerReader::post_process() module->connect(wire, existing); wire->port_input = false; } - log_debug(" -> %s\n", log_id(indexed_name)); + log_debug(" -> %s\n", indexed_name.unescape()); } if (wideports && !existing) { @@ -866,7 +866,7 @@ void AigerReader::post_process() RTLIL::Wire* wire = outputs[variable + co_count]; log_assert(wire); log_assert(wire->port_output); - log_debug("Renaming output %s", log_id(wire)); + log_debug("Renaming output %s", wire); RTLIL::Wire *existing; if (index == 0) { @@ -882,7 +882,7 @@ void AigerReader::post_process() module->connect(wire, existing); wire = existing; } - log_debug(" -> %s\n", log_id(escaped_s)); + log_debug(" -> %s\n", escaped_s.unescape()); } else { RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index); @@ -894,7 +894,7 @@ void AigerReader::post_process() existing->port_output = true; module->connect(wire, existing); } - log_debug(" -> %s\n", log_id(indexed_name)); + log_debug(" -> %s\n", indexed_name.unescape()); } if (wideports && !existing) { @@ -912,7 +912,7 @@ void AigerReader::post_process() else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$box%d", variable)); if (!cell) - log_debug("Box %d (%s) no longer exists.\n", variable, log_id(escaped_s)); + log_debug("Box %d (%s) no longer exists.\n", variable, escaped_s.unescape()); else module->rename(cell, escaped_s); } diff --git a/frontends/aiger2/xaiger.cc b/frontends/aiger2/xaiger.cc index bbec47861..a62c52169 100644 --- a/frontends/aiger2/xaiger.cc +++ b/frontends/aiger2/xaiger.cc @@ -86,7 +86,7 @@ struct Xaiger2Frontend : public Frontend { Module *module = design->module(module_name); if (!module) - log_error("Module '%s' not found\n", log_id(module_name)); + log_error("Module '%s' not found\n", module_name.unescape()); std::ifstream map_file; map_file.open(map_filename); @@ -158,7 +158,7 @@ struct Xaiger2Frontend : public Frontend { } if (!def) - log_error("Bad map file: no module found for box type '%s'\n", log_id(box->type)); + log_error("Bad map file: no module found for box type '%s'\n", box->type.unescape()); if (box_seq >= (int) boxes.size()) { boxes.resize(box_seq + 1); @@ -276,9 +276,9 @@ struct Xaiger2Frontend : public Frontend { uint32_t nins = read_be32(*f); for (uint32_t j = 0; j < nins; j++) cell.ins.push_back(read_idstring(*f)); - log_debug("M: Cell %s (out %s, ins", log_id(cell.type), log_id(cell.out)); + log_debug("M: Cell %s (out %s, ins", cell.type.unescape(), cell.out.unescape()); for (auto in : cell.ins) - log_debug(" %s", log_id(in)); + log_debug(" %s", in.unescape()); log_debug(")\n"); } diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index c190bc7d4..256321252 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1544,7 +1544,7 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule for (auto w : intfmodule->wires()){ auto loc = module_ast->location; auto wire = std::make_unique(loc, AST_WIRE, std::make_unique(loc, AST_RANGE, AstNode::mkconst_int(loc, w->width -1, true), AstNode::mkconst_int(loc, 0, true))); - std::string origname = log_id(w->name); + std::string origname = w->name.unescape(); std::string newname = intfname + "." + origname; wire->str = newname; if (modport != NULL) { @@ -1584,7 +1584,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design) continue; if (design->module(modname) || design->module("$abstract" + modname)) { log("Reprocessing module %s because instantiated module %s has become available.\n", - log_id(name), log_id(modname)); + name.unescape(), modname); loadconfig(); process_and_replace_module(design, this, ast.get(), NULL); return true; @@ -1606,7 +1606,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dictwires()){ auto wire = std::make_unique(loc, AST_WIRE, std::make_unique(loc, AST_RANGE, AstNode::mkconst_int(loc, w->width -1, true), AstNode::mkconst_int(loc, 0, true))); - std::string newname = log_id(w->name); + std::string newname = w->name.unescape(); newname = intfname + "." + newname; wire->str = newname; new_ast->children.push_back(std::move(wire)); @@ -1679,7 +1679,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dictname); + interf_info += intf.second->name.unescape(); has_interfaces = true; } @@ -1735,7 +1735,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dictset_bool_attribute(ID::is_interface); } else { - log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname); + log_error("No port with matching name found (%s) in %s. Stopping\n", intf.first, modname); } } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d9bafcd3a..718d5aa23 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -2197,10 +2197,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) const auto* value = child->children[0].get(); if (value->type == AST_REALVALUE) log_file_warning(*location.begin.filename, location.begin.line, "Replacing floating point parameter %s.%s = %f with string.\n", - log_id(cell), log_id(paraname), value->realvalue); + cell, paraname.unescape(), value->realvalue); else if (value->type != AST_CONSTANT) input_error("Parameter %s.%s with non-constant value!\n", - log_id(cell), log_id(paraname)); + cell, paraname.unescape()); cell->parameters[paraname] = value->asParaConst(); continue; } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 48a4291d2..1b98166e5 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1492,7 +1492,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin const RTLIL::Wire *ref = module->wire(port_name); if (ref == nullptr) input_error("Cell instance refers to port %s which does not exist in module %s!.\n", - log_id(port_name), log_id(module->name)); + port_name.unescape(), module->name.unescape()); // select the argument, if present log_assert(child->children.size() <= 1); diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 350d7cafe..2eae64fa1 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -175,7 +175,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool obj_attributes = &module->attributes; obj_parameters = nullptr; if (design->module(module->name)) - log_error("Duplicate definition of module %s in line %d!\n", log_id(module->name), line_count); + log_error("Duplicate definition of module %s in line %d!\n", module->name.unescape(), line_count); design->add(module); continue; } diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 803931f32..0fac902b5 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -295,7 +295,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->name = RTLIL::escape_id(modname.c_str()); if (design->module(module->name)) - log_error("Re-definition of module %s.\n", log_id(module->name)); + log_error("Re-definition of module %s.\n", module->name.unescape()); design->add(module); @@ -320,22 +320,22 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *port_node = ports_node->data_dict.at(ports_node->data_dict_keys[port_id-1]); if (port_node->type != 'D') - log_error("JSON port node '%s' is not a dictionary.\n", log_id(port_name)); + log_error("JSON port node '%s' is not a dictionary.\n", port_name.unescape()); if (port_node->data_dict.count("direction") == 0) - log_error("JSON port node '%s' has no direction attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has no direction attribute.\n", port_name.unescape()); if (port_node->data_dict.count("bits") == 0) - log_error("JSON port node '%s' has no bits attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has no bits attribute.\n", port_name.unescape()); JsonNode *port_direction_node = port_node->data_dict.at("direction"); JsonNode *port_bits_node = port_node->data_dict.at("bits"); if (port_direction_node->type != 'S') - log_error("JSON port node '%s' has non-string direction attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has non-string direction attribute.\n", port_name.unescape()); if (port_bits_node->type != 'A') - log_error("JSON port node '%s' has non-array bits attribute.\n", log_id(port_name)); + log_error("JSON port node '%s' has non-array bits attribute.\n", port_name.unescape()); Wire *port_wire = module->wire(port_name); @@ -370,7 +370,7 @@ void json_import(Design *design, string &modname, JsonNode *node) port_wire->port_input = true; port_wire->port_output = true; } else - log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", log_id(port_name), port_direction_node->data_string); + log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", port_name.unescape(), port_direction_node->data_string); port_wire->port_id = port_id; @@ -390,7 +390,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->connect(sigbit, State::Sz); else log_error("JSON port node '%s' has invalid '%s' bit string value on bit %d.\n", - log_id(port_name), bitval_node->data_string.c_str(), i); + port_name.unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -405,7 +405,7 @@ void json_import(Design *design, string &modname, JsonNode *node) signal_bits[bitidx] = sigbit; } } else - log_error("JSON port node '%s' has invalid bit value on bit %d.\n", log_id(port_name), i); + log_error("JSON port node '%s' has invalid bit value on bit %d.\n", port_name.unescape(), i); } } @@ -425,15 +425,15 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *net_node = net.second; if (net_node->type != 'D') - log_error("JSON netname node '%s' is not a dictionary.\n", log_id(net_name)); + log_error("JSON netname node '%s' is not a dictionary.\n", net_name.unescape()); if (net_node->data_dict.count("bits") == 0) - log_error("JSON netname node '%s' has no bits attribute.\n", log_id(net_name)); + log_error("JSON netname node '%s' has no bits attribute.\n", net_name.unescape()); JsonNode *bits_node = net_node->data_dict.at("bits"); if (bits_node->type != 'A') - log_error("JSON netname node '%s' has non-array bits attribute.\n", log_id(net_name)); + log_error("JSON netname node '%s' has non-array bits attribute.\n", net_name.unescape()); Wire *wire = module->wire(net_name); @@ -468,7 +468,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->connect(sigbit, State::Sz); else log_error("JSON netname node '%s' has invalid '%s' bit string value on bit %d.\n", - log_id(net_name), bitval_node->data_string.c_str(), i); + net_name.unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -479,7 +479,7 @@ void json_import(Design *design, string &modname, JsonNode *node) signal_bits[bitidx] = sigbit; } } else - log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", log_id(net_name), i); + log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", net_name.unescape(), i); } if (net_node->data_dict.count("attributes")) @@ -500,27 +500,27 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *cell_node = cell_node_it.second; if (cell_node->type != 'D') - log_error("JSON cells node '%s' is not a dictionary.\n", log_id(cell_name)); + log_error("JSON cells node '%s' is not a dictionary.\n", cell_name.unescape()); if (cell_node->data_dict.count("type") == 0) - log_error("JSON cells node '%s' has no type attribute.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has no type attribute.\n", cell_name.unescape()); JsonNode *type_node = cell_node->data_dict.at("type"); if (type_node->type != 'S') - log_error("JSON cells node '%s' has a non-string type.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has a non-string type.\n", cell_name.unescape()); IdString cell_type = RTLIL::escape_id(type_node->data_string.c_str()); Cell *cell = module->addCell(cell_name, cell_type); if (cell_node->data_dict.count("connections") == 0) - log_error("JSON cells node '%s' has no connections attribute.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has no connections attribute.\n", cell_name.unescape()); JsonNode *connections_node = cell_node->data_dict.at("connections"); if (connections_node->type != 'D') - log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", log_id(cell_name)); + log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", cell_name.unescape()); for (auto &conn_it : connections_node->data_dict) { @@ -528,7 +528,7 @@ void json_import(Design *design, string &modname, JsonNode *node) JsonNode *conn_node = conn_it.second; if (conn_node->type != 'A') - log_error("JSON cells node '%s' connection '%s' is not an array.\n", log_id(cell_name), log_id(conn_name)); + log_error("JSON cells node '%s' connection '%s' is not an array.\n", cell_name.unescape(), conn_name.unescape()); SigSpec sig; @@ -547,7 +547,7 @@ void json_import(Design *design, string &modname, JsonNode *node) sig.append(State::Sz); else log_error("JSON cells node '%s' connection '%s' has invalid '%s' bit string value on bit %d.\n", - log_id(cell_name), log_id(conn_name), bitval_node->data_string.c_str(), i); + cell_name.unescape(), conn_name.unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -556,7 +556,7 @@ void json_import(Design *design, string &modname, JsonNode *node) sig.append(signal_bits.at(bitidx)); } else log_error("JSON cells node '%s' connection '%s' has invalid bit value on bit %d.\n", - log_id(cell_name), log_id(conn_name), i); + cell_name.unescape(), conn_name.unescape(), i); } @@ -587,20 +587,20 @@ void json_import(Design *design, string &modname, JsonNode *node) mem->name = memory_name; if (memory_node->type != 'D') - log_error("JSON memory node '%s' is not a dictionary.\n", log_id(memory_name)); + log_error("JSON memory node '%s' is not a dictionary.\n", memory_name.unescape()); if (memory_node->data_dict.count("width") == 0) - log_error("JSON memory node '%s' has no width attribute.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has no width attribute.\n", memory_name.unescape()); JsonNode *width_node = memory_node->data_dict.at("width"); if (width_node->type != 'N') - log_error("JSON memory node '%s' has a non-number width.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has a non-number width.\n", memory_name.unescape()); mem->width = width_node->data_number; if (memory_node->data_dict.count("size") == 0) - log_error("JSON memory node '%s' has no size attribute.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has no size attribute.\n", memory_name.unescape()); JsonNode *size_node = memory_node->data_dict.at("size"); if (size_node->type != 'N') - log_error("JSON memory node '%s' has a non-number size.\n", log_id(memory_name)); + log_error("JSON memory node '%s' has a non-number size.\n", memory_name.unescape()); mem->size = size_node->data_number; mem->start_offset = 0; diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index c21867b30..bc5ef013d 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -212,7 +212,7 @@ struct RpcModule : RTLIL::Module { for (auto module : derived_design->modules_) { std::string mangled_name = name_mangling[module.first.str()]; - log("Importing `%s' as `%s'.\n", log_id(module.first), log_id(mangled_name)); + log("Importing `%s' as `%s'.\n", module.first.unescape(), mangled_name); module.second->name = mangled_name; module.second->design = design; diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc index 7e2ec5460..4709c76ed 100644 --- a/frontends/rtlil/rtlil_frontend.cc +++ b/frontends/rtlil/rtlil_frontend.cc @@ -332,7 +332,7 @@ struct RTLILFrontendWorker { error("No wires found for legalization"); int hash = hash_ops::hash(id).yield(); RTLIL::Wire *wire = current_module->wire_at(abs(hash % wires_size)); - log("Legalizing wire `%s' to `%s'.\n", log_id(id), log_id(wire->name)); + log("Legalizing wire `%s' to `%s'.\n", id.unescape(), wire->name.unescape()); return wire; } diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 6a1c81aa4..ec3d21ccd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1392,13 +1392,13 @@ void VerificImporter::merge_past_ffs_clock(pool &candidates, SigBi RTLIL::Cell *new_ff = module->addDff(NEW_ID, clock, sig_d, sig_q, clock_pol); if (verific_verbose) - log(" merging single-bit past_ffs into new %d-bit ff %s.\n", GetSize(sig_d), log_id(new_ff)); + log(" merging single-bit past_ffs into new %d-bit ff %s.\n", GetSize(sig_d), new_ff); for (int i = 0; i < GetSize(sig_d); i++) for (auto old_ff : dbits_db[sig_d[i]]) { if (verific_verbose) - log(" replacing old ff %s on bit %d.\n", log_id(old_ff), i); + log(" replacing old ff %s on bit %d.\n", old_ff, i); SigBit old_q = old_ff->getPort(ID::Q); SigBit new_q = sig_q[i]; @@ -1736,7 +1736,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net)); if (verific_verbose) - log(" importing net %s as %s.\n", net->Name(), log_id(wire_name)); + log(" importing net %s as %s.\n", net->Name(), wire_name.unescape()); RTLIL::Wire *wire = module->addWire(wire_name); import_attributes(wire->attributes, net, nl, 1); @@ -1760,7 +1760,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus)); if (verific_verbose) - log(" importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name)); + log(" importing netbus %s as %s.\n", netbus->Name(), wire_name.unescape()); RTLIL::Wire *wire = module->addWire(wire_name, netbus->Size()); wire->start_offset = min(netbus->LeftIndex(), netbus->RightIndex()); @@ -1894,7 +1894,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst)); if (verific_verbose) - log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name)); + log(" importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), inst_name.unescape()); if (mode_verific) goto import_verific_cells; @@ -2258,7 +2258,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma for (auto &it : cell_port_conns) { if (verific_verbose) - log(" .%s(%s)\n", log_id(it.first), log_signal(it.second)); + log(" .%s(%s)\n", it.first.unescape(), log_signal(it.second)); cell->setPort(it.first, it.second); } } diff --git a/kernel/cost.cc b/kernel/cost.cc index 4942823d3..230afdeb1 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -210,6 +210,6 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) // TODO: $fsm // ignored: $pow $memrd $memwr $meminit (and v2 counterparts) - log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters)); + log_warning("Can't determine cost of %s cell (%d parameters).\n", cell->type.unescape(), GetSize(cell->parameters)); return 1; } diff --git a/kernel/drivertools.cc b/kernel/drivertools.cc index 90bfb0ee7..55616dea1 100644 --- a/kernel/drivertools.cc +++ b/kernel/drivertools.cc @@ -866,7 +866,7 @@ DriveSpec DriverMap::operator()(DriveSpec spec) std::string log_signal(DriveChunkWire const &chunk) { - const char *id = log_id(chunk.wire->name); + std::string id = chunk.wire->name.unescape(); if (chunk.is_whole()) return id; if (chunk.width == 1) @@ -877,8 +877,8 @@ std::string log_signal(DriveChunkWire const &chunk) std::string log_signal(DriveChunkPort const &chunk) { - const char *cell_id = log_id(chunk.cell->name); - const char *port_id = log_id(chunk.port); + std::string cell_id = chunk.cell->name.unescape(); + std::string port_id = chunk.port.unescape(); if (chunk.is_whole()) return stringf("%s <%s>", cell_id, port_id); if (chunk.width == 1) diff --git a/kernel/ff.cc b/kernel/ff.cc index 7dd5e24ac..727a9d9cb 100644 --- a/kernel/ff.cc +++ b/kernel/ff.cc @@ -792,7 +792,7 @@ void FfData::flip_bits(const pool &bits) { Wire *new_q = module->addWire(NEW_ID, width); if (has_sr && cell) { - log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].\n", log_id(module->name), log_id(cell->name), log_id(cell->type)); + log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].\n", module->name.unescape(), cell->name.unescape(), cell->type.unescape()); } if (is_fine) { diff --git a/kernel/functional.cc b/kernel/functional.cc index 2a1bf598a..4d1423b28 100644 --- a/kernel/functional.cc +++ b/kernel/functional.cc @@ -572,7 +572,7 @@ private: const auto &wr = mem->wr_ports[i]; if (wr.clk_enable) log_error("Write port %zd of memory %s.%s is clocked. This is not supported by the functional backend. " - "Call async2sync or clk2fflogic to avoid this error.\n", i, log_id(mem->module), log_id(mem->memid)); + "Call async2sync or clk2fflogic to avoid this error.\n", i, mem->module, mem->memid.unescape()); Node en = enqueue(driver_map(DriveSpec(wr.en))); Node addr = enqueue(driver_map(DriveSpec(wr.addr))); Node new_data = enqueue(driver_map(DriveSpec(wr.data))); @@ -582,12 +582,12 @@ private: } if (mem->rd_ports.empty()) log_error("Memory %s.%s has no read ports. This is not supported by the functional backend. " - "Call opt_clean to remove it.", log_id(mem->module), log_id(mem->memid)); + "Call opt_clean to remove it.", mem->module, mem->memid.unescape()); for (size_t i = 0; i < mem->rd_ports.size(); i++) { const auto &rd = mem->rd_ports[i]; if (rd.clk_enable) log_error("Read port %zd of memory %s.%s is clocked. This is not supported by the functional backend. " - "Call memory_nordff to avoid this error.\n", i, log_id(mem->module), log_id(mem->memid)); + "Call memory_nordff to avoid this error.\n", i, mem->module, mem->memid.unescape()); Node addr = enqueue(driver_map(DriveSpec(rd.addr))); read_results.push_back(factory.memory_read(node, addr)); } @@ -609,7 +609,7 @@ private: FfData ff(&ff_initvals, cell); if (!ff.has_gclk) log_error("The design contains a %s flip-flop at %s. This is not supported by the functional backend. " - "Call async2sync or clk2fflogic to avoid this error.\n", log_id(cell->type), log_id(cell)); + "Call async2sync or clk2fflogic to avoid this error.\n", cell->type.unescape(), cell); auto &state = factory.add_state(ff.name, ID($state), Sort(ff.width)); Node q_value = factory.value(state); factory.suggest_name(q_value, ff.name); diff --git a/kernel/log.cc b/kernel/log.cc index b114f1eaf..fd3f75502 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -586,7 +586,7 @@ void log_flush() } void log_dump_val_worker(RTLIL::IdString v) { - log("%s", log_id(v)); + log("%s", v.unescape()); } void log_dump_val_worker(RTLIL::SigSpec v) { diff --git a/kernel/mem.cc b/kernel/mem.cc index 02d12dea4..2f7f16c7a 100644 --- a/kernel/mem.cc +++ b/kernel/mem.cc @@ -663,15 +663,15 @@ namespace { auto addr = cell->getPort(ID::ADDR); auto data = cell->getPort(ID::DATA); if (!addr.is_fully_const()) - log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), log_id(cell)); + log_error("Non-constant address %s in memory initialization %s.\n", log_signal(addr), cell); if (!data.is_fully_const()) - log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), log_id(cell)); + log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), cell); init.addr = addr.as_const(); init.data = data.as_const(); if (cell->type == ID($meminit_v2)) { auto en = cell->getPort(ID::EN); if (!en.is_fully_const()) - log_error("Non-constant enable %s in memory initialization %s.\n", log_signal(en), log_id(cell)); + log_error("Non-constant enable %s in memory initialization %s.\n", log_signal(en), cell); init.en = en.as_const(); } else { init.en = RTLIL::Const(State::S1, mem->width); @@ -1022,7 +1022,7 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) { if (c) log("Extracted %s FF from read port %d of %s.%s: %s\n", trans_use_addr ? "addr" : "data", - idx, log_id(module), log_id(memid), log_id(c)); + idx, module, memid.unescape(), c); port.en = State::S1; port.clk = State::S0; diff --git a/kernel/modtools.h b/kernel/modtools.h index 285f22b2a..bdcb0f108 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -320,8 +320,8 @@ struct ModIndex : public RTLIL::Monitor if (it.second.is_output) log(" PRIMARY OUTPUT\n"); for (auto &port : it.second.ports) - log(" PORT: %s.%s[%d] (%s)\n", log_id(port.cell), - log_id(port.port), port.offset, log_id(port.cell->type)); + log(" PORT: %s.%s[%d] (%s)\n", port.cell, + port.port.unescape(), port.offset, port.cell->type.unescape()); } } }; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a99f0803e..020a4ec0c 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1226,7 +1226,7 @@ void RTLIL::Design::add(RTLIL::Module *module) mon->notify_module_add(module); if (yosys_xtrace) { - log("#X# New Module: %s\n", log_id(module)); + log("#X# New Module: %s\n", module); log_backtrace("-X- ", yosys_xtrace-1); } } @@ -1252,7 +1252,7 @@ RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name) mon->notify_module_add(module); if (yosys_xtrace) { - log("#X# New Module: %s\n", log_id(module)); + log("#X# New Module: %s\n", module); log_backtrace("-X- ", yosys_xtrace-1); } @@ -1330,7 +1330,7 @@ void RTLIL::Design::remove(RTLIL::Module *module) mon->notify_module_del(module); if (yosys_xtrace) { - log("#X# Remove Module: %s\n", log_id(module)); + log("#X# Remove Module: %s\n", module); log_backtrace("-X- ", yosys_xtrace-1); } @@ -1472,22 +1472,22 @@ std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartial switch (boxes) { case RTLIL::SB_UNBOXED_WARN: - log_warning("Ignoring boxed module %s.\n", log_id(it.first)); + log_warning("Ignoring boxed module %s.\n", it.first.unescape()); break; case RTLIL::SB_EXCL_BB_WARN: - log_warning("Ignoring blackbox module %s.\n", log_id(it.first)); + log_warning("Ignoring blackbox module %s.\n", it.first.unescape()); break; case RTLIL::SB_UNBOXED_ERR: - log_error("Unsupported boxed module %s.\n", log_id(it.first)); + log_error("Unsupported boxed module %s.\n", it.first.unescape()); break; case RTLIL::SB_EXCL_BB_ERR: - log_error("Unsupported blackbox module %s.\n", log_id(it.first)); + log_error("Unsupported blackbox module %s.\n", it.first.unescape()); break; case RTLIL::SB_UNBOXED_CMDERR: - log_cmd_error("Unsupported boxed module %s.\n", log_id(it.first)); + log_cmd_error("Unsupported boxed module %s.\n", it.first.unescape()); break; case RTLIL::SB_EXCL_BB_CMDERR: - log_cmd_error("Unsupported blackbox module %s.\n", log_id(it.first)); + log_cmd_error("Unsupported blackbox module %s.\n", it.first.unescape()); break; default: break; @@ -1496,13 +1496,13 @@ std::vector RTLIL::Design::selected_modules(RTLIL::SelectPartial switch(partials) { case RTLIL::SELECT_WHOLE_WARN: - log_warning("Ignoring partially selected module %s.\n", log_id(it.first)); + log_warning("Ignoring partially selected module %s.\n", it.first.unescape()); break; case RTLIL::SELECT_WHOLE_ERR: - log_error("Unsupported partially selected module %s.\n", log_id(it.first)); + log_error("Unsupported partially selected module %s.\n", it.first.unescape()); break; case RTLIL::SELECT_WHOLE_CMDERR: - log_cmd_error("Unsupported partially selected module %s.\n", log_id(it.first)); + log_cmd_error("Unsupported partially selected module %s.\n", it.first.unescape()); break; default: break; @@ -2796,14 +2796,14 @@ bool RTLIL::Module::has_processes() const bool RTLIL::Module::has_memories_warn() const { if (!memories.empty()) - log_warning("Ignoring module %s because it contains memories (run 'memory' command first).\n", log_id(this)); + log_warning("Ignoring module %s because it contains memories (run 'memory' command first).\n", this); return !memories.empty(); } bool RTLIL::Module::has_processes_warn() const { if (!processes.empty()) - log_warning("Ignoring module %s because it contains processes (run 'proc' command first).\n", log_id(this)); + log_warning("Ignoring module %s because it contains processes (run 'proc' command first).\n", this); return !processes.empty(); } @@ -3095,7 +3095,7 @@ void RTLIL::Module::connect(const RTLIL::SigSig &conn) } if (yosys_xtrace) { - log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", log_id(this), log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); + log("#X# Connect (SigSig) in %s: %s = %s (%d bits)\n", this, log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); log_backtrace("-X- ", yosys_xtrace-1); } @@ -3118,7 +3118,7 @@ void RTLIL::Module::new_connections(const std::vector &new_conn) mon->notify_connect(this, new_conn); if (yosys_xtrace) { - log("#X# New connections vector in %s:\n", log_id(this)); + log("#X# New connections vector in %s:\n", this); for (auto &conn: new_conn) log("#X# %s = %s (%d bits)\n", log_signal(conn.first), log_signal(conn.second), GetSize(conn.first)); log_backtrace("-X- ", yosys_xtrace-1); diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc index 5f74b3380..19474b565 100644 --- a/kernel/rtlil_bufnorm.cc +++ b/kernel/rtlil_bufnorm.cc @@ -146,7 +146,7 @@ void RTLIL::Module::bufNormalize() // already enqueued or becomes reachable when denormalizing $buf or // $connect cells. auto enqueue_cell_port = [&](Cell *cell, IdString port) { - xlog("processing cell port %s.%s\n", log_id(cell), log_id(port)); + xlog("processing cell port %s.%s\n", cell, port.unescape()); // An empty cell type means the cell got removed if (cell->type.empty()) @@ -270,7 +270,7 @@ void RTLIL::Module::bufNormalize() // normalized mode). while (wire_queue_pos < GetSize(wire_queue_entries)) { auto wire = wire_queue_entries[wire_queue_pos++]; - xlog("processing wire %s\n", log_id(wire)); + xlog("processing wire %s\n", wire); if (wire->driverCell_) { Cell *cell = wire->driverCell_; @@ -287,7 +287,7 @@ void RTLIL::Module::bufNormalize() log_assert(connect_cell->type == ID($connect)); SigSpec const &sig_a = connect_cell->getPort(ID::A); SigSpec const &sig_b = connect_cell->getPort(ID::B); - xlog("found $connect cell %s: %s <-> %s\n", log_id(connect_cell), log_signal(sig_a), log_signal(sig_b)); + xlog("found $connect cell %s: %s <-> %s\n", connect_cell, log_signal(sig_a), log_signal(sig_b)); for (auto &side : {sig_a, sig_b}) for (auto chunk : side.chunks()) if (chunk.wire) @@ -452,7 +452,7 @@ void RTLIL::Module::bufNormalize() } if (wire->driverCell_ == nullptr) { - xlog("wire %s drivers %s\n", log_id(wire), log_signal(wire_drivers)); + xlog("wire %s drivers %s\n", wire, log_signal(wire_drivers)); addBuf(NEW_ID, wire_drivers, wire); } } @@ -541,7 +541,7 @@ void RTLIL::Cell::unsetPort(RTLIL::IdString portname) mon->notify_connect(this, conn_it->first, conn_it->second, signal); if (yosys_xtrace) { - log("#X# Unconnect %s.%s.%s\n", log_id(this->module), log_id(this), log_id(portname)); + log("#X# Unconnect %s.%s.%s\n", this->module, this, portname.unescape()); log_backtrace("-X- ", yosys_xtrace-1); } @@ -601,7 +601,7 @@ void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal) mon->notify_connect(this, conn_it->first, conn_it->second, signal); if (yosys_xtrace) { - log("#X# Connect %s.%s.%s = %s (%d)\n", log_id(this->module), log_id(this), log_id(portname), log_signal(signal), GetSize(signal)); + log("#X# Connect %s.%s.%s = %s (%d)\n", this->module, this, portname.unescape(), log_signal(signal), GetSize(signal)); log_backtrace("-X- ", yosys_xtrace-1); } diff --git a/kernel/satgen.cc b/kernel/satgen.cc index 7fbcba1b2..9fddc303e 100644 --- a/kernel/satgen.cc +++ b/kernel/satgen.cc @@ -1395,9 +1395,9 @@ void report_missing_model(bool warn_only, RTLIL::Cell* cell) { std::string s; if (cell->is_builtin_ff()) - s = stringf("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type)); + s = stringf("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", cell, cell->type.unescape()); else - s = stringf("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type)); + s = stringf("No SAT model available for cell %s (%s).\n", cell, cell->type.unescape()); if (warn_only) { log_formatted_warning_noprefix(s); diff --git a/kernel/scopeinfo.h b/kernel/scopeinfo.h index a3939b903..e06beb1dc 100644 --- a/kernel/scopeinfo.h +++ b/kernel/scopeinfo.h @@ -328,7 +328,7 @@ struct ModuleItem { [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(ptr); return h; } }; -static inline void log_dump_val_worker(typename IdTree::Cursor cursor ) { log("%p %s", cursor.target, log_id(cursor.scope_name)); } +static inline void log_dump_val_worker(typename IdTree::Cursor cursor ) { log("%p %s", cursor.target, cursor.scope_name.unescape()); } template static inline void log_dump_val_worker(const typename std::unique_ptr &cursor ) { log("unique %p", cursor.get()); } diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h index ff60415bd..e2e094b62 100644 --- a/kernel/timinginfo.h +++ b/kernel/timinginfo.h @@ -105,21 +105,21 @@ struct TimingInfo auto dst = cell->getPort(ID::DST); for (const auto &c : src.chunks()) if (!c.wire || !c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", module, cell, log_signal(src)); for (const auto &c : dst.chunks()) if (!c.wire || !c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", module, cell, log_signal(dst)); int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); if (max < 0) - log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); + log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", module, cell); if (cell->getParam(ID::FULL).as_bool()) { for (const auto &s : src) for (const auto &d : dst) { auto r = t.comb.insert(BitBit(s,d)); if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", module, log_signal(s), log_signal(d)); r.first->second = max; } } @@ -130,7 +130,7 @@ struct TimingInfo const auto &d = dst[i]; auto r = t.comb.insert(BitBit(s,d)); if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(s), log_signal(d)); + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", module, log_signal(s), log_signal(d)); r.first->second = max; } } @@ -139,15 +139,15 @@ struct TimingInfo auto src = cell->getPort(ID::SRC).as_bit(); auto dst = cell->getPort(ID::DST); if (!src.wire || !src.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", module, cell, log_signal(src)); for (const auto &c : dst.chunks()) if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", module, cell, log_signal(dst)); int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); int max = std::max(rise_max,fall_max); if (max < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", module, cell); max = 0; } for (const auto &d : dst) { @@ -167,12 +167,12 @@ struct TimingInfo auto dst = cell->getPort(ID::DST).as_bit(); for (const auto &c : src.chunks()) if (!c.wire || !c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", module, cell, log_signal(src)); if (!dst.wire || !dst.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", module, cell, log_signal(dst)); int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); if (max < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", module, cell); max = 0; } for (const auto &s : src) { diff --git a/kernel/yosys.cc b/kernel/yosys.cc index b3688b77b..5643ed7b0 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -954,7 +954,7 @@ static char *readline_obj_generator(const char *text, int state) { for (auto mod : design->modules()) if (RTLIL::unescape_id(mod->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(mod->name))); + obj_names.push_back(strdup(mod->name.unescape().c_str())); } else if (design->module(design->selected_active_module) != nullptr) { @@ -962,19 +962,19 @@ static char *readline_obj_generator(const char *text, int state) for (auto w : module->wires()) if (RTLIL::unescape_id(w->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(w->name))); + obj_names.push_back(strdup(w->name.unescape().c_str())); for (auto &it : module->memories) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(it.first))); + obj_names.push_back(strdup(it.first.unescape().c_str())); for (auto cell : module->cells()) if (RTLIL::unescape_id(cell->name).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(cell->name))); + obj_names.push_back(strdup(cell->name.unescape().c_str())); for (auto &it : module->processes) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(log_id(it.first))); + obj_names.push_back(strdup(it.first.unescape().c_str())); } std::sort(obj_names.begin(), obj_names.end()); @@ -1179,7 +1179,7 @@ struct ScriptCmdPass : public Pass { if (!mod->selected(w)) continue; if (!c.second.is_fully_const()) - log_error("RHS of selected wire %s.%s is not constant.\n", log_id(mod), log_id(w)); + log_error("RHS of selected wire %s.%s is not constant.\n", mod, w); auto v = c.second.as_const(); Pass::call_on_module(design, mod, v.decode_string()); } diff --git a/passes/cmds/abstract.cc b/passes/cmds/abstract.cc index 2ea71268b..2519daf5c 100644 --- a/passes/cmds/abstract.cc +++ b/passes/cmds/abstract.cc @@ -67,7 +67,7 @@ struct Slice { int wire_offset(RTLIL::Wire *wire, int index) const { int rtl_offset = indices == RtlilSlice ? index : wire->from_hdl_index(index); if (rtl_offset < 0 || rtl_offset >= wire->width) { - log_error("Slice %s is out of bounds for wire %s in module %s", to_string(), log_id(wire), log_id(wire->module)); + log_error("Slice %s is out of bounds for wire %s in module %s", to_string(), wire, wire->module); } return rtl_offset; } @@ -187,7 +187,7 @@ unsigned int abstract_state(Module* mod, EnableLogic enable, const std::vector& wire_score) for (auto bit : conn.second) if (bit.wire != nullptr && bit.wire->name[0] != '$') { if (suffix.empty()) - suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first)); + suffix = stringf("_%s_%s", cell->type.unescape(), conn.first.unescape()); name_proposal proposed_name( bit.wire->name.str() + suffix, cell->output(conn.first) ? 0 : wire_score.at(bit.wire) @@ -66,7 +66,7 @@ int autoname_worker(Module *module, const dict& wire_score) for (auto bit : conn.second) if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) { if (suffix.empty()) - suffix = stringf("_%s", log_id(conn.first)); + suffix = stringf("_%s", conn.first.unescape()); name_proposal proposed_name( cell->name.str() + suffix, cell->output(conn.first) ? 0 : wire_score.at(bit.wire) @@ -90,7 +90,7 @@ int autoname_worker(Module *module, const dict& wire_score) if (best_name < it.second) continue; 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)); + log_debug("Rename cell %s in %s to %s.\n", it.first, module, n.unescape()); module->rename(it.first, n); count++; } @@ -99,7 +99,7 @@ int autoname_worker(Module *module, const dict& wire_score) if (best_name < it.second) continue; 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)); + log_debug("Rename wire %s in %s to %s.\n", it.first, module, n.unescape()); module->rename(it.first, n); count++; } @@ -151,7 +151,7 @@ struct AutonamePass : public Pass { count += n; } if (count > 0) - log("Renamed %d objects in module %s (%d iterations).\n", count, log_id(module), iter); + log("Renamed %d objects in module %s (%d iterations).\n", count, module, iter); } } } AutonamePass; diff --git a/passes/cmds/box_derive.cc b/passes/cmds/box_derive.cc index 2590baa93..2d5ee2440 100644 --- a/passes/cmds/box_derive.cc +++ b/passes/cmds/box_derive.cc @@ -79,7 +79,7 @@ struct BoxDerivePass : Pass { if (!base_name.empty()) { base_override = d->module(base_name); if (!base_override) - log_cmd_error("Base module %s not found.\n", log_id(base_name)); + log_cmd_error("Base module %s not found.\n", base_name.unescape()); } dict>, Module*> done; @@ -109,7 +109,7 @@ struct BoxDerivePass : Pass { IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr)); if (!new_name.isPublic()) log_error("Derived module %s cannot be renamed to private name %s.\n", - log_id(derived), log_id(new_name)); + derived, new_name.unescape()); derived->attributes.erase(naming_attr); d->rename(derived, new_name); } diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index 0ced09dd9..6a630ca4b 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -212,7 +212,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove module %s.\n", log_id(module)); + log_header(design, "Trying to remove module %s.\n", module); removed_module = module; break; } @@ -242,7 +242,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove module port %s.\n", log_id(wire)); + log_header(design, "Trying to remove module port %s.\n", wire); wire->port_input = wire->port_output = false; mod->fixup_ports(); return design_copy; @@ -265,7 +265,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove cell %s.%s.\n", log_id(mod), log_id(cell)); + log_header(design, "Trying to remove cell %s.%s.\n", mod, cell); removed_cell = cell; break; } @@ -296,7 +296,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove cell port %s.%s.%s.\n", log_id(mod), log_id(cell), log_id(it.first)); + log_header(design, "Trying to remove cell port %s.%s.%s.\n", mod, cell, it.first.unescape()); RTLIL::SigSpec port_x(State::Sx, port.size()); cell->unsetPort(it.first); cell->setPort(it.first, port_x); @@ -305,7 +305,7 @@ struct BugpointPass : public Pass { if (!stage2 && (cell->input(it.first) || cell->output(it.first)) && index++ == seed) { - log_header(design, "Trying to expose cell port %s.%s.%s as module port.\n", log_id(mod), log_id(cell), log_id(it.first)); + log_header(design, "Trying to expose cell port %s.%s.%s as module port.\n", mod, cell, it.first.unescape()); RTLIL::Wire *wire = mod->addWire(NEW_ID, port.size()); wire->set_bool_attribute(ID($bugpoint)); wire->port_input = cell->input(it.first); @@ -334,7 +334,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove process %s.%s.\n", log_id(mod), log_id(process.first)); + log_header(design, "Trying to remove process %s.%s.\n", mod, process.first.unescape()); removed_process = process.second; break; } @@ -363,7 +363,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first)); + log_header(design, "Trying to remove assign %s %s in %s.%s.\n", log_signal(it->first), log_signal(it->second), mod, pr.first.unescape()); cs->actions.erase(it); return design_copy; } @@ -389,7 +389,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), log_id(mod), log_id(pr.first)); + log_header(design, "Trying to remove sync %s update %s %s in %s.%s.\n", log_signal(sy->signal), log_signal(it->first), log_signal(it->second), mod, pr.first.unescape()); sy->actions.erase(it); return design_copy; } @@ -399,7 +399,7 @@ struct BugpointPass : public Pass { { if (index++ == seed) { - log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), log_id(it->memid), log_signal(it->address), log_signal(it->data), log_signal(it->enable), log_id(mod), log_id(pr.first)); + log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), it->memid.unescape(), log_signal(it->address), log_signal(it->data), log_signal(it->enable), mod, pr.first.unescape()); sy->mem_write_actions.erase(it); // Remove the bit for removed action from other actions' priority masks. for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) { @@ -437,7 +437,7 @@ struct BugpointPass : public Pass { if (index++ == seed) { - log_header(design, "Trying to remove wire %s.%s.\n", log_id(mod), log_id(wire)); + log_header(design, "Trying to remove wire %s.%s.\n", mod, wire); removed_wire = wire; break; } diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index 1019c2955..6e0d65297 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -117,7 +117,7 @@ struct CheckPass : public Pass { for (auto module : design->selected_whole_modules_warn()) { - log("Checking module %s...\n", log_id(module)); + log("Checking module %s...\n", module); SigMap sigmap(module); dict> wire_drivers; @@ -133,7 +133,7 @@ struct CheckPass : public Pass { for (auto bit : sigmap(action.first)) wire_drivers[bit].push_back( stringf("action %s <= %s (case rule) in process %s", - log_signal(action.first), log_signal(action.second), log_id(proc_it.first))); + log_signal(action.first), log_signal(action.second), proc_it.first.unescape())); for (auto bit : sigmap(action.second)) if (bit.wire) used_wires.insert(bit); @@ -154,7 +154,7 @@ struct CheckPass : public Pass { for (auto bit : sigmap(action.first)) wire_drivers[bit].push_back( stringf("action %s <= %s (sync rule) in process %s", - log_signal(action.first), log_signal(action.second), log_id(proc_it.first))); + log_signal(action.first), log_signal(action.second), proc_it.first.unescape())); for (auto bit : sigmap(action.second)) if (bit.wire) used_wires.insert(bit); } @@ -259,7 +259,7 @@ struct CheckPass : public Pass { { if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) { if (allow_tbuf && cell->type == ID($_TBUF_)) goto cell_allowed; - log_warning("Cell %s.%s is an unmapped internal cell of type %s.\n", log_id(module), log_id(cell), log_id(cell->type)); + log_warning("Cell %s.%s is an unmapped internal cell of type %s.\n", module, cell, cell->type.unescape()); counter++; cell_allowed:; } @@ -275,10 +275,10 @@ struct CheckPass : public Pass { if (input && bit.wire) used_wires.insert(bit); if (output && !input && bit.wire) - wire_drivers_count[bit]++; + wire_drivers_count[bit]++; if (output && (bit.wire || !input)) - wire_drivers[bit].push_back(stringf("port %s[%d] of cell %s (%s)", log_id(conn.first), i, - log_id(cell), log_id(cell->type))); + wire_drivers[bit].push_back(stringf("port %s[%d] of cell %s (%s)", conn.first.unescape(), i, + cell, cell->type.unescape())); if (output) driver_cells[bit] = cell; } @@ -298,7 +298,7 @@ struct CheckPass : public Pass { SigSpec sig = sigmap(wire); for (int i = 0; i < GetSize(sig); i++) if (sig[i].wire || !wire->port_output) - wire_drivers[sig[i]].push_back(stringf("module input %s[%d]", log_id(wire), i)); + wire_drivers[sig[i]].push_back(stringf("module input %s[%d]", wire, i)); } if (wire->port_output) for (auto bit : sigmap(wire)) @@ -312,7 +312,7 @@ struct CheckPass : public Pass { 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)); + log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", module, wire); counter++; } } @@ -329,7 +329,7 @@ struct CheckPass : public Pass { for (auto it : wire_drivers) if (wire_drivers_count[it.first] > 1) { - string message = stringf("multiple conflicting drivers for %s.%s:\n", log_id(module), log_signal(it.first)); + string message = stringf("multiple conflicting drivers for %s.%s:\n", module, log_signal(it.first)); for (auto str : it.second) message += stringf(" %s\n", str); log_warning("%s", message); @@ -338,13 +338,13 @@ struct CheckPass : public Pass { for (auto bit : used_wires) if (!wire_drivers.count(bit)) { - log_warning("Wire %s.%s is used but has no driver.\n", log_id(module), log_signal(bit)); + log_warning("Wire %s.%s is used but has no driver.\n", module, log_signal(bit)); counter++; } topo.sort(); for (auto &loop : topo.loops) { - string message = stringf("found logic loop in module %s:\n", log_id(module)); + string message = stringf("found logic loop in module %s:\n", module); // `loop` only contains wire bits, or an occasional special helper node for cells for // which we have done the edges fallback. The cell and its ports that led to an edge are @@ -378,8 +378,8 @@ struct CheckPass : public Pass { SigBit edge_to = sigmap(cell->getPort(to_port))[to_bit]; if (edge_from == from && edge_to == to && nhits++ < HITS_LIMIT) - message += stringf(" %s[%d] --> %s[%d]\n", log_id(from_port), from_bit, - log_id(to_port), to_bit); + message += stringf(" %s[%d] --> %s[%d]\n", from_port.unescape(), from_bit, + to_port.unescape(), to_bit); if (nhits == HITS_LIMIT) message += " ...\n"; } @@ -397,7 +397,7 @@ struct CheckPass : public Pass { driver_src = stringf(" source: %s", src_attr); } - message += stringf(" cell %s (%s)%s\n", log_id(driver), log_id(driver->type), driver_src); + message += stringf(" cell %s (%s)%s\n", driver, driver->type.unescape(), driver_src); if (!coarsened_cells.count(driver)) { MatchingEdgePrinter printer(message, sigmap, prev, bit); @@ -437,7 +437,7 @@ struct CheckPass : public Pass { 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)); + log_warning("Wire %s.%s has 'init' attribute and is not driven by an FF cell.\n", module, log_signal(chunk)); counter++; } } diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc index ccda023c0..fca943d86 100644 --- a/passes/cmds/chformal.cc +++ b/passes/cmds/chformal.cc @@ -330,7 +330,7 @@ struct ChformalPass : public Pass { for (auto cell : constr_cells) { if (is_triggered_check_cell(cell)) - log_error("Cannot delay edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", log_id(cell)); + log_error("Cannot delay edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", cell); for (int i = 0; i < mode_arg; i++) { @@ -411,7 +411,7 @@ struct ChformalPass : public Pass { continue; if (is_triggered_check_cell(cell)) - log_error("Cannot lower edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", log_id(cell)); + log_error("Cannot lower edge triggered $check cell %s, run async2sync or clk2fflogic first.\n", cell); Cell *plain_cell = module->addCell(NEW_ID, formal_flavor(cell)); diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index c6d3320ea..b8a61d532 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -122,7 +122,7 @@ struct ConnectPass : public Pass { RTLIL::Module *module = nullptr; for (auto mod : design->selected_modules()) { if (module != nullptr) - log_cmd_error("Multiple modules selected: %s, %s\n", log_id(module->name), log_id(mod->name)); + log_cmd_error("Multiple modules selected: %s, %s\n", module->name.unescape(), mod->name.unescape()); module = mod; } if (module == nullptr) diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index 5677c666d..dcc6f0004 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -134,8 +134,8 @@ struct ConnwrappersWorker } if (old_sig.size()) - log("Connected extended bits of %s.%s:%s: %s -> %s\n", log_id(module->name), log_id(cell->name), - log_id(conn.first), log_signal(old_sig), log_signal(conn.second)); + log("Connected extended bits of %s.%s:%s: %s -> %s\n", module->name.unescape(), cell->name.unescape(), + conn.first.unescape(), log_signal(old_sig), log_signal(conn.second)); } } } diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index ddbd98bfd..68b778790 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -266,7 +266,7 @@ struct DesignPass : public Pass { for (auto mod : copy_src_modules) { - log("Importing %s as %s.\n", log_id(mod), log_id(prefix)); + log("Importing %s as %s.\n", mod, prefix); RTLIL::Module *t = mod->clone(); t->name = prefix; @@ -295,7 +295,7 @@ struct DesignPass : public Pass { { 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)); + log("Importing %s as %s.\n", fmod, trg_name); if (copy_to_design->module(trg_name) != nullptr) copy_to_design->remove(copy_to_design->module(trg_name)); diff --git a/passes/cmds/design_equal.cc b/passes/cmds/design_equal.cc index d5f0d617a..1912a823e 100644 --- a/passes/cmds/design_equal.cc +++ b/passes/cmds/design_equal.cc @@ -38,9 +38,9 @@ public: [[noreturn]] void formatted_error(std::string err) { - log("Module A: %s\n", log_id(mod_a->name)); + log("Module A: %s\n", mod_a->name.unescape()); log_module(mod_a, " "); - log("Module B: %s\n", log_id(mod_b->name)); + log("Module B: %s\n", mod_b->name.unescape()); log_module(mod_b, " "); log_cmd_error("Designs are different: %s\n", err); } @@ -68,20 +68,20 @@ public: { for (const auto &it : a->attributes) { if (b->attributes.count(it.first) == 0) - return "missing attribute " + std::string(log_id(it.first)) + " in second design"; + return "missing attribute " + std::string(it.first.unescape()) + " in second design"; if (it.second != b->attributes.at(it.first)) - return "attribute " + std::string(log_id(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(it.first)); + return "attribute " + std::string(it.first.unescape()) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(it.first)); } for (const auto &it : b->attributes) if (a->attributes.count(it.first) == 0) - return "missing attribute " + std::string(log_id(it.first)) + " in first design"; + return "missing attribute " + std::string(it.first.unescape()) + " in first design"; return ""; } std::string compare_wires(const RTLIL::Wire *a, const RTLIL::Wire *b) { if (a->name != b->name) - return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->width != b->width) return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width); if (a->start_offset != b->start_offset) @@ -105,19 +105,19 @@ public: { for (const auto &it : mod_a->wires_) { if (mod_b->wires_.count(it.first) == 0) - error("Module %s missing wire %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing wire %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_wires(it.second, mod_b->wires_.at(it.first)); !mismatch.empty()) - error("Module %s wire %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch); + error("Module %s wire %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); } for (const auto &it : mod_b->wires_) if (mod_a->wires_.count(it.first) == 0) - error("Module %s missing wire %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing wire %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } std::string compare_memories(const RTLIL::Memory *a, const RTLIL::Memory *b) { if (a->name != b->name) - return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->width != b->width) return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width); if (a->start_offset != b->start_offset) @@ -132,31 +132,31 @@ public: std::string compare_cells(const RTLIL::Cell *a, const RTLIL::Cell *b) { if (a->name != b->name) - return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->type != b->type) - return "type mismatch: " + std::string(log_id(a->type)) + " != " + log_id(b->type); + return "type mismatch: " + std::string(a->type.unescape()) + " != " + b->type.unescape(); if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch; for (const auto &it : a->parameters) { if (b->parameters.count(it.first) == 0) - return "parameter mismatch: missing parameter " + std::string(log_id(it.first)) + " in second design"; + return "parameter mismatch: missing parameter " + std::string(it.first.unescape()) + " in second design"; if (it.second != b->parameters.at(it.first)) - return "parameter mismatch: " + std::string(log_id(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(it.first)); + return "parameter mismatch: " + std::string(it.first.unescape()) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(it.first)); } for (const auto &it : b->parameters) if (a->parameters.count(it.first) == 0) - return "parameter mismatch: missing parameter " + std::string(log_id(it.first)) + " in first design"; + return "parameter mismatch: missing parameter " + std::string(it.first.unescape()) + " in first design"; for (const auto &it : a->connections()) { if (b->connections().count(it.first) == 0) - return "connection mismatch: missing connection " + std::string(log_id(it.first)) + " in second design"; + return "connection mismatch: missing connection " + std::string(it.first.unescape()) + " in second design"; if (!compare_sigspec(it.second, b->connections().at(it.first))) - return "connection " + std::string(log_id(it.first)) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(it.first)); + return "connection " + std::string(it.first.unescape()) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(it.first)); } for (const auto &it : b->connections()) if (a->connections().count(it.first) == 0) - return "connection mismatch: missing connection " + std::string(log_id(it.first)) + " in first design"; + return "connection mismatch: missing connection " + std::string(it.first.unescape()) + " in first design"; return ""; } @@ -165,26 +165,26 @@ public: { for (const auto &it : mod_a->cells_) { if (mod_b->cells_.count(it.first) == 0) - error("Module %s missing cell %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing cell %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_cells(it.second, mod_b->cells_.at(it.first)); !mismatch.empty()) - error("Module %s cell %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch); + error("Module %s cell %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); } for (const auto &it : mod_b->cells_) if (mod_a->cells_.count(it.first) == 0) - error("Module %s missing cell %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing cell %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } void check_memories() { for (const auto &it : mod_a->memories) { if (mod_b->memories.count(it.first) == 0) - error("Module %s missing memory %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing memory %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_memories(it.second, mod_b->memories.at(it.first)); !mismatch.empty()) - error("Module %s memory %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch); + error("Module %s memory %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); } for (const auto &it : mod_b->memories) if (mod_a->memories.count(it.first) == 0) - error("Module %s missing memory %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing memory %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } std::string compare_case_rules(const RTLIL::CaseRule *a, const RTLIL::CaseRule *b) @@ -251,7 +251,7 @@ public: const auto &ma = a->mem_write_actions[i]; const auto &mb = b->mem_write_actions[i]; if (ma.memid != mb.memid) - return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + log_id(ma.memid) + " != " + log_id(mb.memid); + return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + ma.memid.unescape() + " != " + mb.memid.unescape(); if (!compare_sigspec(ma.address, mb.address)) return "mem_write_actions " + std::to_string(i) + " address mismatch: " + log_signal(ma.address) + " != " + log_signal(mb.address); if (!compare_sigspec(ma.data, mb.data)) @@ -268,7 +268,7 @@ public: std::string compare_processes(const RTLIL::Process *a, const RTLIL::Process *b) { - if (a->name != b->name) return "name mismatch: " + std::string(log_id(a->name)) + " != " + log_id(b->name); + if (a->name != b->name) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch; if (std::string mismatch = compare_case_rules(&a->root_case, &b->root_case); !mismatch.empty()) @@ -285,13 +285,13 @@ public: { for (auto &it : mod_a->processes) { if (mod_b->processes.count(it.first) == 0) - error("Module %s missing process %s in second design.\n", log_id(mod_a->name), log_id(it.first)); + error("Module %s missing process %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); if (std::string mismatch = compare_processes(it.second, mod_b->processes.at(it.first)); !mismatch.empty()) - error("Module %s process %s %s.\n", log_id(mod_a->name), log_id(it.first), mismatch.c_str()); + error("Module %s process %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch.c_str()); } for (auto &it : mod_b->processes) if (mod_a->processes.count(it.first) == 0) - error("Module %s missing process %s in first design.\n", log_id(mod_b->name), log_id(it.first)); + error("Module %s missing process %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } void check_connections() @@ -299,13 +299,13 @@ public: const auto &conns_a = mod_a->connections(); const auto &conns_b = mod_b->connections(); if (conns_a.size() != conns_b.size()) { - error("Module %s connection count differs: %zu != %zu\n", log_id(mod_a->name), conns_a.size(), conns_b.size()); + error("Module %s connection count differs: %zu != %zu\n", mod_a->name.unescape(), conns_a.size(), conns_b.size()); } else { for (size_t i = 0; i < conns_a.size(); i++) { if (!compare_sigspec(conns_a[i].first, conns_b[i].first)) - error("Module %s connection %zu LHS %s != %s.\n", log_id(mod_a->name), i, log_signal(conns_a[i].first), log_signal(conns_b[i].first)); + error("Module %s connection %zu LHS %s != %s.\n", mod_a->name.unescape(), i, log_signal(conns_a[i].first), log_signal(conns_b[i].first)); if (!compare_sigspec(conns_a[i].second, conns_b[i].second)) - error("Module %s connection %zu RHS %s != %s.\n", log_id(mod_a->name), i, log_signal(conns_a[i].second), log_signal(conns_b[i].second)); + error("Module %s connection %zu RHS %s != %s.\n", mod_a->name.unescape(), i, log_signal(conns_a[i].second), log_signal(conns_b[i].second)); } } } @@ -313,9 +313,9 @@ public: void check() { if (mod_a->name != mod_b->name) - error("Modules have different names: %s != %s\n", log_id(mod_a->name), log_id(mod_b->name)); + error("Modules have different names: %s != %s\n", mod_a->name.unescape(), mod_b->name.unescape()); if (std::string mismatch = compare_attributes(mod_a, mod_b); !mismatch.empty()) - error("Module %s %s.\n", log_id(mod_a->name), mismatch); + error("Module %s %s.\n", mod_a->name.unescape(), mismatch); check_wires(); check_cells(); check_memories(); @@ -349,7 +349,7 @@ struct DesignEqualPass : public Pass { for (auto &it : design->modules_) { RTLIL::Module *mod = it.second; if (!other->has(mod->name)) - log_error("Second design missing module %s.\n", log_id(mod->name)); + log_error("Second design missing module %s.\n", mod->name.unescape()); ModuleComparator cmp(mod, other->module(mod->name)); cmp.check(); @@ -357,7 +357,7 @@ struct DesignEqualPass : public Pass { for (auto &it : other->modules_) { RTLIL::Module *mod = it.second; if (!design->has(mod->name)) - log_error("First design missing module %s.\n", log_id(mod->name)); + log_error("First design missing module %s.\n", mod->name.unescape()); } log("Designs are identical.\n"); diff --git a/passes/cmds/dft_tag.cc b/passes/cmds/dft_tag.cc index 0a306d113..216f66b2c 100644 --- a/passes/cmds/dft_tag.cc +++ b/passes/cmds/dft_tag.cc @@ -98,7 +98,7 @@ struct DftTagWorker { } for (auto cell : overwrite_cells) { - log_debug("Applying $overwrite_tag %s for signal %s\n", log_id(cell->name), log_signal(cell->getPort(ID::A))); + log_debug("Applying $overwrite_tag %s for signal %s\n", cell->name.unescape(), log_signal(cell->getPort(ID::A))); SigSpec orig_signal = cell->getPort(ID::A); SigSpec interposed_signal = divert_users(orig_signal); auto *set_tag_cell = module->addSetTag(NEW_ID, cell->getParam(ID::TAG).decode_string(), orig_signal, cell->getPort(ID::SET), cell->getPort(ID::CLR), interposed_signal); @@ -470,9 +470,9 @@ struct DftTagWorker { if (!warned_cells.insert(cell).second) return; if (cell->type.isPublic()) - log_warning("Unhandled cell %s (%s) during tag propagation\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s) during tag propagation\n", cell, cell->type.unescape()); else - log_debug("Unhandled cell %s (%s) during tag propagation\n", log_id(cell), log_id(cell->type)); + log_debug("Unhandled cell %s (%s) during tag propagation\n", cell, cell->type.unescape()); } void process_cell(IdString tag, Cell *cell) @@ -691,7 +691,7 @@ struct DftTagWorker { // TODO handle some more variants if ((ff.has_clk || ff.has_gclk) && !ff.has_ce && !ff.has_aload && !ff.has_srst && !ff.has_arst && !ff.has_sr) { if (ff.has_clk && !tags(ff.sig_clk).empty()) - log_warning("Tags on CLK input ignored for %s (%s)\n", log_id(cell), log_id(cell->type)); + log_warning("Tags on CLK input ignored for %s (%s)\n", cell, cell->type.unescape()); int width = ff.width; @@ -709,7 +709,7 @@ struct DftTagWorker { emit_tag_signal(tag, sig_q, ff.sig_q); return; } else { - log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", cell, cell->type.unescape()); // For unhandled FFs, the default propagation would cause combinational loops emit_tag_signal(tag, ff.sig_q, Const(0, ff.width)); @@ -739,7 +739,7 @@ struct DftTagWorker { // which is an over-approximation (unless the cell is a module that // generates tags itself in which case it could be arbitrary). if (warned_cells.insert(cell).second) - log_warning("Unhandled cell %s (%s) while emitting tag signals\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s) while emitting tag signals\n", cell, cell->type.unescape()); } void emit_tags() diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc index 9324cf630..2f100d724 100644 --- a/passes/cmds/edgetypes.cc +++ b/passes/cmds/edgetypes.cc @@ -92,12 +92,12 @@ struct EdgetypePass : public Pass { auto sink_bit_index = std::get<2>(sink); string source_str = multibit_ports.count(std::pair(source_cell_type, source_port_name)) ? - stringf("%s.%s[%d]", log_id(source_cell_type), log_id(source_port_name), source_bit_index) : - stringf("%s.%s", log_id(source_cell_type), log_id(source_port_name)); + stringf("%s.%s[%d]", source_cell_type.unescape(), source_port_name.unescape(), source_bit_index) : + stringf("%s.%s", source_cell_type.unescape(), source_port_name.unescape()); string sink_str = multibit_ports.count(std::pair(sink_cell_type, sink_port_name)) ? - stringf("%s.%s[%d]", log_id(sink_cell_type), log_id(sink_port_name), sink_bit_index) : - stringf("%s.%s", log_id(sink_cell_type), log_id(sink_port_name)); + stringf("%s.%s[%d]", sink_cell_type.unescape(), sink_port_name.unescape(), sink_bit_index) : + stringf("%s.%s", sink_cell_type.unescape(), sink_port_name.unescape()); edge_cache.insert(source_str + " " + sink_str); } diff --git a/passes/cmds/example_dt.cc b/passes/cmds/example_dt.cc index b10f50502..b18277010 100644 --- a/passes/cmds/example_dt.cc +++ b/passes/cmds/example_dt.cc @@ -226,13 +226,13 @@ struct ExampleDtPass : public Pass { auto ref = compute_graph[i]; log("n%d ", i); - log("%s", log_id(ref.function().name)); + log("%s", ref.function().name.unescape()); for (auto const ¶m : ref.function().parameters) { if (param.second.empty()) - log("[%s]", log_id(param.first)); + log("[%s]", param.first.unescape()); else - log("[%s=%s]", log_id(param.first), log_const(param.second)); + log("[%s=%s]", param.first.unescape(), log_const(param.second)); } log("("); @@ -244,13 +244,13 @@ struct ExampleDtPass : public Pass } log(")\n"); if (ref.has_sparse_attr()) - log("// wire %s\n", log_id(ref.sparse_attr())); + log("// wire %s\n", ref.sparse_attr().unescape()); log("// was #%d %s\n", ref.attr(), log_signal(queue[ref.attr()])); } for (auto const &key : compute_graph.keys()) { - log("return %d as %s \n", key.second, log_id(key.first)); + log("return %d as %s \n", key.second, key.first.unescape()); } } log("Plugin test passed!\n"); diff --git a/passes/cmds/future.cc b/passes/cmds/future.cc index 81cc86bff..15f4b8bd1 100644 --- a/passes/cmds/future.cc +++ b/passes/cmds/future.cc @@ -86,13 +86,13 @@ struct FutureWorker { log_error("Found multiple drivers for future_ff target signal %s\n", log_signal(bit)); auto driver = *found_driver->second.begin(); if (!driver.cell->is_builtin_ff() && driver.cell->type != ID($anyinit)) - log_error("Driver for future_ff target signal %s has non-FF cell type %s\n", log_signal(bit), log_id(driver.cell->type)); + log_error("Driver for future_ff target signal %s has non-FF cell type %s\n", log_signal(bit), driver.cell->type.unescape()); FfData ff(&initvals, driver.cell); if (!ff.has_clk && !ff.has_gclk) log_error("Driver for future_ff target signal %s has cell type %s, which is not clocked\n", log_signal(bit), - log_id(driver.cell->type)); + driver.cell->type.unescape()); ff.unmap_ce_srst(); diff --git a/passes/cmds/linecoverage.cc b/passes/cmds/linecoverage.cc index 26adcce76..2f77f6f21 100644 --- a/passes/cmds/linecoverage.cc +++ b/passes/cmds/linecoverage.cc @@ -93,9 +93,9 @@ struct CoveragePass : public Pass { for (auto module : design->modules()) { - log_debug("Module %s:\n", log_id(module)); + log_debug("Module %s:\n", module); for (auto wire: module->wires()) { - log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), log_id(wire->name)); + log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), wire->name.unescape()); 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(), log_id(cell->name)); + log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), cell->name.unescape()); for (auto src: cell->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc index b3134b110..303abea6c 100644 --- a/passes/cmds/ltp.cc +++ b/passes/cmds/ltp.cc @@ -90,7 +90,7 @@ struct LtpWorker return; if (busy.count(bit) > 0) { - log_warning("Detected loop at %s in %s\n", log_signal(bit), log_id(module)); + log_warning("Detected loop at %s in %s\n", log_signal(bit), module); return; } @@ -117,7 +117,7 @@ struct LtpWorker 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))); + log("%5d: %s (via %s)\n", get<0>(bitinfo), log_signal(bit), get<2>(bitinfo)); } else { log("%5d: %s\n", get<0>(bitinfo), log_signal(bit)); } @@ -130,13 +130,13 @@ struct LtpWorker runner(it.first, 0, State::Sx, nullptr); log("\n"); - log("Longest topological path in %s (length=%d):\n", log_id(module), maxlvl); + log("Longest topological path in %s (length=%d):\n", 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)))); + log("%5s: %s (via %s)\n", "ff", log_signal(get<0>(bit2ff.at(maxbit))), get<1>(bit2ff.at(maxbit))); } }; diff --git a/passes/cmds/portarcs.cc b/passes/cmds/portarcs.cc index 4344d6cb2..581a8bebf 100644 --- a/passes/cmds/portarcs.cc +++ b/passes/cmds/portarcs.cc @@ -107,7 +107,7 @@ struct PortarcsPass : Pass { log_assert(w->port_input || w->port_output); if (w->port_input && w->port_output) { log_warning("Module '%s' with ambiguous direction on port %s ignored.\n", - log_id(m), log_id(w)); + m, w); ambiguous_ports = true; break; } @@ -128,7 +128,7 @@ struct PortarcsPass : Pass { if (!cell->type.in(ID($buf), ID($input_port), ID($connect), ID($tribuf))) { auto tdata = tinfo.find(cell->type); if (tdata == tinfo.end()) - log_cmd_error("Missing timing data for module '%s'.\n", log_id(cell->type)); + log_cmd_error("Missing timing data for module '%s'.\n", cell->type.unescape()); for (auto [edge, delay] : tdata->second.comb) { auto from = edge.first.get_connection(cell); auto to = edge.second.get_connection(cell); @@ -141,7 +141,7 @@ struct PortarcsPass : Pass { } if (!sort.sort()) - log_error("Failed to sort instances in module %s.\n", log_id(m)); + log_error("Failed to sort instances in module %s.\n", m); ordering = sort.sorted; } diff --git a/passes/cmds/portlist.cc b/passes/cmds/portlist.cc index b109ce22a..0804d3a68 100644 --- a/passes/cmds/portlist.cc +++ b/passes/cmds/portlist.cc @@ -71,9 +71,9 @@ struct PortlistPass : public Pass { ports.push_back(stringf("%s [%d:%d] %s", w->port_input ? w->port_output ? "inout" : "input" : "output", w->upto ? w->start_offset : w->start_offset + w->width - 1, w->upto ? w->start_offset + w->width - 1 : w->start_offset, - log_id(w))); + w)); } - log("module %s%s\n", log_id(module), m_mode ? " (" : ""); + log("module %s%s\n", module, m_mode ? " (" : ""); for (int i = 0; i < GetSize(ports); i++) log("%s%s\n", ports[i], m_mode && i+1 < GetSize(ports) ? "," : ""); if (m_mode) diff --git a/passes/cmds/printattrs.cc b/passes/cmds/printattrs.cc index 6a1fab072..6de2ffee3 100644 --- a/passes/cmds/printattrs.cc +++ b/passes/cmds/printattrs.cc @@ -47,9 +47,9 @@ struct PrintAttrsPass : public Pass { static void log_const(RTLIL::IdString s, const RTLIL::Const &x, const unsigned int indent) { if (x.flags & RTLIL::CONST_FLAG_STRING) - log("%s(* %s=\"%s\" *)\n", get_indent_str(indent), log_id(s), x.decode_string()); + log("%s(* %s=\"%s\" *)\n", get_indent_str(indent), s.unescape(), x.decode_string()); else if (x.flags == RTLIL::CONST_FLAG_NONE || x.flags == RTLIL::CONST_FLAG_SIGNED) - log("%s(* %s=%s *)\n", get_indent_str(indent), log_id(s), x.as_string()); + log("%s(* %s=%s *)\n", get_indent_str(indent), s.unescape(), x.as_string()); else log_assert(x.flags & RTLIL::CONST_FLAG_STRING || x.flags == RTLIL::CONST_FLAG_NONE); //intended to fail } @@ -63,14 +63,14 @@ struct PrintAttrsPass : public Pass { for (auto mod : design->selected_modules()) { if (design->selected_whole_module(mod)) { - log("%s%s\n", get_indent_str(indent), log_id(mod->name)); + log("%s%s\n", get_indent_str(indent), mod->name.unescape()); indent += 2; for (auto &it : mod->attributes) log_const(it.first, it.second, indent); } for (auto cell : mod->selected_cells()) { - log("%s%s\n", get_indent_str(indent), log_id(cell->name)); + log("%s%s\n", get_indent_str(indent), cell->name.unescape()); indent += 2; for (auto &it : cell->attributes) log_const(it.first, it.second, indent); @@ -78,7 +78,7 @@ struct PrintAttrsPass : public Pass { } for (auto wire : mod->selected_wires()) { - log("%s%s\n", get_indent_str(indent), log_id(wire->name)); + log("%s%s\n", get_indent_str(indent), wire->name.unescape()); indent += 2; for (auto &it : wire->attributes) log_const(it.first, it.second, indent); diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index a07d588c4..15b6bf539 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -37,7 +37,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: RTLIL::Cell *cell_to_rename = module->cell(from_name); if (wire_to_rename != nullptr) { - log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename), log_id(to_name), log_id(module)); + log("Renaming wire %s to %s in module %s.\n", wire_to_rename, to_name, module); module->rename(wire_to_rename, to_name); if (wire_to_rename->port_id || flag_output) { if (flag_output) @@ -50,7 +50,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: if (cell_to_rename != nullptr) { if (flag_output) log_cmd_error("Called with -output but the specified object is a cell.\n"); - log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename), log_id(to_name), log_id(module)); + log("Renaming cell %s to %s in module %s.\n", cell_to_rename, to_name, module); module->rename(cell_to_rename, to_name); return; } @@ -518,7 +518,7 @@ struct RenamePass : public Pass { if (module == nullptr) log_cmd_error("No top module found!\n"); - log("Renaming module %s to %s.\n", log_id(module), log_id(new_name)); + log("Renaming module %s to %s.\n", module, new_name.unescape()); design->rename(module, new_name); } else @@ -532,7 +532,7 @@ struct RenamePass : public Pass { for (auto module : design->selected_modules()) { if (module->memories.size() != 0 || module->processes.size() != 0) { - log_warning("Skipping module %s with unprocessed memories or processes\n", log_id(module)); + log_warning("Skipping module %s with unprocessed memories or processes\n", module); continue; } diff --git a/passes/cmds/sdc/sdc.cc b/passes/cmds/sdc/sdc.cc index 635aad016..cb0b074d5 100644 --- a/passes/cmds/sdc/sdc.cc +++ b/passes/cmds/sdc/sdc.cc @@ -168,7 +168,7 @@ struct SdcObjects { RTLIL::Wire *wire = top->wire(port); if (!wire) { // This should not be possible. See https://github.com/YosysHQ/yosys/pull/5594#issue-3791198573 - log_error("Port %s doesn't exist", log_id(port)); + log_error("Port %s doesn't exist", port.unescape()); } design_ports.push_back(std::make_pair(port.str().substr(1), wire)); } diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 2359efe03..bcb34d1d4 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -1817,7 +1817,7 @@ struct LsPass : public Pass { log("\n%d %s:\n", int(matches.size()), "modules"); std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str()); for (auto id : matches) - log(" %s%s\n", log_id(id), design->selected_whole_module(design->module(id)) ? "" : "*"); + log(" %s%s\n", id.unescape(), design->selected_whole_module(design->module(id)) ? "" : "*"); } } else diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 25d8fd34c..9491ef19b 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -246,9 +246,9 @@ struct ChparamPass : public Pass { if (!new_parameters.empty()) log_cmd_error("The options -set and -list cannot be used together.\n"); for (auto module : design->selected_modules()) { - log("%s:\n", log_id(module)); + log("%s:\n", module); for (auto param : module->avail_parameters) - log(" %s\n", log_id(param)); + log(" %s\n", param.unescape()); } return; } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index 14a251c41..f45a2aeee 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -645,16 +645,16 @@ struct ShowWorker module = mod; if (design->selected_whole_module(module->name)) { if (module->get_blackbox_attribute()) { - // log("Skipping blackbox module %s.\n", log_id(module->name)); + //log("Skipping blackbox module %s.\n", module->name.unescape()); continue; } else if (module->cells().size() == 0 && module->connections().empty() && module->processes.empty()) { - log("Skipping empty module %s.\n", log_id(module->name)); + log("Skipping empty module %s.\n", module->name.unescape()); continue; } else - log("Dumping module %s to page %d.\n", log_id(module->name), ++page_counter); + log("Dumping module %s to page %d.\n", module->name.unescape(), ++page_counter); } else - log("Dumping selected parts of module %s to page %d.\n", log_id(module->name), ++page_counter); + log("Dumping selected parts of module %s to page %d.\n", module->name.unescape(), ++page_counter); handle_module(); } } diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index 2993c3d3a..9439a3a2e 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -149,7 +149,7 @@ struct SpliceWorker void run() { - log("Splicing signals in module %s:\n", log_id(module->name)); + log("Splicing signals in module %s:\n", module->name.unescape()); driven_bits.push_back(RTLIL::State::Sm); driven_bits.push_back(RTLIL::State::Sm); diff --git a/passes/cmds/splitcells.cc b/passes/cmds/splitcells.cc index d2063a0c8..a99e4d268 100644 --- a/passes/cmds/splitcells.cc +++ b/passes/cmds/splitcells.cc @@ -89,7 +89,7 @@ struct SplitcellsWorker if (GetSize(slices) <= 1) return 0; slices.push_back(GetSize(outsig)); - log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1); + log("Splitting %s cell %s/%s into %d slices:\n", cell->type.unescape(), module, cell, GetSize(slices)-1); for (int i = 1; i < GetSize(slices); i++) { int slice_msb = slices[i]-1; @@ -126,7 +126,7 @@ struct SplitcellsWorker if (slice->hasParam(ID::WIDTH)) slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Y))); - log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Y))); + log(" slice %d: %s => %s\n", i, slice_name, log_signal(slice->getPort(ID::Y))); } module->remove(cell); @@ -155,7 +155,7 @@ struct SplitcellsWorker if (GetSize(slices) <= 1) return 0; slices.push_back(GetSize(outsig)); - log("Splitting %s cell %s/%s into %d slices:\n", log_id(cell->type), log_id(module), log_id(cell), GetSize(slices)-1); + log("Splitting %s cell %s/%s into %d slices:\n", cell->type.unescape(), module, cell, GetSize(slices)-1); for (int i = 1; i < GetSize(slices); i++) { int slice_msb = slices[i]-1; @@ -185,7 +185,7 @@ struct SplitcellsWorker slice->setParam(ID::WIDTH, GetSize(slice->getPort(ID::Q))); - log(" slice %d: %s => %s\n", i, log_id(slice_name), log_signal(slice->getPort(ID::Q))); + log(" slice %d: %s => %s\n", i, slice_name.unescape(), log_signal(slice->getPort(ID::Q))); } module->remove(cell); @@ -258,7 +258,7 @@ struct SplitcellsPass : public Pass { if (count_split_pre) log("Split %d cells in module %s into %d cell slices.\n", - count_split_pre, log_id(module), count_split_post); + count_split_pre, module, count_split_post); } } } SplitnetsPass; diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc index 5dfac1575..259794d32 100644 --- a/passes/cmds/sta.cc +++ b/passes/cmds/sta.cc @@ -66,12 +66,12 @@ struct StaWorker Module *inst_module = design->module(cell->type); if (!inst_module) { if (unrecognised_cells.insert(cell->type).second) - log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type)); + log_warning("Cell type '%s' not recognised! Ignoring.\n", cell->type.unescape()); continue; } if (!inst_module->get_blackbox_attribute()) { - log_warning("Cell type '%s' is not a black- nor white-box! Ignoring.\n", log_id(cell->type)); + log_warning("Cell type '%s' is not a black- nor white-box! Ignoring.\n", cell->type.unescape()); continue; } @@ -82,7 +82,7 @@ struct StaWorker if (!timing.count(derived_type)) { auto &t = timing.setup_module(inst_module); if (t.has_inputs && t.comb.empty() && t.arrival.empty() && t.required.empty()) - log_warning("Module '%s' has no timing arcs!\n", log_id(cell->type)); + log_warning("Module '%s' has no timing arcs!\n", cell->type.unescape()); } auto &t = timing.at(derived_type); @@ -203,10 +203,10 @@ struct StaWorker return; } - log("Latest arrival time in '%s' is %d:\n", log_id(module), maxarrival); + log("Latest arrival time in '%s' is %d:\n", module, maxarrival); auto it = endpoints.find(maxbit); if (it != endpoints.end() && it->second.sink) - log(" %6d %s (%s.%s)\n", maxarrival, log_id(it->second.sink), log_id(it->second.sink->type), log_id(it->second.port)); + log(" %6d %s (%s.%s)\n", maxarrival, it->second.sink, it->second.sink->type.unescape(), it->second.port.unescape()); else { log(" %6d (%s)\n", maxarrival, b.wire->port_output ? "" : ""); if (!b.wire->port_output) @@ -217,7 +217,7 @@ struct StaWorker int arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset]; if (jt->second.driver) { log(" %s\n", log_signal(b)); - log(" %6d %s (%s.%s->%s)\n", arrival, log_id(jt->second.driver), log_id(jt->second.driver->type), log_id(jt->second.src_port), log_id(jt->second.dst_port)); + log(" %6d %s (%s.%s->%s)\n", arrival, jt->second.driver, jt->second.driver->type.unescape(), jt->second.src_port.unescape(), jt->second.dst_port.unescape()); } else if (b.wire->port_input) log(" %6d %s (%s)\n", arrival, log_signal(b), ""); @@ -234,13 +234,13 @@ struct StaWorker continue; if (!b.wire->attributes.count(ID::sta_arrival)) { - log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b)); + log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", module, log_signal(b)); continue; } auto arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset]; if (arrival < 0) { - log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b)); + log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", module, log_signal(b)); continue; } arrival += i.second.required; diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 9494d6032..de767b96a 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -523,7 +523,7 @@ struct statdata_t { print_log_line("cells", local_num_cells, local_area, num_cells, area, 0, print_area, print_hierarchical, print_global_only); for (auto &it : num_cells_by_type) if (it.second) { - auto name = string(log_id(it.first)); + auto name = string(it.first.unescape()); print_log_line(name, local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, area_cells_by_type.at(it.first), 1, print_area, print_hierarchical, print_global_only); @@ -533,7 +533,7 @@ struct statdata_t { print_global_only); for (auto &it : num_submodules_by_type) if (it.second) - print_log_line(string(log_id(it.first)), it.second, 0, it.second, + print_log_line(string(it.first.unescape()), it.second, 0, it.second, submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0, 1, print_area, print_hierarchical, print_global_only); } @@ -607,7 +607,7 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %s", json11::Json(log_id(it.first)).dump(), + log(" %s: %s", json11::Json(it.first.unescape()).dump(), json_line(local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, area_cells_by_type.at(it.first)) @@ -621,7 +621,7 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %s", json11::Json(log_id(it.first)).dump(), + log(" %s: %s", json11::Json(it.first.unescape()).dump(), json_line(0, 0, it.second, submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0) .c_str()); @@ -662,14 +662,14 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } for (auto &it : num_submodules_by_type) if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } log("\n"); @@ -697,14 +697,14 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } for (auto &it : num_submodules_by_type) if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(log_id(it.first)).dump(), it.second); + log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); first_line = false; } log("\n"); @@ -734,7 +734,7 @@ statdata_t hierarchy_worker(std::map &mod_stat, RTL for (auto &it : mod_data.num_submodules_by_type) { if (mod_stat.count(it.first) > 0) { if (!quiet) - mod_data.print_log_line(string(log_id(it.first)), mod_stat.at(it.first).local_num_cells, + mod_data.print_log_line(string(it.first.unescape()), mod_stat.at(it.first).local_num_cells, mod_stat.at(it.first).local_area, mod_stat.at(it.first).num_cells, mod_stat.at(it.first).area, level, has_area, hierarchy_mode); hierarchy_worker(mod_stat, it.first, level + 1, quiet, has_area, hierarchy_mode) * it.second; @@ -1009,7 +1009,7 @@ struct StatPass : public Pass { first_module = false; } else { log("\n"); - log("=== %s%s ===\n", log_id(mod->name), mod->is_selected_whole() ? "" : " (partially selected)"); + log("=== %s%s ===\n", mod->name.unescape(), mod->is_selected_whole() ? "" : " (partially selected)"); log("\n"); data.log_data(mod->name, false, has_area, hierarchy_mode); } @@ -1026,7 +1026,7 @@ struct StatPass : public Pass { log("=== design hierarchy ===\n"); log("\n"); mod_stat[top_mod->name].print_log_header(has_area, hierarchy_mode, true); - mod_stat[top_mod->name].print_log_line(log_id(top_mod->name), mod_stat[top_mod->name].local_num_cells, + mod_stat[top_mod->name].print_log_line(top_mod->name.unescape(), mod_stat[top_mod->name].local_num_cells, mod_stat[top_mod->name].local_area, mod_stat[top_mod->name].num_cells, mod_stat[top_mod->name].area, 0, has_area, hierarchy_mode, true); } diff --git a/passes/cmds/timeest.cc b/passes/cmds/timeest.cc index 1caa1ddaf..3105affa1 100644 --- a/passes/cmds/timeest.cc +++ b/passes/cmds/timeest.cc @@ -83,7 +83,7 @@ struct EstimateSta { void run() { - log("\nModule %s\n", log_id(m)); + log("\nModule %s\n", m); if (clk.has_value()) log("Domain %s\n", log_signal(*clk)); @@ -97,7 +97,7 @@ struct EstimateSta { FfData ff(nullptr, cell); if (!ff.has_clk) { log_warning("Ignoring unsupported storage element '%s' (%s)\n", - log_id(cell), log_id(cell->type)); + cell, cell->type.unescape()); continue; } if (ff.sig_clk != clk) @@ -121,7 +121,7 @@ struct EstimateSta { aigs.emplace(fingerprint, Aig(cell)); if (aigs.at(fingerprint).name.empty()) { log_error("Unsupported cell '%s' in module '%s'", - log_id(cell->type), log_id(m)); + cell->type.unescape(), m); } } @@ -141,7 +141,7 @@ struct EstimateSta { for (auto &mem : Mem::get_all_memories(m)) { for (auto &rd : mem.rd_ports) { if (!rd.clk_enable) { - log_error("Unsupported async memory port '%s'\n", log_id(rd.cell)); + log_error("Unsupported async memory port '%s'\n", rd.cell); continue; } if (sigmap(rd.clk) != clk) @@ -165,7 +165,7 @@ struct EstimateSta { } else if (port->port_output && !port->port_input) { all_outputs.append(port); } else if (port->port_output && port->port_input) { - log_warning("Ignoring bi-directional port %s\n", log_id(port)); + log_warning("Ignoring bi-directional port %s\n", port); } } add_seq(nullptr, all_inputs, all_outputs); @@ -216,7 +216,7 @@ struct EstimateSta { } if (!topo.sort()) - log_error("Module '%s' contains combinational loops", log_id(m)); + log_error("Module '%s' contains combinational loops", m); // now we determine how long it takes for signals to stabilize @@ -342,7 +342,7 @@ struct EstimateSta { std::string src_attr = cell->get_src_attribute(); cell_src = stringf(" source: %s", src_attr); } - log(" cell %s (%s)%s\n", log_id(cell), log_id(cell->type), cell_src); + log(" cell %s (%s)%s\n", cell, cell->type.unescape(), cell_src); printed.insert(cell); } } else { @@ -425,7 +425,7 @@ struct TimeestPass : Pass { if (clk_domain_specified) { if (!m->wire(RTLIL::escape_id(clk_name))) { - log_warning("No domain '%s' in module %s\n", clk_name.c_str(), log_id(m)); + log_warning("No domain '%s' in module %s\n", clk_name.c_str(), m); continue; } diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc index 52c00072f..828b65c24 100644 --- a/passes/cmds/torder.cc +++ b/passes/cmds/torder.cc @@ -74,7 +74,7 @@ struct TorderPass : public Pass { for (auto module : design->selected_modules()) { - log("module %s\n", log_id(module)); + log("module %s\n", module); SigMap sigmap(module); dict> bit_drivers, bit_users; @@ -116,12 +116,12 @@ struct TorderPass : public Pass { for (auto &it : toposort.loops) { log(" loop"); for (auto cell : it) - log(" %s", log_id(cell)); + log(" %s", cell); log("\n"); } for (auto cell : toposort.sorted) - log(" cell %s\n", log_id(cell)); + log(" cell %s\n", cell); } } } TorderPass; diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc index 222fecaca..37f7da89b 100644 --- a/passes/cmds/trace.cc +++ b/passes/cmds/trace.cc @@ -28,34 +28,34 @@ struct TraceMonitor : public RTLIL::Monitor { void notify_module_add(RTLIL::Module *module) override { - log("#TRACE# Module add: %s\n", log_id(module)); + log("#TRACE# Module add: %s\n", module); } void notify_module_del(RTLIL::Module *module) override { - log("#TRACE# Module delete: %s\n", log_id(module)); + log("#TRACE# Module delete: %s\n", module); } void notify_connect(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) 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)); + log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", cell->module, cell, port.unescape(), log_signal(sig), log_signal(old_sig)); } void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) override { - log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second)); + log("#TRACE# Connection in module %s: %s = %s\n", module, log_signal(sigsig.first), log_signal(sigsig.second)); } void notify_connect(RTLIL::Module *module, const std::vector &sigsig_vec) override { - log("#TRACE# New connections in module %s:\n", log_id(module)); + log("#TRACE# New connections in module %s:\n", module); for (auto &sigsig : sigsig_vec) log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second)); } void notify_blackout(RTLIL::Module *module) override { - log("#TRACE# Blackout in module %s:\n", log_id(module)); + log("#TRACE# Blackout in module %s:\n", module); } }; diff --git a/passes/cmds/viz.cc b/passes/cmds/viz.cc index e3b09d029..9eb35d6c2 100644 --- a/passes/cmds/viz.cc +++ b/passes/cmds/viz.cc @@ -279,7 +279,7 @@ struct Graph { Graph(Module *module, const VizConfig &config) : module(module), config(config) { - log("Running 'viz -%d' for module %s:\n", config.effort, log_id(module)); + log("Running 'viz -%d' for module %s:\n", config.effort, module); log(" Phase %d: Construct initial graph\n", phase_counter++); SigMap sigmap(module); @@ -718,7 +718,7 @@ struct VizWorker void write_dot(FILE *f) { - fprintf(f, "digraph \"%s\" {\n", log_id(module)); + fprintf(f, "digraph \"%s\" {\n", module); fprintf(f, " rankdir = LR;\n"); dict>> extra_lines; @@ -734,7 +734,7 @@ struct VizWorker buffer.emplace_back(); for (auto name : g->names()) - buffer.back().push_back(log_id(name)); + buffer.back().push_back(name.unescape()); std::sort(buffer.back().begin(), buffer.back().end()); std::sort(buffer.begin(), buffer.end()); @@ -782,7 +782,7 @@ struct VizWorker g->names().sort(); std::string label; // = stringf("vg=%d\\n", g->index); for (auto n : g->names()) - label = label + (label.empty() ? "" : "\\n") + log_id(n); + label = label + (label.empty() ? "" : "\\n") + n.unescape(); fprintf(f, "\tn%d [shape=rectangle,label=\"%s\"];\n", g->index, label.c_str()); } else { std::string label = stringf("vg=%d | %d cells", g->index, GetSize(g->names())); diff --git a/passes/cmds/wrapcell.cc b/passes/cmds/wrapcell.cc index 4c6f44ed7..1d73decc5 100644 --- a/passes/cmds/wrapcell.cc +++ b/passes/cmds/wrapcell.cc @@ -70,7 +70,7 @@ std::optional format_with_params(std::string fmt, const dicttype)) log_error("Non-internal cell type '%s' on cell '%s' in module '%s' unsupported\n", - log_id(cell->type), log_id(cell), log_id(module)); + cell->type.unescape(), cell, module); std::vector> unused_outputs, used_outputs; for (auto conn : cell->connections()) { @@ -233,7 +233,7 @@ struct WrapcellPass : Pass { std::optional unescaped_name = format_with_params(name_fmt, cell->parameters, context); if (!unescaped_name) log_error("Formatting error when processing cell '%s' in module '%s'\n", - log_id(cell), log_id(module)); + cell, module); IdString name = RTLIL::escape_id(unescaped_name.value()); if (d->module(name)) @@ -274,7 +274,7 @@ struct WrapcellPass : Pass { if (!value) log_error("Formatting error when processing cell '%s' in module '%s'\n", - log_id(cell), log_id(module)); + cell, module); subm->set_string_attribute(rule.name, value.value()); } diff --git a/passes/cmds/xprop.cc b/passes/cmds/xprop.cc index 3f40e72ab..25c1a7320 100644 --- a/passes/cmds/xprop.cc +++ b/passes/cmds/xprop.cc @@ -467,7 +467,7 @@ struct XpropWorker return; } - log_warning("Unhandled cell %s (%s) during maybe-x marking\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s) during maybe-x marking\n", cell, cell->type.unescape()); mark_outputs_maybe_x(cell); } @@ -862,7 +862,7 @@ struct XpropWorker if ((ff.has_clk || ff.has_gclk) && !ff.has_ce && !ff.has_aload && !ff.has_srst && !ff.has_arst && !ff.has_sr) { if (ff.has_clk && maybe_x(ff.sig_clk)) { - log_warning("Only non-x CLK inputs are currently supported for %s (%s)\n", log_id(cell), log_id(cell->type)); + log_warning("Only non-x CLK inputs are currently supported for %s (%s)\n", cell, cell->type.unescape()); } else { auto init_q = ff.val_init; auto init_q_is_1 = init_q; @@ -907,7 +907,7 @@ struct XpropWorker return; } } else { - log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled FF-cell %s (%s), consider running clk2fflogic, async2sync and/or dffunmap\n", cell, cell->type.unescape()); } } @@ -964,9 +964,9 @@ struct XpropWorker log("Running 'demuxmap' preserves x-propagation and can be run before 'xprop'.\n"); if (options.required) - log_error("Unhandled cell %s (%s)\n", log_id(cell), log_id(cell->type)); + log_error("Unhandled cell %s (%s)\n", cell, cell->type.unescape()); else - log_warning("Unhandled cell %s (%s)\n", log_id(cell), log_id(cell->type)); + log_warning("Unhandled cell %s (%s)\n", cell, cell->type.unescape()); } void split_ports() @@ -980,7 +980,7 @@ struct XpropWorker auto wire = module->wire(port); if (module->design->selected(module, wire)) { if (wire->port_input == wire->port_output) { - log_warning("Port %s not an input or an output port which is not supported by xprop\n", log_id(wire)); + log_warning("Port %s not an input or an output port which is not supported by xprop\n", wire); } else if ((options.split_inputs && !options.assume_def_inputs && wire->port_input) || (options.split_outputs && wire->port_output)) { auto port_d = module->uniquify(stringf("%s_d", port)); auto port_x = module->uniquify(stringf("%s_x", port)); diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc index e4480c893..c2308462e 100644 --- a/passes/equiv/equiv_induct.cc +++ b/passes/equiv/equiv_induct.cc @@ -84,7 +84,7 @@ struct EquivInductWorker : public EquivWorker<> void run() { - log("Found %d unproven $equiv cells in module %s:\n", GetSize(workset), log_id(module)); + log("Found %d unproven $equiv cells in module %s:\n", GetSize(workset), module); if (satgen.model_undef) { for (auto cell : cells) @@ -217,7 +217,7 @@ struct EquivInductPass : public Pass { } if (unproven_equiv_cells.empty()) { - log("No selected unproven $equiv cells found in %s.\n", log_id(module)); + log("No selected unproven $equiv cells found in %s.\n", module); continue; } diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index bae7452f7..53e86cdae 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -159,7 +159,7 @@ struct EquivMakeWorker if (encdata.count(id)) { - log("Creating encoder/decoder for signal %s.\n", log_id(id)); + log("Creating encoder/decoder for signal %s.\n", id.unescape()); Wire *dec_wire = equiv_mod->addWire(id.str() + "_decoded", gold_wire->width); Wire *enc_wire = equiv_mod->addWire(id.str() + "_encoded", gate_wire->width); @@ -226,15 +226,15 @@ struct EquivMakeWorker if (gold_wire == nullptr || gate_wire == nullptr || gold_wire->width != gate_wire->width) { if (gold_wire && gold_wire->port_id) - log_error("Can't match gold port `%s' to a gate port.\n", log_id(gold_wire)); + log_error("Can't match gold port `%s' to a gate port.\n", gold_wire); if (gate_wire && gate_wire->port_id) - log_error("Can't match gate port `%s' to a gold port.\n", log_id(gate_wire)); + log_error("Can't match gate port `%s' to a gold port.\n", gate_wire); continue; } log("Presumably equivalent wires: %s (%s), %s (%s) -> %s\n", - log_id(gold_wire), log_signal(assign_map(gold_wire)), - log_id(gate_wire), log_signal(assign_map(gate_wire)), log_id(id)); + gold_wire, log_signal(assign_map(gold_wire)), + gate_wire, log_signal(assign_map(gate_wire)), id.unescape()); if (gold_wire->port_output || gate_wire->port_output) { @@ -313,7 +313,7 @@ struct EquivMakeWorker new_sig[i] = old_sig[i]; if (old_sig != new_sig) { log("Changing input %s of cell %s (%s): %s -> %s\n", - log_id(conn.first), log_id(c), log_id(c->type), + conn.first.unescape(), c, c->type.unescape(), log_signal(old_sig), log_signal(new_sig)); c->setPort(conn.first, new_sig); } @@ -344,7 +344,7 @@ struct EquivMakeWorker goto try_next_cell_name; log("Presumably equivalent cells: %s %s (%s) -> %s\n", - log_id(gold_cell), log_id(gate_cell), log_id(gold_cell->type), log_id(id)); + gold_cell, gate_cell, gold_cell->type.unescape(), id.unescape()); for (auto gold_conn : gold_cell->connections()) { diff --git a/passes/equiv/equiv_mark.cc b/passes/equiv/equiv_mark.cc index 97a2a38dd..0f355af4e 100644 --- a/passes/equiv/equiv_mark.cc +++ b/passes/equiv/equiv_mark.cc @@ -109,7 +109,7 @@ struct EquivMarkWorker void run() { - log("Running equiv_mark on module %s:\n", log_id(module)); + log("Running equiv_mark on module %s:\n", module); // marking region 0 diff --git a/passes/equiv/equiv_miter.cc b/passes/equiv/equiv_miter.cc index 6acfe85a9..b8372ceb0 100644 --- a/passes/equiv/equiv_miter.cc +++ b/passes/equiv/equiv_miter.cc @@ -82,7 +82,7 @@ struct EquivMiterWorker for (auto c : source_module->selected_cells()) if (c->type == ID($equiv)) { - log("Seed $equiv cell: %s\n", log_id(c)); + log("Seed $equiv cell: %s\n", c); seed_cells.insert(c); } @@ -194,11 +194,11 @@ struct EquivMiterWorker w->port_input = true; } if (w->port_output && w->port_input) - log("Created miter inout port %s.\n", log_id(w)); + log("Created miter inout port %s.\n", w); else if (w->port_output) - log("Created miter output port %s.\n", log_id(w)); + log("Created miter output port %s.\n", w); else if (w->port_input) - log("Created miter input port %s.\n", log_id(w)); + log("Created miter input port %s.\n", w); } miter_module->fixup_ports(); @@ -252,7 +252,7 @@ struct EquivMiterWorker void run() { - log("Creating miter %s from module %s.\n", log_id(miter_module), log_id(source_module)); + log("Creating miter %s from module %s.\n", miter_module, source_module); find_miter_cells_wires(); copy_to_miter(); make_stuff(); @@ -320,7 +320,7 @@ struct EquivMiterPass : public Pass { extra_args(args, argidx, design); if (design->module(worker.miter_name)) - log_cmd_error("Miter module %s already exists.\n", log_id(worker.miter_name)); + log_cmd_error("Miter module %s already exists.\n", worker.miter_name.unescape()); worker.source_module = nullptr; for (auto m : design->selected_modules()) { diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc index 5b0696d9b..4062161bb 100644 --- a/passes/equiv/equiv_purge.cc +++ b/passes/equiv/equiv_purge.cc @@ -37,7 +37,7 @@ struct EquivPurgeWorker Wire *wire = sig.as_wire(); if (wire->name.isPublic()) { if (!wire->port_output) { - log(" Module output: %s (%s)\n", log_signal(wire), log_id(cellname)); + log(" Module output: %s (%s)\n", log_signal(wire), cellname.unescape()); wire->port_output = true; } return wire; @@ -53,7 +53,7 @@ struct EquivPurgeWorker Wire *wire = module->addWire(name, GetSize(sig)); wire->port_output = true; module->connect(wire, sig); - log(" Module output: %s (%s)\n", log_signal(wire), log_id(cellname)); + log(" Module output: %s (%s)\n", log_signal(wire), cellname.unescape()); return wire; } } @@ -87,7 +87,7 @@ struct EquivPurgeWorker void run() { - log("Running equiv_purge on module %s:\n", log_id(module)); + log("Running equiv_purge on module %s:\n", module); for (auto wire : module->wires()) { wire->port_input = false; diff --git a/passes/equiv/equiv_remove.cc b/passes/equiv/equiv_remove.cc index 5d1823e12..c871cd9ef 100644 --- a/passes/equiv/equiv_remove.cc +++ b/passes/equiv/equiv_remove.cc @@ -69,7 +69,7 @@ struct EquivRemovePass : public Pass { { for (auto cell : module->selected_cells()) if (cell->type == ID($equiv) && (mode_gold || mode_gate || cell->getPort(ID::A) == cell->getPort(ID::B))) { - log("Removing $equiv cell %s.%s (%s).\n", log_id(module), log_id(cell), log_signal(cell->getPort(ID::Y))); + log("Removing $equiv cell %s.%s (%s).\n", module, cell, log_signal(cell->getPort(ID::Y))); module->connect(cell->getPort(ID::Y), mode_gate ? cell->getPort(ID::B) : cell->getPort(ID::A)); module->remove(cell); remove_count++; diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc index e498928c3..6f3c9dc71 100644 --- a/passes/equiv/equiv_simple.cc +++ b/passes/equiv/equiv_simple.cc @@ -205,10 +205,10 @@ struct EquivSimpleWorker : public EquivWorker (GetSize(cone_a.cells) + GetSize(cone_b.cells)) - GetSize(cells)); #if 0 for (auto cell : short_cells_cone_a) - log(" A-side cell: %s\n", log_id(cell)); + log(" A-side cell: %s\n", cell); for (auto cell : short_cells_cone_b) - log(" B-side cell: %s\n", log_id(cell)); + log(" B-side cell: %s\n", cell); #endif } void report_new_assume_cells(const pool& extra_problem_cells, int old_size, const pool& problem_cells) const @@ -219,7 +219,7 @@ struct EquivSimpleWorker : public EquivWorker old_size - (GetSize(problem_cells) - GetSize(extra_problem_cells))); #if 0 for (auto cell : extra_problem_cells) - log(" cell: %s\n", log_id(cell)); + log(" cell: %s\n", cell); #endif } } @@ -305,7 +305,7 @@ struct EquivSimpleWorker : public EquivWorker pool seed_b = { bit_b }; if (cfg.verbose) { - log(" Trying to prove $equiv cell %s:\n", log_id(cell)); + log(" Trying to prove $equiv cell %s:\n", cell); log(" A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(cell->getPort(ID::Y))); } else { log(" Trying to prove $equiv for %s:", log_signal(cell->getPort(ID::Y))); @@ -477,7 +477,7 @@ struct EquivSimplePass : public Pass { continue; log("Found %d unproven $equiv cells (%d groups) in %s:\n", - unproven_cells_counter, GetSize(unproven_equiv_cells), log_id(module)); + unproven_cells_counter, GetSize(unproven_equiv_cells), module); for (auto cell : module->cells()) { if (!ct.cell_known(cell->type)) diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc index b221be27c..da53c60a2 100644 --- a/passes/equiv/equiv_status.cc +++ b/passes/equiv/equiv_status.cc @@ -67,17 +67,17 @@ struct EquivStatusPass : public Pass { } if (unproven_equiv_cells.empty() && !proven_equiv_cells) { - log("No $equiv cells found in %s.\n", log_id(module)); + log("No $equiv cells found in %s.\n", module); continue; } - log("Found %d $equiv cells in %s:\n", GetSize(unproven_equiv_cells) + proven_equiv_cells, log_id(module)); + log("Found %d $equiv cells in %s:\n", GetSize(unproven_equiv_cells) + proven_equiv_cells, module); log(" Of those cells %d are proven and %d are unproven.\n", proven_equiv_cells, GetSize(unproven_equiv_cells)); if (unproven_equiv_cells.empty()) { log(" Equivalence successfully proven!\n"); } else { for (auto cell : unproven_equiv_cells) - log(" Unproven $equiv %s: %s %s\n", log_id(cell), log_signal(cell->getPort(ID::A)), log_signal(cell->getPort(ID::B))); + log(" Unproven $equiv %s: %s %s\n", cell, log_signal(cell->getPort(ID::A)), log_signal(cell->getPort(ID::B))); } unproven_count += GetSize(unproven_equiv_cells); diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc index 411f0dd5c..7f8d8d282 100644 --- a/passes/equiv/equiv_struct.cc +++ b/passes/equiv/equiv_struct.cc @@ -79,7 +79,7 @@ struct EquivStructWorker inputs_a.append(bits_a[i]); inputs_b.append(bits_b[i]); input_names.push_back(GetSize(bits_a) == 1 ? port_a.first.str() : - stringf("%s[%d]", log_id(port_a.first), i)); + stringf("%s[%d]", port_a.first.unescape(), i)); } } @@ -111,7 +111,7 @@ struct EquivStructWorker } auto merged_attr = cell_b->get_strpool_attribute(ID::equiv_merged); - merged_attr.insert(log_id(cell_b)); + merged_attr.insert(cell_b->name.unescape()); cell_a->add_strpool_attribute(ID::equiv_merged, merged_attr); module->remove(cell_b); } @@ -144,7 +144,7 @@ struct EquivStructWorker SigBit sig_b = sigmap(cell->getPort(ID::B).as_bit()); SigBit sig_y = sigmap(cell->getPort(ID::Y).as_bit()); if (sig_a == sig_b && equiv_inputs.count(sig_y)) { - log(" Purging redundant $equiv cell %s.\n", log_id(cell)); + log(" Purging redundant $equiv cell %s.\n", cell); module->connect(sig_y, sig_a); module->remove(cell); merge_count++; @@ -266,9 +266,9 @@ struct EquivStructWorker run_strategy: int total_group_size = GetSize(gold_cells) + GetSize(gate_cells) + GetSize(other_cells); log(" %s merging %d %s cells (from group of %d) using strategy %s:\n", phase ? "Bwd" : "Fwd", - 2*GetSize(cell_pairs), log_id(cells_type), total_group_size, strategy); + 2*GetSize(cell_pairs), cells_type.unescape(), total_group_size, strategy); for (auto it : cell_pairs) { - log(" Merging cells %s and %s.\n", log_id(it.first), log_id(it.second)); + log(" Merging cells %s and %s.\n", it.first, it.second); merge_cell_pair(it.first, it.second); } } @@ -347,7 +347,7 @@ struct EquivStructPass : public Pass { for (auto module : design->selected_modules()) { int module_merge_count = 0; - log("Running equiv_struct on module %s:\n", log_id(module)); + log("Running equiv_struct on module %s:\n", module); for (int iter = 0;; iter++) { if (iter == max_iter) { log(" Reached iteration limit of %d.\n", iter); @@ -359,7 +359,7 @@ struct EquivStructPass : public Pass { module_merge_count += worker.merge_count; } if (module_merge_count) - log(" Performed a total of %d merges in module %s.\n", module_merge_count, log_id(module)); + log(" Performed a total of %d merges in module %s.\n", module_merge_count, module); } } } EquivStructPass; diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 5f491a16c..dfe99f512 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -132,7 +132,7 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) if (wire->width <= 1) { if (has_fsm_encoding_attr) { - log_warning("Removing fsm_encoding attribute from 1-bit net: %s.%s\n", log_id(wire->module), log_id(wire)); + log_warning("Removing fsm_encoding attribute from 1-bit net: %s.%s\n", wire->module, wire); wire->attributes.erase(ID::fsm_encoding); } return; @@ -230,23 +230,23 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) warnings.push_back("FSM seems to be self-resetting. Possible simulation-synthesis mismatch!\n"); if (!warnings.empty()) { - string warnmsg = stringf("Regarding the user-specified fsm_encoding attribute on %s.%s:\n", log_id(wire->module), log_id(wire)); + string warnmsg = stringf("Regarding the user-specified fsm_encoding attribute on %s.%s:\n", wire->module, wire); for (auto w : warnings) warnmsg += " " + w; log_warning("%s", warnmsg); } else { - log("FSM state register %s.%s already has fsm_encoding attribute.\n", log_id(wire->module), log_id(wire)); + log("FSM state register %s.%s already has fsm_encoding attribute.\n", wire->module, wire); } } else if (looks_like_state_reg && looks_like_good_state_reg && !has_init_attr && !is_module_port && !is_self_resetting) { - log("Found FSM state register %s.%s.\n", log_id(wire->module), log_id(wire)); + log("Found FSM state register %s.%s.\n", wire->module, wire); wire->attributes[ID::fsm_encoding] = RTLIL::Const("auto"); } else if (looks_like_state_reg) { - log("Not marking %s.%s as FSM state register:\n", log_id(wire->module), log_id(wire)); + log("Not marking %s.%s as FSM state register:\n", wire->module, wire); if (is_module_port) log(" Register is connected to module port.\n"); diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc index b11f0d3be..40c1d9904 100644 --- a/passes/fsm/fsm_expand.cc +++ b/passes/fsm/fsm_expand.cc @@ -189,12 +189,12 @@ struct FsmExpand if (GetSize(input_sig) > 10) log_warning("Cell %s.%s (%s) has %d input bits, merging into FSM %s.%s might be problematic.\n", - log_id(cell->module), log_id(cell), log_id(cell->type), - GetSize(input_sig), log_id(fsm_cell->module), log_id(fsm_cell)); + cell->module, cell, cell->type.unescape(), + GetSize(input_sig), fsm_cell->module, fsm_cell); if (GetSize(fsm_data.transition_table) > 10000) log_warning("Transition table for FSM %s.%s already has %d rows, merging more cells " - "into this FSM might be problematic.\n", log_id(fsm_cell->module), log_id(fsm_cell), + "into this FSM might be problematic.\n", fsm_cell->module, fsm_cell, GetSize(fsm_data.transition_table)); std::vector new_transition_table; diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc index 7c79a53cc..1b06b18c2 100644 --- a/passes/fsm/fsm_export.cc +++ b/passes/fsm/fsm_export.cc @@ -64,7 +64,7 @@ void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::st kiss_name.assign(attr_it->second.decode_string()); } else { - kiss_name.assign(log_id(module) + std::string("-") + log_id(cell) + ".kiss2"); + kiss_name.assign(module->name.unescape() + std::string("-") + cell->name.unescape() + ".kiss2"); } log("\n"); diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc index ff3714021..7b3b59ee9 100644 --- a/passes/fsm/fsm_info.cc +++ b/passes/fsm/fsm_info.cc @@ -50,7 +50,7 @@ struct FsmInfoPass : public Pass { for (auto cell : mod->selected_cells()) if (cell->type == ID($fsm)) { log("\n"); - log("FSM `%s' from module `%s':\n", log_id(cell), log_id(mod)); + log("FSM `%s' from module `%s':\n", cell, mod); FsmData fsm_data; fsm_data.copy_from_cell(cell); fsm_data.log_info(cell); diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index e4cd53a07..5c813e481 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -96,7 +96,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs log_error("FSM encoding `%s' is not supported!\n", encoding); if (encfile) - fprintf(encfile, ".fsm %s %s\n", log_id(module), RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); + fprintf(encfile, ".fsm %s %s\n", module, RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); int state_idx_counter = fsm_data.reset_state >= 0 ? 1 : 0; for (int i = 0; i < int(fsm_data.state_table.size()); i++) diff --git a/passes/hierarchy/flatten.cc b/passes/hierarchy/flatten.cc index 17bd6e340..2dd20302c 100644 --- a/passes/hierarchy/flatten.cc +++ b/passes/hierarchy/flatten.cc @@ -149,7 +149,7 @@ struct FlattenWorker hier_wire->attributes.erase(ID::hierconn); if (GetSize(hier_wire) < GetSize(tpl_wire)) { log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", - log_id(module), log_id(hier_wire), log_id(tpl), log_id(tpl_wire), log_id(module), log_id(cell)); + module, hier_wire, tpl, tpl_wire, module, cell); hier_wire->width = GetSize(tpl_wire); } new_wire = hier_wire; @@ -261,7 +261,7 @@ struct FlattenWorker if (sigmap(new_conn.first).has_const()) log_error("Cell port %s.%s.%s is driving constant bits: %s <= %s\n", - log_id(module), log_id(cell), log_id(port_it.first), log_signal(new_conn.first), log_signal(new_conn.second)); + module, cell, port_it.first.unescape(), log_signal(new_conn.first), log_signal(new_conn.second)); module->connect(new_conn); sigmap.add(new_conn.first, new_conn.second); @@ -316,12 +316,12 @@ struct FlattenWorker continue; if (cell->get_bool_attribute(ID::keep_hierarchy) || tpl->get_bool_attribute(ID::keep_hierarchy)) { - log("Keeping %s.%s (found keep_hierarchy attribute).\n", log_id(module), log_id(cell)); + log("Keeping %s.%s (found keep_hierarchy attribute).\n", module, cell); used_modules.insert(tpl); continue; } - log_debug("Flattening %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log_debug("Flattening %s.%s (%s).\n", module, cell, cell->type.unescape()); // If a design is fully selected and has a top module defined, topological sorting ensures that all cells // added during flattening are black boxes, and flattening is finished in one pass. However, when flattening // individual modules, this isn't the case, and the newly added cells might have to be flattened further. @@ -443,7 +443,7 @@ struct FlattenPass : public Pass { if (cleanup && top != nullptr) for (auto module : design->modules().to_vector()) if (!used_modules[module] && !module->get_blackbox_attribute(worker.ignore_wb)) { - log("Deleting now unused module %s.\n", log_id(module)); + log("Deleting now unused module %s.\n", module); design->remove(module); } diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 416997bee..67475eda0 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -225,7 +225,7 @@ struct IFExpander // about it and don't set has_interfaces_not_found (to avoid a // loop). log_warning("Could not find interface instance for `%s' in `%s'\n", - log_id(interface_name), log_id(&module)); + interface_name.unescape(), &module); } // Handle an interface connection from the module @@ -268,12 +268,12 @@ struct IFExpander // Go over all wires in interface, and add replacements to lists. for (auto mod_wire : mod_replace_ports->wires()) { - std::string signal_name1 = conn_name.str() + "." + log_id(mod_wire->name); - std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire); + std::string signal_name1 = conn_name.str() + "." + mod_wire->name.unescape(); + std::string signal_name2 = interface_name.str() + "." + mod_wire->name.unescape(); connections_to_add_name.push_back(RTLIL::IdString(signal_name1)); if(module.wire(signal_name2) == nullptr) { log_error("Could not find signal '%s' in '%s'\n", - signal_name2.c_str(), log_id(module.name)); + signal_name2.c_str(), module.name.unescape()); } else { RTLIL::Wire *wire_in_parent = module.wire(signal_name2); @@ -432,7 +432,7 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI if (id <= 0 || id > GetSize(mod.ports)) log_error("Module `%s' referenced in module `%s' in cell `%s' " "has only %d ports, requested port %d.\n", - log_id(cell.type), log_id(&module), log_id(&cell), + cell.type.unescape(), &module, &cell, GetSize(mod.ports), id); continue; } @@ -441,8 +441,8 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI if (!wire || wire->port_id == 0) { log_error("Module `%s' referenced in module `%s' in cell `%s' " "does not have a port named '%s'.\n", - log_id(cell.type), log_id(&module), log_id(&cell), - log_id(conn.first)); + cell.type.unescape(), &module, &cell, + conn.first.unescape()); } } for (auto ¶m : cell.parameters) { @@ -450,7 +450,7 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI if (id <= 0 || id > GetSize(mod.avail_parameters)) log_error("Module `%s' referenced in module `%s' in cell `%s' " "has only %d parameters, requested parameter %d.\n", - log_id(cell.type), log_id(&module), log_id(&cell), + cell.type.unescape(), &module, &cell, GetSize(mod.avail_parameters), id); continue; } @@ -460,8 +460,8 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI strchr(param.first.c_str(), '.') == NULL) { log_error("Module `%s' referenced in module `%s' in cell `%s' " "does not have a parameter named '%s'.\n", - log_id(cell.type), log_id(&module), log_id(&cell), - log_id(param.first)); + cell.type.unescape(), &module, &cell, + param.first.unescape()); } } } @@ -1036,7 +1036,7 @@ struct HierarchyPass : public Pass { if (top_mod == nullptr) for (auto mod : design->modules()) if (mod->get_bool_attribute(ID::top)) { - log("Attribute `top' found on module `%s'. Setting top module to %s.\n", log_id(mod), log_id(mod)); + log("Attribute `top' found on module `%s'. Setting top module to %s.\n", mod, mod); top_mod = mod; } @@ -1057,12 +1057,12 @@ struct HierarchyPass : public Pass { dict db; for (Module *mod : design->selected_modules()) { int score = find_top_mod_score(design, mod, db); - log("root of %3d design levels: %-20s\n", score, log_id(mod)); + log("root of %3d design levels: %-20s\n", score, mod); if (!top_mod || score > db[top_mod]) top_mod = mod; } if (top_mod != nullptr) - log("Automatically selected %s as design top module.\n", log_id(top_mod)); + log("Automatically selected %s as design top module.\n", top_mod); } if (top_mod != nullptr && top_mod->name.begins_with("$abstract")) { @@ -1162,7 +1162,7 @@ struct HierarchyPass : public Pass { std::map cache; for (auto mod : design->modules()) if (set_keep_print(cache, mod)) { - log("Module %s directly or indirectly displays text -> setting \"keep\" attribute.\n", log_id(mod)); + log("Module %s directly or indirectly displays text -> setting \"keep\" attribute.\n", mod); mod->set_bool_attribute(ID::keep); } } @@ -1171,7 +1171,7 @@ struct HierarchyPass : public Pass { std::map cache; for (auto mod : design->modules()) if (set_keep_assert(cache, mod)) { - log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", log_id(mod)); + log("Module %s directly or indirectly contains formal properties -> setting \"keep\" attribute.\n", mod); mod->set_bool_attribute(ID::keep); } } @@ -1190,7 +1190,7 @@ struct HierarchyPass : public Pass { src += ": "; log_error("%sProperty `%s' in module `%s' uses unsupported SVA constructs. See frontend warnings for details, run `chformal -remove a:unsupported_sva' to ignore.\n", - src, log_id(cell->name), log_id(mod->name)); + src, cell->name.unescape(), mod->name.unescape()); } } } @@ -1499,7 +1499,7 @@ struct HierarchyPass : public Pass { bool resize_widths = !keep_portwidths && GetSize(w) != GetSize(conn.second); if (resize_widths && verific_mod && boxed_params) log_debug("Ignoring width mismatch on %s.%s.%s from verific, is port width parametrizable?\n", - log_id(module), log_id(cell), log_id(conn.first) + module, cell, conn.first.unescape() ); else if (resize_widths) { if (GetSize(w) < GetSize(conn.second)) @@ -1523,14 +1523,14 @@ struct HierarchyPass : public Pass { } if (!conn.second.is_fully_const() || !w->port_input || w->port_output) - log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", log_id(module), log_id(cell), - log_id(conn.first), GetSize(conn.second), GetSize(sig)); + log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", module, cell, + conn.first.unescape(), GetSize(conn.second), GetSize(sig)); cell->setPort(conn.first, sig); } if (w->port_output && !w->port_input && sig.has_const()) log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n", - log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig)); + module, cell, conn.first.unescape(), cell->type.unescape(), log_signal(sig)); } } } diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 9d77b5239..aa3ac72e3 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -42,7 +42,7 @@ struct ThresholdHierarchyKeeping { return 0; if (module->get_blackbox_attribute()) - log_error("Missing cost information on instanced blackbox %s\n", log_id(module)); + log_error("Missing cost information on instanced blackbox %s\n", module); if (done.count(module)) return done.at(module); @@ -61,13 +61,13 @@ struct ThresholdHierarchyKeeping { RTLIL::Module *submodule = design->module(cell->type); if (!submodule) log_error("Hierarchy contains unknown module '%s' (instanced as %s in %s)\n", - log_id(cell->type), log_id(cell), log_id(module)); + cell->type.unescape(), cell, module); size += visit(submodule); } } if (size > threshold) { - log("Keeping %s (estimated size above threshold: %" PRIu64 " > %" PRIu64 ").\n", log_id(module), size, threshold); + log("Keeping %s (estimated size above threshold: %" PRIu64 " > %" PRIu64 ").\n", module, size, threshold); module->set_bool_attribute(ID::keep_hierarchy); size = 0; } @@ -124,7 +124,7 @@ struct KeepHierarchyPass : public Pass { worker.visit(top); } else { for (auto module : design->selected_modules()) { - log("Marking %s.\n", log_id(module)); + log("Marking %s.\n", module); module->set_bool_attribute(ID::keep_hierarchy); } } diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc index 49b59c8df..941f4dce8 100644 --- a/passes/hierarchy/uniquify.cc +++ b/passes/hierarchy/uniquify.cc @@ -71,7 +71,7 @@ struct UniquifyPass : public Pass { for (auto cell : module->selected_cells()) { Module *tmod = design->module(cell->type); - IdString newname = module->name.str() + "." + log_id(cell->name); + IdString newname = module->name.str() + "." + cell->name.unescape(); if (tmod == nullptr) continue; @@ -82,14 +82,14 @@ struct UniquifyPass : public Pass { if (tmod->get_bool_attribute(ID::unique) && newname == tmod->name) continue; - log("Creating module %s from %s.\n", log_id(newname), log_id(tmod)); + log("Creating module %s from %s.\n", newname.unescape(), tmod); auto smod = tmod->clone(); smod->name = newname; cell->type = newname; smod->set_bool_attribute(ID::unique); if (smod->attributes.count(ID::hdlname) == 0) - smod->attributes[ID::hdlname] = string(log_id(tmod->name)); + smod->attributes[ID::hdlname] = string(tmod->name.unescape()); design->add(smod); did_something = true; diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 10301b44a..833aa634b 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -44,7 +44,7 @@ struct rules_t void dump_config() const { - log(" bram %s # variant %d\n", log_id(name), variant); + log(" bram %s # variant %d\n", name.unescape(), variant); log(" init %d\n", init); log(" abits %d\n", abits); log(" dbits %d\n", dbits); @@ -61,16 +61,16 @@ struct rules_t void check_vectors() const { - if (groups != GetSize(ports)) log_error("Bram %s variant %d has %d groups but only %d entries in 'ports'.\n", log_id(name), variant, groups, GetSize(ports)); - if (groups != GetSize(wrmode)) log_error("Bram %s variant %d has %d groups but only %d entries in 'wrmode'.\n", log_id(name), variant, groups, GetSize(wrmode)); - if (groups != GetSize(enable)) log_error("Bram %s variant %d has %d groups but only %d entries in 'enable'.\n", log_id(name), variant, groups, GetSize(enable)); - if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", log_id(name), variant, groups, GetSize(transp)); - if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", log_id(name), variant, groups, GetSize(clocks)); - if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", log_id(name), variant, groups, GetSize(clkpol)); + if (groups != GetSize(ports)) log_error("Bram %s variant %d has %d groups but only %d entries in 'ports'.\n", name.unescape(), variant, groups, GetSize(ports)); + if (groups != GetSize(wrmode)) log_error("Bram %s variant %d has %d groups but only %d entries in 'wrmode'.\n", name.unescape(), variant, groups, GetSize(wrmode)); + if (groups != GetSize(enable)) log_error("Bram %s variant %d has %d groups but only %d entries in 'enable'.\n", name.unescape(), variant, groups, GetSize(enable)); + if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", name.unescape(), variant, groups, GetSize(transp)); + if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", name.unescape(), variant, groups, GetSize(clocks)); + if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", name.unescape(), variant, groups, GetSize(clkpol)); int group = 0; for (auto e : enable) - if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", log_id(name), variant, group, e, dbits); + if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", name.unescape(), variant, group, e, dbits); } vector make_portinfos() const @@ -100,7 +100,7 @@ struct rules_t log_assert(name == other.name); if (groups != other.groups) - log_error("Bram %s variants %d and %d have different values for 'groups'.\n", log_id(name), variant, other.variant); + log_error("Bram %s variants %d and %d have different values for 'groups'.\n", name.unescape(), variant, other.variant); if (abits != other.abits) variant_params[ID::CFG_ABITS] = abits; @@ -112,7 +112,7 @@ struct rules_t for (int i = 0; i < groups; i++) { if (ports[i] != other.ports[i]) - log_error("Bram %s variants %d and %d have different number of %c-ports.\n", log_id(name), variant, other.variant, 'A'+i); + log_error("Bram %s variants %d and %d have different number of %c-ports.\n", name.unescape(), variant, other.variant, 'A'+i); if (wrmode[i] != other.wrmode[i]) variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[i]; if (enable[i] != other.enable[i]) @@ -428,7 +428,7 @@ bool replace_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals, const transp_max = max(transp_max, pi.transp); } - log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant); + log(" Mapping to bram type %s (variant %d):\n", bram.name.unescape(), bram.variant); // bram.dump_config(); std::vector shuffle_map; @@ -715,21 +715,21 @@ grow_read_ports:; for (auto it : match.min_limits) { if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] >= it.second) continue; log(" Rule for bram type %s rejected: requirement 'min %s %d' not met.\n", - log_id(match.name), it.first.c_str(), it.second); + match.name.unescape(), it.first.c_str(), it.second); return false; } for (auto it : match.max_limits) { if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] <= it.second) continue; log(" Rule for bram type %s rejected: requirement 'max %s %d' not met.\n", - log_id(match.name), it.first.c_str(), it.second); + match.name.unescape(), it.first.c_str(), it.second); return false; } @@ -759,13 +759,13 @@ grow_read_ports:; if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << log_id(key); + ss << key.unescape(); const Const &value = rules.map_case(std::get<2>(sums.front())); if (exists && value != Const(1)) ss << "=\"" << value.decode_string() << "\""; log(" Rule for bram type %s rejected: requirement 'attribute %s ...' not met.\n", - log_id(match.name), ss.str().c_str()); + match.name.unescape(), ss.str().c_str()); return false; } } @@ -874,7 +874,7 @@ grow_read_ports:; for (int dupidx = 0; dupidx < dup_count; dupidx++) { Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", mem.memid, grid_d, grid_a, dupidx)), bram.name); - log(" Creating %s cell at grid position <%d %d %d>: %s\n", log_id(bram.name), grid_d, grid_a, dupidx, log_id(c)); + log(" Creating %s cell at grid position <%d %d %d>: %s\n", bram.name.unescape(), grid_d, grid_a, dupidx, c); for (auto &vp : variant_params) c->setParam(vp.first, vp.second); @@ -1004,7 +1004,7 @@ grow_read_ports:; void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) { - log("Processing %s.%s:\n", log_id(mem.module), log_id(mem.memid)); + log("Processing %s.%s:\n", mem.module, mem.memid.unescape()); mem.narrow(); bool cell_init = !mem.inits.empty(); @@ -1031,7 +1031,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) auto &match = rules.matches.at(i); if (!rules.brams.count(rules.matches[i].name)) - log_error("No bram description for resource %s found!\n", log_id(rules.matches[i].name)); + log_error("No bram description for resource %s found!\n", rules.matches[i].name.unescape()); for (int vi = 0; vi < GetSize(rules.brams.at(match.name)); vi++) { @@ -1047,7 +1047,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) avail_wr_ports += GetSize(bram.ports) < j ? bram.ports.at(j) : 0; } - log(" Checking rule #%d for bram type %s (variant %d):\n", i+1, log_id(bram.name), bram.variant); + log(" Checking rule #%d for bram type %s (variant %d):\n", i+1, bram.name.unescape(), bram.variant); log(" Bram geometry: abits=%d dbits=%d wports=%d rports=%d\n", bram.abits, bram.dbits, avail_wr_ports, avail_rd_ports); int dups = avail_rd_ports ? (match_properties["rports"] + avail_rd_ports - 1) / avail_rd_ports : 1; @@ -1077,11 +1077,11 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) goto next_match_rule; log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n", - log_id(match.name), awaste, dwaste, bwaste, waste, efficiency); + match.name.unescape(), awaste, dwaste, bwaste, waste, efficiency); if (cell_init && bram.init == 0) { log(" Rule #%d for bram type %s (variant %d) rejected: cannot be initialized.\n", - i+1, log_id(bram.name), bram.variant); + i+1, bram.name.unescape(), bram.variant); goto next_match_rule; } @@ -1090,11 +1090,11 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) continue; if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] >= it.second) continue; log(" Rule #%d for bram type %s (variant %d) rejected: requirement 'min %s %d' not met.\n", - i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second); + i+1, bram.name.unescape(), bram.variant, it.first.c_str(), it.second); goto next_match_rule; } @@ -1103,11 +1103,11 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) continue; if (!match_properties.count(it.first)) log_error("Unknown property '%s' in match rule for bram type %s.\n", - it.first.c_str(), log_id(match.name)); + it.first.c_str(), match.name.unescape()); if (match_properties[it.first] <= it.second) continue; log(" Rule #%d for bram type %s (variant %d) rejected: requirement 'max %s %d' not met.\n", - i+1, log_id(bram.name), bram.variant, it.first.c_str(), it.second); + i+1, bram.name.unescape(), bram.variant, it.first.c_str(), it.second); goto next_match_rule; } @@ -1137,18 +1137,18 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << log_id(key); + ss << key.unescape(); const Const &value = rules.map_case(std::get<2>(sums.front())); if (exists && value != Const(1)) ss << "=\"" << value.decode_string() << "\""; log(" Rule for bram type %s (variant %d) rejected: requirement 'attribute %s ...' not met.\n", - log_id(bram.name), bram.variant, ss.str().c_str()); + bram.name.unescape(), bram.variant, ss.str().c_str()); goto next_match_rule; } } - log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, log_id(bram.name), bram.variant); + log(" Rule #%d for bram type %s (variant %d) accepted.\n", i+1, bram.name.unescape(), bram.variant); if (or_next_if_better || !best_rule_cache.empty()) { @@ -1156,7 +1156,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) log_error("Found 'or_next_if_better' in last match rule.\n"); if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 1)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); + log(" Mapping to bram type %s failed.\n", match.name.unescape()); failed_brams.insert(pair(bram.name, bram.variant)); goto next_match_rule; } @@ -1183,12 +1183,12 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) auto &best_bram = rules.brams.at(rules.matches.at(best_rule.first).name).at(best_rule.second); if (!replace_memory(mem, rules, initvals, best_bram, rules.matches.at(best_rule.first), match_properties, 2)) - log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", log_id(best_bram.name), best_bram.variant); + log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", best_bram.name.unescape(), best_bram.variant); return; } if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 0)) { - log(" Mapping to bram type %s failed.\n", log_id(match.name)); + log(" Mapping to bram type %s failed.\n", match.name.unescape()); failed_brams.insert(pair(bram.name, bram.variant)); goto next_match_rule; } diff --git a/passes/memory/memory_libmap.cc b/passes/memory/memory_libmap.cc index 87adaa26d..a7be16577 100644 --- a/passes/memory/memory_libmap.cc +++ b/passes/memory/memory_libmap.cc @@ -204,7 +204,7 @@ struct MemMapping { if (!check_init(rdef)) continue; if (rdef.prune_rom && mem.wr_ports.empty()) { - log_debug("memory %s.%s: rejecting mapping to %s: ROM mapping disabled (prune_rom set)\n", log_id(mem.module->name), log_id(mem.memid), log_id(rdef.id)); + log_debug("memory %s.%s: rejecting mapping to %s: ROM mapping disabled (prune_rom set)\n", mem.module->name.unescape(), mem.memid.unescape(), rdef.id.unescape()); continue; } MemConfig cfg; @@ -323,7 +323,7 @@ struct MemMapping { void log_reject(const Ram &ram, std::string message) { if(ys_debug(1)) { - rejected_cfg_debug_msgs += stringf("can't map to to %s: ", log_id(ram.id)); + rejected_cfg_debug_msgs += stringf("can't map to to %s: ", ram.id.unescape()); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -338,7 +338,7 @@ struct MemMapping { rejected_cfg_debug_msgs += portname; first = false; } - rejected_cfg_debug_msgs += stringf("] of %s: ", log_id(ram.id)); + rejected_cfg_debug_msgs += stringf("] of %s: ", ram.id.unescape()); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -361,7 +361,7 @@ struct MemMapping { rejected_cfg_debug_msgs += portname; first = false; } - rejected_cfg_debug_msgs += stringf("] of %s: ", log_id(ram.id)); + rejected_cfg_debug_msgs += stringf("] of %s: ", ram.id.unescape()); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -380,7 +380,7 @@ void MemMapping::dump_configs(int stage) { default: abort(); } - log_debug("Memory %s.%s mapping candidates (%s):\n", log_id(mem.module->name), log_id(mem.memid), stage_name); + log_debug("Memory %s.%s mapping candidates (%s):\n", mem.module->name.unescape(), mem.memid.unescape(), stage_name); if (logic_ok) { log_debug("- logic fallback\n"); log_debug(" - cost: %f\n", logic_cost); @@ -391,7 +391,7 @@ void MemMapping::dump_configs(int stage) { } void MemMapping::dump_config(MemConfig &cfg) { - log_debug("- %s:\n", log_id(cfg.def->id)); + log_debug("- %s:\n", cfg.def->id.unescape()); for (auto &it: cfg.def->options) log_debug(" - option %s %s\n", it.first, log_const(it.second)); log_debug(" - emulation score: %d\n", cfg.score_emu); @@ -527,7 +527,7 @@ void MemMapping::determine_style() { auto find_attr = search_for_attribute(mem, ID::lram); if (find_attr.first && find_attr.second.as_bool()) { kind = RamKind::Huge; - log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", log_id(mem.module->name), log_id(mem.memid)); + log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", mem.module->name.unescape(), mem.memid.unescape()); return; } for (auto attr: {ID::ram_block, ID::rom_block, ID::ram_style, ID::rom_style, ID::ramstyle, ID::romstyle, ID::syn_ramstyle, ID::syn_romstyle}) { @@ -536,7 +536,7 @@ void MemMapping::determine_style() { Const val = find_attr.second; if (val == 1) { kind = RamKind::NotLogic; - log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", log_id(attr), log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", attr.unescape(), mem.module->name.unescape(), mem.memid.unescape()); return; } std::string val_s = val.decode_string(); @@ -549,20 +549,20 @@ void MemMapping::determine_style() { // Nothing. } else if (val_s == "logic" || val_s == "registers") { kind = RamKind::Logic; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to FF\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to FF\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else if (val_s == "distributed") { kind = RamKind::Distributed; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to distributed RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to distributed RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else if (val_s == "block" || val_s == "block_ram" || val_s == "ebr") { kind = RamKind::Block; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to block RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to block RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else if (val_s == "huge" || val_s == "ultra") { kind = RamKind::Huge; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to huge RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid)); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to huge RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); } else { kind = RamKind::NotLogic; style = val_s; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to %s RAM\n", log_id(attr), val_s, log_id(mem.module->name), log_id(mem.memid), val_s); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to %s RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape(), val_s); } return; } @@ -1991,7 +1991,7 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons } void MemMapping::emit(const MemConfig &cfg) { - log("mapping memory %s.%s via %s\n", log_id(mem.module->name), log_id(mem.memid), log_id(cfg.def->id)); + log("mapping memory %s.%s via %s\n", mem.module->name.unescape(), mem.memid.unescape(), cfg.def->id.unescape()); // First, handle emulations. if (cfg.emu_read_first) mem.emulate_read_first(&worker.initvals); @@ -2252,9 +2252,9 @@ struct MemoryLibMapPass : public Pass { int best = map.logic_cost; 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("Rejected candidates for mapping memory %s.%s:\n", module->name.unescape(), mem.memid.unescape()); 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)); + log_error("no valid mapping found for memory %s.%s\n", module->name.unescape(), mem.memid.unescape()); } idx = 0; best = map.cfgs[0].cost; @@ -2266,7 +2266,7 @@ struct MemoryLibMapPass : public Pass { } } if (idx == -1) { - log("using FF mapping for memory %s.%s\n", log_id(module->name), log_id(mem.memid)); + log("using FF mapping for memory %s.%s\n", module->name.unescape(), mem.memid.unescape()); } else { map.emit(map.cfgs[idx]); // Rebuild indices after modifying module diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc index 22aebb43f..54c71a0e8 100644 --- a/passes/memory/memory_memx.cc +++ b/passes/memory/memory_memx.cc @@ -60,7 +60,7 @@ struct MemoryMemxPass : public Pass { { if (port.clk_enable) log_error("Memory %s.%s has a synchronous read port. Synchronous read ports are not supported by memory_memx!\n", - log_id(module), log_id(mem.memid)); + module, mem.memid.unescape()); SigSpec addr_ok = make_addr_check(mem, port.addr); Wire *raw_rdata = module->addWire(NEW_ID, GetSize(port.data)); diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index fe884772a..fbe41431a 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -80,7 +80,7 @@ struct MemoryShareWorker if (GetSize(mem.rd_ports) <= 1) return false; - log("Consolidating read ports of memory %s.%s by address:\n", log_id(module), log_id(mem.memid)); + log("Consolidating read ports of memory %s.%s by address:\n", module, mem.memid.unescape()); bool changed = false; int abits = 0; @@ -197,7 +197,7 @@ struct MemoryShareWorker if (GetSize(mem.wr_ports) <= 1) return false; - log("Consolidating write ports of memory %s.%s by address:\n", log_id(module), log_id(mem.memid)); + log("Consolidating write ports of memory %s.%s by address:\n", module, mem.memid.unescape()); bool changed = false; int abits = 0; @@ -316,7 +316,7 @@ struct MemoryShareWorker if (eligible_ports.size() <= 1) return; - log("Consolidating write ports of memory %s.%s using sat-based resource sharing:\n", log_id(module), log_id(mem.memid)); + log("Consolidating write ports of memory %s.%s using sat-based resource sharing:\n", module, mem.memid.unescape()); // Group eligible ports by clock domain and width. diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ac47f6bf7..e737cd498 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -193,7 +193,7 @@ struct MuxpackWorker { for (auto cell : candidate_cells) { - log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); + log_debug("Considering %s (%s)\n", cell, cell->type.unescape()); SigSpec a_sig = sigmap(cell->getPort(ID::A)); if (cell->type == ID($mux)) { @@ -273,7 +273,7 @@ struct MuxpackWorker Cell *last_cell = chain[cursor+cases-1]; log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases); + module, first_cell, module, last_cell, cases); mux_count += cases; pmux_count += 1; diff --git a/passes/opt/opt_balance_tree.cc b/passes/opt/opt_balance_tree.cc index 129a27376..98d5b9928 100644 --- a/passes/opt/opt_balance_tree.cc +++ b/passes/opt/opt_balance_tree.cc @@ -279,7 +279,7 @@ struct OptBalanceTreeWorker { if (inner_cells) { // Create a tree - log_debug(" Creating tree for %s with %d sources and %d inner cells...\n", log_id(head_cell), GetSize(sources), inner_cells); + log_debug(" Creating tree for %s with %d sources and %d inner cells...\n", head_cell, GetSize(sources), inner_cells); // Build a vector of all source signals vector source_signals; @@ -369,7 +369,7 @@ struct OptBalanceTreePass : public Pass { // Log stats for (auto cell_type : cell_types) - log("Converted %d %s cells into trees.\n", cell_count[cell_type], log_id(cell_type)); + log("Converted %d %s cells into trees.\n", cell_count[cell_type], cell_type.unescape()); // Clean up Yosys::run_pass("clean -purge"); diff --git a/passes/opt/opt_clean/inits.cc b/passes/opt/opt_clean/inits.cc index 70c2ef9e2..0618e739a 100644 --- a/passes/opt/opt_clean/inits.cc +++ b/passes/opt/opt_clean/inits.cc @@ -109,7 +109,7 @@ bool remove_redundant_inits(ShardedVector wires, bool verbose) { bool did_something = false; for (RTLIL::Wire *wire : wires) { if (verbose) - log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); + log_debug(" removing redundant init attribute on %s.\n", wire); wire->attributes.erase(ID::init); did_something = true; } diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index 1a2c1fe82..b9aab1850 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -43,7 +43,7 @@ void demorgan_worker( if (GetSize(insig) < 1) return; - log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig)); + log("Inspecting %s cell %s (%d inputs)\n", cell->type.unescape(), cell->name.unescape(), GetSize(insig)); int num_inverted = 0; for(int i=0; iconnect(ff.sig_q[i], State::S0); log("Handling always-active CLR at position %d on %s (%s) from module %s (changing to const driver).\n", - i, log_id(cell), log_id(cell->type), log_id(module)); + i, cell, cell->type.unescape(), module); sr_removed = true; } else if (is_always_active(ff.sig_set[i], ff.pol_set)) { initvals.remove_init(ff.sig_q[i]); @@ -312,7 +312,7 @@ struct OptDffWorker else module->addNot(NEW_ID, ff.sig_clr[i], ff.sig_q[i]); log("Handling always-active SET at position %d on %s (%s) from module %s (changing to combinatorial circuit).\n", - i, log_id(cell), log_id(cell->type), log_id(module)); + i, cell, cell->type.unescape(), module); sr_removed = true; } else { keep_bits.push_back(i); @@ -335,7 +335,7 @@ struct OptDffWorker if (clr_inactive && signal_all_same(ff.sig_set)) { log("Removing never-active CLR on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_sr = false; ff.has_arst = true; ff.pol_arst = ff.pol_set; @@ -344,7 +344,7 @@ struct OptDffWorker changed = true; } else if (set_inactive && signal_all_same(ff.sig_clr)) { log("Removing never-active SET on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_sr = false; ff.has_arst = true; ff.pol_arst = ff.pol_clr; @@ -370,7 +370,7 @@ struct OptDffWorker if (!failed) { log("Converting CLR/SET to ARST on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_sr = false; ff.has_arst = true; ff.val_arst = val_arst_builder.build(); @@ -389,7 +389,7 @@ struct OptDffWorker // Converts constant Async Load to ARST if (is_always_inactive(ff.sig_aload, ff.pol_aload)) { log("Removing never-active async load on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_aload = false; changed = true; return false; @@ -398,7 +398,7 @@ struct OptDffWorker if (is_active(ff.sig_aload, ff.pol_aload)) { // ALOAD always active log("Handling always-active async load on %s (%s) from module %s (changing to combinatorial circuit).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.remove(); if (ff.has_sr) { @@ -433,7 +433,7 @@ struct OptDffWorker // AD is constant -> ARST if (ff.sig_ad.is_fully_const() && !ff.has_arst && !ff.has_sr) { log("Changing const-value async load to async reset on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_arst = true; ff.has_aload = false; ff.sig_arst = ff.sig_aload; @@ -450,12 +450,12 @@ struct OptDffWorker // Removes ARST if never active or replaces FF if always active if (is_inactive(ff.sig_arst, ff.pol_arst)) { log("Removing never-active ARST on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_arst = false; changed = true; } else if (is_always_active(ff.sig_arst, ff.pol_arst)) { log("Handling always-active ARST on %s (%s) from module %s (changing to const driver).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.remove(); module->connect(ff.sig_q, ff.val_arst); return true; @@ -469,12 +469,12 @@ struct OptDffWorker // Removes SRST if never active or forces D to reset value if always active if (is_inactive(ff.sig_srst, ff.pol_srst)) { log("Removing never-active SRST on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_srst = false; changed = true; } else if (is_always_active(ff.sig_srst, ff.pol_srst)) { log("Handling always-active SRST on %s (%s) from module %s (changing to const D).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_srst = false; if (!ff.ce_over_srst) ff.has_ce = false; @@ -489,7 +489,7 @@ struct OptDffWorker if (is_always_inactive(ff.sig_ce, ff.pol_ce)) { if (ff.has_srst && !ff.ce_over_srst) { log("Handling never-active EN on %s (%s) from module %s (connecting SRST instead).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.pol_ce = ff.pol_srst; ff.sig_ce = ff.sig_srst; ff.has_srst = false; @@ -497,7 +497,7 @@ struct OptDffWorker changed = true; } else if (!opt.keepdc || ff.val_init.is_fully_def()) { log("Handling never-active EN on %s (%s) from module %s (removing D path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_ce = ff.has_clk = ff.has_srst = false; changed = true; } else { @@ -507,7 +507,7 @@ struct OptDffWorker } } else if (is_active(ff.sig_ce, ff.pol_ce)) { log("Removing always-active EN on %s (%s) from module %s.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_ce = false; changed = true; } @@ -517,7 +517,7 @@ struct OptDffWorker { if (!opt.keepdc || ff.val_init.is_fully_def()) { log("Handling const CLK on %s (%s) from module %s (removing D path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_ce = ff.has_clk = ff.has_srst = false; changed = true; } else if (ff.has_ce || ff.has_srst || ff.sig_d != ff.sig_q) { @@ -532,7 +532,7 @@ struct OptDffWorker // Detect feedback loops where D is hardwired to Q if (ff.has_clk && ff.has_srst) { log("Handling D = Q on %s (%s) from module %s (conecting SRST instead).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); if (ff.has_ce && ff.ce_over_srst) { SigSpec ce = ff.pol_ce ? ff.sig_ce : create_not(ff.sig_ce, ff.is_fine); SigSpec srst = ff.pol_srst ? ff.sig_srst : create_not(ff.sig_srst, ff.is_fine); @@ -549,7 +549,7 @@ struct OptDffWorker changed = true; } else if (!opt.keepdc || ff.val_init.is_fully_def()) { log("Handling D = Q on %s (%s) from module %s (removing D path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_gclk = ff.has_clk = ff.has_ce = false; changed = true; } @@ -627,7 +627,7 @@ struct OptDffWorker dff_cells.push_back(new_cell); log("Adding SRST signal on %s (%s) from module %s (D = %s, Q = %s, rval = %s).\n", - log_id(cell), log_id(cell->type), log_id(module), + cell, cell->type.unescape(), module, log_signal(new_ff.sig_d), log_signal(new_ff.sig_q), log_signal(new_ff.val_srst)); } @@ -701,7 +701,7 @@ struct OptDffWorker dff_cells.push_back(new_cell); log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n", - log_id(cell), log_id(cell->type), log_id(module), + cell, cell->type.unescape(), module, log_signal(new_ff.sig_d), log_signal(new_ff.sig_q)); } @@ -768,7 +768,7 @@ struct OptDffWorker if (ff.has_aload && !ff.has_clk && ff.sig_ad == ff.sig_q) { log("Handling AD = Q on %s (%s) from module %s (removing async load path).\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); ff.has_aload = false; changed = true; } @@ -885,7 +885,7 @@ struct OptDffWorker } log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", - val ? 1 : 0, i, log_id(cell), log_id(cell->type), log_id(module)); + val ? 1 : 0, i, cell, cell->type.unescape(), module); // Replace the Q output with the constant value initvals.remove_init(ff.sig_q[i]); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 2c040b09d..48a9aa1da 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -88,7 +88,7 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct) } } - log_debug("Setting undriven signal in %s to constant: %s = %s\n", log_id(module), log_signal(sig), log_signal(val)); + log_debug("Setting undriven signal in %s to constant: %s = %s\n", module, log_signal(sig), log_signal(val)); module->connect(sig, val); did_something = true; } @@ -105,11 +105,11 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct) initval.set(i, State::Sx); } if (initval.is_fully_undef()) { - log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); + log_debug("Removing init attribute from %s/%s.\n", module, wire); wire->attributes.erase(ID::init); did_something = true; } else if (initval != wire->attributes.at(ID::init)) { - log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval)); + log_debug("Updating init attribute on %s/%s: %s\n", module, wire, log_signal(initval)); wire->attributes[ID::init] = initval; did_something = true; } @@ -196,7 +196,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ return false; log_debug("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n", - log_id(cell->type), log_id(cell), log_id(module)); + cell->type.unescape(), cell, module); for (int i = 0; i < GRP_N; i++) { @@ -224,7 +224,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ new_a.replace(dict{{State::Sx, State::S1}, {State::Sz, State::S1}}, &new_b); else log_abort(); } - log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); + log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), cell->type.unescape(), log_signal(new_a)); module->connect(new_y, new_b); module->connect(new_conn); continue; @@ -261,7 +261,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ } } if (!undef_y.empty()) { - log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), log_id(cell->type), log_signal(undef_a)); + log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(undef_b), cell->type.unescape(), log_signal(undef_a)); module->connect(undef_y, undef_b); if (def_y.empty()) { module->connect(new_conn); @@ -292,7 +292,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ module->connect(new_conn); - log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a)); + log_debug(" New cell `%s': A=%s", c, log_signal(new_a)); if (b_name == ID::B) log_debug(", B=%s", log_signal(new_b)); log_debug("\n"); @@ -308,7 +308,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", - log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module), + port.unescape(), cell->type.unescape(), cell, cell->module, log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); cell->setParam(param, !cell->getParam(param).as_bool()); @@ -337,7 +337,7 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", - log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module), + port.unescape(), cell->type.unescape(), cell, cell->module, log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); cell->type = cell->type == type1 ? type2 : type1; @@ -511,7 +511,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (!cells.sort()) { // There might be a combinational loop, or there might be constants on the output of cells. 'check' may find out more. // ...unless this is a coarse-grained cell loop, but not a bit loop, in which case it won't, and all is good. - log("Couldn't topologically sort cells, optimizing module %s may take a longer time.\n", log_id(module)); + log("Couldn't topologically sort cells, optimizing module %s may take a longer time.\n", module); } for (auto cell : cells.sorted) @@ -631,7 +631,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { if (cell->type == ID($reduce_xnor)) { log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n", - log_id(cell->type), log_id(cell->name), log_id(module)); + cell->type.unescape(), cell->name.unescape(), module); cell->type = ID($not); did_something = true; } else { @@ -651,7 +651,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (a_fully_const != b_fully_const) { log_debug("Replacing %s cell `%s' in module `%s' having one fully constant input\n", - log_id(cell->type), log_id(cell->name), log_id(module)); + cell->type.unescape(), cell->name.unescape(), module); RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); int width = GetSize(cell->getPort(ID::Y)); @@ -932,7 +932,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescape(), cell, module); SigSpec new_a = sig_a.extract_end(i); SigSpec new_b = sig_b.extract_end(i); if (new_a.empty() && is_signed) @@ -988,7 +988,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Stripping %d LSB bits of %s cell %s in module %s.\n", i, cell->type.unescape(), cell, module); SigSpec new_a = sig_a.extract_end(i); SigSpec new_b = sig_b.extract_end(i); if (new_a.empty() && is_signed) @@ -1062,7 +1062,7 @@ skip_fine_alu: } if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID::S))) != 0) { - log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", cell->type.unescape(), cell, module); RTLIL::SigSpec tmp = cell->getPort(ID::A); cell->setPort(ID::A, cell->getPort(ID::B)); cell->setPort(ID::B, tmp); @@ -1241,7 +1241,7 @@ skip_fine_alu: RTLIL::SigSpec input = b; ACTION_DO(ID::Y, cell->getPort(ID::A)); } else { - log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescape(), cell, module); cell->type = ID($not); cell->parameters.erase(ID::B_WIDTH); cell->parameters.erase(ID::B_SIGNED); @@ -1255,8 +1255,8 @@ skip_fine_alu: if (cell->type.in(ID($eq), ID($ne)) && (assign_map(cell->getPort(ID::A)).is_fully_zero() || assign_map(cell->getPort(ID::B)).is_fully_zero())) { - log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), - log_id(module), cell->type == ID($eq) ? "$logic_not" : "$reduce_bool"); + log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", cell->type.unescape(), cell, + module, cell->type == ID($eq) ? "$logic_not" : "$reduce_bool"); cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool); if (assign_map(cell->getPort(ID::A)).is_fully_zero()) { cell->setPort(ID::A, cell->getPort(ID::B)); @@ -1303,7 +1303,7 @@ skip_fine_alu: } log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n", - log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID::B))), shift_bits, log_id(module), log_signal(sig_y)); + cell->type.unescape(), cell, log_signal(assign_map(cell->getPort(ID::B))), shift_bits, module, log_signal(sig_y)); module->connect(cell->getPort(ID::Y), sig_y); module->remove(cell); @@ -1428,7 +1428,7 @@ skip_identity: if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S1 && cell->getPort(ID::B) == State::S0) { - log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", cell->type.unescape(), cell, module); cell->setPort(ID::A, cell->getPort(ID::S)); cell->unsetPort(ID::B); cell->unsetPort(ID::S); @@ -1446,7 +1446,7 @@ skip_identity: } if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0) { - log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", cell->type.unescape(), cell, module); cell->setPort(ID::A, cell->getPort(ID::S)); cell->unsetPort(ID::S); if (cell->type == ID($mux)) { @@ -1465,7 +1465,7 @@ skip_identity: } if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) { - log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", cell->type.unescape(), cell, module); cell->setPort(ID::B, cell->getPort(ID::S)); cell->unsetPort(ID::S); if (cell->type == ID($mux)) { @@ -1515,7 +1515,7 @@ skip_identity: } if (cell->getPort(ID::S).size() != new_s.size()) { log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", - GetSize(cell->getPort(ID::S)) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); + GetSize(cell->getPort(ID::S)) - GetSize(new_s), cell->type.unescape(), cell, module); cell->setPort(ID::A, new_a); cell->setPort(ID::B, new_b); cell->setPort(ID::S, new_s); @@ -2021,7 +2021,7 @@ skip_alu_split: Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig)); log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n", - log_id(cell), log_id(module), log_signal(y_value)); + cell, module, log_signal(y_value)); module->connect(y_sig, y_value); module->remove(cell); @@ -2033,7 +2033,7 @@ skip_alu_split: if (redundant_bits) { log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n", - redundant_bits, log_id(cell->type), log_id(cell), log_id(module)); + redundant_bits, cell->type.unescape(), cell, module); cell->setPort(ID::A, sig_a); cell->setPort(ID::B, sig_b); @@ -2172,7 +2172,7 @@ skip_alu_split: if (replace || remove) { log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n", - log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); + cell->type.unescape(), cell, condition.c_str(), replacement.c_str()); if (replace) module->connect(cell->getPort(ID::Y), replace_sig); module->remove(cell); @@ -2295,7 +2295,7 @@ struct OptExprPass : public Pass { NewCellTypes ct(design); for (auto module : design->selected_modules()) { - log("Optimizing module %s.\n", log_id(module)); + log("Optimizing module %s.\n", module); if (undriven) { did_something = false; diff --git a/passes/opt/opt_hier.cc b/passes/opt/opt_hier.cc index 5c3b09b31..532bcad63 100644 --- a/passes/opt/opt_hier.cc +++ b/passes/opt/opt_hier.cc @@ -101,7 +101,7 @@ struct ModuleIndex { if (!port || (!port->port_input && !port->port_output) || port->width != value.size()) { log_error("Port %s connected on instance %s not found in module %s" " or width is not matching\n", - log_id(port_name), log_id(instantiation), log_id(module)); + port_name.unescape(), instantiation, module); } if (port->port_input && port->port_output) { @@ -145,12 +145,12 @@ struct ModuleIndex { if (nunused > 0) { log("Disconnected %d input bits of instance '%s' (type '%s') in '%s'\n", - nunused, log_id(instantiation), log_id(instantiation->type), log_id(parent.module)); + nunused, instantiation, instantiation->type.unescape(), parent.module); changed = true; } if (nconstants > 0) { log("Substituting constant for %d output bits of instance '%s' (type '%s') in '%s'\n", - nconstants, log_id(instantiation), log_id(instantiation->type), log_id(parent.module)); + nconstants, instantiation, instantiation->type.unescape(), parent.module); changed = true; } } @@ -189,7 +189,7 @@ struct ModuleIndex { if (ntie_togethers > 0) { log("Replacing %d output bits with tie-togethers on instance '%s' of '%s' in '%s'\n", - ntie_togethers, log_id(instantiation), log_id(instantiation->type), log_id(parent.module)); + ntie_togethers, instantiation, instantiation->type.unescape(), parent.module); changed = true; } @@ -290,7 +290,7 @@ struct UsageData { if (!port || (!port->port_input && !port->port_output) || port->width != value.size()) { log_error("Port %s connected on instance %s not found in module %s" " or width is not matching\n", - log_id(port_name), log_id(instance), log_id(module)); + port_name.unescape(), instance, module); } if (port->port_input && port->port_output) { @@ -347,7 +347,7 @@ struct UsageData { }; module->rewrite_sigspecs(disconnect_rewrite); for (auto chunk : disconnect_outputs.chunks()) { - log("Disconnected unused output terminal '%s' in module '%s'\n", log_signal(chunk), log_id(module)); + log("Disconnected unused output terminal '%s' in module '%s'\n", log_signal(chunk), module); did_something = true; module->connect(chunk, SigSpec(RTLIL::Sx, chunk.size())); } @@ -368,7 +368,7 @@ struct UsageData { SigSpec const_ = chunk; const_.replace(constant_inputs); log("Substituting constant %s for input terminal '%s' in module '%s'\n", - log_signal(const_), log_signal(chunk), log_id(module)); + log_signal(const_), log_signal(chunk), module); } // Propagate tied-together inputs @@ -397,7 +397,7 @@ struct UsageData { module->rewrite_sigspecs(ties_rewrite); if (applied_ties.size()) { log("Replacing %zu input terminal bits with tie-togethers in module '%s'\n", - applied_ties.size(), log_id(module)); + applied_ties.size(), module); } return did_something; } @@ -433,7 +433,7 @@ struct OptHierPass : Pass { dict indices; for (auto module : d->modules()) { - log_debug("Building index for %s\n", log_id(module)); + log_debug("Building index for %s\n", module); indices.emplace(module->name, ModuleIndex(module)); } @@ -442,14 +442,14 @@ struct OptHierPass : Pass { if (module->get_bool_attribute(ID::top)) continue; - log_debug("Starting usage data for %s\n", log_id(module)); + log_debug("Starting usage data for %s\n", module); usage_datas.emplace(module->name, UsageData(module)); } for (auto module : d->modules()) { for (auto cell : module->cells()) { if (usage_datas.count(cell->type)) { - log_debug("Account for instance %s of %s in %s\n", log_id(cell), log_id(cell->type), log_id(module)); + log_debug("Account for instance %s of %s in %s\n", cell, cell->type.unescape(), module); usage_datas.at(cell->type).refine(cell, indices.at(module->name)); } } @@ -460,13 +460,13 @@ struct OptHierPass : Pass { ModuleIndex &parent_index = indices.at(module->name); if (usage_datas.count(module->name)) { - log_debug("Applying usage data changes to %s\n", log_id(module)); + log_debug("Applying usage data changes to %s\n", module); did_something |= usage_datas.at(module->name).apply_changes(parent_index); } for (auto cell : module->cells()) { if (indices.count(cell->type)) { - log_debug("Applying changes to instance %s of %s in %s\n", log_id(cell), log_id(cell->type), log_id(module)); + log_debug("Applying changes to instance %s of %s in %s\n", cell, cell->type.unescape(), module); did_something |= indices.at(cell->type).apply_changes(parent_index, cell); } } diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index c0a017748..3768eed32 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -121,7 +121,7 @@ struct OptLutWorker SigSpec lut_input = cell->getPort(ID::A); int lut_arity = 0; - log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); + log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, module, cell); luts.insert(cell); // First, find all dedicated logic we're connected to. This results in an overapproximation @@ -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, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, module, lut_dlogic.second); log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first); legal = false; break; @@ -173,7 +173,7 @@ 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, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, module, 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, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type, module, lut_dlogic.second); lut_legal_dlogics.insert(lut_dlogic); for (auto &dlogic_conn : dlogic_map) lut_dlogic_inputs.insert(dlogic_conn.first); @@ -258,7 +258,7 @@ struct OptLutWorker if (const0_match || const1_match || input_match != -1) { - log_debug("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); + log_debug("Found redundant cell %s.%s.\n", module, lut); SigBit value; if (const0_match) @@ -341,7 +341,7 @@ struct OptLutWorker int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; - log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", module, lutA, module, lutB); if (index.query_is_output(lutA->getPort(ID::Y))) { diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc index 580853b51..c1355da25 100644 --- a/passes/opt/opt_lut_ins.cc +++ b/passes/opt/opt_lut_ins.cc @@ -64,7 +64,7 @@ struct OptLutInsPass : public Pass { for (auto module : design->selected_modules()) { - log("Optimizing LUTs in %s.\n", log_id(module)); + log("Optimizing LUTs in %s.\n", module); std::vector remove_cells; // Gather LUTs. @@ -181,7 +181,7 @@ struct OptLutInsPass : public Pass { } if (!doit) continue; - log(" Optimizing lut %s (%d -> %d)\n", log_id(cell), GetSize(inputs), GetSize(new_inputs)); + log(" Optimizing lut %s (%d -> %d)\n", cell, GetSize(inputs), GetSize(new_inputs)); if (techname == "lattice" || techname == "ecp5") { // Pad the LUT to 4 inputs, adding consts from the front. int extra = 4 - GetSize(new_inputs); diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc index 9c5a6d83e..0bd97f5f9 100644 --- a/passes/opt/opt_mem.cc +++ b/passes/opt/opt_mem.cc @@ -108,13 +108,13 @@ struct OptMemPass : public Pass { } State bit; if (!always_0[i]) { - log("%s.%s: removing const-1 lane %d\n", log_id(module->name), log_id(mem.memid), i); + log("%s.%s: removing const-1 lane %d\n", module->name.unescape(), mem.memid.unescape(), i); bit = State::S1; } else if (!always_1[i]) { - log("%s.%s: removing const-0 lane %d\n", log_id(module->name), log_id(mem.memid), i); + log("%s.%s: removing const-0 lane %d\n", module->name.unescape(), mem.memid.unescape(), i); bit = State::S0; } else { - log("%s.%s: removing const-x lane %d\n", log_id(module->name), log_id(mem.memid), i); + log("%s.%s: removing const-x lane %d\n", module->name.unescape(), mem.memid.unescape(), i); bit = State::Sx; } // Reconnect read port data. diff --git a/passes/opt/opt_mem_feedback.cc b/passes/opt/opt_mem_feedback.cc index 20a2a79ed..fe5157934 100644 --- a/passes/opt/opt_mem_feedback.cc +++ b/passes/opt/opt_mem_feedback.cc @@ -163,7 +163,7 @@ struct OptMemFeedbackWorker { auto &port = mem.wr_ports[i]; - log(" Analyzing %s.%s write port %d.\n", log_id(module), log_id(mem.memid), i); + log(" Analyzing %s.%s write port %d.\n", module, mem.memid.unescape(), i); for (int sub = 0; sub < (1 << port.wide_log2); sub++) { @@ -232,7 +232,7 @@ struct OptMemFeedbackWorker // Okay, let's do it. - log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", log_id(module), log_id(mem.memid)); + log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", module, mem.memid.unescape()); // If a write port has a feedback path that we're about to bypass, // but also has priority over some other write port, the feedback diff --git a/passes/opt/opt_mem_widen.cc b/passes/opt/opt_mem_widen.cc index 95e01088c..f642666db 100644 --- a/passes/opt/opt_mem_widen.cc +++ b/passes/opt/opt_mem_widen.cc @@ -65,7 +65,7 @@ struct OptMemWidenPass : public Pass { factor_log2 = port.wide_log2; if (factor_log2 == 0) continue; - log("Widening base width of memory %s in module %s by factor %d.\n", log_id(mem.memid), log_id(module->name), 1 << factor_log2); + log("Widening base width of memory %s in module %s by factor %d.\n", mem.memid.unescape(), module->name.unescape(), 1 << factor_log2); total_count++; // The inits are too messy to expand one-by-one, for they may // collide with one another after expansion. Just hit it with diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 8bf151e71..af77ff46d 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -229,7 +229,7 @@ struct OptMuxtreeWorker for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++) if (root_muxes.at(mux_idx)) { - log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : ""); + log_debug(" Root of a mux tree: %s%s\n", mux2info[mux_idx].cell, root_enable_muxes.at(mux_idx) ? " (pure)" : ""); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); if (glob_evals_left == 0) { @@ -240,7 +240,7 @@ struct OptMuxtreeWorker while (!root_mux_rerun.empty()) { int mux_idx = *root_mux_rerun.begin(); - log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell)); + log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", mux2info[mux_idx].cell); log_assert(root_enable_muxes.at(mux_idx)); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); @@ -437,7 +437,7 @@ struct OptMuxtreeWorker // Ran out of subtree depth, re-eval this input tree in the next re-run root_mux_rerun.insert(m); root_enable_muxes.at(m) = true; - log_debug(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell)); + log_debug(" Removing pure flag from root mux %s.\n", mux2info[m].cell); } else { auto new_limits = limits.subtree(); // Since our knowledge includes assumption, @@ -517,8 +517,8 @@ struct OptMuxtreeWorker } if (did_something) { - log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", log_id(portname), - log_id(muxinfo.cell), log_signal(muxinfo.cell->getPort(portname)), log_signal(sig)); + log(" Replacing known input bits on port %s of cell %s: %s -> %s\n", portname.unescape(), + muxinfo.cell, log_signal(muxinfo.cell->getPort(portname)), log_signal(sig)); muxinfo.cell->setPort(portname, sig); } } @@ -530,7 +530,7 @@ struct OptMuxtreeWorker glob_evals_left--; muxinfo_t &muxinfo = mux2info[mux_idx]; - log_debug("\t\teval %s (replace %d enable %d)\n", log_id(muxinfo.cell), limits.do_replace_known, limits.do_mark_ports_observable); + log_debug("\t\teval %s (replace %d enable %d)\n", muxinfo.cell, limits.do_replace_known, limits.do_mark_ports_observable); // set input ports to constants if we find known active or inactive signals if (limits.do_replace_known) { diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index bf9569d99..b213048aa 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -560,9 +560,9 @@ struct OptSharePass : public Pass { log(" Found cells that share an operand and can be merged by moving the %s %s in front " "of " "them:\n", - log_id(shared.mux->type), log_id(shared.mux)); + shared.mux->type.unescape(), shared.mux); for (const auto& op : shared.ports) - log(" %s\n", log_id(op.op)); + log(" %s\n", op.op); log("\n"); merge_operators(module, shared.mux, shared.ports, shared.shared_operand, sigmap); diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 4a0864df0..6668ff2de 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -390,7 +390,7 @@ struct Pmux2ShiftxPass : public Pass { if (verbose) { printed_pmux_header = true; - log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log("Inspecting $pmux cell %s/%s.\n", module, cell); log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); } @@ -441,7 +441,7 @@ struct Pmux2ShiftxPass : public Pass { if (!printed_pmux_header) { printed_pmux_header = true; - log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log("Inspecting $pmux cell %s/%s.\n", module, cell); log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); } @@ -714,7 +714,7 @@ struct Pmux2ShiftxPass : public Pass { Cell *c = module->addShiftx(NEW_ID, data, shifted_cmp, outsig, false, src); updated_S.append(en); updated_B.append(outsig); - log(" created $shiftx cell %s.\n", log_id(c)); + log(" created $shiftx cell %s.\n", c); // remove this sig and continue with the next block seldb.erase(sig); @@ -799,7 +799,7 @@ struct OnehotPass : public Pass { continue; if (verbose) - log("Checking $eq(%s, %s) cell %s/%s.\n", log_signal(A), log_signal(B), log_id(module), log_id(cell)); + log("Checking $eq(%s, %s) cell %s/%s.\n", log_signal(A), log_signal(B), module, cell); if (!onehot_db.query(A)) { if (verbose) @@ -831,7 +831,7 @@ struct OnehotPass : public Pass { if (verbose) log(" replacing with constant 0 driver.\n"); else - log("Replacing one-hot $eq(%s, %s) cell %s/%s with constant 0 driver.\n", log_signal(A), log_signal(B), log_id(module), log_id(cell)); + log("Replacing one-hot $eq(%s, %s) cell %s/%s with constant 0 driver.\n", log_signal(A), log_signal(B), module, cell); module->connect(Y, SigSpec(1, GetSize(Y))); } else @@ -840,7 +840,7 @@ struct OnehotPass : public Pass { if (verbose) log(" replacing with signal %s.\n", log_signal(sig)); else - log("Replacing one-hot $eq(%s, %s) cell %s/%s with signal %s.\n",log_signal(A), log_signal(B), log_id(module), log_id(cell), log_signal(sig)); + log("Replacing one-hot $eq(%s, %s) cell %s/%s with signal %s.\n",log_signal(A), log_signal(B), module, cell, log_signal(sig)); sig.extend_u0(GetSize(Y)); module->connect(Y, sig); } diff --git a/passes/opt/share.cc b/passes/opt/share.cc index bc363e251..119243d48 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -958,7 +958,7 @@ struct ShareWorker optimize_activation_patterns(activation_patterns_cache[cell]); if (activation_patterns_cache[cell].empty()) { - log("%sFound cell that is never activated: %s\n", indent, log_id(cell)); + log("%sFound cell that is never activated: %s\n", indent, cell); RTLIL::SigSpec cell_outputs = modwalker.cell_outputs[cell]; module->connect(RTLIL::SigSig(cell_outputs, RTLIL::SigSpec(RTLIL::State::Sx, cell_outputs.size()))); cells_to_remove.insert(cell); @@ -1123,7 +1123,7 @@ struct ShareWorker for (auto &loop : toposort.loops) { log("### loop ###\n"); for (auto &c : loop) - log("%s (%s)\n", log_id(c), log_id(c->type)); + log("%s (%s)\n", c, c->type.unescape()); } return found_scc; @@ -1240,14 +1240,14 @@ struct ShareWorker return; log("Found %d cells in module %s that may be considered for resource sharing.\n", - GetSize(shareable_cells), log_id(module)); + GetSize(shareable_cells), module); while (!shareable_cells.empty() && config.limit != 0) { RTLIL::Cell *cell = *shareable_cells.begin(); shareable_cells.erase(cell); - log(" Analyzing resource sharing options for %s (%s):\n", log_id(cell), log_id(cell->type)); + log(" Analyzing resource sharing options for %s (%s):\n", cell, cell->type.unescape()); const pool &cell_activation_patterns = find_cell_activation_patterns(cell, " "); RTLIL::SigSpec cell_activation_signals = bits_from_activation_patterns(cell_activation_patterns); @@ -1275,12 +1275,12 @@ struct ShareWorker log(" Found %d candidates:", GetSize(candidates)); for (auto c : candidates) - log(" %s", log_id(c)); + log(" %s", c); log("\n"); for (auto other_cell : candidates) { - log(" Analyzing resource sharing with %s (%s):\n", log_id(other_cell), log_id(other_cell->type)); + log(" Analyzing resource sharing with %s (%s):\n", other_cell, other_cell->type.unescape()); const pool &other_cell_activation_patterns = find_cell_activation_patterns(other_cell, " "); RTLIL::SigSpec other_cell_activation_signals = bits_from_activation_patterns(other_cell_activation_patterns); @@ -1332,13 +1332,13 @@ struct ShareWorker RTLIL::SigSpec all_ctrl_signals; for (auto &p : filtered_cell_activation_patterns) { - log(" Activation pattern for cell %s: %s = %s\n", log_id(cell), log_signal(p.first), log_signal(p.second)); + log(" Activation pattern for cell %s: %s = %s\n", cell, log_signal(p.first), log_signal(p.second)); cell_active.push_back(qcsat.ez->vec_eq(qcsat.importSig(p.first), qcsat.importSig(p.second))); all_ctrl_signals.append(p.first); } for (auto &p : filtered_other_cell_activation_patterns) { - log(" Activation pattern for cell %s: %s = %s\n", log_id(other_cell), log_signal(p.first), log_signal(p.second)); + log(" Activation pattern for cell %s: %s = %s\n", other_cell, log_signal(p.first), log_signal(p.second)); other_cell_active.push_back(qcsat.ez->vec_eq(qcsat.importSig(p.first), qcsat.importSig(p.second))); all_ctrl_signals.append(p.first); } @@ -1349,13 +1349,13 @@ struct ShareWorker qcsat.prepare(); if (!qcsat.ez->solve(sub1)) { - log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(cell)); + log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", cell); cells_to_remove.insert(cell); break; } if (!qcsat.ez->solve(sub2)) { - log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(other_cell)); + log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", other_cell); cells_to_remove.insert(other_cell); shareable_cells.erase(other_cell); continue; @@ -1391,20 +1391,20 @@ struct ShareWorker if (restrict_activation_patterns(optimized_cell_activation_patterns, optimized_other_cell_activation_patterns)) { for (auto &p : optimized_cell_activation_patterns) - log(" Simplified activation pattern for cell %s: %s = %s\n", log_id(cell), log_signal(p.first), log_signal(p.second)); + log(" Simplified activation pattern for cell %s: %s = %s\n", cell, log_signal(p.first), log_signal(p.second)); for (auto &p : optimized_other_cell_activation_patterns) - log(" Simplified activation pattern for cell %s: %s = %s\n", log_id(other_cell), log_signal(p.first), log_signal(p.second)); + log(" Simplified activation pattern for cell %s: %s = %s\n", other_cell, log_signal(p.first), log_signal(p.second)); } } if (find_in_input_cone(cell, other_cell)) { - log(" Sharing not possible: %s is in input cone of %s.\n", log_id(other_cell), log_id(cell)); + log(" Sharing not possible: %s is in input cone of %s.\n", other_cell, cell); continue; } if (find_in_input_cone(other_cell, cell)) { - log(" Sharing not possible: %s is in input cone of %s.\n", log_id(cell), log_id(other_cell)); + log(" Sharing not possible: %s is in input cone of %s.\n", cell, other_cell); continue; } @@ -1424,14 +1424,14 @@ struct ShareWorker if (cell_select_score <= other_cell_select_score) { RTLIL::SigSpec act = make_cell_activation_logic(optimized_cell_activation_patterns, supercell_aux); supercell = make_supercell(cell, other_cell, act, supercell_aux); - log(" Activation signal for %s: %s\n", log_id(cell), log_signal(act)); + log(" Activation signal for %s: %s\n", cell, log_signal(act)); } else { RTLIL::SigSpec act = make_cell_activation_logic(optimized_other_cell_activation_patterns, supercell_aux); supercell = make_supercell(other_cell, cell, act, supercell_aux); - log(" Activation signal for %s: %s\n", log_id(other_cell), log_signal(act)); + log(" Activation signal for %s: %s\n", other_cell, log_signal(act)); } - log(" New cell: %s (%s)\n", log_id(supercell), log_id(supercell->type)); + log(" New cell: %s (%s)\n", supercell, supercell->type.unescape()); cells_to_remove.insert(cell); cells_to_remove.insert(other_cell); @@ -1476,9 +1476,9 @@ struct ShareWorker } if (!cells_to_remove.empty()) { - log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), log_id(module)); + log("Removing %d cells in module %s:\n", GetSize(cells_to_remove), module); for (auto c : cells_to_remove) { - log(" Removing cell %s (%s).\n", log_id(c), log_id(c->type)); + log(" Removing cell %s (%s).\n", c, c->type.unescape()); remove_cell(c); } } diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 359c76d42..d70299ab8 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -104,14 +104,14 @@ struct WreduceWorker sig_removed.append(bits_removed[i]); if (GetSize(bits_removed) == GetSize(sig_y)) { - log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape()); module->connect(sig_y, sig_removed); module->remove(cell); return; } log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", - GetSize(sig_removed), GetSize(sig_y), log_id(module), log_id(cell), log_id(cell->type)); + GetSize(sig_removed), GetSize(sig_y), module, cell, cell->type.unescape()); int n_removed = GetSize(sig_removed); int n_kept = GetSize(sig_y) - GetSize(sig_removed); @@ -204,13 +204,13 @@ struct WreduceWorker return; if (GetSize(sig_q) == 0) { - log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape()); module->remove(cell); return; } log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); for (auto bit : sig_d) work_queue_bits.insert(bit); @@ -258,7 +258,7 @@ struct WreduceWorker if (bits_removed) { log("Removed top %d bits (of %d) from port %c of cell %s.%s (%s).\n", - bits_removed, GetSize(sig) + bits_removed, port, log_id(module), log_id(cell), log_id(cell->type)); + bits_removed, GetSize(sig) + bits_removed, port, module, cell, cell->type.unescape()); cell->setPort(stringf("\\%c", port), sig); did_something = true; } @@ -331,7 +331,7 @@ struct WreduceWorker if (!port_a_signed && !port_b_signed && signed_cost < unsigned_cost) { log("Converting cell %s.%s (%s) from unsigned to signed.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 1); cell->setParam(ID::B_SIGNED, 1); port_a_signed = true; @@ -339,7 +339,7 @@ struct WreduceWorker did_something = true; } else if (port_a_signed && port_b_signed && unsigned_cost < signed_cost) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 0); cell->setParam(ID::B_SIGNED, 0); port_a_signed = false; @@ -359,7 +359,7 @@ struct WreduceWorker if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 && GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 0); cell->setParam(ID::B_SIGNED, 0); port_a_signed = false; @@ -372,7 +372,7 @@ struct WreduceWorker SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)); if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", - log_id(module), log_id(cell), log_id(cell->type)); + module, cell, cell->type.unescape()); cell->setParam(ID::A_SIGNED, 0); port_a_signed = false; did_something = true; @@ -431,14 +431,14 @@ struct WreduceWorker } if (GetSize(sig) == 0) { - log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removed cell %s.%s (%s).\n", module, cell, cell->type.unescape()); module->remove(cell); return; } if (bits_removed) { log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", - bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); + bits_removed, GetSize(sig) + bits_removed, module, cell, cell->type.unescape()); cell->setPort(ID::Y, sig); did_something = true; } @@ -510,7 +510,7 @@ struct WreduceWorker if (complete_wires[mi.sigmap(w).extract(0, GetSize(w) - unused_top_bits)]) continue; - log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), log_id(module), log_id(w)); + log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, GetSize(w), module, w); Wire *nw = module->addWire(NEW_ID, GetSize(w) - unused_top_bits); module->connect(nw, SigSpec(w).extract(0, GetSize(nw))); module->swap_names(w, nw); @@ -603,7 +603,7 @@ struct WreducePass : public Pass { } if (original_a_width != GetSize(A)) { log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n", - original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type)); + original_a_width-GetSize(A), original_a_width, module, c, c->type.unescape()); c->setPort(ID::A, A); c->setParam(ID::A_WIDTH, GetSize(A)); } @@ -619,7 +619,7 @@ struct WreducePass : public Pass { } if (original_b_width != GetSize(B)) { log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n", - original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type)); + original_b_width-GetSize(B), original_b_width, module, c, c->type.unescape()); c->setPort(ID::B, B); c->setParam(ID::B_WIDTH, GetSize(B)); } @@ -635,7 +635,7 @@ struct WreducePass : public Pass { log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", cur_addrbits-max_addrbits, cur_addrbits, c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init", - log_id(module), log_id(c), log_id(memid)); + module, c, memid.unescape()); c->setParam(ID::ABITS, max_addrbits); c->setPort(ID::ADDR, c->getPort(ID::ADDR).extract(0, max_addrbits)); } diff --git a/passes/pmgen/generate.h b/passes/pmgen/generate.h index 85e208774..e44ff58e8 100644 --- a/passes/pmgen/generate.h +++ b/passes/pmgen/generate.h @@ -106,7 +106,7 @@ void generate_pattern(std::function)> run, const if (found_match) { Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d", pmclass, pattern, modcnt++)); - log("Creating module %s with %d cells.\n", log_id(m), cellcnt); + log("Creating module %s with %d cells.\n", m, cellcnt); mod->cloneInto(m); pmtest_addports(m); mods.push_back(m); @@ -126,7 +126,7 @@ void generate_pattern(std::function)> run, const } Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern)); - log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods)); + log("Creating module %s with %d cells.\n", m, GetSize(mods)); for (auto mod : mods) { Cell *c = m->addCell(mod->name, mod->name); for (auto port : mod->ports) { diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index f6d6a3f93..18bc12346 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -37,7 +37,7 @@ void reduce_chain(test_pmgen_pm &pm) if (ud.longest_chain.empty()) return; - log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), st.first->type.unescape()); SigSpec A; SigSpec Y = ud.longest_chain.front().first->getPort(ID::Y); @@ -51,7 +51,7 @@ void reduce_chain(test_pmgen_pm &pm) } else { A.append(cell->getPort(it.second == ID::A ? ID::B : ID::A)); } - log(" %s\n", log_id(cell)); + log(" %s\n", cell); pm.autoremove(cell); } @@ -66,7 +66,7 @@ void reduce_chain(test_pmgen_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } void reduce_tree(test_pmgen_pm &pm) @@ -81,8 +81,8 @@ void reduce_tree(test_pmgen_pm &pm) SigSpec Y = st.first->getPort(ID::Y); pm.autoremove(st.first); - log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type), - GetSize(A), log_signal(Y), log_id(st.first)); + log("Found %s tree with %d leaves for %s (%s).\n", st.first->type.unescape(), + GetSize(A), log_signal(Y), st.first); Cell *c; @@ -95,7 +95,7 @@ void reduce_tree(test_pmgen_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } void opt_eqpmux(test_pmgen_pm &pm) @@ -109,11 +109,11 @@ void opt_eqpmux(test_pmgen_pm &pm) SigSpec NE = st.pmux->getPort(ID::B).extract(st.pmux_slice_ne*width, width); log("Found eqpmux circuit driving %s (eq=%s, ne=%s, pmux=%s).\n", - log_signal(Y), log_id(st.eq), log_id(st.ne), log_id(st.pmux)); + log_signal(Y), st.eq, st.ne, st.pmux); pm.autoremove(st.pmux); Cell *c = pm.module->addMux(NEW_ID, NE, EQ, st.eq->getPort(ID::Y), Y); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } struct TestPmgenPass : public Pass { diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index 92d8d0569..f754bc948 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -215,7 +215,7 @@ void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable); if (!en.is_fully_zero()) { log_error("Async reset %s causes memory write to %s.\n", - log_signal(sync->signal), log_id(memwr.memid)); + log_signal(sync->signal), memwr.memid.unescape()); } apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address); apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data); diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 8cccb96c4..0df9fc0b2 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -216,7 +216,7 @@ struct ProcCleanPass : public Pass { if (proc->syncs.size() == 0 && proc->root_case.switches.size() == 0 && proc->root_case.actions.size() == 0) { if (!quiet) - log("Removing empty process `%s.%s'.\n", log_id(mod), proc->name); + log("Removing empty process `%s.%s'.\n", mod, proc->name); delme.push_back(proc); } } diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index bda2d272f..5e07dbcb0 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -438,7 +438,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str()); else log("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n", - db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), log_id(cell)); + db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), cell); } offset += width; diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc index a5ae0d6d5..e79d24e96 100644 --- a/passes/proc/proc_memwr.cc +++ b/passes/proc/proc_memwr.cc @@ -75,7 +75,7 @@ void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &n cell->setParam(ID::CLK_ENABLE, State::S1); cell->setParam(ID::CLK_POLARITY, State::S0); } else { - log_error("process memory write with unsupported sync type in %s.%s", log_id(mod), log_id(proc)); + log_error("process memory write with unsupported sync type in %s.%s", mod, proc); } } sr->mem_write_actions.clear(); diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index 8f5eda085..be7961e76 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -154,10 +154,10 @@ struct ProcRmdeadPass : public Pass { proc_rmdead(switch_it, counter, full_case_counter); if (counter > 0) log("Removed %d dead cases from process %s in module %s.\n", counter, - log_id(proc), log_id(mod)); + proc, mod); if (full_case_counter > 0) log("Marked %d switch rules as full_case in process %s in module %s.\n", - full_case_counter, log_id(proc), log_id(mod)); + full_case_counter, proc, mod); total_counter += counter; } } diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc index 7b3357f82..314535e84 100644 --- a/passes/sat/assertpmux.cc +++ b/passes/sat/assertpmux.cc @@ -148,7 +148,7 @@ struct AssertpmuxWorker void run(Cell *pmux) { - log("Adding assert for $pmux cell %s.%s.\n", log_id(module), log_id(pmux)); + log("Adding assert for $pmux cell %s.%s.\n", module, pmux); int swidth = pmux->getParam(ID::S_WIDTH).as_int(); int cntbits = ceil_log2(swidth+1); diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index 086dd5278..be2355e00 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -91,7 +91,7 @@ struct Async2syncPass : public Pass { int trg_width = cell->getParam(ID(TRG_WIDTH)).as_int(); if (trg_width > 1) - log_error("$check cell %s with TRG_WIDTH > 1 is not support by async2sync, use clk2fflogic.\n", log_id(cell)); + log_error("$check cell %s with TRG_WIDTH > 1 is not support by async2sync, use clk2fflogic.\n", cell); if (trg_width == 0) { if (initstate == State::S0) @@ -147,7 +147,7 @@ struct Async2syncPass : public Pass { ff.unmap_ce_srst(); log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_d), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); @@ -212,7 +212,7 @@ struct Async2syncPass : public Pass { ff.unmap_ce_srst(); log("Replacing %s.%s (%s): ALOAD=%s, AD=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type, log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_d), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); @@ -245,7 +245,7 @@ struct Async2syncPass : public Pass { ff.unmap_srst(); log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_arst), log_signal(ff.sig_d), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); @@ -279,7 +279,7 @@ struct Async2syncPass : public Pass { { // Latch. log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index b75c8aab1..0b928ddf6 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -173,7 +173,7 @@ struct Clk2fflogicPass : public Pass { auto &port = mem.rd_ports[i]; if (port.clk_enable) log_error("Read port %d of memory %s.%s is clocked. This is not supported by \"clk2fflogic\"! " - "Call \"memory\" with -nordff to avoid this error.\n", i, log_id(mem.memid), log_id(module)); + "Call \"memory\" with -nordff to avoid this error.\n", i, mem.memid.unescape(), module); } for (int i = 0; i < GetSize(mem.wr_ports); i++) @@ -184,10 +184,10 @@ struct Clk2fflogicPass : public Pass { continue; log("Modifying write port %d on memory %s.%s: CLK=%s, A=%s, D=%s\n", - i, log_id(module), log_id(mem.memid), log_signal(port.clk), + i, module, mem.memid.unescape(), log_signal(port.clk), log_signal(port.addr), log_signal(port.data)); - Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", log_id(mem.memid), i, log_signal(port.clk)))); + Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", mem.memid.unescape(), i, log_signal(port.clk)))); past_clk->attributes[ID::init] = port.clk_polarity ? State::S1 : State::S0; module->addFf(NEW_ID, port.clk, past_clk); @@ -203,13 +203,13 @@ struct Clk2fflogicPass : public Pass { SigSpec clock_edge = module->Eqx(NEW_ID, {port.clk, SigSpec(past_clk)}, clock_edge_pattern); - SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", log_id(mem.memid), i)), GetSize(port.en)); + SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", mem.memid.unescape(), i)), GetSize(port.en)); module->addFf(NEW_ID, port.en, en_q); - SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", log_id(mem.memid), i)), GetSize(port.addr)); + SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", mem.memid.unescape(), i)), GetSize(port.addr)); module->addFf(NEW_ID, port.addr, addr_q); - SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", log_id(mem.memid), i)), GetSize(port.data)); + SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", mem.memid.unescape(), i)), GetSize(port.data)); module->addFf(NEW_ID, port.data, data_q); port.clk = State::S0; @@ -291,16 +291,16 @@ struct Clk2fflogicPass : public Pass { if (ff.has_clk) { log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q)); } else if (ff.has_aload) { log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q)); } else { // $sr. log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q)); } diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 1a68776ff..ff1ae2628 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -93,7 +93,7 @@ struct CutpointPass : public Pass { for (auto module : design->all_selected_modules()) { if (module->is_selected_whole()) { - log("Making all outputs of module %s cut points, removing module contents.\n", log_id(module)); + log("Making all outputs of module %s cut points, removing module contents.\n", module); module->new_connections(std::vector()); for (auto cell : vector(module->cells())) module->remove(cell); @@ -125,7 +125,7 @@ struct CutpointPass : public Pass { 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)); + log("Removing cell %s.%s, making all cell outputs cutpoints.\n", module, cell); for (auto &conn : cell->connections()) { if (cell->output(conn.first)) { bool do_cut = true; @@ -171,7 +171,7 @@ struct CutpointPass : public Pass { for (auto wire : module->selected_wires()) { if (wire->port_output) { - log("Making output wire %s.%s a cutpoint.\n", log_id(module), log_id(wire)); + log("Making output wire %s.%s a cutpoint.\n", module, wire); Wire *new_wire = module->addWire(NEW_ID, wire); module->swap_names(wire, new_wire); module->connect(new_wire, flag_undef ? Const(State::Sx, GetSize(new_wire)) : module->Anyseq(NEW_ID, GetSize(new_wire))); @@ -180,7 +180,7 @@ struct CutpointPass : public Pass { wire->port_output = false; continue; } - log("Making wire %s.%s a cutpoint.\n", log_id(module), log_id(wire)); + log("Making wire %s.%s a cutpoint.\n", module, wire); for (auto bit : sigmap(wire)) cutpoint_bits.insert(bit); } diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index b0eaaca22..a192fba9b 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -149,7 +149,7 @@ struct VlogHammerReporter for (auto c : module->cells()) if (!satgen.importCell(c)) - log_error("Failed to import cell %s (type %s) to SAT database.\n", log_id(c->name), log_id(c->type)); + log_error("Failed to import cell %s (type %s) to SAT database.\n", c->name.unescape(), c->type.unescape()); ez->assume(satgen.signals_eq(recorded_set_vars, recorded_set_vals)); @@ -262,21 +262,21 @@ struct VlogHammerReporter if (module == modules.front()) { RTLIL::SigSpec sig(wire); if (!ce.eval(sig)) - log_error("Can't read back value for port %s!\n", log_id(inputs[i])); + log_error("Can't read back value for port %s!\n", inputs[i].unescape()); input_pattern_list += stringf(" %s", sig.as_const().as_string()); - log("++PAT++ %d %s %s #\n", idx, log_id(inputs[i]), sig.as_const().as_string()); + log("++PAT++ %d %s %s #\n", idx, inputs[i].unescape(), sig.as_const().as_string()); } } if (module->wire(ID(y)) == nullptr) - log_error("No output wire (y) found in module %s!\n", log_id(module->name)); + log_error("No output wire (y) found in module %s!\n", module->name.unescape()); RTLIL::SigSpec sig(module->wire(ID(y))); RTLIL::SigSpec undef; while (!ce.eval(sig, undef)) { - // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", log_id(module->name), log_signal(sig), log_signal(undef)); - log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), log_id(module->name)); + // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", module, log_signal(sig), log_signal(undef)); + log_warning("Setting signal %s in module %s to undef.\n", log_signal(undef), module->name.unescape()); ce.set(undef, RTLIL::Const(RTLIL::State::Sx, undef.size())); } @@ -288,7 +288,7 @@ struct VlogHammerReporter sat_check(module, recorded_set_vars, recorded_set_vals, sig, true); } else if (rtl_sig.size() > 0) { if (rtl_sig.size() != sig.size()) - log_error("Output (y) has a different width in module %s compared to rtl!\n", log_id(module->name)); + log_error("Output (y) has a different width in module %s compared to rtl!\n", module->name.unescape()); for (int i = 0; i < GetSize(sig); i++) if (rtl_sig[i] == RTLIL::State::Sx) sig[i] = RTLIL::State::Sx; @@ -319,10 +319,10 @@ struct VlogHammerReporter RTLIL::IdString esc_name = RTLIL::escape_id(name); for (auto mod : modules) { if (mod->wire(esc_name) == nullptr) - log_error("Can't find input %s in module %s!\n", name, log_id(mod->name)); + log_error("Can't find input %s in module %s!\n", name, mod->name.unescape()); RTLIL::Wire *port = mod->wire(esc_name); if (!port->port_input || port->port_output) - log_error("Wire %s in module %s is not an input!\n", name, log_id(mod->name)); + log_error("Wire %s in module %s is not an input!\n", name, mod->name.unescape()); if (width >= 0 && width != port->width) log_error("Port %s has different sizes in the different modules!\n", name); width = port->width; @@ -443,7 +443,7 @@ struct EvalPass : public Pass { for (auto mod : design->selected_modules()) { if (module) log_cmd_error("Only one module must be selected for the EVAL pass! (selected: %s and %s)\n", - log_id(module->name), log_id(mod->name)); + module->name.unescape(), mod->name.unescape()); module = mod; } if (module == NULL) diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 1e975db0f..ef00a6956 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -210,7 +210,7 @@ void create_dff_dq_map(std::map &map, RTLIL::Mo RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width = 1) { if (module->count_id(name)) - log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", log_id(name)); + log_error("Attempting to create wire %s, but a wire of this name exists already! Hint: Try another value for -sep.\n", name.unescape()); return module->addWire(name, width); } @@ -673,7 +673,7 @@ struct ExposePass : public Pass { } for (auto cell : delete_cells) { - log("Removing cell: %s/%s (%s)\n", log_id(module), log_id(cell), log_id(cell->type)); + log("Removing cell: %s/%s (%s)\n", module, cell, cell->type.unescape()); module->remove(cell); } } diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index 505526c14..27a153921 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -77,7 +77,7 @@ struct FmcombineWorker void import_hier_cell(Cell *cell) { if (!cell->parameters.empty()) - log_cmd_error("Cell %s.%s has unresolved instance parameters.\n", log_id(original), log_id(cell)); + log_cmd_error("Cell %s.%s has unresolved instance parameters.\n", original, cell); FmcombineWorker sub_worker(design, cell->type, opts); sub_worker.generate(); @@ -95,11 +95,11 @@ struct FmcombineWorker void generate() { if (design->module(combined_type)) { - // log("Combined module %s already exists.\n", log_id(combined_type)); + // log("Combined module %s already exists.\n", combined_type.unescape()); return; } - log("Generating combined module %s from module %s.\n", log_id(combined_type), log_id(orig_type)); + log("Generating combined module %s from module %s.\n", combined_type.unescape(), orig_type.unescape()); module = design->addModule(combined_type); for (auto wire : original->wires()) { @@ -332,15 +332,15 @@ struct FmcombinePass : public Pass { module = design->module(module_name); if (module == nullptr) - log_cmd_error("Module %s not found.\n", log_id(module_name)); + log_cmd_error("Module %s not found.\n", module_name.unescape()); gold_cell = module->cell(gold_name); if (gold_cell == nullptr) - log_cmd_error("Gold cell %s not found in module %s.\n", log_id(gold_name), log_id(module)); + log_cmd_error("Gold cell %s not found in module %s.\n", gold_name.unescape(), module); gate_cell = module->cell(gate_name); if (gate_cell == nullptr) - log_cmd_error("Gate cell %s not found in module %s.\n", log_id(gate_name), log_id(module)); + log_cmd_error("Gate cell %s not found in module %s.\n", gate_name.unescape(), module); } else { @@ -363,13 +363,13 @@ struct FmcombinePass : public Pass { FmcombineWorker worker(design, gold_cell->type, opts); worker.generate(); - IdString combined_cell_name = module->uniquify(stringf("\\%s_%s", log_id(gold_cell), log_id(gate_cell))); + IdString combined_cell_name = module->uniquify(stringf("\\%s_%s", gold_cell, gate_cell)); Cell *cell = module->addCell(combined_cell_name, worker.combined_type); cell->attributes = gold_cell->attributes; cell->add_strpool_attribute(ID::src, gate_cell->get_strpool_attribute(ID::src)); - log("Combining cells %s and %s in module %s into new cell %s.\n", log_id(gold_cell), log_id(gate_cell), log_id(module), log_id(cell)); + log("Combining cells %s and %s in module %s into new cell %s.\n", gold_cell, gate_cell, module, cell); for (auto &conn : gold_cell->connections()) cell->setPort(conn.first.str() + "_gold", conn.second); diff --git a/passes/sat/formalff.cc b/passes/sat/formalff.cc index 452e0e59b..bdf673169 100644 --- a/passes/sat/formalff.cc +++ b/passes/sat/formalff.cc @@ -402,7 +402,7 @@ struct PropagateWorker sigmap.apply(bit); if (replaced_clk_bits.count(bit)) log_error("derived signal %s driven by %s (%s) from module %s is used as clock, derived clocks are only supported with clk2fflogic.\n", - log_signal(bit), log_id(cell->name), log_id(cell->type), log_id(module)); + log_signal(bit), cell->name.unescape(), cell->type.unescape(), module); } } } @@ -436,7 +436,7 @@ struct PropagateWorker if (it != replaced_clk_bits.end()) { if (it->second != polarity) log_error("signal %s from module %s is used as clock with different polarities, run clk2fflogic instead.\n", - log_signal(bit), log_id(module)); + log_signal(bit), module); return; } @@ -659,7 +659,7 @@ struct FormalFfPass : public Pass { // XXX $check $print } - log_debug("%s has %d clk bits\n", log_id(module), GetSize(clk_bits)); + log_debug("%s has %d clk bits\n", module, GetSize(clk_bits)); for (auto port : module->ports) { Wire *wire = module->wire(port); @@ -675,7 +675,7 @@ struct FormalFfPass : public Pass { } } } - log_debug("%s has %d non-input clk bits\n", log_id(module), GetSize(clk_bits)); + log_debug("%s has %d non-input clk bits\n", module, GetSize(clk_bits)); if (clk_bits.empty()) continue; @@ -687,21 +687,21 @@ struct FormalFfPass : public Pass { vector &clocked_cells = clk_bit.second; if (!clk.is_wire()) { - log_debug("constant clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("constant clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } if (input_bits.count(clk)) { - log_debug("input clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("input clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } auto found = modwalker.signal_drivers.find(clk); if (found == modwalker.signal_drivers.end() || found->second.empty()) { - log_debug("undriven clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("undriven clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } if (found->second.size() > 1) { - log_debug("multiple drivers for clk bit %s.%s\n", log_id(module), log_signal(SigSpec(clk))); + log_debug("multiple drivers for clk bit %s.%s\n", module, log_signal(SigSpec(clk))); continue; } @@ -711,9 +711,9 @@ struct FormalFfPass : public Pass { pol_clk ? driver.cell->type.in(ID($and), ID($_AND_)) : driver.cell->type.in(ID($or), ID($_OR_)); if (!is_gate) { - log_debug("unsupported gating logic %s.%s (%s) for clock %s %s.%s\n", log_id(module), - log_id(driver.cell), log_id(driver.cell->type), pol_clk ? "posedge" : "negedge", - log_id(module), log_signal(SigSpec(clk))); + log_debug("unsupported gating logic %s.%s (%s) for clock %s %s.%s\n", module, + driver.cell, driver.cell->type.unescape(), pol_clk ? "posedge" : "negedge", + module, log_signal(SigSpec(clk))); continue; } @@ -724,28 +724,28 @@ struct FormalFfPass : public Pass { for (int i = 0; i < 2; i++) { std::swap(gate_clock, gate_enable); - log_debug("clock %s.%s for gated clk bit %s.%s\n", log_id(module), log_signal(SigSpec(gate_clock)), - log_id(module), log_signal(SigSpec(clk))); - log_debug("enable %s.%s for gated clk bit %s.%s\n", log_id(module), log_signal(SigSpec(gate_enable)), - log_id(module), log_signal(SigSpec(clk))); + log_debug("clock %s.%s for gated clk bit %s.%s\n", module, log_signal(SigSpec(gate_clock)), + module, log_signal(SigSpec(clk))); + log_debug("enable %s.%s for gated clk bit %s.%s\n", module, log_signal(SigSpec(gate_enable)), + module, log_signal(SigSpec(clk))); found = modwalker.signal_drivers.find(gate_enable); if (found == modwalker.signal_drivers.end() || found->second.empty()) { - log_debug("undriven gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), - log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); + log_debug("undriven gate enable %s.%s of gated clk bit %s.%s\n", module, + log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk))); continue; } if (found->second.size() > 1) { - log_debug("multiple drivers for gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), - log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); + log_debug("multiple drivers for gate enable %s.%s of gated clk bit %s.%s\n", module, + log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk))); continue; } auto gate_driver = *found->second.begin(); if (!gate_driver.cell->is_builtin_ff()) { - log_debug("non FF driver for gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), - log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); + log_debug("non FF driver for gate enable %s.%s of gated clk bit %s.%s\n", module, + log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk))); continue; } @@ -753,8 +753,8 @@ struct FormalFfPass : public Pass { if (ff.has_gclk || ff.has_ce || ff.has_sr || ff.has_srst || ff.has_arst || (ff.has_aload && ff.has_clk)) { log_debug( "FF driver for gate enable %s.%s of gated clk bit %s.%s has incompatible type: %s\n", - log_id(module), log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk)), - log_id(gate_driver.cell->type)); + module, log_signal(SigSpec(gate_enable)), module, log_signal(SigSpec(clk)), + gate_driver.cell->type.unescape()); continue; } @@ -770,8 +770,8 @@ struct FormalFfPass : public Pass { if (!ff.has_clk || sigmap(ff.sig_clk) != gate_clock || ff.pol_clk != pol_clk) { log_debug("FF driver for gate enable %s.%s of gated clk bit %s.%s has incompatible clocking: " "%s %s.%s\n", - log_id(module), log_signal(SigSpec(gate_enable)), log_id(module), - log_signal(SigSpec(clk)), ff.pol_clk ? "posedge" : "negedge", log_id(module), + module, log_signal(SigSpec(gate_enable)), module, + log_signal(SigSpec(clk)), ff.pol_clk ? "posedge" : "negedge", module, log_signal(SigSpec(ff.sig_clk))); continue; } @@ -781,8 +781,8 @@ struct FormalFfPass : public Pass { log_debug("found clock gate, rewriting %d cells\n", GetSize(clocked_cells)); for (auto clocked_cell : clocked_cells) { - log_debug("rewriting cell %s.%s (%s)\n", log_id(module), log_id(clocked_cell), - log_id(clocked_cell->type)); + log_debug("rewriting cell %s.%s (%s)\n", module, clocked_cell, + clocked_cell->type.unescape()); if (clocked_cell->is_builtin_ff()) { @@ -855,7 +855,7 @@ struct FormalFfPass : public Pass { if (ff.val_init != before) { log("Setting unused undefined initial value of %s.%s (%s) from %s to %s\n", - log_id(module), log_id(cell), log_id(cell->type), + module, cell, cell->type.unescape(), log_const(before), log_const(ff.val_init)); worker.initvals.set_init(ff.sig_q, ff.val_init); } @@ -892,10 +892,10 @@ struct FormalFfPass : public Pass { if (flag_clk2ff && ff.has_clk) { if (ff.sig_clk.is_fully_const()) log_error("Const CLK on %s (%s) from module %s, run async2sync first.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type, module); if (ff.has_aload || ff.has_arst || ff.has_sr) log_error("Async inputs on %s (%s) from module %s, run async2sync first.\n", - log_id(cell), log_id(cell->type), log_id(module)); + cell, cell->type.unescape(), module); auto clk_wire = ff.sig_clk.is_wire() ? ff.sig_clk.as_wire() : nullptr; @@ -912,7 +912,7 @@ struct FormalFfPass : public Pass { if (!attr.empty() && attr != clk_polarity) log_error("CLK %s on %s (%s) from module %s also used with opposite polarity, run clk2fflogic instead.\n", - log_id(clk_wire), log_id(cell), log_id(cell->type), log_id(module)); + clk_wire, cell, cell->type.unescape(), module); attr = clk_polarity; clk_wire->set_bool_attribute(ID::keep); diff --git a/passes/sat/mutate.cc b/passes/sat/mutate.cc index 79ffcd88d..63a8de277 100644 --- a/passes/sat/mutate.cc +++ b/passes/sat/mutate.cc @@ -558,7 +558,7 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena if (opts.none) { string str = "mutate"; if (!opts.ctrl_name.empty()) - str += stringf(" -ctrl %s %d %d", log_id(opts.ctrl_name), opts.ctrl_width, ctrl_value++); + str += stringf(" -ctrl %s %d %d", opts.ctrl_name.unescape(), opts.ctrl_width, ctrl_value++); str += " -mode none"; if (filename.empty()) log("%s\n", str); @@ -569,20 +569,20 @@ void mutate_list(Design *design, const mutate_opts_t &opts, const string &filena for (auto &entry : database) { string str = "mutate"; if (!opts.ctrl_name.empty()) - str += stringf(" -ctrl %s %d %d", log_id(opts.ctrl_name), opts.ctrl_width, ctrl_value++); + str += stringf(" -ctrl %s %d %d", opts.ctrl_name.unescape(), opts.ctrl_width, ctrl_value++); str += stringf(" -mode %s", entry.mode); if (!entry.module.empty()) - str += stringf(" -module %s", log_id(entry.module)); + str += stringf(" -module %s", entry.module.unescape()); if (!entry.cell.empty()) - str += stringf(" -cell %s", log_id(entry.cell)); + str += stringf(" -cell %s", entry.cell.unescape()); if (!entry.port.empty()) - str += stringf(" -port %s", log_id(entry.port)); + str += stringf(" -port %s", entry.port.unescape()); if (entry.portbit >= 0) str += stringf(" -portbit %d", entry.portbit); if (entry.ctrlbit >= 0) str += stringf(" -ctrlbit %d", entry.ctrlbit); if (!entry.wire.empty()) - str += stringf(" -wire %s", log_id(entry.wire)); + str += stringf(" -wire %s", entry.wire.unescape()); if (entry.wirebit >= 0) str += stringf(" -wirebit %d", entry.wirebit); for (auto &s : entry.src) @@ -600,7 +600,7 @@ SigSpec mutate_ctrl_sig(Module *module, IdString name, int width) if (ctrl_wire == nullptr) { - log("Adding ctrl port %s to module %s.\n", log_id(name), log_id(module)); + log("Adding ctrl port %s to module %s.\n", name.unescape(), module); ctrl_wire = module->addWire(name, width); ctrl_wire->port_input = true; @@ -614,7 +614,7 @@ SigSpec mutate_ctrl_sig(Module *module, IdString name, int width) SigSpec ctrl = mutate_ctrl_sig(mod, name, width); - log("Connecting ctrl port to cell %s in module %s.\n", log_id(cell), log_id(mod)); + log("Connecting ctrl port to cell %s in module %s.\n", cell, mod); cell->setPort(name, ctrl); } } @@ -652,13 +652,13 @@ void mutate_inv(Design *design, const mutate_opts_t &opts) if (cell->input(opts.port)) { - log("Add input inverter at %s.%s.%s[%d].\n", log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add input inverter at %s.%s.%s[%d].\n", module, cell, opts.port.unescape(), opts.portbit); SigBit outbit = module->Not(NEW_ID, bit); bit = mutate_ctrl_mux(module, opts, bit, outbit); } else { - log("Add output inverter at %s.%s.%s[%d].\n", log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add output inverter at %s.%s.%s[%d].\n", module, cell, opts.port.unescape(), opts.portbit); SigBit inbit = module->addWire(NEW_ID); SigBit outbit = module->Not(NEW_ID, inbit); module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit)); @@ -680,13 +680,13 @@ void mutate_const(Design *design, const mutate_opts_t &opts, bool one) if (cell->input(opts.port)) { - log("Add input constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add input constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit); SigBit outbit = one ? State::S1 : State::S0; bit = mutate_ctrl_mux(module, opts, bit, outbit); } else { - log("Add output constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit); + log("Add output constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit); SigBit inbit = module->addWire(NEW_ID); SigBit outbit = one ? State::S1 : State::S0; module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit)); @@ -709,13 +709,13 @@ void mutate_cnot(Design *design, const mutate_opts_t &opts, bool one) if (cell->input(opts.port)) { - log("Add input cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit, opts.ctrlbit); + log("Add input cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit, opts.ctrlbit); SigBit outbit = one ? module->Xor(NEW_ID, bit, ctrl) : module->Xnor(NEW_ID, bit, ctrl); bit = mutate_ctrl_mux(module, opts, bit, outbit); } else { - log("Add output cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit, opts.ctrlbit); + log("Add output cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, module, cell, opts.port.unescape(), opts.portbit, opts.ctrlbit); SigBit inbit = module->addWire(NEW_ID); SigBit outbit = one ? module->Xor(NEW_ID, inbit, ctrl) : module->Xnor(NEW_ID, inbit, ctrl); module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit)); @@ -947,26 +947,26 @@ struct MutatePass : public Pass { Module *module = design->module(opts.module); if (module == nullptr) - log_cmd_error("Module %s not found.\n", log_id(opts.module)); + log_cmd_error("Module %s not found.\n", opts.module.unescape()); if (opts.cell.empty()) log_cmd_error("Missing -cell argument.\n"); Cell *cell = module->cell(opts.cell); if (cell == nullptr) - log_cmd_error("Cell %s not found in module %s.\n", log_id(opts.cell), log_id(opts.module)); + log_cmd_error("Cell %s not found in module %s.\n", opts.cell.unescape(), opts.module.unescape()); if (opts.port.empty()) log_cmd_error("Missing -port argument.\n"); if (!cell->hasPort(opts.port)) - log_cmd_error("Port %s not found on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell)); + log_cmd_error("Port %s not found on cell %s.%s.\n", opts.port.unescape(), opts.module.unescape(), opts.cell.unescape()); if (opts.portbit < 0) log_cmd_error("Missing -portbit argument.\n"); if (GetSize(cell->getPort(opts.port)) <= opts.portbit) - log_cmd_error("Out-of-range -portbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell)); + log_cmd_error("Out-of-range -portbit argument for port %s on cell %s.%s.\n", opts.port.unescape(), opts.module.unescape(), opts.cell.unescape()); if (opts.mode == "inv") { mutate_inv(design, opts); @@ -982,7 +982,7 @@ struct MutatePass : public Pass { log_cmd_error("Missing -ctrlbit argument.\n"); if (GetSize(cell->getPort(opts.port)) <= opts.ctrlbit) - log_cmd_error("Out-of-range -ctrlbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell)); + log_cmd_error("Out-of-range -ctrlbit argument for port %s on cell %s.%s.\n", opts.port.unescape(), opts.module.unescape(), opts.cell.unescape()); if (opts.mode == "cnot0" || opts.mode == "cnot1") { mutate_cnot(design, opts, opts.mode == "cnot1"); diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index b011227e2..b892683a8 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -597,7 +597,7 @@ struct QbfSatPass : public Pass { RTLIL::Module *module = nullptr; for (auto mod : design->selected_modules()) { if (module) - log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod)); + log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", module, mod); module = mod; } if (module == nullptr) diff --git a/passes/sat/recover_names.cc b/passes/sat/recover_names.cc index 7939a64e0..e2c93df65 100644 --- a/passes/sat/recover_names.cc +++ b/passes/sat/recover_names.cc @@ -641,8 +641,8 @@ struct RecoverNamesWorker { for (auto gate_bit : gate_bits) { if (solved_gate.count(gate_bit.bit)) continue; - log_debug(" attempting to prove %s[%d] == %s%s[%d]\n", log_id(gold_bit.name), gold_bit.bit, - gate_bit.inverted ? "" : "!", log_id(gate_bit.bit.name), gate_bit.bit.bit); + log_debug(" attempting to prove %s[%d] == %s%s[%d]\n", gold_bit.name.unescape(), gold_bit.bit, + gate_bit.inverted ? "" : "!", gate_bit.bit.name.unescape(), gate_bit.bit.bit); if (!prove_equiv(gold_worker, gate_worker, gold_anchors, gate_anchors, gold_bit, gate_bit.bit, gate_bit.inverted)) continue; log_debug(" success!\n"); @@ -660,7 +660,7 @@ struct RecoverNamesWorker { break; } } - log("Recovered %d net name pairs in module `%s' out.\n", GetSize(gate2gold), log_id(gate_mod)); + log("Recovered %d net name pairs in module `%s' out.\n", GetSize(gate2gold), gate_mod); gate_worker.do_rename(gold_mod, gate2gold, buffer_types); } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 9988eef62..accfe0399 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -1369,7 +1369,7 @@ struct SatPass : public Pass { RTLIL::Module *module = NULL; for (auto mod : design->selected_modules()) { if (module) - log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod)); + log_cmd_error("Only one module must be selected for the SAT pass! (selected: %s and %s)\n", module, mod); module = mod; } if (module == NULL) diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 1be993154..23af70fa5 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -250,11 +250,11 @@ struct SimInstance if (module->get_blackbox_attribute(true)) log_error("Cannot simulate blackbox module %s (instantiated at %s).\n", - log_id(module->name), hiername().c_str()); + module->name.unescape(), hiername().c_str()); if (module->has_processes()) log_error("Found processes in simulation hierarchy (in module %s at %s). Run 'proc' first.\n", - log_id(module), hiername().c_str()); + module, hiername().c_str()); if (parent) { log_assert(parent->children.count(instance) == 0); @@ -413,9 +413,9 @@ struct SimInstance std::string hiername() const { if (instance != nullptr) - return parent->hiername() + "." + log_id(instance->name); + return parent->hiername() + "." + instance->name.unescape(); - return log_id(module->name); + return module->name.unescape(); } vector witness_full_path() const @@ -520,7 +520,7 @@ struct SimInstance { auto &state = mem_database[memid]; if (offset >= state.mem->size * state.mem->width) - log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, log_id(memid)); + log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, memid.unescape()); if (state.data[offset] != data) { state.data.set(offset, data); dirty_memories.insert(memid); @@ -573,7 +573,7 @@ struct SimInstance if (has_y) sig_y = cell->getPort(ID::Y); if (shared->debug) - log("[%s] eval %s (%s)\n", hiername(), log_id(cell), log_id(cell->type)); + log("[%s] eval %s (%s)\n", hiername(), cell, cell->type.unescape()); bool err = false; RTLIL::Const eval_state; @@ -593,7 +593,7 @@ struct SimInstance err = true; if (err) - log_warning("Unsupported evaluable cell type: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_warning("Unsupported evaluable cell type: %s (%s.%s)\n", cell->type.unescape(), module, cell); else set_state(sig_y, eval_state); return; @@ -602,7 +602,7 @@ struct SimInstance if (cell->type == ID($print)) return; - log_error("Unsupported cell type: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); + log_error("Unsupported cell type: %s (%s.%s)\n", cell->type.unescape(), module, cell); } void update_memory(IdString id) { @@ -616,7 +616,7 @@ struct SimInstance Const data = Const(State::Sx, mem.width << port.wide_log2); if (port.clk_enable) - log_error("Memory %s.%s has clocked read ports. Run 'memory_nordff' to transform the circuit to remove those.\n", log_id(module), log_id(mem.memid)); + log_error("Memory %s.%s has clocked read ports. Run 'memory_nordff' to transform the circuit to remove those.\n", module, mem.memid.unescape()); if (addr.is_fully_def()) { int addr_int = addr.as_int(); @@ -819,14 +819,14 @@ struct SimInstance log_assert(cell->module == module); bool has_src = cell->has_attribute(ID::src); log("%s %s%s\n", opening_verbiage, - log_id(cell), has_src ? " at" : ""); + cell, has_src ? " at" : ""); log_source(cell); struct SimInstance *sim = this; while (sim->instance) { has_src = sim->instance->has_attribute(ID::src); - log(" in instance %s of module %s%s\n", log_id(sim->instance), - log_id(sim->instance->type), has_src ? " at" : ""); + log(" in instance %s of module %s%s\n", sim->instance, + sim->instance->type.unescape(), has_src ? " at" : ""); log_source(sim->instance); sim = sim->parent; } @@ -927,7 +927,7 @@ struct SimInstance { for (auto cell : formal_database) { - string label = log_id(cell); + string label = cell->name.unescape(); if (cell->attributes.count(ID::src)) label = cell->attributes.at(ID::src).decode_string(); @@ -939,17 +939,17 @@ struct SimInstance } if (cell->type == ID($cover) && en == State::S1 && a == State::S1) - log("Cover %s.%s (%s) reached.\n", hiername(), log_id(cell), label); + log("Cover %s.%s (%s) reached.\n", hiername(), cell, label); if (cell->type == ID($assume) && en == State::S1 && a != State::S1) - log("Assumption %s.%s (%s) failed.\n", hiername(), log_id(cell), label); + log("Assumption %s.%s (%s) failed.\n", hiername(), cell, label); if (cell->type == ID($assert) && en == State::S1 && a != State::S1) { log_cell_w_hierarchy("Failed assertion", cell); if (shared->serious_asserts) - log_error("Assertion %s.%s (%s) failed.\n", hiername(), log_id(cell), label); + log_error("Assertion %s.%s (%s) failed.\n", hiername(), cell, label); else - log_warning("Assertion %s.%s (%s) failed.\n", hiername(), log_id(cell), label); + log_warning("Assertion %s.%s (%s) failed.\n", hiername(), cell, label); } } } @@ -970,7 +970,7 @@ struct SimInstance { if (!ff_database.empty() || !mem_database.empty()) { if (wbmods.count(module)) - log_error("Instance %s of module %s is not unique: Writeback not possible. (Fix by running 'uniquify'.)\n", hiername(), log_id(module)); + log_error("Instance %s of module %s is not unique: Writeback not possible. (Fix by running 'uniquify'.)\n", hiername(), module); wbmods.insert(module); } @@ -1061,7 +1061,7 @@ struct SimInstance for (auto name : hdlname) exit_scope(); } else - register_signal(log_id(signal.first->name), GetSize(signal.first), signal.first, signal.second.id, registers.count(signal.first)!=0); + register_signal(signal.first->name.unescape().c_str(), GetSize(signal.first), signal.first, signal.second.id, registers.count(signal.first)!=0); } for (auto &trace_mem : trace_mem_database) @@ -1082,7 +1082,7 @@ struct SimInstance for (auto name : hdlname) enter_scope("\\" + name); } else { - signal_name = log_id(memid); + signal_name = memid.unescape(); } for (auto &trace_index : trace_mem.second) { @@ -1269,13 +1269,13 @@ struct SimInstance Const fst_val = Const::from_string(shared->fst->valueOf(item.second)); Const sim_val = get_state(item.first); if (sim_val.size()!=fst_val.size()) { - log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope, log_id(item.first)); + log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope, item.first); continue; } if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X for(int i=0;isim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X for(int i=0;imodule->wire(portname); if (w == nullptr) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); top->set_state(w, value); } @@ -1492,24 +1492,24 @@ struct SimWorker : SimShared { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); } for (auto portname : clockn) { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); } @@ -1630,7 +1630,7 @@ struct SimWorker : SimShared escaped_s = RTLIL::escape_id(cell_name(symbol)); Cell *c = topmod->cell(escaped_s); if (!c) - log_warning("Wire/cell %s not present in module %s\n",symbol,log_id(topmod)); + log_warning("Wire/cell %s not present in module %s\n",symbol,topmod); if (c->is_mem_cell()) { std::string memid = c->parameters.at(ID::MEMID).decode_string(); @@ -1829,7 +1829,7 @@ struct SimWorker : SimShared if (!w) { Cell *c = topmod->cell(escaped_s); if (!c) - log_warning("Wire/cell %s not present in module %s\n",log_id(escaped_s),log_id(topmod)); + log_warning("Wire/cell %s not present in module %s\n",escaped_s.unescape(),topmod); else if (c->type.in(ID($anyconst), ID($anyseq))) { SigSpec sig_y= c->getPort(ID::Y); if ((int)parts[1].size() != GetSize(sig_y)) @@ -1844,9 +1844,9 @@ struct SimWorker : SimShared } else { Cell *c = topmod->cell(escaped_s); if (!c) - log_error("Cell %s not present in module %s\n",log_id(escaped_s),log_id(topmod)); + log_error("Cell %s not present in module %s\n",escaped_s.unescape(),topmod); if (!c->is_mem_cell()) - log_error("Cell %s is not memory cell in module %s\n",log_id(escaped_s),log_id(topmod)); + log_error("Cell %s is not memory cell in module %s\n",escaped_s.unescape(),topmod); Const addr = Const::from_string(parts[1].substr(1,parts[1].size()-2)); Const data = Const::from_string(parts[2]); @@ -2077,13 +2077,13 @@ struct SimWorker : SimShared json.entry("version", "Yosys sim summary"); json.entry("generator", yosys_maybe_version()); json.entry("steps", step); - json.entry("top", log_id(top->module->name)); + json.entry("top", top->module->name.unescape()); json.name("assertions"); json.begin_array(); for (auto &assertion : triggered_assertions) { json.begin_object(); json.entry("step", assertion.step); - json.entry("type", log_id(assertion.cell->type)); + json.entry("type", assertion.cell->type.unescape()); json.entry("path", assertion.instance->witness_full_path(assertion.cell)); auto src = assertion.cell->get_string_attribute(ID::src); if (!src.empty()) { @@ -2148,12 +2148,12 @@ struct SimWorker : SimShared { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); clocks[w] = id; } @@ -2161,12 +2161,12 @@ struct SimWorker : SimShared { Wire *w = topmod->wire(portname); if (!w) - log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module)); + log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module)); + log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, log_id(portname)); + log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); fst_clock.push_back(id); clocks[w] = id; } @@ -2359,7 +2359,7 @@ struct VCDWriter : public OutputWriter vcdfile << stringf("$timescale %s $end\n", worker->timescale); worker->top->write_output_header( - [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); }, + [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", name.unescape()); }, [this]() { vcdfile << stringf("$upscope $end\n");}, [this,use_signal](const char *name, int size, Wire *w, int id, bool is_reg) { if (!use_signal.at(id)) return; @@ -2425,7 +2425,7 @@ struct FSTWriter : public OutputWriter fstWriterSetRepackOnClose(fstfile, 1); worker->top->write_output_header( - [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",log_id(name)).c_str(), nullptr); }, + [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",name.unescape()).c_str(), nullptr); }, [this]() { fstWriterSetUpscope(fstfile); }, [this,use_signal](const char *name, int size, Wire *w, int id, bool is_reg) { if (!use_signal.at(id)) return; @@ -2488,7 +2488,7 @@ struct AIWWriter : public OutputWriter RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); Wire *w = worker->top->module->wire(escaped_s); if (!w) - log_error("Wire %s not present in module %s\n",log_id(escaped_s),log_id(worker->top->module)); + log_error("Wire %s not present in module %s\n",escaped_s.unescape(),worker->top->module); if (index < w->start_offset || index > w->start_offset + w->width) log_error("Index %d for wire %s is out of range\n", index, log_signal(w)); if (type == "input") { diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc index f1b3ad09c..a2192dc8a 100644 --- a/passes/sat/supercover.cc +++ b/passes/sat/supercover.cc @@ -64,7 +64,7 @@ struct SupercoverPass : public Pass { pool handled_bits; int cnt_wire = 0, cnt_bits = 0; - log("Adding cover cells to module %s.\n", log_id(module)); + log("Adding cover cells to module %s.\n", module); for (auto wire : module->selected_wires()) { bool counted_wire = false; diff --git a/passes/sat/synthprop.cc b/passes/sat/synthprop.cc index d94b4a7f7..a54eef199 100644 --- a/passes/sat/synthprop.cc +++ b/passes/sat/synthprop.cc @@ -60,20 +60,20 @@ struct SynthPropWorker void SynthPropWorker::tracing(RTLIL::Module *mod, int depth, TrackingData &tracing_data, std::string hier_path) { - log("%*sTracing in module %s..\n", 2*depth, "", log_id(mod)); + log("%*sTracing in module %s..\n", 2*depth, "", mod); tracing_data[mod] = TrackingItem(); int cnt = 0; for (auto cell : mod->cells()) { if (cell->type == ID($assert)) { - log("%*sFound assert %s..\n", 2*(depth+1), "", log_id(cell)); + log("%*sFound assert %s..\n", 2*(depth+1), "", cell); tracing_data[mod].assertion_cells.emplace(cell); if (!or_outputs) { - tracing_data[mod].names.push_back(hier_path + "." + log_id(cell)); + tracing_data[mod].names.push_back(hier_path + "." + cell->name.unescape()); } cnt++; } else if (RTLIL::Module *submod = design->module(cell->type)) { - tracing(submod, depth+1, tracing_data, hier_path + "." + log_id(cell)); + tracing(submod, depth+1, tracing_data, hier_path + "." + cell->name.unescape()); if (!or_outputs) { for (size_t i = 0; i < tracing_data[submod].names.size(); i++) tracing_data[mod].names.push_back(tracing_data[submod].names[i]); @@ -93,7 +93,7 @@ void SynthPropWorker::run() log_error("Module is not TOP module\n"); TrackingData tracing_data; - tracing(module, 0, tracing_data, log_id(module->name)); + tracing(module, 0, tracing_data, module->name.unescape()); for (auto &data : tracing_data) { if (data.second.names.size() == 0) continue; diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 71c238ec7..e26dbf34f 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -2427,7 +2427,7 @@ struct AbcPass : public Pass { for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + log("Skipping module %s as it contains processes.\n", mod); continue; } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 90c48ae34..309365a11 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -386,7 +386,7 @@ struct Abc9Pass : public ScriptPass for (auto mod : selected_modules) { if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + log("Skipping module %s as it contains processes.\n", mod); continue; } @@ -395,7 +395,7 @@ struct Abc9Pass : public ScriptPass // this check does nothing because the above line adds the whole module to the selection if (!active_design->selected_whole_module(mod)) - log_error("Can't handle partially selected module %s!\n", log_id(mod)); + log_error("Can't handle partially selected module %s!\n", mod); std::string tempdir_name; if (cleanup) @@ -416,7 +416,7 @@ struct Abc9Pass : public ScriptPass log("Extracted %d AND gates and %d wires from module `%s' to a netlist network with %d inputs and %d outputs.\n", active_design->scratchpad_get_int("write_xaiger.num_ands"), active_design->scratchpad_get_int("write_xaiger.num_wires"), - log_id(mod), + mod, active_design->scratchpad_get_int("write_xaiger.num_inputs"), num_outputs); if (num_outputs) { @@ -429,7 +429,7 @@ struct Abc9Pass : public ScriptPass else abc9_exe_cmd += stringf(" -box %s", box_file); run_nocheck(abc9_exe_cmd); - run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name, tempdir_name)); + run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", mod, tempdir_name, tempdir_name)); run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : "")); } else diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e7cf8c637..d6cf731f1 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -48,7 +48,7 @@ void check(RTLIL::Design *design, bool dff_mode) auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); if (!r.second) log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - log_id(m), id, log_id(r.first->second)); + m, id, r.first->second.unescape()); } // Make carry in the last PI, and carry out the last PO @@ -60,21 +60,21 @@ void check(RTLIL::Design *design, bool dff_mode) if (w->get_bool_attribute(ID::abc9_carry)) { if (w->port_input) { if (carry_in != IdString()) - log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) input port.\n", m); carry_in = port_name; } if (w->port_output) { if (carry_out != IdString()) - log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", log_id(m)); + log_error("Module '%s' contains more than one (* abc9_carry *) output port.\n", m); carry_out = port_name; } } } if (carry_in != IdString() && carry_out == IdString()) - log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) input port but no output port.\n", m); if (carry_in == IdString() && carry_out != IdString()) - log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", log_id(m)); + log_error("Module '%s' contains an (* abc9_carry *) output port but no input port.\n", m); if (flop) { int num_outputs = 0; @@ -83,7 +83,7 @@ void check(RTLIL::Design *design, bool dff_mode) if (wire->port_output) num_outputs++; } if (num_outputs != 1) - log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs); + log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", m, num_outputs); } } @@ -121,7 +121,7 @@ void check(RTLIL::Design *design, bool dff_mode) if (!derived_module->get_bool_attribute(ID::abc9_flop)) continue; if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) - log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type)); + log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", derived_type.unescape()); if (derived_module->has_processes()) Pass::call_on_module(design, derived_module, "proc -noopt"); @@ -130,20 +130,20 @@ void check(RTLIL::Design *design, bool dff_mode) for (auto derived_cell : derived_module->cells()) { if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { if (found) - log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); + log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", derived_module); found = true; SigBit Q = derived_cell->getPort(ID::Q); log_assert(GetSize(Q.wire) == 1); if (!Q.wire->port_output) - log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", log_id(derived_module), log_id(derived_cell->type)); + log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", derived_module, derived_cell->type.unescape()); Const init = Q.wire->attributes.at(ID::init, State::Sx); log_assert(GetSize(init) == 1); } else if (unsupported.count(derived_cell->type)) - log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); + log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", derived_module, derived_cell->type.unescape()); } } } @@ -217,7 +217,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) // Block sequential synthesis on cells with (* init *) != 1'b0 // because ABC9 doesn't support them if (init != State::S0) { - log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); + log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", derived_module, derived_cell->type.unescape()); derived_module->set_bool_attribute(ID::abc9_flop, false); } break; @@ -474,7 +474,7 @@ void prep_dff(RTLIL::Design *design) // be instantiating the derived module which will have had any parameters constant-propagated. // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design. // Please file a bug report! - log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", log_id(cell->name), log_id(cell->type)); + log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", cell->name.unescape(), cell->type.unescape()); } modules_sel.select(inst_module); } @@ -621,7 +621,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) std::vector cells; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(module)); + log("Skipping module %s as it contains processes.\n", module); continue; } @@ -669,7 +669,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) auto port_wire = inst_module->wire(i.first.name); if (!port_wire) log_error("Port %s in cell %s (type %s) from module %s does not actually exist", - log_id(i.first.name), log_id(cell), log_id(cell->type), log_id(module)); + i.first.name.unescape(), cell, cell->type.unescape(), module); log_assert(port_wire->port_input); auto d = i.second.first; @@ -688,7 +688,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) if (ys_debug(1)) { static pool> seen; if (seen.emplace(cell->type, i.first).second) log("%s.%s[%d] abc9_required = %d\n", - log_id(cell->type), log_id(i.first.name), offset, d); + cell->type.unescape(), i.first.name.unescape(), offset, d); } #endif auto r = box_cache.insert(d); @@ -848,7 +848,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto cell_name : it) { auto cell = module->cell(cell_name); log_assert(cell); - log("\t%s (%s @ %s)\n", log_id(cell), log_id(cell->type), cell->get_src_attribute()); + log("\t%s (%s @ %s)\n", cell, cell->type.unescape(), cell->get_src_attribute()); } } } @@ -882,7 +882,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) // be instantiating the derived module which will have had any parameters constant-propagated. // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design. // Please file a bug report! - log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", log_id(cell_name), log_id(cell->type)); + log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", cell_name.unescape(), cell->type.unescape()); } log_assert(box_module->get_blackbox_attribute()); @@ -917,7 +917,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } else if (w->port_output) - conn = holes_module->addWire(stringf("%s.%s", cell->type, log_id(port_name)), GetSize(w)); + conn = holes_module->addWire(stringf("%s.%s", cell->type, port_name.unescape()), GetSize(w)); } } else // box_module is a blackbox @@ -929,7 +929,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(w); if (!w->port_output) continue; - Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, log_id(port_name)), GetSize(w)); + Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, port_name.unescape()), GetSize(w)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); @@ -965,12 +965,12 @@ void prep_lut(RTLIL::Design *design, int maxlut) if (o == TimingInfo::NameBit()) o = d; else if (o != d) - log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", log_id(module)); + log_error("Module '%s' with (* abc9_lut *) has more than one output.\n", module); delays.push_back(i.second); } if (GetSize(delays) == 0) - log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", log_id(module)); + log_error("Module '%s' with (* abc9_lut *) has no specify entries.\n", module); if (maxlut && GetSize(delays) > maxlut) continue; // ABC requires non-decreasing LUT input delays @@ -981,9 +981,9 @@ void prep_lut(RTLIL::Design *design, int maxlut) auto r = table.emplace(K, entry); if (!r.second) { if (r.first->second.area != entry.area) - log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", log_id(module), log_id(r.first->second.name)); + log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", module, r.first->second.name.unescape()); if (r.first->second.delays != entry.delays) - log_error("Modules '%s' and '%s' have conflicting specify entries.\n", log_id(module), log_id(r.first->second.name)); + log_error("Modules '%s' and '%s' have conflicting specify entries.\n", module, r.first->second.name.unescape()); } } @@ -1002,7 +1002,7 @@ void prep_lut(RTLIL::Design *design, int maxlut) ss << std::endl; } for (const auto &i : table) { - ss << "# " << log_id(i.second.name) << std::endl; + ss << "# " << i.second.name.unescape() << std::endl; ss << i.first << " " << i.second.area; for (const auto &j : i.second.delays) ss << " " << j; @@ -1046,7 +1046,7 @@ void prep_box(RTLIL::Design *design) } log_assert(num_outputs == 1); - ss << log_id(module) << " " << r.first->second.as_int(); + ss << module->name.unescape() << " " << r.first->second.as_int(); log_assert(module->get_bool_attribute(ID::whitebox)); ss << " " << "1"; ss << " " << num_inputs << " " << num_outputs << std::endl; @@ -1061,13 +1061,13 @@ void prep_box(RTLIL::Design *design) first = false; else ss << " "; - ss << log_id(wire); + ss << wire->name.unescape(); } ss << std::endl; auto &t = timing.setup_module(module).required; if (t.empty()) - log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module)); + log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", module); first = true; for (auto port_name : module->ports) { @@ -1089,8 +1089,8 @@ void prep_box(RTLIL::Design *design) #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second.first); + if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", module, + port_name.unescape(), it->second.first); } #endif } @@ -1135,7 +1135,7 @@ void prep_box(RTLIL::Design *design) outputs.emplace_back(wire, i); } - ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int(); + ss << module->name.unescape() << " " << module->attributes.at(ID::abc9_box_id).as_int(); bool has_model = module->get_bool_attribute(ID::whitebox) || !module->get_bool_attribute(ID::blackbox); ss << " " << (has_model ? "1" : "0"); ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; @@ -1148,15 +1148,15 @@ void prep_box(RTLIL::Design *design) else ss << " "; if (GetSize(i.wire) == 1) - ss << log_id(i.wire); + ss << i.wire->name.unescape(); else - ss << log_id(i.wire) << "[" << i.offset << "]"; + ss << i.wire->name.unescape() << "[" << i.offset << "]"; } ss << std::endl; auto &t = timing.setup_module(module); if (t.comb.empty() && !outputs.empty() && !inputs.empty()) { - log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module)); + log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", module); } for (const auto &o : outputs) { @@ -1174,9 +1174,9 @@ void prep_box(RTLIL::Design *design) } ss << " # "; if (GetSize(o.wire) == 1) - ss << log_id(o.wire); + ss << o.wire->name.unescape(); else - ss << log_id(o.wire) << "[" << o.offset << "]"; + ss << o.wire->name.unescape() << "[" << o.offset << "]"; ss << std::endl; } ss << std::endl; @@ -1206,7 +1206,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name)); if (mapped_mod == NULL) - log_error("ABC output file does not contain a module `%s$abc'.\n", log_id(module)); + log_error("ABC output file does not contain a module `%s$abc'.\n", module); for (auto w : mapped_mod->wires()) { auto nw = module->addWire(remap_name(w->name), GetSize(w)); @@ -1387,7 +1387,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) else { RTLIL::Cell *existing_cell = module->cell(mapped_cell->name); if (!existing_cell) - log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell)); + log_error("Cannot find existing box cell with name '%s' in original design.\n", mapped_cell); if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { SigBit I = mapped_cell->getPort(ID(i)); @@ -1924,12 +1924,12 @@ struct Abc9OpsPass : public Pass { for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { - log("Skipping module %s as it contains processes.\n", log_id(mod)); + log("Skipping module %s as it contains processes.\n", mod); continue; } if (!design->selected_whole_module(mod)) - log_error("Can't handle partially selected module %s!\n", log_id(mod)); + log_error("Can't handle partially selected module %s!\n", mod); if (!write_lut_dst.empty()) write_lut(mod, write_lut_dst); diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 9850ff609..0a312fb77 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -178,7 +178,7 @@ struct AbcNewPass : public ScriptPass { tmpdir = make_temp_dir(tmpdir); modname = mod->name.str(); exe_options = abc_exe_options; - log_header(active_design, "Mapping module '%s'.\n", log_id(mod)); + log_header(active_design, "Mapping module '%s'.\n", mod); log_push(); active_design->select(mod); } diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc index 19e568a61..6b7e0c377 100644 --- a/passes/techmap/aigmap.cc +++ b/passes/techmap/aigmap.cc @@ -150,21 +150,21 @@ struct AigmapPass : public Pass { if (not_replaced_count == 0 && replaced_cells.empty()) continue; - log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", log_id(module), + log("Module %s: replaced %d cells with %d new cells, skipped %d cells.\n", module, GetSize(replaced_cells), GetSize(module->cells()) - orig_num_cells, not_replaced_count); if (!stat_replaced.empty()) { stat_replaced.sort(); log(" replaced %d cell types:\n", GetSize(stat_replaced)); for (auto &it : stat_replaced) - log("%8d %s\n", it.second, log_id(it.first)); + log("%8d %s\n", it.second, it.first.unescape()); } if (!stat_not_replaced.empty()) { stat_not_replaced.sort(); log(" not replaced %d cell types:\n", GetSize(stat_not_replaced)); for (auto &it : stat_not_replaced) - log("%8d %s\n", it.second, log_id(it.first)); + log("%8d %s\n", it.second, it.first.unescape()); } for (auto cell : replaced_cells) diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc index 10f93d925..5cce8c0ee 100644 --- a/passes/techmap/alumacc.cc +++ b/passes/techmap/alumacc.cc @@ -156,7 +156,7 @@ struct AlumaccWorker if (!cell->type.in(ID($pos), ID($neg), ID($add), ID($sub), ID($mul))) continue; - log(" creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type)); + log(" creating $macc model for %s (%s).\n", cell, cell->type.unescape()); maccnode_t *n = new maccnode_t; Macc::term_t new_term; @@ -267,7 +267,7 @@ struct AlumaccWorker if (GetSize(other_n->y) != GetSize(n->y) && macc_may_overflow(other_n->macc, GetSize(other_n->y), port.is_signed)) continue; - log(" merging $macc model for %s into %s.\n", log_id(other_n->cell), log_id(n->cell)); + log(" merging $macc model for %s into %s.\n", other_n->cell, n->cell); bool do_subtract = port.do_subtract; for (int j = 0; j < GetSize(other_n->macc.terms); j++) { @@ -351,7 +351,7 @@ struct AlumaccWorker if (!subtract_b && B < A && GetSize(B)) std::swap(A, B); - log(" creating $alu model for $macc %s.\n", log_id(n->cell)); + log(" creating $alu model for $macc %s.\n", n->cell); alunode = new alunode_t; alunode->cells.push_back(n->cell); @@ -383,7 +383,7 @@ struct AlumaccWorker macc_counter++; - log(" creating $macc cell for %s: %s\n", log_id(n->cell), log_id(cell)); + log(" creating $macc cell for %s: %s\n", n->cell, cell); cell->set_src_attribute(n->cell->get_src_attribute()); @@ -412,7 +412,7 @@ struct AlumaccWorker for (auto cell : lge_cells) { - log(" creating $alu model for %s (%s):", log_id(cell), log_id(cell->type)); + log(" creating $alu model for %s (%s):", cell, cell->type.unescape()); bool cmp_less = cell->type.in(ID($lt), ID($le)); bool cmp_equal = cell->type.in(ID($le), ID($ge)); @@ -451,7 +451,7 @@ struct AlumaccWorker sig_alu[RTLIL::SigSig(A, B)].insert(n); log(" new $alu\n"); } else { - log(" merged with %s.\n", log_id(n->cells.front())); + log(" merged with %s.\n", n->cells.front()); } n->cells.push_back(cell); @@ -484,7 +484,7 @@ struct AlumaccWorker } if (n != nullptr) { - log(" creating $alu model for %s (%s): merged with %s.\n", log_id(cell), log_id(cell->type), log_id(n->cells.front())); + log(" creating $alu model for %s (%s): merged with %s.\n", cell, cell->type.unescape(), n->cells.front()); n->cells.push_back(cell); n->cmp.push_back(std::make_tuple(false, false, cmp_equal, !cmp_equal, false, Y)); } @@ -503,8 +503,8 @@ struct AlumaccWorker log(" creating $pos cell for "); for (int i = 0; i < GetSize(n->cells); i++) - log("%s%s", i ? ", ": "", log_id(n->cells[i])); - log(": %s\n", log_id(n->alu_cell)); + log("%s%s", i ? ", ": "", n->cells[i]); + log(": %s\n", n->alu_cell); goto delete_node; } @@ -514,8 +514,8 @@ struct AlumaccWorker log(" creating $alu cell for "); for (int i = 0; i < GetSize(n->cells); i++) - log("%s%s", i ? ", ": "", log_id(n->cells[i])); - log(": %s\n", log_id(n->alu_cell)); + log("%s%s", i ? ", ": "", n->cells[i]); + log(": %s\n", n->alu_cell); if (n->cells.size() > 0) n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute()); @@ -562,7 +562,7 @@ struct AlumaccWorker void run() { - log("Extracting $alu and $macc cells in module %s:\n", log_id(module)); + log("Extracting $alu and $macc cells in module %s:\n", module); count_bit_users(); extract_macc(); diff --git a/passes/techmap/arith_tree.cc b/passes/techmap/arith_tree.cc index 9494fa958..259e0c5bb 100644 --- a/passes/techmap/arith_tree.cc +++ b/passes/techmap/arith_tree.cc @@ -316,7 +316,7 @@ struct Rewriter { int compressor_count; auto [a, b] = wallace_reduce_scheduled(module, extended, width, &compressor_count); - log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, compressor_count, (int)operands.size(), log_id(module)); + log(" %s -> %d $fa + 1 $add (%d operands, module %s)\n", desc, compressor_count, (int)operands.size(), module); // Emit final add module->addAdd(NEW_ID, a, b, result_y, false); diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc index 58ac25f51..4c97f6ab1 100644 --- a/passes/techmap/attrmap.cc +++ b/passes/techmap/attrmap.cc @@ -131,13 +131,13 @@ void attrmap_apply(string objname, vector> &actio if (new_attr != attr) log("Changed attribute on %s: %s=%s -> %s=%s\n", objname, - log_id(attr.first), log_const(attr.second), log_id(new_attr.first), log_const(new_attr.second)); + attr.first.unescape(), log_const(attr.second), new_attr.first.unescape(), log_const(new_attr.second)); new_attributes[new_attr.first] = new_attr.second; if (0) delete_this_attr: - log("Removed attribute on %s: %s=%s\n", objname, log_id(attr.first), log_const(attr.second)); + log("Removed attribute on %s: %s=%s\n", objname, attr.first.unescape(), log_const(attr.second)); } attributes.swap(new_attributes); @@ -264,14 +264,14 @@ struct AttrmapPass : public Pass { if (modattr_mode) { for (auto module : design->all_selected_whole_modules()) - attrmap_apply(stringf("%s", log_id(module)), actions, module->attributes); + attrmap_apply(stringf("%s", module), actions, module->attributes); } else { for (auto module : design->all_selected_modules()) { for (auto memb : module->selected_members()) - attrmap_apply(stringf("%s.%s", log_id(module), log_id(memb)), actions, memb->attributes); + attrmap_apply(stringf("%s.%s", module, memb), actions, memb->attributes); // attrmap already applied to process itself during above loop, but not its children for (auto proc : module->selected_processes()) @@ -280,10 +280,10 @@ struct AttrmapPass : public Pass { while (!all_cases.empty()) { RTLIL::CaseRule *cs = all_cases.back(); all_cases.pop_back(); - attrmap_apply(stringf("%s.%s (case)", log_id(module), log_id(proc)), actions, cs->attributes); + attrmap_apply(stringf("%s.%s (case)", module, proc), actions, cs->attributes); for (auto &sw : cs->switches) { - attrmap_apply(stringf("%s.%s (switch)", log_id(module), log_id(proc)), actions, sw->attributes); + attrmap_apply(stringf("%s.%s (switch)", module, proc), actions, sw->attributes); all_cases.insert(all_cases.end(), sw->cases.begin(), sw->cases.end()); } } @@ -328,7 +328,7 @@ struct ParamapPass : public Pass { for (auto module : design->selected_modules()) for (auto cell : module->selected_cells()) - attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->parameters); + attrmap_apply(stringf("%s.%s", module, cell), actions, cell->parameters); } } ParamapPass; diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc index 65b63daf1..cff7d8697 100644 --- a/passes/techmap/attrmvcp.cc +++ b/passes/techmap/attrmvcp.cc @@ -121,8 +121,8 @@ struct AttrmvcpPass : public Pass { for (auto bit : sigmap(wire)) if (net2cells.count(bit)) for (auto cell : net2cells.at(bit)) { - log("Moving attribute %s=%s from %s.%s to %s.%s.\n", log_id(attr.first), log_const(attr.second), - log_id(module), log_id(wire), log_id(module), log_id(cell)); + log("Moving attribute %s=%s from %s.%s to %s.%s.\n", attr.first.unescape(), log_const(attr.second), + module, wire, module, cell); cell->attributes[attr.first] = attr.second; did_something = true; } diff --git a/passes/techmap/booth.cc b/passes/techmap/booth.cc index c0bad784a..630c83f8c 100644 --- a/passes/techmap/booth.cc +++ b/passes/techmap/booth.cc @@ -224,7 +224,7 @@ struct BoothPassWorker { macc.from_cell(cell); if (!macc.is_simple_product()) { - log_debug("Not mapping cell %s: not a simple macc cell\n", log_id(cell)); + log_debug("Not mapping cell %s: not a simple macc cell\n", cell); continue; } @@ -240,11 +240,11 @@ struct BoothPassWorker { if (x_sz < 4 || y_sz < 4 || z_sz < 8) { log_debug("Not mapping cell %s sized at %dx%x, %x: size below threshold\n", - log_id(cell), x_sz, y_sz, z_sz); + cell, x_sz, y_sz, z_sz); continue; } - log("Mapping cell %s to %s Booth multiplier\n", log_id(cell), is_signed ? "signed" : "unsigned"); + log("Mapping cell %s to %s Booth multiplier\n", cell, is_signed ? "signed" : "unsigned"); // To simplify the generator size the arguments // to be the same. Then allow logic synthesis to diff --git a/passes/techmap/bufnorm.cc b/passes/techmap/bufnorm.cc index 123687255..9e6ca2e30 100644 --- a/passes/techmap/bufnorm.cc +++ b/passes/techmap/bufnorm.cc @@ -249,7 +249,7 @@ struct BufnormPass : public Pass { for (auto module : design->selected_modules()) { - log("Buffer-normalizing module %s.\n", log_id(module)); + log("Buffer-normalizing module %s.\n", module); SigMap sigmap(module); module->new_connections({}); @@ -293,7 +293,7 @@ struct BufnormPass : public Pass { bit2wires[keybit].insert(wire); if (wire->port_input) { - log(" primary input: %s\n", log_id(wire)); + log(" primary input: %s\n", wire); for (auto bit : SigSpec(wire)) mapped_bits[sigmap(bit)] = bit; } else { @@ -392,7 +392,7 @@ struct BufnormPass : public Pass { if (w->name.isPublic()) log(" directly driven by cell %s port %s: %s\n", - log_id(cell), log_id(conn.first), log_id(w)); + cell, conn.first.unescape(), w); for (auto bit : SigSpec(w)) mapped_bits[sigmap(bit)] = bit; @@ -502,7 +502,7 @@ struct BufnormPass : public Pass { if (conn.second != newsig) { log(" fixing input signal on cell %s port %s: %s\n", - log_id(cell), log_id(conn.first), log_signal(newsig)); + cell, conn.first.unescape(), newsig); cell->setPort(conn.first, newsig); count_updated_cellports++; } diff --git a/passes/techmap/cellmatch.cc b/passes/techmap/cellmatch.cc index ce1a75193..a2e2393d0 100644 --- a/passes/techmap/cellmatch.cc +++ b/passes/techmap/cellmatch.cc @@ -20,7 +20,7 @@ SigSpec module_inputs(Module *m) continue; if (w->width != 1) log_error("Unsupported wide port (%s) of non-unit width found in module %s.\n", - log_id(w), log_id(m)); + w, m); ret.append(w); } return ret; @@ -36,7 +36,7 @@ SigSpec module_outputs(Module *m) continue; if (w->width != 1) log_error("Unsupported wide port (%s) of non-unit width found in module %s.\n", - log_id(w), log_id(m)); + w, m); ret.append(w); } return ret; @@ -96,7 +96,7 @@ bool derive_module_luts(Module *m, std::vector &luts) ff_types.setup_stdcells_mem(); for (auto cell : m->cells()) { if (ff_types.cell_known(cell->type)) { - log("Ignoring module '%s' which isn't purely combinational.\n", log_id(m)); + log("Ignoring module '%s' which isn't purely combinational.\n", m); return false; } } @@ -106,7 +106,7 @@ bool derive_module_luts(Module *m, std::vector &luts) int ninputs = inputs.size(), noutputs = outputs.size(); if (ninputs > 6) { - log_warning("Skipping module %s with more than 6 inputs bits.\n", log_id(m)); + log_warning("Skipping module %s with more than 6 inputs bits.\n", m); return false; } @@ -123,7 +123,7 @@ bool derive_module_luts(Module *m, std::vector &luts) if (!ceval.eval(bit)) { log("Failed to evaluate output '%s' in module '%s'.\n", - log_signal(outputs[j]), log_id(m)); + log_signal(outputs[j]), m); return false; } @@ -203,7 +203,7 @@ struct CellmatchPass : Pass { for (auto lut : luts) p_classes.insert(p_class(ninputs, lut)); - log_debug("Registered %s\n", log_id(m)); + log_debug("Registered %s\n", m); // save as a viable target targets[p_classes].push_back(Target{m, luts}); @@ -237,7 +237,7 @@ struct CellmatchPass : Pass { p_classes.insert(p_class(inputs.size(), lut)); for (auto target : targets[p_classes]) { - log_debug("Candidate %s for matching to %s\n", log_id(target.module), log_id(m)); + log_debug("Candidate %s for matching to %s\n", target.module, m); SigSpec target_inputs = module_inputs(target.module); SigSpec target_outputs = module_outputs(target.module); @@ -271,10 +271,10 @@ struct CellmatchPass : Pass { } if (match) { - log("Module %s matches %s\n", log_id(m), log_id(target.module)); + log("Module %s matches %s\n", m, target.module); // Add target.module to map_design ("$cellmatch") // as a techmap rule to match m and replace it with target.module - Module *map = map_design->addModule(stringf("\\_60_%s_%s", log_id(m), log_id(target.module))); + Module *map = map_design->addModule(stringf("\\_60_%s_%s", m, target.module)); Cell *cell = map->addCell(ID::_TECHMAP_REPLACE_, target.module->name); map->attributes[ID(techmap_celltype)] = m->name.str(); diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc index 7003c6656..7954b7891 100644 --- a/passes/techmap/clkbufmap.cc +++ b/passes/techmap/clkbufmap.cc @@ -257,14 +257,14 @@ struct ClkbufmapPass : public Pass { RTLIL::Cell *cell = nullptr; bool is_input = wire->port_input && !inpad_celltype.empty() && module->get_bool_attribute(ID::top); if (!buf_celltype.empty() && (!is_input || buffer_inputs)) { - log("Inserting %s on %s.%s[%d].\n", buf_celltype, log_id(module), log_id(wire), i); + log("Inserting %s on %s.%s[%d].\n", buf_celltype, module, wire, i); cell = module->addCell(NEW_ID, RTLIL::escape_id(buf_celltype)); iwire = module->addWire(NEW_ID); cell->setPort(RTLIL::escape_id(buf_portname), mapped_wire_bit); cell->setPort(RTLIL::escape_id(buf_portname2), iwire); } if (is_input) { - log("Inserting %s on %s.%s[%d].\n", inpad_celltype, log_id(module), log_id(wire), i); + log("Inserting %s on %s.%s[%d].\n", inpad_celltype, module, wire, i); RTLIL::Cell *cell2 = module->addCell(NEW_ID, RTLIL::escape_id(inpad_celltype)); if (iwire) { cell2->setPort(RTLIL::escape_id(inpad_portname), iwire); diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc index 5245331f8..103fba103 100644 --- a/passes/techmap/deminout.cc +++ b/passes/techmap/deminout.cc @@ -126,7 +126,7 @@ struct DeminoutPass : public Pass { } if (new_input != new_output) { - log("Demoting inout port %s.%s to %s.\n", log_id(module), log_id(wire), new_input ? "input" : "output"); + log("Demoting inout port %s.%s to %s.\n", module, wire, new_input ? "input" : "output"); wire->port_input = new_input; wire->port_output = new_output; keep_running = true; diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index 013675c8a..912f7fb81 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -123,14 +123,14 @@ struct DffinitPass : public Pass { if (noreinit && value[i] != State::Sx && value[i] != initval[i]) log_error("Trying to assign a different init value for %s.%s.%s which technically " "have a conflicted init value.\n", - log_id(module), log_id(cell), log_id(it.second)); + module, cell, it.second.unescape()); value.set(i, initval[i]); } if (highlow_mode && GetSize(value) != 0) { if (GetSize(value) != 1) log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n", - log_id(module), log_id(cell), log_id(it.second)); + module, cell, it.second.unescape()); if (value[0] == State::S1) value = Const(high_string); else @@ -138,8 +138,8 @@ struct DffinitPass : public Pass { } if (value.size() != 0) { - log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second), - log_id(it.first), log_signal(sig), log_signal(value)); + log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", module, cell, it.second.unescape(), + it.first.unescape(), log_signal(sig), log_signal(value)); cell->setParam(it.second, value); } } diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc index dc29750c8..3cba527b2 100644 --- a/passes/techmap/dfflegalize.cc +++ b/passes/techmap/dfflegalize.cc @@ -263,7 +263,7 @@ struct DffLegalizePass : public Pass { } void fail_ff(const FfData &ff, const char *reason) { - log_error("FF %s.%s (type %s) cannot be legalized: %s\n", log_id(ff.module->name), log_id(ff.cell->name), log_id(ff.cell->type), reason); + log_error("FF %s.%s (type %s) cannot be legalized: %s\n", ff.module->name.unescape(), ff.cell->name.unescape(), ff.cell->type.unescape(), reason); } bool try_flip(FfData &ff, int supported_mask) { @@ -381,7 +381,7 @@ struct DffLegalizePass : public Pass { if (ff.has_ce && !supported_cells[FF_ADFFE]) ff.unmap_ce(); - log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name)); + log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape()); log_assert(ff.width == 1); ff.remove(); @@ -600,7 +600,7 @@ struct DffLegalizePass : public Pass { ff.unmap_ce(); if (ff.cell) - log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name)); + log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape()); emulate_split_init_arst(ff); return; } @@ -752,7 +752,7 @@ struct DffLegalizePass : public Pass { // The only hope left is breaking down to adlatch + dlatch + dlatch + mux. if (ff.cell) - log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name)); + log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", ff.module->name.unescape(), ff.cell->name.unescape()); ff.remove(); emulate_split_init_arst(ff); diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 7461e21d8..d4d13d673 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -155,12 +155,12 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, std::map sig_bit_ref; if (sel && !sel->selected(mod)) { - log(" Skipping module %s as it is not selected.\n", log_id(mod->name)); + log(" Skipping module %s as it is not selected.\n", mod->name.unescape()); return false; } if (mod->processes.size() > 0) { - log(" Skipping module %s as it contains unprocessed processes.\n", log_id(mod->name)); + log(" Skipping module %s as it contains unprocessed processes.\n", mod->name.unescape()); return false; } @@ -674,7 +674,7 @@ struct ExtractPass : public Pass { } RTLIL::Cell *new_cell = replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result); design->select(haystack_map.at(result.haystackGraphId), new_cell); - log(" new cell: %s\n", log_id(new_cell->name)); + log(" new cell: %s\n", new_cell->name.unescape()); } } } @@ -691,12 +691,12 @@ struct ExtractPass : public Pass { for (auto &result: results) { log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits); - log(" primary match in %s:", log_id(haystack_map.at(result.graphId)->name)); + log(" primary match in %s:", haystack_map.at(result.graphId)->name.unescape()); for (auto &node : result.nodes) log(" %s", RTLIL::unescape_id(node.nodeId)); log("\n"); for (auto &it : result.matchesPerGraph) - log(" matches in %s: %d\n", log_id(haystack_map.at(it.first)->name), it.second); + log(" matches in %s: %d\n", haystack_map.at(it.first)->name.unescape(), it.second); RTLIL::Module *mod = haystack_map.at(result.graphId); std::set cells; @@ -716,7 +716,7 @@ struct ExtractPass : public Pass { } RTLIL::Module *newMod = new RTLIL::Module; - newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, log_id(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits); + newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, haystack_map.at(result.graphId)->name.unescape(), result.totalMatchesAfterLimits); map->add(newMod); for (auto wire : wires) { diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc index c45792f66..c0e45a70e 100644 --- a/passes/techmap/extract_counter.cc +++ b/passes/techmap/extract_counter.cc @@ -541,7 +541,7 @@ void counter_worker( { extract_value = *sa.begin(); log(" Signal %s declared at %s has COUNT_EXTRACT = %s\n", - log_id(port_wire), + port_wire, count_reg_src.c_str(), extract_value.c_str()); @@ -604,14 +604,14 @@ void counter_worker( { log_error( "Counter extraction is set to FORCE on register %s, but a counter could not be inferred (%s)\n", - log_id(port_wire), + port_wire, reasons[reason]); } return; } //Get new cell name - string countname = string("$COUNTx$") + log_id(extract.rwire->name.str()); + string countname = string("$COUNTx$") + extract.rwire->name.unescape(); //Wipe all of the old connections to the ALU cell->unsetPort(ID::A); @@ -697,7 +697,7 @@ void counter_worker( //Hook up any parallel outputs for(auto load : extract.pouts) { - log(" Counter has parallel output to cell %s port %s\n", log_id(load.cell->name), log_id(load.port)); + log(" Counter has parallel output to cell %s port %s\n", load.cell->name.unescape(), load.port.unescape()); } if(extract.has_pout) { @@ -731,7 +731,7 @@ void counter_worker( countname.c_str(), extract.count_is_up ? "to" : "from", extract.count_value, - log_id(extract.rwire->name), + extract.rwire->name.unescape(), count_reg_src.c_str()); //Optimize the counter @@ -887,13 +887,13 @@ struct ExtractCounterPass : public Pass { for(auto cell : cells_to_remove) { - //log("Removing cell %s\n", log_id(cell->name)); + //log("Removing cell %s\n", cell); module->remove(cell); } for(auto cpair : cells_to_rename) { - //log("Renaming cell %s to %s\n", log_id(cpair.first->name), cpair.second); + //log("Renaming cell %s to %s\n", cpair.first, cpair.second); module->rename(cpair.first, cpair.second); } } diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc index 46ab7e520..15cdc54c9 100644 --- a/passes/techmap/extract_fa.cc +++ b/passes/techmap/extract_fa.cc @@ -289,7 +289,7 @@ struct ExtractFaWorker void run() { - log("Extracting full/half adders from %s:\n", log_id(module)); + log("Extracting full/half adders from %s:\n", module); for (auto it : driver) { @@ -381,7 +381,7 @@ struct ExtractFaWorker auto &fa = facache.at(fakey); X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else if (facache.count(fakey_inv)) @@ -390,14 +390,14 @@ struct ExtractFaWorker invert_xy = true; X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else { Cell *cell = module->addCell(NEW_ID, ID($fa)); cell->setParam(ID::WIDTH, 1); - log(" Created $fa cell %s.\n", log_id(cell)); + log(" Created $fa cell %s.\n", cell); cell->setPort(ID::A, f3i.inv_a ? module->NotGate(NEW_ID, A) : A); cell->setPort(ID::B, f3i.inv_b ? module->NotGate(NEW_ID, B) : B); @@ -488,7 +488,7 @@ struct ExtractFaWorker auto &fa = facache.at(fakey); X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else if (facache.count(fakey_inv)) @@ -497,14 +497,14 @@ struct ExtractFaWorker invert_xy = true; X = get<0>(fa); Y = get<1>(fa); - log(" Reusing $fa cell %s.\n", log_id(get<2>(fa))); + log(" Reusing $fa cell %s.\n", get<2>(fa)); } else { Cell *cell = module->addCell(NEW_ID, ID($fa)); cell->setParam(ID::WIDTH, 1); - log(" Created $fa cell %s.\n", log_id(cell)); + log(" Created $fa cell %s.\n", cell); cell->setPort(ID::A, f2i.inv_a ? module->NotGate(NEW_ID, A) : A); cell->setPort(ID::B, f2i.inv_b ? module->NotGate(NEW_ID, B) : B); diff --git a/passes/techmap/extractinv.cc b/passes/techmap/extractinv.cc index 5050e1464..7444369cc 100644 --- a/passes/techmap/extractinv.cc +++ b/passes/techmap/extractinv.cc @@ -100,7 +100,7 @@ struct ExtractinvPass : public Pass { continue; SigSpec sig = port.second; if (it2->second.size() != sig.size()) - log_error("The inversion parameter needs to be the same width as the port (%s.%s port %s parameter %s)", log_id(module->name), log_id(cell->type), log_id(port.first), log_id(param_name)); + log_error("The inversion parameter needs to be the same width as the port (%s.%s port %s parameter %s)", module->name.unescape(), cell->type.unescape(), port.first.unescape(), param_name.unescape()); RTLIL::Const invmask = it2->second; cell->parameters.erase(param_name); if (invmask.is_fully_zero()) @@ -111,7 +111,7 @@ struct ExtractinvPass : public Pass { RTLIL::Cell *icell = module->addCell(NEW_ID, RTLIL::escape_id(inv_celltype)); icell->setPort(RTLIL::escape_id(inv_portname), SigSpec(iwire, i)); icell->setPort(RTLIL::escape_id(inv_portname2), sig[i]); - log("Inserting %s on %s.%s.%s[%d].\n", inv_celltype, log_id(module), log_id(cell->type), log_id(port.first), i); + log("Inserting %s on %s.%s.%s[%d].\n", inv_celltype, module, cell->type.unescape(), port.first.unescape(), i); sig[i] = SigBit(iwire, i); } cell->setPort(port.first, sig); diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index f5f225a9b..c9d561a4c 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -598,7 +598,7 @@ struct FlowmapWorker continue; if (!cell->known()) - log_error("Cell %s (%s.%s) is unknown.\n", cell->type, log_id(module), log_id(cell)); + log_error("Cell %s (%s.%s) is unknown.\n", cell->type, module, cell); pool fanout; for (auto conn : cell->connections()) @@ -636,7 +636,7 @@ struct FlowmapWorker if (fanin > order) log_error("Cell %s (%s.%s) with fan-in %d cannot be mapped to a %d-LUT.\n", - cell->type.c_str(), log_id(module), log_id(cell), fanin, order); + cell->type.c_str(), module, cell, fanin, order); gate_count++; gate_area += 1 << fanin; @@ -1356,14 +1356,14 @@ struct FlowmapWorker auto origin = node_origins[node]; if (origin.cell->getPort(origin.port).size() == 1) log("Packing %s.%s.%s (%s).\n", - log_id(module), log_id(origin.cell), origin.port.c_str(), log_signal(node)); + module, origin.cell, origin.port.c_str(), log_signal(node)); else log("Packing %s.%s.%s [%d] (%s).\n", - log_id(module), log_id(origin.cell), origin.port.c_str(), origin.offset, log_signal(node)); + module, origin.cell, origin.port.c_str(), origin.offset, log_signal(node)); } else { - log("Packing %s.%s.\n", log_id(module), log_signal(node)); + log("Packing %s.%s.\n", module, log_signal(node)); } for (auto gate_node : lut_gates[node]) @@ -1376,10 +1376,10 @@ struct FlowmapWorker auto gate_origin = node_origins[gate_node]; if (gate_origin.cell->getPort(gate_origin.port).size() == 1) log(" Packing %s.%s.%s (%s).\n", - log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), log_signal(gate_node)); + module, gate_origin.cell, gate_origin.port.c_str(), log_signal(gate_node)); else log(" Packing %s.%s.%s [%d] (%s).\n", - log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node)); + module, gate_origin.cell, gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node)); } vector input_nodes(lut_edges_bw[node].begin(), lut_edges_bw[node].end()); @@ -1423,9 +1423,9 @@ struct FlowmapWorker lut_area += lut_table.size(); if ((int)input_nodes.size() >= minlut) - log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), log_id(module), log_id(lut)); + log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), module, lut); else - log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), log_id(module), log_id(lut), minlut); + log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), module, lut, minlut); } for (auto node : mapped_nodes) diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc index f288987a1..5674de71f 100644 --- a/passes/techmap/insbuf.cc +++ b/passes/techmap/insbuf.cc @@ -83,7 +83,7 @@ struct InsbufPass : public Pass { if (!lhs.wire || !design->selected(module, lhs.wire)) { new_conn.first.append(lhs); new_conn.second.append(rhs); - log("Skip %s: %s -> %s\n", log_id(module), log_signal(rhs), log_signal(lhs)); + log("Skip %s: %s -> %s\n", module, log_signal(rhs), log_signal(lhs)); continue; } @@ -98,7 +98,7 @@ struct InsbufPass : public Pass { cell->setPort(in_portname, rhs); cell->setPort(out_portname, lhs); - log("Add %s/%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs)); + log("Add %s/%s: %s -> %s\n", module, cell, log_signal(rhs), log_signal(lhs)); bufcells.insert(cell); } @@ -115,8 +115,8 @@ struct InsbufPass : public Pass { auto s = sigmap(port.second); if (s == port.second) continue; - log("Rewrite %s/%s/%s: %s -> %s\n", log_id(module), log_id(cell), - log_id(port.first), log_signal(port.second), log_signal(s)); + log("Rewrite %s/%s/%s: %s -> %s\n", module, cell, + port.first.unescape(), log_signal(port.second), log_signal(s)); cell->setPort(port.first, s); } } diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc index d929de300..d7667d6f5 100644 --- a/passes/techmap/iopadmap.cc +++ b/passes/techmap/iopadmap.cc @@ -231,7 +231,7 @@ struct IopadmapPass : public Pass { for (int i = 0; i < GetSize(wire); i++) if (buf_bits.count(sigmap(SigBit(wire, i)))) { buf_ports.insert(make_pair(module->name, make_pair(wire->name, i))); - log("Marking already mapped port: %s.%s[%d].\n", log_id(module), log_id(wire), i); + log("Marking already mapped port: %s.%s[%d].\n", module, wire, i); } } @@ -324,10 +324,10 @@ struct IopadmapPass : public Pass { if (wire->port_input) { - log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype); + log("Mapping port %s.%s[%d] using %s.\n", module, wire, i, tinoutpad_celltype); Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), + module->uniquify(stringf("$iopadmap$%s.%s[%d]", module, wire, i)), RTLIL::escape_id(tinoutpad_celltype)); if (tinoutpad_neg_oe) @@ -348,10 +348,10 @@ struct IopadmapPass : public Pass { if (!tinoutpad_portname_pad.empty()) rewrite_bits[wire][i] = make_pair(cell, RTLIL::escape_id(tinoutpad_portname_pad)); } else { - log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype); + log("Mapping port %s.%s[%d] using %s.\n", module, wire, i, toutpad_celltype); Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)), + module->uniquify(stringf("$iopadmap$%s.%s[%d]", module, wire, i)), RTLIL::escape_id(toutpad_celltype)); if (toutpad_neg_oe) @@ -433,7 +433,7 @@ struct IopadmapPass : public Pass { SigBit wire_bit(wire, i); RTLIL::Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), + module->uniquify(stringf("$iopadmap$%s.%s", module->name.unescape(), wire->name.unescape())), RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), wire_bit); @@ -449,14 +449,14 @@ struct IopadmapPass : public Pass { else { RTLIL::Cell *cell = module->addCell( - module->uniquify(stringf("$iopadmap$%s.%s", log_id(module->name), log_id(wire->name))), + module->uniquify(stringf("$iopadmap$%s.%s", module->name.unescape(), wire->name.unescape())), RTLIL::escape_id(celltype)); cell->setPort(RTLIL::escape_id(portname_int), RTLIL::SigSpec(wire)); if (!portname_pad.empty()) { RTLIL::Wire *new_wire = NULL; new_wire = module->addWire( - module->uniquify(stringf("$iopadmap$%s", log_id(wire))), + module->uniquify(stringf("$iopadmap$%s", wire)), wire); module->swap_names(new_wire, wire); wire->attributes.clear(); @@ -500,7 +500,7 @@ struct IopadmapPass : public Pass { for (auto &it : rewrite_bits) { RTLIL::Wire *wire = it.first; RTLIL::Wire *new_wire = module->addWire( - module->uniquify(stringf("$iopadmap$%s", log_id(wire))), + module->uniquify(stringf("$iopadmap$%s", wire)), wire); module->swap_names(new_wire, wire); wire->attributes.clear(); diff --git a/passes/techmap/lut2bmux.cc b/passes/techmap/lut2bmux.cc index 42042c942..1073b1208 100644 --- a/passes/techmap/lut2bmux.cc +++ b/passes/techmap/lut2bmux.cc @@ -49,7 +49,7 @@ struct Lut2BmuxPass : public Pass { cell->setPort(ID::A, cell->getParam(ID::LUT)); cell->unsetParam(ID::LUT); cell->fixup_parameters(); - log("Converted %s.%s to BMUX cell.\n", log_id(module), log_id(cell)); + log("Converted %s.%s to BMUX cell.\n", module, cell); } } } diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc index 3d45734ec..2ddb16d61 100644 --- a/passes/techmap/lut2mux.cc +++ b/passes/techmap/lut2mux.cc @@ -97,7 +97,7 @@ struct Lut2muxPass : public Pass { if (cell->type == ID($lut)) { IdString cell_name = cell->name; int count = lut2mux(cell, word_mode); - log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count); + log("Converted %s.%s to %d MUX cells.\n", module, cell_name.unescape(), count); } } } diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index 42b615002..cb041f615 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -404,7 +404,7 @@ struct MaccmapPass : public Pass { for (auto mod : design->selected_modules()) for (auto cell : mod->selected_cells()) if (cell->type.in(ID($macc), ID($macc_v2))) { - log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type)); + log("Mapping %s.%s (%s).\n", mod, cell, cell->type.unescape()); maccmap(mod, cell, unmap_mode); mod->remove(cell); } diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 2656f30ce..719a346d8 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -596,7 +596,7 @@ struct MuxcoverWorker void run() { - log("Covering MUX trees in module %s..\n", log_id(module)); + log("Covering MUX trees in module %s..\n", module); treeify(); diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 928182970..9f4e307f9 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -284,7 +284,7 @@ struct ShregmapWorker Cell *last_cell = chain[cursor+depth-1]; log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); + module, first_cell, module, last_cell, depth); dff_count += depth; shreg_count += 1; diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 93001df35..2c252deb3 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -580,7 +580,7 @@ struct SimplemapPass : public Pass { continue; if (!design->selected(mod, cell)) continue; - log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type)); + log("Mapping %s.%s (%s).\n", mod, cell, cell->type.unescape()); mappers.at(cell->type)(mod, cell); mod->remove(cell); } diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index cf7ce56e2..5827feb92 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -93,17 +93,17 @@ struct TechmapWorker RTLIL::SigBit bit = sigmap(conn.second[i]); if (bit.wire == nullptr) { if (verbose) - log(" Constant input on bit %d of port %s: %s\n", i, log_id(conn.first), log_signal(bit)); - constmap_info += stringf("|%s %d %d", log_id(conn.first), i, bit.data); + log(" Constant input on bit %d of port %s: %s\n", i, conn.first.unescape(), log_signal(bit)); + constmap_info += stringf("|%s %d %d", conn.first.unescape(), i, bit.data); } else if (connbits_map.count(bit)) { if (verbose) - log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, log_id(conn.first), - connbits_map.at(bit).second, log_id(connbits_map.at(bit).first)); - constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i, - log_id(connbits_map.at(bit).first), connbits_map.at(bit).second); + log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, conn.first.unescape(), + connbits_map.at(bit).second, connbits_map.at(bit).first.unescape()); + constmap_info += stringf("|%s %d %s %d", conn.first.unescape(), i, + connbits_map.at(bit).first.unescape(), connbits_map.at(bit).second); } else { connbits_map.emplace(bit, std::make_pair(conn.first, i)); - constmap_info += stringf("|%s %d", log_id(conn.first), i); + constmap_info += stringf("|%s %d", conn.first.unescape(), i); } } @@ -146,7 +146,7 @@ struct TechmapWorker if (tpl->processes.size() != 0) { log("Technology map yielded processes:"); for (auto &it : tpl->processes) - log(" %s",log_id(it.first)); + log(" %s",it.first.unescape()); log("\n"); if (autoproc_mode) { Pass::call_on_module(tpl->design, tpl, "proc"); @@ -435,7 +435,7 @@ struct TechmapWorker if (celltypeMap.count(cell->type) == 0) { if (assert_mode && !cell->type.ends_with("_")) - log_error("(ASSERT MODE) No matching template cell for type %s found.\n", log_id(cell->type)); + log_error("(ASSERT MODE) No matching template cell for type %s found.\n", cell->type.unescape()); continue; } @@ -498,10 +498,10 @@ struct TechmapWorker { if ((extern_mode && !in_recursion) || extmapper_name == "wrap") { - std::string m_name = stringf("$extern:%s:%s", extmapper_name, log_id(cell->type)); + std::string m_name = stringf("$extern:%s:%s", extmapper_name, cell->type.unescape()); for (auto &c : cell->parameters) - m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second)); + m_name += stringf(":%s=%s", c.first.unescape(), log_signal(c.second)); if (extmapper_name == "wrap") m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string()); @@ -531,24 +531,24 @@ struct TechmapWorker extmapper_module->check(); if (extmapper_name == "simplemap") { - log("Creating %s with simplemap.\n", log_id(extmapper_module)); + log("Creating %s with simplemap.\n", extmapper_module); if (simplemap_mappers.count(extmapper_cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type)); + log_error("No simplemap mapper for cell type %s found!\n", extmapper_cell->type.unescape()); simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell); extmapper_module->remove(extmapper_cell); } if (extmapper_name == "maccmap") { - log("Creating %s with maccmap.\n", log_id(extmapper_module)); + log("Creating %s with maccmap.\n", extmapper_module); if (!extmapper_cell->type.in(ID($macc), ID($macc_v2))) - log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", log_id(extmapper_cell->type)); + log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", extmapper_cell->type.unescape()); maccmap(extmapper_module, extmapper_cell); extmapper_module->remove(extmapper_cell); } if (extmapper_name == "wrap") { std::string cmd_string = tpl->attributes.at(ID::techmap_wrap).decode_string(); - log("Running \"%s\" on wrapper %s.\n", cmd_string, log_id(extmapper_module)); + log("Running \"%s\" on wrapper %s.\n", cmd_string, extmapper_module); mkdebug.on(); Pass::call_on_module(extmapper_design, extmapper_module, cmd_string); log_continue = true; @@ -563,31 +563,31 @@ struct TechmapWorker goto use_wrapper_tpl; } - auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type)); + auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_module, cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - 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)); + log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), extmapper_module); } else { - auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name, log_id(cell->type)); + auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name, cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), extmapper_name); + log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), extmapper_name); if (extmapper_name == "simplemap") { if (simplemap_mappers.count(cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", log_id(cell->type)); + log_error("No simplemap mapper for cell type %s found!\n", cell->type.unescape()); simplemap_mappers.at(cell->type)(module, cell); } if (extmapper_name == "maccmap") { if (!cell->type.in(ID($macc), ID($macc_v2))) - log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", log_id(cell->type)); + log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", cell->type.unescape()); maccmap(module, cell); } @@ -621,21 +621,21 @@ struct TechmapWorker parameters.emplace(ID::_TECHMAP_CELLNAME_, RTLIL::unescape_id(cell->name)); for (auto &conn : cell->connections()) { - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape())) != 0) { std::vector v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0); - parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); + parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape())) != 0) { std::vector v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) if (bit.wire != nullptr) bit = RTLIL::SigBit(RTLIL::State::Sx); - parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); + parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) { - parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), initvals(conn.second)); + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape())) != 0) { + parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape()), initvals(conn.second)); } } @@ -648,7 +648,7 @@ struct TechmapWorker unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++; for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) { for (auto &bit : sigmap(conn.second)) if (unique_bit_id.count(bit) == 0) unique_bit_id[bit] = unique_bit_id_counter++; @@ -665,7 +665,7 @@ struct TechmapWorker parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits; for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) { SigSpec sm = sigmap(conn.second); RTLIL::Const::Builder builder(GetSize(sm) * bits); for (auto &bit : sm) { @@ -675,7 +675,7 @@ struct TechmapWorker val = val >> 1; } } - parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), builder.build()); + parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape()), builder.build()); } } @@ -724,7 +724,7 @@ struct TechmapWorker RTLIL::SigSpec value = elem.value; if (value.is_fully_const() && value.as_bool()) { log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", - derived_name.c_str(), log_id(elem.wire->name), log_signal(value)); + derived_name.c_str(), elem.wire->name.unescape(), log_signal(value)); techmap_do_cache[tpl] = false; } } @@ -741,7 +741,7 @@ struct TechmapWorker auto &data = it.second.front(); if (!data.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(data.wire->name), log_signal(data.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", data.wire->name.unescape(), log_signal(data.value)); techmap_wire_names.erase(it.first); @@ -758,7 +758,7 @@ struct TechmapWorker log("Analyzing pattern of constant bits for this cell:\n"); IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); - log("Creating constmapped module `%s'.\n", log_id(new_tpl_name)); + log("Creating constmapped module `%s'.\n", new_tpl_name.unescape()); log_assert(map->module(new_tpl_name) == nullptr); RTLIL::Module *new_tpl = map->addModule(new_tpl_name); @@ -865,16 +865,16 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { if (!it.first.ends_with("_TECHMAP_FAIL_") && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.contains("_TECHMAP_DO_") && !it.first.contains("_TECHMAP_DONE_")) - log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first)); + log_error("Techmap yielded unknown config wire %s.\n", it.first.unescape()); if (techmap_do_cache[tpl]) for (auto &it2 : it.second) if (!it2.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(it2.wire->name), log_signal(it2.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", it2.wire->name.unescape(), log_signal(it2.value)); techmap_wire_names.erase(it.first); } for (auto &it : techmap_wire_names) - log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", log_id(it)); + log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", it.unescape()); if (recursive_mode) { if (log_continue) { @@ -914,7 +914,7 @@ struct TechmapWorker if (extern_mode && !in_recursion) { - std::string m_name = stringf("$extern:%s", log_id(tpl)); + std::string m_name = stringf("$extern:%s", tpl); if (!design->module(m_name)) { @@ -924,18 +924,18 @@ struct TechmapWorker module_queue.insert(m); } - log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(m_name)); + log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, module, cell, m_name); cell->type = m_name; cell->parameters.clear(); } else { - auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), log_id(cell->type)); + auto msg = stringf("Using template %s for cells of type %s.", tpl, cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); + log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), tpl); techmap_module_worker(design, module, cell, tpl); cell = nullptr; } @@ -945,7 +945,7 @@ struct TechmapWorker } if (assert_mode && !mapped_cell) - log_error("(ASSERT MODE) Failed to map cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + log_error("(ASSERT MODE) Failed to map cell %s.%s (%s).\n", module, cell, cell->type.unescape()); handled_cells.insert(cell); } @@ -1265,8 +1265,8 @@ struct TechmapPass : public Pass { i.second.sort(RTLIL::sort_by_id_str()); std::string maps = ""; for (auto &map : i.second) - maps += stringf(" %s", log_id(map)); - log_debug(" %s:%s\n", log_id(i.first), maps); + maps += stringf(" %s", map); + log_debug(" %s:%s\n", i.first.unescape(), maps); } log_debug("\n"); diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc index b45cd268a..07f51bdae 100644 --- a/passes/techmap/tribuf.cc +++ b/passes/techmap/tribuf.cc @@ -142,7 +142,7 @@ struct TribufWorker { auto conflict = module->And(NEW_ID, cell_s, other_s); - std::string name = stringf("$tribuf_conflict$%s", log_id(cell->name)); + std::string name = stringf("$tribuf_conflict$%s", cell->name.unescape()); auto assert_cell = module->addAssert(name, module->Not(NEW_ID, conflict), SigSpec(true)); assert_cell->set_src_attribute(cell->get_src_attribute()); diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index 809651ebd..5b6a3adaf 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -68,7 +68,7 @@ struct ZinitPass : public Pass { FfData ff(&initvals, cell); - log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type), + log("FF init value for cell %s (%s): %s = %s\n", cell, cell->type.unescape(), log_signal(ff.sig_q), log_signal(ff.val_init)); pool bits; diff --git a/passes/tests/raise_error.cc b/passes/tests/raise_error.cc index b21ec7d1d..95b477bc8 100644 --- a/passes/tests/raise_error.cc +++ b/passes/tests/raise_error.cc @@ -71,7 +71,7 @@ struct RaiseErrorPass : public Pass { int err_no = 1; string err_msg = ""; if (err_obj != nullptr) { - log("Raising error from '%s'.\n", log_id(err_obj)); + log("Raising error from '%s'.\n", err_obj); err_no = err_obj->attributes[ID::raise_error].as_int(); if (err_no > 256) { err_msg = err_obj->get_string_attribute(ID::raise_error); diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 4d28e659b..3f2588bd1 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -596,20 +596,20 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: for (auto port : gold_mod->ports) { RTLIL::Wire *wire = gold_mod->wire(port); if (wire->port_input) - vlog_file << stringf(" reg [%d:0] %s;\n", GetSize(wire)-1, log_id(wire)); + vlog_file << stringf(" reg [%d:0] %s;\n", GetSize(wire)-1, wire); else - vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", GetSize(wire)-1, log_id(wire), log_id(wire)); + vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", GetSize(wire)-1, wire, wire); } vlog_file << stringf(" %s_expr uut_expr(", uut_name); for (int i = 0; i < GetSize(gold_mod->ports); i++) - vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", log_id(gold_mod->ports[i]), log_id(gold_mod->ports[i]), + vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", gold_mod->ports[i].unescape(), gold_mod->ports[i].unescape(), gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_expr"); vlog_file << stringf(");\n"); vlog_file << stringf(" %s_expr uut_noexpr(", uut_name); for (int i = 0; i < GetSize(gold_mod->ports); i++) - vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", log_id(gold_mod->ports[i]), log_id(gold_mod->ports[i]), + vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", gold_mod->ports[i].unescape(), gold_mod->ports[i].unescape(), gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_noexpr"); vlog_file << stringf(");\n"); @@ -654,7 +654,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: } if (verbose) - log("%s: %s\n", log_id(gold_wire), log_signal(in_value)); + log("%s: %s\n", gold_wire, log_signal(in_value)); in_sig.append(gold_wire); in_val.append(in_value); @@ -663,10 +663,10 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: gate_ce.set(gate_wire, in_value); if (vlog_file.is_open() && GetSize(in_value) > 0) { - vlog_file << stringf(" %s = 'b%s;\n", log_id(gold_wire), in_value.as_string()); + vlog_file << stringf(" %s = 'b%s;\n", gold_wire, in_value.as_string()); if (!vlog_pattern_info.empty()) vlog_pattern_info += " "; - vlog_pattern_info += stringf("%s=%s", log_id(gold_wire), log_signal(in_value)); + vlog_pattern_info += stringf("%s=%s", gold_wire, log_signal(in_value)); } } @@ -690,10 +690,10 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: RTLIL::SigSpec gate_outval(gate_wire); if (!gold_ce.eval(gold_outval)) - log_error("Failed to eval %s in gold module.\n", log_id(gold_wire)); + log_error("Failed to eval %s in gold module.\n", gold_wire); if (!gate_ce.eval(gate_outval)) - log_error("Failed to eval %s in gate module.\n", log_id(gate_wire)); + log_error("Failed to eval %s in gate module.\n", gate_wire); bool gold_gate_mismatch = false; for (int i = 0; i < GetSize(gold_wire); i++) { @@ -706,19 +706,19 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: } if (gold_gate_mismatch) - log_error("Mismatch in output %s: gold:%s != gate:%s\n", log_id(gate_wire), log_signal(gold_outval), log_signal(gate_outval)); + log_error("Mismatch in output %s: gold:%s != gate:%s\n", gate_wire, log_signal(gold_outval), log_signal(gate_outval)); if (verbose) - log("%s: %s\n", log_id(gold_wire), log_signal(gold_outval)); + log("%s: %s\n", gold_wire, log_signal(gold_outval)); out_sig.append(gold_wire); out_val.append(gold_outval); if (vlog_file.is_open()) { vlog_file << stringf(" $display(\"[%s] %s expected: %%b, expr: %%b, noexpr: %%b\", %d'b%s, %s_expr, %s_noexpr);\n", - vlog_pattern_info.c_str(), log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string().c_str(), log_id(gold_wire), log_id(gold_wire)); - vlog_file << stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string()); - vlog_file << stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire), GetSize(gold_outval), gold_outval.as_string()); + vlog_pattern_info.c_str(), gold_wire, GetSize(gold_outval), gold_outval.as_string().c_str(), gold_wire, gold_wire); + vlog_file << stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", gold_wire, GetSize(gold_outval), gold_outval.as_string()); + vlog_file << stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", gold_wire, GetSize(gold_outval), gold_outval.as_string()); } } @@ -1102,10 +1102,10 @@ struct TestCellPass : public Pass { int charcount = 100; for (auto &it : cell_types) { if (charcount > 60) { - cell_type_list += stringf("\n%s", + log_id(it.first)); + cell_type_list += stringf("\n%s", it.first.unescape()); charcount = 0; } else - cell_type_list += stringf(" %s", log_id(it.first)); + cell_type_list += stringf(" %s", it.first.unescape()); charcount += GetSize(it.first); } log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n", diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc index e8d061b93..5d09498f2 100644 --- a/techlibs/anlogic/anlogic_fixcarry.cc +++ b/techlibs/anlogic/anlogic_fixcarry.cc @@ -69,7 +69,7 @@ static void fix_carry_chain(Module *module) continue; adders_to_fix_cells.push_back(cell); - log("Found %s cell named %s with invalid 'c' signal.\n", log_id(cell->type), log_id(cell)); + log("Found %s cell named %s with invalid 'c' signal.\n", cell->type.unescape(), cell); } } @@ -78,7 +78,7 @@ static void fix_carry_chain(Module *module) SigBit bit_ci = get_bit_or_zero(cell->getPort(ID(c))); SigBit canonical_bit = sigmap(bit_ci); auto bit = mapping_bits.at(canonical_bit); - log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); + log("Fixing %s cell named %s breaking carry chain.\n", cell->type.unescape(), cell); Cell *c = module->addCell(NEW_ID, ID(AL_MAP_ADDER)); SigBit new_bit = module->addWire(NEW_ID); SigBit dummy_bit = module->addWire(NEW_ID); diff --git a/techlibs/efinix/efinix_fixcarry.cc b/techlibs/efinix/efinix_fixcarry.cc index c61fa79b8..5056dec1a 100644 --- a/techlibs/efinix/efinix_fixcarry.cc +++ b/techlibs/efinix/efinix_fixcarry.cc @@ -65,7 +65,7 @@ static void fix_carry_chain(Module *module) continue; adders_to_fix_cells.push_back(cell); - log("Found %s cell named %s with invalid CI signal.\n", log_id(cell->type), log_id(cell)); + log("Found %s cell named %s with invalid CI signal.\n", cell->type.unescape(), cell); } } @@ -74,7 +74,7 @@ static void fix_carry_chain(Module *module) SigBit bit_ci = get_bit_or_zero(cell->getPort(ID::CI)); SigBit canonical_bit = sigmap(bit_ci); auto bit = mapping_bits.at(canonical_bit); - log("Fixing %s cell named %s breaking carry chain.\n", log_id(cell->type), log_id(cell)); + log("Fixing %s cell named %s breaking carry chain.\n", cell->type.unescape(), cell); Cell *c = module->addCell(NEW_ID, ID(EFX_ADD)); SigBit new_bit = module->addWire(NEW_ID); c->setParam(ID(I0_POLARITY), State::S1); diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc index 4f60a5c37..691013c8e 100644 --- a/techlibs/greenpak4/greenpak4_dffinv.cc +++ b/techlibs/greenpak4/greenpak4_dffinv.cc @@ -86,7 +86,7 @@ void invert_gp_dff(Cell *cell, bool invert_input) cell->type = stringf("\\GP_DFF%s%s%s", cell_type_s ? "S" : "", cell_type_r ? "R" : "", cell_type_i ? "I" : ""); log("Merged %s inverter into cell %s.%s: %s -> %s\n", invert_input ? "input" : "output", - log_id(cell->module), log_id(cell), cell_type.c_str()+1, log_id(cell->type)); + cell->module, cell, cell_type.c_str()+1, cell->type.unescape()); } struct Greenpak4DffInvPass : public Pass { diff --git a/techlibs/ice40/ice40_dsp.cc b/techlibs/ice40/ice40_dsp.cc index 995cdb97e..7942943c4 100644 --- a/techlibs/ice40/ice40_dsp.cc +++ b/techlibs/ice40/ice40_dsp.cc @@ -29,7 +29,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; - log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); + log("Checking %s.%s for iCE40 DSP inference.\n", pm.module, st.mul); log_debug("ffA: %s\n", log_id(st.ffA, "--")); log_debug("ffB: %s\n", log_id(st.ffB, "--")); @@ -64,7 +64,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) Cell *cell = st.mul; if (cell->type == ID($mul)) { - log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); + log(" replacing %s with SB_MAC16 cell.\n", st.mul->type.unescape()); cell = pm.module->addCell(NEW_ID, ID(SB_MAC16)); pm.module->swap_names(cell, st.mul); @@ -135,22 +135,22 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge"); if (st.ffA) - log(" ffA:%s", log_id(st.ffA)); + log(" ffA:%s", st.ffA); if (st.ffB) - log(" ffB:%s", log_id(st.ffB)); + log(" ffB:%s", st.ffB); if (st.ffCD) - log(" ffCD:%s", log_id(st.ffCD)); + log(" ffCD:%s", st.ffCD); if (st.ffFJKG) - log(" ffFJKG:%s", log_id(st.ffFJKG)); + log(" ffFJKG:%s", st.ffFJKG); if (st.ffH) - log(" ffH:%s", log_id(st.ffH)); + log(" ffH:%s", st.ffH); if (st.ffO) - log(" ffO:%s", log_id(st.ffO)); + log(" ffO:%s", st.ffO); log("\n"); } @@ -196,9 +196,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.add) { accum = (st.ffO && st.add->getPort(st.addAB == ID::A ? ID::B : ID::A) == st.sigO); if (accum) - log(" accumulator %s (%s)\n", log_id(st.add), log_id(st.add->type)); + log(" accumulator %s (%s)\n", st.add, st.add->type.unescape()); else - log(" adder %s (%s)\n", log_id(st.add), log_id(st.add->type)); + log(" adder %s (%s)\n", st.add, st.add->type.unescape()); cell->setPort(ID(ADDSUBTOP), st.add->type == ID($add) ? State::S0 : State::S1); cell->setPort(ID(ADDSUBBOT), st.add->type == ID($add) ? State::S0 : State::S1); } else { diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index c88fd69b6..67d3813a7 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -83,7 +83,7 @@ static void run_ice40_opts(Module *module) module->connect(cell->getPort(ID::CO)[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized away SB_CARRY cell %s.%s: CO=%s\n", - log_id(module), log_id(cell), log_signal(replacement_output)); + module, cell, log_signal(replacement_output)); module->remove(cell); } continue; @@ -137,7 +137,7 @@ static void run_ice40_opts(Module *module) module->connect(cell->getPort(ID::CO)[0], replacement_output); module->design->scratchpad_set_bool("opt.did_something", true); log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n", - log_id(module), log_id(cell), log_signal(replacement_output)); + module, cell, log_signal(replacement_output)); cell->type = ID($lut); auto I3 = get_bit_or_zero(cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3))); cell->setPort(ID::A, { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(ID(I0))) }); @@ -175,7 +175,7 @@ static void run_ice40_opts(Module *module) remap_lut: module->design->scratchpad_set_bool("opt.did_something", true); - log("Mapping SB_LUT4 cell %s.%s back to logic.\n", log_id(module), log_id(cell)); + log("Mapping SB_LUT4 cell %s.%s back to logic.\n", module, cell); cell->type = ID($lut); cell->setParam(ID::WIDTH, 4); diff --git a/techlibs/lattice/lattice_gsr.cc b/techlibs/lattice/lattice_gsr.cc index d7d41eca5..a60b54b16 100644 --- a/techlibs/lattice/lattice_gsr.cc +++ b/techlibs/lattice/lattice_gsr.cc @@ -57,7 +57,7 @@ struct LatticeGsrPass : public Pass { for (auto module : design->selected_modules()) { - log("Handling GSR in %s.\n", log_id(module)); + log("Handling GSR in %s.\n", module); SigMap sigmap(module); @@ -69,11 +69,11 @@ struct LatticeGsrPass : public Pass { if (cell->type != ID(GSR) && cell->type != ID(SGSR)) continue; if (found_gsr) - log_error("Found more than one GSR or SGSR cell in module %s.\n", log_id(module)); + log_error("Found more than one GSR or SGSR cell in module %s.\n", module); found_gsr = true; SigSpec sig_gsr = cell->getPort(ID(GSR)); if (GetSize(sig_gsr) < 1) - log_error("GSR cell %s has disconnected GSR input.\n", log_id(cell)); + log_error("GSR cell %s has disconnected GSR input.\n", cell); gsr = sigmap(sig_gsr[0]); } @@ -97,7 +97,7 @@ struct LatticeGsrPass : public Pass { // For finding active low FF inputs pool inverted_gsr; - log_debug("GSR net in module %s is %s.\n", log_id(module), log_signal(gsr)); + log_debug("GSR net in module %s is %s.\n", module, log_signal(gsr)); for (auto cell : module->selected_cells()) { if (cell->type != ID($_NOT_)) diff --git a/techlibs/microchip/microchip_dffopt.cc b/techlibs/microchip/microchip_dffopt.cc index 98e2f17a7..140ef2c9f 100644 --- a/techlibs/microchip/microchip_dffopt.cc +++ b/techlibs/microchip/microchip_dffopt.cc @@ -121,7 +121,7 @@ struct MicrochipDffOptPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) { - log("Optimizing FFs in %s.\n", log_id(module)); + log("Optimizing FFs in %s.\n", module); SigMap sigmap(module); dict> bit_to_lut; @@ -294,7 +294,7 @@ struct MicrochipDffOptPass : public Pass { ports += " + S"; if (worthy_post_ce) ports += " + CE"; - log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, log_id(cell), log_id(sig_Q.wire), + log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, cell, sig_Q.wire, GetSize(lut_d.second), GetSize(final_lut.second)); // Okay, we're doing it. Unmap ports. diff --git a/techlibs/microchip/microchip_dsp.cc b/techlibs/microchip/microchip_dsp.cc index df7093bc5..01c77644f 100644 --- a/techlibs/microchip/microchip_dsp.cc +++ b/techlibs/microchip/microchip_dsp.cc @@ -31,13 +31,13 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) { auto &st = pm.st_microchip_dsp_pack; - log("Analysing %s.%s for Microchip MACC_PA packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Microchip MACC_PA packing.\n", pm.module, st.dsp); Cell *cell = st.dsp; // pack pre-adder if (st.preAdderStatic) { SigSpec &pasub = cell->connections_.at(ID(PASUB)); - log(" static PASUB preadder %s (%s)\n", log_id(st.preAdderStatic), log_id(st.preAdderStatic->type)); + log(" static PASUB preadder %s (%s)\n", st.preAdderStatic, st.preAdderStatic->type.unescape()); bool D_SIGNED = st.preAdderStatic->getParam(ID::B_SIGNED).as_bool(); bool B_SIGNED = st.preAdderStatic->getParam(ID::A_SIGNED).as_bool(); st.sigB.extend_u0(18, B_SIGNED); @@ -60,7 +60,7 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) } // pack post-adder if (st.postAdderStatic) { - log(" postadder %s (%s)\n", log_id(st.postAdderStatic), log_id(st.postAdderStatic->type)); + log(" postadder %s (%s)\n", st.postAdderStatic, st.postAdderStatic->type.unescape()); SigSpec &sub = cell->connections_.at(ID(SUB)); // Post-adder in MACC_PA also supports subtraction // Determines the sign of the output from the multiplier. @@ -171,13 +171,13 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) log(" clock: %s (%s)\n", log_signal(st.clock), "posedge"); if (st.ffA) - log(" \t ffA:%s\n", log_id(st.ffA)); + log(" \t ffA:%s\n", st.ffA); if (st.ffB) - log(" \t ffB:%s\n", log_id(st.ffB)); + log(" \t ffB:%s\n", st.ffB); if (st.ffD) - log(" \t ffD:%s\n", log_id(st.ffD)); + log(" \t ffD:%s\n", st.ffD); if (st.ffP) - log(" \t ffP:%s\n", log_id(st.ffP)); + log(" \t ffP:%s\n", st.ffP); } log("\n"); @@ -194,7 +194,7 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) { auto &st = pm.st_microchip_dsp_packC; - log_debug("Analysing %s.%s for Microchip DSP packing (REG_C).\n", log_id(pm.module), log_id(st.dsp)); + log_debug("Analysing %s.%s for Microchip DSP packing (REG_C).\n", pm.module, st.dsp); log_debug("ffC: %s\n", log_id(st.ffC, "--")); Cell *cell = st.dsp; @@ -264,7 +264,7 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffC) - log(" ffC:%s", log_id(st.ffC)); + log(" ffC:%s", st.ffC); log("\n"); } diff --git a/techlibs/quicklogic/ql_bram_merge.cc b/techlibs/quicklogic/ql_bram_merge.cc index 7b99d74e5..eeb06060e 100644 --- a/techlibs/quicklogic/ql_bram_merge.cc +++ b/techlibs/quicklogic/ql_bram_merge.cc @@ -128,7 +128,7 @@ struct QlBramMergeWorker { // Create the new cell RTLIL::Cell* merged = module->addCell(NEW_ID, merged_cell_type); - log_debug("Merging split BRAM cells %s and %s -> %s\n", log_id(bram1->name), log_id(bram2->name), log_id(merged->name)); + log_debug("Merging split BRAM cells %s and %s -> %s\n", bram1->name.unescape(), bram2->name.unescape(), merged->name.unescape()); for (auto &it : param_map(false)) { @@ -146,14 +146,14 @@ struct QlBramMergeWorker { if (bram1->hasPort(it.first)) merged->setPort(it.second, bram1->getPort(it.first)); else - log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram1->name)); + log_error("Can't find port %s on cell %s!\n", it.first.unescape(), bram1->name.unescape()); } for (auto &it : port_map(true)) { if (bram2->hasPort(it.first)) merged->setPort(it.second, bram2->getPort(it.first)); else - log_error("Can't find port %s on cell %s!\n", log_id(it.first), log_id(bram2->name)); + log_error("Can't find port %s on cell %s!\n", it.first.unescape(), bram2->name.unescape()); } merged->attributes = bram1->attributes; for (auto attr: bram2->attributes) diff --git a/techlibs/quicklogic/ql_bram_types.cc b/techlibs/quicklogic/ql_bram_types.cc index cf42703aa..2599303bd 100644 --- a/techlibs/quicklogic/ql_bram_types.cc +++ b/techlibs/quicklogic/ql_bram_types.cc @@ -155,7 +155,7 @@ struct QlBramTypesPass : public Pass { } cell->type = RTLIL::escape_id(type); - log_debug("Changed type of memory cell %s to %s\n", log_id(cell->name), log_id(cell->type)); + log_debug("Changed type of memory cell %s to %s\n", cell->name.unescape(), cell->type.unescape()); } } diff --git a/techlibs/quicklogic/ql_dsp_io_regs.cc b/techlibs/quicklogic/ql_dsp_io_regs.cc index ecf163dbf..d7255d761 100644 --- a/techlibs/quicklogic/ql_dsp_io_regs.cc +++ b/techlibs/quicklogic/ql_dsp_io_regs.cc @@ -83,19 +83,19 @@ struct QlDspIORegs : public Pass { for (auto cfg_port : {ID(register_inputs), ID(output_select)}) if (!cell->hasPort(cfg_port) || !sigmap(cell->getPort(cfg_port)).is_fully_const()) log_error("Missing or non-constant '%s' port on DSP cell %s\n", - log_id(cfg_port), log_id(cell)); + cfg_port, cell); int reg_in_i = sigmap(cell->getPort(ID(register_inputs))).as_int(); int out_sel_i = sigmap(cell->getPort(ID(output_select))).as_int(); // Get the feedback port if (!cell->hasPort(ID(feedback))) - log_error("Missing 'feedback' port on %s", log_id(cell)); + log_error("Missing 'feedback' port on %s", cell); SigSpec feedback = sigmap(cell->getPort(ID(feedback))); // Check the top two bits on 'feedback' to be constant zero. // That's what we are expecting from inference. if (feedback.extract(1, 2) != SigSpec(0, 2)) - log_error("Unexpected feedback configuration on %s\n", log_id(cell)); + log_error("Unexpected feedback configuration on %s\n", cell); // Build new type name std::string new_type = "\\QL_DSP2_MULT"; diff --git a/techlibs/quicklogic/ql_dsp_macc.cc b/techlibs/quicklogic/ql_dsp_macc.cc index f0669da6c..febfaddf1 100644 --- a/techlibs/quicklogic/ql_dsp_macc.cc +++ b/techlibs/quicklogic/ql_dsp_macc.cc @@ -73,11 +73,11 @@ static void create_ql_macc_dsp(ql_dsp_macc_pm &pm) } type = RTLIL::escape_id(cell_base_name + cell_size_name + "_cfg_ports"); - log("Inferring MACC %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, log_id(type)); + log("Inferring MACC %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, type); for (auto cell : {st.mul, st.add, st.mux, st.ff}) if (cell) - log(" %s (%s)\n", log_id(cell), log_id(cell->type)); + log(" %s (%s)\n", cell, cell->type.unescape()); // Add the DSP cell RTLIL::Cell *cell = pm.module->addCell(NEW_ID, type); diff --git a/techlibs/quicklogic/ql_dsp_simd.cc b/techlibs/quicklogic/ql_dsp_simd.cc index cd509ce7f..da252673f 100644 --- a/techlibs/quicklogic/ql_dsp_simd.cc +++ b/techlibs/quicklogic/ql_dsp_simd.cc @@ -150,13 +150,13 @@ struct QlDspSimdPass : public Pass { // Create the new cell Cell *simd = module->addCell(NEW_ID, m_SimdDspType); - log(" SIMD: %s (%s) + %s (%s) => %s (%s)\n", log_id(dsp_a), log_id(dsp_a->type), - log_id(dsp_b), log_id(dsp_b->type), log_id(simd), log_id(simd->type)); + log(" SIMD: %s (%s) + %s (%s) => %s (%s)\n", dsp_a, dsp_a->type.unescape(), + dsp_b, dsp_b->type.unescape(), simd, simd->type.unescape()); // Check if the target cell is known (important to know // its port widths) if (!simd->known()) - log_error(" The target cell type '%s' is not known!", log_id(simd)); + log_error(" The target cell type '%s' is not known!", simd); // Connect common ports for (const auto &it : m_DspCfgPorts) diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc index 8a6d3e015..96420be6a 100644 --- a/techlibs/xilinx/xilinx_dffopt.cc +++ b/techlibs/xilinx/xilinx_dffopt.cc @@ -131,7 +131,7 @@ struct XilinxDffOptPass : public Pass { for (auto module : design->selected_modules()) { - log("Optimizing FFs in %s.\n", log_id(module)); + log("Optimizing FFs in %s.\n", module); SigMap sigmap(module); dict> bit_to_lut; @@ -305,7 +305,7 @@ unmap: if (worthy_post_r) ports += " + R"; if (worthy_post_s) ports += " + S"; if (worthy_post_ce) ports += " + CE"; - log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second)); + log(" Merging D%s LUTs for %s/%s (%d -> %d)\n", ports, cell, sig_Q.wire, GetSize(lut_d.second), GetSize(final_lut.second)); // Okay, we're doing it. Unmap ports. if (worthy_post_r) { diff --git a/techlibs/xilinx/xilinx_dsp.cc b/techlibs/xilinx/xilinx_dsp.cc index 194b9ac10..94fad6453 100644 --- a/techlibs/xilinx/xilinx_dsp.cc +++ b/techlibs/xilinx/xilinx_dsp.cc @@ -140,7 +140,7 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) } } - log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); + log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", module, lane1); Cell *cell = addDsp(module); cell->setParam(ID(USE_SIMD), Const("FOUR12")); @@ -221,7 +221,7 @@ void xilinx_simd_pack(Module *module, const std::vector &selected_cells) Cell *lane2 = simd24.front(); simd24.pop_front(); - log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); + log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", module, lane1); Cell *cell = addDsp(module); cell->setParam(ID(USE_SIMD), Const("TWO24")); @@ -260,7 +260,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) { auto &st = pm.st_xilinx_dsp_pack; - log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Xilinx DSP packing.\n", pm.module, st.dsp); log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); log_debug("preSub: %s\n", log_id(st.preSub, "--")); @@ -282,7 +282,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) if (st.preAdd || st.preSub) { Cell* preAdder = st.preAdd ? st.preAdd : st.preSub; - log(" preadder %s (%s)\n", log_id(preAdder), log_id(preAdder->type)); + log(" preadder %s (%s)\n", preAdder, preAdder->type.unescape()); bool A_SIGNED = preAdder->getParam(ID::A_SIGNED).as_bool(); bool D_SIGNED = preAdder->getParam(ID::B_SIGNED).as_bool(); if (st.sigA == preAdder->getPort(ID::B)) @@ -312,7 +312,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) pm.autoremove(preAdder); } if (st.postAdd) { - log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); + log(" postadder %s (%s)\n", st.postAdd, st.postAdd->type.unescape()); SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (st.postAddMux) { @@ -338,7 +338,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) pm.autoremove(st.postAdd); } if (st.overflow) { - log(" overflow %s (%s)\n", log_id(st.overflow), log_id(st.overflow->type)); + log(" overflow %s (%s)\n", st.overflow, st.overflow->type.unescape()); cell->setParam(ID(USE_PATTERN_DETECT), Const("PATDET")); cell->setParam(ID(SEL_PATTERN), Const("PATTERN")); cell->setParam(ID(SEL_MASK), Const("MASK")); @@ -456,28 +456,28 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffA2) { - log(" ffA2:%s", log_id(st.ffA2)); + log(" ffA2:%s", st.ffA2); if (st.ffA1) - log(" ffA1:%s", log_id(st.ffA1)); + log(" ffA1:%s", st.ffA1); } if (st.ffAD) - log(" ffAD:%s", log_id(st.ffAD)); + log(" ffAD:%s", st.ffAD); if (st.ffB2) { - log(" ffB2:%s", log_id(st.ffB2)); + log(" ffB2:%s", st.ffB2); if (st.ffB1) - log(" ffB1:%s", log_id(st.ffB1)); + log(" ffB1:%s", st.ffB1); } if (st.ffD) - log(" ffD:%s", log_id(st.ffD)); + log(" ffD:%s", st.ffD); if (st.ffM) - log(" ffM:%s", log_id(st.ffM)); + log(" ffM:%s", st.ffM); if (st.ffP) - log(" ffP:%s", log_id(st.ffP)); + log(" ffP:%s", st.ffP); } log("\n"); @@ -493,7 +493,7 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) { auto &st = pm.st_xilinx_dsp48a_pack; - log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", log_id(pm.module), log_id(st.dsp)); + log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", pm.module, st.dsp); log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); log_debug("ffA1: %s\n", log_id(st.ffA1, "--")); @@ -511,7 +511,7 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) SigSpec &opmode = cell->connections_.at(ID(OPMODE)); if (st.preAdd) { - log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type)); + log(" preadder %s (%s)\n", st.preAdd, st.preAdd->type.unescape()); bool D_SIGNED = st.preAdd->getParam(ID::A_SIGNED).as_bool(); bool B_SIGNED = st.preAdd->getParam(ID::B_SIGNED).as_bool(); st.sigB.extend_u0(18, B_SIGNED); @@ -529,7 +529,7 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) pm.autoremove(st.preAdd); } if (st.postAdd) { - log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type)); + log(" postadder %s (%s)\n", st.postAdd, st.postAdd->type.unescape()); if (st.postAddMux) { log_assert(st.ffP); @@ -639,23 +639,23 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffA0) - log(" ffA0:%s", log_id(st.ffA0)); + log(" ffA0:%s", st.ffA0); if (st.ffA1) - log(" ffA1:%s", log_id(st.ffA1)); + log(" ffA1:%s", st.ffA1); if (st.ffB0) - log(" ffB0:%s", log_id(st.ffB0)); + log(" ffB0:%s", st.ffB0); if (st.ffB1) - log(" ffB1:%s", log_id(st.ffB1)); + log(" ffB1:%s", st.ffB1); if (st.ffD) - log(" ffD:%s", log_id(st.ffD)); + log(" ffD:%s", st.ffD); if (st.ffM) - log(" ffM:%s", log_id(st.ffM)); + log(" ffM:%s", st.ffM); if (st.ffP) - log(" ffP:%s", log_id(st.ffP)); + log(" ffP:%s", st.ffP); } log("\n"); @@ -671,7 +671,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) { auto &st = pm.st_xilinx_dsp_packC; - log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", log_id(pm.module), log_id(st.dsp)); + log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", pm.module, st.dsp); log_debug("ffC: %s\n", log_id(st.ffC, "--")); Cell *cell = st.dsp; @@ -724,7 +724,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) log(" clock: %s (%s)", log_signal(st.clock), "posedge"); if (st.ffC) - log(" ffC:%s", log_id(st.ffC)); + log(" ffC:%s", st.ffC); log("\n"); } diff --git a/techlibs/xilinx/xilinx_srl.cc b/techlibs/xilinx/xilinx_srl.cc index 2c23f8f42..e23062eb7 100644 --- a/techlibs/xilinx/xilinx_srl.cc +++ b/techlibs/xilinx/xilinx_srl.cc @@ -30,11 +30,11 @@ void run_fixed(xilinx_srl_pm &pm) { auto &st = pm.st_fixed; auto &ud = pm.ud_fixed; - log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type)); + log("Found fixed chain of length %d (%s):\n", GetSize(ud.longest_chain), st.first->type.unescape()); SigSpec initval; for (auto cell : ud.longest_chain) { - log_debug(" %s\n", log_id(cell)); + log_debug(" %s\n", cell); if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_))) { SigBit Q = cell->getPort(ID::Q); log_assert(Q.wire); @@ -100,7 +100,7 @@ void run_fixed(xilinx_srl_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } void run_variable(xilinx_srl_pm &pm) @@ -108,13 +108,13 @@ void run_variable(xilinx_srl_pm &pm) auto &st = pm.st_variable; auto &ud = pm.ud_variable; - log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), log_id(st.first->type)); + log("Found variable chain of length %d (%s):\n", GetSize(ud.chain), st.first->type.unescape()); SigSpec initval; for (const auto &i : ud.chain) { auto cell = i.first; auto slice = i.second; - log_debug(" %s\n", log_id(cell)); + log_debug(" %s\n", cell); if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), ID($dff), ID($dffe))) { SigBit Q = cell->getPort(ID::Q)[slice]; log_assert(Q.wire); @@ -181,7 +181,7 @@ void run_variable(xilinx_srl_pm &pm) else log_abort(); - log(" -> %s (%s)\n", log_id(c), log_id(c->type)); + log(" -> %s (%s)\n", c, c->type.unescape()); } struct XilinxSrlPass : public Pass { From fb83719745e67ae1bfcd6e977438cbd2bcedf248 Mon Sep 17 00:00:00 2001 From: Leo Moser Date: Sat, 9 May 2026 10:28:07 +0200 Subject: [PATCH 149/176] memlib: fix documentation for `PORT__CLK_POL` Signed-off-by: Leo Moser --- passes/memory/memlib.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/memory/memlib.md b/passes/memory/memlib.md index f3c0dd937..5ad3f7777 100644 --- a/passes/memory/memlib.md +++ b/passes/memory/memlib.md @@ -310,7 +310,7 @@ The port clock is always provided on the memory cell as `PORT__CLK` signal (even if it is also shared). Shared clocks are also provided as `CLK_` signals. -For `anyedge` clocks, the cell gets a `PORT__CLKPOL` parameter that is set +For `anyedge` clocks, the cell gets a `PORT__CLK_POL` parameter that is set to 1 for `posedge` clocks and 0 for `negedge` clocks. If the clock is shared, the same information will also be provided as `CLK__POL` parameter. From 40c14858288e12f838ff1b73cc53c3a19d876b4e Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 11 May 2026 14:37:21 +0200 Subject: [PATCH 150/176] Update ABC, reverts 6aaf0db1e1201d72888a461463485b0b5595075a --- abc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abc b/abc index d217b3519..98967c9f3 160000 --- a/abc +++ b/abc @@ -1 +1 @@ -Subproject commit d217b351925ffc5e3036073776fef1810d258499 +Subproject commit 98967c9f3afe4fbfae2d4da57bfd97848576c875 From 7fe32137bdf7c78bfccb8ba09e6fdfddfdf57a90 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 11 May 2026 14:47:08 +0200 Subject: [PATCH 151/176] Revert "Fix tests due to ABC improvements" This reverts commit 417e871b06baf709a8de4a66e9eab890a8f9d041. --- tests/arch/analogdevices/logic.ys | 5 +++-- tests/arch/analogdevices/mux.ys | 6 ++++-- tests/arch/ecp5/add_sub.ys | 8 +++++--- tests/arch/ecp5/lutram.ys | 7 ++++--- tests/arch/gowin/logic.ys | 4 ++-- tests/arch/gowin/mux.ys | 19 ++++++++++++------- tests/arch/intel_alm/logic.ys | 4 ++-- tests/arch/nexus/add_sub.ys | 4 ++-- tests/pyosys/test_design_run_pass.py | 8 +++++--- tests/pyosys/test_ecp5_addsub.py | 8 +++++--- 10 files changed, 44 insertions(+), 29 deletions(-) diff --git a/tests/arch/analogdevices/logic.ys b/tests/arch/analogdevices/logic.ys index 2289685ac..9314c7825 100644 --- a/tests/arch/analogdevices/logic.ys +++ b/tests/arch/analogdevices/logic.ys @@ -6,5 +6,6 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p cd top # Constrain all select calls below inside the top module select -assert-count 1 t:LUT1 -select -assert-count 9 t:LUT2 -select -assert-none t:LUT1 t:LUT2 %% t:* %D +select -assert-count 6 t:LUT2 +select -assert-count 2 t:LUT4 +select -assert-none t:LUT1 t:LUT2 t:LUT4 %% t:* %D diff --git a/tests/arch/analogdevices/mux.ys b/tests/arch/analogdevices/mux.ys index 3244b0dc3..375ce90f2 100644 --- a/tests/arch/analogdevices/mux.ys +++ b/tests/arch/analogdevices/mux.ys @@ -41,8 +41,10 @@ equiv_opt -assert -map +/analogdevices/cells_sim.v synth_analogdevices -noiopad design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module select -assert-max 2 t:LUT3 -select -assert-max 1 t:LUT5 +select -assert-max 2 t:LUT4 select -assert-min 4 t:LUT6 +select -assert-max 7 t:LUT6 +select -assert-max 2 t:LUTMUX7 dump -select -assert-none t:LUT6 t:LUT5 t:LUT3 %% t:* %D +select -assert-none t:LUT6 t:LUT4 t:LUT3 t:LUTMUX7 %% t:* %D diff --git a/tests/arch/ecp5/add_sub.ys b/tests/arch/ecp5/add_sub.ys index 9c3c03499..c3ce8c56d 100644 --- a/tests/arch/ecp5/add_sub.ys +++ b/tests/arch/ecp5/add_sub.ys @@ -4,7 +4,9 @@ proc equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module -select -assert-min 11 t:LUT4 -select -assert-count 2 t:PFUMX -select -assert-none t:LUT4 t:PFUMX %% t:* %D +select -assert-min 25 t:LUT4 +select -assert-max 26 t:LUT4 +select -assert-count 10 t:PFUMX +select -assert-count 6 t:L6MUX21 +select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D diff --git a/tests/arch/ecp5/lutram.ys b/tests/arch/ecp5/lutram.ys index e83890a54..9bef37c68 100644 --- a/tests/arch/ecp5/lutram.ys +++ b/tests/arch/ecp5/lutram.ys @@ -11,8 +11,9 @@ sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs mite design -load postopt cd lutram_1w1r -select -assert-count 28 t:LUT4 -select -assert-count 8 t:PFUMX +select -assert-count 8 t:L6MUX21 +select -assert-count 36 t:LUT4 +select -assert-count 16 t:PFUMX select -assert-count 8 t:TRELLIS_DPR16X4 select -assert-count 8 t:TRELLIS_FF -select -assert-none t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D +select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D diff --git a/tests/arch/gowin/logic.ys b/tests/arch/gowin/logic.ys index 15f050e9b..d2b9e4540 100644 --- a/tests/arch/gowin/logic.ys +++ b/tests/arch/gowin/logic.ys @@ -7,7 +7,7 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:LUT1 select -assert-count 6 t:LUT2 -select -assert-count 2 t:LUT3 +select -assert-count 2 t:LUT4 select -assert-count 8 t:IBUF select -assert-count 10 t:OBUF -select -assert-none t:LUT1 t:LUT2 t:LUT3 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT1 t:LUT2 t:LUT4 t:IBUF t:OBUF %% t:* %D diff --git a/tests/arch/gowin/mux.ys b/tests/arch/gowin/mux.ys index fddf91d0e..2ca973520 100644 --- a/tests/arch/gowin/mux.ys +++ b/tests/arch/gowin/mux.ys @@ -18,12 +18,13 @@ 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 mux4 # Constrain all select calls below inside the top module -select -assert-count 3 t:LUT* -select -assert-count 1 t:MUX2_LUT5 +select -assert-count 4 t:LUT* +select -assert-count 2 t:MUX2_LUT5 +select -assert-count 1 t:MUX2_LUT6 select -assert-count 6 t:IBUF select -assert-count 1 t:OBUF -select -assert-none t:LUT* t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT* t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D design -load read hierarchy -top mux8 @@ -31,13 +32,17 @@ 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:LUT3 -select -assert-count 5 t:LUT4 -select -assert-count 1 t:MUX2_LUT5 +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 +select -assert-count 1 t:MUX2_LUT7 select -assert-count 11 t:IBUF select -assert-count 1 t:OBUF +select -assert-count 1 t:GND -select -assert-none t:LUT* t:MUX2_LUT5 t:IBUF t:OBUF %% t:* %D +select -assert-none t:LUT* t:MUX2_LUT7 t:MUX2_LUT6 t:MUX2_LUT5 t:IBUF t:OBUF t:GND %% t:* %D design -load read hierarchy -top mux16 diff --git a/tests/arch/intel_alm/logic.ys b/tests/arch/intel_alm/logic.ys index 91d6043e0..831f9f174 100644 --- a/tests/arch/intel_alm/logic.ys +++ b/tests/arch/intel_alm/logic.ys @@ -7,6 +7,6 @@ cd top # Constrain all select calls below inside the top module select -assert-count 1 t:MISTRAL_NOT select -assert-count 6 t:MISTRAL_ALUT2 -select -assert-count 2 t:MISTRAL_ALUT3 -select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 %% t:* %D +select -assert-count 2 t:MISTRAL_ALUT4 +select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT4 %% t:* %D diff --git a/tests/arch/nexus/add_sub.ys b/tests/arch/nexus/add_sub.ys index c1599c57e..4317bab81 100644 --- a/tests/arch/nexus/add_sub.ys +++ b/tests/arch/nexus/add_sub.ys @@ -16,6 +16,6 @@ equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd top # Constrain all select calls below inside the top module stat -select -assert-count 7 t:LUT4 -select -assert-count 2 t:WIDEFN9 +select -assert-count 6 t:LUT4 +select -assert-count 4 t:WIDEFN9 select -assert-none t:IB t:OB t:VLO t:LUT4 t:WIDEFN9 %% t:* %D diff --git a/tests/pyosys/test_design_run_pass.py b/tests/pyosys/test_design_run_pass.py index 6e31a7f1c..f0013577d 100644 --- a/tests/pyosys/test_design_run_pass.py +++ b/tests/pyosys/test_design_run_pass.py @@ -13,6 +13,8 @@ base.run_pass("equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5") postopt = ys.Design() postopt.run_pass("design -load postopt") postopt.run_pass(["cd", "top"]) -postopt.run_pass("select -assert-min 11 t:LUT4") -postopt.run_pass(["select", "-assert-count", "2", "t:PFUMX"]) -postopt.run_pass("select -assert-none t:LUT4 t:PFUMX %% t:* %D") +postopt.run_pass("select -assert-min 25 t:LUT4") +postopt.run_pass("select -assert-max 26 t:LUT4") +postopt.run_pass(["select", "-assert-count", "10", "t:PFUMX"]) +postopt.run_pass(["select", "-assert-count", "6", "t:L6MUX21"]) +postopt.run_pass("select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D") diff --git a/tests/pyosys/test_ecp5_addsub.py b/tests/pyosys/test_ecp5_addsub.py index 96258e3ba..ddc50b775 100644 --- a/tests/pyosys/test_ecp5_addsub.py +++ b/tests/pyosys/test_ecp5_addsub.py @@ -13,6 +13,8 @@ ys.run_pass("equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5", base) postopt = ys.Design() ys.run_pass("design -load postopt", postopt) ys.run_pass("cd top", postopt) -ys.run_pass("select -assert-min 11 t:LUT4", postopt) -ys.run_pass("select -assert-count 2 t:PFUMX", postopt) -ys.run_pass("select -assert-none t:LUT4 t:PFUMX %% t:* %D", postopt) +ys.run_pass("select -assert-min 25 t:LUT4", postopt) +ys.run_pass("select -assert-max 26 t:LUT4", postopt) +ys.run_pass("select -assert-count 10 t:PFUMX", postopt) +ys.run_pass("select -assert-count 6 t:L6MUX21", postopt) +ys.run_pass("select -assert-none t:LUT4 t:PFUMX t:L6MUX21 %% t:* %D", postopt) From b61bc1eee0f4bca6ad4fdec172693c8f5eb132b3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 12 May 2026 08:37:44 +0200 Subject: [PATCH 152/176] Update ABC as per 2026-05-12 --- abc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abc b/abc index 98967c9f3..5d51a5e42 160000 --- a/abc +++ b/abc @@ -1 +1 @@ -Subproject commit 98967c9f3afe4fbfae2d4da57bfd97848576c875 +Subproject commit 5d51a5e420f5de493d07bf61109a977248c86ffb From b85cad634782fafac275e5f540c056bfacb2b5d2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 12 May 2026 11:37:23 +0200 Subject: [PATCH 153/176] Release version 0.65 --- CHANGELOG | 10 +++++++++- Makefile | 4 ++-- docs/source/conf.py | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 94e62df4b..f8697205d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,8 +2,16 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.64 .. Yosys 0.65-dev +Yosys 0.64 .. Yosys 0.65 -------------------------- + * New commands and options + - Added "arith_tree" pass to convert add/sub/macc chains + to carry-save adder trees. + - Removed "-force" option from "share" pass. + + * Various + - read_verilog: support positional assignment patterns + for unpacked arrays. Yosys 0.63 .. Yosys 0.64 -------------------------- diff --git a/Makefile b/Makefile index 543ec7f44..5ed3dc5dd 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.64 +YOSYS_VER := 0.65 ifneq (, $(shell command -v git 2>/dev/null)) ifneq (, $(shell git rev-parse --git-dir 2>/dev/null)) @@ -170,7 +170,7 @@ ifneq (, $(shell git rev-parse --git-dir 2>/dev/null)) YOSYS_VER := $(YOSYS_VER)+$(GIT_COMMIT_COUNT) endif else - YOSYS_VER := $(YOSYS_VER)+post +# YOSYS_VER := $(YOSYS_VER)+post endif endif diff --git a/docs/source/conf.py b/docs/source/conf.py index 9520948cf..b85c391db 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,7 +6,7 @@ import os project = 'YosysHQ Yosys' author = 'YosysHQ GmbH' copyright ='2026 YosysHQ GmbH' -yosys_ver = "0.64" +yosys_ver = "0.65" # select HTML theme html_theme = 'furo-ys' From 6f16a5cf5ffa163950e49c0adc8092194cb0bc18 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 12 May 2026 12:32:27 +0200 Subject: [PATCH 154/176] Next dev cycle --- CHANGELOG | 3 +++ Makefile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f8697205d..01faf44c2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ List of major changes and improvements between releases ======================================================= +Yosys 0.65 .. Yosys 0.66-dev +-------------------------- + Yosys 0.64 .. Yosys 0.65 -------------------------- * New commands and options diff --git a/Makefile b/Makefile index 5ed3dc5dd..4af083df4 100644 --- a/Makefile +++ b/Makefile @@ -170,7 +170,7 @@ ifneq (, $(shell git rev-parse --git-dir 2>/dev/null)) YOSYS_VER := $(YOSYS_VER)+$(GIT_COMMIT_COUNT) endif else -# YOSYS_VER := $(YOSYS_VER)+post + YOSYS_VER := $(YOSYS_VER)+post endif endif From b06f9bdf18039bd643c2989921abbd87d554889a Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 12 May 2026 12:51:12 +0200 Subject: [PATCH 155/176] Makefile: error on unused variables --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 543ec7f44..e95d6cace 100644 --- a/Makefile +++ b/Makefile @@ -104,7 +104,7 @@ VPATH := $(YOSYS_SRC) UNITESTPATH := $(YOSYS_SRC)/tests/unit export CXXSTD ?= c++17 -CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include +CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -Werror=unused -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include LIBS := $(LIBS) -lstdc++ -lm PLUGIN_LINKFLAGS := PLUGIN_LIBS := From 4eb1c61bd57d182e7ca470f3ff51d2a751edea6c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 12 May 2026 12:51:41 +0200 Subject: [PATCH 156/176] hashlib: error on unused containers --- kernel/hashlib.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index b43a68abf..937116178 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -55,6 +55,12 @@ namespace hashlib { * instead of pointers. */ +#if defined(__GNUC__) || defined(__clang__) +# define HASHLIB_ATTRIBUTE_WARN_UNUSED __attribute__((warn_unused)) +#else +# define HASHLIB_ATTRIBUTE_WARN_UNUSED +#endif + const int hashtable_size_trigger = 2; const int hashtable_size_factor = 3; @@ -402,7 +408,7 @@ private: }; template -class dict { +class HASHLIB_ATTRIBUTE_WARN_UNUSED dict { struct entry_t { std::pair udata; @@ -877,7 +883,7 @@ public: }; template -class pool +class HASHLIB_ATTRIBUTE_WARN_UNUSED pool { template friend class idict; @@ -1257,7 +1263,7 @@ public: }; template -class idict +class HASHLIB_ATTRIBUTE_WARN_UNUSED idict { pool database; @@ -1360,7 +1366,7 @@ public: * i-prefixed methods operate on indices in parents */ template -class mfp +class HASHLIB_ATTRIBUTE_WARN_UNUSED mfp { idict database; class AtomicParent { From 3a150f28838a8b171de819d712463f29cb7f4411 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 12 May 2026 12:52:10 +0200 Subject: [PATCH 157/176] remove unused hashlib containers --- passes/equiv/equiv_make.cc | 1 + passes/opt/muxpack.cc | 1 - passes/opt/opt_lut.cc | 4 +--- passes/sat/qbfsat.h | 1 - passes/techmap/abc9_ops.cc | 1 - passes/techmap/flowmap.cc | 4 ++-- 6 files changed, 4 insertions(+), 8 deletions(-) diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index bae7452f7..a9a728f94 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -79,6 +79,7 @@ struct EquivMakeWorker if (token == ".fsm") { IdString modname = RTLIL::escape_id(next_token(line)); + (void)modname; IdString signame = RTLIL::escape_id(next_token(line)); if (encdata.count(signame)) log_cmd_error("Re-definition of signal '%s' in encfile '%s'!\n", signame, fn); diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ac47f6bf7..c13790edf 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -263,7 +263,6 @@ struct MuxpackWorker int cases = GetSize(chain) - cursor; Cell *first_cell = chain[cursor]; - dict taps_dict; if (cases < 2) { cursor++; diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index c0a017748..81a7e5a43 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -421,13 +421,12 @@ struct OptLutWorker } RTLIL::Cell *lutM, *lutR; - pool lutM_inputs, lutR_inputs; + pool lutR_inputs; pool lutM_dlogic_inputs; if (combine == COMBINE_A) { log_debug(" Combining LUTs into cell A.\n"); lutM = lutA; - lutM_inputs = lutA_inputs; lutM_dlogic_inputs = lutA_dlogic_inputs; lutR = lutB; lutR_inputs = lutB_inputs; @@ -436,7 +435,6 @@ struct OptLutWorker { log_debug(" Combining LUTs into cell B.\n"); lutM = lutB; - lutM_inputs = lutB_inputs; lutM_dlogic_inputs = lutB_dlogic_inputs; lutR = lutA; lutR_inputs = lutA_inputs; diff --git a/passes/sat/qbfsat.h b/passes/sat/qbfsat.h index 253cecce4..3441b7819 100644 --- a/passes/sat/qbfsat.h +++ b/passes/sat/qbfsat.h @@ -170,7 +170,6 @@ struct QbfSolutionType { std::smatch m; bool sat_regex_found = false; bool unsat_regex_found = false; - dict hole_value_recovered; for (const std::string &x : stdout_lines) { if(std::regex_search(x, m, hole_value_regex)) { std::string loc = m[1].str(); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e7cf8c637..fc27ac58a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -97,7 +97,6 @@ void check(RTLIL::Design *design, bool dff_mode) ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_) }; - pool processed; for (auto module : design->selected_modules()) for (auto cell : module->cells()) { auto inst_module = design->module(cell->type); diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index f5f225a9b..5b447745a 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -1246,14 +1246,14 @@ struct FlowmapWorker } } log(" Breaking LUT %s to %s LUT %s (potential %d).\n", - log_signal(breaking_lut), lut_nodes[breaking_gate] ? "reuse" : "extract", log_signal(breaking_gate), best_potential); + log_signal(breaking_lut), lut_nodes[breaking_gate] ? "reuse" : "extract", log_signal(breaking_gate), best_potential); if (debug_relax) log(" Removing breaking gate %s from LUT.\n", log_signal(breaking_gate)); lut_gates[breaking_lut].erase(breaking_gate); auto cut_inputs = cut_lut_at_gate(breaking_lut, breaking_gate); - pool gate_inputs = cut_inputs.first, other_inputs = cut_inputs.second; + pool gate_inputs = cut_inputs.first; pool worklist = lut_gates[breaking_lut]; pool elim_gates = gate_inputs; From 74efc883c73ab4e6d900e40ff06a052917ac16f5 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 12 May 2026 23:16:43 +0200 Subject: [PATCH 158/176] threading: temporarily cast to void unused stuff, until we rework single-threaded builds again --- kernel/threading.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/threading.cc b/kernel/threading.cc index 817a48df0..eda6bb4cb 100644 --- a/kernel/threading.cc +++ b/kernel/threading.cc @@ -45,9 +45,12 @@ int ThreadPool::pool_size(int reserved_cores, int max_worker_threads) #ifdef YOSYS_ENABLE_THREADS int available_threads = std::min(std::thread::hardware_concurrency(), get_max_threads()); int num_threads = std::min(available_threads - reserved_cores, max_worker_threads); - return std::max(0, num_threads); + return std::max(0, num_threads); #else - return 0; + (void)reserved_cores; + (void)max_worker_threads; + (void)get_max_threads(); + return 0; #endif } @@ -146,6 +149,8 @@ void ParallelDispatchThreadPool::run_worker(int thread_num) signal_worker_done(); } signal_worker_done(); +#else + (void)current_work; #endif } From 1e28e8ccab9921e0fdd349bfa9bfa78e78ad1bea Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 09:49:39 +0200 Subject: [PATCH 159/176] Handle unused variable for WIN32 --- kernel/driver.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/driver.cc b/kernel/driver.cc index 30c9a285f..73b687f80 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -664,6 +664,7 @@ int main(int argc, char **argv) #ifdef _WIN32 log("End of script. Logfile hash: %s\n", hash); + (void)wall_clock_start; #else std::string meminfo; std::string stats_divider = ", "; From 6ff6f8fb3c7c8075a10bec1034176b44e0cc07c0 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 10:10:59 +0200 Subject: [PATCH 160/176] Bump required standard to C++20 --- .github/workflows/test-compile.yml | 16 ++++++++-------- Makefile | 4 ++-- misc/create_vcxsrc.sh | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index 9c75784bf..c322c25b2 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -82,20 +82,20 @@ jobs: $CXX --version # minimum standard - - name: Build C++17 - shell: bash - run: | - make config-$CC_SHORT - make -j$procs CXXSTD=c++17 compile-only - - # maximum standard, only on newest compilers - name: Build C++20 - if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }} shell: bash run: | make config-$CC_SHORT make -j$procs CXXSTD=c++20 compile-only + # maximum standard, only on newest compilers + - name: Build C++26 + if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }} + shell: bash + run: | + make config-$CC_SHORT + make -j$procs CXXSTD=c++26 compile-only + test-compile-result: runs-on: ubuntu-latest needs: diff --git a/Makefile b/Makefile index 3c5c10cda..afbc11005 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,7 @@ VPATH := $(YOSYS_SRC) # Unit test UNITESTPATH := $(YOSYS_SRC)/tests/unit -export CXXSTD ?= c++17 +export CXXSTD ?= c++20 CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -Werror=unused -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include LIBS := $(LIBS) -lstdc++ -lm PLUGIN_LINKFLAGS := @@ -1142,7 +1142,7 @@ vcxsrc: $(GENFILES) $(EXTRA_TARGETS) kernel/version_$(GIT_REV).cc rm -rf $(VCX_DIR_NAME){,.zip} cp -f kernel/version_$(GIT_REV).cc kernel/version.cc set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \ - echo "Analyse: $$f" >&2; cpp -std=c++17 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt + echo "Analyse: $$f" >&2; cpp -std=c++20 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt echo "libs/fst/fst_win_unistd.h" >> srcfiles.txt echo "kernel/version.cc" >> srcfiles.txt bash misc/create_vcxsrc.sh $(VCX_DIR_NAME) $(YOSYS_VER) diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh index 98c1817bd..c880c2a48 100644 --- a/misc/create_vcxsrc.sh +++ b/misc/create_vcxsrc.sh @@ -35,7 +35,7 @@ popd tail -n +$((n+1)) "$vcxsrc"/YosysVS/YosysVS.vcxproj } > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new -sed -i 's,,\n stdcpp17\n /Zc:__cplusplus %(AdditionalOptions),g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new +sed -i 's,,\n stdcpp20\n /Zc:__cplusplus %(AdditionalOptions),g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new sed -i 's,,YOSYS_ENABLE_THREADS;,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new if [ -f "/usr/include/FlexLexer.h" ] ; then sed -i 's,,;..\\yosys\\libs\\flex,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new From 90e019e319a0b0b81c4b95199937900b20045cce Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 10:11:36 +0200 Subject: [PATCH 161/176] Fix compiling on GCC11 --- passes/cmds/timeest.cc | 6 +++--- passes/sat/formalff.cc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/passes/cmds/timeest.cc b/passes/cmds/timeest.cc index 1caa1ddaf..4f6105356 100644 --- a/passes/cmds/timeest.cc +++ b/passes/cmds/timeest.cc @@ -100,7 +100,7 @@ struct EstimateSta { log_id(cell), log_id(cell->type)); continue; } - if (ff.sig_clk != clk) + if (!clk || ff.sig_clk.as_bit() != *clk) continue; launch.append(ff.sig_q); sample.append(ff.sig_d); @@ -144,12 +144,12 @@ struct EstimateSta { log_error("Unsupported async memory port '%s'\n", log_id(rd.cell)); continue; } - if (sigmap(rd.clk) != clk) + if (!clk || sigmap(rd.clk).as_bit() != *clk) continue; add_seq(rd.cell, rd.data, {rd.addr, rd.srst, rd.en}); } for (auto &wr : mem.wr_ports) { - if (sigmap(wr.clk) != clk) + if (!clk || sigmap(wr.clk).as_bit() != *clk) continue; add_seq(wr.cell, {}, {wr.en, wr.addr, wr.data}); } diff --git a/passes/sat/formalff.cc b/passes/sat/formalff.cc index 452e0e59b..5ac93eca7 100644 --- a/passes/sat/formalff.cc +++ b/passes/sat/formalff.cc @@ -767,7 +767,7 @@ struct FormalFfPass : public Pass { ff.sig_d = ff.sig_ad; } - if (!ff.has_clk || sigmap(ff.sig_clk) != gate_clock || ff.pol_clk != pol_clk) { + if (!ff.has_clk || sigmap(ff.sig_clk).as_bit() != gate_clock || ff.pol_clk != pol_clk) { log_debug("FF driver for gate enable %s.%s of gated clk bit %s.%s has incompatible clocking: " "%s %s.%s\n", log_id(module), log_signal(SigSpec(gate_enable)), log_id(module), @@ -798,7 +798,7 @@ struct FormalFfPass : public Pass { auto &mem = memories.at(clocked_cell->name); bool changed = false; for (auto &rd_port : mem.rd_ports) { - if (rd_port.clk_enable && rd_port.clk == clk && rd_port.clk_polarity == pol_clk) { + if (rd_port.clk_enable && rd_port.clk.as_bit() == clk && rd_port.clk_polarity == pol_clk) { log_debug("patching rd port\n"); changed = true; rd_port.clk = gate_clock; @@ -808,7 +808,7 @@ struct FormalFfPass : public Pass { } } for (auto &wr_port : mem.wr_ports) { - if (wr_port.clk_enable && wr_port.clk == clk && wr_port.clk_polarity == pol_clk) { + if (wr_port.clk_enable && wr_port.clk.as_bit() == clk && wr_port.clk_polarity == pol_clk) { log_debug("patching wr port\n"); changed = true; wr_port.clk = gate_clock; From 25459bd8b96d2e6fedf120b6de703578b5126889 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 11:09:40 +0200 Subject: [PATCH 162/176] Fix for clang-10 toolchain --- .github/workflows/test-compile.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index c322c25b2..2540a8415 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -74,6 +74,7 @@ jobs: uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.compiler }} + gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-10') && '10' || '' }} - name: Tool versions shell: bash @@ -81,6 +82,11 @@ jobs: $CC --version $CXX --version + - name: Fix clang-10 toolchain + if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-10' + run: | + echo "CXXFLAGS=--gcc-toolchain=/usr/lib/gcc/x86_64-linux-gnu/10 -stdlib=libstdc++" >> $GITHUB_ENV + # minimum standard - name: Build C++20 shell: bash From 1ef6311e5b80d6a9b5a32cfcd4e987a1f7f93cd1 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 11:24:45 +0200 Subject: [PATCH 163/176] Update documentation and few more defines --- docs/source/getting_started/installation.rst | 2 +- docs/source/yosys_internals/extending_yosys/contributing.rst | 2 +- docs/source/yosys_internals/index.rst | 2 +- kernel/yosys_common.h | 4 ++-- pyosys/generator.py | 2 +- tests/functional/test_functional.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/getting_started/installation.rst b/docs/source/getting_started/installation.rst index 43b996353..2a90a8071 100644 --- a/docs/source/getting_started/installation.rst +++ b/docs/source/getting_started/installation.rst @@ -87,7 +87,7 @@ not regularly tested: Build prerequisites ^^^^^^^^^^^^^^^^^^^ -A C++ compiler with C++17 support is required as well as some standard tools +A C++ compiler with C++20 support is required as well as some standard tools such as GNU Flex, GNU Bison (>=3.8), Make, and Python (>=3.11). Some additional tools: readline, libffi, Tcl and zlib; are optional but enabled by default (see :makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 1ff77a1fd..8d90d2cbe 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -286,7 +286,7 @@ have incorrect results in unusual situations. Coding style ~~~~~~~~~~~~ -Yosys is written in C++17. +Yosys is written in C++20. In general Yosys uses ``int`` instead of ``size_t``. To avoid compiler warnings for implicit type casts, always use ``GetSize(foobar)`` instead of diff --git a/docs/source/yosys_internals/index.rst b/docs/source/yosys_internals/index.rst index 483cc2bf8..217b88e36 100644 --- a/docs/source/yosys_internals/index.rst +++ b/docs/source/yosys_internals/index.rst @@ -25,7 +25,7 @@ wide range of real-world designs, including the `OpenRISC 1200 CPU`_, the .. _k68 CPU: http://opencores.org/projects/k68 -Yosys is written in C++, targeting C++17 at minimum. This chapter describes some +Yosys is written in C++, targeting C++20 at minimum. This chapter describes some of the fundamental Yosys data structures. For the sake of simplicity the C++ type names used in the Yosys implementation are used in this chapter, even though the chapter only explains the conceptual idea behind it and can be used diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 47dae5473..062036dba 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -120,10 +120,10 @@ # define YS_MAYBE_UNUSED #endif -#if __cplusplus >= 201703L +#if __cplusplus >= 202002L # define YS_FALLTHROUGH [[fallthrough]]; #else -# error "C++17 or later compatible compiler is required" +# error "C++20 or later compatible compiler is required" #endif #if defined(__has_cpp_attribute) && __has_cpp_attribute(gnu::cold) diff --git a/pyosys/generator.py b/pyosys/generator.py index f1d429724..4fd7a5698 100644 --- a/pyosys/generator.py +++ b/pyosys/generator.py @@ -376,7 +376,7 @@ class PyosysWrapperGenerator(object): def make_preprocessor_options(self): py_include = get_paths()["include"] preprocessor_bin = shutil.which("clang++") or "g++" - cxx_std = os.getenv("CXX_STD", "c++17") + cxx_std = os.getenv("CXX_STD", "c++20") return ParserOptions( preprocessor=make_gcc_preprocessor( defines=["_YOSYS_", "YOSYS_ENABLE_PYTHON"], diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py index aa7500f8b..661af14d1 100644 --- a/tests/functional/test_functional.py +++ b/tests/functional/test_functional.py @@ -21,7 +21,7 @@ def yosys(script): run([base_path / 'yosys', '-Q', '-p', script]) def compile_cpp(in_path, out_path, args): - run(['g++', '-g', '-std=c++17'] + args + [str(in_path), '-o', str(out_path)]) + run(['g++', '-g', '-std=c++20'] + args + [str(in_path), '-o', str(out_path)]) def yosys_synth(verilog_file, rtlil_file): yosys(f"read_verilog {quote(verilog_file)} ; prep ; setundef -undriven -undef ; write_rtlil {quote(rtlil_file)}") From 81219c58b2504061cfbae10867589ccc0110f984 Mon Sep 17 00:00:00 2001 From: Iztok Jeras Date: Wed, 13 May 2026 11:59:22 +0200 Subject: [PATCH 164/176] documentation: updated description of 'abc' argument '-dont_use' --- passes/techmap/abc.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 1ed0c867d..bd05aa30d 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1935,8 +1935,10 @@ struct AbcPass : public Pass { log(" file format).\n"); log("\n"); log(" -dont_use \n"); - log(" generate netlists for the specified cell library (using the liberty\n"); - log(" file format).\n"); + log(" avoid usage of the technology cell when mapping the design.\n"); + log(" this option can be used multiple times with different cell names and\n"); + log(" supports simple glob patterns in the cell name.\n"); + log(" only supported with Liberty cell libraries.\n"); log("\n"); log(" -genlib \n"); log(" generate netlists for the specified cell library (using the SIS Genlib\n"); From 105011a53b7454f9d819c4bb4978fa03ad565bb2 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 12:05:13 +0200 Subject: [PATCH 165/176] Zero array for for MSVC --- kernel/io.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/io.h b/kernel/io.h index 171f47a80..96b5bb55d 100644 --- a/kernel/io.h +++ b/kernel/io.h @@ -441,7 +441,8 @@ public: private: std::string_view fmt; bool has_escapes = false; - FoundFormatSpec specs[sizeof...(Args)] = {}; + // Making array at least size of one to make MSVC happy and strict to standards + FoundFormatSpec specs[sizeof...(Args) ? sizeof...(Args) : 1] = {}; }; template struct WrapType { using type = T; }; From 9182329fa1c0b8e73909744dff0cd7865bead342 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 12:05:37 +0200 Subject: [PATCH 166/176] Try making clang-10 to work --- .github/workflows/test-compile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index 2540a8415..a896ccf87 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -85,7 +85,7 @@ jobs: - name: Fix clang-10 toolchain if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-10' run: | - echo "CXXFLAGS=--gcc-toolchain=/usr/lib/gcc/x86_64-linux-gnu/10 -stdlib=libstdc++" >> $GITHUB_ENV + echo "CXXFLAGS=--gcc-toolchain=/usr" >> $GITHUB_ENV # minimum standard - name: Build C++20 From 9070c83145068efe16547720c3b6120eb5fdf1f0 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 13:28:09 +0200 Subject: [PATCH 167/176] Fix for generated project files to work with latest VS --- misc/create_vcxsrc.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh index c880c2a48..dccc31fac 100644 --- a/misc/create_vcxsrc.sh +++ b/misc/create_vcxsrc.sh @@ -25,6 +25,7 @@ if [ -f "/usr/include/FlexLexer.h" ] ; then cp /usr/include/FlexLexer.h libs/flex/FlexLexer.h ls libs/flex/*.h >> ../../srcfiles.txt fi +sed -i '\#libs/../kernel/yosys.h#d' ../../srcfiles.txt popd { From 6d4e5f5ad045899ba9fde0fa00513d01920f2027 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 13 May 2026 14:38:58 +0200 Subject: [PATCH 168/176] Bump versions to safe floor --- .github/workflows/test-compile.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index a896ccf87..fe6a43634 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -44,8 +44,8 @@ jobs: - ubuntu-latest compiler: # oldest supported - - 'clang-10' - - 'gcc-10' + - 'clang-14' + - 'gcc-11' # newest, make sure to update maximum standard step to match - 'clang-19' - 'gcc-14' @@ -74,7 +74,7 @@ jobs: uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.compiler }} - gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-10') && '10' || '' }} + gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14') && '12' || '' }} - name: Tool versions shell: bash @@ -82,10 +82,10 @@ jobs: $CC --version $CXX --version - - name: Fix clang-10 toolchain - if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-10' + - name: Fix clang-14 toolchain + if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14' run: | - echo "CXXFLAGS=--gcc-toolchain=/usr" >> $GITHUB_ENV + echo 'CXXFLAGS=--gcc-toolchain=/usr -isystem /usr/include/c++/12 -isystem /usr/include/x86_64-linux-gnu/c++/12' >> $GITHUB_ENV # minimum standard - name: Build C++20 From 70b17181b42f1c1264dcb4c50916575e61a65f3c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 14 May 2026 10:51:40 +0200 Subject: [PATCH 169/176] Bump gcc and clang versions --- .github/workflows/test-compile.yml | 6 +++--- kernel/fmt.cc | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index fe6a43634..3e2ac34c9 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -47,8 +47,8 @@ jobs: - 'clang-14' - 'gcc-11' # newest, make sure to update maximum standard step to match - - 'clang-19' - - 'gcc-14' + - 'clang-22' + - 'gcc-15' include: # macOS x86 - os: macos-15-intel @@ -96,7 +96,7 @@ jobs: # maximum standard, only on newest compilers - name: Build C++26 - if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }} + if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'clang-22' || matrix.compiler == 'gcc-15' }} shell: bash run: | make config-$CC_SHORT diff --git a/kernel/fmt.cc b/kernel/fmt.cc index 200e7e5ce..15179a75a 100644 --- a/kernel/fmt.cc +++ b/kernel/fmt.cc @@ -804,8 +804,10 @@ std::string Fmt::render() const buf += 'X'; else if (has_z) buf += 'Z'; - else - buf += (part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef")[subvalue.as_int()]; + else { + const char *digits = part.hex_upper ? "0123456789ABCDEF" : "0123456789abcdef"; + buf += digits[subvalue.as_int()]; + } } } else if (part.base == 10) { if (part.show_base) From c6f53aec5fe951022896f89c399b67f3dc7366ae Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 14 May 2026 11:28:16 +0200 Subject: [PATCH 170/176] Fixed log_id instances used with fprintf --- passes/cmds/viz.cc | 2 +- passes/fsm/fsm_recode.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/cmds/viz.cc b/passes/cmds/viz.cc index 9eb35d6c2..0d4e3efda 100644 --- a/passes/cmds/viz.cc +++ b/passes/cmds/viz.cc @@ -718,7 +718,7 @@ struct VizWorker void write_dot(FILE *f) { - fprintf(f, "digraph \"%s\" {\n", module); + fprintf(f, "digraph \"%s\" {\n", module->name.unescape().c_str()); fprintf(f, " rankdir = LR;\n"); dict>> extra_lines; diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index 5c813e481..b32c01c39 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -96,7 +96,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs log_error("FSM encoding `%s' is not supported!\n", encoding); if (encfile) - fprintf(encfile, ".fsm %s %s\n", module, RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); + fprintf(encfile, ".fsm %s %s\n", module->name.unescape().c_str(), RTLIL::unescape_id(cell->parameters[ID::NAME].decode_string()).c_str()); int state_idx_counter = fsm_data.reset_state >= 0 ? 1 : 0; for (int i = 0; i < int(fsm_data.state_table.size()); i++) From 58df27ce7c17ec8881936fea531a4e727a1c1b78 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 14 May 2026 12:21:32 +0200 Subject: [PATCH 171/176] Refactor uses of log_id in pgm files --- passes/opt/peepopt_formal_clockgateff.pmg | 2 +- passes/opt/peepopt_muldiv.pmg | 2 +- passes/opt/peepopt_muldiv_c.pmg | 2 +- passes/opt/peepopt_shiftadd.pmg | 2 +- passes/opt/peepopt_shiftmul_left.pmg | 2 +- passes/opt/peepopt_shiftmul_right.pmg | 2 +- techlibs/microchip/microchip_dsp_cascade.pmg | 4 ++-- techlibs/xilinx/xilinx_dsp_cascade.pmg | 8 ++++---- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/passes/opt/peepopt_formal_clockgateff.pmg b/passes/opt/peepopt_formal_clockgateff.pmg index 835f68bd8..1f44a2cf4 100644 --- a/passes/opt/peepopt_formal_clockgateff.pmg +++ b/passes/opt/peepopt_formal_clockgateff.pmg @@ -44,7 +44,7 @@ endmatch code log("replacing clock gate pattern in %s with ff: latch=%s, and=%s\n", - log_id(module), log_id(latch), log_id(and_gate)); + module, latch, and_gate); // Add a flip-flop and rewire the AND gate to use the output of this flop // instead of the latch. We don't delete the latch in case its output is diff --git a/passes/opt/peepopt_muldiv.pmg b/passes/opt/peepopt_muldiv.pmg index a4e232342..c7eb8ec95 100644 --- a/passes/opt/peepopt_muldiv.pmg +++ b/passes/opt/peepopt_muldiv.pmg @@ -32,7 +32,7 @@ code val_y.extend_u0(GetSize(div_y), param(div, \A_SIGNED).as_bool()); did_something = true; - log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); + log("muldiv pattern in %s: mul=%s, div=%s\n", module, mul, div); module->connect(div_y, val_y); autoremove(div); accept; diff --git a/passes/opt/peepopt_muldiv_c.pmg b/passes/opt/peepopt_muldiv_c.pmg index 2cf9b028b..eb8b31e13 100644 --- a/passes/opt/peepopt_muldiv_c.pmg +++ b/passes/opt/peepopt_muldiv_c.pmg @@ -119,7 +119,7 @@ code autoremove(div); // Log, fixup, accept - log("muldiv_const pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); + log("muldiv_const pattern in %s: mul=%s, div=%s\n", module, mul, div); mul->fixup_parameters(); accept; endcode diff --git a/passes/opt/peepopt_shiftadd.pmg b/passes/opt/peepopt_shiftadd.pmg index 58dbefc12..6144e44ef 100644 --- a/passes/opt/peepopt_shiftadd.pmg +++ b/passes/opt/peepopt_shiftadd.pmg @@ -112,7 +112,7 @@ code did_something = true; log("shiftadd pattern in %s: shift=%s, add/sub=%s, offset: %d\n", \ - log_id(module), log_id(shift), log_id(add), offset); + module, shift, add, offset); SigSpec new_a; if(offset<0) { diff --git a/passes/opt/peepopt_shiftmul_left.pmg b/passes/opt/peepopt_shiftmul_left.pmg index 607f8368c..383222195 100644 --- a/passes/opt/peepopt_shiftmul_left.pmg +++ b/passes/opt/peepopt_shiftmul_left.pmg @@ -99,7 +99,7 @@ code } did_something = true; - log("left shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); + log("left shiftmul pattern in %s: shift=%s, mul=%s\n", module, shift, mul); int const_factor = mul_const.as_int(); int new_const_factor = 1 << factor_bits; diff --git a/passes/opt/peepopt_shiftmul_right.pmg b/passes/opt/peepopt_shiftmul_right.pmg index 108829d4f..ac0958bb8 100644 --- a/passes/opt/peepopt_shiftmul_right.pmg +++ b/passes/opt/peepopt_shiftmul_right.pmg @@ -76,7 +76,7 @@ code reject; did_something = true; - log("right shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); + log("right shiftmul pattern in %s: shift=%s, mul=%s\n", module, shift, mul); int const_factor = mul_const.as_int(); int new_const_factor = 1 << factor_bits; diff --git a/techlibs/microchip/microchip_dsp_cascade.pmg b/techlibs/microchip/microchip_dsp_cascade.pmg index fa276d5b5..ad359138d 100644 --- a/techlibs/microchip/microchip_dsp_cascade.pmg +++ b/techlibs/microchip/microchip_dsp_cascade.pmg @@ -135,10 +135,10 @@ finally } - log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", dsp, dsp_pcin); } else { - log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", dsp, dsp_pcin, MAX_DSP_CASCADE); } dsp = dsp_pcin; diff --git a/techlibs/xilinx/xilinx_dsp_cascade.pmg b/techlibs/xilinx/xilinx_dsp_cascade.pmg index 9eebd33c3..587de4713 100644 --- a/techlibs/xilinx/xilinx_dsp_cascade.pmg +++ b/techlibs/xilinx/xilinx_dsp_cascade.pmg @@ -114,7 +114,7 @@ finally } dsp_pcin->setPort(\OPMODE, opmode); - log_debug("PCOUT -> PCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("PCOUT -> PCIN cascade for %s -> %s\n", dsp, dsp_pcin); } if (AREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 30); @@ -128,7 +128,7 @@ finally dsp->setParam(\ACASCREG, AREG); dsp_pcin->setParam(\A_INPUT, Const("CASCADE")); - log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("ACOUT -> ACIN cascade for %s -> %s\n", dsp, dsp_pcin); } if (BREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 18); @@ -161,11 +161,11 @@ finally dsp_pcin->setParam(\B_INPUT, Const("CASCADE")); } - log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); + log_debug("BCOUT -> BCIN cascade for %s -> %s\n", dsp, dsp_pcin); } } else { - log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", log_id(dsp), log_id(dsp_pcin), MAX_DSP_CASCADE); + log_debug(" Blocking %s -> %s cascade (exceeds max: %d)\n", dsp, dsp_pcin, MAX_DSP_CASCADE); } dsp = dsp_pcin; From 9580ebabc5c4077644afb4beb8b6e0e9002b1836 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 14 May 2026 12:35:01 +0200 Subject: [PATCH 172/176] log_id here was needed for unescaping --- frontends/ast/simplify.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 1b98166e5..95dca27d8 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3250,7 +3250,7 @@ skip_dynamic_range_lvalue_expansion:; if (stage > 1 && type == AST_IDENTIFIER && id2ast != nullptr && id2ast->type == AST_MEMORY && !in_lvalue && children.size() == 1 && children[0]->type == AST_RANGE && children[0]->children.size() == 1) { if (integer < (unsigned)id2ast->unpacked_dimensions) - input_error("Insufficient number of array indices for %s.\n", log_id(str)); + input_error("Insufficient number of array indices for %s.\n", RTLIL::unescape_id(str)); newNode = std::make_unique(location, AST_MEMRD, children[0]->children[0]->clone()); newNode->str = str; newNode->id2ast = id2ast; @@ -3523,7 +3523,7 @@ skip_dynamic_range_lvalue_expansion:; (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE) { if (children[0]->integer < (unsigned)children[0]->id2ast->unpacked_dimensions) - input_error("Insufficient number of array indices for %s.\n", log_id(str)); + input_error("Insufficient number of array indices for %s.\n", RTLIL::unescape_id(str)); std::stringstream sstr; sstr << "$memwr$" << children[0]->str << "$" << RTLIL::encode_filename(*location.begin.filename) << ":" << location.begin.line << "$" << (autoidx++); @@ -5273,7 +5273,7 @@ void AstNode::mem2reg_as_needed_pass1(dict> &mem2reg AstNode *mem = id2ast; if (integer < (unsigned)mem->unpacked_dimensions) - input_error("Insufficient number of array indices for %s.\n", log_id(str)); + input_error("Insufficient number of array indices for %s.\n", RTLIL::unescape_id(str)); // flag if used after blocking assignment (in same proc) if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) { From 4a7878b17fdddc686ccc29033385d02262e8f056 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 14 May 2026 15:58:58 +0200 Subject: [PATCH 173/176] Fixing couple more conversion errors --- frontends/ast/ast.cc | 2 +- passes/cmds/design.cc | 4 ++-- passes/cmds/rename.cc | 8 ++++---- passes/techmap/techmap.cc | 2 +- techlibs/quicklogic/ql_dsp_macc.cc | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 256321252..f5a601c3a 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1584,7 +1584,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design) continue; if (design->module(modname) || design->module("$abstract" + modname)) { log("Reprocessing module %s because instantiated module %s has become available.\n", - name.unescape(), modname); + name.unescape(), RTLIL::unescape_id(modname)); loadconfig(); process_and_replace_module(design, this, ast.get(), NULL); return true; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 68b778790..cfd5d8af8 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -266,7 +266,7 @@ struct DesignPass : public Pass { for (auto mod : copy_src_modules) { - log("Importing %s as %s.\n", mod, prefix); + log("Importing %s as %s.\n", mod, RTLIL::unescape_id(prefix)); RTLIL::Module *t = mod->clone(); t->name = prefix; @@ -295,7 +295,7 @@ struct DesignPass : public Pass { { std::string trg_name = prefix + "." + (cell->type.c_str() + (*cell->type.c_str() == '\\')); - log("Importing %s as %s.\n", fmod, trg_name); + log("Importing %s as %s.\n", fmod, RTLIL::unescape_id(trg_name)); if (copy_to_design->module(trg_name) != nullptr) copy_to_design->remove(copy_to_design->module(trg_name)); diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 15b6bf539..2f70126dd 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -31,13 +31,13 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: to_name = RTLIL::escape_id(to_name); if (module->count_id(to_name)) - log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name, module->name); + log_cmd_error("There is already an object `%s' in module `%s'.\n", RTLIL::unescape_id(to_name), module->name); RTLIL::Wire *wire_to_rename = module->wire(from_name); RTLIL::Cell *cell_to_rename = module->cell(from_name); if (wire_to_rename != nullptr) { - log("Renaming wire %s to %s in module %s.\n", wire_to_rename, to_name, module); + log("Renaming wire %s to %s in module %s.\n", wire_to_rename, RTLIL::unescape_id(to_name), module); module->rename(wire_to_rename, to_name); if (wire_to_rename->port_id || flag_output) { if (flag_output) @@ -50,12 +50,12 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: if (cell_to_rename != nullptr) { if (flag_output) log_cmd_error("Called with -output but the specified object is a cell.\n"); - log("Renaming cell %s to %s in module %s.\n", cell_to_rename, to_name, module); + log("Renaming cell %s to %s in module %s.\n", cell_to_rename, RTLIL::unescape_id(to_name), module); module->rename(cell_to_rename, to_name); return; } - log_cmd_error("Object `%s' not found!\n", from_name); + log_cmd_error("Object `%s' not found!\n", RTLIL::unescape_id(from_name)); } static std::string derive_name_from_src(const std::string &src, int counter) diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 5827feb92..e975d2fd2 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -1265,7 +1265,7 @@ struct TechmapPass : public Pass { i.second.sort(RTLIL::sort_by_id_str()); std::string maps = ""; for (auto &map : i.second) - maps += stringf(" %s", map); + maps += stringf(" %s", map.unescape()); log_debug(" %s:%s\n", i.first.unescape(), maps); } log_debug("\n"); diff --git a/techlibs/quicklogic/ql_dsp_macc.cc b/techlibs/quicklogic/ql_dsp_macc.cc index febfaddf1..083dc3ff1 100644 --- a/techlibs/quicklogic/ql_dsp_macc.cc +++ b/techlibs/quicklogic/ql_dsp_macc.cc @@ -73,7 +73,7 @@ static void create_ql_macc_dsp(ql_dsp_macc_pm &pm) } type = RTLIL::escape_id(cell_base_name + cell_size_name + "_cfg_ports"); - log("Inferring MACC %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, type); + log("Inferring MACC %zux%zu->%zu as %s from:\n", a_width, b_width, z_width, type.unescape()); for (auto cell : {st.mul, st.add, st.mux, st.ff}) if (cell) From 965a3e67f072e7f23084c40f23e18c8899f348d3 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 14 May 2026 17:28:10 +0200 Subject: [PATCH 174/176] Remove pmgen related users of log_id --- passes/pmgen/README.md | 4 +-- techlibs/ice40/ice40_dsp.cc | 18 +++++----- techlibs/ice40/ice40_wrapcarry.cc | 4 +-- techlibs/microchip/microchip_dsp.cc | 2 +- techlibs/xilinx/xilinx_dsp.cc | 52 ++++++++++++++--------------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 542c2c0e8..15b4f79a1 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -34,8 +34,8 @@ for the pattern`` and calls the callback function for each found match: pm.run_foobar([&](){ - log("found matching 'foo' cell: %s\n", log_id(pm.st.foo)); - log(" with 'bar' cell: %s\n", log_id(pm.st.bar)); + log("found matching 'foo' cell: %s\n", pm.st.foo); + log(" with 'bar' cell: %s\n", pm.st.bar); }); The `.pmg` file declares matcher state variables that are accessible via the diff --git a/techlibs/ice40/ice40_dsp.cc b/techlibs/ice40/ice40_dsp.cc index 7942943c4..1d0f98f2f 100644 --- a/techlibs/ice40/ice40_dsp.cc +++ b/techlibs/ice40/ice40_dsp.cc @@ -31,15 +31,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("Checking %s.%s for iCE40 DSP inference.\n", pm.module, st.mul); - log_debug("ffA: %s\n", log_id(st.ffA, "--")); - log_debug("ffB: %s\n", log_id(st.ffB, "--")); - log_debug("ffCD: %s\n", log_id(st.ffCD, "--")); - log_debug("mul: %s\n", log_id(st.mul, "--")); - log_debug("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); - log_debug("ffH: %s\n", log_id(st.ffH, "--")); - log_debug("add: %s\n", log_id(st.add, "--")); - log_debug("mux: %s\n", log_id(st.mux, "--")); - log_debug("ffO: %s\n", log_id(st.ffO, "--")); + log_debug("ffA: %s\n", st.ffA ? st.ffA->name.unescape() : "--"); + log_debug("ffB: %s\n", st.ffB ? st.ffB->name.unescape() : "--"); + log_debug("ffCD: %s\n", st.ffCD ? st.ffCD->name.unescape() : "--"); + log_debug("mul: %s\n", st.mul ? st.mul->name.unescape() : "--"); + log_debug("ffFJKG: %s\n", st.ffFJKG ? st.ffFJKG->name.unescape() : "--"); + log_debug("ffH: %s\n", st.ffH ? st.ffH->name.unescape() : "--"); + log_debug("add: %s\n", st.add ? st.add->name.unescape() : "--"); + log_debug("mux: %s\n", st.mux ? st.mux->name.unescape() : "--"); + log_debug("ffO: %s\n", st.ffO ? st.ffO->name.unescape() : "--"); log_debug("\n"); if (GetSize(st.sigA) > 16) { diff --git a/techlibs/ice40/ice40_wrapcarry.cc b/techlibs/ice40/ice40_wrapcarry.cc index f62019617..63ebdbfcf 100644 --- a/techlibs/ice40/ice40_wrapcarry.cc +++ b/techlibs/ice40/ice40_wrapcarry.cc @@ -31,8 +31,8 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) #if 0 log("\n"); - log("carry: %s\n", log_id(st.carry, "--")); - log("lut: %s\n", log_id(st.lut, "--")); + log("carry: %s\n", st.carry ? st.carry->name.unescape() : "--"); + log("lut: %s\n", st.lut ? st.lut->name.unescape() : "--"); #endif log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n"); diff --git a/techlibs/microchip/microchip_dsp.cc b/techlibs/microchip/microchip_dsp.cc index 01c77644f..ff86049eb 100644 --- a/techlibs/microchip/microchip_dsp.cc +++ b/techlibs/microchip/microchip_dsp.cc @@ -195,7 +195,7 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) auto &st = pm.st_microchip_dsp_packC; log_debug("Analysing %s.%s for Microchip DSP packing (REG_C).\n", pm.module, st.dsp); - log_debug("ffC: %s\n", log_id(st.ffC, "--")); + log_debug("ffC: %s\n", st.ffC ? st.ffC->name.unescape() : "--"); Cell *cell = st.dsp; diff --git a/techlibs/xilinx/xilinx_dsp.cc b/techlibs/xilinx/xilinx_dsp.cc index 94fad6453..5c81bff22 100644 --- a/techlibs/xilinx/xilinx_dsp.cc +++ b/techlibs/xilinx/xilinx_dsp.cc @@ -262,20 +262,20 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) log("Analysing %s.%s for Xilinx DSP packing.\n", pm.module, st.dsp); - log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); - log_debug("preSub: %s\n", log_id(st.preSub, "--")); - log_debug("ffAD: %s\n", log_id(st.ffAD, "--")); - log_debug("ffA2: %s\n", log_id(st.ffA2, "--")); - log_debug("ffA1: %s\n", log_id(st.ffA1, "--")); - log_debug("ffB2: %s\n", log_id(st.ffB2, "--")); - log_debug("ffB1: %s\n", log_id(st.ffB1, "--")); - log_debug("ffD: %s\n", log_id(st.ffD, "--")); - log_debug("dsp: %s\n", log_id(st.dsp, "--")); - log_debug("ffM: %s\n", log_id(st.ffM, "--")); - log_debug("postAdd: %s\n", log_id(st.postAdd, "--")); - log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log_debug("ffP: %s\n", log_id(st.ffP, "--")); - log_debug("overflow: %s\n", log_id(st.overflow, "--")); + log_debug("preAdd: %s\n", st.preAdd ? st.preAdd->name.unescape() : "--"); + log_debug("preSub: %s\n", st.preSub ? st.preSub->name.unescape() : "--"); + log_debug("ffAD: %s\n", st.ffAD ? st.ffAD->name.unescape() : "--"); + log_debug("ffA2: %s\n", st.ffA2 ? st.ffA2->name.unescape() : "--"); + log_debug("ffA1: %s\n", st.ffA1 ? st.ffA1->name.unescape() : "--"); + log_debug("ffB2: %s\n", st.ffB2 ? st.ffB2->name.unescape() : "--"); + log_debug("ffB1: %s\n", st.ffB1 ? st.ffB1->name.unescape() : "--"); + log_debug("ffD: %s\n", st.ffD ? st.ffD->name.unescape() : "--"); + log_debug("dsp: %s\n", st.dsp ? st.dsp->name.unescape() : "--"); + log_debug("ffM: %s\n", st.ffM ? st.ffM->name.unescape() : "--"); + log_debug("postAdd: %s\n", st.postAdd ? st.postAdd->name.unescape() : "--"); + log_debug("postAddMux: %s\n", st.postAddMux ? st.postAddMux->name.unescape() : "--"); + log_debug("ffP: %s\n", st.ffP ? st.ffP->name.unescape() : "--"); + log_debug("overflow: %s\n", st.overflow ? st.overflow->name.unescape() : "--"); Cell *cell = st.dsp; @@ -495,17 +495,17 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) log("Analysing %s.%s for Xilinx DSP48A/DSP48A1 packing.\n", pm.module, st.dsp); - log_debug("preAdd: %s\n", log_id(st.preAdd, "--")); - log_debug("ffA1: %s\n", log_id(st.ffA1, "--")); - log_debug("ffA0: %s\n", log_id(st.ffA0, "--")); - log_debug("ffB1: %s\n", log_id(st.ffB1, "--")); - log_debug("ffB0: %s\n", log_id(st.ffB0, "--")); - log_debug("ffD: %s\n", log_id(st.ffD, "--")); - log_debug("dsp: %s\n", log_id(st.dsp, "--")); - log_debug("ffM: %s\n", log_id(st.ffM, "--")); - log_debug("postAdd: %s\n", log_id(st.postAdd, "--")); - log_debug("postAddMux: %s\n", log_id(st.postAddMux, "--")); - log_debug("ffP: %s\n", log_id(st.ffP, "--")); + log_debug("preAdd: %s\n", st.preAdd ? st.preAdd->name.unescape() : "--"); + log_debug("ffA1: %s\n", st.ffA1 ? st.ffA1->name.unescape() : "--"); + log_debug("ffA0: %s\n", st.ffA0 ? st.ffA0->name.unescape() : "--"); + log_debug("ffB1: %s\n", st.ffB1 ? st.ffB1->name.unescape() : "--"); + log_debug("ffB0: %s\n", st.ffB0 ? st.ffB0->name.unescape() : "--"); + log_debug("ffD: %s\n", st.ffD ? st.ffD->name.unescape() : "--"); + log_debug("dsp: %s\n", st.dsp ? st.dsp->name.unescape() : "--"); + log_debug("ffM: %s\n", st.ffM ? st.ffM->name.unescape() : "--"); + log_debug("postAdd: %s\n", st.postAdd ? st.postAdd->name.unescape() : "--"); + log_debug("postAddMux: %s\n", st.postAddMux ? st.postAddMux->name.unescape() : "--"); + log_debug("ffP: %s\n", st.ffP ? st.ffP->name.unescape() : "--"); Cell *cell = st.dsp; SigSpec &opmode = cell->connections_.at(ID(OPMODE)); @@ -672,7 +672,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) auto &st = pm.st_xilinx_dsp_packC; log_debug("Analysing %s.%s for Xilinx DSP packing (CREG).\n", pm.module, st.dsp); - log_debug("ffC: %s\n", log_id(st.ffC, "--")); + log_debug("ffC: %s\n", st.ffC ? st.ffC->name.unescape() : "--"); Cell *cell = st.dsp; From c16e0352f766a2d94a9b1c78b86a22965b7782bc Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 15 May 2026 11:13:59 +0200 Subject: [PATCH 175/176] Bump to clang-22 on macOS as well --- .github/workflows/test-compile.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index 3e2ac34c9..99e4973a7 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -52,10 +52,10 @@ jobs: include: # macOS x86 - os: macos-15-intel - compiler: 'clang-19' + compiler: 'clang-22' # macOS arm - os: macos-latest - compiler: 'clang-19' + compiler: 'clang-22' fail-fast: false steps: - name: Checkout Yosys @@ -96,7 +96,7 @@ jobs: # maximum standard, only on newest compilers - name: Build C++26 - if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'clang-22' || matrix.compiler == 'gcc-15' }} + if: ${{ matrix.compiler == 'clang-22' || matrix.compiler == 'gcc-15' }} shell: bash run: | make config-$CC_SHORT From e4a3b44e8e24bfffbda46989e19316106026eba7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 15 May 2026 12:34:54 +0200 Subject: [PATCH 176/176] Fixed not intentional log_signal removal --- backends/aiger2/aiger.cc | 2 +- passes/techmap/bufnorm.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index c0ab8a65c..6d8ac8a24 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -1048,7 +1048,7 @@ struct XAigerWriter : AigerWriter { } else if (!is_input && !inputs) { for (auto &bit : conn.second) { if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output)) - log_error("Bad connection %s/%s ~ %s\n", box, conn.first.unescape(), conn.second); + log_error("Bad connection %s/%s ~ %s\n", box, conn.first.unescape(), log_signal(conn.second)); ensure_pi(bit, cursor); diff --git a/passes/techmap/bufnorm.cc b/passes/techmap/bufnorm.cc index 9e6ca2e30..c27f2740d 100644 --- a/passes/techmap/bufnorm.cc +++ b/passes/techmap/bufnorm.cc @@ -502,7 +502,7 @@ struct BufnormPass : public Pass { if (conn.second != newsig) { log(" fixing input signal on cell %s port %s: %s\n", - cell, conn.first.unescape(), newsig); + cell, conn.first.unescape(), log_signal(newsig)); cell->setPort(conn.first, newsig); count_updated_cellports++; }