Compare commits

..

1025 Commits

Author SHA1 Message Date
Miodrag Milanović 1801abf30a
Merge pull request #5913 from YosysHQ/abcexternal
Putting back some Makefile.conf
2026-05-28 09:49:16 +00:00
Miodrag Milanovic d8587f44f0 Putting back some Makefile.conf 2026-05-28 11:13:29 +02:00
KrystalDelusion 4230ebff71
Merge pull request #5912 from YosysHQ/krys/opt_clean_docs
opt_clean: Set group for docs gen
2026-05-28 08:35:52 +00:00
nella 715bc4d7d2
Merge pull request #5909 from YosysHQ/nella/fuse_dsp
Add matching for fused mac operations for Nexus (fix #5906).
2026-05-28 08:28:16 +00:00
nella 1414012676 Add sign and op checks. 2026-05-28 09:58:18 +02:00
nella 7fef67a141 Simplify nexus map. 2026-05-28 09:58:18 +02:00
nella d6106f141c Add matching for fused mac operations for Nexus (fix #5906). 2026-05-28 09:58:18 +02:00
Krystine Sherwin 680bb69d85
opt_clean: Set group for docs gen 2026-05-28 14:50:11 +12:00
Emil J 94ec78b6e8
Merge pull request #5907 from JesseDebuger/main
proc: ignore nosync temporaries in always_latch checks
2026-05-27 07:33:42 +00:00
junyao 6f111118de proc: ignore nosync temporaries in always_latch checks 2026-05-26 00:56:07 +08:00
Miodrag Milanović 9d0cdb8551
Merge pull request #5901 from YosysHQ/test_cleanup
Test out-of-tree build support
2026-05-20 10:55:28 +00:00
Miodrag Milanovic 4c8e61a52b Expose SBY binary location 2026-05-19 16:08:21 +02:00
Miodrag Milanovic 07924a3c62 Use common.mk for sva tests as well 2026-05-19 15:15:41 +02:00
Miodrag Milanovic 2b3f4c37f5 Fix functional tests 2026-05-19 14:42:08 +02:00
Miodrag Milanovic 15e09163cd Do not use Makefile.conf 2026-05-19 14:29:06 +02:00
Miodrag Milanovic c0779f488a Make out of tree build testing possible 2026-05-19 14:26:07 +02:00
Emil J 5c6de04467
Merge pull request #5875 from YosysHQ/emil/threading-fix-no-threads
threading: redirect locks to no-op on single-threaded builds
2026-05-18 19:22:19 +00:00
Miodrag Milanović ffa8618413
Merge pull request #5896 from YosysHQ/remove_file
Remove file added by mistake
2026-05-18 15:39:55 +00:00
Miodrag Milanovic 2159a0e634 Remove file added by mistake 2026-05-18 17:00:16 +02:00
Emil J. Tywoniak 0c2786be1f threading: make no-op locks specialized to Mutex instead of templates 2026-05-18 16:26:14 +02:00
Emil J. Tywoniak 1c831aa50d threading: whitespace 2026-05-18 16:26:14 +02:00
Emil J. Tywoniak d322e2fbe0 threading: redirect locks to no-op when ENABLE_THREADS=0 or undefined YOSYS_ENABLE_THREADS 2026-05-18 16:14:01 +02:00
Miodrag Milanović 7bcda9d304
Merge pull request #5893 from YosysHQ/update_log
Log infrastructure cleanup
2026-05-18 11:10:11 +00:00
Miodrag Milanović 8b68ac04f7
Merge pull request #5890 from strophy/fix-aiger-tests-abcexternal
Fix aiger tests when ABCEXTERNAL is set
2026-05-18 07:59:17 +00:00
Miodrag Milanovic 35d13e1c32 Update documentation/demos based on cleanup 2026-05-18 09:13:46 +02:00
Miodrag Milanovic 4a4c3a3be6 Make better validation 2026-05-18 08:50:38 +02:00
Miodrag Milanovic ef092e1f15 Include conf so individual test running works 2026-05-18 08:50:20 +02:00
Miodrag Milanovic 75dcbe03c6 Convert RTLIL::unescape_id of IdString to unescape() 2026-05-16 19:49:45 +02:00
Miodrag Milanovic 8bbc3c359c Remove id2cstr uses in our code base 2026-05-16 19:49:45 +02:00
Leon White 59c1bc35cb Fix aiger tests when ABCEXTERNAL is set 2026-05-16 09:12:20 +02:00
Emil J e87a9bd9a7
Merge pull request #5888 from mikesinouye/pmux
opt_muxtree: reuse knowledge_t and pass by reference
2026-05-15 16:21:33 +00:00
Miodrag Milanović 4b3165dd50
Merge pull request #5859 from YosysHQ/coverage
Generate coverage for tests
2026-05-15 15:37:58 +00:00
Miodrag Milanović 1d87cefd80
Merge pull request #5882 from YosysHQ/std_cpp20
Bump required standard to C++20
2026-05-15 13:13:43 +00:00
Miodrag Milanović 36eceed720
Merge pull request #5862 from codexplorer-fish/cleaning-up-log-id
Cleaning up log_id()
2026-05-15 11:07:43 +00:00
Miodrag Milanovic 992eceaaa0 Ignore configured location 2026-05-15 12:53:04 +02:00
Miodrag Milanovic e4a3b44e8e Fixed not intentional log_signal removal 2026-05-15 12:34:54 +02:00
Miodrag Milanovic 8022b5445b Convert to using LLVM code coverage 2026-05-15 11:59:22 +02:00
Miodrag Milanovic c16e0352f7 Bump to clang-22 on macOS as well 2026-05-15 11:13:59 +02:00
Martin Povišer b423cc3bd6
Merge pull request #5884 from jeras/main
documentation: updated description of 'abc' argument '-dont_use'
2026-05-15 01:13:07 +00:00
Miodrag Milanovic 965a3e67f0 Remove pmgen related users of log_id 2026-05-14 17:28:10 +02:00
Miodrag Milanovic 4a7878b17f Fixing couple more conversion errors 2026-05-14 15:58:58 +02:00
Miodrag Milanovic 9580ebabc5 log_id here was needed for unescaping 2026-05-14 12:35:01 +02:00
Miodrag Milanovic 58df27ce7c Refactor uses of log_id in pgm files 2026-05-14 12:21:32 +02:00
Miodrag Milanovic c6f53aec5f Fixed log_id instances used with fprintf 2026-05-14 11:28:16 +02:00
Miodrag Milanovic 70b17181b4 Bump gcc and clang versions 2026-05-14 10:51:40 +02:00
Miodrag Milanovic 6ac8758e7e Generate coverage for tests 2026-05-14 08:11:43 +02:00
Miodrag Milanović 27ae62f492
Merge pull request #5881 from YosysHQ/fix_mingw32
Remove unused variable for WIN32
2026-05-14 05:49:26 +00:00
Mike Inouye e20a57b09e
Reuse knowledge_t and pass by reference 2026-05-13 10:57:18 -07:00
Miodrag Milanovic 6d4e5f5ad0 Bump versions to safe floor 2026-05-13 14:38:58 +02:00
Miodrag Milanovic 9070c83145 Fix for generated project files to work with latest VS 2026-05-13 13:28:09 +02:00
Miodrag Milanovic 9182329fa1 Try making clang-10 to work 2026-05-13 12:05:37 +02:00
Miodrag Milanovic 105011a53b Zero array for for MSVC 2026-05-13 12:05:13 +02:00
Iztok Jeras 81219c58b2 documentation: updated description of 'abc' argument '-dont_use' 2026-05-13 11:59:22 +02:00
Miodrag Milanovic 1ef6311e5b Update documentation and few more defines 2026-05-13 11:24:45 +02:00
Miodrag Milanovic 25459bd8b9 Fix for clang-10 toolchain 2026-05-13 11:09:40 +02:00
Miodrag Milanovic 90e019e319 Fix compiling on GCC11 2026-05-13 10:11:36 +02:00
Miodrag Milanovic 6ff6f8fb3c Bump required standard to C++20 2026-05-13 10:10:59 +02:00
Miodrag Milanovic 1e28e8ccab Handle unused variable for WIN32 2026-05-13 09:49:39 +02:00
Emil J 2046a23a2f
Merge pull request #5876 from YosysHQ/emil/error-unused-containers
Makefile: error on unused variables, including hashlib containers
2026-05-12 21:53:23 +00:00
Emil J. Tywoniak 74efc883c7 threading: temporarily cast to void unused stuff, until we rework single-threaded builds again 2026-05-12 23:16:43 +02:00
Miodrag Milanović 90c26fe671
Merge pull request #5874 from YosysHQ/release/v0.65
Release version 0.65
2026-05-12 11:07:48 +00:00
Emil J. Tywoniak 3a150f2883 remove unused hashlib containers 2026-05-12 12:52:10 +02:00
Emil J. Tywoniak 4eb1c61bd5 hashlib: error on unused containers 2026-05-12 12:51:41 +02:00
Emil J. Tywoniak b06f9bdf18 Makefile: error on unused variables 2026-05-12 12:51:12 +02:00
Miodrag Milanovic 6f16a5cf5f Next dev cycle 2026-05-12 12:32:27 +02:00
Miodrag Milanovic b85cad6347 Release version 0.65 2026-05-12 11:37:23 +02:00
Miodrag Milanović 3c619da259
Merge pull request #5873 from YosysHQ/update_abc
Update ABC as per 2026-05-12
2026-05-12 07:24:24 +00:00
Miodrag Milanovic b61bc1eee0 Update ABC as per 2026-05-12 2026-05-12 08:37:44 +02:00
Emil J 54866d154f
Merge pull request #5863 from mole99/leo/memlib-docs
memlib: fix documentation for `PORT_<name>_CLK_POL`
2026-05-11 15:15:04 +00:00
Miodrag Milanović 84605d89b7
Merge pull request #5872 from YosysHQ/update_abc
Update ABC, reverts 6aaf0db1e1201d72888a461463485b0b5595075a
2026-05-11 13:25:11 +00:00
Miodrag Milanovic 7fe32137bd Revert "Fix tests due to ABC improvements"
This reverts commit 417e871b06.
2026-05-11 14:47:08 +02:00
Miodrag Milanovic 40c1485828 Update ABC, reverts 6aaf0db1e1201d72888a461463485b0b5595075a 2026-05-11 14:37:21 +02:00
Leo Moser fb83719745
memlib: fix documentation for `PORT_<name>_CLK_POL`
Signed-off-by: Leo Moser <leomoser99@gmail.com>
2026-05-09 10:28:07 +02:00
Codexplorer e41b969da2 Refactored uses of log_id() 2026-05-08 20:59:24 -07:00
Codexplorer 89d83a3410 Logging now handles classes with an IdString "name" member 2026-05-08 16:30:25 -07:00
Emil J 1f02343268
Merge pull request #5817 from YosysHQ/emil/clockgate-reject-sdffe
clockgate: reject $sdffe to fix priority handling
2026-05-08 18:38:51 +00:00
nella db258e6dd9
Merge pull request #5721 from tefantasy/abc-liberty-args
abc: new option to pass extra ABC read_lib args
2026-05-08 13:41:01 +00:00
nella 3f68ee851b
Merge branch 'main' into abc-liberty-args 2026-05-08 15:08:12 +02:00
KrystalDelusion bfc09777e6
Merge pull request #5858 from YosysHQ/krys/check_before_flatten
Docs: Update synth starter for check before flatten
2026-05-08 02:31:03 +00:00
Tianji Liu 3f354eb03b abc: update log for extra read_lib args 2026-05-08 07:17:29 +08:00
nella 10dc0d48b8
Merge branch 'main' into abc-liberty-args 2026-05-07 21:20:17 +02:00
Emil J. Tywoniak 425d47ad2c clockgate: test $sdffe rejected 2026-05-07 16:13:14 +02:00
Emil J. Tywoniak 687e5442f2 clockgate: formal liberty tests 2026-05-07 16:08:55 +02:00
Emil J. Tywoniak f4a10a4808 clockgate: reject $sdffe for correct priority handling 2026-05-07 14:41:18 +02:00
Emil J 4e35ed5955
Merge pull request #5827 from cdleary/cdleary/2026-04-21-sv-positional-assignment-unpacked
Support positional assignment patterns for unpacked arrays
2026-05-07 10:55:17 +00:00
Tianji Liu cb6209506e abc: disable scl merge if extra read_lib args provided 2026-05-07 18:45:35 +08:00
Tianji Liu f8a50e7174 Merge commit 'ab316c14d2c3f950eda7672e5c5507bb5219205a' into abc-liberty-args 2026-05-07 18:12:49 +08:00
Krystine Sherwin 3b26a9e45e
Docs: Update synth starter for check before flatten 2026-05-07 17:38:30 +12:00
Lofty ab316c14d2
Merge pull request #5844 from YosysHQ/lofty/abc-refactor-5
abc_new: integration testing via synth_gatemate
2026-05-06 13:40:15 +00:00
Lofty de1dd3b1c5 add aiger2_zbuf to constids 2026-05-06 14:03:07 +01:00
Lofty fecea911ff synth_gatemate: add -abc_new option 2026-05-06 14:02:48 +01:00
nella 0641b7a725
Merge pull request #5850 from YosysHQ/nella/synth-check
Add check before flatten in synth - Fix #429
2026-05-06 11:23:40 +00:00
nella 7de7d04d7c Update macro order. 2026-05-05 14:53:31 +02:00
nella fff034d2f8 Add check before flatten in synth_*. 2026-05-05 14:06:58 +02:00
Miodrag Milanović 49b4f6d813
Merge pull request #5855 from YosysHQ/abc_32bit
Update ABC with 050-no-128-bit-archs.patch
2026-05-05 11:43:20 +00:00
Miodrag Milanovic 50266c8aa8 Update ABC with 050-no-128-bit-archs.patch 2026-05-05 13:06:20 +02:00
Emil J 73e15f2144
Merge pull request #5851 from YosysHQ/emil/share-remove-force
share: remove -force
2026-05-05 09:06:16 +00:00
Miodrag Milanović b864f70e52
Merge pull request #5848 from YosysHQ/latest_llvm
Use latest brew LLVM on macOS
2026-05-05 04:33:59 +00:00
KrystalDelusion 8427bd3a35
Merge pull request #5807 from petterreinholdtsen/docs-dot-dimensions
Adjusted dot call to avoid pdflatex rejecting input due to too high resolution.
2026-05-04 22:42:11 +00:00
Krystine Sherwin 67fac1879c
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.
2026-05-05 10:24:04 +12:00
Emil J. Tywoniak 7fa660fc60 share: remove -force 2026-05-04 21:34:19 +02:00
nella 16b893bd88 Add check before flatten in synth. 2026-05-04 19:05:00 +02:00
Miodrag Milanović 239e3c2849
Merge pull request #5849 from YosysHQ/strip_windows
Strip windows binaries
2026-05-04 14:34:06 +00:00
Miodrag Milanovic 6cd784e52c Strip windows binaries 2026-05-04 15:47:40 +02:00
Miodrag Milanovic df1fb14b0c Use latest brew LLVM on macOS 2026-05-04 10:26:58 +02:00
Catherine ca88868902
Merge pull request #5846 from flumf/main
Upgrade to WASI SDK 33 and drop exception workaround
2026-05-02 09:58:40 +00:00
bin 5dfe1937a0 Upgrade to WASI SDK 33 and enable exceptions 2026-05-01 13:30:43 -04:00
Emil J 18b832247b
Merge pull request #5843 from QuantamHD/simplemap_pmux
simplemap: Moves $pmux mapping from techmap.v to simple map
2026-04-30 10:36:27 +00:00
Ethan Mahintorabi 805c302411
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 <ethanmoon@google.com>
2026-04-29 21:20:39 +00:00
nella 92287d4857
Merge pull request #5841 from YosysHQ/nella/fix-liberty
Fix ABC: Merged scl conversion failed, using liberty format warning when using -genlib.
2026-04-28 16:43:25 +00:00
nella d2f7fecef5 Fix liberty cache warning with -genlib. 2026-04-28 15:21:54 +02:00
Lofty 0d3923d086 abc_new: use default script if not specified 2026-04-28 12:33:21 +01:00
Emil J a966d06524
Merge pull request #5825 from petterreinholdtsen/autotest-race-text-busy
Added locking around compiling in autotest.sh to avoid text busy race.
2026-04-28 09:12:33 +00:00
Emil J cfa66f5335
Merge pull request #5824 from petterreinholdtsen/autotest-cxxflags
Use CPPFLAGS and CXXFLAGS when compiling in autotest.sh.
2026-04-27 22:06:07 +00:00
nella 4dbae6a473
Merge pull request #5826 from petterreinholdtsen/autotest-print-log-on-error
Made autotest.sh print log on error for easier debugging in CI setups.
2026-04-27 15:43:43 +00:00
Emil J 627b691578
Merge pull request #5831 from stashcroft/main
Make sure co-simulation only uses integer arithmetic
2026-04-27 14:03:58 +00:00
Miodrag Milanović 6b78731792
Merge pull request #5829 from YosysHQ/update_abc
Update ABC as per 2026-04-22
2026-04-27 10:59:29 +00:00
Lofty 5197b9c8ce
Merge pull request #5833 from ghaworth/fix-sdp-dipbdip-typo
Fix RAMB36E1/E2 SDP parity port mapping typo
2026-04-25 08:41:31 +00:00
Petter Reinholdtsen 3187275184 Use CPPFLAGS and CXXFLAGS when compiling in autotest.sh.
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.
2026-04-25 06:47:26 +02:00
Petter Reinholdtsen c03c0d5f9d 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
<URL: https://bugs.debian.org/1133986 >, which include a
link to the build log of the failed build.
2026-04-25 00:02:05 +02:00
Petter Reinholdtsen 59b3b6d4e4 Added locking around compiling in autotest.sh to avoid text busy race.
Patch by Daniel Gröber via Debian.

See also issue #5805.
2026-04-25 00:01:34 +02:00
Petter Reinholdtsen c5a8c3cca5 Made autotest.sh print log on error for easier debugging in CI setups.
Patch by Daniel Gröber via Debian.

See also issue #5805.
2026-04-25 00:01:03 +02:00
Emil J ec0a102302
Merge pull request #5832 from YosysHQ/emil/simple-extract
rtlil: rewrite SigSpec::extract for perf and packing
2026-04-24 19:03:53 +00:00
Emil J 30a914167f
Merge pull request #5809 from QuantamHD/pmux_on2
opt: Remove O(n²) opt routines across the codebase for pmux
2026-04-24 19:03:40 +00:00
Emil J. Tywoniak e0b833ac1a opt_muxtree: dense knowledge 2026-04-24 11:07:58 +02:00
Emil J. Tywoniak 4abaca273e opt_reduce: further optimization 2026-04-24 11:07:58 +02:00
Emil J. Tywoniak 10bbda93f7 rtlil: extend SigSpec::extract test 2026-04-24 11:04:19 +02:00
Emil J. Tywoniak a2dafce910 unit tests: rename SigSpec::extract test 2026-04-24 11:04:19 +02:00
Emil J. Tywoniak 25b9b796c4 rtlil: complicate extract again for packing 2026-04-24 11:04:19 +02:00
Christopher D. Leary 390f09b89a Support positional assignment patterns for unpacked arrays 2026-04-23 14:29:38 -07:00
Scott Ashcroft 23a05fcf35 Add comments to make sure it is clear scale is an exponent of 10 2026-04-23 17:22:14 +01:00
Scott Ashcroft e69341cd5f Make sure co-simulation only uses integer arithmetic 2026-04-23 17:22:14 +01:00
Emil J 2dc69a7578
Merge pull request #5828 from YosysHQ/emil/bash-no-fhs
Remove FHS dependency by replacing /bin/bash with /usr/bin/env bash
2026-04-23 15:47:57 +00:00
Emil J. Tywoniak 14d0138d0c Remove FHS dependency by replacing /bin/sh with /usr/bin/env sh 2026-04-23 15:55:11 +02:00
Emil J. Tywoniak dc570e3d55 Remove FHS dependency by replacing /bin/env with /usr/bin/env 2026-04-23 15:48:33 +02:00
Emil J. Tywoniak 14b0efeced rtlil: simplify extract for performance 2026-04-23 13:58:20 +02:00
nella 7e7336cdb8
Merge pull request #5813 from YosysHQ/nella/fast-liberty-file
abc/abc_new: cache parsed liberty files as .scl to avoid re-parsing across invocations
2026-04-23 11:16:08 +00:00
nella d795a4f1d2 Fix WASI, store in temp dir. 2026-04-23 12:43:43 +02:00
nella afac9a28b0 Fix WASI build. 2026-04-23 12:43:43 +02:00
nella 5d4d94a5dd Fix mac compile. 2026-04-23 12:43:43 +02:00
nella 94a215b4f7 Add dont_use_cells to scl cache. 2026-04-23 12:43:43 +02:00
nella edd3ad525e Add scl caching to abc_new. 2026-04-23 12:43:43 +02:00
nella 9143178343 Merge liberty files into stripped scl files. 2026-04-23 12:43:43 +02:00
Miodrag Milanovic bc83311dd8 Update ABC as per 2026-04-22 2026-04-22 17:37:25 +02:00
Emil J 64e7ce2f57
Merge pull request #5803 from YosysHQ/emil/specrule-port-sanity
Fix $specrule port naming inconsistency
2026-04-22 10:46:36 +00:00
Emil J. Tywoniak f213a34427 Remove FHS dependency by replacing /bin/bash with /usr/bin/env bash everywhere 2026-04-22 10:39:19 +02:00
Emil J 70ee009dd9
Merge pull request #5823 from petterreinholdtsen/spelling-error-frontends-ast-genrtlil
Fixed spelling error in message of frontends/ast/genrtlil.cc.
2026-04-22 08:18:07 +00:00
Miodrag Milanović 3ccbd38cc6
Merge pull request #5768 from YosysHQ/tests
Update tests and test infrastructure
2026-04-22 06:16:05 +00:00
Petter Reinholdtsen a89e8fd869 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.
2026-04-22 04:30:18 +02:00
Lofty ed5d122174
Merge pull request #5793 from YosysHQ/lofty/abc-refactor-4
read/write_xaiger2: further cleanup [sc-269]
2026-04-21 12:13:42 +00:00
N. Engelhardt 2da90a5ad6
Merge pull request #5819 from YosysHQ/xprop_ignore_scopeinfo
xprop: ignore $scopeinfo cells
2026-04-21 09:31:44 +00:00
N. Engelhardt 240f7030b2 xprop: ignore $scopeinfo cells 2026-04-21 10:52:50 +02:00
Emil J 22ef992189
Merge pull request #5816 from petterreinholdtsen/proc-no-path-max
Rewrote Linux edition of proc_self_dirname() to handle any symlink length.
2026-04-20 09:47:59 +00:00
Lofty 33fba24158
Merge pull request #5811 from YosysHQ/emil/abc-fix-deferred-logs
abc: fix deferred logs
2026-04-20 07:56:45 +00:00
Petter Reinholdtsen 89d360aa4a 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.
2026-04-19 20:56:05 +02:00
George Haworth aba5b279c6 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.
2026-04-18 19:10:18 +03:00
Emil J. Tywoniak b4c081c70b abc: fix deferred logs 2026-04-17 13:35:47 +02:00
Miodrag Milanovic a666712687 Update arith_tree tests 2026-04-16 11:04:14 +02:00
Miodrag Milanovic 5737d2db35 Cleanup 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 76732497b9 Cleanup 2026-04-16 11:00:44 +02:00
Miodrag Milanovic bfd3e150fa Add proper deps 2026-04-16 11:00:44 +02:00
Miodrag Milanovic f04532bbac Try to make it more stable 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 8bed9bd824 Use this for now so we can see actual output of functional tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic a490f1c3c4 Move output redirect to one place 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 9c3d79b041 Cleanup 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 1aad357370 Fix some escaping with different approach 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 5ffa0b1dd7 Disabled some in fmt for now 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 686267ea81 Convert functional 2026-04-16 11:00:44 +02:00
Miodrag Milanovic bfd639f6a0 Disable failing test for now 2026-04-16 11:00:44 +02:00
Miodrag Milanovic f087a94470 Convert svinterfaces 2026-04-16 11:00:44 +02:00
Miodrag Milanovic f42800d4d3 Convert arch 2026-04-16 11:00:44 +02:00
Miodrag Milanovic c272bfbdc3 Convert liberty 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 149e2f343a Converted cxxrtl 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 4a89ae66ff Small fix 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 1c76cadac7 Converted rpc 2026-04-16 11:00:44 +02:00
Miodrag Milanovic fdccbe584d Convert realmath 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 514c55f53f Fix yml for verific tests 2026-04-16 11:00:44 +02:00
nella 3ceeb3b00c Consolidated memlib generate script 2026-04-16 11:00:44 +02:00
nella 58e0473e29 Convert bram tests 2026-04-16 11:00:44 +02:00
nella ee31950770 Convert memfile tests 2026-04-16 11:00:44 +02:00
nella 4a9dc33098 Convert memlib tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 1effec2029 Make test simple 2026-04-16 11:00:44 +02:00
Miodrag Milanovic c15bcca25a Better fix 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 0ba9a0fb16 Try fixing tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic d1dc23d9f8 Did share, opt_share and fsm 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 652bbd2b41 Convert xprop tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 68e01a03d7 Converted some more 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 2bc46e77c8 Converted blif tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 1231bd5397 Convert memories tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 5a06a79c0c Correctly handle errors 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 2a8d369be3 Document not covered 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 1bfb95513c Convert autotest script wrapper 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 474d0d7b2e cleanup 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 8953007483 Use generic testing on few more places 2026-04-16 11:00:44 +02:00
Miodrag Milanovic f96fa5ff00 cleanup 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 8ff28a2a86 add prep 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 336a06d091 Add common.mk 2026-04-16 11:00:44 +02:00
Miodrag Milanovic c04d724337 report on summary 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 45bb0413bf Look for all result files 2026-04-16 11:00:44 +02:00
Miodrag Milanovic b361569abf Save results, and create summary and report 2026-04-16 11:00:44 +02:00
Miodrag Milanovic ced2521b03 Convert gen-tests shell script to python 2026-04-16 11:00:44 +02:00
Miodrag Milanovic a2e1fbcfc6 Enabled realmath that was disabled for some reason 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 2f9e35acb8 Fix deprecation warning 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 712ce93501 Clean some seed-tests outputs 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 999255e40c Clean some seed-tests outputs 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 2774671346 Cleanup for abcopt-tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic fc55f16fae Ignore some generated files 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 3c2adfb523 Do not write to console for makefile-tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic ff2dcef53f Propagate ABCOPT and SEEDOPT 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 8f7e5e9449 Make sure targets are built for tests 2026-04-16 11:00:44 +02:00
Miodrag Milanovic 5494000fd7 Move clean for tests in proper Makefile 2026-04-16 11:00:44 +02:00
Miodrag Milanovic c99855535a Split vanilla-test to separate Makefile 2026-04-16 11:00:44 +02:00
Emil J. Tywoniak 0b3d03e69c newcelltypes: fix $specrule port naming 2026-04-13 22:34:46 +02:00
Emil J. Tywoniak 3e45f9729e fix $specrule port naming 2026-04-13 22:34:46 +02:00
nella 413169663d
Merge pull request #5753 from YosysHQ/nella/carry-save-adders
Add Carry-save adders
2026-04-13 11:16:33 +00:00
nella 4506dffa9f Fix use after free. 2026-04-13 12:48:05 +02:00
nella fc71719e6e Rename csa_tree to arith_tree. 2026-04-13 12:48:05 +02:00
nella c3c577f333 Fix test cases. 2026-04-13 12:48:05 +02:00
nella 135812ab02 Further CSA cleanup. 2026-04-13 12:48:05 +02:00
nella 847a8941e9 Clang-Format CSA tree. 2026-04-13 12:48:05 +02:00
nella a02c238874 Consolidate Wallace from booth and CSA. 2026-04-13 12:48:05 +02:00
nella 4bbffecf98 Invert. 2026-04-13 12:48:05 +02:00
nella 42c309347b Clarify. 2026-04-13 12:48:05 +02:00
Emil J. Tywoniak b6d656e932 csa_tree: move to techmap 2026-04-13 12:48:05 +02:00
Emil J. Tywoniak b6a8feec22 csa_tree: refactor 2026-04-13 12:48:05 +02:00
nella 67e145618b Replace utf arrow with ascii arrow. 2026-04-13 12:48:05 +02:00
nella 4f4c820f73 Cleaned up CSA tests. 2026-04-13 12:48:05 +02:00
nella 9cc2e7d95e rm misc comments. 2026-04-13 12:48:05 +02:00
nella 0f61ba5299 Move csa after alumacc. 2026-04-13 12:48:05 +02:00
nella 9dc408eea7 CSA add alumacc related tests. 2026-04-13 12:48:05 +02:00
nella 5d90bcc792 CSA add support for macc and alu cells. 2026-04-13 12:48:05 +02:00
nella fc9adae9a2 Consolidate csa tests. 2026-04-13 12:48:05 +02:00
nella ab1c423692 Tighten csa tests. 2026-04-13 12:48:05 +02:00
nella b64b75db7a Add csa to synth. 2026-04-13 12:48:05 +02:00
nella cfee6bb4af Add more robsutness tests. 2026-04-13 12:48:05 +02:00
nella 6b0caedcdd Add chain tests and tighten synthesis assertions for csa. 2026-04-13 12:48:05 +02:00
nella 335cce4895 Add sub chain support for csa trees. 2026-04-13 12:48:05 +02:00
nella 7183016910 Edge case tests. 2026-04-13 12:48:05 +02:00
nella 1a4a41812c Add csa synth tests. 2026-04-13 12:48:05 +02:00
nella 4c4c5cf15a Add structural tests for csa_tree. 2026-04-13 12:48:05 +02:00
nella e69914b8be better balancing. 2026-04-13 12:48:05 +02:00
nella 46df888191 impl csa tree. 2026-04-13 12:48:05 +02:00
Emil J 90b906c4fc
Merge pull request #5635 from YosysHQ/emil/contributing-again
docs: touch up contributing guidelines
2026-04-12 22:10:41 +00:00
Lofty d51a5535c7
Merge pull request #5798 from rocallahan/hashtable-destruction-race
Avoid racing accesses to shards[0] in ShardedHashtable parallel destruction
2026-04-11 10:25:58 +00:00
Lofty 564c617721
Merge pull request #5790 from Eiko-Eira/main
Fixed typos and incorrect grammar
2026-04-11 03:26:55 +00:00
nella a54bca5493
Merge pull request #5794 from rocallahan/dispatch-pool-destruction
Fix data race in ParallelDispatchThreadPool destruction
2026-04-09 09:57:25 +00:00
Miodrag Milanović 8449dd4700
Merge pull request #5796 from YosysHQ/release/v0.64
Release version 0.64
2026-04-09 06:39:48 +00:00
Miodrag Milanovic dbc6911f40 Next dev cycle 2026-04-09 07:36:58 +02:00
Miodrag Milanovic 7c714b8acc Fix repository check in yml 2026-04-09 07:31:58 +02:00
KrystalDelusion a4b6a8c580
Merge pull request #5799 from YosysHQ/fix_rtd
Fix Read the Docs triggering
2026-04-08 23:10:42 +00:00
KrystalDelusion 9a0842b76a
Merge branch 'main' into fix_rtd 2026-04-09 10:39:08 +12:00
Krystine Sherwin cb56f01971
prepare-docs.yml: Don't skip pushes 2026-04-09 10:30:08 +12:00
Robert O'Callahan 1f6559a5cf Avoid racing accesses to shards[0] in ShardedHashtable parallel destruction 2026-04-08 21:56:36 +00:00
Miodrag Milanovic 74070911cd Fix repository check in yml 2026-04-08 18:11:46 +02:00
Miodrag Milanovic 6d2c445aeb Release version 0.64 2026-04-08 16:54:50 +02:00
Emil J 86448c0001
Merge pull request #5655 from YosysHQ/emil/dffsr-sr-priority-undef
Undefine set&reset behavior of $dffsr
2026-04-08 14:22:34 +00:00
Miodrag Milanović f7b19774b7
Merge pull request #5795 from YosysHQ/update_abc
Update ABC as per 2026-04-08
2026-04-08 12:04:18 +00:00
Miodrag Milanovic 6b5cd74d7e Update ABC as per 2026-04-08 2026-04-08 13:29:08 +02:00
Lofty 6d715784cd read_xaiger2: further cleanup 2026-04-08 11:08:59 +01:00
Lofty f09afcf581 write_xaiger2: further cleanup 2026-04-08 11:08:44 +01:00
Emil J b485173428
Merge pull request #5792 from YosysHQ/emil/toposort-stability
toposort: avoid run to run variance caused by pointer sensitivity
2026-04-08 08:51:47 +00:00
Robert O'Callahan d586af0074 Fix data race in ParallelDispatchThreadPool destruction 2026-04-07 23:21:17 +00:00
Emil J. Tywoniak 9b9e334c79 contributing: small responses to feedback 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak cc3827c80c docs: consolidate contributing.md into contributing.rst harder 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak 2572b1e3df .github: fix label for links 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak 9385928bc2 contributing: Yosys HQ -> YosysHQ 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak d6518f1b9a contributing: fix links 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak 342b0e5fc1 contributing: require bug report inputs to pass check 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak 8bf42c01ce contributing: finish cut off sentence 2026-04-07 18:59:06 +02:00
Emil J. Tywoniak d75d513402 contributing: reformulate HQ GmbH involvement 2026-04-07 18:59:06 +02:00
Lofty a96cf8cc2b
Merge pull request #5789 from YosysHQ/lofty/abc-refactor-3
aig-related cleanup [sc-269]
2026-04-07 09:05:18 +00:00
Emil J. Tywoniak 41b69df2cb abc_new: stable TopoSort 2026-04-06 15:09:52 +02:00
Emil J. Tywoniak cd49dc7be8 cxxrtl: stable TopoSort 2026-04-06 15:09:52 +02:00
Emil J. Tywoniak 41b41fefb3 utils: forbid the use of std::less on pointers in TopoSort 2026-04-06 15:09:52 +02:00
Emil J. Tywoniak 2033df5958 utils: refactor TopoSort 2026-04-06 15:09:52 +02:00
Miodrag Milanović 37ca545b65
Merge pull request #5791 from YosysHQ/ci_macos
Enable macOS builds
2026-04-03 06:54:30 +00:00
Miodrag Milanovic d58e0447c7 Enable macOS builds 2026-04-03 07:59:00 +02:00
Noah Van Dijk 52243e10fb
Fix typo in pmgen/README.md
Line 161:
calulated > calculated
2026-04-02 10:24:31 -05:00
Noah Van Dijk cdf549a493
Fix typos in GettingStarted
Line 8:
is a the > is the

line 88:
all this types > all these types
2026-04-02 10:23:13 -05:00
Lofty b55fd6718b write_xaiger2: fix indentation 2026-04-02 10:47:08 +01:00
Emil J cede13a742
Merge pull request #5765 from YosysHQ/emil/muxpack-wide-port
muxpack: fix wide Y port handling
2026-03-31 10:49:39 +00:00
Emil J ecaaea8734
Merge pull request #5786 from YosysHQ/gus/muxpack-wide-y-test
Regression test for #5765
2026-03-31 12:47:08 +02:00
Lofty 568a31c83a write_xaiger2: fix function argument evaluation order 2026-03-31 10:40:58 +01:00
Lofty 162eeea29a cellaigs: remove some dead code 2026-03-31 09:37:18 +01:00
Lofty 240439bdb0
Merge pull request #5781 from YosysHQ/update_abc
Update ABC as per 2026-03-27
2026-03-30 16:37:29 +00:00
Lofty 903695892a
Merge pull request #5784 from YosysHQ/lofty/abc-changelog
changelog: update for abc changes
2026-03-30 16:36:08 +00:00
Gus Smith 6a5fea1b27 Regression test for #5765 2026-03-30 08:59:28 -07:00
Lofty 0f87fd8ef6 changelog: update for abc changes 2026-03-30 15:24:07 +01:00
Miodrag Milanovic 417e871b06 Fix tests due to ABC improvements 2026-03-30 15:23:27 +01:00
Miodrag Milanovic 23cfeabfe1 Update ABC as per 2026-03-27 2026-03-30 15:23:27 +01:00
Miodrag Milanović 74fef31bf2
Merge pull request #5773 from rocallahan/num-active-workers
Prevent race on `num_active_worker_threads_`.
2026-03-27 19:23:30 +00:00
Miodrag Milanović 18bcd0b499
Merge pull request #5785 from YosysHQ/fix_ci_temp
CI: temporary disable macos for testing
2026-03-27 17:34:18 +00:00
Miodrag Milanovic d37b02af03 CI: temporary disable macos for testing 2026-03-27 17:46:14 +01:00
Miodrag Milanović ebfe5b2c06
Merge pull request #5774 from Silimate/atondapu/sim-cache-sigmap
sim: cache sigmap in register_output_step_values
2026-03-25 06:40:01 +00:00
tondapusili 5b22e64d19 sim: cache sigmap in register_output_step_values 2026-03-24 16:10:11 -07:00
Robert O'Callahan 290fb0556d Prevent race on `num_active_worker_threads_`.
The core issue here is that we need to ensure `num_active_worker_threads_`
is read before incrementing `done_workers`. See the comments
added in this PR to explain why, and why the resulting code is
race-free.
2026-03-24 22:20:18 +00:00
Miodrag Milanović 66306a8ca3
Merge pull request #5769 from Silimate/optimize_sim_pass
sim: early return from checkSignals in sim mode
2026-03-23 17:19:26 +00:00
Miodrag Milanović cc915b4c76
Merge pull request #5717 from zaun/latch-support
gowin: add hardware latch support (DL/DLN/DLC/DLP variants)
2026-03-23 16:51:30 +00:00
Emil J b44188110b
Merge pull request #5764 from YosysHQ/emil/constmap-error
constmap: error if no -cell set
2026-03-23 15:15:04 +00:00
Emil J 7b2ab9b245
Merge pull request #5763 from YosysHQ/emil/c-slow-init
genrtlil: fast memory initialization
2026-03-23 10:21:21 +00:00
tondapusili 69219e6be0 sim: early-return from checkSignals in sim mode 2026-03-20 12:32:49 -07:00
Emil J. Tywoniak 12b443e71c dfflibmap: consistent clk2fflogic usage in test 2026-03-19 19:48:25 +01:00
Emil J. Tywoniak 0e7f7c826d simcells: $dffsr and derivatives undefine S&R in logic tables 2026-03-19 19:27:30 +01:00
Miodrag Milanović 5fd39ff3e1
Merge pull request #5766 from YosysHQ/upgrade_ci
Upgrade CI actions
2026-03-19 18:06:50 +00:00
Emil J dc77140275
Merge pull request #5731 from YosysHQ/nella/wall-clock
Implement wall clock time measurement
2026-03-19 16:21:26 +00:00
nella ee0461eb00 Change time log format. 2026-03-19 14:38:22 +01:00
nella d6ab610622 Implement wall clock time meas. 2026-03-19 14:38:22 +01:00
Miodrag Milanovic 2a8024ea4a Upgrade CI actions 2026-03-19 12:22:57 +01:00
Lofty f560cba952
Merge pull request #5757 from YosysHQ/lofty/abc9-refactor-3
abc9: remove -fast [sc-269]
2026-03-19 08:41:45 +00:00
Lofty 27210627e5 abc9: remove -fast 2026-03-19 07:30:23 +00:00
Lofty 8d1d5a25e5
Merge pull request #5760 from YosysHQ/lofty/abc-refactor-2
abc: remove -S [sc-269]
2026-03-19 07:26:54 +00:00
Lofty 05de1c4ae2
Merge pull request #5759 from YosysHQ/lofty/abc9-refactor-4
abc9: remove abc9.if.C [sc-269]
2026-03-19 07:26:37 +00:00
Emil J. Tywoniak 4f4672d17b muxpack: fix wide Y port handling 2026-03-19 00:12:49 +01:00
Emil J. Tywoniak 7aaa0621d3 constmap: error if no -cell set 2026-03-19 00:01:14 +01:00
Emil J 9746bd3897
Merge pull request #5724 from abhinavputhran/fix/setundef-respect-selection
setundef: respect selection for cells, processes, and connections
2026-03-18 22:53:06 +00:00
Emil J. Tywoniak ad7a776d73 genrtlil: even faster removeSignalFromCaseTree 2026-03-18 23:33:35 +01:00
Emil J. Tywoniak 27737c6e2e rtlil: add remove2 unit test 2026-03-18 23:33:35 +01:00
Emil J. Tywoniak ea11453cef rtlil: faster remove2 2026-03-18 23:33:35 +01:00
Emil J. Tywoniak 23ce4b8560 genrtlil: faster removeSignalFromCaseTree 2026-03-18 23:33:35 +01:00
Miodrag Milanović a141bd941c
Merge pull request #5761 from YosysHQ/fix_ci
Check results properly
2026-03-18 20:08:04 +00:00
Miodrag Milanović 4a6bd6a2fe
Merge pull request #5762 from YosysHQ/revert-5758-lofty/abc-refactor-1
Revert "abc: remove -fast [sc-269]"
2026-03-18 17:57:53 +00:00
Lofty f9d930ba5a
Revert "abc: remove -fast [sc-269]" 2026-03-18 17:55:17 +00:00
Lofty c4cc53a72e synth: fix after abc -fast removal 2026-03-18 17:59:58 +01:00
Miodrag Milanovic bccfdef05d Check results properly 2026-03-18 17:48:28 +01:00
Lofty e05ed6b850
Merge pull request #5758 from YosysHQ/lofty/abc-refactor-1
abc: remove -fast [sc-269]
2026-03-18 15:09:36 +00:00
Lofty 18a7c54ebd
Merge pull request #5756 from YosysHQ/lofty/abc9-refactor-2
abc9: cleanup commented code [sc-269]
2026-03-18 14:46:06 +00:00
Lofty 0b3f103745 abc: remove -S 2026-03-18 14:40:23 +00:00
Lofty 93c762c7c1 abc9: remove abc9.if.C 2026-03-18 14:27:27 +00:00
Lofty 926814f1e4 abc9: cleanup commented code 2026-03-18 14:16:31 +00:00
Lofty 0ea739b7d9 abc: remove -fast 2026-03-18 14:15:42 +00:00
Lofty 150860c1c3
Merge pull request #5755 from YosysHQ/lofty/abc9-refactor-1
abc9_exe: fix typo
2026-03-18 12:25:44 +00:00
Lofty e78690fc47 abc9_exe: fix typo 2026-03-18 11:44:13 +00:00
Emil J c8f715fed8
Merge pull request #5664 from rocallahan/parallel-opt-clean
Parallelize `opt_clean` pass
2026-03-16 09:52:34 +00:00
Miodrag Milanović 06264cdb2e
Merge pull request #5746 from IAmMarcelJung/fabulous/add_frame_config_mux_bels
fabulous: add frame_config_mux BEls
2026-03-16 08:21:01 +00:00
KrystalDelusion 1111a401f7
Merge pull request #5750 from calewis/return_things
Fix missing return in NDEBUG case
2026-03-13 22:07:28 +00:00
Drew Lewis 4251cd69ed Fix missing return in NDEBUG case
Signed-off-by: Drew Lewis <cannada@google.com>
2026-03-13 19:51:49 +00:00
Marcel Jung 49ecb1ac11 fabulous: add frame_config_mux BEls 2026-03-12 16:05:21 +01:00
Lofty 4716f4410f
Merge pull request #5741 from YosysHQ/lofty/quicklogic-mul-bugfix
synth_quicklogic: fix small multiplier inference
2026-03-11 11:47:46 +00:00
Lofty 53939bd3ba synth_quicklogic: fix small multiplier inference 2026-03-11 11:14:09 +00:00
Catherine 18d94fe9a4
Merge pull request #5740 from kivikakk/push-utvloulmsuqy
cxxrtl: Suppress another un/signed comparison warning!
2026-03-11 10:27:27 +00:00
Asherah Connor 5c74446e57 cxxrtl: Suppress another un/signed comparison warning! 2026-03-11 20:50:09 +11:00
Catherine 4d725ee84d
Merge pull request #5739 from kivikakk/push-nsqznnrrssrn
cxxrtl: Suppress un/signed comparison warning; this is positive
2026-03-11 09:00:22 +00:00
Asherah Connor c5c104f560 cxxrtl: Suppress un/signed comparison warning; this is positive 2026-03-11 18:35:48 +11:00
Emil J. Tywoniak 498cb79abe async2sync: explain dffsr control signal variable polarity 2026-03-09 20:18:56 +01:00
Emil J. Tywoniak 43ef4d2901 fixup! async2sync: $dffsr has undef output on S&R 2026-03-09 20:12:24 +01:00
Miodrag Milanović de99d67bbd
Merge pull request #5733 from YosysHQ/update_abc
Update ABC as per 2026-03-09
2026-03-09 12:42:13 +00:00
Miodrag Milanovic fea0d18c0a Update ABC as per 2026-03-09 2026-03-09 13:04:45 +01:00
abhinavputhran 314d01b35f changed rtlil to verilog. setundef_selection_ff stays rtlil because we use specific cell names if write in verilog yosys assign name that can change 2026-03-08 20:14:03 -04:00
abhinavputhran 47c2257f82 setundef: more tests! and wire selection in -init mode 2026-03-08 19:41:31 -04:00
abhinavputhran c23ba3f917 I think CI runs within the tests directory based on error so I changed the file path 2026-03-08 18:15:35 -04:00
abhinavputhran 5048dac854 setundef: add tests for selection in -zero, -undriven, and -init modes. also made setundef.cc clearer 2026-03-06 18:12:03 -05:00
abhinavputhran 9e666c727f setundef: respect selection in -undriven mode 2026-03-06 10:37:59 -05:00
Emil J 2f1cdc2df9
Merge pull request #5728 from povik/tcl-set-result
Replace deprecated Tcl API to fix use-after-free
2026-03-06 13:36:48 +00:00
Emil J. Tywoniak 85013f9ed3 fixup! read_liberty: model clear_preset_variable correctly 2026-03-06 14:24:18 +01:00
Martin Povišer 167c6c4585 Replace deprecated Tcl API to fix use-after-free
Under Tcl 9.0 the Tcl_SetResult utility is a macro:

	#define Tcl_SetResult(interp, result, freeProc) \
		do { \
		    const char *__result = result; \
		    Tcl_FreeProc *__freeProc = freeProc; \
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(__result, -1)); \
		    if (__result != NULL && __freeProc != NULL && __freeProc != TCL_VOLATILE) { \
			if (__freeProc == TCL_DYNAMIC) { \
			    Tcl_Free((char *)__result); \
			} else { \
			    (*__freeProc)((char *)__result); \
			} \
		    } \
		} while(0)

Temporaries constructed as part of the 'result' expression will be
dropped before the 'result' pointer is used. What was safe when
Tcl_SetResult was a function isn't safe with the macro definition.
Transition away from deprecated SetResult to calling
SetObjResult/MewStringObj directly.
2026-03-06 11:52:17 +01:00
Lofty 050483a6b2
Merge pull request #5698 from YosysHQ/lofty/analogdevices
synth_analogdevices: synthesis for Analog Devices EFLX FPGAs [sc-273]
2026-03-06 08:57:59 +00:00
Miodrag Milanovic 602f3fd1a5 Add missing EOL 2026-03-06 09:10:55 +01:00
Miodrag Milanovic 52533b0d1c Update opt_lut_ins and stat for analogdevices and remove ecp5 2026-03-06 09:10:36 +01:00
Robert O'Callahan 9c51ba1b09 Reduce opt_clean parallelism 2026-03-06 02:20:16 +00:00
Robert O'Callahan 8d8c05b338 Fix `OptCleanPass` usage of `CleanRunContext` to avoid constructing extra `KeepCache` and `ParallelDispatchThreadPool` 2026-03-06 02:20:16 +00:00
Robert O'Callahan 32f5044eaf Clarify "Not passing module as function argument" comment
This correct in terms of intent, it's just not fully enforced due to const laundering.
2026-03-06 02:20:16 +00:00
Emil J. Tywoniak 70cc2d67fd opt_clean: refactor 2026-03-06 02:20:14 +00:00
Robert O'Callahan 1260fda83a Add 'init' attributes to RTLIL fuzzing 2026-03-06 02:20:08 +00:00
Robert O'Callahan cdfc586f18 Add unit tests for `ConcurrentWorkQueue` 2026-03-06 02:20:08 +00:00
Robert O'Callahan 1e96328ede Add some tests for `ShardedHashSet` 2026-03-06 02:20:08 +00:00
Robert O'Callahan 3910d569da Add unit tests for `ConcurrentQueue` and `ThreadPool` 2026-03-06 02:20:08 +00:00
Robert O'Callahan ac55935a68 Add unit-tests for `ParallelDispatchThread` and friends 2026-03-06 02:20:08 +00:00
Robert O'Callahan 3603cd52a0 Pass the module `Subpool` to `rmunused_module_signals` and parallelize that function 2026-03-06 02:20:08 +00:00
Robert O'Callahan 7f3b11e56b Add test that connects a wire with `init` to a constant 2026-03-06 02:20:08 +00:00
Robert O'Callahan 19a7c8fcf3 Pass the module `Subpool` to `rmunused_module_cells` and parallelize that function 2026-03-06 02:20:08 +00:00
Robert O'Callahan 8e044d1045 Pass the module `Subpool` to `rmunused_module_init` and parallelize that function 2026-03-06 02:20:06 +00:00
Robert O'Callahan a7437c636d Pass the toplevel thread pool to `rmunused_module`, create a `Subpool`, and parallelize `remove_temporary_cells` 2026-03-06 02:05:46 +00:00
Robert O'Callahan 887c32cb54 Create a toplevel `ParallelDispatchThreadPool` and parallelize `keep_cache_t::scan_module()` with it 2026-03-06 02:05:46 +00:00
Robert O'Callahan 72a21fe01d Introduce `RmStats` struct to encapsulate removal statistics
Turns out this is not strictly necessary for this PR but it's
still a good thing to do and makes it clearer that the stats
are not modified in a possibly racy way.
2026-03-06 02:05:43 +00:00
Robert O'Callahan c2bb7d6a82 Make `keep_cache_t` process all modules up-front instead of on-demand
We will want to query `keep_cache` from parallel threads. If we compute
the results on-demand, that means we need synchronization for cache
access in those queries, which adds complexity and overhead. Instead, prefill
the cache with the status of all relevant modules. Note that this doesn't
actually do more work --- we always consult `keep_cache` for all cells of
all selected modules, so scanning all those cells and determining the kept
status of all dependency modules is always required.

Later in this PR we're going to parallelize `scan_module` itself, and that's also
much easier to do when no other parallel threads are running.
2026-03-06 02:05:04 +00:00
Robert O'Callahan b42bb05b63 Parallelize `Design::check()` 2026-03-06 02:03:21 +00:00
Robert O'Callahan e2166c4684 Parallelize `collect_garbage()` 2026-03-06 02:03:21 +00:00
Robert O'Callahan 5ff7d344c9 Add `FfInitVals::set_parallel()` method
We'll use this later in the PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan fe329a0e14 Add `MonotonicFlag`
We'll use this later in the PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan e71da96314 Add `ConcurrentWorkQueue`
We'll use this later in the PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan ab238c3145 Add `ShardedHashSet`
We'll use this later in the PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan 87521df534 Add `ShardedVector`
We'll use this later in the PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan b079e5721c Add `ParallelDispatchThreadPool`
We'll use this later in the PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan 898a288a99 Add `work_pool_size`, `IntRange`, `item_range_for_worker`, and `ThreadIndex`
We'll use these later in this PR.
2026-03-06 02:03:21 +00:00
Robert O'Callahan 13d9fffdb9 Work around `std::reverse` miscompilation with empty range
This causes problems when compiling with fuzzing instrumenation enabled.
2026-03-06 02:03:21 +00:00
Robert O'Callahan bd7f2d9ba4 Make `log_error()` work in a `Multithreaded` context.
`log_error()` causes an exit so we don't have to try too hard here. The main
thing is to ensure that we normally are able to exit without causing a stack
overflow due to recursive asserts about not being in a `Multithreaded` context.
2026-03-06 02:03:21 +00:00
Robert O'Callahan 7af5dbae35 Add `IdString::unescape()` method
We've already talked about adding this as an alternative to `log_id()`, and we'll
need it later in this PR.
2026-03-06 02:03:21 +00:00
abhinavputhran 6cd66aed47 setundef: rename process loop variable and respect selection in -init mode 2026-03-05 17:51:01 -05:00
abhinavputhran df283fa1c9 setundef: use selected_processes() per review feedback 2026-03-05 11:22:00 -05:00
abhinavputhran 4e54853e35 setundef: use selected_processes() per review feedback 2026-03-05 11:16:07 -05:00
Justin Zaun d9737acc31 gowin: remove lib_whitebox from latch sim cells
Latches are sequential elements and don't need lib_whitebox.
2026-03-05 16:04:23 +01:00
Justin Zaun 9288889e20 gowin: add hardware latch support (DL/DLN/DLC/DLP variants)
Add simulation models, techmap, and dfflegalize rules for Gowin
DL-series latch primitives. Latches use the same physical BEL as
DFFs with REGMODE set to LATCH. All 12 variants are supported:
DL, DLE, DLN, DLNE, DLC, DLCE, DLNC, DLNCE, DLP, DLPE, DLNP, DLNPE.
2026-03-05 16:04:23 +01:00
Miodrag Milanović 95d738edc0
Merge pull request #5726 from YosysHQ/emil/double-expose-yosys_celltypes
celltypes: include newcelltypes to allow legacy code access to migrat…
2026-03-05 11:36:36 +00:00
Emil J 629bf3dffd
Merge pull request #5630 from apullin/array-assignment
ast: Add support for array-to-array assignment
2026-03-05 11:10:12 +00:00
Emil J. Tywoniak 23eb38fe3f celltypes: include newcelltypes to allow legacy code access to migrated yosys_celltypes 2026-03-05 11:59:20 +01:00
Lofty da83c93673 analogdevices: fix SHIFTX name 2026-03-05 05:37:13 +00:00
Lofty f3efa51b3e analogdevices: fix SHREG name 2026-03-05 05:37:13 +00:00
Lofty e2e8245be9 analogdevices: fix MUXF78 name 2026-03-05 05:37:13 +00:00
Lofty c747466a7a analogdevices: update missed T40LP timings 2026-03-05 05:37:13 +00:00
Lofty 91740645a9 analogdevices: update T40LP timings 2026-03-05 05:37:13 +00:00
Lofty 709746b184 analogdevices: update T16FFC timings 2026-03-05 05:37:13 +00:00
Lofty cd60dd4912 synth_analogdevices: update timing model and tests 2026-03-05 05:37:13 +00:00
Lofty 241db706e1 analogdevices: double LUT RAM cost 2026-03-05 05:37:13 +00:00
Lofty 3592d42d3b analogdevices: ignore $assert cells 2026-03-05 05:37:13 +00:00
Krystine Sherwin 5d3ed5a418 analogdevices: Extra tests
`mem_gen.py` based on quicklogic tests.
Remove BUFG from `lutram.ys`.
Extra `sync_ram_sp` models in `arch/common/blockram.v`.
Add analogdevices to main makefile tests.
Not all the other tests are passing, but that's fine for now.
2026-03-05 05:37:13 +00:00
Krystine Sherwin f06018306d analogdevices: Fixing up bram
Tested all the accepted configurations in eXpreso, disabling the RBRAM2 configs that fail to place, and increasing the cost for the double site TDP memories.
2026-03-05 05:37:13 +00:00
Krystine Sherwin 95ef0cd788 analogdevices: Add BRAM options
Enable `-force-params`, and tidy up lutram mapping too.
2026-03-05 05:37:13 +00:00
Lofty 8a09cc5463 analogdevices: LUT RAM only on positive edge 2026-03-05 05:37:13 +00:00
Lofty dea8c275ff analogdevices: DSP tweaks 2026-03-05 05:37:12 +00:00
Lofty 39cb61615f analogdevices: DSP inference 2026-03-05 05:37:12 +00:00
Lofty 891b89f60d analogdevices: remove cells_xtra 2026-03-05 05:37:12 +00:00
Lofty 4954fc980f analogdevices: timings for t40lp 2026-03-05 05:37:12 +00:00
Lofty 2c3876671b analogdevices: use single tech param 2026-03-05 05:37:12 +00:00
Lofty 0a2b6a4f21 analogdevices: expreso does not care about clock buffers 2026-03-05 05:37:12 +00:00
Lofty 6ee0bfa913 analogdevices: prepare for t40lp timings 2026-03-05 05:37:12 +00:00
Krystine Sherwin 9dcffc3dbf analogdevices: Adding RBRAM2 and -tech 2026-03-05 05:37:12 +00:00
Krystine Sherwin 99e26d80b0 analogdevices: (some) Native BRAM
Specifically, the SDP configurations for RBRAM (ignoring 2048x09 because it makes the memlib format unhappy).
Drop the unused defines from the synth pass.
Remove comments from the lutram files referencing xilinx.
2026-03-05 05:37:12 +00:00
Krystine Sherwin 9be3cfb3f9 analogdevices: Update lutram.ys test 2026-03-05 05:37:12 +00:00
Krystine Sherwin 376f746bc9 analogdevices: Native LUTRAM primitives 2026-03-05 05:37:12 +00:00
Lofty 30a03886a5 analogdevices: LUTRAM config 2026-03-05 05:37:12 +00:00
Lofty ae5325fe53 analogdevices: update timing model 2026-03-05 05:37:12 +00:00
Lofty c4bec4e8b8 I thought I removed this... 2026-03-05 05:37:12 +00:00
Lofty 85eb07d14d analogdevices: user retargeting 2026-03-05 05:37:12 +00:00
Lofty c9f6d7b2d4 analogdevices: more housekeeping 2026-03-05 05:37:12 +00:00
Lofty f659cbd159 analogdevices: remove some extra cells! 2026-03-05 05:37:12 +00:00
Lofty 6f205b41f5 test suite 2026-03-05 05:37:12 +00:00
Lofty 4f2f064262 synth_analogdevices: remove scopeinfo cells 2026-03-05 05:37:12 +00:00
Lofty d5ea7f7016 Create synth_analogdevices 2026-03-05 05:37:12 +00:00
Lofty 4caffa7ebd
Merge pull request #5725 from yrabbit/disable-wm-2
GOWIN. Disable read-before-write mode.
2026-03-05 05:36:28 +00:00
Andrew Pullin 6ac8c8cb05 ast: Add support for array-to-array assignment
This commit adds support for SystemVerilog array-to-array assignment
operations that were previously unsupported:

1. Direct array assignment: `b = a;`
2. Array ternary expressions: `out = sel ? a : b;`

Both single-dimensional and multi-dimensional unpacked arrays are
supported. The implementation expands these array operations during
AST simplification into element-wise assignments.

Example of now-supported syntax:
```systemverilog
wire [7:0] state_regs[8];
wire [7:0] r[8];
wire [7:0] sel[8];
assign sel = condition ? state_regs : r;
```

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-04 21:34:40 -08:00
YRabbit 26dc01102e GOWIN. Disable read-before-write mode.
According to the latest documentation from GOWIN -
"UG285-1.4E Gowin BSRAM & SSRAM User Guide"

The dual port BSRAM of all 55nm devices (including GW1N, GW2A and GW1A
series) does not support the read-before-write mode (WRITE_MODE = 2)

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
2026-03-05 09:17:37 +10:00
abhinavputhran 94c789e9c8 setundef: respect selection for cells, processes, and connections
Previously, setundef would rewrite sigspecs in all cells, processes,
and connections regardless of the active selection. Only modules and
memories were correctly filtered by selection.

Fix by using module->selected_cells() for cells, adding a
module->selected() check for processes, and checking wire selection
on the lhs of each connection before rewriting.

Fixes #5624
2026-03-04 17:48:35 -05:00
Emil J. Tywoniak 39343f5f33 docs: document S&R undefined for $dffsr and $dffsre 2026-03-04 19:39:41 +01:00
Emil J 0d7a875675
Merge pull request #5512 from YosysHQ/emil/turbo-celltypes
celltypes: compile-time lookup tables for internal cells
2026-03-04 14:47:57 +00:00
Emil J. Tywoniak 6485a13809 newcelltypes: mark header unstable 2026-03-04 15:17:26 +01:00
Miodrag Milanović 3bc26ff4d0
Merge pull request #5723 from YosysHQ/micko/merge_queue
CI: add support for merge queue
2026-03-04 13:18:09 +01:00
nella 16b1a914f1 Aiger use defines for known ops. 2026-03-04 12:39:45 +01:00
nella 04822c6660 Readd builtin_ff_cell_types for plugin parity. 2026-03-04 12:39:45 +01:00
nella b8ee0803ab Remove todo. 2026-03-04 12:39:45 +01:00
nella 66bd4716cf rtlil use newcelltypes. 2026-03-04 12:39:45 +01:00
nella cae54a4c7b Aiger use newcelltypes. 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak 6d4736269b newcelltypes: extend testing 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak 0284595e9c celltypes: fix absurd eval declarations 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak 793a3513c6 newcelltypes: use unordered_map 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak ae10e9e955 pyosys: disable test 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak 661fcb24cb newcelltypes: fix MSVC build 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak f594014bef newcelltypes: proper bounds for unit test 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak 12412d1fa5 register: use newcelltypes 2026-03-04 12:39:45 +01:00
Emil J. Tywoniak ecb8b20f62 yosys: use newcelltypes for yosys_celltypes users 2026-03-04 12:39:44 +01:00
Emil J. Tywoniak 5216d32d1b yosys: use newcelltypes for yosys_celltypes 2026-03-04 12:22:47 +01:00
Emil J. Tywoniak 7a5c303ccd backends: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak c3ed884bc4 drivertools: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 665b6eeb4a aiger2: add TODO 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 4ab22cbb97 abc: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak d91e1c8607 newcelltypes: test against builtin_ff_cell_types 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 31b86ebc2e newcelltypes: comment 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 8e17fb0266 consteval: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak a0f87dc2d1 modtools: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak a9463d1aee newcelltypes: fix non-cells 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak e3f9911e33 newcelltypes: refactor 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 07ec8708e4 share: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 3212dfaf1f newcelltypes: fix unit test 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 2d7d6ca10b newcelltypes: unit test 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 7e9e88c2ec newcelltypes: bounds check 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 9e59f05c25 newcelltypes: wrap design celltypes support 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 35ccaa60d7 newcelltypes: TurboCellTypes -> StaticCellTypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 6adc08b0e5 opt_expr: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak 3671d577a0 opt_clean: use newcelltypes 2026-03-04 12:22:14 +01:00
Emil J. Tywoniak a61455645d newcelltypes: init 2026-03-04 12:22:14 +01:00
Miodrag Milanovic cf4d4ff23d CI: add support for merge queue 2026-03-04 11:35:16 +01:00
Miodrag Milanović 05d1d56b9d
Merge pull request #5704 from apullin/apullin/abc9-no-loops-fix
abc9: preserve topological-loop asserts with targeted SCC fallback
2026-03-04 11:09:38 +01:00
Miodrag Milanović d3e297fcd4
Merge pull request #5722 from YosysHQ/release/v0.63
Yosys Release v0.63
2026-03-04 09:31:22 +01:00
Miodrag Milanovic 228052bfb3 Next dev cycle 2026-03-04 08:45:13 +01:00
Miodrag Milanovic 70a11c6bf0 Release version 0.63 2026-03-04 07:46:57 +01:00
Miodrag Milanovic b7d013e6bf Fix help message for equiv passes 2026-03-04 07:46:40 +01:00
Tianji Liu 750d536bba abc: new option to pass ABC read_lib args 2026-03-04 11:24:24 +08:00
Emil J. Tywoniak 126492742b read_liberty: fix for msvc 2026-03-03 17:34:58 +01:00
Emil J 04113eb95d
Merge pull request #5714 from likeamahoney/auto-proc-vars
support automatic lifetime qualifier on procedural variables
2026-03-03 17:31:37 +01:00
Emil J. Tywoniak 5b4603c54f dfflibmap: fix formal $dffsr tests with sat, prove "no s&r" assumption only needed when appropriate 2026-03-03 10:35:03 +01:00
Emil J. Tywoniak 22916aaab1 read_liberty: model clear_preset_variable correctly 2026-03-03 10:35:03 +01:00
Emil J. Tywoniak 024408004a dfflibmap: allow formal dffsr mapping tests with clk2fflogic 2026-03-03 10:34:29 +01:00
Emil J. Tywoniak 6f74c54c02 async2sync: $dffsr has undef output on S&R 2026-03-03 10:34:29 +01:00
Emil J. Tywoniak 857bc02710 liberty: warn if dffsr has clear&preset well defined 2026-03-03 10:34:29 +01:00
Emil J. Tywoniak 2dddc53ccf dfflibmap: test dffsr and dffsre from proc with equiv 2026-03-03 10:34:29 +01:00
Emil J. Tywoniak c13a623dbc dfflibmap: test dffsr with either priority liberty file 2026-03-03 10:34:29 +01:00
Emil J. Tywoniak ffb76a3486 dfflibmap: test dffsr mapping without assume 2026-03-03 10:34:29 +01:00
Emil J. Tywoniak a53104379d clk2fflogic: $dffsr has undef output on S&R 2026-03-03 10:34:29 +01:00
KrystalDelusion 1d3f9b7905
Merge pull request #5687 from YosysHQ/nella/pdr-doc
Update help text for rename -witness and write_aiger -ywmap
2026-03-02 09:29:25 +13:00
likeamahoney e9442194f2 support automatic lifetime qualifier on procedural variables 2026-02-27 20:42:52 +03:00
Miodrag Milanović 687a36af38
Merge pull request #5711 from YosysHQ/gowin_warning
gowin: remove spurious warning
2026-02-27 14:04:27 +01:00
Miodrag Milanovic 7f1f247c56 gowin: remove spurious warning 2026-02-27 13:12:32 +01:00
Miodrag Milanović 2dd71c3ba2
Merge pull request #5709 from YosysHQ/update_abc
Update ABC as per 2026-02-27
2026-02-27 08:32:34 +01:00
Miodrag Milanovic b3caec1a93 Update ABC as per 2026-02-27 2026-02-27 07:55:34 +01:00
Andrew Pullin 5970be33fb abc9: preserve topological-loop asserts with targeted SCC fallback
A real-world ABC9 flow hit residual combinational loops after SCC breaking, tripping the prep_xaiger loop assertion.

Keep the existing topological assertions in place (prep_xaiger and reintegrate still assert no_loops).

To handle residual non-box loops, add a targeted fallback in prep_xaiger: when loops remain after normal SCC breaking, insert additional $__ABC9_SCC_BREAKER cuts on non-box loop cells, rebuild toposort, and then re-check the existing assertion.

Also keep pre-ABC9 SCC tagging on all cell types (scc -all_cell_types) and add a regression test (tests/techmap/abc9-nonbox-loop-with-box.ys).
2026-02-26 22:30:32 -08:00
nella 2c52546e2a Fix docs. 2026-02-25 16:42:05 +01:00
Emil J 5f8489d36d
Merge pull request #5666 from YosysHQ/emil/equiv_induct-missing-model-errors
equiv_induct: error on missing model
2026-02-25 15:39:31 +01:00
Miodrag Milanović fd1ac58767
Merge pull request #5706 from YosysHQ/remove-flake-lock
Remove already disabled CI job
2026-02-25 11:15:33 +01:00
Miodrag Milanovic 31f7d0d92d Remove already disabled CI job 2026-02-25 10:36:46 +01:00
Miodrag Milanović 53d8eb43ff
Merge pull request #5702 from YosysHQ/verific_build_all
Check verific configurations
2026-02-23 09:41:59 +01:00
Miodrag Milanovic b51110a50b Build various Verific configurations 2026-02-23 09:01:55 +01:00
Krystine Sherwin fd311c5501 tests/arch/gowin: Add wr_en test 2026-02-22 09:00:37 +01:00
Krystine Sherwin 2386923b8f gowin: Fix bram ADA byte enables 2026-02-22 09:00:37 +01:00
Miodrag Milanović fb653c4181
Merge pull request #5700 from YosysHQ/wasi_speedup
CI: WASI - Applying YoWASP changes to script
2026-02-20 18:00:24 +01:00
Miodrag Milanovic 68e47ebcfe CI: WASI - Applying YoWASP changes to script 2026-02-20 15:23:45 +01:00
Miodrag Milanović 0ed7c5ad53
Merge pull request #5620 from YosysHQ/lofty/abc9-verify
abc9: verify post-mapping equivalence by default
2026-02-20 13:41:11 +01:00
Krystine Sherwin 094481739f memory_libmap: Add -force-params
Reduce complexity for adi brams by unconditionally providing the WIDTH and ABITS parameters.
2026-02-20 10:57:00 +00:00
Emil J 13795203a1
Merge pull request #5680 from YosysHQ/emi/aiger-add-bounds-checks
aigerparse: add some bounds checks
2026-02-20 11:53:49 +01:00
Emil J 74f7b0cf92
Merge pull request #5685 from chathhorn-galois/chathhorn/issue5684
Fix segfault from shift with 0-width signed arg.
2026-02-20 11:53:05 +01:00
Emil J 53509a9b2a
Merge pull request #5692 from YosysHQ/emil/modtools-fix-db-port-deletion
modtools: fix database sanity
2026-02-20 10:49:28 +01:00
Miodrag Milanović 679156d323
Merge pull request #5686 from YosysHQ/version_bump
Automatic version bump
2026-02-19 09:52:22 +01:00
Emil J. Tywoniak abc7563a35 modtools: add ModIndex unit test 2026-02-18 22:15:44 +01:00
Emil J. Tywoniak c75d80905a modtools: fix database sanity on wire name swap 2026-02-18 21:23:21 +01:00
Gus Smith 29a270c4b6
Merge pull request #5675 from rowanG077/add-missing-celledges
kernel/celledges: cover more cell types
2026-02-18 07:50:41 -08:00
Miodrag Milanovic 5bb31485b7 Display repo and branch when applicable 2026-02-18 13:34:36 +01:00
Emil J. Tywoniak 62f19cb3a9 modtools: fix port_del db erase 2026-02-18 12:20:36 +01:00
Emil J 33a2de9635
Merge pull request #5681 from YosysHQ/emil/blifparse-bounds-check
blifparse: add bounds check
2026-02-18 12:18:05 +01:00
nella 01e89a8f9e Remove cell mentions. 2026-02-18 09:29:35 +01:00
nella 2b4f481850 Cleanup docs. 2026-02-18 09:24:41 +01:00
Emil J. Tywoniak 77f64de997 satgen: move report_missing_model here from equiv.h 2026-02-16 17:01:09 +01:00
Emil J. Tywoniak 81ea922512 sat: use the same cell import warnings as equiv 2026-02-16 16:54:26 +01:00
Miodrag Milanovic 63068f9b8f count relative to version tag, and ignore non existing 2026-02-16 16:44:33 +01:00
nella e6e57b33e3 document abc --keep-going pdr [sc-220]. 2026-02-15 09:00:04 +01:00
Miodrag Milanović ac96f318ef
Merge pull request #5676 from YosysHQ/emil/unit-test-by-default
Run unit tests on make test
2026-02-13 15:02:50 +01:00
Miodrag Milanovic 0090aa96b6 Remove version bump action 2026-02-13 14:22:33 +01:00
Miodrag Milanovic adf8b6b0d8 Add +post to version if from tarbal 2026-02-13 14:22:10 +01:00
Miodrag Milanovic c7d88ded94 Make version bump automatic 2026-02-13 14:21:41 +01:00
Chris Hathhorn 1e852cef16 Fix segfault from shift with 0-width signed arg.
Fixes #5684.
2026-02-12 22:03:42 -06:00
github-actions[bot] e2f0c4d9a0 Bump version 2026-02-13 00:35:27 +00:00
Miodrag Milanovic bb7aa7d208 Cleanup of yml files 2026-02-12 14:56:45 +01:00
Miodrag Milanović e4b32d6aae
Merge pull request #5670 from max-kudinov/gowin_mult
Gowin: Add DSP inference for GW1N and GW2A
2026-02-12 14:30:27 +01:00
Miodrag Milanovic e5b3e9fc1f This one should run only vanilla-tests 2026-02-12 14:08:49 +01:00
Miodrag Milanovic c6e48f4bea These are tests from other Makefile 2026-02-12 14:06:08 +01:00
Miodrag Milanovic cc79c6a761 Support building out of tree, but keep always in tests/unit 2026-02-12 12:17:07 +01:00
Maxim Kudinov b055ea05fd gowin: dsp: Add mult inference tests 2026-02-12 14:12:32 +03:00
Maxim Kudinov 5b94a97fb3 gowin: synth_gowin: Add -nodsp option 2026-02-12 13:58:47 +03:00
Maxim Kudinov 542b29fa6a gowin: synth_gowin: Merge flatten label with coarse 2026-02-12 13:58:47 +03:00
Maxim Kudinov 5ea073d45e gowin: format MULT instances 2026-02-12 13:35:49 +03:00
Miodrag Milanović 9b9e7b5ae3
Merge pull request #3389 from uwsampl/support-parameter-default-values-in-json-frontend-and-verilog-backend
Support parameter default values in JSON frontend and Verilog backend
2026-02-12 10:17:56 +01:00
Miodrag Milanović ce5321da8c
Merge pull request #5682 from YosysHQ/update_abc
Update ABC as per 2026-02-11
2026-02-12 08:05:23 +01:00
github-actions[bot] 1319112913 Bump version 2026-02-12 00:32:36 +00:00
Gus Smith 7a0774c3bb Don't dump params by default 2026-02-11 08:33:39 -08:00
Emil J b890b1b43f
Merge pull request #5678 from YosysHQ/emil/remove-dockerfile
Dockerfile: remove
2026-02-11 17:32:21 +01:00
Miodrag Milanovic a13b5c4211 Update ABC as per 2026-02-11 2026-02-11 17:30:08 +01:00
Gus Smith be9c857e72 Fix ABC after merge 2026-02-11 08:12:38 -08:00
Gus Smith b0021e5b10 Add tests 2026-02-11 08:10:57 -08:00
Gus Smith 1ede98797f Update backends/verilog/verilog_backend.cc
Co-authored-by: Marcelina Kościelnicka <236399+mwkmwkmwk@users.noreply.github.com>
2026-02-11 08:10:57 -08:00
Gus Smith 9ad7aed4a5 Update backends/verilog/verilog_backend.cc
Co-authored-by: Marcelina Kościelnicka <236399+mwkmwkmwk@users.noreply.github.com>
2026-02-11 08:10:57 -08:00
Gus Smith 12ace45b89 Support param. default values in JSON FE and SV BE 2026-02-11 08:10:55 -08:00
Gus Smith e3db8fee6f
Merge pull request #3459 from gs-jgj/feature_dsp48e1_presub
Add support for subtract in preadder
2026-02-11 08:02:18 -08:00
Gus Smith 8ab105ac28
Merge pull request #4303 from Coloquinte/sat_choice
Infrastructure to run a Sat solver as a command
2026-02-11 06:54:53 -08:00
Lofty 2e03ee1434 aigerparse: sanity-check AIGER header 2026-02-11 11:46:17 +00:00
Emil J fba29ea8f1
Merge pull request #5679 from YosysHQ/emil/abc9-remove-liberty
abc9: remove -liberty
2026-02-11 12:36:29 +01:00
Emil J. Tywoniak 43a15113ff aigerparse: add some bounds checks 2026-02-11 12:35:16 +01:00
Emil J. Tywoniak 3f1fbfdaee blifparse: add bounds check 2026-02-11 12:16:02 +01:00
Emil J. Tywoniak 915912cc76 abc9: remove -dont_use 2026-02-11 11:39:09 +01:00
Emil J. Tywoniak c4094e457b abc9: remove -genlib, -constr 2026-02-11 11:34:54 +01:00
Emil J. Tywoniak fe613f29b9 .github: move gtest to build dependencies 2026-02-11 11:33:27 +01:00
Emil J. Tywoniak 5a46106a46 abc9: remove -liberty 2026-02-11 01:04:50 +01:00
Emil J. Tywoniak a6a07fb39c Dockerfile: remove 2026-02-11 00:59:12 +01:00
Emil J. Tywoniak 98c3f03497 docs: clarify vanilla test run-test.sh 2026-02-11 00:58:29 +01:00
Emil J. Tywoniak dfbef2fe24 .github: run unit tests in build jobs, not test jobs 2026-02-11 00:55:36 +01:00
Krystine Sherwin 9f30f0e7d6
test-build: Don't rebuild OBJS 2026-02-10 15:34:47 +13:00
Krystine Sherwin 030e495c8b
test-build: Build and cache libyosys.so 2026-02-10 15:05:17 +13:00
github-actions[bot] a6e33d9916 Bump version 2026-02-10 00:38:43 +00:00
Emil J d2f7d3cf63
Merge pull request #5665 from rocallahan/abc-tmp-path
Sanitize ABC global and per-run temporary directory names in logs
2026-02-09 23:26:57 +01:00
Emil J. Tywoniak ff9cd0eed7 Makefile: test target requires unit-test, add vanilla-test for old test target 2026-02-09 23:21:24 +01:00
Gus Smith b04948a8cd Simplify test 2026-02-09 09:38:45 -08:00
Gus Smith 6f6fa49d3c Typo 2026-02-09 09:05:56 -08:00
Rowan Goemans b8ee50d77f kernel/celledges: cover more cell types 2026-02-09 14:13:40 +01:00
Gus Smith 1502e23371 Set solver from scratchpad or command line 2026-02-06 19:26:32 -08:00
Gus Smith b2f9ac4fb5 Check for dimacs nullptr on file creation+fn call 2026-02-06 18:18:03 -08:00
Gus Smith 2bb352a861 Missing newline 2026-02-06 17:45:00 -08:00
Gus Smith f062a0c8d6 Typo 2026-02-06 17:26:08 -08:00
Robert O'Callahan 34f8582725
Sanitize ABC global and per-run temporary directory names in logs 2026-02-07 12:12:13 +13:00
Emil J 1717fa0180
Merge pull request #5663 from YosysHQ/emil/opt_expr-fix-pow-shift
opt_expr: fix const lhs of $pow to $shl
2026-02-05 13:09:01 +01:00
github-actions[bot] 0640a5904b Bump version 2026-02-05 00:33:25 +00:00
Emil J 8bbde80e02
Merge pull request #5631 from rocallahan/cleanup-compare-signals
Clean up `compare_signals()` in `opt_clean`
2026-02-04 17:45:05 +01:00
Emil J 2aa0e1d009
Merge pull request #5629 from rocallahan/remove-zero-wires
Avoid scanning entire module in `Module::remove()` if there are no wires to remove
2026-02-04 17:44:24 +01:00
Emil J 992e64342c
Merge pull request #5621 from rocallahan/remove-opt-sort
Remove `Design::sort()` calls from optimization passes
2026-02-04 16:55:56 +01:00
Miodrag Milanović 776b4d06a6
Merge pull request #5669 from YosysHQ/release/v0.62
Release version 0.62
2026-02-04 08:55:31 +01:00
Miodrag Milanovic ddfa34d743 Next dev cycle 2026-02-04 08:54:38 +01:00
Robert O'Callahan 7326bb7d66
Only reuse ABC processes if we're using yosys-abc and it was built with ENABLE_READLINE
(cherry picked from commit 5054fd17d7b70f2df97360bb0f0cc1c92a6ffe72)
2026-02-04 17:19:10 +13:00
Gus Smith 3f01d7a33a Add test 2026-02-03 14:41:08 -08:00
Emil J. Tywoniak 91b226b4d4 specify: fix test 2026-02-03 18:40:32 +01:00
Emil J. Tywoniak ed53ff2f49 equiv_simple, equiv_induct: fix config 2026-02-03 18:37:39 +01:00
Emil J. Tywoniak c768e55983 ice40: fix dsp_const test 2026-02-03 18:10:29 +01:00
Emil J. Tywoniak 2efd0247a1 opt_hier: fix test 2026-02-03 18:10:29 +01:00
Emil J. Tywoniak d199195785 satgen: cover $input_port 2026-02-03 18:10:29 +01:00
Emil J. Tywoniak 8d1c1faf82 equiv_simple, equiv_induct: error by default on missing model, add -ignore-unknown-cells 2026-02-03 18:10:29 +01:00
Emil J. Tywoniak 8e73e2a306 sat: add -ignore-unknown-cells instead of -ignore_unknown_cells for consistency 2026-02-03 18:10:29 +01:00
Emil J. Tywoniak 000be270ca equiv_simple, equiv_induct: refactor 2026-02-03 17:54:46 +01:00
Jeppe Johansen 44afd4bbdd Add support for subtraction in preadder 2026-02-03 08:31:01 -08:00
Miodrag Milanovic fc11754557 Release version 0.62 2026-02-03 12:09:24 +01:00
Emil J. Tywoniak 3bfeaee8ca opt_expr: fix const lhs of $pow to $shl 2026-02-03 11:59:00 +01:00
Miodrag Milanović 6dbe03f0f5
Merge pull request #5667 from Logikable/vhdl
Guard vhdl_file::UNDEFINED behind VERIFIC_VHDL_SUPPORT.
2026-02-03 07:59:52 +01:00
github-actions[bot] 153ddc0c84 Bump version 2026-02-03 00:33:37 +00:00
Sean Luchen 224549fb88 Guard vhdl_file::UNDEFINED behind VERIFIC_VHDL_SUPPORT.
Signed-off-by: Sean Luchen <seanluchen@google.com>
2026-02-02 15:26:03 -08:00
KrystalDelusion 414b1b6019
Merge pull request #5651 from rocallahan/abc-error-nonfatal
Handle ABC nonfatal "Error:" messages
2026-02-03 08:55:05 +13:00
Emil J 59653da599
Merge pull request #5609 from nataliakokoromyti/upstream-design-run-pass
Add Design::run_pass()
2026-02-02 19:30:18 +01:00
Miodrag Milanović f5c8368f7a
Merge pull request #5662 from YosysHQ/update_abc
Update ABC as per 2026-02-02
2026-02-02 13:44:56 +01:00
Miodrag Milanovic b88d6588bc Update ABC as per 2026-02-02 2026-02-02 11:25:57 +01:00
Miodrag Milanović ac427a79b0
Merge pull request #5644 from nataliakokoromyti/upstream-linux-perf-unistd
Add unistd header for Linux
2026-01-30 08:17:43 +01:00
Miodrag Milanović 382b28acbe
Merge pull request #5648 from YosysHQ/verific_moreopts
verific: fixed -sv2017 option and added ability to set VHDL standard
2026-01-30 08:17:19 +01:00
Robert O'Callahan 9c56c93632 Add missing newlines to some 'log_error's 2026-01-30 01:52:19 +00:00
Robert O'Callahan 6af1b5b19c Don't treat ABC 'Error:' output as indicating a fatal error, since these messages aren't necessarily fatal 2026-01-30 01:52:19 +00:00
github-actions[bot] 106f289e31 Bump version 2026-01-30 00:30:58 +00:00
KrystalDelusion 5a4ad6a6d0
Merge pull request #5640 from YosysHQ/krys/fix_mod.py
Don't use `module mod_name(...)` style in cell libs
2026-01-30 11:40:07 +13:00
Emil J a68fee1115
Merge pull request #5646 from rocallahan/debug-design_equal
Dump module details when `design_equal` fails
2026-01-29 18:57:24 +01:00
Natalia 61b1c3c75a use run_pass in ecp5 add/sub test 2026-01-29 02:42:23 -08:00
Natalia 7439d2489e add assertion to run_pass test 2026-01-29 02:23:07 -08:00
Miodrag Milanovic b70f527c67 verific: fixed -sv2017 option and added ability to set VHDL standard if applicable 2026-01-29 10:32:30 +01:00
Miodrag Milanović 6ba8f3dc19
Merge pull request #5647 from YosysHQ/update_abc
ABC update (MINGW fix)
2026-01-29 10:12:25 +01:00
Miodrag Milanović 43db5c9488
Merge pull request #5645 from nataliakokoromyti/upstream-verific-mixed-sv-vhdl
Upstream verific mixed sv vhdl
2026-01-29 10:12:09 +01:00
Miodrag Milanovic 6007b68e9c ABC update (MINGW fix) 2026-01-29 09:30:12 +01:00
Natalia 8d504ecb48 verific: use MFCU for SV file list 2026-01-29 00:03:28 -08:00
Natalia b6c148f84a tests/verific: ensure mixed -f requires VHDL unit 2026-01-28 22:46:10 -08:00
github-actions[bot] 1f6a13dac7 Bump version 2026-01-29 00:31:03 +00:00
Robert O'Callahan 139c38ecfa Dump module details when design_equal fails 2026-01-28 18:32:12 +00:00
nella 8f6c4d40e4
Merge pull request #5623 from YosysHQ/nella/opt-dff-rewrite
opt_dff restructure.
2026-01-28 14:41:40 +01:00
Natalia 5a64fe2d91 tests/verific: assert module count explicitly 2026-01-28 04:21:13 -08:00
Natalia 8c2ef89732 tests/verific: import mixed -f list with -all 2026-01-28 04:13:04 -08:00
Natalia 74c601db0f tests/verific: add mixed -f list case 2026-01-28 03:55:42 -08:00
Natalia 6a6e5f0f54 linux_perf: only include unistd on Linux 2026-01-28 03:44:33 -08:00
Natalia 188082551a verific: only use MFCU when VHDL present 2026-01-28 03:37:08 -08:00
Natalia fc2b7c317f linux_perf: include unistd for POSIX I/O 2026-01-28 03:14:20 -08:00
Emil J 75008b70e5
Merge pull request #5638 from YosysHQ/emil/linux_perf-fix-help
linux_perf: mark internal, fix help formatting
2026-01-28 11:06:08 +01:00
Miodrag Milanović 97366933b3
Merge pull request #5643 from YosysHQ/update_abc
Update ABC as per 2026-01-28
2026-01-28 10:21:08 +01:00
Miodrag Milanovic fdff3dac2b Update ABC as per 2026-01-28 2026-01-28 09:38:33 +01:00
Krystine Sherwin 8ed7ac04d8
linux_perf.cc: Fix overlength codeblock 2026-01-28 08:17:56 +13:00
Krystine Sherwin 4031310ebb
linux_perf.cc: Use formatted_help
Gets the codeblock formatting better.

Also fold the on|off into a single usage.
2026-01-28 08:10:31 +13:00
Krystine Sherwin aaebce7adc
log_help: Don't reformat codeblocks 2026-01-28 08:07:44 +13:00
Krystine Sherwin c3ffb48a6b
Add and use fix_mod.py 2026-01-28 07:45:58 +13:00
github-actions[bot] 33e4b1d97f Bump version 2026-01-27 00:28:42 +00:00
Gus Smith 09ceadfde7
Merge pull request #4269 from povik/icells_not_derived
Avoid `module_not_derived` on internal cells in techmap result
2026-01-26 14:48:40 -08:00
Emil J 5b10c7f3c6
Merge pull request #4928 from XutaxKamay/main
Add gatesi_mode to init gates under gates_mode in BLIF format
2026-01-26 23:30:11 +01:00
Emil J. Tywoniak ef3b2b0380 linux_perf: mark internal, fix help formatting 2026-01-26 22:59:20 +01:00
nella a3c9716f18 OptDff fix unit tests. 2026-01-26 22:35:25 +01:00
nella 9367090763 OptDff more accurate ctrl/pattern desc. 2026-01-26 22:19:36 +01:00
nella 5803461c24 opt_dff pattern extraction. 2026-01-26 22:10:10 +01:00
Emil J 29a9e42b64
Merge pull request #5628 from rocallahan/linux-perf-ctl
Add `linux_perf` command to turn Linux perf recording on and off.
2026-01-26 19:32:55 +01:00
nella 8576055dea Fix tests. 2026-01-26 18:41:41 +01:00
Emil J 673c8d1ae7
Merge pull request #5615 from rocallahan/remove-used-signals-updates
Don't update `used_signals` for retained wires in `rmunused_module_signals`.
2026-01-26 15:47:25 +01:00
nella a75e0b2e92 opt_dff minor cleanup, added tests for comp var. 2026-01-26 14:24:01 +01:00
Maxim Kudinov 808ec8c04b gowin: synth_gowin: Add MULT inference for GW1N and GW2A 2026-01-25 22:10:08 +03:00
nataliakokoromyti f3c87610f5 verific: allow mixed SV/VHDL in -f files 2026-01-24 23:46:45 -08:00
Robert O'Callahan 32e96605d4 Don't update `used_signals` for retained wires in `rmunused_module_signals`.
These updates should not be necessary. In fact, if they were necessary, this code
would be buggy, because the results would depend on the order in which wires are traversed:
If wire A is retained, which causes an update to `used_signals`, which then causes wire B
to be retained when it otherwise wouldn't be, then we would get different results depending
on whether A is visited before B.

These updates will also make it difficult to process these wires in parallel.
2026-01-24 03:41:18 +00:00
Robert O'Callahan 7d53d64a47 Make the call to `compare_signals()` easier to read.
The negation here is confusing. The intent of the code is "if `s1` is preferred
over `s2` as the canonical `SigBit` for this signal, make `s1` the canonical `SigBit`
in `assign_map`", so write the code that way instead of "if `s2` is not preferred
over `s1` ...".

This doesn't change any behavior now that `compare_signals()` is a total order,
i.e. `s1` is preferred over `s2`, `s2` is preferred over `s1`, or `s1` and `s2` are equal.
Now, when `s1` and `s2` are equal, we don't call `assign_map.add(s1)`, but that's
already a noop in that case.
2026-01-24 02:01:05 +00:00
Robert O'Callahan 2468b391bf Make `compare_signals` produce a total order.
Currently when `s1` and `s2` are different bits of the same wire,
it is possible for both `compare_signals(s1, s2)` and `compare_signals(s2, s1)` to
return false. This means the calling code will call `assign_map.add()` for
both `s1` and `s2`, which doesn't make much sense --- one of `s1` or `s2`
should be consistently preferred.

So fix that by preferring the `SigBit` with the smaller bit offset.
2026-01-24 02:00:33 +00:00
Emil J f5ea73eb97
Merge pull request #5557 from nataliakokoromyti/lut2mux-word
lut2mux: add -word option
2026-01-23 17:24:41 +01:00
nella 0e4282d442 Add more opt_dff documentation. 2026-01-23 09:17:14 +01:00
Robert O'Callahan 4f53612725 Add `linux_perf` command to turn Linux perf recording on and off.
This is extremely useful for profiling specific passes.
2026-01-23 01:44:57 +00:00
Robert O'Callahan dcd7742d52 Avoid scanning entire module if there are no wires to remove
It's pretty common for `opt_clean` to find no wires to remove. In that case,
there is no point scanning the entire design, which can be significantly
expensive for huge designs.
2026-01-23 01:38:20 +00:00
Robert O'Callahan e87bb65956 Move `Design::sort()` calls out of `opt` and `opt_clean` passes into the synth passes that need them. 2026-01-23 01:14:35 +00:00
KrystalDelusion 125609105d
Merge pull request #5593 from RCoeurjoly/RCoeurjoly/5574_fix
abc: handle ABC script errors instead of hanging
2026-01-23 07:16:48 +13:00
KrystalDelusion 98f848e503
Merge pull request #5546 from YosysHQ/krys/nested_packages
Document nesting packages as unsupported
2026-01-23 07:16:22 +13:00
github-actions[bot] a6fc695522 Bump version 2026-01-22 00:28:34 +00:00
Emil J 317a4d77c7
Merge pull request #5610 from nataliakokoromyti/upstream-debugon
Add debugon pass for persistent debug logging
2026-01-21 17:34:30 +01:00
Emil J 5e36503676
Merge pull request #5605 from nataliakokoromyti/opt_balance_tree
Add opt_balance_tree pass
2026-01-21 17:34:08 +01:00
nella f6eba53d1f Fix copyright header. 2026-01-21 14:52:19 +01:00
nella 2c12545cf3 opt_dff restructure. 2026-01-21 10:08:44 +01:00
Miodrag Milanović 2157f9b3fb
Merge pull request #5622 from rocallahan/spurious-copy
Avoid spurious copy in `IdStringCollector::trace_named()`
2026-01-21 08:30:07 +01:00
Robert O'Callahan 2c0448a81b Avoid spurious copy in `IdStringCollector::trace_named()` 2026-01-21 03:31:56 +00:00
github-actions[bot] 57ac113b7f Bump version 2026-01-21 00:27:51 +00:00
Gus Smith 9ed56ac72c Mimic pattern of how other tests build plugins
Seems like using --build isn't supported in CI
2026-01-20 10:44:47 -08:00
Gus Smith bd9dbea4ea Add -I 2026-01-20 10:07:44 -08:00
Gus Smith 0f6ef77775 Add test for ezCmdlineSAT 2026-01-20 09:28:00 -08:00
Gabriel Gouvine 979b673f20 ezsat: Fix handling of error codes 2026-01-20 07:54:50 -08:00
Gabriel Gouvine d2b6bd00b1 ezsat: Rename files and class for ezCmdlineSat 2026-01-20 07:54:50 -08:00
Gabriel Gouvine 6565bf3ebf ezsat: Fix build for emscripten/wasi 2026-01-20 07:54:50 -08:00
Gabriel Gouvine 12315c0d17 ezsat: Support for assumptions in Sat command 2026-01-20 07:54:49 -08:00
Gabriel Gouvine 9315f02c17 ezsat: New Sat class to call an external command 2026-01-20 07:54:49 -08:00
Miodrag Milanović bfd1401b32
Merge pull request #5612 from YosysHQ/sv2017
verific: add explicit System Verilog 2017 option
2026-01-20 14:44:46 +01:00
Lofty 5a9d73369a abc9: verify post-mapping equivalence by default 2026-01-20 09:58:35 +00:00
Miodrag Milanovic d0fa4781c6 verific: Fix -sv2017 message and formatting 2026-01-20 08:07:26 +01:00
Gus Smith 491276983e Add test 2026-01-19 18:34:55 -08:00
Martin Povišer 90673cb0a2 techmap: Use `-icells` mode of frontend instead of type fixup 2026-01-19 16:49:49 -08:00
Martin Povišer f67d4bcfa4 verilog: Do not set `module_not_derived` on internal cells 2026-01-19 16:48:13 -08:00
github-actions[bot] 49e5950791 Bump version 2026-01-20 00:26:10 +00:00
Krystine Sherwin 0f478a5952
tests/bug5574: Fix for non threaded abc 2026-01-20 05:56:14 +13:00
Miodrag Milanovic cc3038f468 verific: Fix -sv2017 message 2026-01-19 16:32:46 +01:00
Miodrag Milanović 2bde91b6ef
Merge pull request #5618 from YosysHQ/update_abc
Update ABC as per 2026-01-19
2026-01-19 15:45:02 +01:00
nella 67d10a41e8
Merge pull request #5617 from YosysHQ/emil/consteval-description
consteval: describe
2026-01-19 14:56:24 +01:00
Miodrag Milanovic 691983be14 Update ABC as per 2026-01-19 2026-01-19 12:08:24 +01:00
Emil J 7880f31acb
Merge pull request #5531 from YosysHQ/emil/shuffle-contributing-docs
docs: shuffle and expand contributing info
2026-01-19 12:02:49 +01:00
Emil J. Tywoniak c3f36afe7f opt_balance_tree: mark experimental 2026-01-19 12:01:25 +01:00
Emil J. Tywoniak befadf6d4d consteval: describe 2026-01-19 12:00:18 +01:00
Miodrag Milanović 9355fa5037
Merge pull request #5616 from rocallahan/fix-unused-var-warning
Fix warning about unused variable in `dffunmap`.
2026-01-19 08:24:48 +01:00
Robert O'Callahan 28c199fbbd Fix warning about unused variable in `dffunmap`. 2026-01-19 03:25:09 +00:00
KrystalDelusion 8da8d681d0
Merge pull request #5544 from YosysHQ/krys/sim_check_eval_err
Improve error handling in sim
2026-01-19 09:51:12 +13:00
Natalia b43c96b03d fix pyosys Design.run_pass binding to use Pass::call signature 2026-01-18 02:24:36 -08:00
Natalia cf511628b0 modify generator for pyosys/wrappers.cc instead of headers 2026-01-18 02:11:09 -08:00
Miodrag Milanovic d095d2c405 verific: add explicit System Verilog 2017 option 2026-01-16 07:56:53 +01:00
Natalia ed64df737b Add -on/-off modes to debug pass 2026-01-15 12:07:26 -08:00
Natalia d5e1647d11 fix tests with truncation issues 2026-01-14 18:03:30 -08:00
Natalia fb864e91ee Add Design::run_pass() API for programmatic pass execution
This commit adds a new run_pass() method to the RTLIL::Design class,
providing a convenient API for executing Yosys passes programmatically.

This is particularly useful for PyYosys users who want to run passes
on a design object without needing to manually construct Pass::call()
invocations. The method wraps Pass::call() with appropriate logging
to maintain consistency with command-line pass execution.

Example usage (from Python):
    design = ys.Design()
    # ... build or load design ...
    design.run_pass("hierarchy")
    design.run_pass("proc")
    design.run_pass("opt")

Changes:
- kernel/rtlil.h: Add run_pass() method declaration
- kernel/rtlil.cc: Implement run_pass() method
- tests/unit/kernel/test_design_run_pass.cc: Add unit tests
2026-01-14 17:35:45 -08:00
github-actions[bot] 967b47d984 Bump version 2026-01-15 00:24:54 +00:00
Natalia 305b6c81d7 Refine width check to allow Y_WIDTH >= natural width
Change from equality check to >= to allow cells where output
is wider than natural width (zero-extended). Only reject cells
with Y_WIDTH < natural width (truncated).

This fixes test failures while still preventing the truncation
issue identified in widlarizer's feedback.
2026-01-14 14:58:53 -08:00
Natalia 60ac3670cb Fix truncation issue in opt_balance_tree pass
Only allow rebalancing of cells with "natural" output widths (no truncation).
This prevents equivalence failures when moving operands between adders
with different intermediate truncation points.

For each operation type, the natural width is:
- Addition: max(A_WIDTH, B_WIDTH) + 1 (for carry bit)
- Multiplication: A_WIDTH + B_WIDTH
- Logic ops: max(A_WIDTH, B_WIDTH)

Fixes widlarizer's counterexample in YosysHQ/yosys#5605 where an 8-bit
intermediate wire was intentionally truncating adder results, and
rebalancing would change where that truncation occurred.
2026-01-14 13:14:56 -08:00
Emil J. Tywoniak ddf3c6c8b7 blif: add -gatesi test 2026-01-14 21:41:56 +01:00
kamay e0077b188d Add gatesi_mode in BLIF format 2026-01-14 21:41:56 +01:00
nella 763001885f
Merge pull request #5608 from YosysHQ/nella/rtlil-to-string
Add rtlil string getters
2026-01-14 19:00:47 +01:00
nella 210b733555 Add rtlil string getters 2026-01-14 15:37:18 +01:00
github-actions[bot] 4c1a18f01d Bump version 2026-01-14 06:40:44 +00:00
Natalia Kokoromyti 6aef8ea8ab Add missing <deque> include for MSVC compatibility 2026-01-13 15:31:46 -08:00
nataliakokoromyti 8a596f330a Update lut2mux.cc 2026-01-13 15:02:17 -08:00
nataliakokoromyti 40f9e235de
Update lut2mux.cc 2026-01-13 14:45:46 -08:00
nataliakokoromyti 6a93a94d9f
fix line 2026-01-13 14:44:51 -08:00
nataliakokoromyti c305c426eb
restore extra_args 2026-01-13 14:43:52 -08:00
Natalia Kokoromyti 8b6925c5b0 Add opt_balance_tree pass for timing optimization
This pass converts cascaded chains of arithmetic and logic cells ($add,
$mul, $and, $or, $xor) into balanced binary trees to improve timing
performance in hardware synthesis.

The optimization uses a breadth-first search approach to identify chains
of compatible cells, then recursively constructs balanced trees that
reduce the critical path depth.

Features:
- Supports arithmetic cells: $add, $mul
- Supports logic cells: $and, $or, $xor
- Command-line options: -arith (arithmetic only), -logic (logic only)
- Preserves signed/unsigned semantics
- Comprehensive test suite with 30 test cases

Original implementation by Akash Levy <akash@silimate.com> for Silimate.
Upstreamed from https://github.com/Silimate/yosys
2026-01-13 14:20:11 -08:00
Emil J 71feb2a2a1
Merge pull request #5604 from YosysHQ/emil/read_verilog-remove-log
read_verilog: remove log I left behind by accident
2026-01-13 17:48:30 +00:00
Emil J. Tywoniak 83c1364eeb read_verilog: remove log I left behind by accident 2026-01-13 18:47:23 +01:00
Emil J 8da113b7f0
Merge pull request #5502 from YosysHQ/emil/digit-separator
Use digit separators for large decimal integers
2026-01-13 17:42:24 +00:00
Emil J d9956b20f8
Merge pull request #5603 from YosysHQ/emil/makefile-no-ast-header
Makefile: no longer install ast.h and ast_binding.h
2026-01-13 17:18:40 +00:00
Emil J ff3c24fcdc
Merge pull request #5521 from YosysHQ/emil/merge-queues
.github: trigger everything that triggers on main or PRs on merge queue
2026-01-13 17:22:37 +01:00
Emil J 5ba0e9cae3
Merge pull request #4235 from ylm/genblk_wire
Add autowires in genblk/for expension
2026-01-13 16:40:22 +01:00
Emil J. Tywoniak 8e2038c419 Use digit separators for large decimal integers 2026-01-13 16:38:12 +01:00
Emil J. Tywoniak 21e6833010 Makefile: no longer install ast.h and ast_binding.h 2026-01-13 16:33:11 +01:00
Miodrag Milanović 8f00c1824f
Merge pull request #5602 from YosysHQ/year_update
Update year in banner and license
2026-01-13 15:30:42 +01:00
Miodrag Milanovic 0e6973037d Update year in banner and license 2026-01-13 14:23:51 +01:00
nella b332279baf
Merge pull request #5592 from YosysHQ/gus/5503-yw-load-error-msg
More helpful error messages when loading Yosys Witness files with `yosys-smtbmc`
2026-01-13 12:00:06 +01:00
Miodrag Milanović 77005b69a2
Merge pull request #5601 from YosysHQ/release/v0.61
Release version 0.61
2026-01-13 09:39:50 +01:00
Miodrag Milanovic b08e044994 Next dev cycle 2026-01-13 09:24:49 +01:00
Miodrag Milanovic 5ae48ee25f Release version 0.61 2026-01-13 08:35:02 +01:00
Miodrag Milanović 51b210c93c
Merge pull request #5600 from YosysHQ/fix_musllinux
musllinux fix so wheels build can work
2026-01-13 07:08:04 +01:00
github-actions[bot] 78cbc21b94 Bump version 2026-01-13 00:22:49 +00:00
Emil J. Tywoniak b8497217bc contributing: review process 2026-01-13 00:16:58 +01:00
Emil J cc25ccfcd7
Merge pull request #5559 from nataliakokoromyti/upstream-lut2bmux
add lut2bmux
2026-01-12 16:09:13 +01:00
Miodrag Milanovic b3b71df07c musllinux fix so wheels build can work 2026-01-12 15:38:45 +01:00
Miodrag Milanović 72690062a1
Merge pull request #5599 from YosysHQ/musllinux_fix
musllinux fix so wheels build can work
2026-01-12 14:00:00 +01:00
Emil J f193dd0a28
Merge pull request #5594 from rocallahan/sdc-workaround
Check for missing port in SDC code to work around compiler bug
2026-01-12 11:22:25 +01:00
Miodrag Milanovic 2b12b74121 musllinux fix so wheels build can work 2026-01-11 15:23:38 +01:00
Robert O'Callahan 37347aacb2 Check for missing port in SDC code
I am getting weird crashes on `main` in `tests/sdc/alu_sub.ys` which I traced to a null `Wire*`
in `SdcObjects::constrained_ports`. The null `Wire*` is being set in the `SdcObjects`
constructor. I don't understand what's going on here, so I added this check to detect the
missing wire early ... and that made the crash go away. Compiler bug maybe? I have
`Debian clang version 19.1.7 (3+build5)`, default build configuration.

Anyway this code seems fine to have.
2026-01-10 04:00:17 +00:00
github-actions[bot] 991e704899 Bump version 2026-01-09 00:26:46 +00:00
KrystalDelusion cc3d569ade
Merge pull request #5591 from YosysHQ/krys/clean_empty_switch
Improve handling of empty switches
2026-01-09 11:52:27 +13:00
Emil J c7b839ef5a
Merge pull request #5530 from rocallahan/parallel-opt-merge
Parallelize `opt_merge`
2026-01-08 10:43:44 +01:00
Robert O'Callahan 41a098172d Expect an error from the bug5574.ys test 2026-01-08 09:58:01 +01:00
Robert O'Callahan 8da919587d Parallelize `opt_merge`.
I'm not sure why but this is actually faster than existing `opt_merge` even with
YOSYS_MAX_THREADS=1, for the jpeg synthesis test. 16.0s before, 15.5s after for
end-to-end synthesis.
2026-01-08 04:21:39 +00:00
Roland Coeurjoly f1fc704c84 abc: handle ABC script errors instead of hanging 2026-01-07 23:46:33 +01:00
github-actions[bot] 35321cd292 Bump version 2026-01-07 00:25:36 +00:00
Krystine Sherwin 9a09758f56
Test empty switches 2026-01-07 13:21:33 +13:00
Gus Smith 4d237bdd92 Deliver more helpful error messages 2026-01-06 16:19:54 -08:00
Gus Smith 9f77465170 Add test 2026-01-06 16:19:04 -08:00
Krystine Sherwin c0e29ef57c
proc_clean: Removing an empty full_case is doing something 2026-01-07 13:10:32 +13:00
Krystine Sherwin fcb8695261
write_verilog: Skip empty switches 2026-01-07 13:09:49 +13:00
Emil J 0ab967b036
Merge pull request #5564 from rocallahan/pass-fuzz
Add support for fuzz-test comparison of two passes intended to give identical RTLIL results
2026-01-06 20:07:31 +01:00
Emil J 5c630a366d
Merge pull request #5555 from rocallahan/defer-redirects
Defer redirecting cell outputs when merging cells in `opt_merge` untill after we've done a full pass over the cells.
2026-01-06 18:48:16 +01:00
Robert O'Callahan 042ec1cf60 Defer redirecting cell outputs when merging cells in `opt_merge` until after we've done a full pass over the cells.
This avoids changing `assign_map` and `initvals`, which are inputs to the hash function for `known_cells`,
while `known_cells` exists. Changing the hash function for a hashtable while it exists leads to
confusing behavior. That also means the exact behavior of `opt_merge` cannot be reproduced by a
parallel implementation.
2026-01-06 16:21:48 +00:00
Emil J 2e1a2cfacb
Merge pull request #5561 from YosysHQ/emil/opt_expr-test-avoid-multiple-drivers
opt_expr: avoid multiple drivers in test
2026-01-06 14:54:55 +01:00
Natalia 11b0e7ad92 add lut2bmux 2026-01-06 14:48:16 +01:00
github-actions[bot] 1567526954 Bump version 2026-01-06 00:26:49 +00:00
Miodrag Milanović 1ccbd21ed8
Merge pull request #5587 from YosysHQ/update_abc
Update ABC as per 2026-01-05
2026-01-05 18:00:36 +01:00
Miodrag Milanovic 6e5a516051 Update ABC as per 2026-01-05 2026-01-05 16:34:45 +01:00
Miodrag Milanović eae00c19a8
Merge pull request #5579 from yrabbit/gw5-bsram-be-w
Gowin. Implement byte enable.
2026-01-05 11:10:03 +01:00
YRabbit 8a78f2f7c5 Gowin. Fix style.
Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
2026-01-05 20:07:31 +10:00
Miodrag Milanović ab4381fba4
Merge pull request #5576 from rocallahan/idstring-pod
Give `IdString` a default move constructor and make it a POD type.
2026-01-05 11:05:56 +01:00
YRabbit ea90f54783 Gowin. Implement byte enable.
Enable write port with byte enables for BSRAM primitives.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
2026-01-03 17:42:49 +10:00
github-actions[bot] 8101c87fab Bump version 2025-12-31 00:27:01 +00:00
Robert O'Callahan a6d696ba2b Give `IdString` a default move constructor and make it a POD type.
Now that we're not refcounting `IdString`, it can use the default move constructor.
This lets us make `IdString` a POD type so it can be passed in registers
in the standard C++ ABI.
2025-12-30 22:35:14 +00:00
Miodrag Milanović 582969b236
Merge pull request #5575 from YosysHQ/update_abc
Update ABC as per 2025-12-29
2025-12-30 10:00:49 +01:00
Miodrag Milanovic 55af32024d Update ABC as per 2025-12-29 2025-12-30 09:23:45 +01:00
github-actions[bot] 96549e5514 Bump version 2025-12-30 00:26:17 +00:00
Miodrag Milanović d523c88c3c
Merge pull request #5573 from rocallahan/increase-timeout
Increase test timeout to 10 seconds
2025-12-29 12:38:34 +01:00
Robert O'Callahan 99d7ab9c42 Increase test timeout to 10 seconds
On my machine, this test regularly times out when doing "make -j" (which defaults to 128).
The high degree of parallelism seems to slow down the spwaning of ABC processes.
2025-12-29 04:35:05 +00:00
github-actions[bot] 17ca71e1ab Bump version 2025-12-24 00:26:02 +00:00
Miodrag Milanović aa9991d3ee
Merge pull request #5571 from YosysHQ/micko/warning
remove unused variable
2025-12-23 16:32:10 +01:00
Miodrag Milanovic 4bc4e4eb41 remove unused variable 2025-12-23 15:47:35 +01:00
Natalia 721b504479 lut2mux: add -word option and test 2025-12-23 05:57:40 -08:00
Miodrag Milanović 09f9e0e8d1
Merge pull request #5568 from rocallahan/abc-spawn-errno
Print `errno` to help diagnose failure to spawn ABC
2025-12-23 08:09:14 +01:00
github-actions[bot] 31f355c599 Bump version 2025-12-23 00:26:12 +00:00
Robert O'Callahan 0e61f57458 Print errno to help diagnose failure to spawn ABC 2025-12-22 21:58:15 +00:00
Robert O'Callahan 9ee51c8f27 Add AFL++ Grammar-Generator grammar for RTLIL fuzzing, and instructions for how to use it. 2025-12-22 21:56:26 +00:00
N. Engelhardt d5b38af4a7
Merge pull request #5550 from YosysHQ/nak/dont_merge_properties 2025-12-22 16:54:43 +01:00
Miodrag Milanović 650c18a2a2
Merge pull request #5565 from rocallahan/idstring-by-value
Pass `IdString` by value instead of by const reference
2025-12-22 14:51:30 +01:00
Miodrag Milanović 580b57c772
Merge pull request #5566 from YosysHQ/update_abc
Update ABC as per 2025-12-22
2025-12-22 13:19:28 +01:00
Miodrag Milanovic 13030e43d4 Update ABC as per 2025-12-22 2025-12-22 12:31:58 +01:00
Robert O'Callahan 48cdb499f2 Remove `IdString::id_string()`.
This was needed for the short time when `ID()` could return a value of `StaticIdString`.
That is no longer a problem.
2025-12-22 01:57:30 +00:00
Robert O'Callahan 46cb05c471 Pass IdString by value instead of by const reference.
When IdString refcounting was expensive, it made sense to pass it by const reference
instead of by value, to avoid refcount churn. Now that IdString is not refcounted,
it's slightly more efficient to pass it by value.
2025-12-22 01:52:59 +00:00
Robert O'Callahan ddd6a16ee0 Add -legalize option to read_rtlil 2025-12-21 21:47:48 +00:00
Robert O'Callahan 914e14946d Implement design_equal command 2025-12-21 21:47:40 +00:00
Emil J. Tywoniak 856d455065 opt_expr: avoid multiple drivers issue #4792 in combined assign tests 2025-12-19 18:32:56 +01:00
Emil J. Tywoniak 772d821fb0 opt_expr: reindent test 2025-12-19 18:32:56 +01:00
github-actions[bot] 64a933d77b Bump version 2025-12-18 00:22:53 +00:00
N. Engelhardt 45d654e2d7 avoid merging formal properties 2025-12-17 20:25:24 +01:00
Miodrag Milanović 49feaa1146
Merge pull request #5549 from nataliakokoromyti/fix-ice40-wrapcarry-src-attr
ice40_wrapcarry: Fix abort when cells have src attributes
2025-12-17 12:15:20 +01:00
Miodrag Milanović d861a26e49
Merge pull request #5504 from nataliakokoromyti/verific-run-test-bugfix
Fix Verific run-test.sh
2025-12-17 11:08:44 +01:00
nataliakokoromyti e289e4c893
add ID::src to allowlist instead 2025-12-17 01:31:32 -08:00
nataliakokoromyti cf8be2bae7
Update ice40_wrapcarry.cc 2025-12-16 09:33:47 -08:00
nataliakokoromyti 2ded4bd893
Update run-test.sh
fix: preserve newline at eof
2025-12-16 04:16:03 -08:00
Miodrag Milanović 07c9d575fd
Merge pull request #5543 from YosysHQ/krys/check_iverilog
Tests: Don't mention iverilog if the error wasn't from iverilog
2025-12-16 07:59:48 +01:00
Miodrag Milanović b201bf2cf3
Merge pull request #5542 from YosysHQ/krys/posix_spawnp
Calling `abc` fails when `ABCEXTERNAL` relies on path expansion
2025-12-16 07:44:27 +01:00
github-actions[bot] 4d61ce63d3 Bump version 2025-12-16 00:26:36 +00:00
Miodrag Milanović bd514df0df
Merge pull request #5540 from donn/pyosys_fix_abcexternal
pyosys: fix install failure when ABCEXTERNAL is set
2025-12-15 08:19:39 +01:00
Krystine Sherwin 18a7d4c262
Document nesting packages as unsupported 2025-12-15 15:42:41 +13:00
Krystine Sherwin 5b317ee03c
sim.cc: Check eval err
Some cells (e.g. $macc_v2) are marked evaluable, but will raise an abort if called with `CellTypes::eval()`.
Instead of falling through to the abort, we can pass a pointer to a boolean to check for errors.
Use said check to catch `CellTypes::eval()` errors and treat them as unevaluable but otherwise continue.
Reflows the series of if checks into `if ... else if ... else` so that we can check for errors and set state in one place.
2025-12-15 12:08:07 +13:00
Krystine Sherwin c69be9d767
Missed an iverilog
Should now still report an iverilog issue if `iverilog` doesn't exist.
2025-12-15 10:31:17 +13:00
Krystine Sherwin 24f4902156
Don't mention iverilog if the error wasn't from iverilog 2025-12-15 10:17:19 +13:00
Krystine Sherwin 9d3d8bf502
Switch posix_spawn to posix_spawnp 2025-12-15 09:40:04 +13:00
Mohamed Gaber 52dc8c5eff
pyosys: fix install failure when ABCEXTERNAL is set
While pyosys technically supports an external abc in installation, the attempt to always copy yosys-abc regardless would cause `make install` to crash.

`__init__.py` already handles yosys-abc not existing, so this just skips the install.
2025-12-13 22:47:32 +02:00
github-actions[bot] 2833a44503 Bump version 2025-12-13 00:24:42 +00:00
Emil J f003eca615
Merge pull request #5526 from YosysHQ/emil/fix-cellaigs-function-arg-eval-order
cellaigs: fix function argument evaluation order
2025-12-12 10:00:09 +01:00
Krystine Sherwin 4da0c552dd
tests/aiger: Fix pipe hiding diff exit status 2025-12-12 11:26:24 +13:00
github-actions[bot] c1ec625f47 Bump version 2025-12-11 00:26:11 +00:00
Yannick Lamarre 9814f9dc4f Add autowires in genblk/for expension
Signed-off-by: Yannick Lamarre <yan.lamarre@gmail.com>
2025-12-10 14:43:42 +01:00
Yannick Lamarre 54b278d574 Add tests for implicit wires in generate blocks.
Signed-off-by: Yannick Lamarre <yan.lamarre@gmail.com>
2025-12-10 14:43:42 +01:00
Emil J 5594b817cd
Merge pull request #5524 from rocallahan/single-thread-log
Check that we don't use logging during multithreading
2025-12-10 13:54:09 +01:00
Emil J e08e9119ee
Merge pull request #5516 from rocallahan/limit-threads
Limit thread usage in tests
2025-12-10 13:45:07 +01:00
Miodrag Milanović 8703e3b4dd
Merge pull request #5536 from YosysHQ/update_abc
Update ABC as per 2025-12-10
2025-12-10 13:13:33 +01:00
Emil J. Tywoniak 99e873efc9 cellaigs: fix AOI and OAI ordering 2025-12-10 12:41:13 +01:00
Emil J. Tywoniak d932ce7f47 cellaigs: formatting 2025-12-10 12:33:17 +01:00
Emil J. Tywoniak 882001cb01 cellaigs: fix adder function argument evaluation order 2025-12-10 12:33:17 +01:00
Emil J. Tywoniak 7f3ea41103 cellaigs: fix function argument evaluation order 2025-12-10 11:36:37 +01:00
Miodrag Milanovic 77f846e992 Update ABC as per 2025-12-10 2025-12-10 11:03:44 +01:00
github-actions[bot] 2e9db8b850 Bump version 2025-12-10 00:26:36 +00:00
Emil J 1cceaa2a80
Merge pull request #5538 from YosysHQ/emil/driver-git-hash
driver: add --git-hash
2025-12-09 15:00:36 +01:00
Miodrag Milanovic cf9ab4c899 Cleanup version.cc creation for VS build 2025-12-09 13:50:17 +01:00
Emil J 1af4f243af
Merge pull request #5535 from rocallahan/cleanup-prefix-strings
Delete prefix strings on shutdown to avoid triggering leak warnings.
2025-12-09 12:21:17 +01:00
Emil J. Tywoniak 6acb79afa2 driver: add --git-hash 2025-12-09 11:58:57 +01:00
Emil J. Tywoniak 23e1b0656c version: add git hash string 2025-12-09 11:58:43 +01:00
Emil J. Tywoniak 16a420afee contributing: clarify some things 2025-12-05 12:16:14 +01:00
Robert O'Callahan d274ff8627 Delete prefix strings on shutdown to avoid triggering leak warnings.
Fixes #5532
2025-12-05 09:45:47 +00:00
github-actions[bot] 0e31e389f2 Bump version 2025-12-05 00:25:44 +00:00
Emil J 685515865c
Merge pull request #5518 from rocallahan/remove-cover
Remove `cover()` coverage tracking
2025-12-04 18:50:15 +01:00
Emil J. Tywoniak 518610bbc4 contributing: split out git style 2025-12-04 17:26:51 +01:00
Emil J 46fbed6e6f
Merge pull request #5525 from YosysHQ/emil/fix-xaiger2-empty-cell-input
aiger2: fix empty cell input
2025-12-04 16:47:53 +01:00
Robert O'Callahan 638e904f91 Remove cover() coverage tracking 2025-12-04 16:27:13 +01:00
Robert O'Callahan 2ca28d964b Limit YOSYS_MAX_THREADS to 4 for abcopt-tests 2025-12-04 12:09:49 +01:00
Robert O'Callahan a871415abf Limit YOSYS_MAX_THREADS to 4 when running seed-tests 2025-12-04 12:09:48 +01:00
Robert O'Callahan fc951a28d3 Limit YOSYS_MAX_THREADS to 4 when running makefile-tests so we don't overload systems when running 'make -j... test' 2025-12-04 12:09:04 +01:00
Robert O'Callahan 7219ac94b3 Add YOSYS_MAX_THREADS 2025-12-04 12:09:04 +01:00
github-actions[bot] 52b1245547 Bump version 2025-12-04 00:25:21 +00:00
Emil J. Tywoniak 2843ea3008 contributing: fix rst 2025-12-03 13:10:20 +01:00
Emil J. Tywoniak e2dffbf991 contributing: move to docs, expand 2025-12-03 12:30:17 +01:00
Emil J. Tywoniak 9c9f4f347e README: mention docs can be read offline 2025-12-03 12:30:17 +01:00
Emil J. Tywoniak 6778151207 CONTRIBUTING: simplify CI description 2025-12-03 12:30:17 +01:00
Emil J. Tywoniak 436a247d60 Shuffle around information about bug reports and contributions 2025-12-03 12:30:17 +01:00
Miodrag Milanovic 58c7dc7cc2 Next dev cycle 2025-12-03 07:23:34 +01:00
Miodrag Milanovic 5bafeb77dc Release version 0.60 2025-12-03 07:19:42 +01:00
Gus Smith 07a690570e
Merge pull request #5128 from gussmith23/gussmith23-rosette-backend-updates
Add association-list-based helper functions into Rosette backend
2025-12-02 16:27:05 -08:00
Gus Smith dd65dd610d Fixes 2025-12-02 11:17:21 -08:00
Emil J. Tywoniak 36f0e0392f aiger2: add crash test 2025-12-02 15:30:02 +01:00
Krystine Sherwin b2e527c67e
tests/aiger: Only write aigmap.err on error 2025-12-02 14:17:16 +13:00
Krystine Sherwin 6842003e76
tests/aiger: Add gold .aag files
Generated with changes from 26f2c111
2025-12-02 14:03:37 +13:00
Krystine Sherwin e2e7922756
tests/aiger: Compare .aag outputs against known
Any files that differ (e.g. due to compiler order of operations changing) will trigger an error.
2025-12-02 14:03:36 +13:00
Krystine Sherwin 9ec361beab
test_cell.cc: Generate .aag for all compatible cells
Skips (with warning) on cells that didn't convert to avoid `write_aiger` from raising an error.
2025-12-02 14:03:36 +13:00
Emil J 9871e9b17e
Merge pull request #5496 from YosysHQ/emil/liberty-flop-loops
read_liberty: support loopy retention cells
2025-12-01 22:50:20 +01:00
Emil J. Tywoniak b2270ae1c8 aiger2: fix case where submodule cell input port has empty SigSpec 2025-12-01 19:40:58 +01:00
Emil J. Tywoniak cebb80250c aiger2: formatting 2025-12-01 19:40:17 +01:00
Gus Smith 38ee4fc730 Undo more unnecessary changes 2025-11-29 16:17:27 -08:00
Gus Smith 62e666c2ed Make run-test work from anywhere 2025-11-29 16:08:42 -08:00
Gus Smith fb8a1ad3bc Add back param 2025-11-29 16:07:18 -08:00
Gus Smith 0f8e1e3bf7 Undo more changes 2025-11-29 16:06:18 -08:00
Gus Smith 5f84b8b339 Undo some other changes 2025-11-29 15:32:19 -08:00
Gus Smith e223087578 Undo more changes that slipped in from somewhere? a merge maybe? 2025-11-29 15:28:34 -08:00
Gus Smith ade6379345 Explicitly store whether to use association lists
Instead of checking for the presence of helper names each time we need to
determine whether to use association lists, explicitly store a boolean flag
indicating whether association list helpers are being used.
2025-11-29 15:24:56 -08:00
Gus Smith ddcd93024f Capture error case more correctly 2025-11-29 15:20:37 -08:00
Gus Smith 5d5a7ab443 remove unused 2025-11-29 15:08:57 -08:00
Gus Smith 473edd19ed Undo formatting 2025-11-29 15:06:46 -08:00
Gus Smith 403740428c Remove unknown change 2025-11-29 15:01:17 -08:00
Gus Smith ded7c9cb03 More formatting undos' 2025-11-29 14:59:04 -08:00
Gus Smith 9909049d2a Undo formatting changes 2025-11-29 14:55:55 -08:00
Robert O'Callahan 7e75200b2a Check that we don't use logging during multithreading 2025-11-29 22:47:23 +00:00
Gus Smith d603b7bb58 Update ABC 2025-11-29 14:23:51 -08:00
Gus Smith 6fe35fa46c Merge remote-tracking branch 'origin/main' into gussmith23-rosette-backend-updates 2025-11-29 14:20:36 -08:00
KrystalDelusion 34fa8a4ff7
Merge pull request #3516 from dehekkendekrekker/subcircuit_fix
Fixes #3515
2025-11-29 12:51:15 +13:00
Emil J 9525f79d61
Merge pull request #5514 from rocallahan/idstring-safety
Make `IdString` thread-safe for read-only access
2025-11-28 23:58:33 +01:00
Emil J. Tywoniak 214d09a8c6 .github: everything that triggers on main or PRs should trigger on merge queue commit 2025-11-27 14:57:02 +01:00
github-actions[bot] e4044e1b4a Bump version 2025-11-27 00:24:24 +00:00
Miodrag Milanović c43246bba5
Merge pull request #5517 from povik/static
Add static library option
2025-11-26 16:11:37 +01:00
Martin Povišer c1e40e113c Use `$(AR)` 2025-11-26 13:02:44 +01:00
Martin Povišer 7cb3a0f830 Add static library option 2025-11-26 12:34:37 +01:00
github-actions[bot] 752d24c0a8 Bump version 2025-11-26 00:24:41 +00:00
Robert O'Callahan b23dc345ae Make it safe to access .c_str() for autoidx IDs in a multithreaded context 2025-11-25 22:49:41 +00:00
Robert O'Callahan 948001f39f Merge the two autoidx hashtables into one
When something calls `IdString::c_str()` on an autoidx ID, we need to cache the
full string in a thread-safe way. If we need to allocate an entry in some data
structure to do that, it's difficult to do in a thread-safe no-performance-hazard way.
So instead, store the cached string pointer in the same hashtable as the prefix
pointer.
2025-11-25 21:57:46 +00:00
Robert O'Callahan 8f0ecce53f Forbid creating IdStrings and incrementing autoidx during multithreaded phases, and add dynamic checks for that
We could make it safe to increment autoidx during multithreaded passes, but that's
actually undesirable because it would lead to nondeterminism. If/when we need new
IDs during parallel passes, we'll have to figure out how to allocate them in a
deterministic way, and that will depend on the details of what the pass does.
So don't try to tackle that now.
2025-11-25 21:57:46 +00:00
Robert O'Callahan 4c8b537d71 Remove YOSYS_NO_IDS_REFCNT
Refcounting is hardly used at all so this option is not that useful.

We might want to have a different option that disables GC if that becomes
a performance issue, but that should be a different option.
2025-11-25 21:57:46 +00:00
Robert O'Callahan 7f9de6e48f Make coverage data thread-safe 2025-11-25 21:46:48 +00:00
Miodrag Milanović 10fd97821e
Merge pull request #5511 from YosysHQ/update_abc
Update ABC as per 2025-11-24
2025-11-25 14:56:28 +01:00
Miodrag Milanovic cae020a581 Update ABC as per 2025-11-24 2025-11-25 11:29:48 +01:00
github-actions[bot] 5d3599a78c Bump version 2025-11-25 00:23:19 +00:00
Natalia d4e0437cfd Fix Verific run-test.mk setup 2025-11-24 15:56:28 -08:00
Krystine Sherwin a8e8746fc0
tests: Tidy up bug3515
Add base case where mapping is possible for sanity checking.
2025-11-25 07:35:19 +13:00
Krystine Sherwin ba31a02578
tests: Add bug3515 2025-11-25 07:04:34 +13:00
De hekkende krekker 38a1e66145
Fixes #3515 2025-11-25 06:58:14 +13:00
Emil J 510f9ef63d
Merge pull request #5499 from mikesinouye/abc_new
Enable abc_new pass when not in NDEBUG
2025-11-24 16:57:29 +01:00
Emil J. Tywoniak e8cbc92462 abc_new: sorted -> is_sorted 2025-11-24 11:46:09 +01:00
Emil J faa1e8fac4
Merge pull request #5500 from mikesinouye/xaiger2
Enable xaiger2 pass when not in NDEBUG
2025-11-24 11:44:36 +01:00
Miodrag Milanović 0d954f2f4c
Merge pull request #5498 from YosysHQ/krys/check_enable_abc
Check ENABLE_ABC validity
2025-11-24 08:09:45 +01:00
Miodrag Milanović d550757b4e
Merge pull request #5501 from rocallahan/tcl-size
Use `Tcl_Size` instead of `int` to fix build errors
2025-11-24 08:07:00 +01:00
Robert O'Callahan 53614a37a1 Use `Tcl_Size` instead of `int` to fix build errors
Fixes these build errors I'm getting locally with `tcl-devel-9.0.0-7.fc42.x86_64`.
I guess Tcl 9 broke this.

```
passes/cmds/sdc/sdc.cc:438:6: error: no matching function for call to 'Tcl_ListObjLength'
  438 |         if (Tcl_ListObjLength(interp, listObj, &listLength) == TCL_OK) {
      |             ^~~~~~~~~~~~~~~~~
/usr/include/tclDecls.h:1788:13: note: candidate function not viable: no known conversion from 'int *' to 'Tcl_Size *' (aka 'long *') for 3rd argument
 1788 | EXTERN int              Tcl_ListObjLength(Tcl_Interp *interp,
      |                         ^
 1789 |                                 Tcl_Obj *listPtr, Tcl_Size *lengthPtr);
      |                                                   ~~~~~~~~~~~~~~~~~~~
passes/cmds/sdc/sdc.cc:446:8: error: no matching function for call to 'Tcl_ListObjLength'
  446 |                         if (Tcl_ListObjLength(interp, subListObj, &subListLength) == TCL_OK) {
      |                             ^~~~~~~~~~~~~~~~~
/usr/include/tclDecls.h:1788:13: note: candidate function not viable: no known conversion from 'int *' to 'Tcl_Size *' (aka 'long *') for 3rd argument
 1788 | EXTERN int              Tcl_ListObjLength(Tcl_Interp *interp,
      |                         ^
 1789 |                                 Tcl_Obj *listPtr, Tcl_Size *lengthPtr);
      |                                                   ~~~~~~~~~~~~~~~~~~~
```
2025-11-24 18:46:56 +13:00
github-actions[bot] 33a49452d9 Bump version 2025-11-22 00:23:19 +00:00
Mike Inouye f098352ae6
Enable xaiger2 pass when not in NDEBUG 2025-11-21 14:23:32 -08:00
Mike Inouye 615e338acd
Fix abc_new pass when not in NDEBUG 2025-11-21 14:10:05 -08:00
KrystalDelusion 542723d121
Check ENABLE_ABC validity
From https://github.com/YosysHQ/yosys/pull/5497#issuecomment-3561398279, for ENABLE_ABC=1 to be valid, either ABC must be linked (LINK_ABC=1), or it must be possible to spawn executables (DISABLE_SPAWN=0).  This configuration (ENABLE_ABC=1 LINK_ABC=0 DISABLE_SPAWN=1) already fails compilation in `abc.cc` trying to call `run_command()` which doesn't exist if DISABLE_SPAWN=1.  All we are doing here is catching the known bad configuration and providing an explanation for why it isn't working.
2025-11-22 09:51:07 +13:00
KrystalDelusion bf70581efa
Merge pull request #5497 from YosysHQ/krys/abc_done
Fix ABC completion detection edge case
2025-11-22 09:37:50 +13:00
Krystine Sherwin 44ab884b06 bug5495.sh: Skip test if timeout isn't available 2025-11-21 04:03:39 +00:00
Robert O'Callahan e33ca17388 Force a newline to appear before YOSYS_ABC_DONE 2025-11-21 03:50:07 +00:00
Krystine Sherwin 4d1b688717
Tests: Add testcase for problematic ABC DONE check 2025-11-21 14:46:01 +13:00
Emil J. Tywoniak bfc957ee2d filterlib, read_liberty: add loopy retention cell formal equivalence test 2025-11-21 00:57:54 +01:00
Emil J. Tywoniak b3112bf025 filterlib: prefer using precedence over unsynthesizable verilog 2025-11-21 00:43:54 +01:00
Emil J. Tywoniak d5c1cd8fc0 read_liberty: support loopy retention cells 2025-11-20 13:21:32 +01:00
Emil J. Tywoniak 302643330c read_liberty: add cell context to more errors, remove log_id 2025-11-20 13:21:28 +01:00
Emil J 8ea51e1479
Merge pull request #5493 from YosysHQ/emil/sdc-fix-leak
sdc: use Tcl memory management functionality
2025-11-20 11:39:36 +01:00
github-actions[bot] 25ba41f424 Bump version 2025-11-20 00:24:25 +00:00
Emil J. Tywoniak 6eb9e823e0 sdc: use Tcl memory management functionality 2025-11-20 00:21:15 +01:00
Emil J b5625f9189
Merge pull request #5237 from YosysHQ/emil/sdc_expand
SDC expansion with OpenSTA
2025-11-19 23:27:33 +01:00
Miodrag Milanović e83d721cb0
Merge pull request #5492 from donn/getitem
pyosys: __getitem__ for supported classes
2025-11-19 17:58:01 +01:00
Mohamed Gaber 58e831486d
pyosys: __getitem__ for supported classes
- functions that have a const `[]` operator method now support `__getitem__` in Python
- fields of a pointer type now return a `reference_internal` instead of a `copy` because classes referenced to by pointers typically aren't copyable (e.g. RTLIL::Wire, RTLIL::Module, etc)
- removed duplicate of test_script.py
2025-11-19 18:09:41 +02:00
Emil J 2eff366e8c
Merge branch 'main' into emil/sdc_expand 2025-11-19 16:29:37 +01:00
Emil J 2cc0770305
Merge pull request #5412 from YosysHQ/emil/sdc-read-only
Add sdc command with smart flattening
2025-11-19 16:02:55 +01:00
Emil J. Tywoniak 1edc32dcd0 opensta, sdc_expand: mark as experimental 2025-11-19 15:31:17 +01:00
Emil J. Tywoniak 920f4793fb sdc: error on unknown getters 2025-11-19 15:26:02 +01:00
Emil J. Tywoniak 229123eb87 sdc: disable without YOSYS_ENABLE_TCL 2025-11-19 15:26:02 +01:00
Emil J. Tywoniak 033a2d5a67 sdc: remove vestigial code for tracked constraint followup work 2025-11-19 15:26:02 +01:00
Emil J. Tywoniak f56e121ddb sdc: add help 2025-11-19 15:26:02 +01:00
Emil J. Tywoniak 650392d4ec sdc: specialize stubs for the call graph 2025-11-19 15:26:02 +01:00
Emil J. Tywoniak 07de7509bf sdc: add -keep_hierarchy test 2025-11-19 15:26:02 +01:00
Emil J. Tywoniak 224ed524fa sdc: move to directory 2025-11-19 15:26:01 +01:00
Emil J. Tywoniak 94dd248dfb sdc: graph mode only 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 8a54e51300 sdc: add -keep_hierarchy 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak d4228efae8 sdc: keep_hiearchy 2025-11-19 15:25:24 +01:00
Emil Jiří Tywoniak 075237f73b sdc: refactor more 2025-11-19 15:25:24 +01:00
Emil Jiří Tywoniak 48ff9d4950 sdc: refactor find_matching 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak ae1235210d sdc: functional graph 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak c6491629d8 sdc: start graph 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 24a6412ea8 sdc: bit selections 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 21c68e0022 sdc: unknown handler experiment 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 420a083d9b sdc: simple mode, remove per-tool stubs 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 834125a076 sdc: return resolved patterns 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak dc48ceadd9 sdc: collect strictly matching objects 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 9a3c7f70ad sdc: stubs SDC commands supported by OpenSTA 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak c26aa3186d sdc: collect design objects 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak c1c6ec1266 sdc: stubs SDC commands supported by Vivado 2025-11-19 15:25:24 +01:00
Emil J. Tywoniak 5a798b64ef sdc: separate out 2025-11-19 15:25:22 +01:00
Emil Jiří Tywoniak c281bac461 sdc: add initial stubbed demo 2025-11-19 15:25:03 +01:00
Emil J. Tywoniak 85d2702ef6 opensta, sdc_expand: fix help 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 411fc149df opensta: refactor default command 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak a5b6c3cc19 opensta, sdc_expand: more scratchpad 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 9a5465bc83 icell_liberty: simplify 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 6846168db3 opensta: opensta.exe scratchpad variable 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 5acb77cab1 sdc_expand, opensta: typos 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak cee3d0b598 icell_liberty: refactor and add help 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 9f07e21e35 rtlil: undeprecate builtin_ff_cell_types 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 7bc88d5c40 sdc_expand: cleanup 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 793594bd59 sdc_expand: log header 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 7bed6ec658 opensta: quiet blackbox warning 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 0c4105d72c opensta: quiet net width mismatch warning 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak bbf1e4bca2 sdc_expand, opensta: start 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak e4e32d7966 icell_liberty: flop harder 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak c2c9506f4f icell_liberty: flops 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak 9e81db4373 ff: split out type-only information 2025-11-19 15:20:50 +01:00
Emil J. Tywoniak b3ead7e47d icell_liberty: start 2025-11-19 15:20:50 +01:00
github-actions[bot] 9aa2dde7ef Bump version 2025-11-18 00:24:34 +00:00
Emil J b8012086a3
Merge pull request #5485 from YosysHQ/emil/remove-cells-lib
techlibs: remove cells.lib
2025-11-17 14:57:31 +01:00
Miodrag Milanović cfa9c8bfc8
Merge pull request #5489 from rocallahan/fix-counter-reset
Fix `reset_auto_counter_id` to correctly detect `_NNN_` patterns
2025-11-17 14:26:57 +01:00
Miodrag Milanovic 58d4e2c38e ignore generated file 2025-11-17 13:35:38 +01:00
Miodrag Milanović 725a1c3a4b
Merge pull request #5488 from rocallahan/sigspec-at
Implement at() methods on SigSpec so that SigSpec::bits().at() continues to work as it did
2025-11-17 12:11:14 +01:00
Robert O'Callahan b870693393 Fix reset_auto_counter_id to correctly detect _NNN_ patterns
This fixes a regression caused by commit c4c389fdd7.
2025-11-17 09:21:59 +00:00
Robert O'Callahan 261a0ae9e1 Implement at() methods on SigSpec so that SigSpec::bits().at() continues to work as it did
Fixes a regression caused by commit 745222fa3b, which caused some
third-party code to fail to build, e.g.:
5d7aa035c6/lib/Transforms/YosysOptimizer/RTLILImporter.cpp (L229)
2025-11-17 09:15:55 +00:00
github-actions[bot] 677bf21947 Bump version 2025-11-15 00:23:54 +00:00
Emil J 84adc82fad
Merge pull request #5484 from YosysHQ/emil/idstring-simpler-final-gc
driver: move IdString collection to yosys_shutdown
2025-11-15 00:10:12 +01:00
Emil J. Tywoniak f47540b950 techlibs: remove cells.lib 2025-11-14 15:40:14 +01:00
Emil J. Tywoniak c497b3b24c Revert "rtlil: make tracing optional in IdString garbage collection"
This reverts commit 8c76f93fce.
2025-11-14 15:32:10 +01:00
Emil J. Tywoniak 65d7d70507 driver: move IdString collection to yosys_shutdown 2025-11-14 15:31:45 +01:00
Miodrag Milanović ba99c05902
Merge pull request #5482 from rocallahan/newid-namespace
Add missing `YOSYS_NAMESPACE_PREFIX` to fix callers of `NEW_ID` that aren't in the Yosys namespace
2025-11-14 14:06:15 +01:00
Miodrag Milanović 4bfdc62f65
Merge pull request #5472 from Anhijkt/arst-fsm-handling
fsm_detect: add adff detection
2025-11-14 13:47:08 +01:00
Anhijkt b08195a9cf typo 2025-11-14 13:34:58 +02:00
Anhijkt a75b999f13 fsm_detect: fix test 2025-11-14 13:25:51 +02:00
github-actions[bot] abc78f0424 Bump version 2025-11-14 00:25:00 +00:00
Miodrag Milanović b91dbc7324
Merge pull request #5481 from YosysHQ/micko/pyosys_ci
Build pyosys on CI
2025-11-13 21:06:05 +01:00
Miodrag Milanovic 40bbb84766 Enable pyosys install in out of tree builds 2025-11-13 16:17:53 +01:00
Miodrag Milanovic 10b49f3a91 Update generator to reflect IdString changes 2025-11-13 16:17:53 +01:00
Miodrag Milanovic 5e0bc3fd9f Build pyosys on CI 2025-11-13 16:17:53 +01:00
Emil J 1929956fd7
Merge pull request #5483 from YosysHQ/emil/idstring-memory-safety
Resolve IdString memory leaks
2025-11-13 16:14:38 +01:00
Emil J. Tywoniak f2263642a4 xilinx: fix IdString memory leak 2025-11-13 14:10:52 +01:00
Emil J. Tywoniak a915143768 ice40: fix IdString memory leak 2025-11-13 14:10:52 +01:00
Emil J. Tywoniak c48bc56f4a driver: fix timing data divison by zero when no passes run 2025-11-13 14:10:52 +01:00
Emil J. Tywoniak 1dd5b150e5 driver: garbage collect IdStrings without tracing at exit 2025-11-13 14:10:52 +01:00
Emil J. Tywoniak bc3fc21248 microchip: fix IdString memory leak 2025-11-13 14:10:52 +01:00
github-actions[bot] 04135ba3e4 Bump version 2025-11-13 00:24:44 +00:00
Robert O'Callahan ead0f922e1 Add missing YOSYS_NAMESPACE_PREFIX to fix callers of NEW_ID that aren't in the Yosys namespace 2025-11-12 22:29:54 +00:00
Emil J. Tywoniak 8c76f93fce rtlil: make tracing optional in IdString garbage collection 2025-11-12 20:22:30 +01:00
Emil J. Tywoniak 1ee4fc9d27 fix YOSYS_XTRACE_GET_PUT 2025-11-12 20:20:51 +01:00
Emil J. Tywoniak 50bfb5c5c9 constids: add $input_port and $connect 2025-11-12 20:19:42 +01:00
Emil J d93039a194
Merge pull request #5417 from rocallahan/idstring-gc
Implement garbage collection of `IdString`s
2025-11-12 13:43:53 +01:00
Emil J. Tywoniak ae281720cf tests: remove unstable FPGA synthesis result checks 2025-11-12 11:52:04 +01:00
Robert O'Callahan 578d658871 Add timing stats for IdString garbage collection 2025-11-12 11:52:04 +01:00
Robert O'Callahan 8c2984dc5f Fix AbcModuleState::remap_name() to avoid calling IdString::c_str() 2025-11-12 11:52:04 +01:00
Robert O'Callahan c4c389fdd7 Fix verilog backend to avoid IdString::c_str() 2025-11-12 11:52:04 +01:00
Robert O'Callahan 325b27f43a Avoid calling IdString::c_str() in opt_clean 2025-11-12 11:52:04 +01:00
Robert O'Callahan df8444c5e7 Optimize IdString operations to avoid calling c_str() 2025-11-12 11:52:04 +01:00
Robert O'Callahan e95ed7bbab Make NEW_ID create IDs whose string allocation is delayed 2025-11-12 11:52:04 +01:00
Robert O'Callahan 8895757364 Ensure that `new_id(_suffix)()` cannot create collisions with existing `IdString`s. 2025-11-12 11:52:04 +01:00
Robert O'Callahan 9577a028c8 Make new_id/new_id_suffix taking string_view to avoid allocating strings 2025-11-12 11:52:04 +01:00
Robert O'Callahan b3f3f42577 Remove StaticIdString and just use IdString now that we can make it constexpr 2025-11-12 11:52:04 +01:00
Robert O'Callahan b0e2d75dbe Make IdString refcounts a hashtable containing only the nonzero refcounts
This saves space and doesn't cost very much since we hardly ever have nonzero refcounts any more.

It also allows for IdStrings with negative indexes, which we're going to add.
2025-11-12 11:52:04 +01:00
Robert O'Callahan 54bde15329 Implement IdString garbage collection instead of refcounting. 2025-11-12 11:52:04 +01:00
Robert O'Callahan 5133b4bdea Create RTLIL::OwningIdString and use it in a few places 2025-11-12 11:52:04 +01:00
Robert O'Callahan d28f97e9da Remove YOSYS_USE_STICKY_IDS 2025-11-12 11:52:04 +01:00
Robert O'Callahan 0fe79ce01b Make RTLIL::Design::get_all_designs() unconditionally defined 2025-11-12 11:52:04 +01:00
Robert O'Callahan e84bc3c6c5 Remove explicit empty-string check when looking up IdStrings 2025-11-12 11:52:04 +01:00
Robert O'Callahan 20639906e3 Store IdString lengths and use them 2025-11-12 11:52:04 +01:00
Robert O'Callahan 32641bbf93 Make IdString::contains take std::string_view so we avoid a strlen when the parameter is a string constant 2025-11-12 11:52:04 +01:00
Robert O'Callahan 2319d82efb Make IdString::begins_width/ends_with take std::string_view so we avoid a strlen when the parameter is a string constant 2025-11-12 11:52:04 +01:00
github-actions[bot] 5f76729cbb Bump version 2025-11-12 00:24:49 +00:00
KrystalDelusion 529886f7fb
Merge pull request #5473 from YosysHQ/krys/unsized_params
Handle unsized params
2025-11-12 07:14:44 +13:00
Krystine Sherwin 7302bf9a66
Add CONST_FLAG_UNSIZED
In order to support unsized constants being used as parameters, the `const` struct needs to know if it is unsized (so that the parameter can be used to set the size).
Add unsized flag to param value serialization and rtlil back-/front-end.
Add cell params to `tests/rtlil/everything.v`.
2025-11-07 17:45:07 +13:00
Krystine Sherwin e4c5900acd
tests/verilog: Unsized params in cell
Non-zero case fails with `read_verilog`, but passes with `verific` and `read_slang`.
2025-11-07 17:13:12 +13:00
Krystine Sherwin a5cc905184
simplify.cc: Fix unsized const in params 2025-11-07 15:52:24 +13:00
Anhijkt 7d10a72490 fsm_detect: add adff detection 2025-11-06 23:29:47 +02:00
Krystine Sherwin dcf72ff8e2
Document tests/functional prereqs 2025-07-07 11:27:37 +12:00
Krystine Sherwin 108a4ed496
tests/functional: Reduce CI to 100 steps
Takes approx half the time, at least when testing locally.
2025-07-07 10:45:51 +12:00
Krystine Sherwin 3c54d8aef7
tests/functional: Auto parallelize
Use the unique cell name (cell type + parameters) for the vcd filename to avoid collisions when converting to fst.
2025-07-07 10:38:32 +12:00
Gus Smith a1d68fe3bc Add option for using assoc list helpers in tests 2025-06-26 17:44:12 -07:00
Gus Smith 8a9d724873 Finish up functions and tests, TODO: CLI 2025-06-23 19:20:06 -07:00
Gus Smith 51560b0bf6 Start adding Rosette simulation facilties 2025-05-26 21:47:59 -07:00
Gus Smith 9faa61dfc6 Remove gate on smt and rkt tests
as per
https://github.com/YosysHQ/yosys/pull/5128#issuecomment-2896280647
2025-05-26 20:43:32 -07:00
Gus Smith d8b27d41c0 Bugfix 2025-05-21 21:31:07 -07:00
Gus Smith 8ec9de00ec Use ir.inputs()/ir.outputs() 2025-05-20 17:45:23 -07:00
Gus Smith af51097af7 Convert to 'assoc list helpers' 2025-05-18 18:01:43 -07:00
Gus Smith a55dc80175 Rename parameter 2025-05-17 16:04:17 -07:00
Gus Smith c1111f125c Add output helper as well 2025-05-17 15:19:09 -07:00
Gus Smith 1fdfba2a1a Add helper for accessing by base name
The existing access function isn't useful if we don't have access to the original
names of the input/output/state signals. There may be a better way to do this, but
it might require restructuring the SmtrStruct.
2025-05-17 15:17:29 -07:00
Gus Smith 10b8fdddb4 Rename argument 2025-05-17 14:39:11 -07:00
Gus Smith 7b4c9c5dcd Add optional keyword-based constructor 2025-05-17 14:12:09 -07:00
Gus Smith fd5918c811 get_field_names for structs 2025-05-17 14:10:23 -07:00
762 changed files with 32048 additions and 8841 deletions

View File

@ -6,6 +6,8 @@ body:
attributes:
value: >
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/).

View File

@ -42,7 +42,7 @@ runs:
if: runner.os == 'Linux' && inputs.get-build-deps == 'true'
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
with:
packages: bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev
packages: bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libgtest-dev libgmock-dev
version: ${{ inputs.runs-on }}-buildys
- name: Linux docs dependencies
@ -52,15 +52,6 @@ runs:
packages: graphviz xdot
version: ${{ inputs.runs-on }}-docsys
# if updating test dependencies, make sure to update
# docs/source/yosys_internals/extending_yosys/test_suites.rst to match.
- name: Linux test dependencies
if: runner.os == 'Linux' && inputs.get-test-deps == 'true'
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
with:
packages: libgtest-dev
version: ${{ inputs.runs-on }}-testys
- name: Install macOS Dependencies
if: runner.os == 'macOS'
shell: bash

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true
persist-credentials: false
@ -23,7 +23,7 @@ jobs:
get-build-deps: true
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: cpp
queries: security-extended,security-and-quality
@ -32,4 +32,4 @@ jobs:
run: make yosys -j6
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4

View File

@ -1,22 +1,20 @@
name: Test extra build flows
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
merge_group:
#push:
# branches: [ main ]
workflow_dispatch:
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
steps:
- id: skip_check
if: ${{ github.event_name != 'merge_group' }}
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
@ -25,20 +23,28 @@ jobs:
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
vs-prep:
name: Prepare Visual Studio build
runs-on: ubuntu-latest
needs: [pre_job]
if: needs.pre_job.outputs.should_skip != 'true'
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true
persist-credentials: false
- run: sudo apt-get install libfl-dev
- name: Build
run: make vcxsrc YOSYS_VER=latest
- uses: actions/upload-artifact@v4
run: make vcxsrc YOSYS_COMPILER="Visual Studio" VCX_DIR_NAME=yosys-win32-vcxsrc-latest
- uses: actions/upload-artifact@v7
with:
name: vcxsrc
path: yosys-win32-vcxsrc-latest.zip
@ -47,9 +53,9 @@ jobs:
name: Visual Studio build
runs-on: windows-latest
needs: [vs-prep, pre_job]
if: needs.pre_job.outputs.should_skip != 'true'
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
name: vcxsrc
path: .
@ -64,17 +70,17 @@ jobs:
wasi-build:
name: WASI build
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true
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
@ -102,6 +108,7 @@ jobs:
ENABLE_ZLIB := 0
CXXFLAGS += -I$(pwd)/flex-prefix/include
LINKFLAGS += -Wl,-z,stack-size=8388608 -Wl,--stack-first -Wl,--strip-all
END
make -C build -f ../Makefile CXX=clang -j$(nproc)
@ -109,14 +116,14 @@ jobs:
nix-build:
name: "Build nix flake"
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true
persist-credentials: false
@ -124,3 +131,21 @@ jobs:
with:
install_url: https://releases.nixos.org/nix/nix-2.30.0/install
- run: nix build .?submodules=1 -L
extra-builds-result:
runs-on: ubuntu-latest
needs:
- vs-build
- wasi-build
- nix-build
if: always()
steps:
- name: Check results
run: |
echo "Needs results: ${{ join(needs.*.result, ',') }}"
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
echo "Some jobs failed or were cancelled"
exit 1
fi
- run: echo "All good"

View File

@ -1,12 +1,18 @@
name: Build docs artifact with Verific
on: [push, pull_request]
on:
pull_request:
merge_group:
push:
branches: [ main, "docs-preview/**", "docs-preview*" ]
tags: [ "*" ]
workflow_dispatch:
jobs:
check_docs_rebuild:
runs-on: ubuntu-latest
outputs:
skip_check: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
docs_export: ${{ steps.docs_var.outputs.docs_export }}
env:
docs_export: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/docs-preview') || startsWith(github.ref, 'refs/tags/') }}
@ -17,16 +23,26 @@ jobs:
paths_ignore: '["**/README.md"]'
# don't cancel in case we're updating docs
cancel_others: 'false'
# only run on push *or* pull_request, not both
concurrent_skipping: ${{ env.docs_export && 'never' || 'same_content_newer'}}
# push filtering means we only want to skip duplicates for PRs
do_not_skip: '["workflow_dispatch", "merge_group", "push"]'
concurrent_skipping: 'same_content_newer'
- id: docs_var
run: echo "docs_export=${docs_export}" >> $GITHUB_OUTPUT
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
prepare-docs:
# docs builds are needed for anything on main, any tagged versions, and any tag
# or branch starting with docs-preview
needs: check_docs_rebuild
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
@ -75,7 +91,7 @@ jobs:
make -C docs html -j$procs TARGETS= EXTRA_TARGETS=
- name: Trigger RTDs build
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' }}
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' && github.repository == 'YosysHQ/yosys' }}
uses: dfm/rtds-action@v1.1.0
with:
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}

View File

@ -1,13 +1,18 @@
name: Create source archive with vendored dependencies
on: [push, workflow_dispatch]
on:
pull_request:
merge_group:
push:
branches: [ main ]
workflow_dispatch:
jobs:
vendor-sources:
runs-on: ubuntu-latest
steps:
- name: Checkout repository with submodules
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: 'recursive'
persist-credentials: false
@ -27,7 +32,7 @@ jobs:
gzip yosys-src-vendored.tar
- name: Store tarball artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: vendored-sources
path: yosys-src-vendored.tar.gz

View File

@ -1,22 +1,20 @@
name: Build and run tests
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
merge_group:
#push:
# branches: [ main ]
workflow_dispatch:
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
steps:
- id: skip_check
if: ${{ github.event_name != 'merge_group' }}
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
@ -25,12 +23,21 @@ jobs:
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
pre_docs_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
steps:
- id: skip_check
if: ${{ github.event_name != 'merge_group' }}
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on readme changes
@ -39,6 +46,14 @@ jobs:
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
build-yosys:
name: Reusable build
runs-on: ${{ matrix.os }}
@ -53,7 +68,7 @@ jobs:
fail-fast: false
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true
persist-credentials: false
@ -71,6 +86,7 @@ jobs:
cd build
make -f ../Makefile config-$CC
make -f ../Makefile -j$procs
make -f ../Makefile unit-test -j$procs
- name: Log yosys-config output
run: |
@ -80,10 +96,10 @@ jobs:
shell: bash
run: |
cd build
tar -cvf ../build.tar share/ yosys yosys-*
tar -cvf ../build.tar share/ yosys yosys-* libyosys.so
- name: Store build artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: build-${{ matrix.os }}
path: build.tar
@ -102,7 +118,7 @@ jobs:
fail-fast: false
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
persist-credentials: false
@ -114,7 +130,7 @@ jobs:
get-iverilog: true
- name: Download build artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: build-${{ matrix.os }}
@ -130,7 +146,7 @@ jobs:
- name: Run tests
shell: bash
run: |
make -j$procs test TARGETS= EXTRA_TARGETS= CONFIG=$CC
make -j$procs vanilla-test TARGETS= EXTRA_TARGETS= CONFIG=$CC
- name: Report errors
if: ${{ failure() }}
@ -150,7 +166,7 @@ jobs:
os: [ubuntu-latest]
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
persist-credentials: false
@ -160,7 +176,7 @@ jobs:
runs-on: ${{ matrix.os }}
- name: Download build artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: build-${{ matrix.os }}
@ -190,7 +206,7 @@ jobs:
fail-fast: false
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
persist-credentials: false
@ -202,7 +218,7 @@ jobs:
get-docs-deps: true
- name: Download build artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: build-${{ matrix.os }}
@ -224,7 +240,7 @@ jobs:
name: Try build docs
runs-on: [self-hosted, linux, x64, fast]
needs: [pre_docs_job]
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
strategy:
matrix:
docs-target: [html, latexpdf]
@ -263,3 +279,22 @@ jobs:
name: docs-build-${{ matrix.docs-target }}
path: docs/build/
retention-days: 7
test-build-result:
runs-on: ubuntu-latest
needs:
- test-yosys
- test-cells
- test-docs
- test-docs-build
if: always()
steps:
- name: Check results
run: |
echo "Needs results: ${{ join(needs.*.result, ',') }}"
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
echo "Some jobs failed or were cancelled"
exit 1
fi
- run: echo "All good"

View File

@ -1,22 +1,20 @@
name: Compiler testing
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
merge_group:
#push:
# branches: [ main ]
workflow_dispatch:
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
steps:
- id: skip_check
if: ${{ github.event_name != 'merge_group' }}
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
@ -25,10 +23,18 @@ jobs:
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
test-compile:
runs-on: ${{ matrix.os }}
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
env:
CXXFLAGS: ${{ startsWith(matrix.compiler, 'gcc') && '-Wp,-D_GLIBCXX_ASSERTIONS' || ''}}
CC_SHORT: ${{ startsWith(matrix.compiler, 'gcc') && 'gcc' || 'clang' }}
@ -38,22 +44,22 @@ 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'
- 'clang-22'
- 'gcc-15'
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
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true
persist-credentials: false
@ -68,6 +74,7 @@ jobs:
uses: aminya/setup-cpp@v1
with:
compiler: ${{ matrix.compiler }}
gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14') && '12' || '' }}
- name: Tool versions
shell: bash
@ -75,17 +82,38 @@ jobs:
$CC --version
$CXX --version
# minimum standard
- name: Build C++17
shell: bash
- name: Fix clang-14 toolchain
if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14'
run: |
make config-$CC_SHORT
make -j$procs CXXSTD=c++17 compile-only
echo 'CXXFLAGS=--gcc-toolchain=/usr -isystem /usr/include/c++/12 -isystem /usr/include/x86_64-linux-gnu/c++/12' >> $GITHUB_ENV
# maximum standard, only on newest compilers
# minimum standard
- 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-22' || matrix.compiler == 'gcc-15' }}
shell: bash
run: |
make config-$CC_SHORT
make -j$procs CXXSTD=c++26 compile-only
test-compile-result:
runs-on: ubuntu-latest
needs:
- test-compile
if: always()
steps:
- name: Check results
run: |
echo "Needs results: ${{ join(needs.*.result, ',') }}"
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
echo "Some jobs failed or were cancelled"
exit 1
fi
- run: echo "All good"

View File

@ -1,31 +1,41 @@
name: Check clang sanitizers
on:
# always test main
push:
branches:
- main
# ignore PRs due to time needed
# allow triggering tests, ignores skip check
pull_request:
merge_group:
#push:
# branches: [ main ]
workflow_dispatch:
jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
steps:
- id: skip_check
if: ${{ github.event_name != 'merge_group' }}
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
# cancel previous builds if a new commit is pushed
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
run_san:
name: Build and run tests
runs-on: ${{ matrix.os }}
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
env:
CC: clang
ASAN_OPTIONS: halt_on_error=1
@ -37,7 +47,7 @@ jobs:
fail-fast: false
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true
persist-credentials: false
@ -64,7 +74,7 @@ jobs:
- name: Run tests
shell: bash
run: |
make -j$procs test TARGETS= EXTRA_TARGETS=
make -j$procs vanilla-test TARGETS= EXTRA_TARGETS=
- name: Report errors
if: ${{ failure() }}
@ -72,7 +82,18 @@ jobs:
run: |
find tests/**/*.err -print -exec cat {} \;
- name: Run unit tests
shell: bash
test-sanitizers-result:
runs-on: ubuntu-latest
needs:
- run_san
if: always()
steps:
- name: Check results
run: |
make -j$procs unit-test ENABLE_LIBYOSYS=1
echo "Needs results: ${{ join(needs.*.result, ',') }}"
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
echo "Some jobs failed or were cancelled"
exit 1
fi
- run: echo "All good"

109
.github/workflows/test-verific-cfg.yml vendored Normal file
View File

@ -0,0 +1,109 @@
name: Build various Verific configurations
on:
workflow_dispatch:
jobs:
test-verific-cfg:
if: github.repository_owner == 'YosysHQ'
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
with:
persist-credentials: false
submodules: true
- name: Runtime environment
run: |
echo "procs=$(nproc)" >> $GITHUB_ENV
- name: verific [SV]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs
- name: verific [VHDL]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs
- name: verific [SV + VHDL]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs
- name: verific [SV + HIER]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs
- name: verific [VHDL + HIER]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs
- name: verific [SV + VHDL + HIER]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 0" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs
- name: verific [SV + VHDL + HIER + EDIF + LIBERTY]
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_SYSTEMVERILOG := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_VHDL := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_HIER_TREE := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j$procs

View File

@ -1,22 +1,20 @@
name: Build and run tests with Verific (Linux)
on:
# always test main
push:
branches:
- main
# test PRs
pull_request:
# allow triggering tests, ignores skip check
merge_group:
#push:
# branches: [ main ]
workflow_dispatch:
jobs:
pre-job:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
should_skip: ${{ steps.set_output.outputs.should_skip }}
steps:
- id: skip_check
if: ${{ github.event_name != 'merge_group' }}
uses: fkirc/skip-duplicate-actions@v5
with:
# don't run on documentation changes
@ -25,9 +23,17 @@ jobs:
# but never cancel main
cancel_others: ${{ github.ref != 'refs/heads/main' }}
- id: set_output
run: |
if [ "${{ github.event_name }}" = "merge_group" ]; then
echo "should_skip=false" >> $GITHUB_OUTPUT
else
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
fi
test-verific:
needs: pre-job
if: ${{ needs.pre-job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
@ -38,10 +44,18 @@ jobs:
- name: Runtime environment
run: |
echo "procs=$(nproc)" >> $GITHUB_ENV
mkdir -p "${GITHUB_WORKSPACE}/coverage"
echo "LLVM_PROFILE_FILE=${GITHUB_WORKSPACE}/coverage/coverage_%p.profraw" >> $GITHUB_ENV
echo "LLVM_PROFILE_FILE_BUFFER_SIZE=0" >> $GITHUB_ENV
- name: Skip generating files
if: ${{ github.event_name != 'merge_group' && github.event_name != 'workflow_dispatch' }}
run: |
echo "LLVM_PROFILE_FILE=/dev/null" >> $GITHUB_ENV
- name: Build Yosys
run: |
make config-clang
make config-gcov
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
@ -67,19 +81,95 @@ jobs:
- name: Run Yosys tests
run: |
make -j$procs test
make -j$procs vanilla-test
- 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.ref == 'refs/heads/main' }}
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
run: |
make -C sby run_ci
- name: Run unit tests
shell: bash
- name: Run coverage
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
run: |
make -j$procs unit-test ENABLE_LTO=1 ENABLE_LIBYOSYS=1
make coverage
make clean_coverage
- name: Push coverage
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
run: |
git clone https://x-access-token:${{ secrets.REPORTS_TOKEN }}@github.com/YosysHQ/reports.git out
rm -rf out/coverage/main
mkdir -p out/coverage/main
cp -r coverage_html/* out/coverage/main/
cd out
# find . -name "*.html" -type f -print0 | xargs -0 sed -i -z 's#\(<td class="headerItem">Date:</td>[[:space:]]*<td class="headerValue">\)[^<]*\(</td>\)#\1\2#g'
git config user.name "yosyshq-ci"
git config user.email "105224853+yosyshq-ci@users.noreply.github.com"
git add .
if ! git diff --cached --quiet; then
git commit -m "Update coverage"
git push
else
echo "No changes to commit"
fi
test-pyosys:
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
with:
persist-credentials: false
submodules: true
- name: Install UV
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Runtime environment
run: |
echo "procs=$(nproc)" >> $GITHUB_ENV
echo "${{ github.workspace }}/.local/bin" >> $GITHUB_PATH
- name: Build pyosys
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
echo "ENABLE_PYOSYS := 1" >> Makefile.conf
echo "PYTHON_DESTDIR := /usr/lib/python3/site-packages" >> Makefile.conf
make -j$procs
- name: Install pyosys
run: |
make install DESTDIR=${GITHUB_WORKSPACE}/.local PREFIX=
- name: Run pyosys tests
run: |
export PYTHONPATH=${GITHUB_WORKSPACE}/.local/usr/lib/python3/site-packages:$PYTHONPATH
python3 tests/pyosys/run_tests.py
test-verific-result:
runs-on: ubuntu-latest
needs:
- test-verific
- test-pyosys
if: always()
steps:
- name: Check results
run: |
echo "Needs results: ${{ join(needs.*.result, ',') }}"
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
echo "Some jobs failed or were cancelled"
exit 1
fi
- run: echo "All good"

View File

@ -1,25 +0,0 @@
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
jobs:
lockfile:
if: github.repository == 'YosysHQ/Yosys'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
with:
token: ${{CI_CREATE_PR_TOKEN}}
pr-title: "Update flake.lock" # Title of PR to be created
pr-labels: | # Labels to be set on the PR
dependencies
automated

View File

@ -1,34 +0,0 @@
name: Bump version
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
bump-version:
if: github.repository == 'YosysHQ/Yosys'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
persist-credentials: false
- name: Take last commit
id: log
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
- name: Bump version
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
run: |
make bumpversion
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add Makefile
git commit -m "Bump version"
- name: Push changes # push the output folder to your repo
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -49,7 +49,7 @@ jobs:
name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }}
runs-on: ${{ matrix.os.runner }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: true
@ -108,13 +108,13 @@ jobs:
PATH="$PWD/bison/src:$PATH"
CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh
CIBW_TEST_COMMAND: python3 {project}/tests/pyosys/run_tests.py
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: python-wheels-${{ matrix.os.runner }}
path: ./wheelhouse/*.whl
upload_wheels:
name: Upload Wheels
if: (github.repository == 'YosysHQ/Yosys') && (github.event_name == 'workflow_dispatch')
if: (github.repository == 'YosysHQ/yosys') && (github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
# Specifying a GitHub environment is optional, but strongly encouraged
environment: pypi
@ -123,7 +123,7 @@ jobs:
id-token: write
needs: build_wheels
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
path: "."
pattern: python-wheels-*

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -e -x
# Build-time dependencies

4
.gitignore vendored
View File

@ -65,10 +65,10 @@
/viz.js
# other
/coverage.info
/yosys.profdata
/coverage
/coverage_html
# these really belong in global gitignore since they're not specific to this project but rather to user tool choice
# but too many people don't have a global gitignore configured:
# https://docs.github.com/en/get-started/git-basics/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer

View File

@ -9,6 +9,6 @@ brew "python3"
brew "uv"
brew "xdot"
brew "bash"
brew "llvm@20"
brew "llvm"
brew "lld"
brew "googletest"

View File

@ -2,9 +2,97 @@
List of major changes and improvements between releases
=======================================================
Yosys 0.59 .. Yosys 0.60-dev
Yosys 0.65 .. Yosys 0.66-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
--------------------------
* New commands and options
- Added "synth_analogdevices" pass to support synthesis
for Analog Devices FPGAs.
* Various
- Removed rarely-used options from ABC/ABC9.
- Removed "-S" option from "abc" pass.
- Removed "-fast" option from "abc9" and "abc9_exe".
- Calls to "abc -g AND -fast" to map logic to
AND-Inverter Graph form should be replaced with
"aigmap".
- The above change was made to SBY, so we recommend
updating it.
- Added hardware latch support for Gowin FPGAs.
Yosys 0.62 .. Yosys 0.63
--------------------------
* Various
- Added DSP inference for Gowin GW1N and GW2A.
- Added support for subtract in preadder for Xilinx arch.
- Added infrastructure to run a sat solver as a command.
* New commands and options
- Added "-ignore-unknown-cells" option to "equiv_induct"
and "equiv_simple" pass.
- Added "-force-params" option to "memory_libmap" pass.
- Added "-select-solver" option to "sat" pass.
- Added "-default_params" option to "write_verilog" pass.
- Added "-nodsp" option to "synth_gowin" pass.
Yosys 0.61 .. Yosys 0.62
--------------------------
* Various
- verific: Added "-sv2017" flag option to support System
Verilog 2017.
- verific: Added VHDL related flags to "-f" and "-F" and
support reading VHDL file from file lists.
- Updated cell libs with proper module declaration where
non standard (...) style was used.
* New commands and options
- Added "-word" option to "lut2mux" pass to enable emitting
word level cells.
- Added experimental "opt_balance_tree" pass to convert
cascaded cells into tree of cells to improve timing.
- Added "-gatesi" option to "write_blif" pass to init gates
under gates_mode in BLIF format.
- Added "-on" and "-off" options to "debug" pass for
persistent debug logging.
- Added "linux_perf" pass to control performance recording.
Yosys 0.60 .. Yosys 0.61
--------------------------
* Various
- Removed "cover" pass for coverage tracking.
- Avoid merging formal properties with "opt_merge" pass.
- Parallelize "opt_merge" pass.
* New commands and options
- Added "design_equal" pass to support fuzz-test comparison.
- Added "lut2bmux" pass to convert $lut to $bmux.
- Added "-legalize" option to "read_rtlil" pass to prevent
semantic errors.
Yosys 0.59 .. Yosys 0.60
--------------------------
* Various
- read_verilog: suport unsized parameters.
- Added static library compile option.
* New commands and options
- Added "sdc" pass for reading SDC files.
- Added experimental "sdc_expand" and "opensta" for OpenSTA integration.
- Added "icell_liberty" pass for used internal cells.
Yosys 0.58 .. Yosys 0.59
--------------------------
* Various

View File

@ -1,70 +1,15 @@
# Introduction
# Contributing to Yosys
Thanks for thinking about contributing to the Yosys project. If this is your
Thanks for considering helping out. If this is your
first time contributing to an open source project, please take a look at the
following guide:
following guide about the basics:
https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project.
Information about the Yosys coding style is available on our Read the Docs:
https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html.
Check out our [Contributing guidelines](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html) to learn the best ways to
# Using the issue tracker
+ get help
+ report bugs
+ contribute code
+ review code
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.
When [creating a new issue](https://github.com/YosysHQ/yosys/issues/new/choose),
we have a few templates available. Please make use of these! It will make it
much easier for someone to respond and help.
### Bug reports
Before you submit an issue, please check out the [how-to guide for
`bugpoint`](https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html).
This guide will take you through the process of using the [`bugpoint`
command](https://yosys.readthedocs.io/en/latest/cmd/bugpoint.html) in Yosys to
produce a [minimal, complete and verifiable
example](https://stackoverflow.com/help/minimal-reproducible-example) (MVCE).
Providing an MVCE with your bug report drastically increases the likelihood that
someone will be able to help resolve your issue.
# Using pull requests
If you are working on something to add to Yosys, or fix something that isn't
working quite right, make a [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 below to find the best way to [ask us
questions](#asking-questions).
In general, all changes to the code are done as a PR, with [Continuous
Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools that
automatically run the full suite of tests compiling and running Yosys. Please
make use of this! If you're adding a feature: add a test! Not only does it
verify that your feature is working as expected, but it can also be a handy way
for people to see how the feature is used. If you're fixing a bug: add a test!
If you can, do this first; it's okay if the test starts off failing - you
already know there is a bug. CI also helps to make sure that your changes still
work under a range of compilers, settings, and targets.
### 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 beggining 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.
# Asking questions
If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/) or in our [discussions
page](https://github.com/YosysHQ/yosys/discussions).
The Discourse is also a great place to ask questions about developing or
contributing to Yosys.
We have open [dev 'jour fixe' (JF) meetings](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.
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).

View File

@ -1,6 +1,6 @@
ISC License
Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com>
Copyright (C) 2012 - 2026 Claire Xenia Wolf <claire@yosyshq.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@ -1,58 +0,0 @@
ARG IMAGE="python:3-slim-buster"
#---
FROM $IMAGE AS base
RUN apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
ca-certificates \
clang \
lld \
curl \
libffi-dev \
libreadline-dev \
tcl-dev \
graphviz \
xdot \
&& apt-get autoclean && apt-get clean && apt-get -y autoremove \
&& update-ca-certificates \
&& rm -rf /var/lib/apt/lists
#---
FROM base AS build
RUN apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
bison \
flex \
gawk \
gcc \
git \
iverilog \
pkg-config \
&& apt-get autoclean && apt-get clean && apt-get -y autoremove \
&& rm -rf /var/lib/apt/lists
COPY . /yosys
ENV PREFIX /opt/yosys
RUN cd /yosys \
&& make \
&& make install \
&& make test
#---
FROM base
COPY --from=build /opt/yosys /opt/yosys
ENV PATH /opt/yosys/bin:$PATH
RUN useradd -m yosys
USER yosys
CMD ["yosys"]

263
Makefile
View File

@ -21,8 +21,8 @@ ENABLE_VERIFIC_HIER_TREE := 1
ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0
ENABLE_VERIFIC_EDIF := 0
ENABLE_VERIFIC_LIBERTY := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
ENABLE_LIBYOSYS_STATIC := 0
ENABLE_ZLIB := 1
ENABLE_HELP_SOURCE := 0
@ -103,8 +103,8 @@ VPATH := $(YOSYS_SRC)
# Unit test
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
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 :=
PLUGIN_LIBS :=
@ -161,7 +161,19 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.59+0
YOSYS_VER := 0.65
ifneq (, $(shell command -v git 2>/dev/null))
ifneq (, $(shell git rev-parse --git-dir 2>/dev/null))
GIT_COMMIT_COUNT := $(or $(shell git rev-list --count v$(YOSYS_VER)..HEAD 2>/dev/null),0)
ifneq ($(GIT_COMMIT_COUNT),0)
YOSYS_VER := $(YOSYS_VER)+$(GIT_COMMIT_COUNT)
endif
else
YOSYS_VER := $(YOSYS_VER)+post
endif
endif
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
@ -177,15 +189,14 @@ CXXFLAGS += -DYOSYS_VER=\\"$(YOSYS_VER)\\" \
TARBALL_GIT_REV := $(shell cat $(YOSYS_SRC)/.gitcommit)
ifneq ($(findstring Format:,$(TARBALL_GIT_REV)),)
GIT_REV := $(shell GIT_DIR=$(YOSYS_SRC)/.git git rev-parse --short=9 HEAD || echo UNKNOWN)
GIT_DIRTY := $(shell GIT_DIR=$(YOSYS_SRC)/.git git diff --exit-code --quiet 2>/dev/null; if [ $$? -ne 0 ]; then echo "-dirty"; fi)
else
GIT_REV := $(TARBALL_GIT_REV)
GIT_DIRTY := ""
endif
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 03eb220.. | wc -l`/;" Makefile
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
# set ABCEXTERNAL = <abc-command> to use an external ABC instance
@ -248,9 +259,6 @@ ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
CXXFLAGS += -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER)
LINKFLAGS += -g -fsanitize=$(SANITIZER)
ifneq ($(findstring address,$(SANITIZER)),)
ENABLE_COVER := 0
endif
ifneq ($(findstring memory,$(SANITIZER)),)
CXXFLAGS += -fPIE -fsanitize-memory-track-origins
LINKFLAGS += -fPIE -fsanitize-memory-track-origins
@ -283,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
@ -342,6 +351,9 @@ endif
ifeq ($(ENABLE_LIBYOSYS),1)
TARGETS += libyosys.so
ifeq ($(ENABLE_LIBYOSYS_STATIC),1)
TARGETS += libyosys.a
endif
endif
PY_WRAPPER_FILE = pyosys/wrappers
@ -444,8 +456,11 @@ endif
endif
ifeq ($(ENABLE_GCOV),1)
CXXFLAGS += --coverage
LINKFLAGS += --coverage
LLVM_PROFILE_FILE ?= $(realpath $(YOSYS_SRC))/coverage/coverage_%p.profraw
export LLVM_PROFILE_FILE
export LLVM_PROFILE_FILE_BUFFER_SIZE=0
CXXFLAGS += -fprofile-instr-generate -fcoverage-mapping
LINKFLAGS+= -fprofile-instr-generate
endif
ifeq ($(ENABLE_GPROF),1)
@ -474,6 +489,9 @@ else
ifeq ($(ABCEXTERNAL),)
TARGETS := $(PROGRAM_PREFIX)yosys-abc$(EXE) $(TARGETS)
endif
ifeq ($(DISABLE_SPAWN),1)
$(error ENABLE_ABC=1 requires either LINK_ABC=1 or DISABLE_SPAWN=0)
endif
endif
endif
@ -541,10 +559,6 @@ LIBS_VERIFIC += -Wl,--whole-archive $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VE
endif
endif
ifeq ($(ENABLE_COVER),1)
CXXFLAGS += -DYOSYS_ENABLE_COVER
endif
ifeq ($(ENABLE_CCACHE),1)
CXX := ccache $(CXX)
else
@ -603,6 +617,7 @@ $(eval $(call add_include_file,kernel/bitpattern.h))
$(eval $(call add_include_file,kernel/cellaigs.h))
$(eval $(call add_include_file,kernel/celledges.h))
$(eval $(call add_include_file,kernel/celltypes.h))
$(eval $(call add_include_file,kernel/newcelltypes.h))
$(eval $(call add_include_file,kernel/consteval.h))
$(eval $(call add_include_file,kernel/constids.inc))
$(eval $(call add_include_file,kernel/cost.h))
@ -637,6 +652,7 @@ $(eval $(call add_include_file,kernel/yosys_common.h))
$(eval $(call add_include_file,kernel/yw.h))
$(eval $(call add_include_file,libs/ezsat/ezsat.h))
$(eval $(call add_include_file,libs/ezsat/ezminisat.h))
$(eval $(call add_include_file,libs/ezsat/ezcmdline.h))
ifeq ($(ENABLE_ZLIB),1)
$(eval $(call add_include_file,libs/fst/fstapi.h))
endif
@ -644,8 +660,6 @@ $(eval $(call add_include_file,libs/sha1/sha1.h))
$(eval $(call add_include_file,libs/json11/json11.hpp))
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
$(eval $(call add_include_file,passes/techmap/libparse.h))
$(eval $(call add_include_file,frontends/ast/ast.h))
$(eval $(call add_include_file,frontends/ast/ast_binding.h))
$(eval $(call add_include_file,frontends/blif/blifparse.h))
$(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))
@ -684,6 +698,7 @@ OBJS += libs/json11/json11.o
OBJS += libs/ezsat/ezsat.o
OBJS += libs/ezsat/ezminisat.o
OBJS += libs/ezsat/ezcmdline.o
OBJS += libs/minisat/Options.o
OBJS += libs/minisat/SimpSolver.o
@ -722,7 +737,6 @@ OBJS += passes/hierarchy/hierarchy.o
OBJS += passes/cmds/select.o
OBJS += passes/cmds/show.o
OBJS += passes/cmds/stat.o
OBJS += passes/cmds/cover.o
OBJS += passes/cmds/design.o
OBJS += passes/cmds/plugin.o
@ -772,6 +786,9 @@ else
$(P) $(CXX) -o libyosys.so -shared -Wl,-soname,libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC)
endif
libyosys.a: $(filter-out kernel/driver.o,$(OBJS))
$(P) $(AR) rcs $@ $^
%.o: %.cc
$(Q) mkdir -p $(dir $@)
$(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $<
@ -790,12 +807,34 @@ endif
$(Q) mkdir -p $(dir $@)
$(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $<
YOSYS_VER_STR := Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(notdir $(CXX)) $(shell \
$(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1) $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))
YOSYS_REPO :=
ifneq (, $(shell command -v git 2>/dev/null))
ifneq (, $(shell git rev-parse --git-dir 2>/dev/null))
GIT_REMOTE := $(strip $(shell git config --get remote.origin.url 2>/dev/null | $(AWK) '{print tolower($$0)}'))
ifneq ($(strip $(GIT_REMOTE)),)
YOSYS_REPO := $(strip $(shell echo $(GIT_REMOTE) | $(AWK) -F '[:/]' '{gsub(/\.git$$/, "", $$NF); printf "%s/%s", $$(NF-1), $$NF}'))
endif
ifeq ($(strip $(YOSYS_REPO)),yosyshq/yosys)
YOSYS_REPO :=
endif
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
ifeq ($(filter main HEAD release/v%,$(GIT_BRANCH)),)
YOSYS_REPO := $(YOSYS_REPO) at $(GIT_BRANCH)
endif
YOSYS_REPO := $(strip $(YOSYS_REPO))
endif
endif
YOSYS_GIT_STR := $(GIT_REV)$(GIT_DIRTY)
YOSYS_COMPILER := $(notdir $(CXX)) $(shell $(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1) $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS))
YOSYS_VER_STR := Yosys $(YOSYS_VER) (git sha1 $(YOSYS_GIT_STR), $(YOSYS_COMPILER))
ifneq ($(strip $(YOSYS_REPO)),)
YOSYS_VER_STR := $(YOSYS_VER_STR) [$(YOSYS_REPO)]
endif
kernel/version_$(GIT_REV).cc: $(YOSYS_SRC)/Makefile
$(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc
$(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"$(YOSYS_VER_STR)\"; }" > kernel/version_$(GIT_REV).cc
$(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"$(YOSYS_VER_STR)\"; const char *yosys_git_hash_str=\"$(YOSYS_GIT_STR)\"; }" > kernel/version_$(GIT_REV).cc
ifeq ($(ENABLE_VERIFIC),1)
CXXFLAGS_NOVERIFIC = $(foreach v,$(CXXFLAGS),$(if $(findstring $(VERIFIC_DIR),$(v)),,$(v)))
@ -883,106 +922,15 @@ else
ABCOPT=""
endif
# Tests that generate .mk with tests/gen-tests-makefile.sh
MK_TEST_DIRS =
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/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
test: vanilla-test unit-test
# Tests that don't generate .mk
SH_TEST_DIRS =
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
.PHONY: vanilla-test
# 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: makefile-tests abcopt-tests seed-tests
@echo ""
@echo " Passed \"make test\"."
ifeq ($(ENABLE_VERIFIC),1)
ifeq ($(YOSYS_NOVERIFIC),1)
@echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1."
endif
endif
@echo ""
vanilla-test: $(TARGETS) $(EXTRA_TARGETS)
@$(MAKE) -C tests vanilla-test \
$(if $(ENABLE_VERIFIC),ENABLE_VERIFIC=$(ENABLE_VERIFIC)) \
$(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
@ -1008,11 +956,11 @@ ystests: $(TARGETS) $(EXTRA_TARGETS)
# Unit test
unit-test: libyosys.so
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" \
@$(MAKE) -f $(UNITESTPATH)/Makefile CXX="$(CXX)" CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" \
CXXFLAGS="$(CXXFLAGS)" LINKFLAGS="$(LINKFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)"
clean-unit-test:
@$(MAKE) -C $(UNITESTPATH) clean
@$(MAKE) -f $(UNITESTPATH)/Makefile clean
install-dev: $(PROGRAM_PREFIX)yosys-config share
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
@ -1022,15 +970,15 @@ install-dev: $(PROGRAM_PREFIX)yosys-config share
install: $(TARGETS) $(EXTRA_TARGETS)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
$(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR)
ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),)
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys; fi
$(INSTALL_SUDO) cp $(filter-out libyosys.so libyosys.a,$(TARGETS)) $(DESTDIR)$(BINDIR)
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)/.
@ -1038,13 +986,18 @@ ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR)
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so; fi
ifeq ($(ENABLE_LIBYOSYS_STATIC),1)
$(INSTALL_SUDO) cp libyosys.a $(DESTDIR)$(LIBDIR)/
endif
ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
$(INSTALL_SUDO) cp pyosys/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
$(INSTALL_SUDO) cp $(YOSYS_SRC)/pyosys/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
$(INSTALL_SUDO) cp -r share $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
ifeq ($(ENABLE_ABC),1)
$(INSTALL_SUDO) cp yosys-abc $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc
ifeq ($(ABCEXTERNAL),)
$(INSTALL_SUDO) cp $(PROGRAM_PREFIX)yosys-abc$(EXE) $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc$(EXE)
endif
endif
endif
endif
@ -1060,6 +1013,9 @@ uninstall:
$(INSTALL_SUDO) rm -rvf $(DESTDIR)$(DATDIR)
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_LIBYOSYS_STATIC),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.a
endif
ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
@ -1140,16 +1096,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
@ -1158,7 +1106,7 @@ clean-py:
rm -f $(PY_WRAPPER_FILE).inc.cc $(PY_WRAPPER_FILE).cc
rm -f $(PYTHON_OBJECTS)
rm -f *.whl
rm -f libyosys.so
rm -f libyosys.so libyosys.a
rm -rf kernel/*.pyh
clean-abc:
@ -1170,12 +1118,13 @@ mrproper: clean
coverage:
./$(PROGRAM_PREFIX)yosys -qp 'help; help -all'
rm -rf coverage.info coverage_html
lcov --capture -d . --no-external -o coverage.info
genhtml coverage.info --output-directory coverage_html
rm -rf coverage_html
llvm-profdata merge -sparse coverage/coverage_*.profraw -o yosys.profdata
llvm-cov show ./$(PROGRAM_PREFIX)yosys -instr-profile=yosys.profdata -format=html -output-dir=coverage_html --compilation-dir=. -ignore-filename-regex='(^|.*/)libs/.*|/usr/include/.*|$(subst /,\/,$(VERIFIC_DIR))/.*'
clean_coverage:
find . -name "*.gcda" -type f -delete
rm -rf coverage
rm -f yosys.profdata
FUNC_KERNEL := functional.cc functional.h sexpr.cc sexpr.h compute_graph.h
FUNC_INCLUDES := $(addprefix --include *,functional/* $(FUNC_KERNEL))
@ -1192,15 +1141,17 @@ qtcreator:
{ echo .; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \) -printf '%h\n' | sort -u; } > qtcreator.includes
touch qtcreator.creator
vcxsrc: $(GENFILES) $(EXTRA_TARGETS)
rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip}
VCX_DIR_NAME := yosys-win32-vcxsrc-$(YOSYS_VER)
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
bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV)
echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc
zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc
zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/
echo "kernel/version.cc" >> srcfiles.txt
bash misc/create_vcxsrc.sh $(VCX_DIR_NAME) $(YOSYS_VER)
zip $(VCX_DIR_NAME)/genfiles.zip $(GENFILES) kernel/version.cc
zip -r $(VCX_DIR_NAME).zip $(VCX_DIR_NAME)/
rm -f srcfiles.txt kernel/version.cc
config-clean: clean
@ -1235,7 +1186,7 @@ config-msys2-64: clean
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
config-gcov: clean
echo 'CONFIG := gcc' > Makefile.conf
echo 'CONFIG := clang' > Makefile.conf
echo 'ENABLE_GCOV := 1' >> Makefile.conf
echo 'ENABLE_DEBUG := 1' >> Makefile.conf

View File

@ -114,8 +114,8 @@ To build Yosys simply type 'make' in this directory.
$ sudo make install
Tests are located in the tests subdirectory and can be executed using the test
target. Note that you need gawk as well as a recent version of iverilog (i.e.
build from git). Then, execute tests via:
target. Note that you need gawk, a recent version of iverilog, and gtest.
Execute tests via:
$ make test
@ -246,6 +246,8 @@ Building the documentation
Note that there is no need to build the manual if you just want to read it.
Simply visit https://yosys.readthedocs.io/en/latest/ instead.
If you're offline, you can read the sources, replacing `.../en/latest`
with `docs/source`.
In addition to those packages listed above for building Yosys from source, the
following are used for building the website:

2
abc

@ -1 +1 @@
Subproject commit 1c5ed1ce378cc04beac30bb31abc4c37c8467042
Subproject commit 5d51a5e420f5de493d07bf61109a977248c86ffb

View File

@ -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);
}
}
}
@ -930,7 +930,9 @@ struct AigerBackend : public Backend {
log(" make indexes zero based, enable using map files with smt solvers.\n");
log("\n");
log(" -ywmap <filename>\n");
log(" write a map file for conversion to and from yosys witness traces.\n");
log(" write a map file for conversion to and from yosys witness traces,\n");
log(" also allows for mapping AIGER bad-state properties and invariant\n");
log(" constraints back to individual formal properties by name.\n");
log("\n");
log(" -I, -O, -B, -L\n");
log(" If the design contains no input/output/assert/flip-flop then create one\n");
@ -1025,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);

View File

@ -268,7 +268,7 @@ struct XAigerWriter
if (ys_debug(1)) {
static pool<std::pair<IdString,TimingInfo::NameBit>> 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<IdString, std::vector<IdString>> 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);

View File

@ -21,9 +21,13 @@
// - 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/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/rtlil.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@ -44,8 +48,22 @@ PRIVATE_NAMESPACE_BEGIN
// TODO
//#define ARITH_OPS ID($add), ID($sub), ID($neg)
#define KNOWN_OPS BITWISE_OPS, REDUCE_OPS, LOGIC_OPS, GATE_OPS, ID($pos), CMP_OPS, \
ID($pmux), ID($bmux) /*, ARITH_OPS*/
static constexpr auto known_ops = []() constexpr {
StaticCellTypes::Categories::Category c{};
for (auto id : {BITWISE_OPS})
c.set_id(id);
for (auto id : {REDUCE_OPS})
c.set_id(id);
for (auto id : {LOGIC_OPS})
c.set_id(id);
for (auto id : {GATE_OPS})
c.set_id(id);
for (auto id : {CMP_OPS})
c.set_id(id);
for (auto id : {ID($pos), ID($pmux), ID($bmux)})
c.set_id(id);
return c;
}();
template<typename Writer, typename Lit, Lit CFALSE, Lit CTRUE>
struct Index {
@ -91,7 +109,7 @@ struct Index {
int pos = index_wires(info, m);
for (auto cell : m->cells()) {
if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
if (known_ops(cell->type) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
continue;
Module *submodule = m->design->module(cell->type);
@ -114,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);
}
}
}
@ -162,6 +180,11 @@ struct Index {
if (!strashing) {
return (static_cast<Writer*>(this))->emit_gate(a, b);
} 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);
@ -182,7 +205,9 @@ struct Index {
Lit OR(Lit a, Lit b)
{
return NOT(AND(NOT(a), NOT(b)));
Lit not_a = NOT(a);
Lit not_b = NOT(b);
return NOT(AND(not_a, not_b));
}
Lit MUX(Lit a, Lit b, Lit s)
@ -196,17 +221,24 @@ struct Index {
return b;
}
return OR(AND(a, NOT(s)), AND(b, s));
Lit not_s = NOT(s);
Lit a_active = AND(a, not_s);
Lit b_active = AND(b, s);
return OR(a_active, b_active);
}
Lit XOR(Lit a, Lit b)
{
return OR(AND(a, NOT(b)), AND(NOT(a), b));
Lit not_a = NOT(a);
Lit not_b = NOT(b);
Lit a_and_not_b = AND(a, not_b);
Lit not_a_and_b = AND(not_a, b);
return OR(a_and_not_b, not_a_and_b);
}
Lit XNOR(Lit a, Lit b)
{
return NOT(OR(AND(a, NOT(b)), AND(NOT(a), b)));
return NOT(XOR(a, b));
}
Lit CARRY(Lit a, Lit b, Lit c)
@ -218,7 +250,10 @@ struct Index {
return AND(a, b);
}
}
return OR(AND(a, b), AND(c, OR(a, b)));
Lit a_or_b = OR(a, b);
Lit a_or_b_and_c = AND(c, a_or_b);
Lit a_and_b = AND(a, b);
return OR(a_and_b, a_or_b_and_c);
}
Lit REDUCE(std::vector<Lit> lits, bool op_xor=false)
@ -366,7 +401,7 @@ struct Index {
} else if (cell->type.in(ID($xor), ID($_XOR_))) {
return XOR(a, b);
} else if (cell->type.in(ID($xnor), ID($_XNOR_))) {
return NOT(XOR(a, b));
return XNOR(a, b);
} else if (cell->type.in(ID($_ANDNOT_))) {
return AND(a, NOT(b));
} else if (cell->type.in(ID($_ORNOT_))) {
@ -386,7 +421,9 @@ struct Index {
if (oport == ID::Y) {
return XOR(ab, c);
} else /* oport == ID::X */ {
return OR(AND(a, b), AND(c, ab));
Lit a_and_b = AND(a, b);
Lit c_and_ab = AND(c, ab);
return OR(a_and_b, c_and_ab);
}
} else if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
Lit c, d;
@ -397,10 +434,15 @@ struct Index {
else
d = cell->type == ID($_AOI3_) ? CTRUE : CFALSE;
if (/* aoi */ cell->type.in(ID($_AOI3_), ID($_AOI4_)))
return NOT(OR(AND(a, b), AND(c, d)));
else
return NOT(AND(OR(a, b), OR(c, d)));
if (/* aoi */ cell->type.in(ID($_AOI3_), ID($_AOI4_))) {
Lit a_and_b = AND(a, b);
Lit c_and_d = AND(c, d);
return NOT(OR(a_and_b, c_and_d));
} else {
Lit a_or_b = OR(a, b);
Lit c_or_d = OR(c, d);
return NOT(AND(a_or_b, c_or_d));
}
} else {
log_abort();
}
@ -421,7 +463,11 @@ struct Index {
sels.push_back(NOT(s));
}
return OR(AND(REDUCE(sels), a), NOT(REDUCE(bar)));
Lit reduce_sels = REDUCE(sels);
Lit reduce_sels_and_a = AND(reduce_sels, a);
Lit reduce_bar = NOT(REDUCE(bar));
return OR(reduce_sels_and_a, reduce_bar);
} else if (cell->type == ID($bmux)) {
SigSpec aport = cell->getPort(ID::A);
SigSpec sport = cell->getPort(ID::S);
@ -491,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", cell->type.unescape(), cell, cell->module);
Module *def = design->module(cell->type);
log_assert(def);
levels.push_back(Level(index.modules.at(def), cell));
@ -510,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 += minfo.module->name.unescape();
else
ret += RTLIL::unescape_id(pair.second->name);
ret += cell->name.unescape();
first = false;
}
return ret;
@ -525,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;
}
@ -535,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;
}
@ -578,7 +627,7 @@ struct Index {
// an output of a cell
Cell *driver = bit.wire->driverCell();
if (driver->type.in(KNOWN_OPS)) {
if (known_ops(driver->type)) {
ret = impl_op(cursor, driver, bit.wire->driverPort(), bit.offset);
} else {
Module *def = cursor.enter(*this, driver);
@ -587,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);
@ -606,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);
@ -700,6 +749,9 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
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);
@ -716,7 +768,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
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));
}
@ -729,15 +781,16 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
// populate inputs
std::vector<SigBit> inputs;
for (auto id : top->ports) {
Wire *w = top->wire(id);
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));
lit_counter += 2;
ninputs++;
}
Wire *w = top->wire(id);
log_assert(w);
if (w->port_input && !w->port_output)
for (int i = 0; i < w->width; i++) {
auto bit = SigBit(w, i);
pi_literal(bit) = lit_counter;
inputs.push_back(bit);
lit_counter += 2;
ninputs++;
}
}
this->f = f;
@ -745,35 +798,38 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
write_header();
// insert padding where output literals will go (once known)
for (auto id : top->ports) {
Wire *w = top->wire(id);
log_assert(w);
if (w->port_output) {
for (auto bit : SigSpec(w)) {
(void) bit;
char buf[16];
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
f->write(buf, strlen(buf));
noutputs++;
Wire *w = top->wire(id);
log_assert(w);
if (w->port_output) {
for (auto bit : SigSpec(w)) {
(void) bit;
char buf[16];
snprintf(buf, sizeof(buf), "%08d\n", 0);
f->write(buf, strlen(buf));
noutputs++;
}
}
}
}
auto data_start = f->tellp();
// now the guts
std::vector<std::pair<SigBit, int>> outputs;
for (auto w : top->wires())
if (w->port_output) {
for (auto bit : SigSpec(w))
outputs.push_back({bit, eval_po(bit)});
}
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
@ -782,12 +838,13 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
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 = bit.wire->name.unescape();
f->write(name.data(), name.size());
f->put('\n');
}
@ -796,10 +853,11 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
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);
std::string name = bit.wire->name.unescape();
f->write(name.data(), name.size());
f->put('\n');
}
@ -845,11 +903,14 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
return false;
int max = 1;
for (auto wire : mod->wires())
if (wire->port_input && !wire->port_output)
for (int i = 0; i < wire->width; i++) {
int ilevel = visit(cursor, driver->getPort(wire->name)[i]);
max = std::max(max, ilevel + 1);
for (auto wire : mod->wires()) {
if (wire->port_input && !wire->port_output) {
SigSpec port = driver->getPort(wire->name);
for (int i = 0; i < std::min(wire->width, port.size()); i++) {
int ilevel = visit(cursor, port[i]);
max = std::max(max, ilevel + 1);
}
}
}
lits[idx] = max;
@ -867,33 +928,34 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
Wire *w = top->wire(id);
log_assert(w);
if (w->port_input && !w->port_output)
for (int i = 0; i < w->width; i++)
pi_literal(SigBit(w, i)) = 0;
for (int i = 0; i < w->width; i++)
pi_literal(SigBit(w, i)) = 0;
}
HierCursor cursor;
for (auto box : top_minfo->found_blackboxes) {
Module *def = design->module(box->type);
if (!(def && def->has_attribute(ID::abc9_box_id)))
for (auto &conn : box->connections_)
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
for (auto bit : conn.second)
pi_literal(bit, &cursor) = 0;
for (auto &conn : box->connections_)
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
for (auto bit : conn.second)
pi_literal(bit, &cursor) = 0;
}
for (auto w : top->wires())
if (w->port_output) {
for (auto bit : SigSpec(w))
(void) eval_po(bit);
for (auto w : top->wires()) {
if (w->port_output) {
for (auto bit : SigSpec(w))
(void) eval_po(bit);
}
}
for (auto box : top_minfo->found_blackboxes) {
Module *def = design->module(box->type);
if (!(def && def->has_attribute(ID::abc9_box_id)))
for (auto &conn : box->connections_)
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
for (auto bit : conn.second)
(void) eval_po(bit);
for (auto &conn : box->connections_)
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
for (auto bit : conn.second)
(void) eval_po(bit);
}
}
};
@ -912,15 +974,15 @@ struct XAigerWriter : AigerWriter {
std::vector<HierBit> pos;
std::vector<HierBit> pis;
// * The aiger output port sequence is COs (inputs to modeled boxes),
// inputs to opaque boxes, then module outputs. COs going first is
// required by abc.
// * proper_pos_counter counts ports which follow after COs
// * The mapping file `pseudopo` and `po` statements use indexing relative
// to the first port following COs.
// * If a module output is directly driven by an opaque box, the emission
// of the po statement in the mapping file is skipped. This is done to
// aid re-integration of the mapped result.
// * The aiger output port sequence is COs (inputs to modeled boxes),
// inputs to opaque boxes, then module outputs. COs going first is
// required by abc.
// * proper_pos_counter counts ports which follow after COs
// * The mapping file `pseudopo` and `po` statements use indexing relative
// to the first port following COs.
// * If a module output is directly driven by an opaque box, the emission
// of the po statement in the mapping file is skipped. This is done to
// aid re-integration of the mapped result.
int proper_pos_counter = 0;
pool<SigBit> driven_by_opaque_box;
@ -986,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(), log_signal(conn.second));
ensure_pi(bit, cursor);
@ -1011,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<std::tuple<HierCursor, Cell *, Module *>> nonopaque_boxes;
@ -1026,8 +1088,8 @@ 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,
box->type.unescape());
Module *box_module = design->module(box->type), *box_derived;
@ -1096,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;
}
@ -1131,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;
}
@ -1148,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());
}
}
}
@ -1198,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
@ -1230,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();
@ -1247,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;
@ -1287,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);
@ -1327,41 +1390,50 @@ struct Aiger2Backend : Backend {
log(" perform structural hashing while writing\n");
log("\n");
log(" -flatten\n");
log(" allow descending into submodules and write a flattened view of the design\n");
log(" hierarchy starting at the selected top\n");
log("\n");
log(" allow descending into submodules and write a flattened view of the design\n");
log(" hierarchy starting at the selected top\n");
log("\n");
log("This command is able to ingest all combinational cells except for:\n");
log("\n");
pool<IdString> supported = {KNOWN_OPS};
CellTypes ct;
ct.setup_internals_eval();
log(" ");
int col = 0;
for (auto pair : ct.cell_types)
if (!supported.count(pair.first)) {
if (col + pair.first.size() + 2 > 72) {
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
auto &cell = StaticCellTypes::builder.cells[i];
if (!cell.features.is_evaluable)
continue;
if (cell.features.is_stdcell)
continue;
if (known_ops(cell.type))
continue;
std::string name = cell.type.unescape();
if (col + name.size() + 2 > 72) {
log("\n ");
col = 0;
}
col += pair.first.size() + 2;
log("%s, ", log_id(pair.first));
col += name.size() + 2;
log("%s, ", name.c_str());
}
log("\n");
log("\n");
log("And all combinational gates except for:\n");
log("\n");
CellTypes ct2;
ct2.setup_stdcells();
log(" ");
col = 0;
for (auto pair : ct2.cell_types)
if (!supported.count(pair.first)) {
if (col + pair.first.size() + 2 > 72) {
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
auto &cell = StaticCellTypes::builder.cells[i];
if (!cell.features.is_evaluable)
continue;
if (!cell.features.is_stdcell)
continue;
if (known_ops(cell.type))
continue;
std::string name = cell.type.unescape();
if (col + name.size() + 2 > 72) {
log("\n ");
col = 0;
}
col += pair.first.size() + 2;
log("%s, ", log_id(pair.first));
col += name.size() + 2;
log("%s, ", name.c_str());
}
log("\n");
}
@ -1419,20 +1491,20 @@ struct XAiger2Backend : Backend {
log(" perform structural hashing while writing\n");
log("\n");
log(" -flatten\n");
log(" allow descending into submodules and write a flattened view of the design\n");
log(" hierarchy starting at the selected top\n");
log("\n");
log(" -mapping_prep\n");
log(" after the file is written, prepare the module for reintegration of\n");
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
log(" whiteboxed are removed from the design as well as all wires which only\n");
log(" connect to removed cells\n");
log(" (conflicts with -flatten)\n");
log("\n");
log(" -map2 <file>\n");
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
log(" reintegrate a mapping\n");
log(" (conflicts with -flatten)\n");
log(" allow descending into submodules and write a flattened view of the design\n");
log(" hierarchy starting at the selected top\n");
log("\n");
log(" -mapping_prep\n");
log(" after the file is written, prepare the module for reintegration of\n");
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
log(" whiteboxed are removed from the design as well as all wires which only\n");
log(" connect to removed cells\n");
log(" (conflicts with -flatten)\n");
log("\n");
log(" -map2 <file>\n");
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
log(" reintegrate a mapping\n");
log(" (conflicts with -flatten)\n");
log("\n");
}

View File

@ -24,7 +24,7 @@
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/log.h"
#include <string>
@ -44,6 +44,7 @@ struct BlifDumperConfig
bool iattr_mode;
bool blackbox_mode;
bool noalias_mode;
bool gatesi_mode;
std::string buf_type, buf_in, buf_out;
std::map<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::IdString>> unbuf_types;
@ -51,7 +52,7 @@ struct BlifDumperConfig
BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false),
cname_mode(false), iname_mode(false), param_mode(false), attr_mode(false), iattr_mode(false),
blackbox_mode(false), noalias_mode(false) { }
blackbox_mode(false), noalias_mode(false), gatesi_mode(false) { }
};
struct BlifDumper
@ -60,7 +61,7 @@ struct BlifDumper
RTLIL::Module *module;
RTLIL::Design *design;
BlifDumperConfig *config;
CellTypes ct;
NewCellTypes ct;
SigMap sigmap;
dict<SigBit, int> init_bits;
@ -90,7 +91,7 @@ struct BlifDumper
const std::string str(RTLIL::IdString id)
{
std::string str = RTLIL::unescape_id(id);
std::string str = id.unescape();
for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?';
@ -107,7 +108,7 @@ struct BlifDumper
return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef";
}
std::string str = RTLIL::unescape_id(sig.wire->name);
std::string str = sig.wire->name.unescape();
for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?';
@ -118,16 +119,21 @@ struct BlifDumper
return str;
}
const std::string str_init(RTLIL::SigBit sig)
template <bool Space = true> const std::string str_init(RTLIL::SigBit sig)
{
sigmap.apply(sig);
if (init_bits.count(sig) == 0)
return " 2";
if (init_bits.count(sig) == 0) {
if constexpr (Space)
return " 2";
else
return "2";
}
string str = stringf(" %d", init_bits.at(sig));
return str;
if constexpr (Space)
return stringf(" %d", init_bits.at(sig));
else
return stringf("%d", init_bits.at(sig));
}
const char *subckt_or_gate(std::string cell_type)
@ -144,7 +150,7 @@ struct BlifDumper
void dump_params(const char *command, dict<IdString, Const> &params)
{
for (auto &param : 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("\"");
@ -469,6 +475,11 @@ struct BlifDumper
f << stringf(".names %s %s\n1 1\n", str(rhs_bit), str(lhs_bit));
}
if (config->gatesi_mode) {
for (auto &&init_bit : init_bits)
f << stringf(".gateinit %s=%s\n", str(init_bit.first), str_init<false>(init_bit.first));
}
f << stringf(".end\n");
}
@ -550,6 +561,9 @@ struct BlifBackend : public Backend {
log(" -impltf\n");
log(" do not write definitions for the $true, $false and $undef wires.\n");
log("\n");
log(" -gatesi\n");
log(" write initial bit(s) with .gateinit for gates that needs to be initialized.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
@ -640,6 +654,10 @@ struct BlifBackend : public Backend {
config.noalias_mode = true;
continue;
}
if (args[argidx] == "-gatesi") {
config.gatesi_mode = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
@ -660,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);

View File

@ -119,7 +119,7 @@ struct BtorWorker
template<typename T>
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<pair<int, Mem*>> 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);

View File

@ -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)
@ -756,7 +756,7 @@ struct CxxrtlWorker {
// 1b. Generated identifiers for internal names (beginning with `$`) start with `i_`.
// 2. An underscore is escaped with another underscore, i.e. `__`.
// 3. Any other non-alnum character is escaped with underscores around its lowercase hex code, e.g. `@` as `_40_`.
std::string mangle_name(const RTLIL::IdString &name)
std::string mangle_name(RTLIL::IdString name)
{
std::string mangled;
bool first = true;
@ -786,7 +786,7 @@ struct CxxrtlWorker {
return mangled;
}
std::string mangle_module_name(const RTLIL::IdString &name, bool is_blackbox = false)
std::string mangle_module_name(RTLIL::IdString name, bool is_blackbox = false)
{
// Class namespace.
if (is_blackbox)
@ -794,19 +794,19 @@ struct CxxrtlWorker {
return mangle_name(name);
}
std::string mangle_memory_name(const RTLIL::IdString &name)
std::string mangle_memory_name(RTLIL::IdString name)
{
// Class member namespace.
return "memory_" + mangle_name(name);
}
std::string mangle_cell_name(const RTLIL::IdString &name)
std::string mangle_cell_name(RTLIL::IdString name)
{
// Class member namespace.
return "cell_" + mangle_name(name);
}
std::string mangle_wire_name(const RTLIL::IdString &name)
std::string mangle_wire_name(RTLIL::IdString name)
{
// Class member namespace.
return mangle_name(name);
@ -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<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
for (const auto &param_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);
@ -2776,7 +2776,8 @@ struct CxxrtlWorker {
{
RTLIL::Module *top_module = nullptr;
std::vector<RTLIL::Module*> modules;
TopoSort<RTLIL::Module*> topo_design;
using Order = IdString::compare_ptr_by_name<RTLIL::NamedObject>;
TopoSort<RTLIL::Module*, Order> topo_design;
for (auto module : design->modules()) {
if (!design->selected_module(module))
continue;
@ -2939,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++) {
@ -2952,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));
}
}
}
@ -2977,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;
@ -2986,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)) &&
@ -3115,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
@ -3188,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) {
@ -3236,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.
@ -3419,7 +3420,7 @@ struct CxxrtlWorker {
if (!design->selected_whole_module(module))
if (design->selected_module(module))
log_cmd_error("Can't handle partially selected module `%s'!\n", id2cstr(module->name));
log_cmd_error("Can't handle partially selected module `%s'!\n", module);
if (!design->selected_module(module))
continue;

View File

@ -614,7 +614,7 @@ struct value : public expr_base<value<Bits>> {
int64_t divisor_shift = divisor.ctlz() - dividend.ctlz();
assert(divisor_shift >= 0);
divisor = divisor.shl(value<Bits>{(chunk::type) divisor_shift});
for (size_t step = 0; step <= divisor_shift; step++) {
for (size_t step = 0; step <= (uint64_t) divisor_shift; step++) {
quotient = quotient.shl(value<Bits>{1u});
if (!dividend.ucmp(divisor)) {
dividend = dividend.sub(divisor);
@ -1119,7 +1119,7 @@ struct fmt_part {
case STRING: {
buf.reserve(Bits/8);
for (int i = 0; i < Bits; i += 8) {
for (size_t i = 0; i < Bits; i += 8) {
char ch = 0;
for (int j = 0; j < 8 && i + j < int(Bits); j++)
if (val.bit(i + j))

View File

@ -23,16 +23,18 @@
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true)
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br)
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false)
#define EDIF_DEF(_id) edif_names(_id.unescape(), true)
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(_id.unescape(), true, _ren, _bl, _br)
#define EDIF_REF(_id) edif_names(_id.unescape(), false)
#define EDIF_DEF_STR(_id) edif_names(RTLIL::unescape_id(_id), true)
#define EDIF_REF_STR(_id) edif_names(RTLIL::unescape_id(_id), false)
struct EdifNames
{
@ -138,7 +140,7 @@ struct EdifBackend : public Backend {
bool lsbidx = false;
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
bool nogndvcc = false, gndvccy = false, keepmode = false;
CellTypes ct(design);
NewCellTypes ct(design);
EdifNames edif_names;
size_t argidx;
@ -207,9 +209,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())
{
@ -227,7 +229,7 @@ struct EdifBackend : public Backend {
if (top_module_name.empty())
log_error("No module found in design!\n");
*f << stringf("(edif %s\n", EDIF_DEF(top_module_name));
*f << stringf("(edif %s\n", EDIF_DEF_STR(top_module_name));
*f << stringf(" (edifVersion 2 0 0)\n");
*f << stringf(" (edifLevel 0)\n");
*f << stringf(" (keywordMap (keywordLevel 0))\n");
@ -317,12 +319,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 +488,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);
@ -534,7 +536,7 @@ struct EdifBackend : public Backend {
if (netname[i] == ' ' || netname[i] == '\\')
netname.erase(netname.begin() + i--);
}
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
*f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
for (auto &ref : it.second)
*f << stringf(" %s\n", ref.first);
if (sig.wire == NULL) {
@ -572,7 +574,7 @@ struct EdifBackend : public Backend {
if (keepmode)
{
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
*f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
auto &refs = net_join_db.at(mapped_sig);
for (auto &ref : refs)
@ -588,7 +590,7 @@ struct EdifBackend : public Backend {
}
else
{
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF(netname));
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF_STR(netname));
}
}
}
@ -599,8 +601,8 @@ struct EdifBackend : public Backend {
}
*f << stringf(" )\n");
*f << stringf(" (design %s\n", EDIF_DEF(top_module_name));
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name));
*f << stringf(" (design %s\n", EDIF_DEF_STR(top_module_name));
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF_STR(top_module_name));
*f << stringf(" )\n");
*f << stringf(")\n");

View File

@ -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;

View File

@ -89,7 +89,7 @@ struct CxxStruct {
}
f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n");
for (auto p : types) {
f.print("\t\t\tfn(\"{}\", {});\n", RTLIL::unescape_id(p.first), scope(p.first, p.first));
f.print("\t\t\tfn(\"{}\", {});\n", p.first.unescape(), scope(p.first, p.first));
}
f.print("\t\t}}\n");
f.print("\t}};\n\n");

View File

@ -80,7 +80,7 @@ public:
SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {}
void insert(IdString field_name, SmtSort sort) {
field_names(field_name);
auto accessor = scope.unique_name("\\" + name + "_" + RTLIL::unescape_id(field_name));
auto accessor = scope.unique_name("\\" + name + "_" + field_name.unescape());
fields.emplace_back(Field{sort, accessor});
}
void write_definition(SExprWriter &w) {
@ -99,7 +99,7 @@ public:
w.open(list(name));
for(auto field_name : field_names) {
w << fn(field_name);
w.comment(RTLIL::unescape_id(field_name), true);
w.comment(field_name.unescape(), true);
}
w.close();
}

View File

@ -106,7 +106,7 @@ public:
w.open(list(name));
for(auto field_name : field_names) {
w << fn(field_name);
w.comment(RTLIL::unescape_id(field_name), true);
w.comment(field_name.unescape(), true);
}
w.close();
}
@ -188,20 +188,27 @@ struct SmtrModule {
Functional::IR ir;
SmtrScope scope;
std::string name;
bool use_assoc_list_helpers;
std::optional<std::string> input_helper_name;
std::optional<std::string> output_helper_name;
SmtrStruct input_struct;
SmtrStruct output_struct;
SmtrStruct state_struct;
SmtrModule(Module *module)
: ir(Functional::IR::from_module(module))
, scope()
, name(scope.unique_name(module->name))
, input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope)
, output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope)
, state_struct(scope.unique_name(module->name.str() + "_State"), scope)
SmtrModule(Module *module, bool assoc_list_helpers)
: ir(Functional::IR::from_module(module)), scope(), name(scope.unique_name(module->name)), use_assoc_list_helpers(assoc_list_helpers),
input_struct(scope.unique_name(module->name.str() + "_Inputs"), scope),
output_struct(scope.unique_name(module->name.str() + "_Outputs"), scope),
state_struct(scope.unique_name(module->name.str() + "_State"), scope)
{
scope.reserve(name + "_initial");
if (assoc_list_helpers) {
input_helper_name = scope.unique_name(module->name.str() + "_inputs_helper");
scope.reserve(*input_helper_name);
output_helper_name = scope.unique_name(module->name.str() + "_outputs_helper");
scope.reserve(*output_helper_name);
}
for (auto input : ir.inputs())
input_struct.insert(input->name, input->sort);
for (auto output : ir.outputs())
@ -257,6 +264,45 @@ struct SmtrModule {
w.pop();
}
void write_assoc_list_helpers(SExprWriter &w)
{
log_assert(output_helper_name && input_helper_name);
// Input struct keyword-based constructor.
w.push();
w.open(list("define"));
const auto inputs_name = "inputs";
w.open(list(*input_helper_name, inputs_name));
w.close();
w.open(list(input_struct.name));
for (auto input : ir.inputs()) {
w.push();
w.open(list("let"));
w.push();
w.open(list());
w.open(list("assoc-result"));
w << list("assoc", "\"" + input->name.unescape() + "\"", inputs_name);
w.pop();
w.open(list("if", "assoc-result"));
w << list("cdr", "assoc-result");
w.open(list("begin"));
w << list("fprintf", list("current-error-port"), "\"%s not found in inputs\"");
w << "'not-found";
w.pop();
}
w.pop();
// Output struct keyword-based destructuring
w.push();
w.open(list("define"));
const auto outputs_name = "outputs";
w << list(*output_helper_name, outputs_name);
w.open(list("list"));
for (auto output : ir.outputs()) {
w << list("cons", "\"" + output->name.unescape() + "\"", output_struct.access("outputs", output->name));
}
w.pop();
}
void write(std::ostream &out)
{
SExprWriter w(out);
@ -265,6 +311,10 @@ struct SmtrModule {
output_struct.write_definition(w);
state_struct.write_definition(w);
if (use_assoc_list_helpers) {
write_assoc_list_helpers(w);
}
write_eval(w);
write_initial(w);
}
@ -282,12 +332,16 @@ struct FunctionalSmtrBackend : public Backend {
log("\n");
log(" -provides\n");
log(" include 'provide' statement(s) for loading output as a module\n");
log(" -assoc-list-helpers\n");
log(" provide helper functions which convert inputs/outputs from/to association lists\n");
log(" \n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
auto provides = false;
auto assoc_list_helpers = false;
log_header(design, "Executing Functional Rosette Backend.\n");
@ -296,6 +350,8 @@ struct FunctionalSmtrBackend : public Backend {
{
if (args[argidx] == "-provides")
provides = true;
else if (args[argidx] == "-assoc-list-helpers")
assoc_list_helpers = true;
else
break;
}
@ -307,8 +363,8 @@ struct FunctionalSmtrBackend : public Backend {
}
for (auto module : design->selected_modules()) {
log("Processing module `%s`.\n", module->name);
SmtrModule smtr(module);
log("Processing module `%s`.\n", module->name.c_str());
SmtrModule smtr(module, assoc_list_helpers);
smtr.write(*f);
}
}

View File

@ -146,11 +146,11 @@ struct FunctionalTestGeneric : public Pass
log("Dumping module `%s'.\n", module->name);
auto fir = Functional::IR::from_module(module);
for(auto node : fir)
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n";
std::cout << node.name().unescape() << " = " << node.to_string([](auto n) { return n.name().unescape(); }) << "\n";
for(auto output : fir.all_outputs())
std::cout << RTLIL::unescape_id(output->kind) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n";
std::cout << output->kind.unescape() << " " << output->name.unescape() << " = " << output->value().name().unescape() << "\n";
for(auto state : fir.all_states())
std::cout << RTLIL::unescape_id(state->kind) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n";
std::cout << state->kind.unescape() << " " << state->name.unescape() << " = " << state->next_value().name().unescape() << "\n";
}
}
} FunctionalCxxBackend;

View File

@ -20,7 +20,7 @@
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/log.h"
#include <string>
@ -41,7 +41,7 @@ static std::string netname(std::set<std::string> &conntypes_code, std::set<std::
return stringf("CONST_%d_0x%x", sig.size(), sig.as_int());
}
return RTLIL::unescape_id(sig.as_wire()->name);
return sig.as_wire()->name.unescape();
}
struct IntersynthBackend : public Backend {
@ -117,7 +117,7 @@ struct IntersynthBackend : public Backend {
std::set<std::string> conntypes_code, celltypes_code;
std::string netlists_code;
CellTypes ct(design);
NewCellTypes ct(design);
for (auto lib : libs)
ct.setup_design(lib);
@ -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<std::string> 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<string> 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 &param : 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");

View File

@ -91,7 +91,7 @@ struct JnyWriter
{
_cells.clear();
for (auto cell : mod->cells()) {
const auto cell_type = escape_string(RTLIL::unescape_id(cell->type));
const auto cell_type = escape_string(cell->type.unescape());
if (_cells.find(cell_type) == _cells.end())
_cells.emplace(cell_type, std::vector<Cell*>());
@ -214,7 +214,7 @@ struct JnyWriter
void write_cell_conn(const std::pair<RTLIL::IdString, RTLIL::SigSpec>& sig, uint16_t indent_level = 0) {
const auto _indent = gen_indent(indent_level);
f << _indent << " {\n";
f << _indent << " \"name\": \"" << escape_string(RTLIL::unescape_id(sig.first)) << "\",\n";
f << _indent << " \"name\": \"" << escape_string(sig.first.unescape()) << "\",\n";
f << _indent << " \"signals\": [\n";
write_sigspec(sig.second, indent_level + 2);
@ -232,7 +232,7 @@ struct JnyWriter
const auto _indent = gen_indent(indent_level);
f << _indent << "{\n";
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(mod->name)));
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(mod->name.unescape()));
f << _indent << " \"cell_sorts\": [\n";
bool first_sort{true};
@ -280,7 +280,7 @@ struct JnyWriter
f << ",\n";
f << _indent << " {\n";
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(con.first)));
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(con.first.unescape()));
f << _indent << " \"direction\": \"";
if (port_cell->input(con.first))
f << "i";
@ -351,10 +351,10 @@ struct JnyWriter
f << stringf(",\n");
const auto param_val = param.second;
if (!param_val.empty()) {
f << stringf(" %s\"%s\": ", _indent, escape_string(RTLIL::unescape_id(param.first)));
f << stringf(" %s\"%s\": ", _indent, escape_string(param.first.unescape()));
write_param_val(param_val);
} else {
f << stringf(" %s\"%s\": true", _indent, escape_string(RTLIL::unescape_id(param.first)));
f << stringf(" %s\"%s\": true", _indent, escape_string(param.first.unescape()));
}
first_param = false;
@ -366,7 +366,7 @@ struct JnyWriter
log_assert(cell != nullptr);
f << _indent << " {\n";
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(RTLIL::unescape_id(cell->name)));
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(cell->name.unescape()));
if (_include_connections) {
f << ",\n" << _indent << " \"connections\": [\n";

View File

@ -76,7 +76,7 @@ struct JsonWriter
string get_name(IdString name)
{
return get_string(RTLIL::unescape_id(name));
return get_string(name.unescape());
}
string get_bits(SigSpec sig)
@ -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++;
}

View File

@ -61,7 +61,9 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
return;
}
}
f << stringf("%d'", width);
if ((data.flags & RTLIL::CONST_FLAG_UNSIZED) == 0) {
f << stringf("%d'", width);
}
if (data.flags & RTLIL::CONST_FLAG_SIGNED) {
f << stringf("s");
}
@ -173,9 +175,10 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::
dump_attributes(f, indent, cell);
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
for (const auto& [name, param] : reversed(cell->parameters)) {
f << stringf("%s parameter%s%s %s ", indent,
f << stringf("%s parameter%s%s%s %s ", indent,
(param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
(param.flags & RTLIL::CONST_FLAG_UNSIZED) != 0 ? " unsized" : "",
name);
dump_const(f, param);
f << stringf("\n");

View File

@ -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);

View File

@ -20,7 +20,7 @@
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/log.h"
#include "kernel/mem.h"
#include "libs/json11/json11.hpp"
@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN
struct Smt2Worker
{
CellTypes ct;
NewCellTypes ct;
SigMap sigmap;
RTLIL::Module *module;
bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode;
@ -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<std::string> 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();

View File

@ -735,6 +735,12 @@ def ywfile_signal(sig, step, mask=None):
output = []
def ywfile_signal_error(reason, detail=None):
msg = f"Yosys witness signal mismatch for {sig.pretty()}: {reason}"
if detail:
msg += f" ({detail})"
raise ValueError(msg)
if sig.path in smt_wires:
for wire in smt_wires[sig.path]:
width, offset = wire["width"], wire["offset"]
@ -765,6 +771,12 @@ def ywfile_signal(sig, step, mask=None):
for mem in smt_mems[sig.memory_path]:
width, size, bv = mem["width"], mem["size"], mem["statebv"]
if sig.memory_addr is not None and sig.memory_addr >= size:
ywfile_signal_error(
"memory address out of bounds",
f"address={sig.memory_addr} size={size}",
)
smt_expr = smt.net_expr(topmod, f"s{step}", mem["smtpath"])
if bv:
@ -781,18 +793,34 @@ def ywfile_signal(sig, step, mask=None):
smt_expr = "((_ extract %d %d) %s)" % (slice_high, sig.offset, smt_expr)
output.append((0, sig.width, smt_expr))
else:
ywfile_signal_error("memory not found in design")
output.sort()
output = [chunk for chunk in output if chunk[0] != chunk[1]]
if not output:
if sig.memory_path:
ywfile_signal_error("memory signal has no matching bits in design")
else:
ywfile_signal_error("signal not found in design")
pos = 0
for start, end, smt_expr in output:
assert start == pos
if start != pos:
ywfile_signal_error(
"signal width/offset mismatch",
f"expected coverage at bit {pos}",
)
pos = end
assert pos == sig.width
if pos != sig.width:
ywfile_signal_error(
"signal width/offset mismatch",
f"covered {pos} of {sig.width} bits",
)
if len(output) == 1:
return output[0][-1]

View File

@ -20,7 +20,7 @@
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "kernel/log.h"
#include <string>
@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SmvWorker
{
CellTypes ct;
NewCellTypes ct;
SigMap sigmap;
RTLIL::Module *module;
std::ostream &f;
@ -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();
}

View File

@ -30,7 +30,7 @@ PRIVATE_NAMESPACE_BEGIN
static string spice_id2str(IdString id)
{
static const char *escape_chars = "$\\[]()<>=";
string s = RTLIL::unescape_id(id);
string s = id.unescape();
for (auto &ch : s)
if (strchr(escape_chars, ch) != nullptr) ch = '_';
@ -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;

View File

@ -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";

View File

@ -95,7 +95,8 @@ bool VERILOG_BACKEND::id_is_verilog_escaped(const std::string &str) {
PRIVATE_NAMESPACE_BEGIN
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs,
noparallelcase, default_params;
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
dict<RTLIL::IdString, int> auto_name_map;
std::set<RTLIL::IdString> reg_wires;
@ -108,22 +109,30 @@ IdString initial_id;
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
{
const char *str = id.c_str();
if (*str == '$' && may_rename && !norename)
auto_name_map[id] = auto_name_counter++;
if (str[0] != '\\' || str[1] != '_' || str[2] == 0)
auto it = id.begin();
auto it_end = id.end();
if (it == it_end)
return;
for (int i = 2; str[i] != 0; i++) {
if (str[i] == '_' && str[i+1] == 0)
continue;
if (str[i] < '0' || str[i] > '9')
if (*it == '$' && may_rename && !norename)
auto_name_map[id] = auto_name_counter++;
if (*it != '\\' || (it + 1) == it_end || *(it + 1) != '_' || (it + 2) == it_end)
return;
std::string s;
it += 2;
while (it != it_end) {
char ch = *it;
if (ch == '_' && (it + 1) == it_end)
break;
if (ch < '0' || ch > '9')
return;
s.push_back(ch);
++it;
}
int num = atoi(str+2);
int num = atoi(s.c_str());
if (num >= auto_name_offset)
auto_name_offset = num + 1;
}
@ -413,6 +422,13 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
}
}
void dump_parameter(std::ostream &f, std::string indent, RTLIL::IdString id_string, RTLIL::Const parameter)
{
f << stringf("%sparameter %s = ", indent.c_str(), id(id_string).c_str());
dump_const(f, parameter);
f << ";\n";
}
void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
{
dump_attributes(f, indent, wire->attributes, "\n", /*modattr=*/false, /*regattr=*/reg_wires.count(wire->name));
@ -2135,6 +2151,9 @@ void dump_case_actions(std::ostream &f, std::string indent, RTLIL::CaseRule *cs)
bool dump_proc_switch_ifelse(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw)
{
if (sw->cases.empty())
return true;
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) {
if ((*it)->compare.size() == 0) {
break;
@ -2369,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)
@ -2427,6 +2446,10 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
f << indent + " " << "reg " << id(initial_id) << " = 0;\n";
}
if (default_params)
for (auto p : module->parameter_default_values)
dump_parameter(f, indent + " ", p.first, p.second);
// first dump input / output according to their order in module->ports
for (auto port : module->ports)
dump_wire(f, indent + " ", module->wire(port));
@ -2534,6 +2557,10 @@ struct VerilogBackend : public Backend {
log(" use 'defparam' statements instead of the Verilog-2001 syntax for\n");
log(" cell parameters.\n");
log("\n");
log(" -default_params\n");
log(" emit module parameter declarations from\n");
log(" parameter_default_values.\n");
log("\n");
log(" -blackboxes\n");
log(" usually modules with the 'blackbox' attribute are ignored. with\n");
log(" this option set only the modules with the 'blackbox' attribute\n");
@ -2571,6 +2598,7 @@ struct VerilogBackend : public Backend {
siminit = false;
simple_lhs = false;
noparallelcase = false;
default_params = false;
auto_prefix = "";
bool blackboxes = false;
@ -2631,6 +2659,10 @@ struct VerilogBackend : public Backend {
defparam = true;
continue;
}
if (arg == "-defaultparams") {
default_params = true;
continue;
}
if (arg == "-decimal") {
decimal = true;
continue;
@ -2682,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);

View File

@ -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 -o $@ $<
$(FAKETIME) dot -Tpdf -Gsize="8.5,11" -o $@ $<
%.pdf: %.tex
cd $(@D) && $(FAKETIME) pdflatex $(<F) --interaction=nonstopmode

View File

@ -154,6 +154,10 @@ to the following Verilog code template, where ``RST_EDGE`` is ``posedge`` if
``RST_LVL`` if ``1``, ``negedge`` otherwise, and ``SET_EDGE`` is ``posedge`` if
``SET_LVL`` if ``1``, ``negedge`` otherwise.
When both set and reset are active, the state and output is undefined. The Verilog
code model does not correspond to this due to limitations
of synthesizable Verilog.
.. code-block:: verilog
:force:
@ -187,6 +191,10 @@ types relate to the following Verilog code template, where ``RST_EDGE`` is
``posedge`` if ``RST_LVL`` if ``1``, ``negedge`` otherwise, and ``SET_EDGE`` is
``posedge`` if ``SET_LVL`` if ``1``, ``negedge`` otherwise.
When both set and reset are active, the state and output is undefined. The Verilog
code model does not correspond to this due to limitations
of synthesizable Verilog.
.. code-block:: verilog
:force:

View File

@ -78,6 +78,7 @@ D-type flip-flops with asynchronous set and reset are represented by `$dffsr`
cells. As the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition
they also have multi-bit ``SET`` and ``CLR`` input ports and the corresponding
polarity parameters, like `$sr` cells.
When both set and reset are active, the state and output is undefined.
D-type flip-flops with enable are represented by `$dffe`, `$adffe`, `$aldffe`,
`$dffsre`, `$sdffe`, and `$sdffce` cells, which are enhanced variants of `$dff`,

View File

@ -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;

View File

@ -24,19 +24,19 @@ struct FunctionalDummyBackend : public Backend {
// write node functions
for (auto node : ir)
*f << " assign " << id2cstr(node.name())
*f << " assign " << node.name().unescape()
<< " = " << node.to_string() << "\n";
*f << "\n";
// write outputs and next state
for (auto output : ir.outputs())
*f << " " << id2cstr(output->kind)
<< " " << id2cstr(output->name)
<< " = " << id2cstr(output->value().name()) << "\n";
*f << " " << output->kind.unescape()
<< " " << output->name.unescape()
<< " = " << output->value().name().unescape() << "\n";
for (auto state : ir.states())
*f << " " << id2cstr(state->kind)
<< " " << id2cstr(state->name)
<< " = " << id2cstr(state->next_value().name()) << "\n";
*f << " " << state->kind.unescape()
<< " " << state->name.unescape()
<< " = " << state->next_value().name().unescape() << "\n";
}
}
} FunctionalDummyBackend;

View File

@ -17,6 +17,7 @@ coarse:
opt_clean
memory_collect
opt -noff -keepdc -fast
sort
check:
stat

View File

@ -6,6 +6,7 @@ begin:
proc
flatten:
check
flatten
tribuf -logic
deminout

View File

@ -27,7 +27,7 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re
// count output lines for this module (needed only for summary output at the end)
int line_count = 0;
log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name));
log("Looking for stub wires in module %s:\n", module);
// For all ports on all cells
for (auto &cell_iter : module->cells_)
@ -74,11 +74,11 @@ static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool re
// report stub bits and/or stub wires, don't report single bits
// if called with report_bits set to false.
if (GetSize(stub_bits) == GetSize(sig)) {
log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name));
log(" found stub wire: %s\n", wire);
} else {
if (!report_bits)
continue;
log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name));
log(" found wire with stub bits: %s [", wire);
for (int bit : stub_bits)
log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit);
log("]\n");

View File

@ -5,8 +5,8 @@ import os
project = 'YosysHQ Yosys'
author = 'YosysHQ GmbH'
copyright ='2025 YosysHQ GmbH'
yosys_ver = "0.59"
copyright ='2026 YosysHQ GmbH'
yosys_ver = "0.65"
# select HTML theme
html_theme = 'furo-ys'

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -117,3 +117,32 @@ Result with fixed :file:`axis_master.v`:
Solving problem with 159144 variables and 441626 clauses..
SAT proof finished - no model found: SUCCESS!
Witness framework and per-property tracking
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When using AIGER-based formal verification flows (such as the ``abc`` engine in
SBY), Yosys provides infrastructure for tracking individual formal
properties through the verification pipeline.
The `rename -witness` pass assigns public names to all cells that participate in
the witness framework:
- Witness signal cells: `$anyconst`, `$anyseq`, `$anyinit`,
`$allconst`, `$allseq`
- Formal property cells: `$assert`, `$assume`, `$cover`, `$live`,
`$fair`, `$check`
These public names allow downstream tools to refer to individual properties by
their hierarchical path rather than by anonymous internal identifiers.
The `write_aiger -ywmap` option generates a map file for conversion to and from
Yosys witness traces, and also allows for mapping AIGER bad-state properties and
invariant constraints back to individual formal properties by name. This enables
features like per-property pass/fail reporting (e.g. ``abc pdr`` with
``--keep-going`` mode).
The `write_smt2` backend similarly uses the public witness names when emitting
SMT2 comments. Cells whose ``hdlname`` attribute contains the ``_witness_``
marker are treated as having private names for comment purposes, keeping solver
output clean.

View File

@ -355,6 +355,9 @@ from SystemVerilog:
design with `read_verilog`, all its packages are available to SystemVerilog
files being read into the same design afterwards.
- nested packages are currently not supported (i.e. calling ``import`` inside
a ``package`` .. ``endpackage`` block)
- typedefs are supported (including inside packages)
- type casts are currently not supported

View File

@ -1,57 +1,18 @@
Contributing to Yosys
=====================
.. note::
For information on making a pull request on github, refer to our
|CONTRIBUTING|_ file.
.. |CONTRIBUTING| replace:: :file:`CONTRIBUTING.md`
.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/blob/main/CONTRIBUTING.md
Coding Style
------------
Formatting of code
~~~~~~~~~~~~~~~~~~
- Yosys code is using tabs for indentation. Tabs are 8 characters.
- A continuation of a statement in the following line is indented by two
additional tabs.
- Lines are as long as you want them to be. A good rule of thumb is to break
lines at about column 150.
- Opening braces can be put on the same or next line as the statement opening
the block (if, switch, for, while, do). Put the opening brace on its own line
for larger blocks, especially blocks that contains blank lines.
- Otherwise stick to the `Linux Kernel Coding Style`_.
.. _Linux Kernel Coding Style: https://www.kernel.org/doc/Documentation/process/coding-style.rst
C++ Language
~~~~~~~~~~~~
Yosys is written in C++17.
In general Yosys uses ``int`` instead of ``size_t``. To avoid compiler warnings
for implicit type casts, always use ``GetSize(foobar)`` instead of
``foobar.size()``. (``GetSize()`` is defined in :file:`kernel/yosys.h`)
Use range-based for loops whenever applicable.
Reporting bugs
--------------
- use the `bug report template`_
We fix well-reported bugs the fastest. A good bug report is an issue on the `issue tracker`_
and includes the following information:
.. _bug report template: https://github.com/YosysHQ/yosys/issues/new?template=bug_report.yml
.. _`issue tracker`: https://github.com/YosysHQ/yosys/issues
- short title briefly describing the issue, e.g.
Title
~~~~~
briefly describe the issue, for example:
techmap of wide mux with undefined inputs raises error during synth_xilinx
@ -64,10 +25,20 @@ Reporting bugs
Reproduction Steps
~~~~~~~~~~~~~~~~~~
- ideally a code-block (starting and ending with triple backquotes) containing
the minimized design (Verilog or RTLIL), followed by a code-block containing
the minimized yosys script OR a command line call to yosys with
code-formatting (starting and ending with single backquotes)
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 :doc:`how-to guide for bugpoint </using_yosys/bugpoint>`.
The reproduction steps are ideally a code-block (starting and ending with
triple backquotes) containing
the minimized design (Verilog or RTLIL), followed by a code-block containing
the minimized yosys script OR a command line call to yosys with
code-formatting (starting and ending with single backquotes).
.. code-block:: markdown
@ -86,9 +57,9 @@ Reproduction Steps
`yosys -p ': minimum sequence of commands;' min.v`
- alternatively can provide a single code-block which includes the minimized
design as a "here document" followed by the sequence of commands which
reproduce the error
Alternatively, you can provide a single code-block which includes the minimized
design as a "here document" followed by the sequence of commands which
reproduce the error
+ see :doc:`/using_yosys/more_scripting/load_design` for more on heredocs.
@ -101,7 +72,9 @@ Reproduction Steps
# minimum sequence of commands
```
- any environment variables or command line options should also be mentioned
Don't forget to mention:
- any important environment variables or command line options
- if the problem occurs for a range of values/designs, what is that range
- if you're using an external tool, such as ``valgrind``, to detect the issue,
what version of that tool are you using and what options are you giving it
@ -115,46 +88,57 @@ Reproduction Steps
around Yosys such as OpenLane; you should instead minimize your input and
reproduction steps to just the Yosys part.
"Expected Behaviour"
~~~~~~~~~~~~~~~~~~~~
.. _MVCE: https://stackoverflow.com/help/minimal-reproducible-example
.. _how-to guide for bugpoint: https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html
- if you have a similar design/script that doesn't give the error, include it
here as a reference
- if the bug is that an error *should* be raised but isn't, are there any other
commands with similar error messages
"Actual Behaviour"
Expected Behaviour
~~~~~~~~~~~~~~~~~~
- any error messages go here
- any details relevant to the crash that were found with ``--trace`` or
``--debug`` flags
- if you identified the point of failure in the source code, you could mention
it here, or as a comment below
Describe what you'd expect to happen when we follow the reproduction steps
if the bug was fixed.
+ if possible, use a permalink to the source on GitHub
+ you can browse the source repository for a certain commit with the failure
If you have a similar design/script that doesn't give the error, include it
here as a reference. If the bug is that an error *should* be raised but isn't,
note if there are any other commands with similar error messages.
Actual Behaviour
~~~~~~~~~~~~~~~~
Describe what you actually see when you follow the reproduction steps.
This can include:
* any error messages
* any details relevant to the crash that were found with ``--trace`` or
``--debug`` flags
* the part of the source code that triggers the bug
* if possible, use a permalink to the source on GitHub
* you can browse the source repository for a certain commit with the failure
and open the source file, select the relevant lines (click on the line
number for the first relevant line, then while holding shift click on the
line number for the last relevant line), click on the ``...`` that appears
and select "Copy permalink"
+ should look something like
* should look something like
``https://github.com/YosysHQ/yosys/blob/<commit_hash>/path/to/file#L139-L147``
+ clicking on "Preview" should reveal a code block containing the lines of
* clicking on "Preview" should reveal a code block containing the lines of
source specified, with a link to the source file at the given commit
Additional details
Additional Details
~~~~~~~~~~~~~~~~~~
- once you have created the issue, any additional details can be added as a
comment on that issue
- could include any additional context as to what you were doing when you first
encountered the bug
- was this issue discovered through the use of a fuzzer
- if you've minimized the script, consider including the `bugpoint` script you
used, or the original script, e.g.
Anything else you think might be helpful or relevant when verifying or fixing
the bug.
Once you have created the issue, any additional details can be added as a
comment on that issue. You can include any additional context as to what you
were doing when you first encountered the bug.
If this issue discovered through the use of a fuzzer, ALWAYS declare that.
If you've minimized the script, consider including the `bugpoint` script you
used, or the original script, for example:
.. code-block:: markdown
@ -171,8 +155,257 @@ Additional details
Minimized from
`yosys -p ': original sequence of commands to produce error;' design.v`
- if you're able to, it may also help to share the original un-minimized design
+ if the design is too big for a comment, consider turning it into a `Gist`_
If possible, it may also help to share the original un-minimized design.
If the design is too big for a comment, consider turning it into a `Gist`_
.. _Gist: https://gist.github.com/
Contributing code
-----------------
Code that matters
~~~~~~~~~~~~~~~~~
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`_. Please, be as explicit and concrete
as possible when explaining the motivation for what you're building.
Additionally, if you do so on the forum first before you starting hacking
away at C++, you might solve your problem without writing a single line
of code!
PRs are considered for relevance, priority, and quality
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
Making sense
~~~~~~~~~~~~
Given enough effort, the behavior of any code can be figured out to any
desired extent. However, the author of the code is by far in the best
position to make this as easy as possible.
Yosys is a long-standing project and has accumulated a lot of C-style code
that's not written to be read, just written to run. We improve this bit
by bit when opportunities arise, but it is what it is.
New additions are expected to be a lot cleaner.
The purpose and behavior of the code changed should be described clearly.
Your change should contain exactly what it needs to match that description.
This means:
* nothing more than that - no dead code, no undocumented features
* nothing missing - if something is partially built, that's fine,
but you have to make that clear. For example, some passes
only support some types of cells
Here are some software engineering approaches that help:
* Use abstraction to model the problem and hide details
* Maximize the usage of types (structs over loose variables),
not necessarily in an object-oriented way
* Use functions, scopes, type aliases
* In new passes, make sure the logic behind how and why it works is actually provided
in coherent comments, and that variable and type naming is consistent with the terms
you use in the description.
* The logic of the implementation should be described in mathematical
or algorithm theory terms. Correctness, termination, computational complexity.
Make it clear if you're re-implementing a classic data structure for logic synthesis
or graph traversal etc.
* There's various ways of traversing the design with use-def indices (for getting
drivers and driven signals) available in Yosys. They have advantages and sometimes
disadvantages. Prefer not re-implementing these
* Prefer references over pointers, and smart pointers over raw pointers
* Aggressively deduplicate code. Within functions, within passes,
across passes, even against existing code
* Prefer declaring things ``const``
* Prefer range-based for loops over C-style
Common mistakes
~~~~~~~~~~~~~~~
* Deleting design objects invalidates iterators. Defer deletions or hold a copy
of the list of pointers to design objects
* Deleting wires can get sketchy and is intended to be done solely by
the ``opt_clean`` pass so just don't do it
* Iterating over an entire design and checking if things are selected is more
inefficient than using the ``selected_*`` methods
* Remember to call ``fixup_ports`` at the end if you're modifying module interfaces
Testing your change
~~~~~~~~~~~~~~~~~~~
Untested code can't be maintained. Inevitable codebase-wide changes
are likely to break anything untested. Tests also help reviewers understand
the purpose of the code change in practice.
Your code needs to come with tests. If it's a feature, a test that covers
representative examples of the added behavior. If it's a bug fix, it should
reproduce the original isolated bug. But in some situations, adding a test
isn't viable. If you can't provide a test, explain this decision.
Prefer writing unit tests (:file:`tests/unit`) for isolated tests to
the internals of more serious code changes, like those to the core of yosys,
or more algorithmic ones.
The rest of the test suite is mostly based on running Yosys on various Yosys
and Tcl scripts that manually call Yosys commands.
See :doc:`/yosys_internals/extending_yosys/test_suites` for more information
about how our test suite is structured.
The basic test writing approach is checking
for the presence of some kind of object or pattern with ``-assert-count`` in
:doc:`/using_yosys/more_scripting/selections`.
It's often best to use equivalence checking with ``equiv_opt -assert``
or similar to prove that the changes done to the design by a modified pass
preserve equivalence. But some code isn't meant to preserve equivalence.
Sometimes proving equivalence takes an impractically long time for larger
inputs. Also beware, the ``equiv_`` passes are a bit quirky and might even
have incorrect results in unusual situations.
.. Changes to core parts of Yosys or passes that are included in synthesis flows
.. can change runtime and memory usage - for the better or for worse. This strongly
.. depends on the design involved. Such risky changes should then be benchmarked
.. with various designs.
.. TODO Emil benchmarking
Coding style
~~~~~~~~~~~~
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
``foobar.size()``. (``GetSize()`` is defined in :file:`kernel/yosys.h`)
For auto formatting code, a :file:`.clang-format` file is present top-level.
Yosys code is using tabs for indentation. A tab is 8 characters wide,
but prefer not relying on it. A continuation of a statement
in the following line is indented by two additional tabs. Lines are
as long as you want them to be. A good rule of thumb is to break lines
at about column 150. Opening braces can be put on the same or next line
as the statement opening the block (if, switch, for, while, do).
Put the opening brace on its own line for larger blocks, especially
blocks that contains blank lines. Remove trailing whitespace on sight.
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
~~~~~~~~~
We don't have a strict commit message style.
Some style hints:
* Refactor and document existing code if you touch it,
but in separate commits from your functional changes
* Prefer smaller commits organized by good chunks. Git has a lot of features
like fixup commits, interactive rebase with autosquash
Reviewing PRs
-------------
Reviewing PRs is a totally valid form of external contributing to the project!
Who's the reviewer?
~~~~~~~~~~~~~~~~~~~
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
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
is our CODEOWNERS file in the git repository. What we're looking for in code
owners is activity and trust. For activity, if you're only interested in
a yosys pass for example for the time you spend writing a thesis, it might be
better to focus on writing good tests and docs in the PRs you submit rather than
to commit to code ownership and therefore to be responsible for fixing things
and reviewing other people's PRs at various unexpected points later. If you're
prolific in some part of the codebase and not a code owner, we still value your
experience and may tag you in PRs.
As a matter of fact, the purpose of code ownership is to avoid maintainer
burnout by removing orphaned parts of the codebase. If you become a code owner
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 implicit expectations of stability we aim to
respect within reason.
.. TODO this deserves its own section elsewhere I think? But it would be distracting elsewhere
Sometimes, multiple maintainers may add review comments. This is considered
healthy collaborative even if it might create disagreement at times. If
somebody is already reviewing a PR, others, even non-maintainers are free to
leave comments with extra observations and alternate perspectives in a
collaborative spirit.
How to review
~~~~~~~~~~~~~
First, read everything above about contributing. Those are the values you
should gently enforce as a reviewer. They're ordered by importance, but
explicitly, descriptions are more important than code, long-form comments
describing the design are more important than piecemeal comments, etc.
If a PR is poorly described, incomplete, tests are broken, or if the
author is not responding, please don't feel pressured to take over their
role by reverse engineering the code or fixing things for them, unless
there are good reasons to do so.
If a PR author submits LLM outputs they haven't understood themselves,
they will not be able to implement feedback. Take this into consideration
as well. We do not ban LLM code from the codebase, we ban bad code.
Reviewers may have diverse styles of communication while reviewing - one
may do one thorough review, another may prefer a back and forth with the
basics out the way before digging into the code. Generally, PRs may have
several requests for modifications and long discussions, but often
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 and compilers. Sanitizer builds are only
tested on the main branch.

View File

@ -230,8 +230,7 @@ Use ``log_error()`` to report a non-recoverable error:
.. code:: C++
if (design->modules.count(module->name) != 0)
log_error("A module with the name %s already exists!\n",
RTLIL::id2cstr(module->name));
log_error("A module with the name %s already exists!\n", module);
Use ``log_cmd_error()`` to report a recoverable error:

View File

@ -181,7 +181,7 @@ pointer ``f`` to the output file, or stdout if none is given.
For this minimal example all we are doing is printing out each node. The
``node.name()`` method returns an ``RTLIL::IdString``, which we convert for
printing with ``id2cstr()``. Then, to print the function of the node, we use
printing with ``unescape()``. Then, to print the function of the node, we use
``node.to_string()`` which gives us a string of the form ``function(args)``. The
``function`` part is the result of ``Functional::IR::fn_to_string(node.fn())``;
while ``args`` is the zero or more arguments passed to the function, most

View File

@ -8,7 +8,44 @@ Running the included test suite
The Yosys source comes with a test suite to avoid regressions and keep
everything working as expected. Tests can be run by calling ``make test`` from
the root Yosys directory.
the root Yosys directory. By default, this runs vanilla and unit tests.
Vanilla tests
~~~~~~~~~~~~~
These make up the majority of our testing coverage.
They can be run with ``make vanilla-test`` and are based on calls to
make subcommands (``make makefile-tests``) and shell scripts
(``make seed-tests`` and ``make abcopt-tests``). Both use ``run-test.sh``
files, but make-based tests only call ``tests/gen-tests-makefile.sh``
to generate a makefile appropriate for the given directory, so only
afterwards when make is invoked do the tests actually run.
Usually their structure looks something like this:
you write a .ys file that gets automatically run,
which runs a frontend like ``read_verilog`` or ``read_rtlil`` with
a relative path or a heredoc, then runs some commands including the command
under test, and then uses :doc:`/using_yosys/more_scripting/selections`
with ``-assert-count``. Usually it's unnecessary to "register" the test anywhere
as if it's being added to an existing directory, depending
on how the ``run-test.sh`` in that directory works.
Unit tests
~~~~~~~~~~
Running the unit tests requires the following additional packages:
.. tab:: Ubuntu
.. code:: console
sudo apt-get install libgtest-dev
.. tab:: macOS
No additional requirements.
Unit tests can be run with ``make unit-test``.
Functional tests
~~~~~~~~~~~~~~~~
@ -41,23 +78,6 @@ instructions <https://github.com/Z3Prover/z3>`_.
Then, set the :makevar:`ENABLE_FUNCTIONAL_TESTS` make variable when calling
``make test`` and the functional tests will be run as well.
Unit tests
~~~~~~~~~~
Running the unit tests requires the following additional packages:
.. tab:: Ubuntu
.. code:: console
sudo apt-get install libgtest-dev
.. tab:: macOS
No additional requirements.
Unit tests can be run with ``make unit-test``.
Docs tests
~~~~~~~~~~

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex
yosys -p '
read_verilog -formal demo.v

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex
yosys demo.ys
$TD_HOME/bin/td build.tcl

View File

@ -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

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -ex

View File

@ -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)

View File

@ -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

View File

@ -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}

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
export REV="de2i"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
iverilog -o presynth lfsr_updown_tb.v lfsr_updown.v &&\

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env sh
set -e
yosys run_yosys.ys
edif2ngd example.edif

View File

@ -37,7 +37,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/newcelltypes.h"
#include "aigerparse.h"
YOSYS_NAMESPACE_BEGIN
@ -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()
@ -286,10 +286,15 @@ end_of_header:
RTLIL::IdString escaped_s = stringf("\\%s", s);
RTLIL::Wire* wire;
if (c == 'i') wire = inputs[l1];
else if (c == 'l') wire = latches[l1];
else if (c == 'o') {
if (c == 'i') {
log_assert(l1 < inputs.size());
wire = inputs[l1];
} else if (c == 'l') {
log_assert(l1 < latches.size());
wire = latches[l1];
} else if (c == 'o') {
wire = module->wire(escaped_s);
log_assert(l1 < outputs.size());
if (wire) {
// Could have been renamed by a latch
module->swap_names(wire, outputs[l1]);
@ -297,9 +302,9 @@ end_of_header:
goto next;
}
wire = outputs[l1];
}
else if (c == 'b') wire = bad_properties[l1];
else log_abort();
} else if (c == 'b') {
wire = bad_properties[l1];
} else log_abort();
module->rename(wire, escaped_s);
}
@ -652,6 +657,9 @@ void AigerReader::parse_aiger_binary()
unsigned l1, l2, l3;
std::string line;
if (M != I + L + A)
log_error("Binary AIGER input is malformed: maximum variable index M is %u, but number of inputs, latches and AND gates adds up to %u.\n", M, I + L + A);
// Parse inputs
int digits = decimal_digits(I);
for (unsigned i = 1; i <= I; ++i) {
@ -813,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) {
@ -827,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);
@ -838,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) {
@ -858,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) {
@ -874,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);
@ -886,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) {
@ -904,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);
}

View File

@ -80,13 +80,13 @@ 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)
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);
@ -110,7 +110,8 @@ struct Xaiger2Frontend : public Frontend {
for (int i = 0; i < (int) O; i++) {
int po;
*f >> po;
log_assert(f->get() == '\n');
int c = f->get();
log_assert(c == '\n');
outputs.push_back(po);
}
@ -127,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",
@ -140,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)
@ -157,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", box->type.unescape());
if (box_seq >= (int) boxes.size()) {
boxes.resize(box_seq + 1);
@ -275,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");
}
@ -402,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",
@ -422,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",

View File

@ -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 = "|"; }
@ -993,6 +1004,8 @@ RTLIL::Const AstNode::asParaConst() const
RTLIL::Const val = asAttrConst();
if (is_signed)
val.flags |= RTLIL::CONST_FLAG_SIGNED;
if (is_unsized)
val.flags |= RTLIL::CONST_FLAG_UNSIZED;
return val;
}
@ -1531,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<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(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) {
@ -1571,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(), RTLIL::unescape_id(modname));
loadconfig();
process_and_replace_module(design, this, ast.get(), NULL);
return true;
@ -1593,7 +1606,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
RTLIL::Module *intfmodule = intf.second;
for (auto w : intfmodule->wires()){
auto wire = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(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));
@ -1666,7 +1679,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
bool has_interfaces = false;
for(auto &intf : interfaces) {
interf_info += log_id(intf.second->name);
interf_info += intf.second->name.unescape();
has_interfaces = true;
}
@ -1722,7 +1735,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
new_subcell->set_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);
}
}
@ -1766,7 +1779,10 @@ static std::string serialize_param_value(const RTLIL::Const &val) {
res.push_back('s');
if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL)
res.push_back('r');
res += stringf("%d", GetSize(val));
if (val.flags & RTLIL::ConstFlags::CONST_FLAG_UNSIZED)
res.push_back('u');
else
res += stringf("%d", GetSize(val));
res.push_back('\'');
res.append(val.as_string("?"));
return res;
@ -1860,7 +1876,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
} else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(loc, it->second.decode_string());
else
child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0);
child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0, (it->second.flags & RTLIL::CONST_FLAG_UNSIZED) != 0);
rewritten.insert(it->first);
}

View File

@ -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,

View File

@ -342,6 +342,9 @@ struct AST_INTERNAL::ProcessGenerator
// The most recently assigned $print or $check cell \PRIORITY.
int last_effect_priority;
// Track which signals have been assigned in current_case to avoid unnecessary removeSignalFromCaseTree calls
pool<RTLIL::SigBit> current_case_assigned_bits;
ProcessGenerator(std::unique_ptr<AstNode> a, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(std::move(a)), initSyncSignals(initSyncSignalsArg), last_effect_priority(0)
{
// rewrite lookahead references
@ -403,6 +406,18 @@ struct AST_INTERNAL::ProcessGenerator
if (GetSize(syncrule->signal) != 1)
always->input_error("Found posedge/negedge event on a signal that is not 1 bit wide!\n");
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
// Automatic (nosync) variables must not become flip-flops: remove
// them from clocked sync rules so that proc_dff does not infer
// an unnecessary register for a purely combinational temporary.
syncrule->actions.erase(
std::remove_if(syncrule->actions.begin(), syncrule->actions.end(),
[](const RTLIL::SigSig &ss) {
for (auto &chunk : ss.first.chunks())
if (chunk.wire && chunk.wire->get_bool_attribute(ID::nosync))
return true;
return false;
}),
syncrule->actions.end());
proc->syncs.push_back(syncrule);
}
if (proc->syncs.empty()) {
@ -418,6 +433,10 @@ struct AST_INTERNAL::ProcessGenerator
subst_rvalue_map = subst_lvalue_from.to_sigbit_dict(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
} else {
addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
// Track initial assignments
for (auto &bit : subst_lvalue_to)
if (bit.wire != NULL)
current_case_assigned_bits.insert(bit);
}
// process the AST
@ -545,14 +564,42 @@ struct AST_INTERNAL::ProcessGenerator
// e.g. when the last statement in the code "a = 23; if (b) a = 42; a = 0;" is processed this
// function is called to clean up the first two assignments as they are overwritten by
// the third assignment.
void removeSignalFromCaseTree(const RTLIL::SigSpec &pattern, RTLIL::CaseRule *cs)
void removeSignalFromCaseTree(const pool<RTLIL::SigBit> &pattern_bits, RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); it++)
it->first.remove2(pattern, &it->second);
// Optimization: check actions in reverse order and stop early if we've found all pattern bits
pool<RTLIL::SigBit> remaining_bits = pattern_bits;
for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) {
bool has_pattern = false;
for (auto &bit : it->first) {
if (bit.wire != NULL && remaining_bits.count(bit)) {
has_pattern = true;
remaining_bits.erase(bit);
}
}
if (has_pattern) {
it->first.remove2(pattern_bits, &it->second);
}
// Early exit if we've processed all bits in pattern
if (remaining_bits.empty())
break;
}
for (auto it = cs->switches.begin(); it != cs->switches.end(); it++)
for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
removeSignalFromCaseTree(pattern, *it2);
removeSignalFromCaseTree(pattern_bits, *it2);
}
void removeSignalFromCaseTree(const RTLIL::SigSpec &pattern, RTLIL::CaseRule *cs)
{
pool<RTLIL::SigBit> pattern_bits;
pattern_bits.reserve(pattern.size());
for (auto &bit : pattern)
if (bit.wire != NULL)
pattern_bits.insert(bit);
removeSignalFromCaseTree(pattern_bits, cs);
}
// add an assignment (aka "action") but split it up in chunks. this way huge assignments
@ -611,7 +658,23 @@ struct AST_INTERNAL::ProcessGenerator
subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]);
}
removeSignalFromCaseTree(lvalue, current_case);
// Check if any bits in lvalue have been assigned before in current_case
bool has_overlap = false;
for (auto &bit : lvalue) {
if (bit.wire != NULL && current_case_assigned_bits.count(bit)) {
has_overlap = true;
break;
}
}
if (has_overlap)
removeSignalFromCaseTree(lvalue, current_case);
// Track newly assigned bits
for (auto &bit : lvalue)
if (bit.wire != NULL)
current_case_assigned_bits.insert(bit);
remove_unwanted_lvalue_bits(lvalue, rvalue);
current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue));
}
@ -658,9 +721,15 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
pool<RTLIL::SigBit> backup_assigned_bits = std::move(current_case_assigned_bits);
current_case_assigned_bits.clear();
set_src_attr(current_case, child.get());
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
// Track temp assignments
for (auto &bit : this_case_eq_ltemp)
if (bit.wire != NULL)
current_case_assigned_bits.insert(bit);
for (auto& node : child->children) {
if (node->type == AST_DEFAULT)
default_case = current_case;
@ -674,6 +743,7 @@ struct AST_INTERNAL::ProcessGenerator
else
log_assert(current_case->compare.size() == 0);
current_case = backup_case;
current_case_assigned_bits = std::move(backup_assigned_bits);
subst_lvalue_map.restore();
subst_rvalue_map.restore();
@ -702,8 +772,24 @@ struct AST_INTERNAL::ProcessGenerator
subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
this_case_eq_lvalue.replace(subst_lvalue_map.stdmap());
removeSignalFromCaseTree(this_case_eq_lvalue, current_case);
// Check if any bits in lvalue have been assigned before in current_case
bool has_overlap = false;
for (auto &bit : this_case_eq_lvalue) {
if (bit.wire != NULL && current_case_assigned_bits.count(bit)) {
has_overlap = true;
break;
}
}
if (has_overlap)
removeSignalFromCaseTree(this_case_eq_lvalue, current_case);
addChunkActions(current_case->actions, this_case_eq_lvalue, this_case_eq_ltemp);
// Track newly assigned bits
for (auto &bit : this_case_eq_lvalue)
if (bit.wire != NULL)
current_case_assigned_bits.insert(bit);
}
break;
@ -712,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:
@ -844,6 +930,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::Cell *cell = current_module->addCell(cellname, ID($check));
set_src_attr(cell, ast);
cell->set_bool_attribute(ID(keep));
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first);
@ -1125,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:
@ -1737,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); }
@ -2084,8 +2183,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
check_unique_id(current_module, id, this, "cell");
RTLIL::Cell *cell = current_module->addCell(id, "");
set_src_attr(cell, this);
// Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
cell->set_bool_attribute(ID::module_not_derived);
for (auto it = children.begin(); it != children.end(); it++) {
auto* child = it->get();
@ -2100,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;
}
@ -2148,6 +2245,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
log_abort();
}
// Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass
if (cell->type.isPublic())
cell->set_bool_attribute(ID::module_not_derived);
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
input_error("Attribute `%s' with non-constant value.\n", attr.first);

View File

@ -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) {
@ -269,6 +274,100 @@ static int add_dimension(AstNode *node, AstNode *rnode)
node->input_error("Unpacked array in packed struct/union member %s\n", node->str);
}
// Check if node is an unexpanded array reference (AST_IDENTIFIER -> AST_MEMORY without indexing)
static bool is_unexpanded_array_ref(AstNode *node)
{
if (node->type != AST_IDENTIFIER)
return false;
if (node->id2ast == nullptr || node->id2ast->type != AST_MEMORY)
return false;
// No indexing children = whole array reference
return node->children.empty();
}
// Check if two memories have compatible unpacked dimensions for array assignment
static bool arrays_have_compatible_dims(AstNode *mem_a, AstNode *mem_b)
{
if (mem_a->unpacked_dimensions != mem_b->unpacked_dimensions)
return false;
for (int i = 0; i < mem_a->unpacked_dimensions; i++) {
if (mem_a->dimensions[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;
}
// 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<int> array_indices_from_position(AstNode *mem, const std::vector<int> &position)
{
int num_dims = mem->unpacked_dimensions;
log_assert(GetSize(position) == num_dims);
std::vector<int> indices(num_dims);
for (int d = 0; d < num_dims; d++) {
int low = mem->dimensions[d].range_right;
int high = low + mem->dimensions[d].range_width - 1;
indices[d] = mem->dimensions[d].range_swapped ? (low + position[d]) : (high - position[d]);
}
return indices;
}
// Generate all element positions for a multi-dimensional unpacked array and
// call callback once for each combination.
static void foreach_array_position(AstNode *mem, std::function<void(const std::vector<int>&)> callback)
{
int num_dims = mem->unpacked_dimensions;
if (num_dims == 0) {
callback({});
return;
}
std::vector<int> position(num_dims, 0);
std::vector<int> sizes(num_dims);
for (int d = 0; d < num_dims; d++)
sizes[d] = mem->dimensions[d].range_width;
// Iterate through all position combinations (rightmost dimension fastest).
while (true) {
callback(position);
int d = num_dims - 1;
while (d >= 0) {
position[d]++;
if (position[d] < sizes[d])
break;
position[d] = 0;
d--;
}
if (d < 0)
break;
}
}
static int size_packed_struct(AstNode *snode, int base_offset)
{
// Struct members will be laid out in the structure contiguously from left to right.
@ -879,7 +978,7 @@ static void check_auto_nosync(AstNode *node)
}
// remove the attributes we've "consumed"
for (const RTLIL::IdString &str : attrs_to_drop) {
for (RTLIL::IdString str : attrs_to_drop) {
auto it = node->attributes.find(str);
node->attributes.erase(it);
}
@ -1393,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);
@ -1653,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:
@ -2265,9 +2370,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
}
if (children[0]->type == AST_CONSTANT) {
if (width != int(children[0]->bits.size())) {
RTLIL::SigSpec sig(children[0]->bits);
sig.extend_u0(width, children[0]->is_signed);
children[0] = mkconst_bits(location, sig.as_const().to_bits(), is_signed);
RTLIL::Const val;
if (children[0]->is_unsized) {
val = children[0]->bitsAsUnsizedConst(width);
} else {
val = children[0]->bitsAsConst(width);
}
children[0] = mkconst_bits(location, val.to_bits(), is_signed);
fixup_hierarchy_flags();
}
children[0]->is_signed = is_signed;
@ -3141,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<AstNode>(location, AST_MEMRD, children[0]->children[0]->clone());
newNode->str = str;
newNode->id2ast = id2ast;
@ -3196,6 +3305,217 @@ skip_dynamic_range_lvalue_expansion:;
}
}
// 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()))
{
AstNode *lhs = children[0].get();
AstNode *rhs = children[1].get();
AstNode *lhs_mem = lhs->id2ast;
// Case 1: Direct array assignment (b = a)
bool is_direct_assign = is_unexpanded_array_ref(rhs);
// Case 2: Ternary array assignment (out = sel ? a : b)
bool is_ternary_assign = (rhs->type == AST_TERNARY &&
is_unexpanded_array_ref(rhs->children[1].get()) &&
is_unexpanded_array_ref(rhs->children[2].get()));
// 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;
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 indices to an array identifier clone.
auto add_indices_to_id = [&](std::unique_ptr<AstNode> id, const std::vector<int>& indices) {
int indexed_dims = GetSize(indices);
if (indexed_dims == 1) {
// Single dimension: use AST_RANGE
id->children.push_back(std::make_unique<AstNode>(location, AST_RANGE,
mkconst_int(location, indices[0], true)));
} else {
// Multiple dimensions: use AST_MULTIRANGE
auto multirange = std::make_unique<AstNode>(location, AST_MULTIRANGE);
for (int idx : indices) {
multirange->children.push_back(std::make_unique<AstNode>(location, AST_RANGE,
mkconst_int(location, idx, true)));
}
id->children.push_back(std::move(multirange));
}
id->integer = indexed_dims;
// Reset basic_prep so multirange gets resolved during subsequent simplify passes
id->basic_prep = false;
return id;
};
auto add_position_to_id = [&](std::unique_ptr<AstNode> id, AstNode *mem, const std::vector<int>& 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<void(AstNode*, int)> 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<int>& 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<int> 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<std::unique_ptr<AstNode>> assignments;
std::vector<std::unique_ptr<AstNode>> pattern_temp_assignments;
foreach_array_position(lhs_mem, [&](const std::vector<int>& position) {
auto lhs_idx = add_position_to_id(lhs->clone(), lhs_mem, position);
std::unique_ptr<AstNode> rhs_expr;
if (is_direct_assign) {
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_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<AstNode>(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<AstNode>(location, AST_WIRE,
std::make_unique<AstNode>(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<AstNode>(location, AST_IDENTIFIER);
tmp_id->str = wire_tmp->str;
pattern_temp_assignments.push_back(std::make_unique<AstNode>(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<AstNode>(location, type,
std::move(lhs_idx), std::move(rhs_expr));
assign->was_checked = true;
assignments.push_back(std::move(assign));
});
// For continuous assignments, add to module; for procedural, use block
if (type == AST_ASSIGN) {
// Add all but last to module
for (size_t i = 0; i + 1 < assignments.size(); i++)
current_ast_mod->children.push_back(std::move(assignments[i]));
// Last one replaces current node
newNode = std::move(assignments.back());
} else {
// Wrap in AST_BLOCK for procedural
newNode = std::make_unique<AstNode>(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));
}
goto apply_newNode;
}
}
// assignment with memory in left-hand side expression -> replace with memory write port
if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
@ -3203,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++);
@ -4454,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;
@ -4686,6 +5008,7 @@ void AstNode::expand_genblock(const std::string &prefix)
switch (child->type) {
case AST_WIRE:
case AST_AUTOWIRE:
case AST_MEMORY:
case AST_STRUCT:
case AST_UNION:
@ -4714,6 +5037,93 @@ void AstNode::expand_genblock(const std::string &prefix)
}
break;
case AST_IDENTIFIER:
if (!child->str.empty() && prefix.size() > 0) {
bool is_resolved = false;
std::string identifier_str = child->str;
if (current_ast_mod != nullptr && identifier_str.compare(0, current_ast_mod->str.size(), current_ast_mod->str) == 0) {
if (identifier_str.at(current_ast_mod->str.size()) == '.') {
identifier_str = '\\' + identifier_str.substr(current_ast_mod->str.size()+1, identifier_str.size());
}
}
// search starting in the innermost scope and then stepping outward
for (size_t ppos = prefix.size() - 1; ppos; --ppos) {
if (prefix.at(ppos) != '.') continue;
std::string new_prefix = prefix.substr(0, ppos + 1);
auto attempt_resolve = [&new_prefix](const std::string &ident) -> std::string {
std::string new_name = prefix_id(new_prefix, ident);
if (current_scope.count(new_name))
return new_name;
return {};
};
// attempt to resolve the full identifier
std::string resolved = attempt_resolve(identifier_str);
if (!resolved.empty()) {
is_resolved = true;
break;
}
// attempt to resolve hierarchical prefixes within the identifier,
// as the prefix could refer to a local scope which exists but
// hasn't yet been elaborated
for (size_t spos = identifier_str.size() - 1; spos; --spos) {
if (identifier_str.at(spos) != '.') continue;
resolved = attempt_resolve(identifier_str.substr(0, spos));
if (!resolved.empty()) {
is_resolved = true;
identifier_str = resolved + identifier_str.substr(spos);
ppos = 1; // break outer loop
break;
}
}
if (current_scope.count(identifier_str) == 0) {
AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
for (auto& node : current_scope_ast->children) {
switch (node->type) {
case AST_PARAMETER:
case AST_LOCALPARAM:
case AST_WIRE:
case AST_AUTOWIRE:
case AST_GENVAR:
case AST_MEMORY:
case AST_FUNCTION:
case AST_TASK:
case AST_DPI_FUNCTION:
if (prefix_id(new_prefix, identifier_str) == node->str) {
is_resolved = true;
current_scope[node->str] = node.get();
}
break;
case AST_ENUM:
current_scope[node->str] = node.get();
for (auto& enum_node : node->children) {
log_assert(enum_node->type==AST_ENUM_ITEM);
if (prefix_id(new_prefix, identifier_str) == enum_node->str) {
is_resolved = true;
current_scope[enum_node->str] = enum_node.get();
}
}
break;
default:
break;
}
}
}
}
if ((current_scope.count(identifier_str) == 0) && is_resolved == false) {
if (current_ast_mod == nullptr) {
input_error("Identifier `%s' is implicitly declared outside of a module.\n", child->str.c_str());
} else if (flag_autowire || identifier_str == "\\$global_clock") {
auto auto_wire = std::make_unique<AstNode>(child->location, AST_AUTOWIRE);
auto_wire->str = identifier_str;
children.push_back(std::move(auto_wire));
} else {
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", identifier_str.c_str());
}
}
}
break;
default:
break;
}
@ -4863,7 +5273,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &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)) {

View File

@ -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;
}
@ -245,7 +245,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (undef_wire != nullptr)
module->rename(undef_wire, stringf("$undef$%d", ++blif_maxnum));
autoidx = std::max(autoidx, blif_maxnum+1);
autoidx.ensure_at_least(blif_maxnum+1);
blif_maxnum = 0;
}
@ -470,6 +470,27 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
continue;
}
if (!strcmp(cmd, ".gateinit"))
{
char *p = strtok(NULL, " \t\r\n");
if (p == NULL)
goto error;
char *n = strtok(p, "=");
char *init = strtok(NULL, "=");
if (n == NULL || init == NULL)
goto error;
if (init[0] != '0' && init[0] != '1')
goto error;
if (blif_wire(n)->attributes.find(ID::init) == blif_wire(n)->attributes.end())
blif_wire(n)->attributes.emplace(ID::init, Const(init[0] == '1' ? 1 : 0, 1));
else
blif_wire(n)->attributes[ID::init] = Const(init[0] == '1' ? 1 : 0, 1);
continue;
}
if (!strcmp(cmd, ".names"))
{
char *p;
@ -608,6 +629,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
goto try_next_value;
}
}
log_assert(i < lutptr->size());
lutptr->set(i, !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1);
try_next_value:;
}

View File

@ -295,13 +295,16 @@ 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);
if (node->data_dict.count("attributes"))
json_parse_attr_param(module->attributes, node->data_dict.at("attributes"));
if (node->data_dict.count("parameter_default_values"))
json_parse_attr_param(module->parameter_default_values, node->data_dict.at("parameter_default_values"));
dict<int, SigBit> signal_bits;
if (node->data_dict.count("ports"))
@ -317,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);
@ -367,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;
@ -387,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;
@ -402,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);
}
}
@ -422,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);
@ -465,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;
@ -476,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"))
@ -497,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)
{
@ -525,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;
@ -544,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;
@ -553,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);
}
@ -584,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;

View File

@ -20,6 +20,7 @@
#include "passes/techmap/libparse.h"
#include "kernel/register.h"
#include "kernel/log.h"
#include <array>
YOSYS_NAMESPACE_BEGIN
@ -40,14 +41,14 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++;
if (id_len == 0)
log_error("Expected identifier at `%s'.\n", expr);
log_error("Expected identifier at `%s' in %s.\n", expr, module);
if (id_len == 1 && (*expr == '0' || *expr == '1'))
return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1;
std::string id = RTLIL::escape_id(std::string(expr, id_len));
if (!module->wires_.count(id))
log_error("Can't resolve wire name %s.\n", RTLIL::unescape_id(id));
log_error("Can't resolve wire name %s in %s.\n", RTLIL::unescape_id(id), module);
expr += id_len;
return module->wires_.at(id);
@ -174,7 +175,7 @@ static RTLIL::SigSpec parse_func_expr(RTLIL::Module *module, const char *expr)
#endif
if (stack.size() != 1 || stack.back().type != 3)
log_error("Parser error in function expr `%s'.\n", orig_expr);
log_error("Parser error in function expr `%s'in %s.\n", orig_expr, module);
return stack.back().sig;
}
@ -191,14 +192,29 @@ static RTLIL::SigSpec create_tristate(RTLIL::Module *module, RTLIL::SigSpec func
return cell->getPort(ID::Y);
}
static void create_latch_ff_wires(RTLIL::Module *module, const LibertyAst *node)
{
module->addWire(RTLIL::escape_id(node->args.at(0)));
module->addWire(RTLIL::escape_id(node->args.at(1)));
}
static std::pair<RTLIL::SigSpec, RTLIL::SigSpec> find_latch_ff_wires(RTLIL::Module *module, const LibertyAst *node)
{
auto* iq_wire = module->wire(RTLIL::escape_id(node->args.at(0)));
auto* iqn_wire = module->wire(RTLIL::escape_id(node->args.at(1)));
log_assert(iq_wire && iqn_wire);
return std::make_pair(iq_wire, iqn_wire);
}
static void create_ff(RTLIL::Module *module, const LibertyAst *node)
{
RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0))));
RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
auto [iq_sig, iqn_sig] = find_latch_ff_wires(module, node);
RTLIL::SigSpec clk_sig, data_sig, clear_sig, preset_sig;
bool clk_polarity = true, clear_polarity = true, preset_polarity = true;
const std::string name = module->name.unescape();
std::optional<char> clear_preset_var1;
std::optional<char> clear_preset_var2;
for (auto child : node->children) {
if (child->id == "clocked_on")
clk_sig = parse_func_expr(module, child->value.c_str());
@ -208,10 +224,18 @@ static void create_ff(RTLIL::Module *module, const LibertyAst *node)
clear_sig = parse_func_expr(module, child->value.c_str());
if (child->id == "preset")
preset_sig = parse_func_expr(module, child->value.c_str());
for (auto& [id, var] : {pair{"clear_preset_var1", &clear_preset_var1}, {"clear_preset_var2", &clear_preset_var2}})
if (child->id == id) {
if (child->value.size() != 1)
log_error("Unexpected length of clear_preset_var* value %s in FF cell %s\n", child->value, name);
*var = child->value[0];
}
}
if (clk_sig.size() == 0 || data_sig.size() == 0)
log_error("FF cell %s has no next_state and/or clocked_on attribute.\n", log_id(module->name));
log_error("FF cell %s has no next_state and/or clocked_on attribute.\n", name);
for (bool rerun_invert_rollback = true; rerun_invert_rollback;)
{
@ -236,43 +260,69 @@ static void create_ff(RTLIL::Module *module, const LibertyAst *node)
}
}
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_));
cell->setPort(ID::A, iq_sig);
cell->setPort(ID::Y, iqn_sig);
for (auto& [out_sig, cp_var, neg] : {tuple{iq_sig, clear_preset_var1, false}, {iqn_sig, clear_preset_var2, true}}) {
SigSpec q_sig = out_sig;
if (neg) {
q_sig = module->addWire(NEW_ID, out_sig.as_wire());
module->addNotGate(NEW_ID, q_sig, out_sig);
}
cell = module->addCell(NEW_ID, "");
cell->setPort(ID::D, data_sig);
cell->setPort(ID::Q, iq_sig);
cell->setPort(ID::C, clk_sig);
RTLIL::Cell* cell = module->addCell(NEW_ID, "");
cell->setPort(ID::D, data_sig);
cell->setPort(ID::Q, q_sig);
cell->setPort(ID::C, clk_sig);
if (clear_sig.size() == 0 && preset_sig.size() == 0) {
cell->type = stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N');
if (clear_sig.size() == 0 && preset_sig.size() == 0) {
cell->type = stringf("$_DFF_%c_", clk_polarity ? 'P' : 'N');
}
if (clear_sig.size() == 1 && preset_sig.size() == 0) {
cell->type = stringf("$_DFF_%c%c0_", clk_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N');
cell->setPort(ID::R, clear_sig);
}
if (clear_sig.size() == 0 && preset_sig.size() == 1) {
cell->type = stringf("$_DFF_%c%c1_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N');
cell->setPort(ID::R, preset_sig);
}
if (clear_sig.size() == 1 && preset_sig.size() == 1) {
cell->type = stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N');
SigBit s_sig = preset_sig;
SigBit r_sig = clear_sig;
if (cp_var && *cp_var != 'X') {
// Either set or reset dominates
bool set_dominates;
if (*cp_var == 'L') {
set_dominates = neg;
} else if (*cp_var == 'H') {
set_dominates = !neg;
} else {
log_error("FF cell %s has unsupported clear&preset behavior \'%c\'.\n", name, *cp_var);
}
log_debug("cell %s variable %d cp_var %c set dominates? %d\n", name, (int)neg + 1, *cp_var, set_dominates);
// S&R priority is well-defined now
if (set_dominates) {
r_sig = module->AndnotGate(NEW_ID, r_sig, s_sig);
} else {
s_sig = module->AndnotGate(NEW_ID, s_sig, r_sig);
}
} else {
log_debug("cell %s variable %d undef c&p behavior\n", name, (int)neg + 1);
}
cell->setPort(ID::S, s_sig);
cell->setPort(ID::R, r_sig);
}
log_assert(!cell->type.empty());
}
if (clear_sig.size() == 1 && preset_sig.size() == 0) {
cell->type = stringf("$_DFF_%c%c0_", clk_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N');
cell->setPort(ID::R, clear_sig);
}
if (clear_sig.size() == 0 && preset_sig.size() == 1) {
cell->type = stringf("$_DFF_%c%c1_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N');
cell->setPort(ID::R, preset_sig);
}
if (clear_sig.size() == 1 && preset_sig.size() == 1) {
cell->type = stringf("$_DFFSR_%c%c%c_", clk_polarity ? 'P' : 'N', preset_polarity ? 'P' : 'N', clear_polarity ? 'P' : 'N');
cell->setPort(ID::S, preset_sig);
cell->setPort(ID::R, clear_sig);
}
log_assert(!cell->type.empty());
}
static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool flag_ignore_miss_data_latch)
{
RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0))));
RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
auto [iq_sig, iqn_sig] = find_latch_ff_wires(module, node);
RTLIL::SigSpec enable_sig, data_sig, clear_sig, preset_sig;
bool enable_polarity = true, clear_polarity = true, preset_polarity = true;
@ -289,9 +339,9 @@ static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool fla
if (enable_sig.size() == 0 || data_sig.size() == 0) {
if (!flag_ignore_miss_data_latch)
log_error("Latch cell %s has no data_in and/or enable attribute.\n", log_id(module->name));
log_error("Latch cell %s has no data_in and/or enable attribute.\n", module);
else
log("Ignored latch cell %s with no data_in and/or enable attribute.\n", log_id(module->name));
log("Ignored latch cell %s with no data_in and/or enable attribute.\n", module);
return false;
}
@ -582,9 +632,9 @@ struct LibertyFrontend : public Frontend {
{
if (!flag_ignore_miss_dir)
{
log_error("Missing or invalid direction for pin %s on cell %s.\n", node->args.at(0), log_id(module->name));
log_error("Missing or invalid direction for pin %s on cell %s.\n", node->args.at(0), module);
} else {
log("Ignoring cell %s with missing or invalid direction for pin %s.\n", log_id(module->name), node->args.at(0));
log("Ignoring cell %s with missing or invalid direction for pin %s.\n", module, node->args.at(0));
delete module;
goto skip_cell;
}
@ -596,13 +646,13 @@ struct LibertyFrontend : public Frontend {
if (node->id == "bus" && node->args.size() == 1)
{
if (flag_ignore_buses) {
log("Ignoring cell %s with a bus interface %s.\n", log_id(module->name), node->args.at(0));
log("Ignoring cell %s with a bus interface %s.\n", module, node->args.at(0));
delete module;
goto skip_cell;
}
if (!flag_lib)
log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", log_id(cell_name));
log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", RTLIL::unescape_id(cell_name));
const LibertyAst *dir = node->find("direction");
@ -613,7 +663,7 @@ struct LibertyFrontend : public Frontend {
}
if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal"))
log_error("Missing or invalid direction for bus %s on cell %s.\n", node->args.at(0), log_id(module->name));
log_error("Missing or invalid direction for bus %s on cell %s.\n", node->args.at(0), module);
simple_comb_cell = false;
@ -624,7 +674,7 @@ struct LibertyFrontend : public Frontend {
if (!bus_type_node || !type_map.count(bus_type_node->value))
log_error("Unknown or unsupported type for bus interface %s on cell %s.\n",
node->args.at(0).c_str(), log_id(cell_name));
node->args.at(0).c_str(), RTLIL::unescape_id(cell_name));
int bus_type_width = std::get<0>(type_map.at(bus_type_node->value));
int bus_type_offset = std::get<1>(type_map.at(bus_type_node->value));
@ -646,6 +696,13 @@ struct LibertyFrontend : public Frontend {
{
// some liberty files do not put ff/latch at the beginning of a cell
// try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes
// but first, in case of balloon retention cells, we need all ff/latch output wires
// defined before we add ff/latch cells
for (auto node : cell->children)
{
if ((node->id == "ff" && node->args.size() == 2) || (node->id == "latch" && node->args.size() == 2))
create_latch_ff_wires(module, node);
}
for (auto node : cell->children)
{
if (node->id == "ff" && node->args.size() == 2)
@ -701,9 +758,9 @@ struct LibertyFrontend : public Frontend {
if (dir->value != "inout") { // allow inout with missing function, can be used for power pins
if (!flag_ignore_miss_func)
{
log_error("Missing function on output %s of cell %s.\n", log_id(wire->name), log_id(module->name));
log_error("Missing function on output %s of cell %s.\n", wire, module);
} else {
log("Ignoring cell %s with missing function on output %s.\n", log_id(module->name), log_id(wire->name));
log("Ignoring cell %s with missing function on output %s.\n", module, wire);
delete module;
goto skip_cell;
}
@ -757,13 +814,13 @@ struct LibertyFrontend : public Frontend {
if (design->has(cell_name)) {
Module *existing_mod = design->module(cell_name);
if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
log_error("Re-definition of cell/module %s!\n", log_id(cell_name));
log_error("Re-definition of cell/module %s!\n", RTLIL::unescape_id(cell_name));
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", log_id(cell_name));
log("Ignoring re-definition of module %s.\n", RTLIL::unescape_id(cell_name));
delete module;
goto skip_cell;
} else {
log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", log_id(cell_name));
log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", RTLIL::unescape_id(cell_name));
design->remove(existing_mod);
}
}
@ -780,3 +837,4 @@ skip_cell:;
YOSYS_NAMESPACE_END

View File

@ -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;

View File

@ -40,6 +40,7 @@ struct RTLILFrontendWorker {
bool flag_nooverwrite = false;
bool flag_overwrite = false;
bool flag_lib = false;
bool flag_legalize = false;
int line_num;
std::string line_buf;
@ -285,6 +286,7 @@ struct RTLILFrontendWorker {
if (width > MAX_CONST_WIDTH)
error("Constant width %lld out of range before `%s`.", width, error_token());
bits.reserve(width);
int start_idx = idx;
while (true) {
RTLIL::State bit;
switch (line[idx]) {
@ -299,8 +301,9 @@ struct RTLILFrontendWorker {
bits.push_back(bit);
++idx;
}
done:
std::reverse(bits.begin(), bits.end());
done:
if (start_idx < idx)
std::reverse(bits.begin(), bits.end());
if (GetSize(bits) > width)
bits.resize(width);
@ -322,6 +325,17 @@ struct RTLILFrontendWorker {
return val;
}
RTLIL::Wire *legalize_wire(RTLIL::IdString id)
{
int wires_size = current_module->wires_size();
if (wires_size == 0)
error("No wires found for legalization");
int hash = hash_ops<RTLIL::IdString>::hash(id).yield();
RTLIL::Wire *wire = current_module->wire_at(abs(hash % wires_size));
log("Legalizing wire `%s' to `%s'.\n", id.unescape(), wire->name.unescape());
return wire;
}
RTLIL::SigSpec parse_sigspec()
{
RTLIL::SigSpec sig;
@ -339,8 +353,12 @@ struct RTLILFrontendWorker {
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
RTLIL::Wire *wire = current_module->wire(*id);
if (wire == nullptr)
error("Wire `%s' not found.", *id);
if (wire == nullptr) {
if (flag_legalize)
wire = legalize_wire(*id);
else
error("Wire `%s' not found.", *id);
}
sig = RTLIL::SigSpec(wire);
} else {
sig = RTLIL::SigSpec(parse_const());
@ -349,17 +367,44 @@ struct RTLILFrontendWorker {
while (try_parse_char('[')) {
int left = parse_integer();
if (left >= sig.size() || left < 0)
error("bit index %d out of range", left);
if (left >= sig.size() || left < 0) {
if (flag_legalize) {
int legalized;
if (sig.size() == 0)
legalized = 0;
else
legalized = std::max(0, std::min(left, sig.size() - 1));
log("Legalizing bit index %d to %d.\n", left, legalized);
left = legalized;
} else {
error("bit index %d out of range", left);
}
}
if (try_parse_char(':')) {
int right = parse_integer();
if (right < 0)
error("bit index %d out of range", right);
if (left < right)
error("invalid slice [%d:%d]", left, right);
sig = sig.extract(right, left-right+1);
if (right < 0) {
if (flag_legalize) {
log("Legalizing bit index %d to %d.\n", right, 0);
right = 0;
} else
error("bit index %d out of range", right);
}
if (left < right) {
if (flag_legalize) {
log("Legalizing bit index %d to %d.\n", left, right);
left = right;
} else
error("invalid slice [%d:%d]", left, right);
}
if (flag_legalize && left >= sig.size())
log("Legalizing slice %d:%d by igoring it\n", left, right);
else
sig = sig.extract(right, left - right + 1);
} else {
sig = sig.extract(left);
if (flag_legalize && left >= sig.size())
log("Legalizing slice %d by igoring it\n", left);
else
sig = sig.extract(left);
}
expect_char(']');
}
@ -476,8 +521,14 @@ struct RTLILFrontendWorker {
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
if (current_module->wire(*id) != nullptr)
error("RTLIL error: redefinition of wire %s.", *id);
if (current_module->wire(*id) != nullptr) {
if (flag_legalize) {
log("Legalizing redefinition of wire %s.\n", *id);
pool<RTLIL::Wire*> wires = {current_module->wire(*id)};
current_module->remove(wires);
} else
error("RTLIL error: redefinition of wire %s.", *id);
}
wire = current_module->addWire(std::move(*id));
break;
}
@ -528,8 +579,13 @@ struct RTLILFrontendWorker {
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
if (current_module->memories.count(*id) != 0)
error("RTLIL error: redefinition of memory %s.", *id);
if (current_module->memories.count(*id) != 0) {
if (flag_legalize) {
log("Legalizing redefinition of memory %s.\n", *id);
current_module->remove(current_module->memories.at(*id));
} else
error("RTLIL error: redefinition of memory %s.", *id);
}
memory->name = std::move(*id);
break;
}
@ -551,14 +607,36 @@ struct RTLILFrontendWorker {
expect_eol();
}
void legalize_width_parameter(RTLIL::Cell *cell, RTLIL::IdString port_name)
{
std::string width_param_name = port_name.str() + "_WIDTH";
if (cell->parameters.count(width_param_name) == 0)
return;
RTLIL::Const &param = cell->parameters.at(width_param_name);
if (param.as_int() != 0)
return;
cell->parameters[width_param_name] = RTLIL::Const(cell->getPort(port_name).size());
}
void parse_cell()
{
RTLIL::IdString cell_type = parse_id();
RTLIL::IdString cell_name = parse_id();
expect_eol();
if (current_module->cell(cell_name) != nullptr)
error("RTLIL error: redefinition of cell %s.", cell_name);
if (current_module->cell(cell_name) != nullptr) {
if (flag_legalize) {
RTLIL::IdString new_name;
int suffix = 1;
do {
new_name = RTLIL::IdString(cell_name.str() + "_" + std::to_string(suffix));
++suffix;
} while (current_module->cell(new_name) != nullptr);
log("Legalizing redefinition of cell %s by renaming to %s.\n", cell_name, new_name);
cell_name = new_name;
} else
error("RTLIL error: redefinition of cell %s.", cell_name);
}
RTLIL::Cell *cell = current_module->addCell(cell_name, cell_type);
cell->attributes = std::move(attrbuf);
@ -567,10 +645,13 @@ struct RTLILFrontendWorker {
if (try_parse_keyword("parameter")) {
bool is_signed = false;
bool is_real = false;
bool is_unsized = false;
if (try_parse_keyword("signed")) {
is_signed = true;
} else if (try_parse_keyword("real")) {
is_real = true;
} else if (try_parse_keyword("unsized")) {
is_unsized = true;
}
RTLIL::IdString param_name = parse_id();
RTLIL::Const val = parse_const();
@ -578,13 +659,21 @@ struct RTLILFrontendWorker {
val.flags |= RTLIL::CONST_FLAG_SIGNED;
if (is_real)
val.flags |= RTLIL::CONST_FLAG_REAL;
if (is_unsized)
val.flags |= RTLIL::CONST_FLAG_UNSIZED;
cell->parameters.insert({std::move(param_name), std::move(val)});
expect_eol();
} else if (try_parse_keyword("connect")) {
RTLIL::IdString port_name = parse_id();
if (cell->hasPort(port_name))
error("RTLIL error: redefinition of cell port %s.", port_name);
if (cell->hasPort(port_name)) {
if (flag_legalize)
log("Legalizing redefinition of cell port %s.", port_name);
else
error("RTLIL error: redefinition of cell port %s.", port_name);
}
cell->setPort(std::move(port_name), parse_sigspec());
if (flag_legalize)
legalize_width_parameter(cell, port_name);
expect_eol();
} else if (try_parse_keyword("end")) {
expect_eol();
@ -601,6 +690,11 @@ struct RTLILFrontendWorker {
error("dangling attribute");
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
if (flag_legalize) {
int min_size = std::min(s1.size(), s2.size());
s1 = s1.extract(0, min_size);
s2 = s2.extract(0, min_size);
}
current_module->connect(std::move(s1), std::move(s2));
expect_eol();
}
@ -677,8 +771,13 @@ struct RTLILFrontendWorker {
RTLIL::IdString proc_name = parse_id();
expect_eol();
if (current_module->processes.count(proc_name) != 0)
error("RTLIL error: redefinition of process %s.", proc_name);
if (current_module->processes.count(proc_name) != 0) {
if (flag_legalize) {
log("Legalizing redefinition of process %s.\n", proc_name);
current_module->remove(current_module->processes.at(proc_name));
} else
error("RTLIL error: redefinition of process %s.", proc_name);
}
RTLIL::Process *proc = current_module->addProcess(std::move(proc_name));
proc->attributes = std::move(attrbuf);
@ -799,6 +898,11 @@ struct RTLILFrontend : public Frontend {
log(" -lib\n");
log(" only create empty blackbox modules\n");
log("\n");
log(" -legalize\n");
log(" prevent semantic errors (e.g. reference to unknown wire, redefinition of wire/cell)\n");
log(" by deterministically rewriting the input into something valid. Useful when using\n");
log(" fuzzing to generate random but valid RTLIL.\n");
log("\n");
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
@ -823,6 +927,10 @@ struct RTLILFrontend : public Frontend {
worker.flag_lib = true;
continue;
}
if (arg == "-legalize") {
worker.flag_legalize = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);

View File

@ -1392,13 +1392,13 @@ void VerificImporter::merge_past_ffs_clock(pool<RTLIL::Cell*> &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];
@ -1492,10 +1492,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
design->add(module);
if (is_blackbox(nl)) {
log("Importing blackbox module %s.\n", RTLIL::id2cstr(module->name));
log("Importing blackbox module %s.\n", module);
module->set_bool_attribute(ID::blackbox);
} else {
log("Importing module %s.\n", RTLIL::id2cstr(module->name));
log("Importing module %s.\n", module);
}
import_attributes(module->attributes, nl, nl);
if (module->name.isPublic())
@ -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);
}
}
@ -3114,9 +3114,11 @@ struct VerificPass : public Pass {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
log(" verific {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv} <verilog-file>..\n");
log(" verific {-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|\n");
log(" -sv2017|-sv} <verilog-file>..\n");
log("\n");
log("Load the specified Verilog/SystemVerilog files into Verific.\n");
log("Note that -sv option will use latest supported SystemVerilog standard.\n");
log("\n");
log("All files specified in one call to this command are one compilation unit.\n");
log("Files passed to different calls to this command are treated as belonging to\n");
@ -3161,7 +3163,10 @@ struct VerificPass : public Pass {
#endif
#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
log(" verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|\n");
log(" -sv2012|-sv|-formal] <command-file>\n");
#ifdef VERIFIC_VHDL_SUPPORT
log(" -vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl2019|-vhdl|\n");
#endif
log(" -sv2012|-sv2017|-sv|-formal] <command-file>\n");
log("\n");
log("Load and execute the specified command file.\n");
log("Override verilog parsing mode can be set.\n");
@ -3696,6 +3701,9 @@ struct VerificPass : public Pass {
if (GetSize(args) > argidx && (args[argidx] == "-f" || args[argidx] == "-F"))
{
unsigned verilog_mode = veri_file::UNDEFINED;
#ifdef VERIFIC_VHDL_SUPPORT
unsigned vhdl_mode = vhdl_file::UNDEFINED;
#endif
bool is_formal = false;
const char* filename = nullptr;
@ -3714,10 +3722,38 @@ struct VerificPass : public Pass {
} else if (args[argidx] == "-sv2009") {
verilog_mode = veri_file::SYSTEM_VERILOG_2009;
continue;
} else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal") {
} else if (args[argidx] == "-sv2012") {
verilog_mode = veri_file::SYSTEM_VERILOG_2012;
continue;
} else if (args[argidx] == "-sv2017") {
verilog_mode = veri_file::SYSTEM_VERILOG_2017;
continue;
} else if (args[argidx] == "-sv" || args[argidx] == "-formal") {
verilog_mode = veri_file::SYSTEM_VERILOG;
if (args[argidx] == "-formal") is_formal = true;
continue;
#ifdef VERIFIC_VHDL_SUPPORT
} else if (args[argidx] == "-vhdl87") {
vhdl_mode = vhdl_file::VHDL_87;
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1987").c_str());
continue;
} else if (args[argidx] == "-vhdl93") {
vhdl_mode = vhdl_file::VHDL_93;
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str());
continue;
} else if (args[argidx] == "-vhdl2k") {
vhdl_mode = vhdl_file::VHDL_2K;
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1993").c_str());
continue;
} else if (args[argidx] == "-vhdl2019") {
vhdl_mode = vhdl_file::VHDL_2019;
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2019").c_str());
continue;
} else if (args[argidx] == "-vhdl2008" || args[argidx] == "-vhdl") {
vhdl_mode = vhdl_file::VHDL_2008;
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2008").c_str());
continue;
#endif
} else if (args[argidx].compare(0, 1, "-") == 0) {
cmd_error(args, argidx, "unknown option");
goto check_error;
@ -3742,10 +3778,36 @@ struct VerificPass : public Pass {
veri_file::DefineMacro("VERIFIC");
veri_file::DefineMacro(is_formal ? "FORMAL" : "SYNTHESIS");
#ifdef VERIFIC_VHDL_SUPPORT
if (vhdl_mode == vhdl_file::UNDEFINED) {
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_2008").c_str());
vhdl_mode = vhdl_file::VHDL_2008;
}
int i;
Array *file_names_sv = new Array(POINTER_HASH);
FOREACH_ARRAY_ITEM(file_names, i, filename) {
std::string filename_str = filename;
if ((filename_str.substr(filename_str.find_last_of(".") + 1) == "vhd") ||
(filename_str.substr(filename_str.find_last_of(".") + 1) == "vhdl")) {
if (!vhdl_file::Analyze(filename, work.c_str(), vhdl_mode)) {
verific_error_msg.clear();
log_cmd_error("Reading VHDL sources failed.\n");
}
} else {
file_names_sv->Insert(strdup(filename));
}
}
if (!veri_file::AnalyzeMultipleFiles(file_names_sv, analysis_mode, work.c_str(), veri_file::MFCU)) {
verific_error_msg.clear();
log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n");
}
delete file_names_sv;
#else
if (!veri_file::AnalyzeMultipleFiles(file_names, analysis_mode, work.c_str(), veri_file::MFCU)) {
verific_error_msg.clear();
log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n");
}
#endif
delete file_names;
verific_import_pending = true;
@ -3753,7 +3815,8 @@ struct VerificPass : public Pass {
}
if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" ||
args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal"))
args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv2017" || args[argidx] == "-sv" ||
args[argidx] == "-formal"))
{
Array file_names;
unsigned verilog_mode;
@ -3766,7 +3829,11 @@ struct VerificPass : public Pass {
verilog_mode = veri_file::SYSTEM_VERILOG_2005;
else if (args[argidx] == "-sv2009")
verilog_mode = veri_file::SYSTEM_VERILOG_2009;
else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal")
else if (args[argidx] == "-sv2012")
verilog_mode = veri_file::SYSTEM_VERILOG_2012;
else if (args[argidx] == "-sv2017")
verilog_mode = veri_file::SYSTEM_VERILOG_2017;
else if (args[argidx] == "-sv" || args[argidx] == "-formal")
verilog_mode = veri_file::SYSTEM_VERILOG;
else
log_abort();

View File

@ -1846,7 +1846,10 @@ struct VerificSvaImporter
if (mode_assume) c = module->addAssume(root_name, sig_a_q, sig_en_q);
if (mode_cover) c = module->addCover(root_name, sig_a_q, sig_en_q);
if (c) importer->import_attributes(c->attributes, root);
if (c) {
c->set_bool_attribute(ID(keep));
importer->import_attributes(c->attributes, root);
}
}
}
catch (ParserErrorException)

View File

@ -500,7 +500,6 @@ struct VerilogFrontend : public Frontend {
log("Parsing %s%s input from `%s' to AST representation.\n",
parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
log("verilog frontend filename %s\n", filename.c_str());
if (flag_relative_share) {
auto share_path = proc_share_dirname();
if (filename.substr(0, share_path.length()) == share_path)

View File

@ -84,7 +84,7 @@
int current_function_or_task_port_id;
std::vector<char> case_type_stack;
bool do_not_require_port_stubs;
bool current_wire_rand, current_wire_const;
bool current_wire_rand, current_wire_const, current_wire_automatic;
bool current_modport_input, current_modport_output;
bool default_nettype_wire = true;
std::istream* lexin;
@ -546,7 +546,7 @@
%token TOK_z "'z'"
%type <ast_t> range range_or_multirange non_opt_range non_opt_multirange
%type <ast_t> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <ast_t> wire_type expr basic_expr concat_list assignment_pattern_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <string_t> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%type <string_t> type_name
%type <ast_t> opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type
@ -958,14 +958,18 @@ delay:
non_opt_delay | %empty;
io_wire_type:
{ extra->astbuf3 = std::make_unique<AstNode>(@$, AST_WIRE); extra->current_wire_rand = false; extra->current_wire_const = false; }
{ extra->astbuf3 = std::make_unique<AstNode>(@$, AST_WIRE); extra->current_wire_rand = false; extra->current_wire_const = false; extra->current_wire_automatic = false; }
wire_type_token_io wire_type_const_rand opt_wire_type_token wire_type_signedness
{ $$ = std::move(extra->astbuf3); SET_RULE_LOC(@$, @2, @$); };
non_io_wire_type:
{ extra->astbuf3 = std::make_unique<AstNode>(@$, AST_WIRE); extra->current_wire_rand = false; extra->current_wire_const = false; }
wire_type_const_rand wire_type_token wire_type_signedness
{ $$ = std::move(extra->astbuf3); SET_RULE_LOC(@$, @2, @$); };
{ extra->astbuf3 = std::make_unique<AstNode>(@$, AST_WIRE); extra->current_wire_rand = false; extra->current_wire_const = false; extra->current_wire_automatic = false; }
opt_lifetime wire_type_const_rand wire_type_token wire_type_signedness
{
if (extra->current_wire_automatic)
extra->astbuf3->set_attribute(ID::nosync, AstNode::mkconst_int(extra->astbuf3->location, 1, false));
$$ = std::move(extra->astbuf3); SET_RULE_LOC(@$, @2, @$);
};
wire_type:
io_wire_type { $$ = std::move($1); } |
@ -1253,6 +1257,10 @@ opt_automatic:
TOK_AUTOMATIC |
%empty;
opt_lifetime:
TOK_AUTOMATIC { extra->current_wire_automatic = true; } |
%empty;
task_func_args_opt:
TOK_LPAREN TOK_RPAREN | %empty | TOK_LPAREN {
extra->albuf = nullptr;
@ -3341,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<AstNode>(@$, AST_REPLICATE, std::move($2), std::move($4));
} |
@ -3572,6 +3585,16 @@ concat_list:
$$->children.push_back(std::move($1));
};
assignment_pattern_list:
expr {
$$ = std::make_unique<AstNode>(@$, 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); } |

View File

@ -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

View File

@ -291,7 +291,7 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
if (pos < 0)
result.set(i, vacant_bits);
else if (pos >= BigInteger(GetSize(arg1)))
result.set(i, sign_ext ? arg1.back() : vacant_bits);
result.set(i, sign_ext && !arg1.empty() ? arg1.back() : vacant_bits);
else
result.set(i, arg1[pos.toInt()]);
}

Some files were not shown because too many files have changed in this diff Show More