summaryrefslogtreecommitdiff
path: root/passes
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2016-09-23 07:09:40 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2016-09-23 07:09:40 +0200
commit4f096fe65b77435daba019248273e547fa18d167 (patch)
tree52a8438cfecf42cc43e8ec6b9625d26bbd12159a /passes
parentc89f61c730da973adc7cce93f0839db49683c761 (diff)
Squashed commit of the following:
commit 0c697b9eacacfebd69c9603c2cb79ec70311197d Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 20 09:29:56 2016 +0200 Added autotest.sh -I commit e788ad48855cf02ba426abef83077b7f4ec80fa3 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Sep 19 20:43:43 2016 +0200 Cosmetic fix in test_autotb.cc commit 2e244c2d8e8e57f185b4165267682536843c8616 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Sep 19 20:43:28 2016 +0200 Added yosys-smtbmc --noinfo and --dummy commit 5e155aa1214a586e0db50c27e9b487915032f08e Author: Clifford Wolf <clifford@clifford.at> Date: Mon Sep 19 10:20:20 2016 +0200 Avoid creating very long strings in test_autotb commit aaa99c35bdcde8bec9d44ca23814f323a4e09c75 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Sep 19 01:30:07 2016 +0200 Added $past, $stable, $rose, $fell SVA functions commit d009cdd6eef5a24a11584a543bab8543f3940f6c Author: Clifford Wolf <clifford@clifford.at> Date: Sun Sep 18 20:48:09 2016 +0200 Improved handling of SMT2 logics in yosys-smtbmc commit 13a03b84d402d4a9891e6513a44551572d3e92db Author: Clifford Wolf <clifford@clifford.at> Date: Sun Sep 18 18:48:59 2016 +0200 Added support for bus interfaces to "read_liberty -lib" commit 0ead5a9e44fecf0712658efd168ebd7868039867 Merge: 7bc88e8 d8ad889 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Sep 18 00:50:02 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit 7bc88e81010d5e641a55da9fb99724a90a2a4efa Author: Clifford Wolf <clifford@clifford.at> Date: Sun Sep 18 00:48:36 2016 +0200 yosys-smtbmc: added -i support smtc files commit d8ad889594cb5746d3d0b1f7590eeaf63d13c64a Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 14 20:46:54 2016 +0200 Bugfix in techmap parameter handling commit d39db41df87113792c383fc2f127a3d42ae6dd0e Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 13 13:23:06 2016 +0200 Work-around for boolector bug commit d01e34136ecfecc3f155d3fe7c74e07346ecae4e Merge: 6f416c1 2c031cd Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 13 12:34:19 2016 +0200 Merge pull request #228 from Kmanfi/test Fix for modules with big interfaces. commit 2c031cd24f536a35a32ce3c78d548fa627265557 Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Tue Sep 13 13:13:27 2016 +0300 Fix for modules with big interfaces. commit 6f416c19537fcaab27b26d66c3144b468cec136a Author: Clifford Wolf <clifford@clifford.at> Date: Sun Sep 11 18:08:56 2016 +0200 Added missing :produce-models setting to smtio.py commit 5199aafca0579aceb3b4a2ad1af610bcb4ccfcd1 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Sep 10 16:24:08 2016 +0200 Minor improvements to smtio.py vcd writer commit b582f11074c1877888341cf6d3fdceb490e88a3e Author: Clifford Wolf <clifford@clifford.at> Date: Sat Sep 10 15:14:41 2016 +0200 fixed write_smt2 for (non-combinatorial) loops through hierarchical cells commit 3ceba145d54f725c90436c7322a67320d4308ce8 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Sep 8 18:08:15 2016 +0200 smt2 mem init bugfix commit 2c0d818296eda10f763287784b749a712bfeda98 Merge: 14bfd3c 9e72046 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Sep 8 11:17:05 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit 14bfd3c5c159626a2b3b8dec3a446e0f7c4c7e0c Author: Clifford Wolf <clifford@clifford.at> Date: Thu Sep 8 11:16:12 2016 +0200 yosys-smtbmc meminit support commit 9e72046906bdb9a15054c6c54b0003bfdc3baf6e Merge: 209a3d9 df4ab16 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Sep 8 10:06:40 2016 +0200 Merge pull request #225 from Kmanfi/test Typo fix. commit df4ab169a7ae84f9380e658e3ac5958a3d3e57d3 Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Thu Sep 8 10:57:16 2016 +0300 Typo fix. commit 209a3d9ffcb5f7efbe60b0e0d45755329532535e Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 7 21:01:51 2016 +0200 Bugfix in "yosys-smtbmc --unroll" commit 6770d6e0f878b4e172bb04f1d0df5fa72f05e167 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 7 20:57:56 2016 +0200 Added "yosys-smtbmc --unroll" commit ceff7ecd91e152dfac1d80188e592667cbec0392 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 7 13:43:57 2016 +0200 Install celledges.h commit cb7dbf4070a7ca3658b7e473cb54f2eafb6c9ae3 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 7 12:42:16 2016 +0200 Improvements in assertpmux commit e2570ffb872382f190b98d89b2eb7995a5d46758 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 7 11:08:54 2016 +0200 Updated ABC to hg 8e08604f8ad3 commit ab18e9df7c55581a9713a332af425011793106a7 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Sep 7 00:28:01 2016 +0200 Added assertpmux commit f3f5a0204542da3b49e88bcf0b461b6476d45d63 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 6 17:43:24 2016 +0200 Added "tee +INT -INT" commit fc5281b3f7656dd5e245f4ab7d81f39a14693f6b Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 6 17:35:25 2016 +0200 Run log_flush() before solving in sat command commit d55a93b39ff331aea16d627de92b1cbee2be68db Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 6 17:35:06 2016 +0200 Bugfix in parsing of BLIF latch init values commit 97583ab7295499b1b78ac7035e6e0b37d7b87734 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 6 17:34:42 2016 +0200 Avoid creation of bogus initial blocks for assert/assume in always @* commit dcb5a6ea8aaf857ea02f2a6c789e2a13ce501299 Author: Larry Doolittle <ldoolitt@recycle.lbl.gov> Date: Mon Sep 5 19:58:18 2016 -0700 Fix spelling and grammar in README commit 97b449fe55384d6637db8a0850ed33a4c864bbc3 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Sep 6 01:40:31 2016 +0200 yosys-smtbmc: flush stdout after each log msg commit 372d672c2a73314aa4a796357ae09f1570527500 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Sep 4 16:32:47 2016 +0200 Minor bugfix in write_smt2 commit 19a3b3732cc0ab25858b99ce29a172abcfe1fd43 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Sep 3 18:49:53 2016 +0200 Minor README updates commit fa5565b606bf58de1e1150c937afe014fcd928b6 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Sep 3 14:26:00 2016 +0200 Added boolector support to yosys-smtbmc commit d2eba7631ff8bfb897db72f787ca365003176ca1 Merge: 2ee9bf1 068d5bc Author: Clifford Wolf <clifford@clifford.at> Date: Fri Sep 2 13:55:51 2016 +0200 Merge branch 'smtbmc-kmanfi' commit 068d5bc02ffea9ba627bbf7151fdb36500eae0f2 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Sep 2 13:54:24 2016 +0200 Made examples/smtbmc/demo1.v more interesting commit 948aac9e1eaed04aa8de08e62cfb078d6337e9c9 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Sep 2 13:46:56 2016 +0200 Don't re-create hex_dict for each value commit d88cd0ae7f8761637722d5d2c6cc1c8bac762ce3 Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Fri Sep 2 13:09:09 2016 +0300 More PEP 8 fixes. commit c4ba1965fd4300cb7de48cde996bb068d951967d Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Fri Sep 2 13:01:31 2016 +0300 Indentation and PEP 8 fixes. CamelCase and white space after semicolon. commit 2343dda946e5ff335573c6b047d299bb90c98b1e Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Fri Sep 2 12:50:23 2016 +0300 Use dict lookup instead of many ifs. commit 279298c0b85250fd0c4e3637d10f9cf24e832259 Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Fri Sep 2 11:12:30 2016 +0300 Fix: Unresolved reference. commit 74dd36ad5555ceae0ce153e67bf26d594e9f09da Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Fri Sep 2 11:02:19 2016 +0300 Some syntax fixes. Generator and comma separated list modifications. commit 2ee9bf10d029396ba03b1d3023f15ff585e26bcb Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 23:57:24 2016 +0200 Added "prep -nomem" commit aa25a4cec66bfde84f9142b21679e82ba90ee910 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 19:27:42 2016 +0200 Added $anyconst support to yosys-smtbmc commit 6f41e5277d1d41db7a620c73cf1b65558b55f236 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 19:09:56 2016 +0200 Removed $aconst cell type commit a8124c137e2bfa3605dacadfe469ea22934b4cb3 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 14:49:47 2016 +0200 Fixed memory bug in write_smt2 commit b04a40d9fe6725dbe1b97a63931b0c0710e3149d Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 12:40:09 2016 +0200 Made "write_smt2 -bv -mem" default, added "write_smt2 -nobv -nomem" commit 39e4faa2e4c51c9588df233c795b4e85523879cf Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 11:26:10 2016 +0200 Added $anyconst support to smt2 back-end commit 4ea7054b56c568e15ffe9ee3560fd458fabcdf00 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 30 01:34:04 2016 +0200 Improved init spec handling in opt_rmdff, modernized the code a bit commit c417421495c3510add13859b2e33983880b4a224 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 29 22:41:45 2016 +0200 Added "yosys-smtbmc --dump-all" commit b226893461af46f2183be8ca9dfab62b49133c71 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 29 14:53:32 2016 +0200 More yosys-smtbmc bugfixes commit a2e2fc5980e3465011d7373be34e2d018240ede4 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 29 13:53:12 2016 +0200 Various fixes and improvements in yosys-smtbmc commit eae390ae17839bf0273b32149f46a2560a23d934 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 28 21:35:33 2016 +0200 Removed $predict again commit 66582964bc11aadf3d0783a346706d801451a13f Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 28 12:34:36 2016 +0200 Improved "show" help message commit f56dba8e2053d12fbd8e1e9b7dc83f3e4e340f3d Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 27 22:04:15 2016 +0200 Some changes to yosys-smtbmc cmd line options, add --final-only commit 23afeadb5e01a7b816c6ae203746caa8ae2aaed7 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 27 17:06:22 2016 +0200 Fixed handling of transparent bram rd ports on ROMs commit adcda6817e0df097bf70f8c200edcf15341f3188 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 27 14:30:36 2016 +0200 Added smtc "final" statement commit 7500b403de9eeafcc3de2a8eba051a03d5f5f10e Merge: 1276c87 3356d39 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Aug 26 23:36:15 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit 3356d3947bc8cd343019587f5fc33b8ca27afdb3 Merge: 17233b1 ee620c6 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Aug 26 23:36:05 2016 +0200 Merge pull request #215 from frznchckn/to_upstream Add some useful flexibility to build process commit 1276c87a56f6f6d1a134877f024d2af785354570 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Aug 26 23:35:27 2016 +0200 Added read_verilog -norestrict -assume-asserts commit ee620c6a24a62725f6f41b43728fe7ce4112e130 Author: Russell L Friesenhahn <russellf@arlut.utexas.edu> Date: Fri Aug 26 11:15:36 2016 -0500 Relax test to see if yosys dir is a git repository in Makefile This prevents the test from failing in the case that yosys is a submodule of a repository since for a submodule the .git is actually a file containing the location of the submodule's .git directory commit 23f217b1668415009a7a842b66012686c2f2d5b0 Author: Russell L Friesenhahn <russellf@arlut.utexas.edu> Date: Tue Aug 16 22:07:36 2016 -0500 Allow redefining of the ABC repository URL For persons or organizations that prefer to keep their own mirrors of repositories, users may now specify the URL of the ABC Mercurial repository that yosys clones during build. The URL may be set in the Makefile directly, on the command-line, or in the environment commit 17233b11e185d2c863ccd06830e8cd0d2be38e83 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Aug 26 17:33:02 2016 +0200 Various fixes and improvements in smt2 back-end commit 4be4969bae5d99af572ca99859dc4a550c24d4cf Author: Clifford Wolf <clifford@clifford.at> Date: Thu Aug 25 11:44:25 2016 +0200 Improved verilog parser errors commit ad56ad44c3bdd3d075a32879785a04e3e30491eb Author: Clifford Wolf <clifford@clifford.at> Date: Wed Aug 24 23:18:29 2016 +0200 More yosys-smtbmc smtc features commit ee3e7a0e45e764c2655391b0e444e4379c97fe3c Author: Clifford Wolf <clifford@clifford.at> Date: Wed Aug 24 22:09:50 2016 +0200 yosys-smtbmc --smtc -g commit cd18235f30221ea2a5d51ab8b1d2639f51f1e99d Author: Clifford Wolf <clifford@clifford.at> Date: Wed Aug 24 15:30:08 2016 +0200 Added SV "restrict" keyword commit 6523023645bd2227cac68f46364dff3867d9641a Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 22 17:45:01 2016 +0200 Minor yosys-smtbmc bugfix commit 583ceee6eb69fb8093f7d184d737ea93e2744c5b Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 22 17:27:43 2016 +0200 Added "yosys-smtbmc --constr" commit 2bd30e20261240057752f124506c8b38af95afc4 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 22 16:48:46 2016 +0200 Added "yosys-smtbmc --dump-constr" commit f8a77abfac6da12e2e11c43b4e6aa6e613ac0d4b Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 22 15:05:57 2016 +0200 Added glob support to all front-ends commit 450f6f59b494af14014f0cbe93df4ceca0eecd76 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 22 14:27:46 2016 +0200 Fixed bug with memories that do not have a down-to-zero data width commit cad40fc87449e69a086a627bfb25aa49ae400753 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 22 14:26:33 2016 +0200 Fixed bug in memory_share for memory ports with different ABITS commit 7a33b9892a7a542ca1ac0b503c4368a1721a9afb Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 21 15:56:22 2016 +0200 yosys-smtbmc: improved --dump-vlogtb handling of memories commit cdd0b85e47d6c1718ec5c0d2d80c87af3e3bbc83 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 21 13:45:46 2016 +0200 Added another mem2reg test case commit 82a4a0230feedd994546ad57a1f4ae79b8f80136 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 21 13:23:58 2016 +0200 Another bugfix in mem2reg code commit dbdd8927e78622885bc85c429e783b89b2d3022d Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 21 13:18:09 2016 +0200 Minor improvements to AstNode::dumpAst() and AstNode::dumpVlog() commit a93fcec93fdd5da581ece4a593369978db9dd42c Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 18:44:27 2016 +0200 Added examples/smtbmc/demo2.v commit f7578b0239720562571d88d5a0406488075a2a31 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 18:43:39 2016 +0200 Added "yosys-smtbmc --dump-vlogtb" commit ed785194def450e68f217a3ae1764b5c5a679298 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 18:42:32 2016 +0200 Added support for memories to smtio.py commit c325bae792a953037c115ad6763081c7ad15f01c Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 18:41:57 2016 +0200 Deprecated "write_smt2 -regs" (by default on now), and some other smt2 back-end improvements commit 28271e43c9876daad3deddd0668188406e56b8ae Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 16:32:50 2016 +0200 Added "yosys-smtbmc -g" commit a889acb897b742f8d17ebccb0fb0d0a8e622fb70 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 16:07:59 2016 +0200 Added smtbmc longopt support commit fe9315b7a19bcb6dcde1a1ce49dd23f999bda7eb Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 13:47:46 2016 +0200 Fixed finish_addr handling in $readmemh/$readmemb commit 75bf7416f0dcf7b5bf3e095779f78039c75c316c Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 13:06:06 2016 +0200 Bugfix in partial mem write handling in verilog back-end commit d77a914683207ab9e4be20d8a10573acd8af777a Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 20 12:52:50 2016 +0200 Added "wreduce -memx" commit 15ef6084533809894dd0b5200a65497047c2ccf8 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Aug 19 19:48:26 2016 +0200 Added memory_memx pass, "memory -memx", and "prep -memx" commit f6629b9c29838879cec6a94d6cb47afc6fbd2db4 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Aug 19 18:38:25 2016 +0200 Optimize memory address port width in wreduce and memory_collect, not verilog front-end commit 9b8e06bee177f53c34a9dd6dd907a822f21659be Author: Clifford Wolf <clifford@clifford.at> Date: Thu Aug 18 21:47:02 2016 +0200 Added missing support for mem read enable ports to verilog back-end commit b3a01451a54506addf7493d4e3abaa621aa5689c Author: Clifford Wolf <clifford@clifford.at> Date: Thu Aug 18 13:43:12 2016 +0200 Bugfix in test_autotb commit de8ee412c30e92efe3a3e1434c0f4b495f8cdbbe Author: Clifford Wolf <clifford@clifford.at> Date: Thu Aug 18 11:17:45 2016 +0200 Improved smtbmc vcd generation performance commit dfcd30ea869f43af520aef033aa1311457112904 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Aug 17 20:10:02 2016 +0200 Added printing of code loc of failed asserts to yosys-smtbmc commit 42a971226bd1972c3c21d386c02c1bc2ac850129 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 22:44:38 2016 +0200 Fixed default build config commit 1419f3983ef28cf8c9ec8837010bef498f085b63 Merge: 5767e4b 5299b17 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 22:41:53 2016 +0200 Merge pull request #203 from cr1901/master Add MSYS2-compatible build. commit 5299b170568bd1de71c906eeb8929a053febc039 Author: William D. Jones <thor0505@comcast.net> Date: Tue Aug 16 14:41:37 2016 -0400 Add MSYS2-compatible build. commit 5767e4bc4db8d70bd02945769b6784618f7d003a Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 09:36:49 2016 +0200 Use _Exit(0) on win32, always use _Exit(1) in log_error() commit 5531bd757808499c23d082c4aa3566cfd5e5ec70 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 09:08:26 2016 +0200 Updated ABC to hg rev a86455b00da5 commit 00f29d5e5cdd08a14aa02119f46f8ee10cd1368d Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 09:07:13 2016 +0200 Fixed use-after-free dict<> usage pattern in hierarchy.cc commit b4d544f0d90d50059d95520d863924bffa3122ac Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 00:56:42 2016 +0200 Updated ABC to hg rev 760ba358e790 commit 4561586eedb32fc5525cae87fded69860f609686 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 00:52:10 2016 +0200 ABC mxe cross-build fix commit 321e15b0bfe84bf3b34b3a24d90ff55fe90de7cd Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 16 00:36:24 2016 +0200 Minor fixes in show command commit 5d90a5b9058d0e47643026b3439644cf974566a4 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 15 09:33:06 2016 +0200 Added greenpak4_dffinv commit f0a8713fea9fea016e5a83fefd9e00a32f4a88d2 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 15 08:26:20 2016 +0200 Fixed upto handling in verilog back-end commit 1058660ac882d97bd41737627c6246948edcab90 Merge: 6ac67ea 0b0ba96 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Aug 14 15:49:08 2016 +0200 Merge pull request #200 from azonenberg/master Updates to GP_RCOSC, new GP_DFF*I cells commit 0b0ba964881ce2996ee2feb1a5ca91c21669f0f7 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sun Aug 14 00:30:45 2016 -0700 greenpak4: Changed name of inverted output ports for consistency commit 3b9756c6a3ae1d1f5b6e530d4b50e07710b44987 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sun Aug 14 00:11:44 2016 -0700 greenpak4: Added GP_DFFxI cells commit 2b062c48cb4405f4a1bb6bd49edaf687bbc2cc4e Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Aug 13 22:27:58 2016 -0700 greenpak4: Renamed ports for better consistency (see azonenberg/openfpga:#6) commit 6ac67eac10cfd3e9508ef02f6301455fc3c13451 Merge: e9fe57c 0515809 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Aug 11 11:17:44 2016 +0200 Merge pull request #198 from whitequark/master synth_greenpak4: use attrmvcp to move LOC from wires to cells commit 0515809448d11beae27a6199ea02c59b36b58299 Author: whitequark <whitequark@whitequark.org> Date: Wed Aug 10 20:09:35 2016 +0000 synth_greenpak4: use attrmvcp to move LOC from wires to cells. commit e9fe57c75e225f80156ceabbc10741c3cfee1c87 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Aug 10 19:32:11 2016 +0200 Only allow posedge/negedge with 1 bit wide signals commit 73b7232ec89d9e3611ee5dbbc0cf663a33b09c8f Author: Clifford Wolf <clifford@clifford.at> Date: Wed Aug 10 13:44:08 2016 +0200 Fixed some compiler warnings in attrmap command commit b0aab4e3046f1a598314e2563fa84b3a8ddc7fa5 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 9 19:56:55 2016 +0200 Added "attrmap" command commit 39da8eddaefc078c6f7aba9958c40daec69f33d4 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 9 19:56:10 2016 +0200 Added log_const() API commit 3c6d31fd061fb591a95b08ecfd1d2e50690dfc48 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 9 11:18:48 2016 +0200 Added "attrmvcp" pass commit f7730d43bb4d5b44ec76e1080f4baf2f6b26807f Author: Yury Gribov <tetra2005@gmail.com> Date: Sun Aug 7 21:34:33 2016 +0100 Use /proc/self/exe on Cygwin as well. commit 9d15529214f164701ac4f53d0f3a5d4943b8f8dd Author: Clifford Wolf <clifford@clifford.at> Date: Mon Aug 8 11:47:35 2016 +0200 Undo "preserve wire attributes in iopadmap" change (it was OK before) commit 88a67afa7d044bd1abb952d7c709876e4159db1a Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 6 13:32:29 2016 +0200 Added "test_autotb -seed" (and "autotest.sh -S") commit 90c17aad56b0bf4b3ace5dea8c2d8555b52d4bfb Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 6 13:24:59 2016 +0200 preserve wire attributes in iopadmap commit 7f755dec75824e27dd79173a76d5819bf7fdbd27 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Aug 6 13:16:23 2016 +0200 Fixed bug in parsing real constants commit 5d6765a9d20ab2a88c02d06cb58fca2bfaf39c8d Author: Clifford Wolf <clifford@clifford.at> Date: Tue Aug 2 10:37:19 2016 +0200 Added "insbuf" command commit 21e1bac0846e01fb58ae1fd42215b92f245ae18d Merge: 5fe13a1 da56a5b Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 30 12:50:39 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit 5fe13a16eaaee4ac53523b5325cb9d92b5a1150d Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 30 12:46:06 2016 +0200 Added "write_verilog -defparam" commit 7fa61cba1bd9c29a6a9516a75003db576f673b4c Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 30 12:38:40 2016 +0200 Added "write_verilog -nodec -nostr" commit da56a5bbc60e58c305227105b68654264738c241 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 27 16:11:37 2016 +0200 Added $initstate support to smtbmc flow commit 8d88fcb27011a6f8f47a8615c30ab658fafab0f2 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 27 15:52:20 2016 +0200 Added SatGen support for $anyconst commit 9540be1d45cce45d0008a4160bc4aa70ff0dfe1d Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 27 15:44:11 2016 +0200 Removed $predict support from SatGen commit 40563129872f5a2287f54cb0dbd79534b493a5d6 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 27 15:41:22 2016 +0200 Added $anyconst and $aconst commit a7b07696238dbfd8e4fb5fd41d597200abef4909 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 27 15:40:17 2016 +0200 Added "read_verilog -dump_rtlil" commit 8537c4d2061db1ee11defc357781c6c534be5b3d Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jul 25 16:39:25 2016 +0200 Renamed AbstractCellEdgesDatabase::add_cell() to add_edges_from_cell() commit 5b944ef11b8964a00d833ad29c96ad46da06f7a3 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jul 25 16:37:58 2016 +0200 Fixed a verilog parser memory leak commit 7a67add95d3d2f3293f84e38b891024d6444d2a4 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jul 25 12:48:03 2016 +0200 Fixed parsing of empty positional cell ports commit b1c432af5613b0e5817ccc35bb081737dfcb6867 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jul 24 17:21:53 2016 +0200 Improvements in CellEdgesDatabase commit f162b858f22e66dd553973c1275fc7994fc615f1 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jul 24 13:59:57 2016 +0200 Added CellEdgesDatabase API commit 54966679df103781f0c8d72079aedd84a9dc0ec6 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jul 24 12:18:39 2016 +0200 Moved SatHelper::setup_init() code to SatHelper::setup() commit 34e833103b77b06972ead21a9373c5541cb5ee7d Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 23 17:01:03 2016 +0200 Added $initstate support to "sat" command commit 9aae1d1e8ff1afa15459e5463397d1557ba8a361 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 23 11:56:53 2016 +0200 No tristate warning message for "read_verilog -lib" commit 89deb412c68505a0c66e92a93a334e08370f0e6b Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 22 10:28:45 2016 +0200 Added satgen initstate support commit 7fef5ff10436a51a91f57157f687345795f60e40 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Jul 21 14:37:28 2016 +0200 Using $initstate in "initial assume" and "initial assert" commit 5c166e76e52cdaf6ea97952c17d3d79185a59f96 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Jul 21 14:23:22 2016 +0200 Added $initstate cell type and vlog function commit d7763634b68a735443c61aa32918ee0cdd6e9250 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Jul 21 13:34:33 2016 +0200 After reading the SV spec, using non-standard predict() instead of expect() commit 721f1f5ecfb6334904f6058d6d376d21b5efc438 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 13 16:56:17 2016 +0200 Added basic support for $expect cells commit b3155af5f65333d272da339222e1e1962fb088b7 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 13 09:49:05 2016 +0200 Added examples/smtbmc commit 2afc72cae31720d7eacb0423a0dc87d4eccb1aa1 Merge: 9e5c947 546233f Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 13 09:39:27 2016 +0200 Merge pull request #191 from whitequark/json-module-attributes write_json: also write module attributes commit 9e5c9471e366e1abaad62525e783eb549274d951 Merge: e92998a 32bea97 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jul 13 09:24:31 2016 +0200 Merge pull request #193 from azonenberg/master Removed splitnets in synth_greenpak4, added GP_DAC, refactored GP_BANDGAP commit 32bea97b757e11002133d8e69b23eac3df7fb800 Merge: 52a738a e92998a Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Tue Jul 12 16:12:37 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit e92998a79cec635270a350117eddb52c6232f388 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Jul 12 09:46:15 2016 +0200 Minor bugfix in FSM reset state detection commit 546233f0e154cca0bacb4960faf54ba8d206c1fd Author: whitequark <whitequark@whitequark.org> Date: Tue Jul 12 06:32:04 2016 +0000 write_json: also write module attributes. commit 52a738a54435d9e54ac7cb523551ae866cc76770 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Jul 11 22:45:55 2016 -0700 Added GP_DAC cell commit baae472b83b3dac1293bb95ff0a87d9180a67479 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Jul 11 22:45:42 2016 -0700 Removed VOUT port of GP_BANDGAP commit 8619d33114edc58d89247ac3471d4115e1689a82 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Jul 11 22:42:25 2016 -0700 Removed splitnets in prep for new gp4par parser commit c71785d65e9775093b24ce684ed4fbe93bedb04d Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jul 11 12:49:33 2016 +0200 Yosys-smtbmc: Support for hierarchical VCD dumping commit 0153ad85d906105f5b4b520f6d62dbf646b2c285 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jul 11 11:49:05 2016 +0200 Moved smt2 yosys info parsing from smtbmc.py to smtio.py commit cdb58f68ab180deea6d13caa131aa0ea62cb2a8a Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jul 11 11:40:55 2016 +0200 Added "prep -auto-top" and "synth -auto-top" commit a72fb85dc2195a4519a8f360bd5f0846ef8d26a4 Merge: 771c5fe 307e31a Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jul 10 18:17:09 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit 307e31a95e96165650798e68fd5bb22809f4127f Merge: b5a9fba c064583 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jul 10 18:12:00 2016 +0200 Merge pull request #189 from whitequark/master greenpak4: add GP_COUNT{8,14}_ADV cells commit 771c5fe0009cf2195e12be40b242662380681624 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jul 10 18:11:25 2016 +0200 Support for hierarchical designs in smt2 back-end commit c0645839fe499fbc37199744cab5c624e5840dba Author: whitequark <whitequark@whitequark.org> Date: Sun Jul 10 14:41:34 2016 +0000 greenpak4: add GP_COUNT{8,14}_ADV cells. commit b5a9fba0db5a8f29cffa22aa61f9d9cb7f69009a Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 9 14:02:49 2016 +0200 Further improved fsm_detect output, attempt to detect self-resetting circuits commit d63ffabacbe26aa5ade942940a44671427e2db7c Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 9 13:23:06 2016 +0200 Added printing of some warning messages to fsm_detect commit d3f0d7242732d8fb8885600c00c80c1aff8b5253 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 18:31:31 2016 +0200 Added warning about adding fsm_encoding attributes to wires to manual commit 21659847a7a31f80140e03a5b6351da54c062836 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 14:41:36 2016 +0200 Minor fixes in ice40_ff* passes for sloppy SB_DFF instantiations commit 9a101dc1f78acb404cc98e0acc4530c238070fd8 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 14:31:06 2016 +0200 Fixed mem assignment in left-hand-side concatenation commit b782076698b76445b6b1087671687483c6d6c545 Merge: e420412 27b5347 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 11:56:53 2016 +0200 Merge branch 'eddiehung-vtr' commit 27b5347a871d209ec4cba094e1203cc896c9c4b3 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 11:49:55 2016 +0200 Restored blif "-true - .." behavior, use "-true + .." for eddiehung-vtr behavior commit 72149aba2e8fece72450a81142a44d123154fd12 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 11:41:26 2016 +0200 In BLIF, a .names without entries already always outputs 0 commit 6bda61292513cbe7ffd69b4e3462b849757d2337 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 11:35:15 2016 +0200 Undo eddiehung-vtr Makefile changes commit f6b7cf23d65c8e86cbfb742f30167dcc89825cbd Merge: e420412 7c62318 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 8 11:32:36 2016 +0200 Merge branch 'yosys-0.5-vtr' of https://github.com/eddiehung/yosys into eddiehung-vtr commit e420412043228cec6a15b356cc9eea82bbafe9c0 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jul 2 13:32:20 2016 +0200 Fixed autotest.sh handling of `timescale commit 080f95f9332d9caae95095ab9935f78d3b60f204 Merge: df5ebfa 6ed6b3c Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 1 12:24:31 2016 +0200 Merge branch 'assert-limit' commit 6ed6b3cb6d1f1735201861d30cd70736b76e5221 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jul 1 12:24:13 2016 +0200 Replaced "select -assert-limit" with -assert-max and -assert-min commit 9a742f4069d6413bcf46b84c3b3f0e5cfc47f647 Author: eshellko <kornukhin@mail.ru> Date: Fri Jul 1 10:24:22 2016 +0400 Added 'assert-limit' option for 'select' command For resource limited designs such as FPGA it can be useful to specify limit of specific resources available on board. So user can check if he should change RTL as early as mapping done. commit df5ebfa0a0fc6d060caaa21b74a2f1a7b4ba0f86 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Jun 30 09:58:13 2016 +0200 Improved ice40_ffinit error reporting commit 7cddab0788cadc220ffa098c4ac037362ad6948e Merge: 541083c 545bcb3 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Jun 21 08:44:20 2016 +0200 Merge pull request #181 from rubund/input_logic_allowed Allow defining input ports as "input logic" in SystemVerilog commit 545bcb37e8fa569d88374f92aafdcc1004e9b587 Author: Ruben Undheim <ruben.undheim@gmail.com> Date: Mon Jun 20 20:16:37 2016 +0200 Allow defining input ports as "input logic" in SystemVerilog commit 541083cf329addb57117618de41697dd010d07cf Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jun 19 22:19:19 2016 +0200 Bugfix in "abc -script" handling commit 9bca8ccd40d70b6f6ad218cb9b1ae7dd4d3e8e68 Merge: ca91bcc a8200a7 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jun 19 15:48:40 2016 +0200 Merge branch 'sv_packages' of https://github.com/rubund/yosys commit ca91bccb6b03a0b098f80bf14b55a1444eef73c0 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Jun 19 13:08:16 2016 +0200 Added "deminout" commit a8200a773fb8cf2ce2d8793716b62e01c97dd731 Author: Ruben Undheim <ruben.undheim@gmail.com> Date: Sat Jun 18 14:13:36 2016 +0200 A few modifications after pull request comments - Renamed Design::packages to Design::verilog_packages - No need to include ast.h in rtlil.h commit 9e28290b0f4f6006897b46fd3ab8817a1c82b0b1 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jun 18 12:33:13 2016 +0200 Added "read_blif -sop" commit 5ffad4e0737bfb7e86129f3c74e7ee917ef782cc Author: Clifford Wolf <clifford@clifford.at> Date: Sat Jun 18 12:28:49 2016 +0200 Added $sop support to BLIF back-end commit 178ff3e7f6f9766f0b1a3e8dcc96e030aea59b15 Author: Ruben Undheim <ruben.undheim@gmail.com> Date: Sat Jun 18 10:24:21 2016 +0200 Added support for SystemVerilog packages with localparam definitions commit 3380281e15ca61cec8beda70938fb7b6f4c121d6 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 20:15:35 2016 +0200 Added "dc2" to default ABC scripts commit 7a4ee5da747382df323d41f60e974ef92bdc1e82 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 20:15:11 2016 +0200 Fixed init issue in mem2reg_test2 test case commit f498204ae462e2307f93c3ba8e6ba3b793b94d1f Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 19:39:35 2016 +0200 Added "abc -I <num> -P <num>" commit ebece2b8d5123aeb372df3ce226927bf3e6d09d6 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 17:47:30 2016 +0200 Added $sop SAT model commit 95757efb25dc51a73b384b475b0fc87d0e11d10e Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 16:31:16 2016 +0200 Improved support for $sop cells commit 52bb1b968d4bfbbbd84eca88f0e80c486cc1a16e Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 13:46:01 2016 +0200 Added $sop cell type and "abc -sop" commit c3365034e9db8b6450db578daefd860276d5071f Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 17 11:16:31 2016 +0200 Updated ABC to hg rev b5df6e2b76f0 commit 99edf249669158b8c8bef0c7c3b926a2bbb7a621 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Jun 9 11:47:41 2016 +0200 Added "nlutmap -assert" commit 52b0b4e31e98816bc15b957c89bca76619231143 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jun 8 12:14:32 2016 +0200 Do not run "wreduce" in "prep -ifx" commit 2032e6d8e46c0b715e73423cb34f4a624617df6e Author: Clifford Wolf <clifford@clifford.at> Date: Mon Jun 6 17:15:50 2016 +0200 Added "proc_mux -ifx" commit dcf576641b4a9b476d51fbe1b0cdfb57d02a76e6 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Jun 3 11:38:31 2016 +0200 Added "setundef -init" commit d2695e2bfa0c1bc8cbcb5cd8396b12a7f83959af Author: Clifford Wolf <clifford@clifford.at> Date: Thu Jun 2 14:37:07 2016 +0200 Fix all undef-muxes in dlatch input cone commit adfc80727c19021f911833305f5d322af6b8a0aa Author: Clifford Wolf <clifford@clifford.at> Date: Wed Jun 1 13:25:06 2016 +0200 Avoid creating undef-muxes when inferring latches in proc_dlatch commit 11f7b8a2a1dd6e5c47e8081e4485127331fd80be Author: Clifford Wolf <clifford@clifford.at> Date: Sun May 29 12:17:36 2016 +0200 Added opt_expr support for div/mod by power-of-two commit 766032c5f85e33c8aabb69d1868c3493f254695f Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 27 17:55:03 2016 +0200 Fixed procedural assignments to non-unique lvalues, e.g. {y,y} = {a,b} commit ee071586c55915c6535bad0a47bf80c8f2029272 Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 27 17:25:33 2016 +0200 Fixed access-after-delete bug in mem2reg code commit e9ceec26ffe773d36b5316c79149913777d6581f Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 27 16:37:36 2016 +0200 fixed typos in error messages commit 611f121cb9fb8a451e891356a6260f4b299afc7d Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 27 16:33:13 2016 +0200 Fixed "scc" for cells that have feedback singals _and_ are part of a larger loop commit 33742f4e8f5b39940a1dc6aa9582e94516cd0a5f Merge: 8e9e793 e22e4d5 Author: Clifford Wolf <clifford@clifford.at> Date: Sun May 22 18:15:08 2016 +0200 Merge pull request #172 from zeldin/deterministic_hierarchy Made the expansion order of hierarchy deterministic commit e22e4d59b8abe9ba60d32402d0ff9b84d266743d Author: Marcus Comstedt <marcus@mc.pp.se> Date: Sun May 22 16:37:47 2016 +0200 Made the expansion order of hierarchy deterministic commit 8e9e793126a2772eed4b041bc60415943c71d5ee Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 20 17:13:11 2016 +0200 Some fixes in tests/asicworld/*_tb.v commit 1e227caf720bc5870ea9244e6b5657cf9c9717ab Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 20 16:58:02 2016 +0200 Improvements and fixes in autotest.sh script and test_autotb commit 884ec967871dede8d5ad6fb730a405e421a18dbe Merge: f3983a0 8c3bc2a Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 20 16:48:50 2016 +0200 Merge branch 'master' of https://github.com/Kmanfi/yosys commit f3983a094052e875e05823a6063c1775d1f84b39 Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 20 16:43:13 2016 +0200 Also escape "=" in spice output commit 060bf4819a3742ba2ad8142c9a7e665555c22ac7 Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 20 16:21:35 2016 +0200 Small improvements in Verilog front-end docs commit 8c3bc2ac0da4457f90775608e9701e0a7ba1e4cf Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Thu May 19 11:53:29 2016 +0300 Close opened dump file. commit f6221ade950411ed10e6f260971cff78b30b8666 Author: Kaj Tuomi <kaj.tuomi@siru.fi> Date: Thu May 19 11:34:38 2016 +0300 Fix for Modelsim transcript line warp issue #164 commit ffcdc53a18197e40571b9c604fff07408cc12346 Author: Clifford Wolf <clifford@clifford.at> Date: Sun May 15 00:05:30 2016 +0200 Don't sign-extend memory bram initialization data commit 864eeadcd9244505c7c026e2044799ff5bcf4782 Author: Clifford Wolf <clifford@clifford.at> Date: Sat May 14 11:43:20 2016 +0200 Added missing "#define HASHLIB_H" commit d05115ceda2969badb83b3b2f0cefcd447c29451 Author: Clifford Wolf <clifford@clifford.at> Date: Sat May 14 11:35:39 2016 +0200 Minor presentation fixes commit 407cdea0bc3a3d2a258b30a3e19d0861c3c4ba6f Author: Clifford Wolf <clifford@clifford.at> Date: Wed May 11 09:31:53 2016 +0200 Updated min GCC requirement to GCC 4.8 commit b8b39472bb1b991ab96dede1b188868d9d98246b Author: Clifford Wolf <clifford@clifford.at> Date: Mon May 9 12:43:49 2016 +0200 Added manual download link to README commit 570014800aa34d71868d04f9ef83e4a13b847773 Author: Clifford Wolf <clifford@clifford.at> Date: Sun May 8 10:50:39 2016 +0200 Include <cmath> in yosys.h commit fa76d51941ce5e4076317195bd1b603bccb74f02 Merge: f103bfb 47eace0 Author: Clifford Wolf <clifford@clifford.at> Date: Sun May 8 10:22:01 2016 +0200 Merge pull request #162 from azonenberg/master Added GP_DELAY cell. Fixed several errors in simulation models. commit 47eace0b9f2b9ddd7ae76e06e2ade85ceea88e17 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat May 7 21:29:26 2016 -0700 Added GP_DELAY cell commit 41bbad4e4c25bc1b0227348ec0329187c8688c4b Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat May 7 21:14:42 2016 -0700 Fixed typo in port name commit b5171541cd9da6a4e2b5aaaaf3bca76e059c7e3f Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat May 7 21:14:18 2016 -0700 Fixed extra semicolon commit 85ee88b0ee13eb49bb255d7e66a62fce823c028a Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat May 7 21:14:00 2016 -0700 Fixed typo in parameter name commit a0c19aae55d878576c7481a6a4a5d10ba98c5224 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat May 7 21:13:47 2016 -0700 Added simulation timescale declaration commit f103bfb9baddcd5ff16e610bc314c3de9eb3d526 Author: Clifford Wolf <clifford@clifford.at> Date: Sat May 7 10:53:18 2016 +0200 Fixes for MXE build commit c3f6e0ea851b90b11671015f2bb472c857f0e2d9 Author: Clifford Wolf <clifford@clifford.at> Date: Sat May 7 09:33:16 2016 +0200 Added support for "keep" attribute to shregmap commit 6fe3d5a1cf938081110db0470def2b2687dd665f Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 6 23:02:37 2016 +0200 Added synth_ice40 support for latches via logic loops commit d10dfccabb6bf4b1ba3f334b899f57093b8a0ddc Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 6 15:05:53 2016 +0200 Added "write_blif -noalias" commit 126da0ad3dfb7b75aaaadc97c7d40b495da9d164 Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 6 14:32:32 2016 +0200 Fixed ice40_opt lut unmapping, added "ice40_opt -unlut" commit aadca148da35963888e362d6eb5a3982b1903c10 Author: Clifford Wolf <clifford@clifford.at> Date: Fri May 6 13:59:30 2016 +0200 Fixed preservation of important attributes in techmap commit ec1938737bcfb625d4e62afaefd30d67acb588bf Merge: 9647dc3 2096a05 Author: Clifford Wolf <clifford@clifford.at> Date: Thu May 5 18:18:48 2016 +0200 Merge pull request #159 from azonenberg/master Fixes to use new I/O pad techmapping, renamed ports for GP_SHREG commit 2096a05ec2aaecb89316c5a229b497c21c2327f9 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed May 4 17:13:54 2016 -0700 Changed order of passes for better handling of INIT attributes on "output reg" FFs commit 3486637b19030bc65af77c99c282ff5a7e610ee8 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed May 4 17:04:50 2016 -0700 Changed port names in greenpak shregmap commit dee1c27a19f91fb44df67b2ab9834ee8140772c4 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed May 4 17:03:45 2016 -0700 Renamed module parameter commit a613f171aeb8703b6849a87b73899389fb9912d8 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed May 4 15:55:16 2016 -0700 Refactored synth_greenpak4 to use iopadmap for mapping GP_IOBUF/GP_OBUFT cells instead of extract commit 9647dc3c07039c49b9bcf5932050467ca451ceef Author: Clifford Wolf <clifford@clifford.at> Date: Wed May 4 22:48:02 2016 +0200 Added tristate buffer support to iopadmap commit 86add2907276ab7c9ec2c2861901a7a7adedf0fa Merge: 7a74ae4 deb1ecc Author: Clifford Wolf <clifford@clifford.at> Date: Wed May 4 19:12:59 2016 +0200 Merge pull request #157 from azonenberg/master Added GP_ABUF cell, support for tri-state I/O buffers in GreenPak commit deb1eccab5bad3e5a090254e0d3a069a3c474d8b Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed May 4 08:06:18 2016 -0700 Fixed incorrect signal naming in GP_IOBUF commit 2db8dd6d354b8d29382054668ae34e7852b413a2 Merge: dcee325 7a74ae4 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed May 4 07:23:27 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 7a74ae4c5403ce68a8245c45359d49f80d6e863a Merge: 658f936 12000b9 Author: Clifford Wolf <clifford@clifford.at> Date: Wed May 4 10:48:42 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit 658f93663b12d3199f636cad8bf75aa1ee58108b Author: Clifford Wolf <clifford@clifford.at> Date: Wed May 4 10:48:23 2016 +0200 Fixed iopadmap attribute handling commit dcee3256d59907c474542e0dfd24df7c047e6f50 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Tue May 3 22:53:29 2016 -0700 Added tri-state I/O extraction for GreenPak commit 66095153fd6110dbe84552175d4919f4f5fd75fc Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Tue May 3 22:03:04 2016 -0700 Added GreenPak I/O buffer cells commit 9fc9d5f1fb1eea47118c00ecad1352ec84fd3047 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon May 2 20:29:39 2016 -0700 Added comment to clarify GP_ABUF cell commit 79460208c928e62c608d71c0d6d484293835e8dc Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon May 2 20:27:41 2016 -0700 Added GP_ABUF cell commit 12000b90de0bade5fca641c49f3375316220ed39 Merge: 06d35ea 3a85e40 Author: Clifford Wolf <clifford@clifford.at> Date: Mon May 2 09:49:07 2016 +0200 Merge pull request #154 from azonenberg/master Add GP_PGA cell commit 3a85e40f42f4fa52934562135571cfcba35af80e Merge: fb87022 06d35ea Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sun May 1 10:07:21 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 06d35ea9425dbfeff8bcd0d842a31d22843b937b Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 29 10:26:22 2016 +0200 Improved TCL_VERSION detection so it does not read .tclshrc commit fb87022dca2bd8366cb006951e3f59c9f0540476 Merge: 134e093 e01464e Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 29 00:57:37 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit e01464e2ac2bf3bd2752e10b48d2fc3ffc4fdf9e Author: Clifford Wolf <clifford@clifford.at> Date: Thu Apr 28 23:17:30 2016 +0200 Added "qwp -v" commit 134e093e4e86080e1e4066f32128d268a36aeee5 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 27 23:07:21 2016 -0700 Added GP_PGA cell commit 0d2923cccd00ed14537f3239b0059a76673798a4 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 26 19:49:05 2016 +0200 Connections between inputs and inouts are driven by the input commit 958fb29c76a13838a922ff8553178d2c31c1ddef Author: Clifford Wolf <clifford@clifford.at> Date: Mon Apr 25 16:37:11 2016 +0200 Fixed test_autotb for modules with many cell ports commit 93e107e455b506731d9114e0dc2644f78797cf0f Author: Clifford Wolf <clifford@clifford.at> Date: Mon Apr 25 10:43:04 2016 +0200 Fixed proc_mux performance bug commit d086224a39fcd488062d7f75cc936cce5435069c Merge: b1d6f05 d57c851 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Apr 25 10:33:18 2016 +0200 Merge pull request #150 from azonenberg/master GreenPak analog comparator support commit d57c85111f4136e5ae098aa42cd337f82dd4b57e Merge: 349d717 b1d6f05 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sun Apr 24 22:11:56 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 349d7172023e9ee38b8e25e3bd04e2dfd0af1e62 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sun Apr 24 17:01:21 2016 -0700 Removed VIN_BUF_EN commit b1d6f05fa2156017f50383d01d49342c8ec5e209 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Apr 24 19:29:56 2016 +0200 Fixed performance bug in proc_dlatch commit 9aa4b3309c35d842e2b1a04172745a5e34a3c445 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Apr 24 17:12:34 2016 +0200 Added "yosys -D ALL" commit 6e215f374dcd92e2c1bff8ad6114f3d3dc9b06f5 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 23 22:53:49 2016 -0700 Renamed VOUT to OUT on GP_ACMP cell commit 512486dcf37f779e6271e299eb186ab2559eb344 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 23 22:33:36 2016 -0700 Added GP_ACMP cell commit 09ffebb9959510cacdc04c926800223235f50313 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Apr 24 00:48:33 2016 +0200 Added "prep -flatten" and "synth -flatten" commit 77aa2031e7e93b3d91b7594ad21d84e946b7cb04 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Apr 24 00:48:06 2016 +0200 Converted "prep" to ScriptPass commit 096c25d29d7e66003123dc4700ae72b0a4c10ca2 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 23 23:10:13 2016 +0200 Improvements in greenpak4 shreg mapping commit c9c5192cd63dc4c08441e94c8d53428503ccc4af Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 23 23:09:45 2016 +0200 Run clean after splitnets in synth_greenpak4 commit 7f16784f3c0151c9b7f2861965d73ce7c960ebb5 Merge: 421b0d7 e13c661 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 23 12:22:08 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit e13c66122ef4bc9cc8da77cda1d6bf594104acdb Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 23 20:20:21 2016 +0200 Added "shregmap -zinit" for greenpak4 tech commit 421b0d715c43fbcbfc1465518d444c9ca97cbabb Merge: 2849fd4 34195f2 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 23 10:18:15 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 34195f281fc4829f58c3dfc9c7944691044186e0 Merge: f85cfa5 0cbe70e Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 23 10:33:32 2016 +0200 Merge https://github.com/azonenberg/yosys commit f85cfa56667e32ff9e165f9d957d05bde25342c0 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 23 10:31:19 2016 +0200 Added "shregmap" to synth_greenpak4 commit a24021ea20bb70d0368c6b3e549a87fa5c4ab8ae Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 23 10:27:33 2016 +0200 Converted synth_greenpak4 to ScriptPass commit 2849fd486eaa1a77316cc6ffc86ec885b8a0d9fb Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 22 23:01:39 2016 -0700 Fixed typo in help text commit 0cbe70eaa40056a9d41070652282694cd7285b1a Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 22 19:08:19 2016 -0700 Fixed typo commit ab11f2aa701f4ff7a8df98d2a4158ea1f661a205 Merge: d90c1e9 7311be4 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 22 19:07:55 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 7311be4028a9caad5a0fac1a3433220b4233ef84 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 22 19:42:08 2016 +0200 Added "shregmap -tech greenpak4" commit 779e2cc819463fa5bc4ebfee397eb06368eb10b0 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 22 18:02:55 2016 +0200 Added support for "active high" and "active low" latches in BLIF front-end commit 60ac1bd178eef96b5cc34091dca7552cc3cad70f Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 22 18:00:46 2016 +0200 Added support for "active high" and "active low" latches in BLIF back-end commit 965b0d59b5da01dc34f01e01d723b75140df7c60 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 22 12:13:06 2016 +0200 More flexible handling of initialization values commit 0bc95f1e049afc35bb5ea30663b0a5725dfbf584 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Apr 21 23:28:37 2016 +0200 Added "yosys -D" feature commit 1565d1af69f552b790aa43fd6be194ee59ab76f3 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Apr 21 19:47:25 2016 +0200 Fixed performance bug in "share" pass commit 5a09fa45535ffceae90359be727d2ff6e0ac2c58 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Apr 21 15:31:54 2016 +0200 Fixed handling of parameters and const functions in casex/casez pattern commit f38ca3e18fb27472595d59be8c0cea7ef50b7c4c Author: Clifford Wolf <clifford@clifford.at> Date: Thu Apr 21 13:02:56 2016 +0200 Improvements in opt_expr commit 1761d08dd239bcf1765ebf807fc22514edac387f Author: Clifford Wolf <clifford@clifford.at> Date: Thu Apr 21 12:06:07 2016 +0200 Bugfix and improvements in memory_share commit d90c1e952256dc00d070863835e061d73e4bc6b3 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 20 20:48:19 2016 -0700 Added GP_VREF cell commit bf64974d43600b2e8ad63a1762489a152c002a41 Merge: f1fa757 8c9ac5d Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 19 10:37:04 2016 +0200 Merge pull request #149 from azonenberg/master GP_RCOSC and GP_SHREG cells plus some cleanup commit 8c9ac5db7bd97fce3bfe5040a238d4f08d726473 Merge: b2c36f6 f1fa757 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Apr 18 19:22:52 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit f1fa757d0e7de4fce01dd4c2b2ec8f1aed0fb1a6 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Apr 18 11:58:21 2016 +0200 Added "shregmap -params" commit 525651c8f6fc5a4f00f3c7b5208d6882f75ac736 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Apr 18 11:44:10 2016 +0200 Added "shregmap -zinit" and "shregmap -init" commit b2c36f6136d0fa3a6203197d78092bc1bb31e998 Merge: be57071 ce7c980 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sun Apr 17 08:15:34 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit ce7c980ec755c481182de9bd078e190bd8d9ff51 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Apr 17 15:37:22 2016 +0200 Improvements in "shregmap" commit be570712d82eafb28850d4400f2220991c3864a4 Merge: d0aaf8d de647a3 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 16 15:14:32 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit de647a390c654bcdb04255c89d5d970cb0c1ed24 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 16 23:20:49 2016 +0200 Added "shregmap" pass commit fbdb8e7b3ed94993228181f949506355989ef54b Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 16 23:20:34 2016 +0200 Fixed copy&paste error in log message in lut2mux commit a07f893a5fd018e426e1aa6de7ad986ea8acd468 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 16 23:20:11 2016 +0200 Minor hashlib bugfix commit d0aaf8d2621fd75b968700ec4cb8dd6acf568737 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 13 23:13:51 2016 -0700 Added GP_SHREG cell commit cdefa60367cf15b2e0a7fb35e4a42fe8358755b5 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 13 23:13:39 2016 -0700 Refactoring: alphabetized cells_sim commit f1679936fe3f40d7fab3438a00dad2fed5a5f00e Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 9 01:18:02 2016 -0700 Fixed missing semicolon commit c1b8d3b580601ad9ba61b247fa967efdfe19fcda Merge: 58d8715 3d9ff91 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 9 01:17:24 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 58d87156815871c47c0ea356ba50b738537adfab Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Apr 9 01:17:13 2016 -0700 Added GP_RCOSC cell commit 3d9ff912c208d330fea12c0149fbe352e9ea7c0a Merge: ace4622 01a5f71 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 8 11:58:40 2016 +0200 Merge pull request #147 from azonenberg/master Added GP_BANDGAP, GP_POR, GP_RINGOSC primitives commit 01a5f711871658c9997f7352414cd4ac50ed772c Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 6 23:42:22 2016 -0700 Fixed assertion failure for non-inferrable counters in some cases commit 48c10d90f4b8c813782d4c5a304b2e1e24d140d8 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 6 23:10:34 2016 -0700 Added second divider to GP_RINGOSC commit 1df559c7062b62a8b72b70d40d65da99667a2183 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 6 22:40:25 2016 -0700 Added GP_RINGOSC primitive commit f6a0f2cf73e8dde315493f113235bbfa27920391 Merge: c2b909c ace4622 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Apr 6 22:31:22 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit ace462237f1223a41f6d29d1fe29652fcf435882 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 5 13:25:23 2016 +0200 Hashlib indenting fix commit 38245b6733d9ec28ae1d37fb5ffba62b0aec791c Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 5 13:25:05 2016 +0200 Added msan origins tracking commit 6041f780c31525c1fc4d34b95317d7946466957b Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 5 12:51:04 2016 +0200 Prefer noninverting FFs in dfflibmap commit eaac5bfbc7faa7144a85590a94d14094899d197f Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 5 08:26:10 2016 +0200 Improved formatting of "sat" output tables commit 3920bf58d01ad9b34a7afba5bfa2f19ffff53240 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Apr 5 08:18:21 2016 +0200 Fixed some typos commit c2b909c051edf189d6e1f807bb367c3c543dc058 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Apr 4 21:46:07 2016 -0700 Added GP_POR commit c01ff05fabe948acfbbb259e92b3bd0009bd068e Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Apr 4 16:56:43 2016 -0700 Added GP_BANDGAP cell commit e4e6becba9259a125bfd2788d453f5ac33272d2f Merge: 27e0d29 71f9f40 Author: Clifford Wolf <clifford@clifford.at> Date: Sun Apr 3 17:16:26 2016 +0200 Merge pull request #145 from laanwj/master Add instructions for building manual on Ubuntu commit 71f9f40fa9e44351f7a9ebabff622c2569689745 Author: Wladimir J. van der Laan <laanwj@gmail.com> Date: Sun Apr 3 14:26:56 2016 +0200 Fix a few typos in the manual commit f9d7091c3b04fd9aa067ed1c087a29faac55d640 Author: Wladimir J. van der Laan <laanwj@gmail.com> Date: Sun Apr 3 14:26:46 2016 +0200 Add instructions for building manual on Ubuntu commit 27e0d29863bcf80520993574415f79b32312c5fb Merge: 7a4dd27 34667de Author: Clifford Wolf <clifford@clifford.at> Date: Sat Apr 2 10:19:36 2016 +0200 Merge pull request #144 from azonenberg/master Added COUNT_EXTRACT constraint to greenpak4_counters pass. Added support for inferring level-resettable counters. Fixed use-after-free. commit 34667ded53ca50d612dc71302544fdde744d853d Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 1 23:41:03 2016 -0700 Removed more debug prints commit 87e7cd9fbd6e603da262e68f7ec68eb0d7233c2c Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 1 23:39:32 2016 -0700 Removed forgotten debug code commit 2386885f228ebecccf4987ac81bde11df56dae38 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 1 21:18:29 2016 -0700 Added GreenPak inverter support commit b0a28c793cebcd1a7317b63b215151ce9ace3a42 Merge: 6dbcf50 7a4dd27 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 1 18:09:08 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 6dbcf50fa1ea8591d8d944234627e6918612060b Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 1 18:07:59 2016 -0700 Added support for inferring counters with asynchronous resets. Fixed use-after-free in inference pass. commit 7a4dd27b1b36e4e4667f31ee7b3c6e6bc3896f60 Merge: 2553319 f277267 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Apr 1 09:13:52 2016 +0200 Merge pull request #143 from azonenberg/master Fixed several techmapping issues irelated to greenpak flipflops commit f277267916b7b1c97fe90576abecde003cc231ab Merge: 736a998 2553319 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Fri Apr 1 00:03:00 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 736a998a75e12ca83b45b74a79e78fae8ab12d16 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Thu Mar 31 23:16:45 2016 -0700 DFFINIT is now correctly called for all kinds of flipflop, not just DFF commit 7498ff8041cdd464521a6802055a9893a0c6cf61 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Thu Mar 31 22:51:22 2016 -0700 Fixed incorrect port name in cells_map.v commit 25533190818b0fe207be9a4626a9a273a08ae219 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 11:16:34 2016 +0200 Added ScriptPass helper class for script-like passes commit 6cafd08ac1090f405168187632fab4308129c599 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 09:58:55 2016 +0200 Improved opt_merge support for $pmux cells commit 6f1b6dc322bf6cceeadef7c666b8ff333ec6f2bf Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 09:57:44 2016 +0200 Added log_dump() support for dict<> and pool<> containers commit e5dd5c0bcccd4e79921e6a28b550a5960a93ee07 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 09:57:23 2016 +0200 Preserve empty $pmux default cases commit e2f6d61c004776f2f573f3c5b70ad352ce6b4e1a Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 09:56:56 2016 +0200 Typo fixes in opt_expr and opt_merge commit c04a3d276320aa9aca4e3a678df3135b35473055 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 23:58:45 2016 -0700 Fixed typo (wasn't written in 2012) commit ec93680bd583b670e03ed98b4b1081eab8d0f3f6 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 08:52:49 2016 +0200 Renamed opt_share to opt_merge commit 1d0f0d668ade740c928c66c400476924abf62384 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 08:43:28 2016 +0200 Renamed opt_const to opt_expr commit d31c968d76e99d5c7288d0eb844e041bb36aa77d Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 08:00:59 2016 +0200 Fixed typo in greenpak4_counters.cc commit cecd0cf788a7fcefe6e88c32557fd844482a1c9c Merge: 0db5328 984561c Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 31 07:59:55 2016 +0200 Merge pull request #142 from azonenberg/master Add initial GreenPak4 counter inference, misc related fixes commit 984561c034bac0b996d8b2201105a795c6c0e00d Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 22:52:01 2016 -0700 Renamed counters pass to greenpak4_counters commit 1ae33344f4f18f4fbb899e4635659bf1cd8f0448 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 22:40:14 2016 -0700 Added initial implementation of "counters" pass to synth_greenpak4. Can only infer non-resettable down counters for now. commit 1b42e0c471ba81843e3fbd1869e84b36f8a24c2f Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 22:03:50 2016 -0700 Reduced log verbosity commit ad19e0c64ab69ab059efc258ae616f4fb5b8847d Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 21:54:23 2016 -0700 Continued work on counter extraction. Can recognize compatible RTL counters but not replace with hard macros. commit d16d05e41587a282a53eda59af837b7d264498fc Merge: 94a6923 0db5328 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 20:38:18 2016 -0700 Merge https://github.com/cliffordwolf/yosys commit 94a6923e7dd363c5b11116e9bd85aa012fed512a Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 20:30:25 2016 -0700 Updated tech lib for greenpak4 counter with some clarifications commit dd7204c0bdb65956fdf27925da3ccfe6f592d012 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 20:30:03 2016 -0700 Fixed typo in log message commit 0db53284fd610cac1e956a87c7eec7df3d8564c5 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 30 13:52:26 2016 +0200 We have 2016 for a while now commit 48dbc75beddd6db92f09125b49761859be33693d Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 30 13:24:49 2016 +0200 Added .vhd file extension support commit 489caf32c54ee250338eca72c5f0098106d17788 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Wed Mar 30 01:07:20 2016 -0700 Initial work on greenpak4 counter extraction. Doesn't work but a decent start commit 2c15a3a9d0aad62f92c37bd76b763d6c2cf079b1 Merge: a47f695 19c2023 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 30 10:02:18 2016 +0200 Merge branch 'master' of github.com:cliffordwolf/yosys commit a47f69536a1ac93657d334f57dac2a800ab34f3f Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 30 10:02:03 2016 +0200 Added support for installed plugins commit 3ea60266488fe7e0b040c379a11d523c11ec9460 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Tue Mar 29 20:02:59 2016 -0700 Added splitnets to synth_greenpak4 commit 19c20235b55648c150df294320b9f2515d2f3c5b Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 29 15:12:14 2016 +0200 Added more cell help messages commit 8c8b2e72b1b34f6219c87e7bd5b39620947cd787 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 29 13:44:14 2016 +0200 Fixed indenting in techlibs/greenpak4/gp_dff.lib commit d4472ae9453c3eb713e2260b198d0236632a60b7 Merge: 9578443 75f0030 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 29 09:53:35 2016 +0200 Merge pull request #141 from azonenberg/master Add Greenpak4 SYSRESET block support commit 75f0030458a6c5e37238e2437ea469ba9dfd389b Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Mar 28 23:16:43 2016 -0700 Added keep constraint to GP_SYSRESET cell commit ea9cc0309245c8d1af5d34b836238f197d34e332 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Mon Mar 28 22:49:46 2016 -0700 Added GP_SYSRESET block commit 95784437ac237be981d0cf573386ba22f28f9624 Merge: 2ec832d 963c0d2 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 28 16:54:23 2016 +0200 Merge pull request #137 from ravenexp/master Embed DATDIR make variable value into yosys binary. commit 2ec832ddced03aff3fb5cef53ae935f39d32547c Merge: aade2c2 73870c1 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 28 16:53:47 2016 +0200 Merge pull request #138 from SebKuzminsky/help-typo fix a cut-n-paste error in the -h help commit aade2c21fa4bdbeb129122d4b1832459e30aec82 Merge: a922d70 3197b6c Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 28 16:53:24 2016 +0200 Merge pull request #139 from azonenberg/master Add GreenPak4 LF oscillator support, renamed internal cell for consistency commit 3197b6c3721b4985b5a5e4223ce7092e27f750c7 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Mar 26 23:29:02 2016 -0700 Added GP_COUNT8/GP_COUNT14 cells commit 31a7567affb7425af1aa27d6dcda4666859ce62f Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Mar 26 14:13:52 2016 -0700 Changed GP_LFOSC parameter configuration commit 44fd3cd149786bc3aaf180af8ec83f790d9cebbe Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Mar 26 13:42:53 2016 -0700 Added GP_LFOSC cell commit af15b92c861f11d1f4b5016fed0cb8cb45af9175 Author: Andrew Zonenberg <azonenberg@drawersteak.com> Date: Sat Mar 26 13:42:41 2016 -0700 Renamed GP4_V* cells to GP_V* for consistency commit 73870c1edfb72a402d69394b5dc6b0a7dd5bb596 Author: Sebastian Kuzminsky <seb@highlab.com> Date: Sat Mar 26 11:15:35 2016 -0600 fix a cut-n-paste error in the -h help commit 963c0d2525c9d7af9a2c7640b554923f3a4f647e Author: Sergey Kvachonok <ravenexp@gmail.com> Date: Sat Mar 26 11:01:53 2016 +0300 Embed DATDIR make variable value into yosys binary. Use it as the last resort in the share/ directory location search. commit a922d705d4c5e5c2f0cfc59f31fa11901ef307e1 Merge: 5328a85 e14055e Author: Clifford Wolf <clifford@clifford.at> Date: Fri Mar 25 09:16:45 2016 +0100 Merge pull request #136 from ravenexp/master Minor Makefile adjustments commit e14055edf06f4551f220b3875a95d8c25b8b7aae Author: Sergey Kvachonok <ravenexp@gmail.com> Date: Fri Mar 25 08:47:45 2016 +0300 Optionally use ${CC} when compiling test utils. Default to gcc when not set. commit d53a16e43a6db35b15584e582c64cfac0f7e5e3d Author: Sergey Kvachonok <ravenexp@gmail.com> Date: Thu Mar 24 16:07:05 2016 +0300 Allow redefining pkg-config Makefile command. Example usage: $ make CXX=i686-w64-mingw32-g++ PKG_CONFIG=i686-w64-mingw32-pkg-config commit 972f4a9616006f6030d1627c65f5ced68aabfff4 Author: Sergey Kvachonok <ravenexp@gmail.com> Date: Thu Mar 24 12:18:21 2016 +0300 Allow redefining binary and data install locations. Add three more Makefile variables in addition to PREFIX: $ make BINDIR=/.../bin LIBDIR=/.../lib DATDIR=/.../share/yosys The defaults are: BINDIR = $(PREFIX)/bin LIBDIR = $(PREFIX)/lib DATDIR = $(PREFIX)/share/yosys commit 5328a851490588d6162ca0edaad5ed713bc75401 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 24 12:16:32 2016 +0100 Do not set "nosync" on task outputs, fixes #134 commit 9717495401e58a3d0a41113b541442227daa7cc3 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 23 08:56:08 2016 +0100 Fixed handling of inverters (aka 1-input luts) in nlutmap commit b4bf787f1091c79d6fed6ac1ec91ebadbceb8023 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 23 08:46:10 2016 +0100 Added GP_DFFS, GP_DFFR, and GP_DFFSR commit 456c10f16e5b535fc5aa95eacfabbe018fef2348 Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 23 08:12:54 2016 +0100 Added GP_DFF INIT parameter commit 4f2ea221dcdc632cdbb22f91403d076b61ec69ca Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 22 14:46:10 2016 +0100 Added ast.h to exported headers commit 043fa0fad039287ee1b6a6fec3d925b9c7304af8 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 21 16:33:34 2016 +0100 Cleanup abstract modules at end of "hierarchy -top" commit 2c7e107d7a55a47fe6f6943e4541014649b57567 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 21 16:30:55 2016 +0100 Support for abstract modules in chparam commit 4f0d4899ce2c93f1f4eef685b03d9f06d4433429 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 21 16:19:51 2016 +0100 Added support for $stop system task commit ca8f8e30f20fd48127003486f1701ac17fd35aa6 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 21 09:44:52 2016 +0100 Improvements in synth_greenpak4, added -part option commit bb9374b67c583761f4bdc72dbd19a79940d51082 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Mar 19 20:02:40 2016 +0100 Improvements in ABCEXTERNAL handling commit b471a32ec3c563bcb02b84a15217beca18b409ab Merge: e5d42eb 2656b2c Author: Clifford Wolf <clifford@clifford.at> Date: Sat Mar 19 19:46:27 2016 +0100 Merge pull request #130 from ravenexp/master Support calling out to an external ABC. commit 2656b2c55a139bc158cb67b18dd201bd0f4cf0c6 Author: Sergey Kvachonok <ravenexp@gmail.com> Date: Sat Mar 19 18:36:18 2016 +0300 Support calling out to an external ABC. $ make ABCEXTERNAL=my-abc && make ABCEXTERNAL=my-abc install configures yosys to use an external ABC executable instead of building and installing the in-tree ABC copy (yosys-abc). commit e5d42ebb4d921aa9b9ad952b063f6ca2e3ffd9db Author: Clifford Wolf <clifford@clifford.at> Date: Sat Mar 19 11:51:13 2016 +0100 Added $display %m support, fixed mem leak in $display, fixes #128 commit ff5c61b1207304e97714d40d37c1627510cc08a8 Author: Clifford Wolf <clifford@clifford.at> Date: Sat Mar 19 11:09:10 2016 +0100 Added black box modules for all the 7-series design elements (as listed in ug953) commit ef4207d5ade8254c9b0f63cac2ad5fee310362d4 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Mar 18 12:15:00 2016 +0100 Fixed localparam signdness, fixes #127 commit b6d08f39baf508951ef36bedbd583f2b9fb48d1b Author: Clifford Wolf <clifford@clifford.at> Date: Fri Mar 18 10:53:29 2016 +0100 Set "nosync" attribute on internal task/function wires commit 33c10350b22a8cc943cf3c294ee86969c5ce97f4 Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 15 12:22:31 2016 +0100 Fixed Verilog parser fix and more similar improvements commit 81d4e9e7c1c311f837dadb1634c83b4e70929669 Author: Andrew Becker <andrew.becker@epfl.ch> Date: Mon Mar 14 19:28:34 2016 +0100 Use left-recursive rule for cell_port_list in Verilog parser. commit 2a8d5e64f5a994fa8f4f51c00d647ad977e42e4b Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 14 13:03:28 2016 +0100 Bugfix in write_verilog for RTLIL processes commit dac807fb33a3619dea955ce4b16342e6e0008111 Author: Clifford Wolf <clifford@clifford.at> Date: Fri Mar 11 11:30:01 2016 +0100 Cleanups and improvements in examples/cmos/ commit 3265795154200786adbb399c6615915a6641f958 Merge: 35a6ad4 b34385e Author: Clifford Wolf <clifford@clifford.at> Date: Fri Mar 11 11:10:44 2016 +0100 Merge commit 'b34385ec924b6067c1f82bdbae923f8062518956' commit 35a6ad4cc162d0f6aeec5bab1fd52d6ca041d868 Author: Clifford Wolf <clifford@clifford.at> Date: Thu Mar 10 11:14:51 2016 +0100 Fixed typos in verilog_defaults help message commit d117893007baa506b702967ac6ee9f70af3c236a Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 8 21:30:45 2016 +0100 Added "write_edif -nogndvcc" commit dcd4fb998435b13193a9816e54d4c6b9284d119b Author: Clifford Wolf <clifford@clifford.at> Date: Tue Mar 8 16:54:15 2016 +0100 Added examples/cxx-api/evaldemo.cc commit e7ed653771ab3483f988f4adfca5c635c10c3480 Merge: c4aaed0 b0ac32b Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 7 11:17:44 2016 +0100 Merge branch 'master' of github.com:cliffordwolf/yosys commit c4aaed099f948f8212898faecfc0f09027347928 Author: Clifford Wolf <clifford@clifford.at> Date: Mon Mar 7 11:14:11 2016 +0100 Using "mfs" and "lutpack" in ABC lut mapping commit b34385ec924b6067c1f82bdbae923f8062518956 Author: Uros Platise <uros@isotel.eu> Date: Sat Mar 5 08:34:05 2016 +0100 Completed ngspice digital example with verilog tb commit b0ac32bc03b340b26e0d3bb778af1c915722abdf Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 2 12:07:57 2016 +0100 Added digital (xspice) example code to examples/cmos/ commit 5547fae4cf2e254d2f35f76f5c0b07abec2376dd Author: Clifford Wolf <clifford@clifford.at> Date: Wed Mar 2 12:02:59 2016 +0100 Be more conservative with net names in spice output commit b36cad75f6d785559391ca7875d893f40736c305 Merge: c89f61c 7e6426a Author: Clifford Wolf <clifford@clifford.at> Date: Mon Feb 29 10:18:50 2016 +0100 Merge pull request #119 from SebKuzminsky/spelling-fixes user-facing spelling fixes commit 7e6426a67da352e0ea41f80b9303087545cb12ac Author: Sebastian Kuzminsky <seb@highlab.com> Date: Sun Feb 28 15:14:01 2016 -0700 user-facing spelling fixes "speciefied" -> "specified" "unkown" -> "unknown" commit 7c623182393aa2e8445336a99f0cfd4bc7c7e88f Author: eddiehung <e.hung@imperial.ac.uk> Date: Sun May 3 12:53:09 2015 +0100 Fix for all zero mask commit 079c1205fec6d194114b3d031d78a23cb8e0e7f9 Author: eddiehung <e.hung@imperial.ac.uk> Date: Sun May 3 10:37:20 2015 +0100 Escape '<' and '>' some more commit 872e13321c4c39997d3b14408224ef1c2fcc0821 Author: eddiehung <e.hung@imperial.ac.uk> Date: Tue Apr 28 08:56:00 2015 +0100 For vtr, escape angle brackets as well commit 058deb777e72458fa018e21eaf0322ca75b86fd7 Author: eddiehung <e.hung@imperial.ac.uk> Date: Tue Apr 28 08:55:26 2015 +0100 blifwriter: write out .names for true/false/undef type == '-'
Diffstat (limited to 'passes')
-rw-r--r--passes/cmds/check.cc2
-rw-r--r--passes/cmds/connwrappers.cc2
-rw-r--r--passes/cmds/cover.cc2
-rw-r--r--passes/cmds/plugin.cc8
-rw-r--r--passes/cmds/qwp.cc32
-rw-r--r--passes/cmds/scc.cc8
-rw-r--r--passes/cmds/select.cc42
-rw-r--r--passes/cmds/setattr.cc6
-rw-r--r--passes/cmds/setundef.cc94
-rw-r--r--passes/cmds/show.cc18
-rw-r--r--passes/cmds/splice.cc2
-rw-r--r--passes/cmds/splitnets.cc2
-rw-r--r--passes/cmds/stat.cc2
-rw-r--r--passes/cmds/tee.cc10
-rw-r--r--passes/cmds/torder.cc2
-rw-r--r--passes/equiv/equiv_induct.cc2
-rw-r--r--passes/equiv/equiv_make.cc2
-rw-r--r--passes/equiv/equiv_mark.cc2
-rw-r--r--passes/equiv/equiv_miter.cc2
-rw-r--r--passes/equiv/equiv_purge.cc2
-rw-r--r--passes/equiv/equiv_remove.cc2
-rw-r--r--passes/equiv/equiv_simple.cc2
-rw-r--r--passes/equiv/equiv_status.cc2
-rw-r--r--passes/equiv/equiv_struct.cc2
-rw-r--r--passes/fsm/fsm.cc2
-rw-r--r--passes/fsm/fsm_detect.cc139
-rw-r--r--passes/fsm/fsm_expand.cc2
-rw-r--r--passes/fsm/fsm_export.cc2
-rw-r--r--passes/fsm/fsm_extract.cc9
-rw-r--r--passes/fsm/fsm_info.cc2
-rw-r--r--passes/fsm/fsm_map.cc2
-rw-r--r--passes/fsm/fsm_opt.cc2
-rw-r--r--passes/fsm/fsm_recode.cc2
-rw-r--r--passes/hierarchy/hierarchy.cc20
-rw-r--r--passes/hierarchy/singleton.cc2
-rw-r--r--passes/hierarchy/submod.cc6
-rw-r--r--passes/memory/Makefile.inc1
-rw-r--r--passes/memory/memory.cc15
-rw-r--r--passes/memory/memory_bram.cc7
-rw-r--r--passes/memory/memory_collect.cc18
-rw-r--r--passes/memory/memory_dff.cc2
-rw-r--r--passes/memory/memory_map.cc2
-rw-r--r--passes/memory/memory_memx.cc92
-rw-r--r--passes/memory/memory_share.cc51
-rw-r--r--passes/memory/memory_unpack.cc2
-rw-r--r--passes/opt/Makefile.inc4
-rw-r--r--passes/opt/opt.cc52
-rw-r--r--passes/opt/opt_clean.cc5
-rw-r--r--passes/opt/opt_expr.cc (renamed from passes/opt/opt_const.cc)216
-rw-r--r--passes/opt/opt_merge.cc (renamed from passes/opt/opt_share.cc)70
-rw-r--r--passes/opt/opt_muxtree.cc4
-rw-r--r--passes/opt/opt_reduce.cc2
-rw-r--r--passes/opt/opt_rmdff.cc123
-rw-r--r--passes/opt/share.cc55
-rw-r--r--passes/opt/wreduce.cc31
-rw-r--r--passes/proc/proc.cc16
-rw-r--r--passes/proc/proc_arst.cc2
-rw-r--r--passes/proc/proc_clean.cc2
-rw-r--r--passes/proc/proc_dff.cc2
-rw-r--r--passes/proc/proc_dlatch.cc147
-rw-r--r--passes/proc/proc_init.cc31
-rw-r--r--passes/proc/proc_mux.cc53
-rw-r--r--passes/proc/proc_rmdead.cc6
-rw-r--r--passes/sat/Makefile.inc1
-rw-r--r--passes/sat/assertpmux.cc240
-rw-r--r--passes/sat/eval.cc2
-rw-r--r--passes/sat/expose.cc2
-rw-r--r--passes/sat/freduce.cc2
-rw-r--r--passes/sat/miter.cc12
-rw-r--r--passes/sat/sat.cc217
-rw-r--r--passes/techmap/Makefile.inc8
-rw-r--r--passes/techmap/abc.cc216
-rw-r--r--passes/techmap/aigmap.cc2
-rw-r--r--passes/techmap/alumacc.cc2
-rw-r--r--passes/techmap/attrmap.cc250
-rw-r--r--passes/techmap/attrmvcp.cc139
-rw-r--r--passes/techmap/deminout.cc116
-rw-r--r--passes/techmap/dff2dffe.cc2
-rw-r--r--passes/techmap/dffinit.cc2
-rw-r--r--passes/techmap/dfflibmap.cc26
-rw-r--r--passes/techmap/dffsr2dff.cc2
-rw-r--r--passes/techmap/extract.cc10
-rw-r--r--passes/techmap/hilomap.cc2
-rw-r--r--passes/techmap/insbuf.cc94
-rw-r--r--passes/techmap/iopadmap.cc168
-rw-r--r--passes/techmap/lut2mux.cc2
-rw-r--r--passes/techmap/maccmap.cc2
-rw-r--r--passes/techmap/muxcover.cc2
-rw-r--r--passes/techmap/nlutmap.cc20
-rw-r--r--passes/techmap/pmuxtree.cc2
-rw-r--r--passes/techmap/shregmap.cc584
-rw-r--r--passes/techmap/simplemap.cc33
-rw-r--r--passes/techmap/techmap.cc48
-rw-r--r--passes/techmap/tribuf.cc2
-rw-r--r--passes/tests/test_autotb.cc63
-rw-r--r--passes/tests/test_cell.cc171
96 files changed, 3338 insertions, 557 deletions
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index 2ad84838..b3622cb1 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -68,7 +68,7 @@ struct CheckPass : public Pass {
}
extra_args(args, argidx, design);
- log_header("Executing CHECK pass (checking for obvious problems).\n");
+ log_header(design, "Executing CHECK pass (checking for obvious problems).\n");
for (auto module : design->selected_whole_modules_warn())
{
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index 7828dce1..c9ab226d 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -198,7 +198,7 @@ struct ConnwrappersPass : public Pass {
}
extra_args(args, argidx, design);
- log_header("Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n");
+ log_header(design, "Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n");
for (auto &mod_it : design->modules_)
if (design->selected(mod_it.second))
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 5644066a..1475475c 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -124,7 +124,7 @@ struct CoverPass : public Pass {
extra_args(args, argidx, design);
if (do_log) {
- log_header("Printing code coverage counters.\n");
+ log_header(design, "Printing code coverage counters.\n");
log("\n");
}
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index e2d80d9b..828c671d 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -31,19 +31,23 @@ std::map<std::string, std::string> loaded_plugin_aliases;
#ifdef YOSYS_ENABLE_PLUGINS
void load_plugin(std::string filename, std::vector<std::string> aliases)
{
+ std::string orig_filename = filename;
+
if (filename.find('/') == std::string::npos)
filename = "./" + filename;
if (!loaded_plugins.count(filename)) {
void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL);
+ if (hdl == NULL && orig_filename.find('/') == std::string::npos)
+ hdl = dlopen((proc_share_dirname() + "plugins/" + orig_filename + ".so").c_str(), RTLD_LAZY|RTLD_LOCAL);
if (hdl == NULL)
log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror());
- loaded_plugins[filename] = hdl;
+ loaded_plugins[orig_filename] = hdl;
Pass::init_register();
}
for (auto &alias : aliases)
- loaded_plugin_aliases[alias] = filename;
+ loaded_plugin_aliases[alias] = orig_filename;
}
#else
void load_plugin(std::string, std::vector<std::string>)
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index 8ec815a7..1b800b6d 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -40,6 +40,7 @@ struct QwpConfig
{
bool ltr;
bool alpha;
+ bool verbose;
double grid;
std::ofstream dump_file;
@@ -47,6 +48,7 @@ struct QwpConfig
QwpConfig() {
ltr = false;
alpha = false;
+ verbose = false;
grid = 1.0 / 16;
}
};
@@ -211,10 +213,16 @@ struct QwpWorker
//
// M := [AA Ay]
+ if (config.verbose)
+ log("> System size: %d^2\n", GetSize(nodes));
+
// Row major order
int N = GetSize(nodes), N1 = N+1;
vector<double> M(N * N1);
+ if (config.verbose)
+ log("> Edge constraints: %d\n", GetSize(edges));
+
// Edge constraints:
// A[i,:] := [ 0 0 .... 0 weight 0 ... 0 -weight 0 ... 0 0], y[i] := 0
//
@@ -232,6 +240,9 @@ struct QwpWorker
M[idx2 + idx1*N1] += -weight * weight;
}
+ if (config.verbose)
+ log("> Node constraints: %d\n", GetSize(nodes));
+
// Node constraints:
// A[i,:] := [ 0 0 .... 0 weight 0 ... 0 0], y[i] := weight * pos
//
@@ -263,6 +274,9 @@ struct QwpWorker
}
#endif
+ if (config.verbose)
+ log("> Solving\n");
+
// Solve "AA*x = Ay"
// (least squares fit for "A*x = y")
//
@@ -277,6 +291,9 @@ struct QwpWorker
// gaussian elimination
for (int i = 0; i < N; i++)
{
+ if (config.verbose && ((i+1) % (N/15)) == 0)
+ log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N);
+
// find best row
int best_row = queue.front();
int best_row_queue_idx = 0;
@@ -312,6 +329,9 @@ struct QwpWorker
}
}
+ if (config.verbose)
+ log("> Solved\n");
+
log_assert(queue.empty());
log_assert(GetSize(pivot_cache) == N);
@@ -334,6 +354,9 @@ struct QwpWorker
}
#endif
+ if (config.verbose)
+ log("> Update nodes\n");
+
// update node positions
for (int i = 0; i < N; i++)
{
@@ -778,6 +801,9 @@ struct QwpPass : public Pass {
log(" -dump <html_file_name>\n");
log(" Dump a protocol of the placement algorithm to the html file.\n");
log("\n");
+ log(" -v\n");
+ log(" Verbose solver output for profiling or debugging\n");
+ log("\n");
log("Note: This implementation of a quadratic wirelength placer uses exact\n");
log("dense matrix operations. It is only a toy-placer for small circuits.\n");
log("\n");
@@ -787,7 +813,7 @@ struct QwpPass : public Pass {
QwpConfig config;
xorshift32_state = 123456789;
- log_header("Executing QWP pass (quadratic wirelength placer).\n");
+ log_header(design, "Executing QWP pass (quadratic wirelength placer).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -799,6 +825,10 @@ struct QwpPass : public Pass {
config.alpha = true;
continue;
}
+ if (args[argidx] == "-v") {
+ config.verbose = true;
+ continue;
+ }
if (args[argidx] == "-grid" && argidx+1 < args.size()) {
config.grid = 1.0 / atoi(args[++argidx].c_str());
continue;
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index 532026f2..bb6d7447 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -181,10 +181,10 @@ struct SccWorker
cell2scc[cell] = sccList.size();
scc.insert(cell);
sccList.push_back(scc);
- workQueue.erase(cell);
log("\n");
- } else
- run(cell, 0, maxDepth);
+ }
+
+ run(cell, 0, maxDepth);
}
log("Found %d SCCs in module %s.\n", int(sccList.size()), RTLIL::id2cstr(module->name));
@@ -264,7 +264,7 @@ struct SccPass : public Pass {
int maxDepth = -1;
int expect = -1;
- log_header("Executing SCC pass (detecting logic loops).\n");
+ log_header(design, "Executing SCC pass (detecting logic loops).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index 3e64dd84..d2e1a2e2 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -952,7 +952,7 @@ struct SelectPass : public Pass {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" select [ -add | -del | -set <name> ] {-read <filename> | <selection>}\n");
- log(" select [ -assert-none | -assert-any ] {-read <filename> | <selection>}\n");
+ log(" select [ <assert_option> ] {-read <filename> | <selection>}\n");
log(" select [ -list | -write <filename> | -count | -clear ]\n");
log(" select -module <modname>\n");
log("\n");
@@ -988,6 +988,14 @@ struct SelectPass : public Pass {
log(" do not modify the current selection. instead assert that the given\n");
log(" selection contains exactly N objects.\n");
log("\n");
+ log(" -assert-max N\n");
+ log(" do not modify the current selection. instead assert that the given\n");
+ log(" selection contains less than or exactly N objects.\n");
+ log("\n");
+ log(" -assert-min N\n");
+ log(" do not modify the current selection. instead assert that the given\n");
+ log(" selection contains at least N objects.\n");
+ log("\n");
log(" -list\n");
log(" list all objects in the current selection\n");
log("\n");
@@ -1168,6 +1176,8 @@ struct SelectPass : public Pass {
bool assert_none = false;
bool assert_any = false;
int assert_count = -1;
+ int assert_max = -1;
+ int assert_min = -1;
std::string write_file, read_file;
std::string set_name, sel_str;
@@ -1197,6 +1207,14 @@ struct SelectPass : public Pass {
assert_count = atoi(args[++argidx].c_str());
continue;
}
+ if (arg == "-assert-max" && argidx+1 < args.size()) {
+ assert_max = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (arg == "-assert-min" && argidx+1 < args.size()) {
+ assert_min = atoi(args[++argidx].c_str());
+ continue;
+ }
if (arg == "-clear") {
clear_mode = true;
continue;
@@ -1273,14 +1291,14 @@ struct SelectPass : public Pass {
if (none_mode && args.size() != 2)
log_cmd_error("Option -none can not be combined with any other options.\n");
- if (add_mode + del_mode + assert_none + assert_any + (assert_count >= 0) > 1)
- log_cmd_error("Options -add, -del, -assert-none, -assert-any or -assert-count can not be combined.\n");
+ if (add_mode + del_mode + assert_none + assert_any + (assert_count >= 0) + (assert_max >= 0) + (assert_min >= 0) > 1)
+ log_cmd_error("Options -add, -del, -assert-none, -assert-any, assert-count, -assert-max or -assert-min can not be combined.\n");
- if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0))
- log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any or -assert-count.\n");
+ if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
+ log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any, assert-count, -assert-max, or -assert-min.\n");
- if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0))
- log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any or -assert-count.\n");
+ if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
+ log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n");
if (work_stack.size() == 0 && got_module) {
RTLIL::Selection sel;
@@ -1385,7 +1403,7 @@ struct SelectPass : public Pass {
return;
}
- if (assert_count >= 0)
+ if (assert_count >= 0 || assert_max >= 0 || assert_min >= 0)
{
int total_count = 0;
if (work_stack.size() == 0)
@@ -1407,9 +1425,15 @@ struct SelectPass : public Pass {
if (sel->selected_member(mod_it.first, it.first))
total_count++;
}
- if (assert_count != total_count)
+ if (assert_count >= 0 && assert_count != total_count)
log_error("Assertion failed: selection contains %d elements instead of the asserted %d:%s\n",
total_count, assert_count, sel_str.c_str());
+ if (assert_max >= 0 && assert_max < total_count)
+ log_error("Assertion failed: selection contains %d elements, more than the maximum number %d:%s\n",
+ total_count, assert_max, sel_str.c_str());
+ if (assert_min >= 0 && assert_min > total_count)
+ log_error("Assertion failed: selection contains %d elements, less than the minimum number %d:%s\n",
+ total_count, assert_min, sel_str.c_str());
return;
}
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 75c738b6..9b05ae32 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -215,6 +215,12 @@ struct ChparamPass : public Pass {
}
break;
}
+
+ for (int i = argidx; i < GetSize(args); i++)
+ if (design->module("$abstract\\" + args[i]) != nullptr &&
+ design->module(RTLIL::escape_id(args[i])) == nullptr)
+ args[i] = "$abstract\\" + args[i];
+
extra_args(args, argidx, design);
do_setunset(new_parameters, setunset_list);
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 9ca2e874..26b2eb87 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -79,11 +79,15 @@ struct SetundefPass : public Pass {
log(" replace with random bits using the specified integer als seed\n");
log(" value for the random number generator.\n");
log("\n");
+ log(" -init\n");
+ log(" also create/update init values for flip-flops\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
bool got_value = false;
bool undriven_mode = false;
+ bool init_mode = false;
SetundefWorker worker;
size_t argidx;
@@ -103,6 +107,10 @@ struct SetundefPass : public Pass {
worker.next_bit_mode = 1;
continue;
}
+ if (args[argidx] == "-init") {
+ init_mode = true;
+ continue;
+ }
if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
got_value = true;
worker.next_bit_mode = 2;
@@ -118,12 +126,8 @@ struct SetundefPass : public Pass {
if (!got_value)
log_cmd_error("One of the options -zero, -one, or -random <seed> must be specified.\n");
- for (auto &mod_it : design->modules_)
+ for (auto module : design->selected_modules())
{
- RTLIL::Module *module = mod_it.second;
- if (!design->selected(module))
- continue;
-
if (undriven_mode)
{
if (!module->processes.empty())
@@ -151,6 +155,86 @@ struct SetundefPass : public Pass {
}
}
+ if (init_mode)
+ {
+ SigMap sigmap(module);
+ pool<SigBit> ffbits;
+ pool<Wire*> initwires;
+
+ pool<IdString> fftypes;
+ fftypes.insert("$dff");
+ fftypes.insert("$dffe");
+ fftypes.insert("$dffsr");
+ fftypes.insert("$adff");
+
+ std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
+
+ for (auto c1 : list_np)
+ fftypes.insert(stringf("$_DFF_%c_", c1));
+
+ for (auto c1 : list_np)
+ for (auto c2 : list_np)
+ fftypes.insert(stringf("$_DFFE_%c%c_", c1, c2));
+
+ for (auto c1 : list_np)
+ for (auto c2 : list_np)
+ for (auto c3 : list_01)
+ fftypes.insert(stringf("$_DFF_%c%c%c_", c1, c2, c3));
+
+ for (auto c1 : list_np)
+ for (auto c2 : list_np)
+ for (auto c3 : list_np)
+ fftypes.insert(stringf("$_DFFSR_%c%c%c_", c1, c2, c3));
+
+ for (auto cell : module->cells())
+ {
+ if (!fftypes.count(cell->type))
+ continue;
+
+ for (auto bit : sigmap(cell->getPort("\\Q")))
+ ffbits.insert(bit);
+ }
+
+ for (auto wire : module->wires())
+ {
+ if (!wire->attributes.count("\\init"))
+ continue;
+
+ for (auto bit : sigmap(wire))
+ ffbits.erase(bit);
+
+ initwires.insert(wire);
+ }
+
+ for (int wire_types = 0; wire_types < 2; wire_types++)
+ for (auto wire : module->wires())
+ {
+ if (wire->name[0] == (wire_types ? '\\' : '$'))
+ next_wire:
+ continue;
+
+ for (auto bit : sigmap(wire))
+ if (!ffbits.count(bit))
+ goto next_wire;
+
+ for (auto bit : sigmap(wire))
+ ffbits.erase(bit);
+
+ initwires.insert(wire);
+ }
+
+ for (auto wire : initwires)
+ {
+ Const &initval = wire->attributes["\\init"];
+
+ for (int i = 0; i < GetSize(wire); i++)
+ if (GetSize(initval) <= i)
+ initval.bits.push_back(worker.next_bit());
+ else if (initval.bits[i] == State::Sx)
+ initval.bits[i] = worker.next_bit();
+ }
+ }
+
module->rewrite_sigspecs(worker);
}
}
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 3b03d680..3a3939a8 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -582,8 +582,9 @@ struct ShowPass : public Pass {
log(" Run the specified command with the graphics file as parameter.\n");
log("\n");
log(" -format <format>\n");
- log(" Generate a graphics file in the specified format.\n");
- log(" Usually <format> is 'svg' or 'ps'.\n");
+ log(" Generate a graphics file in the specified format. Use 'dot' to just\n");
+ log(" generate a .dot file, or other <format> strings such as 'svg' or 'ps'\n");
+ log(" to generate files in other formats (this calls the 'dot' command).\n");
log("\n");
log(" -lib <verilog_or_ilang_file>\n");
log(" Use the specified library file for determining whether cell ports are\n");
@@ -646,12 +647,13 @@ struct ShowPass : public Pass {
log("unless another prefix is specified using -prefix <prefix>.\n");
log("\n");
log("Yosys on Windows and YosysJS use different defaults: The output is written\n");
- log("to 'show.dot' in the current directory and new viewer is launched.\n");
+ log("to 'show.dot' in the current directory and new viewer is launched each time\n");
+ log("the 'show' command is executed.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Generating Graphviz representation of design.\n");
+ log_header(design, "Generating Graphviz representation of design.\n");
log_push();
std::vector<std::pair<std::string, RTLIL::Selection>> color_selections;
@@ -759,7 +761,7 @@ struct ShowPass : public Pass {
}
extra_args(args, argidx, design);
- if (format != "ps") {
+ if (format != "ps" && format != "dot") {
int modcount = 0;
for (auto &mod_it : design->modules_) {
if (mod_it.second->get_bool_attribute("\\blackbox"))
@@ -770,7 +772,7 @@ struct ShowPass : public Pass {
modcount++;
}
if (modcount > 1)
- log_cmd_error("For formats different than 'ps' only one module must be selected.\n");
+ log_cmd_error("For formats different than 'ps' or 'dot' only one module must be selected.\n");
}
for (auto filename : libfiles) {
@@ -784,7 +786,7 @@ struct ShowPass : public Pass {
}
if (libs.size() > 0)
- log_header("Continuing show pass.\n");
+ log_header(design, "Continuing show pass.\n");
std::string dot_file = stringf("%s.dot", prefix.c_str());
std::string out_file = stringf("%s.%s", prefix.c_str(), format.empty() ? "svg" : format.c_str());
@@ -806,7 +808,7 @@ struct ShowPass : public Pass {
log_cmd_error("Nothing there to show.\n");
if (format != "dot" && !format.empty()) {
- std::string cmd = stringf("dot -T%s -o '%s.new' '%s' && mv '%s.new' '%s'", format.c_str(), out_file.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str());
+ std::string cmd = stringf("dot -T%s '%s' > '%s.new' && mv '%s.new' '%s'", format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str());
log("Exec: %s\n", cmd.c_str());
if (run_command(cmd) != 0)
log_cmd_error("Shell command failed!\n");
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 2556fb74..7418ec4d 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -341,7 +341,7 @@ struct SplicePass : public Pass {
if (!ports.empty() && !no_ports.empty())
log_cmd_error("The options -port and -no_port are exclusive!\n");
- log_header("Executing SPLICE pass (creating cells for signal splicing).\n");
+ log_header(design, "Executing SPLICE pass (creating cells for signal splicing).\n");
for (auto &mod_it : design->modules_)
{
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index 0d7892d7..14eeb066 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -109,7 +109,7 @@ struct SplitnetsPass : public Pass {
bool flag_driver = false;
std::string format = "[]:";
- log_header("Executing SPLITNETS pass (splitting up multi-bit signals).\n");
+ log_header(design, "Executing SPLITNETS pass (splitting up multi-bit signals).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 048933fc..362a0edf 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -232,7 +232,7 @@ struct StatPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Printing statistics.\n");
+ log_header(design, "Printing statistics.\n");
bool width_mode = false;
RTLIL::Module *top_mod = NULL;
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index a0484090..3db2dbf0 100644
--- a/passes/cmds/tee.cc
+++ b/passes/cmds/tee.cc
@@ -45,10 +45,14 @@ struct TeePass : public Pass {
log(" -a logfile\n");
log(" Write output to this file, append if exists.\n");
log("\n");
+ log(" +INT, -INT\n");
+ log(" Add/subract INT from the -v setting for this command.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
std::vector<FILE*> backup_log_files, files_to_close;
+ int backup_log_verbose_level = log_verbose_level;
backup_log_files = log_files;
size_t argidx;
@@ -70,6 +74,10 @@ struct TeePass : public Pass {
files_to_close.push_back(f);
continue;
}
+ if (GetSize(args[argidx]) >= 2 && (args[argidx][0] == '-' || args[argidx][0] == '+') && args[argidx][1] >= '0' && args[argidx][1] <= '9') {
+ log_verbose_level += atoi(args[argidx].c_str());
+ continue;
+ }
break;
}
@@ -85,6 +93,8 @@ struct TeePass : public Pass {
for (auto cf : files_to_close)
fclose(cf);
+
+ log_verbose_level = backup_log_verbose_level;
log_files = backup_log_files;
}
} TeePass;
diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc
index 50317c02..56223610 100644
--- a/passes/cmds/torder.cc
+++ b/passes/cmds/torder.cc
@@ -48,7 +48,7 @@ struct TorderPass : public Pass {
bool noautostop = false;
dict<IdString, pool<IdString>> stop_db;
- log_header("Executing TORDER pass (print cells in topological order).\n");
+ log_header(design, "Executing TORDER pass (print cells in topological order).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc
index cdb951ec..c958c3de 100644
--- a/passes/equiv/equiv_induct.cc
+++ b/passes/equiv/equiv_induct.cc
@@ -198,7 +198,7 @@ struct EquivInductPass : public Pass {
bool model_undef = false;
int max_seq = 4;
- log_header("Executing EQUIV_INDUCT pass.\n");
+ log_header(design, "Executing EQUIV_INDUCT pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc
index 8b063c54..40ca4262 100644
--- a/passes/equiv/equiv_make.cc
+++ b/passes/equiv/equiv_make.cc
@@ -464,7 +464,7 @@ struct EquivMakePass : public Pass {
worker.read_blacklists();
worker.read_encfiles();
- log_header("Executing EQUIV_MAKE pass (creating equiv checking module).\n");
+ log_header(design, "Executing EQUIV_MAKE pass (creating equiv checking module).\n");
worker.equiv_mod = design->addModule(RTLIL::escape_id(args[argidx+2]));
worker.run();
diff --git a/passes/equiv/equiv_mark.cc b/passes/equiv/equiv_mark.cc
index 3e9819d1..22c50176 100644
--- a/passes/equiv/equiv_mark.cc
+++ b/passes/equiv/equiv_mark.cc
@@ -218,7 +218,7 @@ struct EquivMarkPass : public Pass {
}
virtual void execute(std::vector<std::string> args, Design *design)
{
- log_header("Executing EQUIV_MARK pass.\n");
+ log_header(design, "Executing EQUIV_MARK pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_miter.cc b/passes/equiv/equiv_miter.cc
index 982176c4..eb2e5a17 100644
--- a/passes/equiv/equiv_miter.cc
+++ b/passes/equiv/equiv_miter.cc
@@ -333,7 +333,7 @@ struct EquivMiterPass : public Pass {
found_two_modules:
log_cmd_error("Exactly one module must be selected for 'equiv_miter'!\n");
- log_header("Executing EQUIV_MITER pass.\n");
+ log_header(design, "Executing EQUIV_MITER pass.\n");
worker.miter_module = design->addModule(worker.miter_name);
worker.run();
diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc
index f4141ad4..163b1009 100644
--- a/passes/equiv/equiv_purge.cc
+++ b/passes/equiv/equiv_purge.cc
@@ -189,7 +189,7 @@ struct EquivPurgePass : public Pass {
}
virtual void execute(std::vector<std::string> args, Design *design)
{
- log_header("Executing EQUIV_PURGE pass.\n");
+ log_header(design, "Executing EQUIV_PURGE pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_remove.cc b/passes/equiv/equiv_remove.cc
index b5c383b6..770497a5 100644
--- a/passes/equiv/equiv_remove.cc
+++ b/passes/equiv/equiv_remove.cc
@@ -46,7 +46,7 @@ struct EquivRemovePass : public Pass {
bool mode_gate = false;
int remove_count = 0;
- log_header("Executing EQUIV_REMOVE pass.\n");
+ log_header(design, "Executing EQUIV_REMOVE pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc
index fa22dc62..49963ed6 100644
--- a/passes/equiv/equiv_simple.cc
+++ b/passes/equiv/equiv_simple.cc
@@ -277,7 +277,7 @@ struct EquivSimplePass : public Pass {
int success_counter = 0;
int max_seq = 1;
- log_header("Executing EQUIV_SIMPLE pass.\n");
+ log_header(design, "Executing EQUIV_SIMPLE pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc
index 8a2f5e05..7b9230b3 100644
--- a/passes/equiv/equiv_status.cc
+++ b/passes/equiv/equiv_status.cc
@@ -41,7 +41,7 @@ struct EquivStatusPass : public Pass {
bool assert_mode = false;
int unproven_count = 0;
- log_header("Executing EQUIV_STATUS pass.\n");
+ log_header(design, "Executing EQUIV_STATUS pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc
index 2c85d2d3..c4ced6a7 100644
--- a/passes/equiv/equiv_struct.cc
+++ b/passes/equiv/equiv_struct.cc
@@ -321,7 +321,7 @@ struct EquivStructPass : public Pass {
bool mode_fwd = false;
int max_iter = -1;
- log_header("Executing EQUIV_STRUCT pass.\n");
+ log_header(design, "Executing EQUIV_STRUCT pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/fsm/fsm.cc b/passes/fsm/fsm.cc
index 3f5564fc..3b537ecd 100644
--- a/passes/fsm/fsm.cc
+++ b/passes/fsm/fsm.cc
@@ -76,7 +76,7 @@ struct FsmPass : public Pass {
std::string encfile_opt;
std::string encoding_opt;
- log_header("Executing FSM pass (extract and optimize FSM).\n");
+ log_header(design, "Executing FSM pass (extract and optimize FSM).\n");
log_push();
size_t argidx;
diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc
index 740113e3..6a560f16 100644
--- a/passes/fsm/fsm_detect.cc
+++ b/passes/fsm/fsm_detect.cc
@@ -36,18 +36,21 @@ static SigPool sig_at_port;
static bool check_state_mux_tree(RTLIL::SigSpec old_sig, RTLIL::SigSpec sig, pool<Cell*> &recursion_monitor)
{
- if (sig_at_port.check_any(assign_map(sig)))
- return false;
-
- if (sig.is_fully_const() || old_sig == sig)
+ if (sig.is_fully_const() || old_sig == sig) {
return true;
+ }
+
+ if (sig_at_port.check_any(assign_map(sig))) {
+ return false;
+ }
std::set<sig2driver_entry_t> cellport_list;
sig2driver.find(sig, cellport_list);
for (auto &cellport : cellport_list)
{
- if ((cellport.first->type != "$mux" && cellport.first->type != "$pmux") || cellport.second != "\\Y")
+ if ((cellport.first->type != "$mux" && cellport.first->type != "$pmux") || cellport.second != "\\Y") {
return false;
+ }
if (recursion_monitor.count(cellport.first)) {
log_warning("logic loop in mux tree at signal %s in module %s.\n",
@@ -110,28 +113,134 @@ static bool check_state_users(RTLIL::SigSpec sig)
static void detect_fsm(RTLIL::Wire *wire)
{
- if (wire->attributes.count("\\init") > 0)
- return;
- if (wire->attributes.count("\\fsm_encoding") > 0 || wire->width <= 1)
+ bool has_fsm_encoding_attr = wire->attributes.count("\\fsm_encoding") > 0 && wire->attributes.at("\\fsm_encoding").decode_string() != "none";
+ bool has_fsm_encoding_none = wire->attributes.count("\\fsm_encoding") > 0 && wire->attributes.at("\\fsm_encoding").decode_string() == "none";
+ bool has_init_attr = wire->attributes.count("\\init") > 0;
+ bool is_module_port = sig_at_port.check_any(assign_map(RTLIL::SigSpec(wire)));
+ bool looks_like_state_reg = false, looks_like_good_state_reg = false;
+ bool is_self_resetting = false;
+
+ if (has_fsm_encoding_none)
return;
- if (sig_at_port.check_any(assign_map(RTLIL::SigSpec(wire))))
+
+ if (wire->width <= 1) {
+ if (has_fsm_encoding_attr) {
+ log_warning("Removing fsm_encoding attribute from 1-bit net: %s.%s\n", log_id(wire->module), log_id(wire));
+ wire->attributes.erase("\\fsm_encoding");
+ }
return;
+ }
std::set<sig2driver_entry_t> cellport_list;
sig2driver.find(RTLIL::SigSpec(wire), cellport_list);
- for (auto &cellport : cellport_list) {
+
+ for (auto &cellport : cellport_list)
+ {
if ((cellport.first->type != "$dff" && cellport.first->type != "$adff") || cellport.second != "\\Q")
continue;
+
muxtree_cells.clear();
pool<Cell*> recursion_monitor;
RTLIL::SigSpec sig_q = assign_map(cellport.first->getPort("\\Q"));
RTLIL::SigSpec sig_d = assign_map(cellport.first->getPort("\\D"));
- if (sig_q == RTLIL::SigSpec(wire) && check_state_mux_tree(sig_q, sig_d, recursion_monitor) && check_state_users(sig_q)) {
- log("Found FSM state register %s in module %s.\n", wire->name.c_str(), module->name.c_str());
- wire->attributes["\\fsm_encoding"] = RTLIL::Const("auto");
- return;
+
+ if (sig_q != assign_map(wire))
+ continue;
+
+ looks_like_state_reg = check_state_mux_tree(sig_q, sig_d, recursion_monitor);
+ looks_like_good_state_reg = check_state_users(sig_q);
+
+ if (!looks_like_state_reg)
+ break;
+
+ ConstEval ce(wire->module);
+
+ std::set<sig2driver_entry_t> cellport_list;
+ sig2user.find(sig_q, cellport_list);
+
+ for (auto &cellport : cellport_list)
+ {
+ RTLIL::Cell *cell = cellport.first;
+ bool set_output = false, clr_output = false;
+
+ if (cell->type == "$ne")
+ set_output = true;
+
+ if (cell->type == "$eq")
+ clr_output = true;
+
+ if (!set_output && !clr_output) {
+ clr_output = true;
+ for (auto &port_it : cell->connections())
+ if (port_it.first != "\\A" || port_it.first != "\\Y")
+ clr_output = false;
+ }
+
+ if (set_output || clr_output) {
+ for (auto &port_it : cell->connections())
+ if (cell->output(port_it.first)) {
+ SigSpec sig = assign_map(port_it.second);
+ Const val(set_output ? State::S1 : State::S0, GetSize(sig));
+ ce.set(sig, val);
+ }
+ }
+ }
+
+ SigSpec sig_y = sig_d, sig_undef;
+ if (ce.eval(sig_y, sig_undef))
+ is_self_resetting = true;
+ }
+
+ if (has_fsm_encoding_attr)
+ {
+ vector<string> warnings;
+
+ if (is_module_port)
+ warnings.push_back("Forcing fsm recoding on module port might result in larger circuit.\n");
+
+ if (!looks_like_good_state_reg)
+ warnings.push_back("Users of state reg look like fsm recoding might result in larger circuit.\n");
+
+ if (has_init_attr)
+ warnings.push_back("Init value on fsm state registers are ignored. Possible simulation-synthesis mismatch!");
+
+ if (!looks_like_state_reg)
+ warnings.push_back("Doesn't look like a proper FSM. Possible simulation-synthesis mismatch!\n");
+
+ if (is_self_resetting)
+ warnings.push_back("FSM seems to be self-resetting. Possible simulation-synthesis mismatch!\n");
+
+ if (!warnings.empty()) {
+ string warnmsg = stringf("Regarding the user-specified fsm_encoding attribute on %s.%s:\n", log_id(wire->module), log_id(wire));
+ for (auto w : warnings) warnmsg += " " + w;
+ log_warning("%s", warnmsg.c_str());
+ } else {
+ log("FSM state register %s.%s already has fsm_encoding attribute.\n", log_id(wire->module), log_id(wire));
}
}
+ else
+ if (looks_like_state_reg && looks_like_good_state_reg && !has_init_attr && !is_module_port && !is_self_resetting)
+ {
+ log("Found FSM state register %s.%s.\n", log_id(wire->module), log_id(wire));
+ wire->attributes["\\fsm_encoding"] = RTLIL::Const("auto");
+ }
+ else
+ if (looks_like_state_reg)
+ {
+ log("Not marking %s.%s as FSM state register:\n", log_id(wire->module), log_id(wire));
+
+ if (is_module_port)
+ log(" Register is connected to module port.\n");
+
+ if (!looks_like_good_state_reg)
+ log(" Users of register don't seem to benefit from recoding.\n");
+
+ if (has_init_attr)
+ log(" Register has an initialization value.");
+
+ if (is_self_resetting)
+ log(" Circuit seems to be self-resetting.\n");
+ }
}
struct FsmDetectPass : public Pass {
@@ -154,7 +263,7 @@ struct FsmDetectPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FSM_DETECT pass (finding FSMs in design).\n");
+ log_header(design, "Executing FSM_DETECT pass (finding FSMs in design).\n");
extra_args(args, 1, design);
CellTypes ct;
diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc
index 43c9a792..3ded3f37 100644
--- a/passes/fsm/fsm_expand.cc
+++ b/passes/fsm/fsm_expand.cc
@@ -258,7 +258,7 @@ struct FsmExpandPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FSM_EXPAND pass (merging auxiliary logic into FSMs).\n");
+ log_header(design, "Executing FSM_EXPAND pass (merging auxiliary logic into FSMs).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_) {
diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc
index 0eff2884..1cbfcfae 100644
--- a/passes/fsm/fsm_export.cc
+++ b/passes/fsm/fsm_export.cc
@@ -152,7 +152,7 @@ struct FsmExportPass : public Pass {
bool flag_origenc = false;
size_t argidx;
- log_header("Executing FSM_EXPORT pass (exporting FSMs in KISS2 file format).\n");
+ log_header(design, "Executing FSM_EXPORT pass (exporting FSMs in KISS2 file format).\n");
for (argidx = 1; argidx < args.size(); argidx++) {
arg = args[argidx];
diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc
index d61ac568..8a4ee3f2 100644
--- a/passes/fsm/fsm_extract.cc
+++ b/passes/fsm/fsm_extract.cc
@@ -92,12 +92,15 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL
if (reset_state && RTLIL::SigSpec(*reset_state).is_fully_undef())
do {
+ SigSpec new_reset_state;
if (sig_aa.is_fully_def())
- *reset_state = sig_aa.as_const();
+ new_reset_state = sig_aa.as_const();
else if (sig_bb.is_fully_def())
- *reset_state = sig_bb.as_const();
+ new_reset_state = sig_bb.as_const();
else
break;
+ new_reset_state.extend_u0(GetSize(*reset_state));
+ *reset_state = new_reset_state.as_const();
log(" found reset state: %s (guessed from mux tree)\n", log_signal(*reset_state));
} while (0);
@@ -416,7 +419,7 @@ struct FsmExtractPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FSM_EXTRACT pass (extracting FSM from design).\n");
+ log_header(design, "Executing FSM_EXTRACT pass (extracting FSM from design).\n");
extra_args(args, 1, design);
CellTypes ct;
diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc
index 20db82c1..2cc1a7d5 100644
--- a/passes/fsm/fsm_info.cc
+++ b/passes/fsm/fsm_info.cc
@@ -43,7 +43,7 @@ struct FsmInfoPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FSM_INFO pass (dumping all available information on FSM cells).\n");
+ log_header(design, "Executing FSM_INFO pass (dumping all available information on FSM cells).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_)
diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc
index 574b9a20..5b32ed59 100644
--- a/passes/fsm/fsm_map.cc
+++ b/passes/fsm/fsm_map.cc
@@ -335,7 +335,7 @@ struct FsmMapPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FSM_MAP pass (mapping FSMs to basic logic).\n");
+ log_header(design, "Executing FSM_MAP pass (mapping FSMs to basic logic).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_) {
diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc
index a7cc95ff..5b1da44f 100644
--- a/passes/fsm/fsm_opt.cc
+++ b/passes/fsm/fsm_opt.cc
@@ -336,7 +336,7 @@ struct FsmOptPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FSM_OPT pass (simple optimizations of FSMs).\n");
+ log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_) {
diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc
index a4b45295..5102d833 100644
--- a/passes/fsm/fsm_recode.cc
+++ b/passes/fsm/fsm_recode.cc
@@ -157,7 +157,7 @@ struct FsmRecodePass : public Pass {
FILE *encfile = NULL;
std::string default_encoding;
- log_header("Executing FSM_RECODE pass (re-assigning FSM state encoding).\n");
+ log_header(design, "Executing FSM_RECODE pass (re-assigning FSM state encoding).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index fcc30d17..4d1e3987 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -261,7 +261,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
return did_something;
}
-void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*> &used, RTLIL::Module *mod, int indent)
+void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> &used, RTLIL::Module *mod, int indent)
{
if (used.count(mod) > 0)
return;
@@ -287,7 +287,7 @@ void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*> &used, RTL
void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
{
- std::set<RTLIL::Module*> used;
+ std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used;
hierarchy_worker(design, used, top, 0);
std::vector<RTLIL::Module*> del_modules;
@@ -297,8 +297,6 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
int del_counter = 0;
for (auto mod : del_modules) {
- if (mod->name.substr(0, 9) == "$abstract")
- continue;
if (!purge_lib && mod->get_bool_attribute("\\blackbox"))
continue;
log("Removing unused module `%s'.\n", mod->name.c_str());
@@ -324,10 +322,12 @@ bool set_keep_assert(std::map<RTLIL::Module*, bool> &cache, RTLIL::Module *mod)
int find_top_mod_score(Design *design, Module *module, dict<Module*, int> &db)
{
if (db.count(module) == 0) {
+ int score = 0;
db[module] = 0;
for (auto cell : module->cells())
if (design->module(cell->type))
- db[module] = max(db[module], find_top_mod_score(design, design->module(cell->type), db) + 1);
+ score = max(score, find_top_mod_score(design, design->module(cell->type), db) + 1);
+ db[module] = score;
}
return db.at(module);
}
@@ -398,7 +398,7 @@ struct HierarchyPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing HIERARCHY pass (managing design hierarchy).\n");
+ log_header(design, "Executing HIERARCHY pass (managing design hierarchy).\n");
bool flag_check = false;
bool purge_lib = false;
@@ -508,7 +508,7 @@ struct HierarchyPass : public Pass {
top_mod = mod_it.second;
if (top_mod == nullptr && auto_top_mode) {
- log_header("Finding top of design hierarchy..\n");
+ log_header(design, "Finding top of design hierarchy..\n");
dict<Module*, int> db;
for (Module *mod : design->selected_modules()) {
int score = find_top_mod_score(design, mod, db);
@@ -525,9 +525,9 @@ struct HierarchyPass : public Pass {
{
did_something = false;
- std::set<RTLIL::Module*> used_modules;
+ std::set<RTLIL::Module*, IdString::compare_ptr_by_name<Module>> used_modules;
if (top_mod != NULL) {
- log_header("Analyzing design hierarchy..\n");
+ log_header(design, "Analyzing design hierarchy..\n");
hierarchy_worker(design, used_modules, top_mod, 0);
} else {
for (auto mod : design->modules())
@@ -541,7 +541,7 @@ struct HierarchyPass : public Pass {
}
if (top_mod != NULL) {
- log_header("Analyzing design hierarchy..\n");
+ log_header(design, "Analyzing design hierarchy..\n");
hierarchy_clean(design, top_mod, purge_lib);
}
diff --git a/passes/hierarchy/singleton.cc b/passes/hierarchy/singleton.cc
index 5715c0eb..03c365fb 100644
--- a/passes/hierarchy/singleton.cc
+++ b/passes/hierarchy/singleton.cc
@@ -43,7 +43,7 @@ struct SingletonPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing SINGLETON pass (creating singleton modules).\n");
+ log_header(design, "Executing SINGLETON pass (creating singleton modules).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc
index d4e8c96c..9f312f82 100644
--- a/passes/hierarchy/submod.cc
+++ b/passes/hierarchy/submod.cc
@@ -298,7 +298,7 @@ struct SubmodPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing SUBMOD pass (moving cells to submodules as requested).\n");
+ log_header(design, "Executing SUBMOD pass (moving cells to submodules as requested).\n");
log_push();
std::string opt_name;
@@ -321,7 +321,7 @@ struct SubmodPass : public Pass {
if (opt_name.empty())
{
Pass::call(design, "opt_clean");
- log_header("Continuing SUBMOD pass.\n");
+ log_header(design, "Continuing SUBMOD pass.\n");
std::set<RTLIL::IdString> handled_modules;
@@ -356,7 +356,7 @@ struct SubmodPass : public Pass {
log("Nothing selected -> do nothing.\n");
else {
Pass::call_on_module(design, module, "opt_clean");
- log_header("Continuing SUBMOD pass.\n");
+ log_header(design, "Continuing SUBMOD pass.\n");
SubmodWorker worker(design, module, copy_mode, opt_name);
}
}
diff --git a/passes/memory/Makefile.inc b/passes/memory/Makefile.inc
index aeff225d..ad359c01 100644
--- a/passes/memory/Makefile.inc
+++ b/passes/memory/Makefile.inc
@@ -6,4 +6,5 @@ OBJS += passes/memory/memory_collect.o
OBJS += passes/memory/memory_unpack.o
OBJS += passes/memory/memory_bram.o
OBJS += passes/memory/memory_map.o
+OBJS += passes/memory/memory_memx.o
diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc
index 4e74d1a4..947d598b 100644
--- a/passes/memory/memory.cc
+++ b/passes/memory/memory.cc
@@ -31,14 +31,15 @@ struct MemoryPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" memory [-nomap] [-nordff] [-bram <bram_rules>] [selection]\n");
+ log(" memory [-nomap] [-nordff] [-memx] [-bram <bram_rules>] [selection]\n");
log("\n");
log("This pass calls all the other memory_* passes in a useful order:\n");
log("\n");
- log(" memory_dff [-nordff]\n");
+ log(" memory_dff [-nordff] (-memx implies -nordff)\n");
log(" opt_clean\n");
log(" memory_share\n");
log(" opt_clean\n");
+ log(" memory_memx (when called with -memx)\n");
log(" memory_collect\n");
log(" memory_bram -rules <bram_rules> (when called with -bram)\n");
log(" memory_map (skipped if called with -nomap)\n");
@@ -51,9 +52,10 @@ struct MemoryPass : public Pass {
{
bool flag_nomap = false;
bool flag_nordff = false;
+ bool flag_memx = false;
string memory_bram_opts;
- log_header("Executing MEMORY pass.\n");
+ log_header(design, "Executing MEMORY pass.\n");
log_push();
size_t argidx;
@@ -66,6 +68,11 @@ struct MemoryPass : public Pass {
flag_nordff = true;
continue;
}
+ if (args[argidx] == "-memx") {
+ flag_nordff = true;
+ flag_memx = true;
+ continue;
+ }
if (argidx+1 < args.size() && args[argidx] == "-bram") {
memory_bram_opts += " -rules " + args[++argidx];
continue;
@@ -77,6 +84,8 @@ struct MemoryPass : public Pass {
Pass::call(design, flag_nordff ? "memory_dff -nordff" : "memory_dff");
Pass::call(design, "opt_clean");
Pass::call(design, "memory_share");
+ if (flag_memx)
+ Pass::call(design, "memory_memx");
Pass::call(design, "opt_clean");
Pass::call(design, "memory_collect");
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index f2d9b584..a7f9cf38 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -656,6 +656,9 @@ grow_read_ports:;
bool transp = rd_transp[cell_port_i] == State::S1;
SigBit clksig = rd_clk[cell_port_i];
+ if (wr_ports == 0)
+ transp = false;
+
pair<SigBit, bool> clkdom(clksig, clkpol);
if (!clken)
clkdom = pair<SigBit, bool>(State::S1, false);
@@ -826,7 +829,7 @@ grow_read_ports:;
State padding = State::Sx;
for (int j = 0; j < bram.dbits; j++)
if (init_offset+i < GetSize(initdata) && init_shift+j < GetSize(initdata[init_offset+i]))
- padding = initparam[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j];
+ initparam[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j];
else
initparam[i*bram.dbits+j] = padding;
}
@@ -1211,7 +1214,7 @@ struct MemoryBramPass : public Pass {
{
rules_t rules;
- log_header("Executing MEMORY_BRAM pass (mapping $mem cells to block memories).\n");
+ log_header(design, "Executing MEMORY_BRAM pass (mapping $mem cells to block memories).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc
index 5c0acb3e..ab66e3fb 100644
--- a/passes/memory/memory_collect.cc
+++ b/passes/memory/memory_collect.cc
@@ -37,8 +37,6 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
log("Collecting $memrd, $memwr and $meminit for memory `%s' in module `%s':\n",
memory->name.c_str(), module->name.c_str());
- int addr_bits = 0;
-
Const init_data(State::Sx, memory->size * memory->width);
SigMap sigmap(module);
@@ -59,16 +57,28 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
SigSpec sig_rd_data;
SigSpec sig_rd_en;
+ int addr_bits = 0;
std::vector<Cell*> memcells;
for (auto &cell_it : module->cells_) {
Cell *cell = cell_it.second;
if (cell->type.in("$memrd", "$memwr", "$meminit") && memory->name == cell->parameters["\\MEMID"].decode_string()) {
- addr_bits = max(addr_bits, cell->getParam("\\ABITS").as_int());
+ SigSpec addr = sigmap(cell->getPort("\\ADDR"));
+ for (int i = 0; i < GetSize(addr); i++)
+ if (addr[i] != State::S0)
+ addr_bits = std::max(addr_bits, i+1);
memcells.push_back(cell);
}
}
+ if (memory->start_offset == 0 && addr_bits < 30 && (1 << addr_bits) < memory->size)
+ memory->size = 1 << addr_bits;
+
+ if (memory->start_offset >= 0)
+ addr_bits = std::min(addr_bits, ceil_log2(memory->size + memory->start_offset));
+
+ addr_bits = std::max(addr_bits, 1);
+
if (memcells.empty()) {
log(" no cells found. removing memory.\n");
return nullptr;
@@ -247,7 +257,7 @@ struct MemoryCollectPass : public Pass {
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
- log_header("Executing MEMORY_COLLECT pass (generating $mem cells).\n");
+ log_header(design, "Executing MEMORY_COLLECT pass (generating $mem cells).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_)
if (design->selected(mod_it.second))
diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc
index beb2016a..40691d16 100644
--- a/passes/memory/memory_dff.cc
+++ b/passes/memory/memory_dff.cc
@@ -283,7 +283,7 @@ struct MemoryDffPass : public Pass {
{
bool flag_wr_only = false;
- log_header("Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");
+ log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index 0b8ccb36..bffeec85 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -363,7 +363,7 @@ struct MemoryMapPass : public Pass {
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
- log_header("Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
+ log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
extra_args(args, 1, design);
for (auto mod : design->selected_modules())
MemoryMapWorker(design, mod);
diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc
new file mode 100644
index 00000000..2b02e249
--- /dev/null
+++ b/passes/memory/memory_memx.cc
@@ -0,0 +1,92 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/register.h"
+#include "kernel/log.h"
+#include <sstream>
+#include <set>
+#include <stdlib.h>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct MemoryMemxPass : public Pass {
+ MemoryMemxPass() : Pass("memory_memx", "emulate vlog sim behavior for mem ports") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" memory_memx [selection]\n");
+ log("\n");
+ log("This pass adds additional circuitry that emulates the Verilog simulation\n");
+ log("behavior for out-of-bounds memory reads and writes.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
+ log_header(design, "Executing MEMORY_MEMX pass (converting $mem cells to logic and flip-flops).\n");
+ extra_args(args, 1, design);
+
+ for (auto module : design->selected_modules())
+ {
+ vector<Cell*> mem_port_cells;
+
+ for (auto cell : module->selected_cells())
+ if (cell->type.in("$memrd", "$memwr"))
+ mem_port_cells.push_back(cell);
+
+ for (auto cell : mem_port_cells)
+ {
+ IdString memid = cell->getParam("\\MEMID").decode_string();
+ RTLIL::Memory *mem = module->memories.at(memid);
+
+ int lowest_addr = mem->start_offset;
+ int highest_addr = mem->start_offset + mem->size - 1;
+
+ SigSpec addr = cell->getPort("\\ADDR");
+ addr.extend_u0(32);
+
+ SigSpec addr_ok = module->Nex(NEW_ID, module->ReduceXor(NEW_ID, addr), module->ReduceXor(NEW_ID, {addr, State::S1}));
+ if (lowest_addr != 0)
+ addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Ge(NEW_ID, addr, lowest_addr));
+ addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Le(NEW_ID, addr, highest_addr));
+
+ if (cell->type == "$memrd")
+ {
+ if (cell->getParam("\\CLK_ENABLE").as_bool())
+ log_error("Cell %s.%s (%s) has an enabled clock. Clocked $memrd cells are not supported by memory_memx!\n",
+ log_id(module), log_id(cell), log_id(cell->type));
+
+ SigSpec rdata = cell->getPort("\\DATA");
+ Wire *raw_rdata = module->addWire(NEW_ID, GetSize(rdata));
+ module->addMux(NEW_ID, SigSpec(State::Sx, GetSize(rdata)), raw_rdata, addr_ok, rdata);
+ cell->setPort("\\DATA", raw_rdata);
+ }
+
+ if (cell->type == "$memwr")
+ {
+ SigSpec en = cell->getPort("\\EN");
+ en = module->And(NEW_ID, en, addr_ok.repeat(GetSize(en)));
+ cell->setPort("\\EN", en);
+ }
+ }
+ }
+ }
+} MemoryMemxPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc
index 3a6fd0b4..ca09ac52 100644
--- a/passes/memory/memory_share.cc
+++ b/passes/memory/memory_share.cc
@@ -43,7 +43,7 @@ struct MemoryShareWorker
CellTypes cone_ct;
std::map<RTLIL::SigBit, std::pair<RTLIL::Cell*, int>> sig_to_mux;
- std::map<std::set<std::map<RTLIL::SigBit, bool>>, RTLIL::SigBit> conditions_logic_cache;
+ std::map<pair<std::set<std::map<SigBit, bool>>, SigBit>, SigBit> conditions_logic_cache;
// -----------------------------------------------------------------
@@ -109,10 +109,12 @@ struct MemoryShareWorker
return false;
}
- RTLIL::SigBit conditions_to_logic(std::set<std::map<RTLIL::SigBit, bool>> &conditions, int &created_conditions)
+ RTLIL::SigBit conditions_to_logic(std::set<std::map<RTLIL::SigBit, bool>> &conditions, SigBit olden, int &created_conditions)
{
- if (conditions_logic_cache.count(conditions))
- return conditions_logic_cache.at(conditions);
+ auto key = make_pair(conditions, olden);
+
+ if (conditions_logic_cache.count(key))
+ return conditions_logic_cache.at(key);
RTLIL::SigSpec terms;
for (auto &cond : conditions) {
@@ -125,13 +127,16 @@ struct MemoryShareWorker
created_conditions++;
}
- if (terms.size() == 0)
+ if (olden.wire != nullptr || olden != State::S1)
+ terms.append(olden);
+
+ if (GetSize(terms) == 0)
terms = State::S1;
- if (terms.size() > 1)
+ if (GetSize(terms) > 1)
terms = module->ReduceAnd(NEW_ID, terms);
- return conditions_logic_cache[conditions] = terms;
+ return conditions_logic_cache[key] = terms;
}
void translate_rd_feedback_to_en(std::string memid, std::vector<RTLIL::Cell*> &rd_ports, std::vector<RTLIL::Cell*> &wr_ports)
@@ -140,15 +145,14 @@ struct MemoryShareWorker
std::map<RTLIL::SigBit, std::set<RTLIL::SigBit>> muxtree_upstream_map;
std::set<RTLIL::SigBit> non_feedback_nets;
- for (auto wire_it : module->wires_)
- if (wire_it.second->port_output) {
- std::vector<RTLIL::SigBit> bits = RTLIL::SigSpec(wire_it.second);
+ for (auto wire : module->wires())
+ if (wire->port_output) {
+ std::vector<RTLIL::SigBit> bits = sigmap(wire);
non_feedback_nets.insert(bits.begin(), bits.end());
}
- for (auto cell_it : module->cells_)
+ for (auto cell : module->cells())
{
- RTLIL::Cell *cell = cell_it.second;
bool ignore_data_port = false;
if (cell->type == "$mux" || cell->type == "$pmux")
@@ -173,7 +177,7 @@ struct MemoryShareWorker
cell->parameters.at("\\MEMID").decode_string() == memid)
ignore_data_port = true;
- for (auto conn : cell_it.second->connections())
+ for (auto conn : cell->connections())
{
if (ignore_data_port && conn.first == "\\DATA")
continue;
@@ -240,13 +244,8 @@ struct MemoryShareWorker
std::map<RTLIL::SigBit, bool> state;
std::set<std::map<RTLIL::SigBit, bool>> conditions;
- if (cell_en[i].wire != NULL) {
- state[cell_en[i]] = false;
- conditions.insert(state);
- }
-
find_data_feedback(async_rd_bits.at(sig_addr).at(i), cell_data[i], state, conditions);
- cell_en[i] = conditions_to_logic(conditions, created_conditions);
+ cell_en[i] = conditions_to_logic(conditions, cell_en[i], created_conditions);
}
if (created_conditions) {
@@ -620,6 +619,12 @@ struct MemoryShareWorker
RTLIL::SigBit this_en_active = module->ReduceOr(NEW_ID, this_en);
+ if (GetSize(last_addr) < GetSize(this_addr))
+ last_addr.extend_u0(GetSize(this_addr));
+ else
+ this_addr.extend_u0(GetSize(last_addr));
+
+ wr_ports[i]->setParam("\\ABITS", GetSize(this_addr));
wr_ports[i]->setPort("\\ADDR", module->Mux(NEW_ID, last_addr, this_addr, this_en_active));
wr_ports[i]->setPort("\\DATA", module->Mux(NEW_ID, last_data, this_data, this_en_active));
@@ -666,10 +671,8 @@ struct MemoryShareWorker
std::map<std::string, std::pair<std::vector<RTLIL::Cell*>, std::vector<RTLIL::Cell*>>> memindex;
sigmap_xmux = sigmap;
- for (auto &it : module->cells_)
+ for (auto cell : module->cells())
{
- RTLIL::Cell *cell = it.second;
-
if (cell->type == "$memrd")
memindex[cell->parameters.at("\\MEMID").decode_string()].first.push_back(cell);
@@ -746,11 +749,11 @@ struct MemorySharePass : public Pass {
log("\n");
log("Note that in addition to the algorithms implemented in this pass, the $memrd\n");
log("and $memwr cells are also subject to generic resource sharing passes (and other\n");
- log("optimizations) such as opt_share.\n");
+ log("optimizations) such as \"share\" and \"opt_merge\".\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
- log_header("Executing MEMORY_SHARE pass (consolidating $memrc/$memwr cells).\n");
+ log_header(design, "Executing MEMORY_SHARE pass (consolidating $memrd/$memwr cells).\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules())
MemoryShareWorker(design, module);
diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc
index 60724da7..a0fc31b5 100644
--- a/passes/memory/memory_unpack.cc
+++ b/passes/memory/memory_unpack.cc
@@ -138,7 +138,7 @@ struct MemoryUnpackPass : public Pass {
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
- log_header("Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n");
+ log_header(design, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n");
extra_args(args, 1, design);
for (auto &mod_it : design->modules_)
if (design->selected(mod_it.second))
diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc
index 43defb78..a8b1537b 100644
--- a/passes/opt/Makefile.inc
+++ b/passes/opt/Makefile.inc
@@ -1,11 +1,11 @@
OBJS += passes/opt/opt.o
-OBJS += passes/opt/opt_share.o
+OBJS += passes/opt/opt_merge.o
OBJS += passes/opt/opt_muxtree.o
OBJS += passes/opt/opt_reduce.o
OBJS += passes/opt/opt_rmdff.o
OBJS += passes/opt/opt_clean.o
-OBJS += passes/opt/opt_const.o
+OBJS += passes/opt/opt_expr.o
ifneq ($(SMALL),1)
OBJS += passes/opt/share.o
diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc
index f5389d8e..13ea5469 100644
--- a/passes/opt/opt.cc
+++ b/passes/opt/opt.cc
@@ -37,23 +37,23 @@ struct OptPass : public Pass {
log("a series of trivial optimizations and cleanups. This pass executes the other\n");
log("passes in the following order:\n");
log("\n");
- log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
- log(" opt_share [-share_all] -nomux\n");
+ log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
+ log(" opt_merge [-share_all] -nomux\n");
log("\n");
log(" do\n");
log(" opt_muxtree\n");
log(" opt_reduce [-fine] [-full]\n");
- log(" opt_share [-share_all]\n");
+ log(" opt_merge [-share_all]\n");
log(" opt_rmdff\n");
log(" opt_clean [-purge]\n");
- log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
+ log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
log(" while <changed design>\n");
log("\n");
log("When called with -fast the following script is used instead:\n");
log("\n");
log(" do\n");
- log(" opt_const [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
- log(" opt_share [-share_all]\n");
+ log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
+ log(" opt_merge [-share_all]\n");
log(" opt_rmdff\n");
log(" opt_clean [-purge]\n");
log(" while <changed design in opt_rmdff>\n");
@@ -66,12 +66,12 @@ struct OptPass : public Pass {
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
std::string opt_clean_args;
- std::string opt_const_args;
+ std::string opt_expr_args;
std::string opt_reduce_args;
- std::string opt_share_args;
+ std::string opt_merge_args;
bool fast_mode = false;
- log_header("Executing OPT pass (performing simple optimizations).\n");
+ log_header(design, "Executing OPT pass (performing simple optimizations).\n");
log_push();
size_t argidx;
@@ -81,37 +81,37 @@ struct OptPass : public Pass {
continue;
}
if (args[argidx] == "-mux_undef") {
- opt_const_args += " -mux_undef";
+ opt_expr_args += " -mux_undef";
continue;
}
if (args[argidx] == "-mux_bool") {
- opt_const_args += " -mux_bool";
+ opt_expr_args += " -mux_bool";
continue;
}
if (args[argidx] == "-undriven") {
- opt_const_args += " -undriven";
+ opt_expr_args += " -undriven";
continue;
}
if (args[argidx] == "-clkinv") {
- opt_const_args += " -clkinv";
+ opt_expr_args += " -clkinv";
continue;
}
if (args[argidx] == "-fine") {
- opt_const_args += " -fine";
+ opt_expr_args += " -fine";
opt_reduce_args += " -fine";
continue;
}
if (args[argidx] == "-full") {
- opt_const_args += " -full";
+ opt_expr_args += " -full";
opt_reduce_args += " -full";
continue;
}
if (args[argidx] == "-keepdc") {
- opt_const_args += " -keepdc";
+ opt_expr_args += " -keepdc";
continue;
}
if (args[argidx] == "-share_all") {
- opt_share_args += " -share_all";
+ opt_merge_args += " -share_all";
continue;
}
if (args[argidx] == "-fast") {
@@ -125,32 +125,32 @@ struct OptPass : public Pass {
if (fast_mode)
{
while (1) {
- Pass::call(design, "opt_const" + opt_const_args);
- Pass::call(design, "opt_share" + opt_share_args);
+ Pass::call(design, "opt_expr" + opt_expr_args);
+ Pass::call(design, "opt_merge" + opt_merge_args);
design->scratchpad_unset("opt.did_something");
Pass::call(design, "opt_rmdff");
if (design->scratchpad_get_bool("opt.did_something") == false)
break;
Pass::call(design, "opt_clean" + opt_clean_args);
- log_header("Rerunning OPT passes. (Removed registers in this run.)\n");
+ log_header(design, "Rerunning OPT passes. (Removed registers in this run.)\n");
}
Pass::call(design, "opt_clean" + opt_clean_args);
}
else
{
- Pass::call(design, "opt_const" + opt_const_args);
- Pass::call(design, "opt_share -nomux" + opt_share_args);
+ Pass::call(design, "opt_expr" + opt_expr_args);
+ Pass::call(design, "opt_merge -nomux" + opt_merge_args);
while (1) {
design->scratchpad_unset("opt.did_something");
Pass::call(design, "opt_muxtree");
Pass::call(design, "opt_reduce" + opt_reduce_args);
- Pass::call(design, "opt_share" + opt_share_args);
+ Pass::call(design, "opt_merge" + opt_merge_args);
Pass::call(design, "opt_rmdff");
Pass::call(design, "opt_clean" + opt_clean_args);
- Pass::call(design, "opt_const" + opt_const_args);
+ Pass::call(design, "opt_expr" + opt_expr_args);
if (design->scratchpad_get_bool("opt.did_something") == false)
break;
- log_header("Rerunning OPT passes. (Maybe there is more to do..)\n");
+ log_header(design, "Rerunning OPT passes. (Maybe there is more to do..)\n");
}
}
@@ -158,7 +158,7 @@ struct OptPass : public Pass {
design->sort();
design->check();
- log_header(fast_mode ? "Finished fast OPT passes.\n" : "Finished OPT passes. (There is nothing left to do.)\n");
+ log_header(design, fast_mode ? "Finished fast OPT passes.\n" : "Finished OPT passes. (There is nothing left to do.)\n");
log_pop();
}
} OptPass;
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 175e8e11..6600ffa2 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -156,6 +156,9 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool &regs, SigPoo
if (w1->port_input != w2->port_input)
return w2->port_input;
+ if ((w1->port_input && w1->port_output) != (w2->port_input && w2->port_output))
+ return !(w2->port_input && w2->port_output);
+
if (w1->name[0] == '\\' && w2->name[0] == '\\') {
if (regs.check_any(s1) != regs.check_any(s2))
return regs.check_any(s2);
@@ -380,7 +383,7 @@ struct OptCleanPass : public Pass {
{
bool purge_mode = false;
- log_header("Executing OPT_CLEAN pass (remove unused cells and wires).\n");
+ log_header(design, "Executing OPT_CLEAN pass (remove unused cells and wires).\n");
log_push();
size_t argidx;
diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_expr.cc
index 0fcacf0a..b62eae28 100644
--- a/passes/opt/opt_const.cc
+++ b/passes/opt/opt_expr.cc
@@ -179,7 +179,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
log("\n");
}
- cover_list("opt.opt_const.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str());
+ cover_list("opt.opt_expr.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str());
module->remove(cell);
did_something = true;
@@ -304,7 +304,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
for (auto cell : cells.sorted)
{
-#define ACTION_DO(_p_, _s_) do { cover("opt.opt_const.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
+#define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
#define ACTION_DO_Y(_v_) ACTION_DO("\\Y", RTLIL::SigSpec(RTLIL::State::S ## _v_))
if (clkinv)
@@ -342,6 +342,68 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", "\\R", assign_map, invert_map);
}
+ bool detect_const_and = false;
+ bool detect_const_or = false;
+
+ if (cell->type.in("$reduce_and", "$_AND_"))
+ detect_const_and = true;
+
+ if (cell->type.in("$and", "$logic_and") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1)
+ detect_const_and = true;
+
+ if (cell->type.in("$reduce_or", "$reduce_bool", "$_OR_"))
+ detect_const_or = true;
+
+ if (cell->type.in("$or", "$logic_or") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1)
+ detect_const_or = true;
+
+ if (detect_const_and || detect_const_or)
+ {
+ pool<SigBit> input_bits = assign_map(cell->getPort("\\A")).to_sigbit_pool();
+ bool found_zero = false, found_one = false, found_inv = false;
+
+ if (cell->hasPort("\\B")) {
+ vector<SigBit> more_bits = assign_map(cell->getPort("\\B")).to_sigbit_vector();
+ input_bits.insert(more_bits.begin(), more_bits.end());
+ }
+
+ for (auto bit : input_bits) {
+ if (bit == State::S0)
+ found_zero = true;
+ if (bit == State::S1)
+ found_one = true;
+ if (invert_map.count(bit) && input_bits.count(invert_map.at(bit)))
+ found_inv = true;
+ }
+
+ if (detect_const_and && (found_zero || found_inv)) {
+ cover("opt.opt_expr.const_and");
+ replace_cell(assign_map, module, cell, "const_and", "\\Y", RTLIL::State::S0);
+ goto next_cell;
+ }
+
+ if (detect_const_or && (found_one || found_inv)) {
+ cover("opt.opt_expr.const_or");
+ replace_cell(assign_map, module, cell, "const_or", "\\Y", RTLIL::State::S1);
+ goto next_cell;
+ }
+ }
+
+ if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor", "$neg") &&
+ GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\Y")) == 1)
+ {
+ if (cell->type == "$reduce_xnor") {
+ cover("opt.opt_expr.reduce_xnor_not");
+ log("Replacing %s cell `%s' in module `%s' with $not cell.\n",
+ log_id(cell->type), log_id(cell->name), log_id(module));
+ cell->type = "$not";
+ } else {
+ cover("opt.opt_expr.unary_buffer");
+ replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort("\\A"));
+ }
+ goto next_cell;
+ }
+
if (do_fine)
{
if (cell->type == "$not" || cell->type == "$pos" ||
@@ -366,7 +428,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
- cover("opt.opt_const.fine.$reduce_and");
+ cover("opt.opt_expr.fine.$reduce_and");
log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
cell->setPort("\\A", sig_a = new_a);
@@ -392,7 +454,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
- cover_list("opt.opt_const.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
+ cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
cell->setPort("\\A", sig_a = new_a);
@@ -418,7 +480,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) {
- cover_list("opt.opt_const.fine.B", "$logic_and", "$logic_or", cell->type.str());
+ cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
log("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
cell->setPort("\\B", sig_b = new_b);
@@ -428,18 +490,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
- if (cell->type == "$logic_or" && (assign_map(cell->getPort("\\A")) == RTLIL::State::S1 || assign_map(cell->getPort("\\B")) == RTLIL::State::S1)) {
- cover("opt.opt_const.one_high");
- replace_cell(assign_map, module, cell, "one high", "\\Y", RTLIL::State::S1);
- goto next_cell;
- }
-
- if (cell->type == "$logic_and" && (assign_map(cell->getPort("\\A")) == RTLIL::State::S0 || assign_map(cell->getPort("\\B")) == RTLIL::State::S0)) {
- cover("opt.opt_const.one_low");
- replace_cell(assign_map, module, cell, "one low", "\\Y", RTLIL::State::S0);
- goto next_cell;
- }
-
if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" ||
cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" ||
cell->type == "$lt" || cell->type == "$le" || cell->type == "$ge" || cell->type == "$gt" ||
@@ -462,7 +512,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (0) {
found_the_x_bit:
- cover_list("opt.opt_const.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
+ cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
"$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str());
if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" ||
cell->type == "$lt" || cell->type == "$le" || cell->type == "$ge" || cell->type == "$gt")
@@ -475,13 +525,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if ((cell->type == "$_NOT_" || cell->type == "$not" || cell->type == "$logic_not") && cell->getPort("\\Y").size() == 1 &&
invert_map.count(assign_map(cell->getPort("\\A"))) != 0) {
- cover_list("opt.opt_const.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
+ cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str());
replace_cell(assign_map, module, cell, "double_invert", "\\Y", invert_map.at(assign_map(cell->getPort("\\A"))));
goto next_cell;
}
if ((cell->type == "$_MUX_" || cell->type == "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) {
- cover_list("opt.opt_const.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
+ cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
log("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
RTLIL::SigSpec tmp = cell->getPort("\\A");
cell->setPort("\\A", cell->getPort("\\B"));
@@ -564,7 +614,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (input.match(" 1")) ACTION_DO("\\Y", input.extract(1, 1));
if (input.match("01 ")) ACTION_DO("\\Y", input.extract(0, 1));
if (input.match("10 ")) {
- cover("opt.opt_const.mux_to_inv");
+ cover("opt.opt_expr.mux_to_inv");
cell->type = "$_NOT_";
cell->setPort("\\A", input.extract(0, 1));
cell->unsetPort("\\B");
@@ -599,7 +649,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
log_assert(GetSize(a) == GetSize(b));
for (int i = 0; i < GetSize(a); i++) {
if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) {
- cover_list("opt.opt_const.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
+ cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1);
new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false);
replace_cell(assign_map, module, cell, "isneq", "\\Y", new_y);
@@ -612,7 +662,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_a.size() == 0) {
- cover_list("opt.opt_const.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
+ cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S1 : RTLIL::State::S0);
new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false);
replace_cell(assign_map, module, cell, "empty", "\\Y", new_y);
@@ -620,7 +670,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (new_a.size() < a.size() || new_b.size() < b.size()) {
- cover_list("opt.opt_const.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
+ cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str());
cell->setPort("\\A", new_a);
cell->setPort("\\B", new_b);
cell->parameters["\\A_WIDTH"] = new_a.size();
@@ -635,7 +685,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec b = assign_map(cell->getPort("\\B"));
if (a.is_fully_const() && !b.is_fully_const()) {
- cover_list("opt.opt_const.eqneq.swapconst", "$eq", "$ne", cell->type.str());
+ cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str());
cell->setPort("\\A", b);
cell->setPort("\\B", a);
std::swap(a, b);
@@ -646,7 +696,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec input = b;
ACTION_DO("\\Y", cell->getPort("\\A"));
} else {
- cover_list("opt.opt_const.eqneq.isnot", "$eq", "$ne", cell->type.str());
+ cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->type = "$not";
cell->parameters.erase("\\B_WIDTH");
@@ -661,7 +711,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if ((cell->type == "$eq" || cell->type == "$ne") &&
(assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero()))
{
- cover_list("opt.opt_const.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
+ cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
log("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool";
@@ -699,7 +749,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
sig_y[i] = sig_a[GetSize(sig_a)-1];
}
- cover_list("opt.opt_const.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
+ cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
log("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y));
@@ -760,9 +810,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (identity_wrt_a || identity_wrt_b)
{
if (identity_wrt_a)
- cover_list("opt.opt_const.identwrt.a", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
+ cover_list("opt.opt_expr.identwrt.a", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
if (identity_wrt_b)
- cover_list("opt.opt_const.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
+ cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
log("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
@@ -786,14 +836,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") &&
cell->getPort("\\A") == RTLIL::SigSpec(0, 1) && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) {
- cover_list("opt.opt_const.mux_bool", "$mux", "$_MUX_", cell->type.str());
+ cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str());
replace_cell(assign_map, module, cell, "mux_bool", "\\Y", cell->getPort("\\S"));
goto next_cell;
}
if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") &&
cell->getPort("\\A") == RTLIL::SigSpec(1, 1) && cell->getPort("\\B") == RTLIL::SigSpec(0, 1)) {
- cover_list("opt.opt_const.mux_invert", "$mux", "$_MUX_", cell->type.str());
+ cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", cell->getPort("\\S"));
cell->unsetPort("\\B");
@@ -812,7 +862,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) {
- cover_list("opt.opt_const.mux_and", "$mux", "$_MUX_", cell->type.str());
+ cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", cell->getPort("\\S"));
cell->unsetPort("\\S");
@@ -832,7 +882,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) {
- cover_list("opt.opt_const.mux_or", "$mux", "$_MUX_", cell->type.str());
+ cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
log("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\B", cell->getPort("\\S"));
cell->unsetPort("\\S");
@@ -856,7 +906,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
int width = cell->getPort("\\A").size();
if ((cell->getPort("\\A").is_fully_undef() && cell->getPort("\\B").is_fully_undef()) ||
cell->getPort("\\S").is_fully_undef()) {
- cover_list("opt.opt_const.mux_undef", "$mux", "$pmux", cell->type.str());
+ cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str());
replace_cell(assign_map, module, cell, "mux_undef", "\\Y", cell->getPort("\\A"));
goto next_cell;
}
@@ -875,17 +925,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
new_s = new_s.extract(0, new_s.size()-1);
}
if (new_s.size() == 0) {
- cover_list("opt.opt_const.mux_empty", "$mux", "$pmux", cell->type.str());
+ cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str());
replace_cell(assign_map, module, cell, "mux_empty", "\\Y", new_a);
goto next_cell;
}
if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) {
- cover_list("opt.opt_const.mux_sel01", "$mux", "$pmux", cell->type.str());
+ cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str());
replace_cell(assign_map, module, cell, "mux_sel01", "\\Y", new_s);
goto next_cell;
}
if (cell->getPort("\\S").size() != new_s.size()) {
- cover_list("opt.opt_const.mux_reduce", "$mux", "$pmux", cell->type.str());
+ cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
log("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", new_a);
@@ -911,7 +961,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), dummy_arg, \
cell->parameters["\\A_SIGNED"].as_bool(), false, \
cell->parameters["\\Y_WIDTH"].as_int())); \
- cover("opt.opt_const.const.$" #_t); \
+ cover("opt.opt_expr.const.$" #_t); \
replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), "\\Y", y); \
goto next_cell; \
} \
@@ -926,7 +976,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
cell->parameters["\\A_SIGNED"].as_bool(), \
cell->parameters["\\B_SIGNED"].as_bool(), \
cell->parameters["\\Y_WIDTH"].as_int())); \
- cover("opt.opt_const.const.$" #_t); \
+ cover("opt.opt_expr.const.$" #_t); \
replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), "\\Y", y); \
goto next_cell; \
} \
@@ -1002,7 +1052,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (a_val == 0)
{
- cover("opt.opt_const.mul_shift.zero");
+ cover("opt.opt_expr.mul_shift.zero");
log("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
cell->name.c_str(), module->name.c_str());
@@ -1018,9 +1068,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (a_val == (1 << i))
{
if (swapped_ab)
- cover("opt.opt_const.mul_shift.swapped");
+ cover("opt.opt_expr.mul_shift.swapped");
else
- cover("opt.opt_const.mul_shift.unswapped");
+ cover("opt.opt_expr.mul_shift.unswapped");
log("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
a_val, cell->name.c_str(), module->name.c_str(), i);
@@ -1048,6 +1098,75 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ if (!keepdc && cell->type.in("$div", "$mod"))
+ {
+ bool b_signed = cell->parameters["\\B_SIGNED"].as_bool();
+ SigSpec sig_b = assign_map(cell->getPort("\\B"));
+ SigSpec sig_y = assign_map(cell->getPort("\\Y"));
+
+ if (sig_b.is_fully_def() && sig_b.size() <= 32)
+ {
+ int b_val = sig_b.as_int();
+
+ if (b_val == 0)
+ {
+ cover("opt.opt_expr.divmod_zero");
+
+ log("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
+ cell->name.c_str(), module->name.c_str());
+
+ module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size())));
+ module->remove(cell);
+
+ did_something = true;
+ goto next_cell;
+ }
+
+ for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++)
+ if (b_val == (1 << i))
+ {
+ if (cell->type == "$div")
+ {
+ cover("opt.opt_expr.div_shift");
+
+ log("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
+ b_val, cell->name.c_str(), module->name.c_str(), i);
+
+ std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
+
+ while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
+ new_b.pop_back();
+
+ cell->type = "$shr";
+ cell->parameters["\\B_WIDTH"] = GetSize(new_b);
+ cell->parameters["\\B_SIGNED"] = false;
+ cell->setPort("\\B", new_b);
+ cell->check();
+ }
+ else
+ {
+ cover("opt.opt_expr.mod_mask");
+
+ log("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
+ b_val, cell->name.c_str(), module->name.c_str());
+
+ std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
+
+ if (b_signed)
+ new_b.push_back(State::S0);
+
+ cell->type = "$and";
+ cell->parameters["\\B_WIDTH"] = GetSize(new_b);
+ cell->setPort("\\B", new_b);
+ cell->check();
+ }
+
+ did_something = true;
+ goto next_cell;
+ }
+ }
+ }
+
next_cell:;
#undef ACTION_DO
#undef ACTION_DO_Y
@@ -1056,15 +1175,16 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
-struct OptConstPass : public Pass {
- OptConstPass() : Pass("opt_const", "perform const folding") { }
+struct OptExprPass : public Pass {
+ OptExprPass() : Pass("opt_expr", "perform const folding and simple expression rewriting") { }
virtual void help()
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" opt_const [options] [selection]\n");
+ log(" opt_expr [options] [selection]\n");
log("\n");
log("This pass performs const folding on internal cell types with constant inputs.\n");
+ log("It also performs some simple expression rewritring.\n");
log("\n");
log(" -mux_undef\n");
log(" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n");
@@ -1100,7 +1220,7 @@ struct OptConstPass : public Pass {
bool do_fine = false;
bool keepdc = false;
- log_header("Executing OPT_CONST pass (perform const folding).\n");
+ log_header(design, "Executing OPT_EXPR pass (perform const folding).\n");
log_push();
size_t argidx;
@@ -1158,6 +1278,6 @@ struct OptConstPass : public Pass {
log_pop();
}
-} OptConstPass;
+} OptExprPass;
PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_merge.cc
index 46752e43..97989d27 100644
--- a/passes/opt/opt_share.cc
+++ b/passes/opt/opt_merge.cc
@@ -31,7 +31,7 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-struct OptShareWorker
+struct OptMergeWorker
{
RTLIL::Design *design;
RTLIL::Module *module;
@@ -45,6 +45,29 @@ struct OptShareWorker
dict<const RTLIL::Cell*, std::string> cell_hash_cache;
#endif
+ static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
+ {
+ SigSpec sig_s = conn.at("\\S");
+ SigSpec sig_b = conn.at("\\B");
+
+ int s_width = GetSize(sig_s);
+ int width = GetSize(sig_b) / s_width;
+
+ vector<pair<SigBit, SigSpec>> sb_pairs;
+ for (int i = 0; i < s_width; i++)
+ sb_pairs.push_back(pair<SigBit, SigSpec>(sig_s[i], sig_b.extract(i*width, width)));
+
+ std::sort(sb_pairs.begin(), sb_pairs.end());
+
+ conn["\\S"] = SigSpec();
+ conn["\\B"] = SigSpec();
+
+ for (auto &it : sb_pairs) {
+ conn["\\S"].append(it.first);
+ conn["\\B"].append(it.second);
+ }
+ }
+
#ifdef USE_CELL_HASH_CACHE
std::string int_to_hash_string(unsigned int v)
{
@@ -91,25 +114,40 @@ struct OptShareWorker
assign_map.apply(alt_conn.at("\\A"));
alt_conn.at("\\A").sort_and_unify();
conn = &alt_conn;
+ } else
+ if (cell->type == "$pmux") {
+ alt_conn = *conn;
+ assign_map.apply(alt_conn.at("\\A"));
+ assign_map.apply(alt_conn.at("\\B"));
+ assign_map.apply(alt_conn.at("\\S"));
+ sort_pmux_conn(alt_conn);
+ conn = &alt_conn;
}
+ vector<string> hash_conn_strings;
+
for (auto &it : *conn) {
if (cell->output(it.first))
continue;
RTLIL::SigSpec sig = it.second;
assign_map.apply(sig);
- hash_string += "C " + it.first.str() + "=";
+ string s = "C " + it.first.str() + "=";
for (auto &chunk : sig.chunks()) {
if (chunk.wire)
- hash_string += "{" + chunk.wire->name.str() + " " +
+ s += "{" + chunk.wire->name.str() + " " +
int_to_hash_string(chunk.offset) + " " +
int_to_hash_string(chunk.width) + "}";
else
- hash_string += RTLIL::Const(chunk.data).as_string();
+ s += RTLIL::Const(chunk.data).as_string();
}
- hash_string += "\n";
+ hash_conn_strings.push_back(s + "\n");
}
+ std::sort(hash_conn_strings.begin(), hash_conn_strings.end());
+
+ for (auto it : hash_conn_strings)
+ hash_string += it;
+
cell_hash_cache[cell] = sha1(hash_string);
return cell_hash_cache[cell];
}
@@ -171,6 +209,10 @@ struct OptShareWorker
if (cell1->type == "$reduce_and" || cell1->type == "$reduce_or" || cell1->type == "$reduce_bool") {
conn1["\\A"].sort_and_unify();
conn2["\\A"].sort_and_unify();
+ } else
+ if (cell1->type == "$pmux") {
+ sort_pmux_conn(conn1);
+ sort_pmux_conn(conn2);
}
if (conn1 != conn2) {
@@ -212,14 +254,14 @@ struct OptShareWorker
}
struct CompareCells {
- OptShareWorker *that;
- CompareCells(OptShareWorker *that) : that(that) {}
+ OptMergeWorker *that;
+ CompareCells(OptMergeWorker *that) : that(that) {}
bool operator()(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) const {
return that->compare_cells(cell1, cell2);
}
};
- OptShareWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all) :
+ OptMergeWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all) :
design(design), module(module), assign_map(module), mode_share_all(mode_share_all)
{
total_count = 0;
@@ -286,13 +328,13 @@ struct OptShareWorker
}
};
-struct OptSharePass : public Pass {
- OptSharePass() : Pass("opt_share", "consolidate identical cells") { }
+struct OptMergePass : public Pass {
+ OptMergePass() : Pass("opt_merge", "consolidate identical cells") { }
virtual void help()
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" opt_share [options] [selection]\n");
+ log(" opt_merge [options] [selection]\n");
log("\n");
log("This pass identifies cells with identical type and input signals. Such cells\n");
log("are then merged to one cell.\n");
@@ -306,7 +348,7 @@ struct OptSharePass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing OPT_SHARE pass (detect identical cells).\n");
+ log_header(design, "Executing OPT_MERGE pass (detect identical cells).\n");
bool mode_nomux = false;
bool mode_share_all = false;
@@ -328,7 +370,7 @@ struct OptSharePass : public Pass {
int total_count = 0;
for (auto module : design->selected_modules()) {
- OptShareWorker worker(design, module, mode_nomux, mode_share_all);
+ OptMergeWorker worker(design, module, mode_nomux, mode_share_all);
total_count += worker.total_count;
}
@@ -336,6 +378,6 @@ struct OptSharePass : public Pass {
design->scratchpad_set_bool("opt.did_something", true);
log("Removed a total of %d cells.\n", total_count);
}
-} OptSharePass;
+} OptMergePass;
PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc
index 905a0162..f5ddc2af 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -68,7 +68,7 @@ struct OptMuxtreeWorker
OptMuxtreeWorker(RTLIL::Design *design, RTLIL::Module *module) :
design(design), module(module), assign_map(module), removed_count(0)
{
- log("Running muxtree optimizier on module %s..\n", module->name.c_str());
+ log("Running muxtree optimizer on module %s..\n", module->name.c_str());
log(" Creating internal representation of mux trees.\n");
@@ -464,7 +464,7 @@ struct OptMuxtreePass : public Pass {
}
virtual void execute(vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n");
+ log_header(design, "Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n");
extra_args(args, 1, design);
int total_count = 0;
diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc
index 98b7b2e1..eb9d02ad 100644
--- a/passes/opt/opt_reduce.cc
+++ b/passes/opt/opt_reduce.cc
@@ -354,7 +354,7 @@ struct OptReducePass : public Pass {
{
bool do_fine = false;
- log_header("Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).\n");
+ log_header(design, "Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc
index e1b184af..fa954afa 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -60,7 +60,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
return false;
delete_dlatch:
- log("Removing %s (%s) from module %s.\n", dlatch->name.c_str(), dlatch->type.c_str(), mod->name.c_str());
+ log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod));
remove_init_attr(dlatch->getPort("\\Q"));
mod->remove(dlatch);
return true;
@@ -170,7 +170,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
return false;
delete_dff:
- log("Removing %s (%s) from module %s.\n", dff->name.c_str(), dff->type.c_str(), mod->name.c_str());
+ log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
remove_init_attr(dff->getPort("\\Q"));
mod->remove(dff);
return true;
@@ -190,73 +190,116 @@ struct OptRmdffPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- int total_count = 0;
- log_header("Executing OPT_RMDFF pass (remove dff with constant values).\n");
+ int total_count = 0, total_initdrv = 0;
+ log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n");
extra_args(args, 1, design);
- for (auto &mod_it : design->modules_)
+ for (auto module : design->selected_modules())
{
- if (!design->selected(mod_it.second))
- continue;
-
- assign_map.set(mod_it.second);
- dff_init_map.set(mod_it.second);
- for (auto &it : mod_it.second->wires_)
- if (it.second->attributes.count("\\init") != 0) {
- dff_init_map.add(it.second, it.second->attributes.at("\\init"));
- for (int i = 0; i < GetSize(it.second); i++) {
- SigBit wire_bit(it.second, i), mapped_bit = assign_map(wire_bit);
- if (mapped_bit.wire)
+ pool<SigBit> driven_bits;
+ dict<SigBit, State> init_bits;
+
+ assign_map.set(module);
+ dff_init_map.set(module);
+
+ for (auto wire : module->wires())
+ {
+ if (wire->attributes.count("\\init") != 0) {
+ Const initval = wire->attributes.at("\\init");
+ dff_init_map.add(wire, initval);
+ for (int i = 0; i < GetSize(wire); i++) {
+ SigBit wire_bit(wire, i), mapped_bit = assign_map(wire_bit);
+ if (mapped_bit.wire) {
init_attributes[mapped_bit].insert(wire_bit);
+ if (i < GetSize(initval))
+ init_bits[mapped_bit] = initval[i];
+ }
}
}
+
+ if (wire->port_input) {
+ for (auto bit : assign_map(wire))
+ driven_bits.insert(bit);
+ }
+ }
mux_drivers.clear();
std::vector<RTLIL::IdString> dff_list;
std::vector<RTLIL::IdString> dlatch_list;
- for (auto &it : mod_it.second->cells_) {
- if (it.second->type == "$mux" || it.second->type == "$pmux") {
- if (it.second->getPort("\\A").size() == it.second->getPort("\\B").size())
- mux_drivers.insert(assign_map(it.second->getPort("\\Y")), it.second);
+ for (auto cell : module->cells())
+ {
+ for (auto &conn : cell->connections())
+ if (cell->output(conn.first) || !cell->known())
+ for (auto bit : assign_map(conn.second))
+ driven_bits.insert(bit);
+
+ if (cell->type == "$mux" || cell->type == "$pmux") {
+ if (cell->getPort("\\A").size() == cell->getPort("\\B").size())
+ mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell);
continue;
}
- if (!design->selected(mod_it.second, it.second))
+
+ if (!design->selected(module, cell))
continue;
- if (it.second->type == "$_DFF_N_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_P_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_NN0_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_NN1_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_NP0_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_NP1_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_PN0_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_PN1_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_PP0_") dff_list.push_back(it.first);
- if (it.second->type == "$_DFF_PP1_") dff_list.push_back(it.first);
- if (it.second->type == "$dff") dff_list.push_back(it.first);
- if (it.second->type == "$adff") dff_list.push_back(it.first);
- if (it.second->type == "$dlatch") dlatch_list.push_back(it.first);
+
+ if (cell->type.in("$_DFF_N_", "$_DFF_P_",
+ "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
+ "$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
+ "$dff", "$adff"))
+ dff_list.push_back(cell->name);
+
+ if (cell->type == "$dlatch")
+ dlatch_list.push_back(cell->name);
}
for (auto &id : dff_list) {
- if (mod_it.second->cells_.count(id) > 0 &&
- handle_dff(mod_it.second, mod_it.second->cells_[id]))
+ if (module->cell(id) != nullptr &&
+ handle_dff(module, module->cells_[id]))
total_count++;
}
for (auto &id : dlatch_list) {
- if (mod_it.second->cells_.count(id) > 0 &&
- handle_dlatch(mod_it.second, mod_it.second->cells_[id]))
+ if (module->cell(id) != nullptr &&
+ handle_dlatch(module, module->cells_[id]))
total_count++;
}
+
+ SigSpec const_init_sigs;
+
+ for (auto bit : init_bits)
+ if (!driven_bits.count(bit.first))
+ const_init_sigs.append(bit.first);
+
+ const_init_sigs.sort_and_unify();
+
+ for (SigSpec sig : const_init_sigs.chunks())
+ {
+ Const val;
+
+ for (auto bit : sig)
+ val.bits.push_back(init_bits.at(bit));
+
+ log("Promoting init spec %s = %s to constant driver in module %s.\n",
+ log_signal(sig), log_signal(val), log_id(module));
+
+ module->connect(sig, val);
+ remove_init_attr(sig);
+ total_initdrv++;
+ }
}
assign_map.clear();
mux_drivers.clear();
- if (total_count)
+ if (total_count || total_initdrv)
design->scratchpad_set_bool("opt.did_something", true);
- log("Replaced %d DFF cells.\n", total_count);
+
+ if (total_initdrv)
+ log("Promoted %d init specs to constant drivers.\n", total_initdrv);
+
+ if (total_count)
+ log("Replaced %d DFF cells.\n", total_count);
}
} OptRmdffPass;
diff --git a/passes/opt/share.cc b/passes/opt/share.cc
index 1d9b1006..22914eaa 100644
--- a/passes/opt/share.cc
+++ b/passes/opt/share.cc
@@ -793,10 +793,59 @@ struct ShareWorker
return true;
}
- void optimize_activation_patterns(pool<ssc_pair_t> & /* patterns */)
+ void optimize_activation_patterns(pool<ssc_pair_t> &patterns)
{
// TODO: Remove patterns that are contained in other patterns
- // TODO: Consolidate pairs of patterns that only differ in the value for one signal bit
+
+ dict<SigSpec, pool<Const>> db;
+ bool did_something = false;
+
+ for (auto const &p : patterns)
+ {
+ auto &sig = p.first;
+ auto &val = p.second;
+ int len = GetSize(sig);
+
+ for (int i = 0; i < len; i++)
+ {
+ auto otherval = val;
+
+ if (otherval.bits[i] == State::S0)
+ otherval.bits[i] = State::S1;
+ else if (otherval.bits[i] == State::S1)
+ otherval.bits[i] = State::S0;
+ else
+ continue;
+
+ if (db[sig].count(otherval))
+ {
+ auto newsig = sig;
+ newsig.remove(i);
+
+ auto newval = val;
+ newval.bits.erase(newval.bits.begin() + i);
+
+ db[newsig].insert(newval);
+ db[sig].erase(otherval);
+
+ did_something = true;
+ goto next_pattern;
+ }
+ }
+
+ db[sig].insert(val);
+ next_pattern:;
+ }
+
+ if (!did_something)
+ return;
+
+ patterns.clear();
+ for (auto &it : db)
+ for (auto &val : it.second)
+ patterns.insert(make_pair(it.first, val));
+
+ optimize_activation_patterns(patterns);
}
const pool<ssc_pair_t> &find_cell_activation_patterns(RTLIL::Cell *cell, const char *indent)
@@ -1451,7 +1500,7 @@ struct SharePass : public Pass {
config.generic_other_ops.insert("$alu");
config.generic_other_ops.insert("$macc");
- log_header("Executing SHARE pass (SAT-based resource sharing).\n");
+ log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 4f08da67..07503fbb 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -366,15 +366,26 @@ struct WreducePass : public Pass {
log(" assign y = a + b + c + 1;\n");
log(" endmodule\n");
log("\n");
+ log("Options:\n");
+ log("\n");
+ log(" -memx\n");
+ log(" Do not change the width of memory address ports. Use this options in\n");
+ log(" flows that use the 'memory_memx' pass.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, Design *design)
{
WreduceConfig config;
+ bool opt_memx = false;
- log_header("Executing WREDUCE pass (reducing word size of cells).\n");
+ log_header(design, "Executing WREDUCE pass (reducing word size of cells).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-memx") {
+ opt_memx = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -385,6 +396,7 @@ struct WreducePass : public Pass {
continue;
for (auto c : module->selected_cells())
+ {
if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
"$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) {
@@ -396,6 +408,23 @@ struct WreducePass : public Pass {
module->connect(sig, Const(0, GetSize(sig)));
}
}
+ if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
+ IdString memid = c->getParam("\\MEMID").decode_string();
+ RTLIL::Memory *mem = module->memories.at(memid);
+ if (mem->start_offset >= 0) {
+ int cur_addrbits = c->getParam("\\ABITS").as_int();
+ int max_addrbits = ceil_log2(mem->start_offset + mem->size);
+ if (cur_addrbits > max_addrbits) {
+ log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
+ cur_addrbits-max_addrbits, cur_addrbits,
+ c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init",
+ log_id(module), log_id(c), log_id(memid));
+ c->setParam("\\ABITS", max_addrbits);
+ c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits));
+ }
+ }
+ }
+ }
WreduceWorker worker(&config, module);
worker.run();
diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc
index 577ff6bf..d5366f26 100644
--- a/passes/proc/proc.cc
+++ b/passes/proc/proc.cc
@@ -52,12 +52,17 @@ struct ProcPass : public Pass {
log(" -global_arst [!]<netname>\n");
log(" This option is passed through to proc_arst.\n");
log("\n");
+ log(" -ifx\n");
+ log(" This option is passed through to proc_mux. proc_rmdead is not\n");
+ log(" executed in -ifx mode.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
std::string global_arst;
+ bool ifxmode = false;
- log_header("Executing PROC pass (convert processes to netlists).\n");
+ log_header(design, "Executing PROC pass (convert processes to netlists).\n");
log_push();
size_t argidx;
@@ -67,18 +72,23 @@ struct ProcPass : public Pass {
global_arst = args[++argidx];
continue;
}
+ if (args[argidx] == "-ifx") {
+ ifxmode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
Pass::call(design, "proc_clean");
- Pass::call(design, "proc_rmdead");
+ if (!ifxmode)
+ Pass::call(design, "proc_rmdead");
Pass::call(design, "proc_init");
if (global_arst.empty())
Pass::call(design, "proc_arst");
else
Pass::call(design, "proc_arst -global_arst " + global_arst);
- Pass::call(design, "proc_mux");
+ Pass::call(design, ifxmode ? "proc_mux -ifx" : "proc_mux");
Pass::call(design, "proc_dlatch");
Pass::call(design, "proc_dff");
Pass::call(design, "proc_clean");
diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc
index 1da23728..216b00dd 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -226,7 +226,7 @@ struct ProcArstPass : public Pass {
std::string global_arst;
bool global_arst_neg = false;
- log_header("Executing PROC_ARST pass (detect async resets in processes).\n");
+ log_header(design, "Executing PROC_ARST pass (detect async resets in processes).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc
index 35801951..7dbabc21 100644
--- a/passes/proc/proc_clean.cc
+++ b/passes/proc/proc_clean.cc
@@ -156,7 +156,7 @@ struct ProcCleanPass : public Pass {
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
int total_count = 0;
- log_header("Executing PROC_CLEAN pass (remove empty switches from decision trees).\n");
+ log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n");
extra_args(args, 1, design);
diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc
index 63713139..f532990c 100644
--- a/passes/proc/proc_dff.cc
+++ b/passes/proc/proc_dff.cc
@@ -369,7 +369,7 @@ struct ProcDffPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing PROC_DFF pass (convert process syncs to FFs).\n");
+ log_header(design, "Executing PROC_DFF pass (convert process syncs to FFs).\n");
extra_args(args, 1, design);
diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc
index e37d81dd..6621afd3 100644
--- a/passes/proc/proc_dlatch.cc
+++ b/passes/proc/proc_dlatch.cc
@@ -33,6 +33,8 @@ struct proc_dlatch_db_t
Module *module;
SigMap sigmap;
+ pool<Cell*> generated_dlatches;
+ dict<Cell*, vector<SigBit>> mux_srcbits;
dict<SigBit, pair<Cell*, int>> mux_drivers;
dict<SigBit, int> sigusers;
@@ -40,10 +42,24 @@ struct proc_dlatch_db_t
{
for (auto cell : module->cells())
{
- if (cell->type.in("$mux", "$pmux")) {
+ if (cell->type.in("$mux", "$pmux"))
+ {
auto sig_y = sigmap(cell->getPort("\\Y"));
for (int i = 0; i < GetSize(sig_y); i++)
mux_drivers[sig_y[i]] = pair<Cell*, int>(cell, i);
+
+ pool<SigBit> mux_srcbits_pool;
+ for (auto bit : sigmap(cell->getPort("\\A")))
+ mux_srcbits_pool.insert(bit);
+ for (auto bit : sigmap(cell->getPort("\\B")))
+ mux_srcbits_pool.insert(bit);
+
+ vector<SigBit> mux_srcbits_vec;
+ for (auto bit : mux_srcbits_pool)
+ if (bit.wire != nullptr)
+ mux_srcbits_vec.push_back(bit);
+
+ mux_srcbits[cell].swap(mux_srcbits_vec);
}
for (auto &conn : cell->connections())
@@ -58,6 +74,42 @@ struct proc_dlatch_db_t
sigusers[bit]++;
}
+ bool quickcheck(const SigSpec &haystack, const SigSpec &needle)
+ {
+ pool<SigBit> haystack_bits = sigmap(haystack).to_sigbit_pool();
+ pool<SigBit> needle_bits = sigmap(needle).to_sigbit_pool();
+
+ pool<Cell*> cells_queue, cells_visited;
+ pool<SigBit> bits_queue, bits_visited;
+
+ bits_queue = haystack_bits;
+ while (!bits_queue.empty())
+ {
+ for (auto &bit : bits_queue) {
+ auto it = mux_drivers.find(bit);
+ if (it != mux_drivers.end())
+ if (!cells_visited.count(it->second.first))
+ cells_queue.insert(it->second.first);
+ bits_visited.insert(bit);
+ }
+
+ bits_queue.clear();
+
+ for (auto c : cells_queue) {
+ for (auto bit : mux_srcbits[c]) {
+ if (needle_bits.count(bit))
+ return true;
+ if (!bits_visited.count(bit))
+ bits_queue.insert(bit);
+ }
+ }
+
+ cells_queue.clear();
+ }
+
+ return false;
+ }
+
struct rule_node_t
{
// a node is true if "signal" equals "match" and [any
@@ -202,6 +254,84 @@ struct proc_dlatch_db_t
rules_sig[n] = and_bits[0];
return and_bits[0];
}
+
+ void fixup_mux(Cell *cell)
+ {
+ SigSpec sig_a = cell->getPort("\\A");
+ SigSpec sig_b = cell->getPort("\\B");
+ SigSpec sig_s = cell->getPort("\\S");
+ SigSpec sig_any_valid_b;
+
+ SigSpec sig_new_b, sig_new_s;
+ for (int i = 0; i < GetSize(sig_s); i++) {
+ SigSpec b = sig_b.extract(i*GetSize(sig_a), GetSize(sig_a));
+ if (!b.is_fully_undef()) {
+ sig_any_valid_b = b;
+ sig_new_b.append(b);
+ sig_new_s.append(sig_s[i]);
+ }
+ }
+
+ if (sig_new_s.empty()) {
+ sig_new_b = sig_a;
+ sig_new_s = State::S0;
+ }
+
+ if (sig_a.is_fully_undef() && !sig_any_valid_b.empty())
+ cell->setPort("\\A", sig_any_valid_b);
+
+ if (GetSize(sig_new_s) == 1) {
+ cell->type = "$mux";
+ cell->unsetParam("\\S_WIDTH");
+ } else {
+ cell->type = "$pmux";
+ cell->setParam("\\S_WIDTH", GetSize(sig_new_s));
+ }
+
+ cell->setPort("\\B", sig_new_b);
+ cell->setPort("\\S", sig_new_s);
+ }
+
+ void fixup_muxes()
+ {
+ pool<Cell*> visited, queue;
+ dict<Cell*, pool<SigBit>> upstream_cell2net;
+ dict<SigBit, pool<Cell*>> upstream_net2cell;
+
+ CellTypes ct;
+ ct.setup_internals();
+
+ for (auto cell : module->cells())
+ for (auto conn : cell->connections()) {
+ if (cell->input(conn.first))
+ for (auto bit : sigmap(conn.second))
+ upstream_cell2net[cell].insert(bit);
+ if (cell->output(conn.first))
+ for (auto bit : sigmap(conn.second))
+ upstream_net2cell[bit].insert(cell);
+ }
+
+ queue = generated_dlatches;
+ while (!queue.empty())
+ {
+ pool<Cell*> next_queue;
+
+ for (auto cell : queue) {
+ if (cell->type.in("$mux", "$pmux"))
+ fixup_mux(cell);
+ for (auto bit : upstream_cell2net[cell])
+ for (auto cell : upstream_net2cell[bit])
+ next_queue.insert(cell);
+ visited.insert(cell);
+ }
+
+ queue.clear();
+ for (auto cell : next_queue) {
+ if (!visited.count(cell) && ct.cell_known(cell->type))
+ queue.insert(cell);
+ }
+ }
+ }
};
void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
@@ -218,9 +348,17 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
continue;
}
- for (auto ss : sr->actions) {
+ for (auto ss : sr->actions)
+ {
db.sigmap.apply(ss.first);
db.sigmap.apply(ss.second);
+
+ if (!db.quickcheck(ss.second, ss.first)) {
+ nolatches_bits.first.append(ss.first);
+ nolatches_bits.second.append(ss.second);
+ continue;
+ }
+
for (int i = 0; i < GetSize(ss.first); i++)
latches_out_in[ss.first[i]] = ss.second[i];
}
@@ -268,6 +406,8 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
SigSpec rhs = latches_bits.second.extract(offset, width);
Cell *cell = db.module->addDlatch(NEW_ID, db.module->Not(NEW_ID, db.make_hold(n)), rhs, lhs);
+ db.generated_dlatches.insert(cell);
+
log("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n",
db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), log_id(cell));
}
@@ -292,7 +432,7 @@ struct ProcDlatchPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing PROC_DLATCH pass (convert process syncs to latches).\n");
+ log_header(design, "Executing PROC_DLATCH pass (convert process syncs to latches).\n");
extra_args(args, 1, design);
@@ -301,6 +441,7 @@ struct ProcDlatchPass : public Pass {
for (auto &proc_it : module->processes)
if (design->selected(module, proc_it.second))
proc_dlatch(db, proc_it.second);
+ db.fixup_muxes();
}
}
} ProcDlatchPass;
diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc
index 633d4e58..0c8fb83d 100644
--- a/passes/proc/proc_init.cc
+++ b/passes/proc/proc_init.cc
@@ -61,13 +61,28 @@ void proc_init(RTLIL::Module *mod, RTLIL::Process *proc)
log_cmd_error("Failed to get a constant init value for %s: %s\n", log_signal(lhs), log_signal(rhs));
int offset = 0;
- for (auto &lhs_c : lhs.chunks()) {
- if (lhs_c.wire != NULL) {
- RTLIL::SigSpec value = rhs.extract(offset, lhs_c.width);
- if (value.size() != lhs_c.wire->width)
- log_cmd_error("Init value is not for the entire wire: %s = %s\n", log_signal(lhs_c), log_signal(value));
- log(" Setting init value: %s = %s\n", log_signal(lhs_c.wire), log_signal(value));
- lhs_c.wire->attributes["\\init"] = value.as_const();
+ for (auto &lhs_c : lhs.chunks())
+ {
+ if (lhs_c.wire != nullptr)
+ {
+ SigSpec valuesig = rhs.extract(offset, lhs_c.width);
+ if (!valuesig.is_fully_const())
+ log_cmd_error("Non-const initialization value: %s = %s\n", log_signal(lhs_c), log_signal(valuesig));
+
+ Const value = valuesig.as_const();
+ Const &wireinit = lhs_c.wire->attributes["\\init"];
+
+ while (GetSize(wireinit.bits) < lhs_c.wire->width)
+ wireinit.bits.push_back(State::Sx);
+
+ for (int i = 0; i < lhs_c.width; i++) {
+ auto &initbit = wireinit.bits[i + lhs_c.offset];
+ if (initbit != State::Sx && initbit != value[i])
+ log_cmd_error("Conflicting initialization values for %s.\n", log_signal(lhs_c));
+ initbit = value[i];
+ }
+
+ log(" Set init value: %s = %s\n", log_signal(lhs_c.wire), log_signal(wireinit));
}
offset += lhs_c.width;
}
@@ -100,7 +115,7 @@ struct ProcInitPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing PROC_INIT pass (extract init attributes).\n");
+ log_header(design, "Executing PROC_INIT pass (extract init attributes).\n");
extra_args(args, 1, design);
diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc
index 943e8c56..57e131ca 100644
--- a/passes/proc/proc_mux.cc
+++ b/passes/proc/proc_mux.cc
@@ -143,7 +143,7 @@ struct SnippetSwCache
}
};
-RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw)
+RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw, bool ifxmode)
{
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
@@ -164,14 +164,14 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
if (comp.size() == 0)
return RTLIL::SigSpec();
- if (sig.size() == 1 && comp == RTLIL::SigSpec(1,1))
+ if (sig.size() == 1 && comp == RTLIL::SigSpec(1,1) && !ifxmode)
{
mod->connect(RTLIL::SigSig(RTLIL::SigSpec(cmp_wire, cmp_wire->width++), sig));
}
else
{
// create compare cell
- RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), "$eq");
+ RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), ifxmode ? "$eqx" : "$eq");
eq_cell->attributes = sw->attributes;
eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
@@ -211,7 +211,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
return RTLIL::SigSpec(ctrl_wire);
}
-RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw)
+RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode)
{
log_assert(when_signal.size() == else_signal.size());
@@ -223,7 +223,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
return when_signal;
// compare results
- RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw);
+ RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode);
if (ctrl_sig.size() == 0)
return when_signal;
log_assert(ctrl_sig.size() == 1);
@@ -245,12 +245,15 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
return RTLIL::SigSpec(result_wire);
}
-void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw)
+void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode)
{
log_assert(last_mux_cell != NULL);
log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size());
- RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw);
+ if (when_signal == last_mux_cell->getPort("\\A"))
+ return;
+
+ RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode);
log_assert(ctrl_sig.size() == 1);
last_mux_cell->type = "$pmux";
@@ -266,7 +269,7 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve
}
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool, hash_ptr_ops> &swpara,
- RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval)
+ RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval, bool ifxmode)
{
RTLIL::SigSpec result = defval;
@@ -329,7 +332,7 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
for (auto pat : cs2->compare)
if (!pat.is_fully_const())
extra_group_for_next_case = true;
- else
+ else if (!ifxmode)
pool.take(pat);
}
}
@@ -340,18 +343,18 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
for (size_t i = 0; i < sw->cases.size(); i++) {
int case_idx = sw->cases.size() - i - 1;
RTLIL::CaseRule *cs2 = sw->cases[case_idx];
- RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, cs2, sig, initial_val);
+ RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, cs2, sig, initial_val, ifxmode);
if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1])
- append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw);
+ append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, ifxmode);
else
- result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw);
+ result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, ifxmode);
}
}
return result;
}
-void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc)
+void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc, bool ifxmode)
{
log("Creating decoders for process `%s.%s'.\n", mod->name.c_str(), proc->name.c_str());
@@ -372,7 +375,7 @@ void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc)
log("%6d/%d: %s\n", ++cnt, GetSize(sigsnip.snippets), log_signal(sig));
- RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, &proc->root_case, sig, RTLIL::SigSpec(RTLIL::State::Sx, sig.size()));
+ RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, &proc->root_case, sig, RTLIL::SigSpec(RTLIL::State::Sx, sig.size()), ifxmode);
mod->connect(RTLIL::SigSig(sig, value));
}
}
@@ -383,23 +386,37 @@ struct ProcMuxPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" proc_mux [selection]\n");
+ log(" proc_mux [options] [selection]\n");
log("\n");
log("This pass converts the decision trees in processes (originating from if-else\n");
log("and case statements) to trees of multiplexer cells.\n");
log("\n");
+ log(" -ifx\n");
+ log(" Use Verilog simulation behavior with respect to undef values in\n");
+ log(" 'case' expressions and 'if' conditions.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing PROC_MUX pass (convert decision trees to multiplexers).\n");
+ bool ifxmode = false;
+ log_header(design, "Executing PROC_MUX pass (convert decision trees to multiplexers).\n");
- extra_args(args, 1, design);
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-ifx") {
+ ifxmode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
for (auto mod : design->modules())
if (design->selected(mod))
for (auto &proc_it : mod->processes)
if (design->selected(mod, proc_it.second))
- proc_mux(mod, proc_it.second);
+ proc_mux(mod, proc_it.second, ifxmode);
}
} ProcMuxPass;
diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc
index f60d4b30..5672fb47 100644
--- a/passes/proc/proc_rmdead.cc
+++ b/passes/proc/proc_rmdead.cc
@@ -51,8 +51,8 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter)
counter++;
continue;
}
- if (pool.empty())
- sw->cases[i]->compare.clear();
+ // if (pool.empty())
+ // sw->cases[i]->compare.clear();
}
for (auto switch_it : sw->cases[i]->switches)
@@ -76,7 +76,7 @@ struct ProcRmdeadPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing PROC_RMDEAD pass (remove dead branches from decision trees).\n");
+ log_header(design, "Executing PROC_RMDEAD pass (remove dead branches from decision trees).\n");
extra_args(args, 1, design);
diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc
index 4fa6bf0d..0c5f6fc6 100644
--- a/passes/sat/Makefile.inc
+++ b/passes/sat/Makefile.inc
@@ -4,4 +4,5 @@ OBJS += passes/sat/freduce.o
OBJS += passes/sat/eval.o
OBJS += passes/sat/miter.o
OBJS += passes/sat/expose.o
+OBJS += passes/sat/assertpmux.o
diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc
new file mode 100644
index 00000000..63a90767
--- /dev/null
+++ b/passes/sat/assertpmux.cc
@@ -0,0 +1,240 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct AssertpmuxWorker
+{
+ Module *module;
+ SigMap sigmap;
+
+ bool flag_noinit;
+ bool flag_always;
+
+ // get<0> ... mux cell
+ // get<1> ... mux port index
+ // get<2> ... mux bit index
+ dict<SigBit, pool<tuple<Cell*, int, int>>> sigbit_muxusers;
+
+ dict<SigBit, SigBit> sigbit_actsignals;
+ dict<SigSpec, SigBit> sigspec_actsignals;
+ dict<tuple<Cell*, int>, SigBit> muxport_actsignal;
+
+ AssertpmuxWorker(Module *module, bool flag_noinit, bool flag_always) :
+ module(module), sigmap(module), flag_noinit(flag_noinit), flag_always(flag_always)
+ {
+ for (auto wire : module->wires())
+ {
+ if (wire->port_output)
+ for (auto bit : sigmap(wire))
+ sigbit_actsignals[bit] = State::S1;
+ }
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type.in("$mux", "$pmux"))
+ {
+ int width = cell->getParam("\\WIDTH").as_int();
+ int numports = cell->type == "$mux" ? 2 : cell->getParam("\\S_WIDTH").as_int() + 1;
+
+ SigSpec sig_a = sigmap(cell->getPort("\\A"));
+ SigSpec sig_b = sigmap(cell->getPort("\\B"));
+ SigSpec sig_s = sigmap(cell->getPort("\\S"));
+
+ for (int i = 0; i < numports; i++) {
+ SigSpec bits = i == 0 ? sig_a : sig_b.extract(width*(i-1), width);
+ for (int k = 0; k < width; k++) {
+ tuple<Cell*, int, int> muxuser(cell, i, k);
+ sigbit_muxusers[bits[k]].insert(muxuser);
+ }
+ }
+ }
+ else
+ {
+ for (auto &conn : cell->connections()) {
+ if (!cell->known() || cell->input(conn.first))
+ for (auto bit : sigmap(conn.second))
+ sigbit_actsignals[bit] = State::S1;
+ }
+ }
+ }
+ }
+
+ SigBit get_bit_activation(SigBit bit)
+ {
+ sigmap.apply(bit);
+
+ if (sigbit_actsignals.count(bit) == 0)
+ {
+ SigSpec output;
+
+ for (auto muxuser : sigbit_muxusers.at(bit))
+ {
+ Cell *cell = std::get<0>(muxuser);
+ int portidx = std::get<1>(muxuser);
+ int bitidx = std::get<2>(muxuser);
+
+ tuple<Cell*, int> muxport(cell, portidx);
+
+ if (muxport_actsignal.count(muxport) == 0) {
+ if (portidx == 0)
+ muxport_actsignal[muxport] = module->LogicNot(NEW_ID, cell->getPort("\\S"));
+ else
+ muxport_actsignal[muxport] = cell->getPort("\\S")[portidx-1];
+ }
+
+ output.append(module->LogicAnd(NEW_ID, muxport_actsignal.at(muxport), get_bit_activation(cell->getPort("\\Y")[bitidx])));
+ }
+
+ output.sort_and_unify();
+
+ if (GetSize(output) == 0)
+ output = State::S0;
+ else if (GetSize(output) > 1)
+ output = module->ReduceOr(NEW_ID, output);
+
+ sigbit_actsignals[bit] = output.as_bit();
+ }
+
+ return sigbit_actsignals.at(bit);
+ }
+
+ SigBit get_activation(SigSpec sig)
+ {
+ sigmap.apply(sig);
+ sig.sort_and_unify();
+
+ if (sigspec_actsignals.count(sig) == 0)
+ {
+ SigSpec output;
+
+ for (auto bit : sig)
+ output.append(get_bit_activation(bit));
+
+ output.sort_and_unify();
+
+ if (GetSize(output) == 0)
+ output = State::S0;
+ else if (GetSize(output) > 1)
+ output = module->ReduceOr(NEW_ID, output);
+
+ sigspec_actsignals[sig] = output.as_bit();
+ }
+
+ return sigspec_actsignals.at(sig);
+ }
+
+ void run(Cell *pmux)
+ {
+ log("Adding assert for $pmux cell %s.%s.\n", log_id(module), log_id(pmux));
+
+ int swidth = pmux->getParam("\\S_WIDTH").as_int();
+ int cntbits = ceil_log2(swidth+1);
+
+ SigSpec sel = pmux->getPort("\\S");
+ SigSpec cnt(State::S0, cntbits);
+
+ for (int i = 0; i < swidth; i++)
+ cnt = module->Add(NEW_ID, cnt, sel[i]);
+
+ SigSpec assert_a = module->Le(NEW_ID, cnt, SigSpec(1, cntbits));
+ SigSpec assert_en;
+
+ if (flag_noinit)
+ assert_en.append(module->LogicNot(NEW_ID, module->Initstate(NEW_ID)));
+
+ if (!flag_always)
+ assert_en.append(get_activation(pmux->getPort("\\Y")));
+
+ if (GetSize(assert_en) == 0)
+ assert_en = State::S1;
+
+ if (GetSize(assert_en) == 2)
+ assert_en = module->LogicAnd(NEW_ID, assert_en[0], assert_en[1]);
+
+ Cell *assert_cell = module->addAssert(NEW_ID, assert_a, assert_en);
+
+ if (pmux->attributes.count("\\src") != 0)
+ assert_cell->attributes["\\src"] = pmux->attributes.at("\\src");
+ }
+};
+
+struct AssertpmuxPass : public Pass {
+ AssertpmuxPass() : Pass("assertpmux", "convert internal signals to module ports") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" assertpmux [options] [selection]\n");
+ log("\n");
+ log("This command adds asserts to the design that assert that all parallel muxes\n");
+ log("($pmux cells) have a maximum of one of their inputs enable at any time.\n");
+ log("\n");
+ log(" -noinit\n");
+ log(" do not enforce the pmux condition during the init state\n");
+ log("\n");
+ log(" -always\n");
+ log(" usually the $pmux condition is only checked when the $pmux output\n");
+ log(" is used be the mux tree it drives. this option will deactivate this\n");
+ log(" additional constrained and check the $pmux condition always.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ bool flag_noinit = false;
+ bool flag_always = false;
+
+ log_header(design, "Executing ASSERTPMUX pass (add asserts for $pmux cells).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-noinit") {
+ flag_noinit = true;
+ continue;
+ }
+ if (args[argidx] == "-always") {
+ flag_always = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ AssertpmuxWorker worker(module, flag_noinit, flag_always);
+ vector<Cell*> pmux_cells;
+
+ for (auto cell : module->selected_cells())
+ if (cell->type == "$pmux")
+ pmux_cells.push_back(cell);
+
+ for (auto cell : pmux_cells)
+ worker.run(cell);
+ }
+
+ }
+} AssertpmuxPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc
index 614a1bd3..09f69cc5 100644
--- a/passes/sat/eval.cc
+++ b/passes/sat/eval.cc
@@ -389,7 +389,7 @@ struct EvalPass : public Pass {
std::vector<std::string> shows, tables;
bool set_undef = false;
- log_header("Executing EVAL pass (evaluate the circuit given an input).\n");
+ log_header(design, "Executing EVAL pass (evaluate the circuit given an input).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc
index ebdf2ed5..9427547f 100644
--- a/passes/sat/expose.cc
+++ b/passes/sat/expose.cc
@@ -262,7 +262,7 @@ struct ExposePass : public Pass {
bool flag_evert_dff = false;
std::string sep = ".";
- log_header("Executing EXPOSE pass (exposing internal signals as outputs).\n");
+ log_header(design, "Executing EXPOSE pass (exposing internal signals as outputs).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/sat/freduce.cc b/passes/sat/freduce.cc
index 373b8048..77263f6a 100644
--- a/passes/sat/freduce.cc
+++ b/passes/sat/freduce.cc
@@ -798,7 +798,7 @@ struct FreducePass : public Pass {
inv_mode = false;
dump_prefix = std::string();
- log_header("Executing FREDUCE pass (perform functional reduction).\n");
+ log_header(design, "Executing FREDUCE pass (perform functional reduction).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc
index 682299ef..4854e19b 100644
--- a/passes/sat/miter.cc
+++ b/passes/sat/miter.cc
@@ -32,7 +32,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
bool flag_make_assert = false;
bool flag_flatten = false;
- log_header("Executing MITER pass (creating miter circuit).\n");
+ log_header(design, "Executing MITER pass (creating miter circuit).\n");
size_t argidx;
for (argidx = 2; argidx < args.size(); argidx++)
@@ -254,7 +254,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (flag_flatten) {
log_push();
- Pass::call_on_module(design, miter_module, "flatten; opt_const -keepdc -undriven;;");
+ Pass::call_on_module(design, miter_module, "flatten; opt_expr -keepdc -undriven;;");
log_pop();
}
}
@@ -264,7 +264,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
bool flag_make_outputs = false;
bool flag_flatten = false;
- log_header("Executing MITER pass (creating miter circuit).\n");
+ log_header(design, "Executing MITER pass (creating miter circuit).\n");
size_t argidx;
for (argidx = 2; argidx < args.size(); argidx++)
@@ -327,7 +327,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
if (flag_flatten) {
log_push();
- Pass::call_on_module(design, module, "opt_const -keepdc -undriven;;");
+ Pass::call_on_module(design, module, "opt_expr -keepdc -undriven;;");
log_pop();
}
}
@@ -361,7 +361,7 @@ struct MiterPass : public Pass {
log(" also create an 'assert' cell that checks if trigger is always low.\n");
log("\n");
log(" -flatten\n");
- log(" call 'flatten; opt_const -keepdc -undriven;;' on the miter circuit.\n");
+ log(" call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
log("\n");
log("\n");
log(" miter -assert [options] module [miter_name]\n");
@@ -375,7 +375,7 @@ struct MiterPass : public Pass {
log(" keep module output ports.\n");
log("\n");
log(" -flatten\n");
- log(" call 'flatten; opt_const -keepdc -undriven;;' on the miter circuit.\n");
+ log(" call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc
index 2e9c6d2f..a6ac7afd 100644
--- a/passes/sat/sat.cc
+++ b/passes/sat/sat.cc
@@ -90,106 +90,16 @@ struct SatHelper
log_cmd_error("Bit %d of %s is undef but option -enable_undef is missing!\n", int(i), log_signal(sig));
}
- void setup_init()
- {
- log ("\nSetting up initial state:\n");
-
- RTLIL::SigSpec big_lhs, big_rhs;
-
- for (auto &it : module->wires_)
- {
- if (it.second->attributes.count("\\init") == 0)
- continue;
-
- RTLIL::SigSpec lhs = sigmap(it.second);
- RTLIL::SigSpec rhs = it.second->attributes.at("\\init");
- log_assert(lhs.size() == rhs.size());
-
- RTLIL::SigSpec removed_bits;
- for (int i = 0; i < lhs.size(); i++) {
- RTLIL::SigSpec bit = lhs.extract(i, 1);
- if (!satgen.initial_state.check_all(bit)) {
- removed_bits.append(bit);
- lhs.remove(i, 1);
- rhs.remove(i, 1);
- i--;
- }
- }
-
- if (removed_bits.size())
- log_warning("ignoring initial value on non-register: %s\n", log_signal(removed_bits));
-
- if (lhs.size()) {
- log("Import set-constraint from init attribute: %s = %s\n", log_signal(lhs), log_signal(rhs));
- big_lhs.remove2(lhs, &big_rhs);
- big_lhs.append(lhs);
- big_rhs.append(rhs);
- }
- }
-
- for (auto &s : sets_init)
- {
- RTLIL::SigSpec lhs, rhs;
-
- if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
- log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str());
- if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
- log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str());
- show_signal_pool.add(sigmap(lhs));
- show_signal_pool.add(sigmap(rhs));
-
- if (lhs.size() != rhs.size())
- log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
- s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
-
- log("Import set-constraint: %s = %s\n", log_signal(lhs), log_signal(rhs));
- big_lhs.remove2(lhs, &big_rhs);
- big_lhs.append(lhs);
- big_rhs.append(rhs);
- }
-
- if (!satgen.initial_state.check_all(big_lhs)) {
- RTLIL::SigSpec rem = satgen.initial_state.remove(big_lhs);
- log_cmd_error("Found -set-init bits that are not part of the initial_state: %s\n", log_signal(rem));
- }
-
- if (set_init_def) {
- RTLIL::SigSpec rem = satgen.initial_state.export_all();
- std::vector<int> undef_rem = satgen.importUndefSigSpec(rem, 1);
- ez->assume(ez->NOT(ez->expression(ezSAT::OpOr, undef_rem)));
- }
-
- if (set_init_undef) {
- RTLIL::SigSpec rem = satgen.initial_state.export_all();
- rem.remove(big_lhs);
- big_lhs.append(rem);
- big_rhs.append(RTLIL::SigSpec(RTLIL::State::Sx, rem.size()));
- }
-
- if (set_init_zero) {
- RTLIL::SigSpec rem = satgen.initial_state.export_all();
- rem.remove(big_lhs);
- big_lhs.append(rem);
- big_rhs.append(RTLIL::SigSpec(RTLIL::State::S0, rem.size()));
- }
-
- if (big_lhs.size() == 0) {
- log("No constraints for initial state found.\n\n");
- return;
- }
-
- log("Final constraint equation: %s = %s\n\n", log_signal(big_lhs), log_signal(big_rhs));
- check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
- ez->assume(satgen.signals_eq(big_lhs, big_rhs, 1));
- }
-
- void setup(int timestep = -1)
+ void setup(int timestep = -1, bool initstate = false)
{
if (timestep > 0)
log ("\nSetting up time step %d:\n", timestep);
else
log ("\nSetting up SAT problem:\n");
+ if (initstate)
+ satgen.setInitState(timestep);
+
if (timestep > max_timestep)
max_timestep = timestep;
@@ -341,6 +251,97 @@ struct SatHelper
log("Import constraint from assume cell: %s when %s.\n", log_signal(assumes_a[i]), log_signal(assumes_en[i]));
ez->assume(satgen.importAssumes(timestep));
}
+
+ if (initstate)
+ {
+ RTLIL::SigSpec big_lhs, big_rhs;
+
+ for (auto &it : module->wires_)
+ {
+ if (it.second->attributes.count("\\init") == 0)
+ continue;
+
+ RTLIL::SigSpec lhs = sigmap(it.second);
+ RTLIL::SigSpec rhs = it.second->attributes.at("\\init");
+ log_assert(lhs.size() == rhs.size());
+
+ RTLIL::SigSpec removed_bits;
+ for (int i = 0; i < lhs.size(); i++) {
+ RTLIL::SigSpec bit = lhs.extract(i, 1);
+ if (!satgen.initial_state.check_all(bit)) {
+ removed_bits.append(bit);
+ lhs.remove(i, 1);
+ rhs.remove(i, 1);
+ i--;
+ }
+ }
+
+ if (removed_bits.size())
+ log_warning("ignoring initial value on non-register: %s\n", log_signal(removed_bits));
+
+ if (lhs.size()) {
+ log("Import set-constraint from init attribute: %s = %s\n", log_signal(lhs), log_signal(rhs));
+ big_lhs.remove2(lhs, &big_rhs);
+ big_lhs.append(lhs);
+ big_rhs.append(rhs);
+ }
+ }
+
+ for (auto &s : sets_init)
+ {
+ RTLIL::SigSpec lhs, rhs;
+
+ if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first))
+ log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str());
+ if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second))
+ log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str());
+ show_signal_pool.add(sigmap(lhs));
+ show_signal_pool.add(sigmap(rhs));
+
+ if (lhs.size() != rhs.size())
+ log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
+ s.first.c_str(), log_signal(lhs), lhs.size(), s.second.c_str(), log_signal(rhs), rhs.size());
+
+ log("Import init set-constraint: %s = %s\n", log_signal(lhs), log_signal(rhs));
+ big_lhs.remove2(lhs, &big_rhs);
+ big_lhs.append(lhs);
+ big_rhs.append(rhs);
+ }
+
+ if (!satgen.initial_state.check_all(big_lhs)) {
+ RTLIL::SigSpec rem = satgen.initial_state.remove(big_lhs);
+ log_cmd_error("Found -set-init bits that are not part of the initial_state: %s\n", log_signal(rem));
+ }
+
+ if (set_init_def) {
+ RTLIL::SigSpec rem = satgen.initial_state.export_all();
+ std::vector<int> undef_rem = satgen.importUndefSigSpec(rem, 1);
+ ez->assume(ez->NOT(ez->expression(ezSAT::OpOr, undef_rem)));
+ }
+
+ if (set_init_undef) {
+ RTLIL::SigSpec rem = satgen.initial_state.export_all();
+ rem.remove(big_lhs);
+ big_lhs.append(rem);
+ big_rhs.append(RTLIL::SigSpec(RTLIL::State::Sx, rem.size()));
+ }
+
+ if (set_init_zero) {
+ RTLIL::SigSpec rem = satgen.initial_state.export_all();
+ rem.remove(big_lhs);
+ big_lhs.append(rem);
+ big_rhs.append(RTLIL::SigSpec(RTLIL::State::S0, rem.size()));
+ }
+
+ if (big_lhs.size() == 0) {
+ log("No constraints for initial state found.\n\n");
+ return;
+ }
+
+ log("Final init constraint equation: %s = %s\n", log_signal(big_lhs), log_signal(big_rhs));
+ check_undef_enabled(big_lhs), check_undef_enabled(big_rhs);
+ ez->assume(satgen.signals_eq(big_lhs, big_rhs, timestep));
+ }
}
int setup_proof(int timestep = -1)
@@ -630,11 +631,11 @@ struct SatHelper
"---------------------------------------------------------------------------------------------------";
if (last_timestep == -2) {
log(max_timestep > 0 ? " Time " : " ");
- log("%-*s %10s %10s %*s\n", maxModelName+10, "Signal Name", "Dec", "Hex", maxModelWidth+5, "Bin");
+ log("%-*s %11s %9s %*s\n", maxModelName+5, "Signal Name", "Dec", "Hex", maxModelWidth+3, "Bin");
}
log(max_timestep > 0 ? " ---- " : " ");
- log("%*.*s %10.10s %10.10s %*.*s\n", maxModelName+10, maxModelName+10,
- hline, hline, hline, maxModelWidth+5, maxModelWidth+5, hline);
+ log("%*.*s %11.11s %9.9s %*.*s\n", maxModelName+5, maxModelName+5,
+ hline, hline, hline, maxModelWidth+3, maxModelWidth+3, hline);
last_timestep = info.timestep;
}
@@ -647,9 +648,9 @@ struct SatHelper
log(" ");
if (info.width <= 32 && !found_undef)
- log("%-*s %10d %10x %*s\n", maxModelName+10, info.description.c_str(), value.as_int(), value.as_int(), maxModelWidth+5, value.as_string().c_str());
+ log("%-*s %11d %9x %*s\n", maxModelName+5, info.description.c_str(), value.as_int(), value.as_int(), maxModelWidth+3, value.as_string().c_str());
else
- log("%-*s %10s %10s %*s\n", maxModelName+10, info.description.c_str(), "--", "--", maxModelWidth+5, value.as_string().c_str());
+ log("%-*s %11s %9s %*s\n", maxModelName+5, info.description.c_str(), "--", "--", maxModelWidth+3, value.as_string().c_str());
}
if (last_timestep == -2)
@@ -1073,7 +1074,7 @@ struct SatPass : public Pass {
int tempinduct_skip = 0, stepsize = 1;
std::string vcd_file_name, json_file_name, cnf_file_name;
- log_header("Executing SAT pass (solving SAT problems in the circuit).\n");
+ log_header(design, "Executing SAT pass (solving SAT problems in the circuit).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
@@ -1377,7 +1378,6 @@ struct SatPass : public Pass {
SatHelper basecase(design, module, enable_undef);
SatHelper inductstep(design, module, enable_undef);
- bool basecase_setup_init = true;
basecase.sets = sets;
basecase.set_assumes = set_assumes;
@@ -1403,7 +1403,7 @@ struct SatPass : public Pass {
for (int timestep = 1; timestep <= seq_len; timestep++)
if (!tempinduct_inductonly)
- basecase.setup(timestep);
+ basecase.setup(timestep, timestep == 1);
inductstep.sets = sets;
inductstep.set_assumes = set_assumes;
@@ -1436,15 +1436,10 @@ struct SatPass : public Pass {
if (!tempinduct_inductonly)
{
- basecase.setup(seq_len + inductlen);
+ basecase.setup(seq_len + inductlen, seq_len + inductlen == 1);
int property = basecase.setup_proof(seq_len + inductlen);
basecase.generate_model();
- if (basecase_setup_init) {
- basecase.setup_init();
- basecase_setup_init = false;
- }
-
if (inductlen > 1)
basecase.force_unique_state(seq_len + 1, seq_len + inductlen);
@@ -1452,6 +1447,7 @@ struct SatPass : public Pass {
{
log("\n[base case %d] Solving problem with %d variables and %d clauses..\n",
inductlen, basecase.ez->numCnfVariables(), basecase.ez->numCnfClauses());
+ log_flush();
if (basecase.solve(basecase.ez->NOT(property))) {
log("SAT temporal induction proof finished - model found for base case: FAIL!\n");
@@ -1522,6 +1518,7 @@ struct SatPass : public Pass {
log("\n[induction step %d] Solving problem with %d variables and %d clauses..\n",
inductlen, inductstep.ez->numCnfVariables(), inductstep.ez->numCnfClauses());
+ log_flush();
if (!inductstep.solve(inductstep.ez->NOT(property))) {
if (inductstep.gotTimeout)
@@ -1599,14 +1596,13 @@ struct SatPass : public Pass {
} else {
std::vector<int> prove_bits;
for (int timestep = 1; timestep <= seq_len; timestep++) {
- sathelper.setup(timestep);
+ sathelper.setup(timestep, timestep == 1);
if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
if (timestep > prove_skip)
prove_bits.push_back(sathelper.setup_proof(timestep));
}
if (sathelper.prove.size() || sathelper.prove_x.size() || sathelper.prove_asserts)
sathelper.ez->assume(sathelper.ez->NOT(sathelper.ez->expression(ezSAT::OpAnd, prove_bits)));
- sathelper.setup_init();
}
sathelper.generate_model();
@@ -1628,6 +1624,7 @@ struct SatPass : public Pass {
rerun_solver:
log("\nSolving problem with %d variables and %d clauses..\n",
sathelper.ez->numCnfVariables(), sathelper.ez->numCnfClauses());
+ log_flush();
if (sathelper.solve())
{
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 8112516c..b5024fa9 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -7,6 +7,9 @@ OBJS += passes/techmap/libparse.o
ifeq ($(ENABLE_ABC),1)
OBJS += passes/techmap/abc.o
+ifneq ($(ABCEXTERNAL),)
+passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
+endif
endif
ifneq ($(SMALL),1)
@@ -23,6 +26,11 @@ OBJS += passes/techmap/tribuf.o
OBJS += passes/techmap/lut2mux.o
OBJS += passes/techmap/nlutmap.o
OBJS += passes/techmap/dffsr2dff.o
+OBJS += passes/techmap/shregmap.o
+OBJS += passes/techmap/deminout.o
+OBJS += passes/techmap/insbuf.o
+OBJS += passes/techmap/attrmvcp.o
+OBJS += passes/techmap/attrmap.o
endif
GENFILES += passes/techmap/techmap.inc
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 7da26602..cc79296c 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -29,15 +29,17 @@
// Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025
// http://en.wikipedia.org/wiki/Topological_sorting
-#define ABC_COMMAND_LIB "strash; scorr; ifraig; retime {D}; strash; dch -f; map {D}"
-#define ABC_COMMAND_CTR "strash; scorr; ifraig; retime {D}; strash; dch -f; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
-#define ABC_COMMAND_LUT "strash; scorr; ifraig; retime; strash; dch -f; if"
-#define ABC_COMMAND_DFL "strash; scorr; ifraig; retime; strash; dch -f; map"
-
-#define ABC_FAST_COMMAND_LIB "retime {D}; map {D}"
-#define ABC_FAST_COMMAND_CTR "retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
-#define ABC_FAST_COMMAND_LUT "retime; if"
-#define ABC_FAST_COMMAND_DFL "retime; map"
+#define ABC_COMMAND_LIB "strash; dc2; scorr; ifraig; retime -o {D}; strash; dch -f; map {D}"
+#define ABC_COMMAND_CTR "strash; dc2; scorr; ifraig; retime -o {D}; strash; dch -f; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
+#define ABC_COMMAND_LUT "strash; dc2; scorr; ifraig; retime -o; strash; dch -f; if; mfs"
+#define ABC_COMMAND_SOP "strash; dc2; scorr; ifraig; retime -o; strash; dch -f; cover {I} {P}"
+#define ABC_COMMAND_DFL "strash; dc2; scorr; ifraig; retime -o; strash; dch -f; map"
+
+#define ABC_FAST_COMMAND_LIB "retime -o {D}; map {D}"
+#define ABC_FAST_COMMAND_CTR "retime -o {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
+#define ABC_FAST_COMMAND_LUT "retime -o; if"
+#define ABC_FAST_COMMAND_SOP "retime -o; cover -I {I} -P {P}"
+#define ABC_FAST_COMMAND_DFL "retime -o; map"
#include "kernel/register.h"
#include "kernel/sigtools.h"
@@ -593,7 +595,8 @@ struct abc_output_filter
void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
- bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir)
+ bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, bool fast_mode,
+ const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode)
{
module = current_module;
map_autoidx = autoidx++;
@@ -616,7 +619,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
tempdir_name = make_temp_dir(tempdir_name);
- log_header("Extracting gate netlist of module `%s' to `%s/input.blif'..\n",
+ log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n",
module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str());
std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str());
@@ -642,16 +645,30 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
abc_script += script_file[i];
} else
abc_script += stringf("source %s", script_file.c_str());
- } else if (!lut_costs.empty())
+ } else if (!lut_costs.empty()) {
+ bool all_luts_cost_same = true;
+ for (int this_cost : lut_costs)
+ if (this_cost != lut_costs.front())
+ all_luts_cost_same = false;
abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
- else if (!liberty_file.empty())
+ if (all_luts_cost_same && !fast_mode)
+ abc_script += "; lutpack";
+ } else if (!liberty_file.empty())
abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
+ else if (sop_mode)
+ abc_script += fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP;
else
abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
+ for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
+ abc_script = abc_script.substr(0, pos) + sop_inputs + abc_script.substr(pos+3);
+
+ for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
+ abc_script = abc_script.substr(0, pos) + sop_products + abc_script.substr(pos+3);
+
abc_script += stringf("; write_blif %s/output.blif", tempdir_name.c_str());
abc_script = add_echos_to_abc_cmd(abc_script);
@@ -828,7 +845,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (count_output > 0)
{
- log_header("Executing ABC.\n");
+ log_header(design, "Executing ABC.\n");
buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
f = fopen(buffer.c_str(), "wt");
@@ -892,13 +909,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (ifs.fail())
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
- bool builtin_lib = liberty_file.empty() && script_file.empty() && lut_costs.empty();
+ bool builtin_lib = liberty_file.empty();
RTLIL::Design *mapped_design = new RTLIL::Design;
- parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_");
+ parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
ifs.close();
- log_header("Re-integrating ABC results.\n");
+ log_header(design, "Re-integrating ABC results.\n");
RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"];
if (mapped_mod == NULL)
log_error("ABC output file does not contain a module `netlist'.\n");
@@ -910,10 +927,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
}
std::map<std::string, int> cell_stats;
- if (builtin_lib)
+ for (auto c : mapped_mod->cells())
{
- for (auto &it : mapped_mod->cells_) {
- RTLIL::Cell *c = it.second;
+ if (builtin_lib)
+ {
cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "\\ZERO" || c->type == "\\ONE") {
RTLIL::SigSig conn;
@@ -1052,60 +1069,57 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
design->select(module, cell);
continue;
}
- log_abort();
}
- }
- else
- {
- for (auto &it : mapped_mod->cells_)
- {
- RTLIL::Cell *c = it.second;
- cell_stats[RTLIL::unescape_id(c->type)]++;
- if (c->type == "\\_const0_" || c->type == "\\_const1_") {
- RTLIL::SigSig conn;
- conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
- conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1);
- module->connect(conn);
- continue;
- }
- if (c->type == "\\_dff_") {
- log_assert(clk_sig.size() == 1);
- RTLIL::Cell *cell;
- if (en_sig.size() == 0) {
- cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
- } else {
- log_assert(en_sig.size() == 1);
- cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
- cell->setPort("\\E", en_sig);
- }
- if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
- cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
- cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
- cell->setPort("\\C", clk_sig);
- design->select(module, cell);
- continue;
- }
- if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
- SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
- SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
- module->connect(my_y, my_a);
- continue;
+
+ cell_stats[RTLIL::unescape_id(c->type)]++;
+
+ if (c->type == "\\_const0_" || c->type == "\\_const1_") {
+ RTLIL::SigSig conn;
+ conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
+ conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1);
+ module->connect(conn);
+ continue;
+ }
+
+ if (c->type == "\\_dff_") {
+ log_assert(clk_sig.size() == 1);
+ RTLIL::Cell *cell;
+ if (en_sig.size() == 0) {
+ cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
+ } else {
+ log_assert(en_sig.size() == 1);
+ cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
+ cell->setPort("\\E", en_sig);
}
- RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
- cell->parameters = c->parameters;
- for (auto &conn : c->connections()) {
- RTLIL::SigSpec newsig;
- for (auto &c : conn.second.chunks()) {
- if (c.width == 0)
- continue;
- log_assert(c.width == 1);
- newsig.append(module->wires_[remap_name(c.wire->name)]);
- }
- cell->setPort(conn.first, newsig);
- }
+ cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
+ cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
+ cell->setPort("\\C", clk_sig);
design->select(module, cell);
+ continue;
+ }
+
+ if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
+ SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
+ SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
+ module->connect(my_y, my_a);
+ continue;
+ }
+
+ RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
+ if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
+ cell->parameters = c->parameters;
+ for (auto &conn : c->connections()) {
+ RTLIL::SigSpec newsig;
+ for (auto &c : conn.second.chunks()) {
+ if (c.width == 0)
+ continue;
+ log_assert(c.width == 1);
+ newsig.append(module->wires_[remap_name(c.wire->name)]);
+ }
+ cell->setPort(conn.first, newsig);
}
+ design->select(module, cell);
}
for (auto conn : mapped_mod->connections()) {
@@ -1167,7 +1181,11 @@ struct AbcPass : public Pass {
log("library to a target architecture.\n");
log("\n");
log(" -exe <command>\n");
- log(" use the specified command name instead of \"yosys-abc\" to execute ABC.\n");
+#ifdef ABCEXTERNAL
+ log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
+#else
+ log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
log(" -script <file>\n");
@@ -1186,9 +1204,15 @@ struct AbcPass : public Pass {
log(" for -liberty with -constr:\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_CTR).c_str());
log("\n");
- log(" for -lut:\n");
+ log(" for -lut/-luts (only one LUT size):\n");
+ log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT "; lutpack").c_str());
+ log("\n");
+ log(" for -lut/-luts (different LUT sizes):\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str());
log("\n");
+ log(" for -sop:\n");
+ log("%s\n", fold_abc_cmd(ABC_COMMAND_SOP).c_str());
+ log("\n");
log(" otherwise:\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_DFL).c_str());
log("\n");
@@ -1202,9 +1226,12 @@ struct AbcPass : public Pass {
log(" for -liberty with -constr:\n");
log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_CTR).c_str());
log("\n");
- log(" for -lut:\n");
+ log(" for -lut/-luts:\n");
log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str());
log("\n");
+ log(" for -sop:\n");
+ log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_SOP).c_str());
+ log("\n");
log(" otherwise:\n");
log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_DFL).c_str());
log("\n");
@@ -1227,6 +1254,14 @@ struct AbcPass : public Pass {
log(" set delay target. the string {D} in the default scripts above is\n");
log(" replaced by this option when used, and an empty string otherwise.\n");
log("\n");
+ log(" -I <num>\n");
+ log(" maximum number of SOP inputs.\n");
+ log(" (replaces {I} in the default scripts above)\n");
+ log("\n");
+ log(" -P <num>\n");
+ log(" maximum number of SOP products.\n");
+ log(" (replaces {P} in the default scripts above)\n");
+ log("\n");
log(" -lut <width>\n");
log(" generate netlist using luts of (max) the specified width.\n");
log("\n");
@@ -1240,6 +1275,9 @@ struct AbcPass : public Pass {
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
log(" 2, 3, .. inputs.\n");
log("\n");
+ log(" -sop\n");
+ log(" map to sum-of-product cells and inverters\n");
+ log("\n");
// log(" -mux4, -mux8, -mux16\n");
// log(" try to extract 4-input, 8-input, and/or 16-input muxes\n");
// log(" (ignored when used with -liberty or -lut)\n");
@@ -1286,13 +1324,18 @@ struct AbcPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing ABC pass (technology mapping using ABC).\n");
+ log_header(design, "Executing ABC pass (technology mapping using ABC).\n");
log_push();
+#ifdef ABCEXTERNAL
+ std::string exe_file = ABCEXTERNAL;
+#else
std::string exe_file = proc_self_dirname() + "yosys-abc";
- std::string script_file, liberty_file, constr_file, clk_str, delay_target;
+#endif
+ std::string script_file, liberty_file, constr_file, clk_str;
+ std::string delay_target, sop_inputs, sop_products;
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
- bool show_tempdir = false;
+ bool show_tempdir = false, sop_mode = false;
vector<int> lut_costs;
markgroups = false;
@@ -1302,9 +1345,11 @@ struct AbcPass : public Pass {
enabled_gates.clear();
#ifdef _WIN32
+#ifndef ABCEXTERNAL
if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
exe_file = proc_self_dirname() + "..\\yosys-abc";
#endif
+#endif
size_t argidx;
char pwd [PATH_MAX];
@@ -1340,6 +1385,14 @@ struct AbcPass : public Pass {
delay_target = "-D " + args[++argidx];
continue;
}
+ if (arg == "-I" && argidx+1 < args.size()) {
+ sop_inputs = "-I " + args[++argidx];
+ continue;
+ }
+ if (arg == "-P" && argidx+1 < args.size()) {
+ sop_products = "-P " + args[++argidx];
+ continue;
+ }
if (arg == "-lut" && argidx+1 < args.size()) {
string arg = args[++argidx];
size_t pos = arg.find_first_of(':');
@@ -1374,6 +1427,10 @@ struct AbcPass : public Pass {
}
continue;
}
+ if (arg == "-sop") {
+ sop_mode = true;
+ continue;
+ }
if (arg == "-mux4") {
map_mux4 = true;
continue;
@@ -1447,7 +1504,8 @@ struct AbcPass : public Pass {
if (mod->processes.size() > 0)
log("Skipping module %s as it contains processes.\n", log_id(mod));
else if (!dff_mode || !clk_str.empty())
- abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir);
+ abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
+ delay_target, sop_inputs, sop_products, fast_mode, mod->selected_cells(), show_tempdir, sop_mode);
else
{
assign_map.set(mod);
@@ -1580,7 +1638,7 @@ struct AbcPass : public Pass {
assigned_cells_reverse[cell] = key;
}
- log_header("Summary of detected clock domains:\n");
+ log_header(design, "Summary of detected clock domains:\n");
for (auto &it : assigned_cells)
log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
@@ -1591,8 +1649,8 @@ struct AbcPass : public Pass {
clk_sig = assign_map(std::get<1>(it.first));
en_polarity = std::get<2>(it.first);
en_sig = assign_map(std::get<3>(it.first));
- abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs,
- !clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir);
+ abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
+ keepff, delay_target, sop_inputs, sop_products, fast_mode, it.second, show_tempdir, sop_mode);
assign_map.set(mod);
}
}
diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc
index db1c731e..b9ac7ade 100644
--- a/passes/techmap/aigmap.cc
+++ b/passes/techmap/aigmap.cc
@@ -41,7 +41,7 @@ struct AigmapPass : public Pass {
{
bool nand_mode = false;
- log_header("Executing AIGMAP pass (map logic to AIG).\n");
+ log_header(design, "Executing AIGMAP pass (map logic to AIG).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index 3c7ff4b9..9f6dd02d 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -544,7 +544,7 @@ struct AlumaccPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing ALUMACC pass (create $alu and $macc cells).\n");
+ log_header(design, "Executing ALUMACC pass (create $alu and $macc cells).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc
new file mode 100644
index 00000000..f715b63e
--- /dev/null
+++ b/passes/techmap/attrmap.cc
@@ -0,0 +1,250 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+Const make_value(string &value)
+{
+ if (GetSize(value) >= 2 && value.front() == '"' && value.back() == '"')
+ return Const(value.substr(1, GetSize(value)-2));
+
+ SigSpec sig;
+ SigSpec::parse(sig, nullptr, value);
+ return sig.as_const();
+}
+
+bool match_name(string &name, IdString &id, bool ignore_case=false)
+{
+ string str1 = RTLIL::escape_id(name);
+ string str2 = id.str();
+
+ if (ignore_case)
+ return !strcasecmp(str1.c_str(), str2.c_str());
+
+ return str1 == str2;
+}
+
+bool match_value(string &value, Const &val, bool ignore_case=false)
+{
+ if (ignore_case && ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) && GetSize(value) && value.front() == '"' && value.back() == '"') {
+ string str1 = value.substr(1, GetSize(value)-2);
+ string str2 = val.decode_string();
+ return !strcasecmp(str1.c_str(), str2.c_str());
+ }
+
+ return make_value(value) == val;
+}
+
+struct AttrmapAction {
+ virtual ~AttrmapAction() { }
+ virtual bool apply(IdString &id, Const &val) = 0;
+};
+
+struct AttrmapTocase : AttrmapAction {
+ string name;
+ virtual bool apply(IdString &id, Const&) {
+ if (match_name(name, id, true))
+ id = RTLIL::escape_id(name);
+ return true;
+ }
+};
+
+struct AttrmapRename : AttrmapAction {
+ string old_name, new_name;
+ virtual bool apply(IdString &id, Const&) {
+ if (match_name(old_name, id))
+ id = RTLIL::escape_id(new_name);
+ return true;
+ }
+};
+
+struct AttrmapMap : AttrmapAction {
+ bool imap;
+ string old_name, new_name;
+ string old_value, new_value;
+ virtual bool apply(IdString &id, Const &val) {
+ if (match_name(old_name, id) && match_value(old_value, val, true)) {
+ id = RTLIL::escape_id(new_name);
+ val = make_value(new_value);
+ }
+ return true;
+ }
+};
+
+struct AttrmapRemove : AttrmapAction {
+ string name, value;
+ virtual bool apply(IdString &id, Const &val) {
+ return !(match_name(name, id) && match_value(value, val));
+ }
+};
+
+void attrmap_apply(string objname, vector<std::unique_ptr<AttrmapAction>> &actions, dict<RTLIL::IdString, RTLIL::Const> &attributes)
+{
+ dict<RTLIL::IdString, RTLIL::Const> new_attributes;
+
+ for (auto attr : attributes)
+ {
+ auto new_attr = attr;
+ for (auto &action : actions)
+ if (!action->apply(new_attr.first, new_attr.second))
+ goto delete_this_attr;
+
+ if (new_attr != attr)
+ log("Changed attribute on %s: %s=%s -> %s=%s\n", objname.c_str(),
+ log_id(attr.first), log_const(attr.second), log_id(new_attr.first), log_const(new_attr.second));
+
+ new_attributes[new_attr.first] = new_attr.second;
+
+ if (0)
+ delete_this_attr:
+ log("Removed attribute on %s: %s=%s\n", objname.c_str(), log_id(attr.first), log_const(attr.second));
+ }
+
+ attributes.swap(new_attributes);
+}
+
+struct AttrmapPass : public Pass {
+ AttrmapPass() : Pass("attrmap", "renaming attributes") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" attrmap [options] [selection]\n");
+ log("\n");
+ log("This command renames attributes and/or mapps key/value pairs to\n");
+ log("other key/value pairs.\n");
+ log("\n");
+ log(" -tocase <name>\n");
+ log(" Match attribute names case-insensitively and set it to the specified\n");
+ log(" name.\n");
+ log("\n");
+ log(" -rename <old_name> <new_name>\n");
+ log(" Rename attributes as specified\n");
+ log("\n");
+ log(" -map <old_name>=<old_value> <new_name>=<new_value>\n");
+ log(" Map key/value pairs as indicated.\n");
+ log("\n");
+ log(" -imap <old_name>=<old_value> <new_name>=<new_value>\n");
+ log(" Like -map, but use case-insensitive match for <old_value> when\n");
+ log(" it is a string value.\n");
+ log("\n");
+ log(" -remove <name>=<value>\n");
+ log(" Remove attributes matching this pattern.\n");
+ log("\n");
+ log(" -modattr\n");
+ log(" Operate on module attributes instead of attributes on wires and cells.\n");
+ log("\n");
+ log("For example, mapping Xilinx-style \"keep\" attributes to Yosys-style:\n");
+ log("\n");
+ log(" attrmap -tocase keep -imap keep=\"true\" keep=1 \\\n");
+ log(" -imap keep=\"false\" keep=0 -remove keep=0\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n");
+
+ bool modattr_mode = false;
+ vector<std::unique_ptr<AttrmapAction>> actions;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ std::string arg = args[argidx];
+ if (arg == "-tocase" && argidx+1 < args.size()) {
+ auto action = new AttrmapTocase;
+ action->name = args[++argidx];
+ actions.push_back(std::unique_ptr<AttrmapAction>(action));
+ continue;
+ }
+ if (arg == "-rename" && argidx+2 < args.size()) {
+ auto action = new AttrmapRename;
+ action->old_name = args[++argidx];
+ action->new_name = args[++argidx];
+ actions.push_back(std::unique_ptr<AttrmapAction>(action));
+ continue;
+ }
+ if ((arg == "-map" || arg == "-imap") && argidx+2 < args.size()) {
+ string arg1 = args[++argidx];
+ string arg2 = args[++argidx];
+ string val1, val2;
+ size_t p = arg1.find("=");
+ if (p != string::npos) {
+ val1 = arg1.substr(p+1);
+ arg1 = arg1.substr(0, p);
+ }
+ p = arg2.find("=");
+ if (p != string::npos) {
+ val2 = arg2.substr(p+1);
+ arg2 = arg2.substr(0, p);
+ }
+ auto action = new AttrmapMap;
+ action->imap = (arg == "-map");
+ action->old_name = arg1;
+ action->new_name = arg2;
+ action->old_value = val1;
+ action->new_value = val2;
+ actions.push_back(std::unique_ptr<AttrmapAction>(action));
+ continue;
+ }
+ if (arg == "-remove" && argidx+1 < args.size()) {
+ string arg1 = args[++argidx], val1;
+ size_t p = arg1.find("=");
+ if (p != string::npos) {
+ val1 = arg1.substr(p+1);
+ arg1 = arg1.substr(0, p);
+ }
+ auto action = new AttrmapRemove;
+ action->name = arg1;
+ action->value = val1;
+ actions.push_back(std::unique_ptr<AttrmapAction>(action));
+ continue;
+ }
+ if (arg == "-modattr") {
+ modattr_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (modattr_mode)
+ {
+ for (auto module : design->selected_whole_modules())
+ attrmap_apply(stringf("%s", log_id(module)), actions, module->attributes);
+ }
+ else
+ {
+ for (auto module : design->selected_modules())
+ {
+ for (auto wire : module->selected_wires())
+ attrmap_apply(stringf("%s.%s", log_id(module), log_id(wire)), actions, wire->attributes);
+
+ for (auto cell : module->selected_cells())
+ attrmap_apply(stringf("%s.%s", log_id(module), log_id(cell)), actions, cell->attributes);
+ }
+ }
+ }
+} AttrmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc
new file mode 100644
index 00000000..50eaf61d
--- /dev/null
+++ b/passes/techmap/attrmvcp.cc
@@ -0,0 +1,139 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct AttrmvcpPass : public Pass {
+ AttrmvcpPass() : Pass("attrmvcp", "move or copy attributes from wires to driving cells") { }
+ virtual void help()
+ {
+ log("\n");
+ log(" attrmvcp [options] [selection]\n");
+ log("\n");
+ log("Move or copy attributes on wires to the cells driving them.\n");
+ log("\n");
+ log(" -copy\n");
+ log(" By default, attributes are moved. This will only add\n");
+ log(" the attribute to the cell, without removing it from\n");
+ log(" the wire.\n");
+ log("\n");
+ log(" -purge\n");
+ log(" If no selected cell consumes the attribute, then it is\n");
+ log(" left on the wire by default. This option will cause the\n");
+ log(" attribute to be removed from the wire, even if no selected\n");
+ log(" cell takes it.\n");
+ log("\n");
+ log(" -driven\n");
+ log(" By default, attriburtes are moved to the cell driving the\n");
+ log(" wire. With this option set it will be moved to the cell\n");
+ log(" driven by the wire instead.\n");
+ log("\n");
+ log(" -attr <attrname>\n");
+ log(" Move or copy this attribute. This option can be used\n");
+ log(" multiple times.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing ATTRMVCP pass (move or copy attributes).\n");
+
+ bool copy_mode = false;
+ bool driven_mode = false;
+ bool purge_mode = false;
+ pool<IdString> attrnames;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ std::string arg = args[argidx];
+ if (arg == "-copy") {
+ copy_mode = true;
+ continue;
+ }
+ if (arg == "-driven") {
+ driven_mode = true;
+ continue;
+ }
+ if (arg == "-purge") {
+ purge_mode = true;
+ continue;
+ }
+ if (arg == "-attr" && argidx+1 < args.size()) {
+ attrnames.insert(RTLIL::escape_id(args[++argidx]));
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ dict<SigBit, pool<Cell*>> net2cells;
+ SigMap sigmap(module);
+
+ for (auto cell : module->selected_cells())
+ for (auto &conn : cell->connections())
+ if (driven_mode) {
+ if (cell->input(conn.first))
+ for (auto bit : sigmap(conn.second))
+ net2cells[bit].insert(cell);
+ } else {
+ if (cell->output(conn.first))
+ for (auto bit : sigmap(conn.second))
+ net2cells[bit].insert(cell);
+ }
+
+ for (auto wire : module->selected_wires())
+ {
+ dict<IdString, Const> new_attributes;
+
+ for (auto attr : wire->attributes)
+ {
+ bool did_something = false;
+
+ if (!attrnames.count(attr.first)) {
+ new_attributes[attr.first] = attr.second;
+ continue;
+ }
+
+ for (auto bit : sigmap(wire))
+ if (net2cells.count(bit))
+ for (auto cell : net2cells.at(bit)) {
+ log("Moving attribute %s=%s from %s.%s to %s.%s.\n", log_id(attr.first), log_const(attr.second),
+ log_id(module), log_id(wire), log_id(module), log_id(cell));
+ cell->attributes[attr.first] = attr.second;
+ did_something = true;
+ }
+
+ if (!purge_mode && !did_something)
+ new_attributes[attr.first] = attr.second;
+ }
+
+ if (!copy_mode)
+ wire->attributes.swap(new_attributes);
+ }
+ }
+ }
+} AttrmvcpPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
new file mode 100644
index 00000000..ed4e4576
--- /dev/null
+++ b/passes/techmap/deminout.cc
@@ -0,0 +1,116 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct DeminoutPass : public Pass {
+ DeminoutPass() : Pass("deminout", "demote inout ports to input or output") { }
+ virtual void help()
+ {
+ log("\n");
+ log(" deminout [options] [selection]\n");
+ log("\n");
+ log("\"Demote\" inout ports to input or output ports, if possible.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing DEMINOUT pass (demote inout ports to input or output).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-bits") {
+ // flag_bits = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ bool keep_running = true;
+
+ while (keep_running)
+ {
+ keep_running = false;
+
+ for (auto module : design->selected_modules())
+ {
+ SigMap sigmap(module);
+ pool<SigBit> bits_written, bits_used, bits_inout;
+ dict<SigBit, int> bits_numports;
+
+ for (auto wire : module->wires())
+ if (wire->port_id)
+ for (auto bit : sigmap(wire))
+ bits_numports[bit]++;
+
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections())
+ {
+ bool cellport_out = cell->output(conn.first) || !cell->known();
+ bool cellport_in = cell->input(conn.first) || !cell->known();
+
+ if (cellport_out && cellport_in)
+ for (auto bit : sigmap(conn.second))
+ bits_inout.insert(bit);
+
+ if (cellport_out)
+ for (auto bit : sigmap(conn.second))
+ bits_written.insert(bit);
+
+ if (cellport_in)
+ for (auto bit : sigmap(conn.second))
+ bits_used.insert(bit);
+ }
+
+ for (auto wire : module->selected_wires())
+ if (wire->port_input && wire->port_output)
+ {
+ bool new_input = false;
+ bool new_output = false;
+
+ for (auto bit : sigmap(wire))
+ {
+ if (bits_numports[bit] > 1 || bits_inout.count(bit))
+ new_input = true, new_output = true;
+
+ if (bits_written.count(bit))
+ new_output = true;
+ else if (bits_used.count(bit))
+ new_input = true;
+ }
+
+ if (new_input != new_output) {
+ log("Demoting inout port %s.%s to %s.\n", log_id(module), log_id(wire), new_input ? "input" : "output");
+ wire->port_input = new_input;
+ wire->port_output = new_output;
+ keep_running = true;
+ }
+ }
+ }
+ }
+ }
+} DeminoutPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
index 51bfaade..1b8920bb 100644
--- a/passes/techmap/dff2dffe.cc
+++ b/passes/techmap/dff2dffe.cc
@@ -285,7 +285,7 @@ struct Dff2dffePass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
+ log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
bool unmap_mode = false;
dict<IdString, IdString> direct_dict;
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index e0273f43..d737b342 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -41,7 +41,7 @@ struct DffinitPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing DFFINIT pass (set INIT param on FF cells).\n");
+ log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n");
dict<IdString, dict<IdString, IdString>> ff_types;
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 4d7a1a70..c8104fb7 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -108,6 +108,7 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
LibertyAst *best_cell = NULL;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
+ bool best_cell_noninv = false;
double best_cell_area = 0;
if (ast->id != "library")
@@ -155,6 +156,7 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
int num_pins = 0;
bool found_output = false;
+ bool found_noninv_output = false;
for (auto pin : cell->children)
{
if (pin->id != "pin" || pin->args.size() != 1)
@@ -175,10 +177,14 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
value.erase(pos, 1);
if (value == ff->args[0]) {
this_cell_ports[pin->args[0]] = cell_next_pol ? 'Q' : 'q';
+ if (cell_next_pol)
+ found_noninv_output = true;
found_output = true;
} else
if (value == ff->args[1]) {
this_cell_ports[pin->args[0]] = cell_next_pol ? 'q' : 'Q';
+ if (!cell_next_pol)
+ found_noninv_output = true;
found_output = true;
}
}
@@ -187,7 +193,7 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
this_cell_ports[pin->args[0]] = 0;
}
- if (!found_output || (best_cell != NULL && num_pins > best_cell_pins))
+ if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output))))
continue;
if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area)
@@ -196,12 +202,14 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
best_cell = cell;
best_cell_pins = num_pins;
best_cell_area = area;
+ best_cell_noninv = found_noninv_output;
best_cell_ports.swap(this_cell_ports);
continue_cell_loop:;
}
if (best_cell != NULL) {
- log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.c_str());
+ log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
+ best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str());
if (prepare_mode) {
cell_mappings[cell_type].cell_name = cell_type;
cell_mappings[cell_type].ports["C"] = 'C';
@@ -221,6 +229,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
LibertyAst *best_cell = NULL;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
+ bool best_cell_noninv = false;
double best_cell_area = 0;
if (ast->id != "library")
@@ -260,6 +269,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
int num_pins = 0;
bool found_output = false;
+ bool found_noninv_output = false;
for (auto pin : cell->children)
{
if (pin->id != "pin" || pin->args.size() != 1)
@@ -280,10 +290,14 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
value.erase(pos, 1);
if (value == ff->args[0]) {
this_cell_ports[pin->args[0]] = cell_next_pol ? 'Q' : 'q';
+ if (cell_next_pol)
+ found_noninv_output = true;
found_output = true;
} else
if (value == ff->args[1]) {
this_cell_ports[pin->args[0]] = cell_next_pol ? 'q' : 'Q';
+ if (!cell_next_pol)
+ found_noninv_output = true;
found_output = true;
}
}
@@ -292,7 +306,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
this_cell_ports[pin->args[0]] = 0;
}
- if (!found_output || (best_cell != NULL && num_pins > best_cell_pins))
+ if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output))))
continue;
if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area)
@@ -301,12 +315,14 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
best_cell = cell;
best_cell_pins = num_pins;
best_cell_area = area;
+ best_cell_noninv = found_noninv_output;
best_cell_ports.swap(this_cell_ports);
continue_cell_loop:;
}
if (best_cell != NULL) {
- log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.c_str());
+ log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
+ best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str());
if (prepare_mode) {
cell_mappings[cell_type].cell_name = cell_type;
cell_mappings[cell_type].ports["C"] = 'C';
@@ -531,7 +547,7 @@ struct DfflibmapPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
+ log_header(design, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
std::string liberty_file;
bool prepare_mode = false;
diff --git a/passes/techmap/dffsr2dff.cc b/passes/techmap/dffsr2dff.cc
index 8dcbb4ed..0d4d5362 100644
--- a/passes/techmap/dffsr2dff.cc
+++ b/passes/techmap/dffsr2dff.cc
@@ -188,7 +188,7 @@ struct Dffsr2dffPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n");
+ log_header(design, "Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index fc73177c..71e29c60 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -442,7 +442,7 @@ struct ExtractPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing EXTRACT pass (map subcircuits to cells).\n");
+ log_header(design, "Executing EXTRACT pass (map subcircuits to cells).\n");
log_push();
SubCircuitSolver solver;
@@ -627,7 +627,7 @@ struct ExtractPass : public Pass {
std::map<std::string, RTLIL::Module*> needle_map, haystack_map;
std::vector<RTLIL::Module*> needle_list;
- log_header("Creating graphs for SubCircuit library.\n");
+ log_header(design, "Creating graphs for SubCircuit library.\n");
if (!mine_mode)
for (auto &mod_it : map->modules_) {
@@ -654,7 +654,7 @@ struct ExtractPass : public Pass {
if (!mine_mode)
{
std::vector<SubCircuit::Solver::Result> results;
- log_header("Running solver from SubCircuit library.\n");
+ log_header(design, "Running solver from SubCircuit library.\n");
std::sort(needle_list.begin(), needle_list.end(), compareSortNeedleList);
@@ -667,7 +667,7 @@ struct ExtractPass : public Pass {
if (results.size() > 0)
{
- log_header("Substitute SubCircuits with cells.\n");
+ log_header(design, "Substitute SubCircuits with cells.\n");
for (int i = 0; i < int(results.size()); i++) {
auto &result = results[i];
@@ -688,7 +688,7 @@ struct ExtractPass : public Pass {
{
std::vector<SubCircuit::Solver::MineResult> results;
- log_header("Running miner from SubCircuit library.\n");
+ log_header(design, "Running miner from SubCircuit library.\n");
solver.mine(results, mine_cells_min, mine_cells_max, mine_min_freq, mine_limit_mod);
map = new RTLIL::Design;
diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc
index a0bd2f9a..82cecac2 100644
--- a/passes/techmap/hilomap.cc
+++ b/passes/techmap/hilomap.cc
@@ -76,7 +76,7 @@ struct HilomapPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing HILOMAP pass (mapping to constant drivers).\n");
+ log_header(design, "Executing HILOMAP pass (mapping to constant drivers).\n");
hicell_celltype = std::string();
hicell_portname = std::string();
diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc
new file mode 100644
index 00000000..aa81468d
--- /dev/null
+++ b/passes/techmap/insbuf.cc
@@ -0,0 +1,94 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct InsbufPass : public Pass {
+ InsbufPass() : Pass("insbuf", "insert buffer cells for connected wires") { }
+ virtual void help()
+ {
+ log("\n");
+ log(" insbuf [options] [selection]\n");
+ log("\n");
+ log("Insert buffer cells into the design for directly connected wires.\n");
+ log("\n");
+ log(" -buf <celltype> <in-portname> <out-portname>\n");
+ log(" Use the given cell type instead of $_BUF_. (Notice that the next\n");
+ log(" call to \"clean\" will remove all $_BUF_ in the design.)\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing INSBUF pass (insert buffer cells for connected wires).\n");
+
+ std::string celltype = "$_BUF_", in_portname = "\\A", out_portname = "\\Y";
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ std::string arg = args[argidx];
+ if (arg == "-buf" && argidx+3 < args.size()) {
+ celltype = args[++argidx];
+ in_portname = args[++argidx];
+ out_portname = args[++argidx];
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ std::vector<RTLIL::SigSig> new_connections;
+
+ for (auto &conn : module->connections())
+ {
+ RTLIL::SigSig new_conn;
+
+ for (int i = 0; i < GetSize(conn.first); i++)
+ {
+ SigBit lhs = conn.first[i];
+ SigBit rhs = conn.second[i];
+
+ if (lhs.wire && !design->selected(module, lhs.wire)) {
+ new_conn.first.append(lhs);
+ new_conn.second.append(rhs);
+ continue;
+ }
+
+ Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype));
+ cell->setPort(RTLIL::escape_id(in_portname), rhs);
+ cell->setPort(RTLIL::escape_id(out_portname), lhs);
+ log("Added %s.%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs));
+ }
+
+ if (GetSize(new_conn.first))
+ new_connections.push_back(new_conn);
+ }
+
+ module->new_connections(new_connections);
+ }
+ }
+} InsbufPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 9dab40ca..4acbf7c0 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -17,9 +17,8 @@
*
*/
-#include "kernel/register.h"
-#include "kernel/rtlil.h"
-#include "kernel/log.h"
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -48,12 +47,23 @@ struct IopadmapPass : public Pass {
log(" Map module input ports to the given cell type with the\n");
log(" given output port name. if a 2nd portname is given, the\n");
log(" signal is passed through the pad call, using the 2nd\n");
- log(" portname as input.\n");
+ log(" portname as the port facing the module port.\n");
log("\n");
log(" -outpad <celltype> <portname>[:<portname>]\n");
log(" -inoutpad <celltype> <portname>[:<portname>]\n");
log(" Similar to -inpad, but for output and inout ports.\n");
log("\n");
+ log(" -toutpad <celltype> <portname>:<portname>[:<portname>]\n");
+ log(" Merges $_TBUF_ cells into the output pad cell. This takes precedence\n");
+ log(" over the other -outpad cell. The first portname is the enable input\n");
+ log(" of the tristate driver.\n");
+ log("\n");
+ log(" -tinoutpad <celltype> <portname>:<portname>:<portname>[:<portname>]\n");
+ log(" Merges $_TBUF_ cells into the inout pad cell. This takes precedence\n");
+ log(" over the other -inoutpad cell. The first portname is the enable input\n");
+ log(" of the tristate driver and the 2nd portname is the internal output\n");
+ log(" buffering the external signal.\n");
+ log("\n");
log(" -widthparam <param_name>\n");
log(" Use the specified parameter name to set the port width.\n");
log("\n");
@@ -65,14 +75,18 @@ struct IopadmapPass : public Pass {
log(" are wider. (the default behavior is to create word-wide\n");
log(" buffers using -widthparam to set the word size on the cell.)\n");
log("\n");
+ log("Tristate PADS (-toutpad, -tinoutpad) always operate in -bits mode.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
+ log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
std::string inpad_celltype, inpad_portname, inpad_portname2;
std::string outpad_celltype, outpad_portname, outpad_portname2;
std::string inoutpad_celltype, inoutpad_portname, inoutpad_portname2;
+ std::string toutpad_celltype, toutpad_portname, toutpad_portname2, toutpad_portname3;
+ std::string tinoutpad_celltype, tinoutpad_portname, tinoutpad_portname2, tinoutpad_portname3, tinoutpad_portname4;
std::string widthparam, nameparam;
bool flag_bits = false;
@@ -98,6 +112,21 @@ struct IopadmapPass : public Pass {
split_portname_pair(inoutpad_portname, inoutpad_portname2);
continue;
}
+ if (arg == "-toutpad" && argidx+2 < args.size()) {
+ toutpad_celltype = args[++argidx];
+ toutpad_portname = args[++argidx];
+ split_portname_pair(toutpad_portname, toutpad_portname2);
+ split_portname_pair(toutpad_portname2, toutpad_portname3);
+ continue;
+ }
+ if (arg == "-tinoutpad" && argidx+2 < args.size()) {
+ tinoutpad_celltype = args[++argidx];
+ tinoutpad_portname = args[++argidx];
+ split_portname_pair(tinoutpad_portname, tinoutpad_portname2);
+ split_portname_pair(tinoutpad_portname2, tinoutpad_portname3);
+ split_portname_pair(tinoutpad_portname3, tinoutpad_portname4);
+ continue;
+ }
if (arg == "-widthparam" && argidx+1 < args.size()) {
widthparam = args[++argidx];
continue;
@@ -116,12 +145,132 @@ struct IopadmapPass : public Pass {
for (auto module : design->selected_modules())
{
+ dict<IdString, pool<int>> skip_wires;
+
+ if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
+ {
+ SigMap sigmap(module);
+ dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
+
+ for (auto cell : module->cells())
+ if (cell->type == "$_TBUF_") {
+ SigBit bit = sigmap(cell->getPort("\\Y").as_bit());
+ tbuf_bits[bit].first = cell->name;
+ }
+
+ for (auto cell : module->cells())
+ for (auto port : cell->connections())
+ for (auto bit : sigmap(port.second))
+ if (tbuf_bits.count(bit))
+ tbuf_bits.at(bit).second.insert(cell->name);
+
+ for (auto wire : module->selected_wires())
+ {
+ if (!wire->port_output)
+ continue;
+
+ for (int i = 0; i < GetSize(wire); i++)
+ {
+ SigBit wire_bit(wire, i);
+ SigBit mapped_wire_bit = sigmap(wire_bit);
+
+ if (tbuf_bits.count(mapped_wire_bit) == 0)
+ continue;
+
+ auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit);
+ Cell *tbuf_cell = module->cell(tbuf_cache.first);
+
+ if (tbuf_cell == nullptr)
+ continue;
+
+ SigBit en_sig = tbuf_cell->getPort("\\E").as_bit();
+ SigBit data_sig = tbuf_cell->getPort("\\A").as_bit();
+
+ if (wire->port_input && !tinoutpad_celltype.empty())
+ {
+ log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, tinoutpad_celltype.c_str());
+
+ Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(tinoutpad_celltype));
+ Wire *owire = module->addWire(NEW_ID);
+
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname), en_sig);
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname2), owire);
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname3), data_sig);
+ cell->setPort(RTLIL::escape_id(tinoutpad_portname4), wire_bit);
+ cell->attributes["\\keep"] = RTLIL::Const(1);
+
+ for (auto cn : tbuf_cache.second) {
+ auto c = module->cell(cn);
+ if (c == nullptr)
+ continue;
+ for (auto port : c->connections()) {
+ SigSpec sig = port.second;
+ bool newsig = false;
+ for (auto &bit : sig)
+ if (sigmap(bit) == mapped_wire_bit) {
+ bit = owire;
+ newsig = true;
+ }
+ if (newsig)
+ c->setPort(port.first, sig);
+ }
+ }
+
+
+ module->remove(tbuf_cell);
+ skip_wires[wire->name].insert(i);
+ continue;
+ }
+
+ if (!wire->port_input && !toutpad_celltype.empty())
+ {
+ log("Mapping port %s.%s[%d] using %s.\n", log_id(module), log_id(wire), i, toutpad_celltype.c_str());
+
+ Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(toutpad_celltype));
+
+ cell->setPort(RTLIL::escape_id(toutpad_portname), en_sig);
+ cell->setPort(RTLIL::escape_id(toutpad_portname2), data_sig);
+ cell->setPort(RTLIL::escape_id(toutpad_portname3), wire_bit);
+ cell->attributes["\\keep"] = RTLIL::Const(1);
+
+ for (auto cn : tbuf_cache.second) {
+ auto c = module->cell(cn);
+ if (c == nullptr)
+ continue;
+ for (auto port : c->connections()) {
+ SigSpec sig = port.second;
+ bool newsig = false;
+ for (auto &bit : sig)
+ if (sigmap(bit) == mapped_wire_bit) {
+ bit = data_sig;
+ newsig = true;
+ }
+ if (newsig)
+ c->setPort(port.first, sig);
+ }
+ }
+
+ module->remove(tbuf_cell);
+ skip_wires[wire->name].insert(i);
+ continue;
+ }
+ }
+ }
+ }
+
for (auto wire : module->selected_wires())
{
if (!wire->port_id)
continue;
std::string celltype, portname, portname2;
+ pool<int> skip_bit_indices;
+
+ if (skip_wires.count(wire->name)) {
+ if (!flag_bits)
+ continue;
+ skip_bit_indices = skip_wires.at(wire->name);
+ }
if (wire->port_input && !wire->port_output) {
if (inpad_celltype.empty()) {
@@ -163,12 +312,21 @@ struct IopadmapPass : public Pass {
if (!portname2.empty()) {
new_wire = module->addWire(NEW_ID, wire);
module->swap_names(new_wire, wire);
+ wire->attributes.clear();
}
if (flag_bits)
{
for (int i = 0; i < wire->width; i++)
{
+ if (skip_bit_indices.count(i)) {
+ if (wire->port_output)
+ module->connect(SigSpec(new_wire, i), SigSpec(wire, i));
+ else
+ module->connect(SigSpec(wire, i), SigSpec(new_wire, i));
+ continue;
+ }
+
RTLIL::Cell *cell = module->addCell(NEW_ID, RTLIL::escape_id(celltype));
cell->setPort(RTLIL::escape_id(portname), RTLIL::SigSpec(wire, i));
if (!portname2.empty())
diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc
index fe55e499..2bb0bd8b 100644
--- a/passes/techmap/lut2mux.cc
+++ b/passes/techmap/lut2mux.cc
@@ -67,7 +67,7 @@ struct Lut2muxPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing LUT2MUX pass (mapping to constant drivers).\n");
+ log_header(design, "Executing LUT2MUX pass (convert $lut to $_MUX_).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc
index d5b8fe80..32569d07 100644
--- a/passes/techmap/maccmap.cc
+++ b/passes/techmap/maccmap.cc
@@ -379,7 +379,7 @@ struct MaccmapPass : public Pass {
{
bool unmap_mode = false;
- log_header("Executing MACCMAP pass (map $macc cells).\n");
+ log_header(design, "Executing MACCMAP pass (map $macc cells).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc
index 514c3365..1dc64958 100644
--- a/passes/techmap/muxcover.cc
+++ b/passes/techmap/muxcover.cc
@@ -581,7 +581,7 @@ struct MuxcoverPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing MUXCOVER pass (mapping to wider MUXes).\n");
+ log_header(design, "Executing MUXCOVER pass (mapping to wider MUXes).\n");
bool use_mux4 = false;
bool use_mux8 = false;
diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc
index 7ece4005..6fcdf82b 100644
--- a/passes/techmap/nlutmap.cc
+++ b/passes/techmap/nlutmap.cc
@@ -26,6 +26,7 @@ PRIVATE_NAMESPACE_BEGIN
struct NlutmapConfig
{
vector<int> luts;
+ bool assert_mode = false;
};
struct NlutmapWorker
@@ -64,7 +65,7 @@ struct NlutmapWorker
{
vector<int> available_luts = config.luts;
- while (!available_luts.empty())
+ while (GetSize(available_luts) > 1)
{
int n_luts = available_luts.back();
int lut_size = GetSize(available_luts);
@@ -84,7 +85,7 @@ struct NlutmapWorker
if (cell->type != "$lut" || mapped_cells.count(cell))
continue;
- if (GetSize(cell->getPort("\\A")) == lut_size)
+ if (GetSize(cell->getPort("\\A")) == lut_size || lut_size == 2)
candidate_ratings[cell] = 0;
for (auto &conn : cell->connections())
@@ -116,6 +117,12 @@ struct NlutmapWorker
available_luts.back() += n_luts;
}
+ if (config.assert_mode) {
+ for (auto cell : module->cells())
+ if (cell->type == "$lut" && !mapped_cells.count(cell))
+ log_error("Insufficient number of LUTs to map all logic cells!\n");
+ }
+
run_abc(0);
}
};
@@ -135,6 +142,9 @@ struct NlutmapPass : public Pass {
log(" The number of LUTs with 1, 2, 3, ... inputs that are\n");
log(" available in the target architecture.\n");
log("\n");
+ log(" -assert\n");
+ log(" Create an error if not all logic can be mapped\n");
+ log("\n");
log("Excess logic that does not fit into the specified LUTs is mapped back\n");
log("to generic logic gates ($_AND_, etc.).\n");
log("\n");
@@ -143,7 +153,7 @@ struct NlutmapPass : public Pass {
{
NlutmapConfig config;
- log_header("Executing NLUTMAP pass (mapping to constant drivers).\n");
+ log_header(design, "Executing NLUTMAP pass (mapping to constant drivers).\n");
log_push();
size_t argidx;
@@ -156,6 +166,10 @@ struct NlutmapPass : public Pass {
config.luts.push_back(atoi(token.c_str()));
continue;
}
+ if (args[argidx] == "-assert") {
+ config.assert_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc
index 3c12bfd0..c626dbcc 100644
--- a/passes/techmap/pmuxtree.cc
+++ b/passes/techmap/pmuxtree.cc
@@ -78,7 +78,7 @@ struct PmuxtreePass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing PMUXTREE pass.\n");
+ log_header(design, "Executing PMUXTREE pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc
new file mode 100644
index 00000000..6936b499
--- /dev/null
+++ b/passes/techmap/shregmap.cc
@@ -0,0 +1,584 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ShregmapTech
+{
+ virtual ~ShregmapTech() { }
+ virtual bool analyze(vector<int> &taps) = 0;
+ virtual bool fixup(Cell *cell, dict<int, SigBit> &taps) = 0;
+};
+
+struct ShregmapOptions
+{
+ int minlen, maxlen;
+ int keep_before, keep_after;
+ bool zinit, init, params, ffe;
+ dict<IdString, pair<IdString, IdString>> ffcells;
+ ShregmapTech *tech;
+
+ ShregmapOptions()
+ {
+ minlen = 2;
+ maxlen = 0;
+ keep_before = 0;
+ keep_after = 0;
+ zinit = false;
+ init = false;
+ params = false;
+ ffe = false;
+ tech = nullptr;
+ }
+};
+
+struct ShregmapTechGreenpak4 : ShregmapTech
+{
+ bool analyze(vector<int> &taps)
+ {
+ if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) {
+ taps.clear();
+ return true;
+ }
+
+ if (GetSize(taps) > 2)
+ return false;
+
+ if (taps.back() > 16) return false;
+
+ return true;
+ }
+
+ bool fixup(Cell *cell, dict<int, SigBit> &taps)
+ {
+ auto D = cell->getPort("\\D");
+ auto C = cell->getPort("\\C");
+
+ auto newcell = cell->module->addCell(NEW_ID, "\\GP_SHREG");
+ newcell->setPort("\\nRST", State::S1);
+ newcell->setPort("\\CLK", C);
+ newcell->setPort("\\IN", D);
+
+ int i = 0;
+ for (auto tap : taps) {
+ newcell->setPort(i ? "\\OUTB" : "\\OUTA", tap.second);
+ newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap.first + 1);
+ i++;
+ }
+
+ cell->setParam("\\OUTA_INVERT", 0);
+ return false;
+ }
+};
+
+struct ShregmapWorker
+{
+ Module *module;
+ SigMap sigmap;
+
+ const ShregmapOptions &opts;
+ int dff_count, shreg_count;
+
+ pool<Cell*> remove_cells;
+ pool<SigBit> remove_init;
+
+ dict<SigBit, bool> sigbit_init;
+ dict<SigBit, Cell*> sigbit_chain_next;
+ dict<SigBit, Cell*> sigbit_chain_prev;
+ pool<SigBit> sigbit_with_non_chain_users;
+ pool<Cell*> chain_start_cells;
+
+ void make_sigbit_chain_next_prev()
+ {
+ for (auto wire : module->wires())
+ {
+ if (wire->port_output || wire->get_bool_attribute("\\keep")) {
+ for (auto bit : sigmap(wire))
+ sigbit_with_non_chain_users.insert(bit);
+ }
+
+ if (wire->attributes.count("\\init")) {
+ SigSpec initsig = sigmap(wire);
+ Const initval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
+ if (initval[i] == State::S0 && !opts.zinit)
+ sigbit_init[initsig[i]] = false;
+ else if (initval[i] == State::S1)
+ sigbit_init[initsig[i]] = true;
+ }
+ }
+
+ for (auto cell : module->cells())
+ {
+ if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep"))
+ {
+ IdString d_port = opts.ffcells.at(cell->type).first;
+ IdString q_port = opts.ffcells.at(cell->type).second;
+
+ SigBit d_bit = sigmap(cell->getPort(d_port).as_bit());
+ SigBit q_bit = sigmap(cell->getPort(q_port).as_bit());
+
+ if (opts.init || sigbit_init.count(q_bit) == 0)
+ {
+ if (sigbit_chain_next.count(d_bit)) {
+ sigbit_with_non_chain_users.insert(d_bit);
+ } else
+ sigbit_chain_next[d_bit] = cell;
+
+ sigbit_chain_prev[q_bit] = cell;
+ continue;
+ }
+ }
+
+ for (auto conn : cell->connections())
+ if (cell->input(conn.first))
+ for (auto bit : sigmap(conn.second))
+ sigbit_with_non_chain_users.insert(bit);
+ }
+ }
+
+ void find_chain_start_cells()
+ {
+ for (auto it : sigbit_chain_next)
+ {
+ if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first))
+ goto start_cell;
+
+ if (sigbit_chain_prev.count(it.first) != 0)
+ {
+ Cell *c1 = sigbit_chain_prev.at(it.first);
+ Cell *c2 = it.second;
+
+ if (c1->type != c2->type)
+ goto start_cell;
+
+ if (c1->parameters != c2->parameters)
+ goto start_cell;
+
+ IdString d_port = opts.ffcells.at(c1->type).first;
+ IdString q_port = opts.ffcells.at(c1->type).second;
+
+ auto c1_conn = c1->connections();
+ auto c2_conn = c1->connections();
+
+ c1_conn.erase(d_port);
+ c1_conn.erase(q_port);
+
+ c2_conn.erase(d_port);
+ c2_conn.erase(q_port);
+
+ if (c1_conn != c2_conn)
+ goto start_cell;
+
+ continue;
+ }
+
+ start_cell:
+ chain_start_cells.insert(it.second);
+ }
+ }
+
+ vector<Cell*> create_chain(Cell *start_cell)
+ {
+ vector<Cell*> chain;
+
+ Cell *c = start_cell;
+ while (c != nullptr)
+ {
+ chain.push_back(c);
+
+ IdString q_port = opts.ffcells.at(c->type).second;
+ SigBit q_bit = sigmap(c->getPort(q_port).as_bit());
+
+ if (sigbit_chain_next.count(q_bit) == 0)
+ break;
+
+ c = sigbit_chain_next.at(q_bit);
+ if (chain_start_cells.count(c) != 0)
+ break;
+ }
+
+ return chain;
+ }
+
+ void process_chain(vector<Cell*> &chain)
+ {
+ if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after)
+ return;
+
+ int cursor = opts.keep_before;
+ while (cursor < GetSize(chain) - opts.keep_after)
+ {
+ int depth = GetSize(chain) - opts.keep_after - cursor;
+
+ if (opts.maxlen > 0)
+ depth = std::min(opts.maxlen, depth);
+
+ Cell *first_cell = chain[cursor];
+ IdString q_port = opts.ffcells.at(first_cell->type).second;
+ dict<int, SigBit> taps_dict;
+
+ if (opts.tech)
+ {
+ vector<SigBit> qbits;
+ vector<int> taps;
+
+ for (int i = 0; i < depth; i++)
+ {
+ Cell *cell = chain[cursor+i];
+ auto qbit = sigmap(cell->getPort(q_port));
+ qbits.push_back(qbit);
+
+ if (sigbit_with_non_chain_users.count(qbit))
+ taps.push_back(i);
+ }
+
+ while (depth > 0)
+ {
+ if (taps.empty() || taps.back() < depth-1)
+ taps.push_back(depth-1);
+
+ if (opts.tech->analyze(taps))
+ break;
+
+ taps.pop_back();
+ depth--;
+ }
+
+ depth = 0;
+ for (auto tap : taps) {
+ taps_dict[tap] = qbits.at(tap);
+ log_assert(depth < tap+1);
+ depth = tap+1;
+ }
+ }
+
+ if (depth < 2) {
+ cursor++;
+ continue;
+ }
+
+ Cell *last_cell = chain[cursor+depth-1];
+
+ log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n",
+ log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth);
+
+ dff_count += depth;
+ shreg_count += 1;
+
+ string shreg_cell_type_str = "$__SHREG";
+ if (opts.params) {
+ shreg_cell_type_str += "_";
+ } else {
+ if (first_cell->type[1] != '_')
+ shreg_cell_type_str += "_";
+ shreg_cell_type_str += first_cell->type.substr(1);
+ }
+
+ if (opts.init) {
+ vector<State> initval;
+ for (int i = depth-1; i >= 0; i--) {
+ SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit());
+ if (sigbit_init.count(bit) == 0)
+ initval.push_back(State::Sx);
+ else if (sigbit_init.at(bit))
+ initval.push_back(State::S1);
+ else
+ initval.push_back(State::S0);
+ remove_init.insert(bit);
+ }
+ first_cell->setParam("\\INIT", initval);
+ }
+
+ if (opts.zinit)
+ for (int i = depth-1; i >= 0; i--) {
+ SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit());
+ remove_init.insert(bit);
+ }
+
+ if (opts.params)
+ {
+ int param_clkpol = -1;
+ int param_enpol = 2;
+
+ if (first_cell->type == "$_DFF_N_") param_clkpol = 0;
+ if (first_cell->type == "$_DFF_P_") param_clkpol = 1;
+
+ if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0;
+ if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1;
+ if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0;
+ if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1;
+
+ log_assert(param_clkpol >= 0);
+ first_cell->setParam("\\CLKPOL", param_clkpol);
+ if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol);
+ }
+
+ first_cell->type = shreg_cell_type_str;
+ first_cell->setPort(q_port, last_cell->getPort(q_port));
+ first_cell->setParam("\\DEPTH", depth);
+
+ if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict))
+ remove_cells.insert(first_cell);
+
+ for (int i = 1; i < depth; i++)
+ remove_cells.insert(chain[cursor+i]);
+ cursor += depth;
+ }
+ }
+
+ void cleanup()
+ {
+ for (auto cell : remove_cells)
+ module->remove(cell);
+
+ for (auto wire : module->wires())
+ {
+ if (wire->attributes.count("\\init") == 0)
+ continue;
+
+ SigSpec initsig = sigmap(wire);
+ Const &initval = wire->attributes.at("\\init");
+
+ for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
+ if (remove_init.count(initsig[i]))
+ initval[i] = State::Sx;
+
+ if (SigSpec(initval).is_fully_undef())
+ wire->attributes.erase("\\init");
+ }
+
+ remove_cells.clear();
+ sigbit_chain_next.clear();
+ sigbit_chain_prev.clear();
+ chain_start_cells.clear();
+ }
+
+ ShregmapWorker(Module *module, const ShregmapOptions &opts) :
+ module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0)
+ {
+ make_sigbit_chain_next_prev();
+ find_chain_start_cells();
+
+ for (auto c : chain_start_cells) {
+ vector<Cell*> chain = create_chain(c);
+ process_chain(chain);
+ }
+
+ cleanup();
+ }
+};
+
+struct ShregmapPass : public Pass {
+ ShregmapPass() : Pass("shregmap", "map shift registers") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" shregmap [options] [selection]\n");
+ log("\n");
+ log("This pass converts chains of $_DFF_[NP]_ gates to target specific shift register\n");
+ log("primitives. The generated shift register will be of type $__SHREG_DFF_[NP]_ and\n");
+ log("will use the same interface as the original $_DFF_*_ cells. The cell parameter\n");
+ log("'DEPTH' will contain the depth of the shift register. Use a target-specific\n");
+ log("'techmap' map file to convert those cells to the actual target cells.\n");
+ log("\n");
+ log(" -minlen N\n");
+ log(" minimum length of shift register (default = 2)\n");
+ log(" (this is the length after -keep_before and -keep_after)\n");
+ log("\n");
+ log(" -maxlen N\n");
+ log(" maximum length of shift register (default = no limit)\n");
+ log(" larger chains will be mapped to multiple shift register instances\n");
+ log("\n");
+ log(" -keep_before N\n");
+ log(" number of DFFs to keep before the shift register (default = 0)\n");
+ log("\n");
+ log(" -keep_after N\n");
+ log(" number of DFFs to keep after the shift register (default = 0)\n");
+ log("\n");
+ log(" -clkpol pos|neg|any\n");
+ log(" limit match to only positive or negative edge clocks. (default = any)\n");
+ log("\n");
+ log(" -enpol pos|neg|none|any_or_none|any\n");
+ log(" limit match to FFs with the specified enable polarity. (default = none)\n");
+ log("\n");
+ log(" -match <cell_type>[:<d_port_name>:<q_port_name>]\n");
+ log(" match the specified cells instead of $_DFF_N_ and $_DFF_P_. If\n");
+ log(" ':<d_port_name>:<q_port_name>' is omitted then 'D' and 'Q' is used\n");
+ log(" by default. E.g. the option '-clkpol pos' is just an alias for\n");
+ log(" '-match $_DFF_P_', which is an alias for '-match $_DFF_P_:D:Q'.\n");
+ log("\n");
+ log(" -params\n");
+ log(" instead of encoding the clock and enable polarity in the cell name by\n");
+ log(" deriving from the original cell name, simply name all generated cells\n");
+ log(" $__SHREG_ and use CLKPOL and ENPOL parameters. An ENPOL value of 2 is\n");
+ log(" used to denote cells without enable input. The ENPOL parameter is\n");
+ log(" omitted when '-enpol none' (or no -enpol option) is passed.\n");
+ log("\n");
+ log(" -zinit\n");
+ log(" assume the shift register is automatically zero-initialized, so it\n");
+ log(" becomes legal to merge zero initialized FFs into the shift register.\n");
+ log("\n");
+ log(" -init\n");
+ log(" map initialized registers to the shift reg, add an INIT parameter to\n");
+ log(" generated cells with the initialization value. (first bit to shift out\n");
+ log(" in LSB position)\n");
+ log("\n");
+ log(" -tech greenpak4\n");
+ log(" map to greenpak4 shift registers.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ ShregmapOptions opts;
+ string clkpol, enpol;
+
+ log_header(design, "Executing SHREGMAP pass (map shift registers).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-clkpol" && argidx+1 < args.size()) {
+ clkpol = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-enpol" && argidx+1 < args.size()) {
+ enpol = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-match" && argidx+1 < args.size()) {
+ vector<string> match_args = split_tokens(args[++argidx], ":");
+ if (GetSize(match_args) < 2)
+ match_args.push_back("D");
+ if (GetSize(match_args) < 3)
+ match_args.push_back("Q");
+ IdString id_cell_type(RTLIL::escape_id(match_args[0]));
+ IdString id_d_port_name(RTLIL::escape_id(match_args[1]));
+ IdString id_q_port_name(RTLIL::escape_id(match_args[2]));
+ opts.ffcells[id_cell_type] = make_pair(id_d_port_name, id_q_port_name);
+ continue;
+ }
+ if (args[argidx] == "-minlen" && argidx+1 < args.size()) {
+ opts.minlen = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-maxlen" && argidx+1 < args.size()) {
+ opts.maxlen = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-keep_before" && argidx+1 < args.size()) {
+ opts.keep_before = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-keep_after" && argidx+1 < args.size()) {
+ opts.keep_after = atoi(args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-tech" && argidx+1 < args.size() && opts.tech == nullptr) {
+ string tech = args[++argidx];
+ if (tech == "greenpak4") {
+ clkpol = "pos";
+ opts.zinit = true;
+ opts.tech = new ShregmapTechGreenpak4;
+ } else {
+ argidx--;
+ break;
+ }
+ continue;
+ }
+ if (args[argidx] == "-zinit") {
+ opts.zinit = true;
+ continue;
+ }
+ if (args[argidx] == "-init") {
+ opts.init = true;
+ continue;
+ }
+ if (args[argidx] == "-params") {
+ opts.params = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (opts.zinit && opts.init)
+ log_cmd_error("Options -zinit and -init are exclusive!\n");
+
+ if (opts.ffcells.empty())
+ {
+ bool clk_pos = clkpol == "" || clkpol == "pos" || clkpol == "any";
+ bool clk_neg = clkpol == "" || clkpol == "neg" || clkpol == "any";
+
+ bool en_none = enpol == "" || enpol == "none" || enpol == "any_or_none";
+ bool en_pos = enpol == "pos" || enpol == "any" || enpol == "any_or_none";
+ bool en_neg = enpol == "neg" || enpol == "any" || enpol == "any_or_none";
+
+ if (clk_pos && en_none)
+ opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q"));
+ if (clk_neg && en_none)
+ opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q"));
+
+ if (clk_pos && en_pos)
+ opts.ffcells["$_DFFE_PP_"] = make_pair(IdString("\\D"), IdString("\\Q"));
+ if (clk_pos && en_neg)
+ opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q"));
+
+ if (clk_neg && en_pos)
+ opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q"));
+ if (clk_neg && en_neg)
+ opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q"));
+
+ if (en_pos || en_neg)
+ opts.ffe = true;
+ }
+ else
+ {
+ if (!clkpol.empty())
+ log_cmd_error("Options -clkpol and -match are exclusive!\n");
+ if (!enpol.empty())
+ log_cmd_error("Options -enpol and -match are exclusive!\n");
+ if (opts.params)
+ log_cmd_error("Options -params and -match are exclusive!\n");
+ }
+
+ int dff_count = 0;
+ int shreg_count = 0;
+
+ for (auto module : design->selected_modules()) {
+ ShregmapWorker worker(module, opts);
+ dff_count += worker.dff_count;
+ shreg_count += worker.shreg_count;
+ }
+
+ log("Converted %d dff cells into %d shift registers.\n", dff_count, shreg_count);
+
+ if (opts.tech != nullptr) {
+ delete opts.tech;
+ opts.tech = nullptr;
+ }
+ }
+} ShregmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index f6ac3964..0fb64734 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -321,6 +321,36 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
module->connect(cell->getPort("\\Y"), lut_data);
}
+void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ SigSpec ctrl = cell->getPort("\\A");
+ SigSpec table = cell->getParam("\\TABLE");
+
+ int width = cell->getParam("\\WIDTH").as_int();
+ int depth = cell->getParam("\\DEPTH").as_int();
+ table.extend_u0(2 * width * depth);
+
+ SigSpec products;
+
+ for (int i = 0; i < depth; i++) {
+ SigSpec in, pat;
+ for (int j = 0; j < width; j++) {
+ if (table[2*i*width + 2*j + 0] == State::S1) {
+ in.append(ctrl[j]);
+ pat.append(State::S0);
+ }
+ if (table[2*i*width + 2*j + 1] == State::S1) {
+ in.append(ctrl[j]);
+ pat.append(State::S1);
+ }
+ }
+
+ products.append(GetSize(in) > 0 ? module->Eq(NEW_ID, in, pat) : State::S1);
+ }
+
+ module->connect(cell->getPort("\\Y"), module->ReduceOr(NEW_ID, products));
+}
+
void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
{
int offset = cell->parameters.at("\\OFFSET").as_int();
@@ -498,6 +528,7 @@ void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTL
mappers["$mux"] = simplemap_mux;
mappers["$tribuf"] = simplemap_tribuf;
mappers["$lut"] = simplemap_lut;
+ mappers["$sop"] = simplemap_sop;
mappers["$slice"] = simplemap_slice;
mappers["$concat"] = simplemap_concat;
mappers["$sr"] = simplemap_sr;
@@ -543,7 +574,7 @@ struct SimplemapPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
+ log_header(design, "Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
extra_args(args, 1, design);
std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 5334ebfa..b2cc492b 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -234,8 +234,10 @@ struct TechmapWorker
tpl_written_bits.insert(bit);
SigMap port_signal_map;
+ SigSig port_signal_assign;
- for (auto &it : cell->connections()) {
+ for (auto &it : cell->connections())
+ {
RTLIL::IdString portname = it.first;
if (positional_ports.count(portname) > 0)
portname = positional_ports.at(portname);
@@ -244,16 +246,22 @@ struct TechmapWorker
log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname.c_str(), cell->name.c_str(), tpl->name.c_str());
continue;
}
+
RTLIL::Wire *w = tpl->wires_.at(portname);
- RTLIL::SigSig c;
+ RTLIL::SigSig c, extra_connect;
+
if (w->port_output && !w->port_input) {
c.first = it.second;
c.second = RTLIL::SigSpec(w);
apply_prefix(cell->name.str(), c.second, module);
+ extra_connect.first = c.second;
+ extra_connect.second = c.first;
} else if (!w->port_output && w->port_input) {
c.first = RTLIL::SigSpec(w);
c.second = it.second;
apply_prefix(cell->name.str(), c.first, module);
+ extra_connect.first = c.first;
+ extra_connect.second = c.second;
} else {
SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
apply_prefix(cell->name.str(), sig_tpl_pf, module);
@@ -266,28 +274,48 @@ struct TechmapWorker
c.second.append(sig_mod[i]);
}
}
+ extra_connect.first = sig_tpl_pf;
+ extra_connect.second = sig_mod;
}
+
if (c.second.size() > c.first.size())
c.second.remove(c.first.size(), c.second.size() - c.first.size());
+
if (c.second.size() < c.first.size())
c.second.append(RTLIL::SigSpec(RTLIL::State::S0, c.first.size() - c.second.size()));
+
log_assert(c.first.size() == c.second.size());
- if (flatten_mode) {
+
+ if (flatten_mode)
+ {
// more conservative approach:
// connect internal and external wires
+
if (sigmaps.count(module) == 0)
sigmaps[module].set(module);
+
if (sigmaps.at(module)(c.first).has_const())
log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n",
log_id(module), log_id(cell), log_id(it.first), log_signal(c.first), log_signal(c.second));
+
module->connect(c);
- } else {
+ }
+ else
+ {
// approach that yields nicer outputs:
// replace internal wires that are connected to external wires
+
if (w->port_output)
port_signal_map.add(c.second, c.first);
else
port_signal_map.add(c.first, c.second);
+
+ for (auto &attr : w->attributes) {
+ if (attr.first == "\\src")
+ continue;
+ module->connect(extra_connect);
+ break;
+ }
}
}
@@ -611,7 +639,7 @@ struct TechmapWorker
if (techmap_cache.count(key) > 0) {
tpl = techmap_cache[key];
} else {
- if (cell->parameters.size() != 0) {
+ if (parameters.size() != 0) {
derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end()));
tpl = map->module(derived_name);
log_continue = true;
@@ -779,7 +807,7 @@ struct TechmapWorker
if (recursive_mode) {
if (log_continue) {
- log_header("Continuing TECHMAP pass.\n");
+ log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
}
while (techmap_module(map, tpl, map, handled_cells, celltypeMap, true)) { }
@@ -790,7 +818,7 @@ struct TechmapWorker
continue;
if (log_continue) {
- log_header("Continuing TECHMAP pass.\n");
+ log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
}
@@ -833,7 +861,7 @@ struct TechmapWorker
}
if (log_continue) {
- log_header("Continuing TECHMAP pass.\n");
+ log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
}
@@ -976,7 +1004,7 @@ struct TechmapPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing TECHMAP pass (map to technology primitives).\n");
+ log_header(design, "Executing TECHMAP pass (map to technology primitives).\n");
log_push();
TechmapWorker worker;
@@ -1108,7 +1136,7 @@ struct FlattenPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing FLATTEN pass (flatten design).\n");
+ log_header(design, "Executing FLATTEN pass (flatten design).\n");
log_push();
extra_args(args, 1, design);
diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc
index d0564b4e..03629082 100644
--- a/passes/techmap/tribuf.cc
+++ b/passes/techmap/tribuf.cc
@@ -160,7 +160,7 @@ struct TribufPass : public Pass {
{
TribufConfig config;
- log_header("Executing TRIBUF pass.\n");
+ log_header(design, "Executing TRIBUF pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc
index bb516fca..cb31056f 100644
--- a/passes/tests/test_autotb.cc
+++ b/passes/tests/test_autotb.cc
@@ -71,16 +71,21 @@ static std::string idy(std::string str1, std::string str2 = std::string(), std::
return id(str1);
}
-static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
+static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int seed)
{
+ f << stringf("`ifndef outfile\n");
+ f << stringf("\t`define outfile \"/dev/stdout\"\n");
+ f << stringf("`endif\n");
+
f << stringf("module testbench;\n\n");
- f << stringf("integer i;\n\n");
+ f << stringf("integer i;\n");
+ f << stringf("integer file;\n\n");
f << stringf("reg [31:0] xorshift128_x = 123456789;\n");
f << stringf("reg [31:0] xorshift128_y = 362436069;\n");
f << stringf("reg [31:0] xorshift128_z = 521288629;\n");
- f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", int(time(NULL)));
+ f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(NULL)));
f << stringf("reg [31:0] xorshift128_t;\n\n");
f << stringf("task xorshift128;\n");
f << stringf("begin\n");
@@ -150,6 +155,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
f << stringf("\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2);
for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it)
f << stringf("\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2);
+ f << stringf("\t#%d;\n", ((2*delay_counter+99)/100)*100);
for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) {
f << stringf("\t#100; %s <= 1;\n", it->first.c_str());
f << stringf("\t#100; %s <= 0;\n", it->first.c_str());
@@ -157,6 +163,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
delay_counter = 0;
for (auto it = signal_in.begin(); it != signal_in.end(); ++it)
f << stringf("\t%s <= #%d ~0;\n", it->first.c_str(), ++delay_counter*2);
+ f << stringf("\t#%d;\n", ((2*delay_counter+99)/100)*100);
for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) {
f << stringf("\t#100; %s <= 1;\n", it->first.c_str());
f << stringf("\t#100; %s <= 0;\n", it->first.c_str());
@@ -167,6 +174,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
continue;
f << stringf("\t%s <= #%d 'b%s;\n", it->first.c_str(), ++delay_counter*2, signal_const[it->first].c_str());
}
+ f << stringf("\t#%d;\n", ((2*delay_counter+99)/100)*100);
f << stringf("end\n");
f << stringf("endtask\n\n");
@@ -179,6 +187,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
f << stringf("\txorshift128;\n");
f << stringf("\t%s <= #%d { xorshift128_x, xorshift128_y, xorshift128_z, xorshift128_w };\n", it->first.c_str(), ++delay_counter*2);
}
+ f << stringf("\t#%d;\n", ((2*delay_counter+99)/100)*100);
f << stringf("end\n");
f << stringf("endtask\n\n");
@@ -206,61 +215,70 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
f << stringf("task %s;\n", idy(mod->name.str(), "print_status").c_str());
f << stringf("begin\n");
- f << stringf("\t$display(\"#OUT# %%b %%b %%b %%t %%d\", {");
+ f << stringf("\t$fdisplay(file, \"#OUT# %%b %%b %%b %%t %%d\", {");
if (signal_in.size())
for (auto it = signal_in.begin(); it != signal_in.end(); it++) {
f << stringf("%s %s", it == signal_in.begin() ? "" : ",", it->first.c_str());
int len = it->second;
+ header2 += ", \"";
if (len > 1)
header2 += "/", len--;
while (len > 1)
header2 += "-", len--;
if (len > 0)
header2 += shorthand, len--;
+ header2 += "\"";
header1.push_back(" " + it->first);
- header1.back()[0] = shorthand++;
+ header1.back()[0] = shorthand;
+ shorthand = shorthand == 'Z' ? 'A' : shorthand+1;
}
else {
f << stringf(" 1'bx");
- header2 += "#";
+ header2 += ", \"#\"";
}
f << stringf(" }, {");
- header2 += " ";
+ header2 += ", \" \"";
if (signal_clk.size()) {
for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) {
f << stringf("%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str());
int len = it->second;
+ header2 += ", \"";
if (len > 1)
header2 += "/", len--;
while (len > 1)
header2 += "-", len--;
if (len > 0)
header2 += shorthand, len--;
+ header2 += "\"";
header1.push_back(" " + it->first);
- header1.back()[0] = shorthand++;
+ header1.back()[0] = shorthand;
+ shorthand = shorthand == 'Z' ? 'A' : shorthand+1;
}
} else {
f << stringf(" 1'bx");
- header2 += "#";
+ header2 += ", \"#\"";
}
f << stringf(" }, {");
- header2 += " ";
+ header2 += ", \" \"";
if (signal_out.size()) {
for (auto it = signal_out.begin(); it != signal_out.end(); it++) {
f << stringf("%s %s", it == signal_out.begin() ? "" : ",", it->first.c_str());
int len = it->second;
+ header2 += ", \"";
if (len > 1)
header2 += "/", len--;
while (len > 1)
header2 += "-", len--;
if (len > 0)
header2 += shorthand, len--;
+ header2 += "\"";
header1.push_back(" " + it->first);
- header1.back()[0] = shorthand++;
+ header1.back()[0] = shorthand;
+ shorthand = shorthand == 'Z' ? 'A' : shorthand+1;
}
} else {
f << stringf(" 1'bx");
- header2 += "#";
+ header2 += ", \"#\"";
}
f << stringf(" }, $time, i);\n");
f << stringf("end\n");
@@ -268,17 +286,17 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
f << stringf("task %s;\n", idy(mod->name.str(), "print_header").c_str());
f << stringf("begin\n");
- f << stringf("\t$display(\"#OUT#\");\n");
+ f << stringf("\t$fdisplay(file, \"#OUT#\");\n");
for (auto &hdr : header1)
- f << stringf("\t$display(\"#OUT# %s\");\n", hdr.c_str());
- f << stringf("\t$display(\"#OUT#\");\n");
- f << stringf("\t$display(\"#OUT# %s\");\n", header2.c_str());
+ f << stringf("\t$fdisplay(file, \"#OUT# %s\");\n", hdr.c_str());
+ f << stringf("\t$fdisplay(file, \"#OUT#\");\n");
+ f << stringf("\t$fdisplay(file, {\"#OUT# \"%s});\n", header2.c_str());
f << stringf("end\n");
f << stringf("endtask\n\n");
f << stringf("task %s;\n", idy(mod->name.str(), "test").c_str());
f << stringf("begin\n");
- f << stringf("\t$display(\"#OUT#\\n#OUT# ==== %s ====\");\n", idy(mod->name.str()).c_str());
+ f << stringf("\t$fdisplay(file, \"#OUT#\\n#OUT# ==== %s ====\");\n", idy(mod->name.str()).c_str());
f << stringf("\t%s;\n", idy(mod->name.str(), "reset").c_str());
f << stringf("\tfor (i=0; i<%d; i=i+1) begin\n", num_iter);
f << stringf("\t\tif (i %% 20 == 0) %s;\n", idy(mod->name.str(), "print_header").c_str());
@@ -293,9 +311,11 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter)
f << stringf("initial begin\n");
f << stringf("\t// $dumpfile(\"testbench.vcd\");\n");
f << stringf("\t// $dumpvars(0, testbench);\n");
+ f << stringf("\tfile = $fopen(`outfile);\n");
for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it)
if (!it->second->get_bool_attribute("\\gentb_skip"))
f << stringf("\t%s;\n", idy(it->first.str(), "test").c_str());
+ f << stringf("\t$fclose(file);\n");
f << stringf("\t$finish;\n");
f << stringf("end\n\n");
@@ -332,8 +352,9 @@ struct TestAutotbBackend : public Backend {
virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
{
int num_iter = 1000;
+ int seed = 0;
- log_header("Executing TEST_AUTOTB backend (auto-generate pseudo-random test benches).\n");
+ log_header(design, "Executing TEST_AUTOTB backend (auto-generate pseudo-random test benches).\n");
int argidx;
for (argidx = 1; argidx < GetSize(args); argidx++)
@@ -342,11 +363,15 @@ struct TestAutotbBackend : public Backend {
num_iter = atoi(args[++argidx].c_str());
continue;
}
+ if (args[argidx] == "-seed" && argidx+1 < GetSize(args)) {
+ seed = atoi(args[++argidx].c_str());
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
- autotest(*f, design, num_iter);
+ autotest(*f, design, num_iter, seed);
}
} TestAutotbBackend;
diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc
index a8fcac9b..049c2053 100644
--- a/passes/tests/test_cell.cc
+++ b/passes/tests/test_cell.cc
@@ -21,6 +21,7 @@
#include "kernel/yosys.h"
#include "kernel/satgen.h"
#include "kernel/consteval.h"
+#include "kernel/celledges.h"
#include "kernel/macc.h"
#include <algorithm>
@@ -42,6 +43,32 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
RTLIL::Wire *wire;
+ if (cell_type == "$mux" || cell_type == "$pmux")
+ {
+ int width = 1 + xorshift32(8);
+ int swidth = cell_type == "$mux" ? 1 : 1 + xorshift32(8);
+
+ wire = module->addWire("\\A");
+ wire->width = width;
+ wire->port_input = true;
+ cell->setPort("\\A", wire);
+
+ wire = module->addWire("\\B");
+ wire->width = width * swidth;
+ wire->port_input = true;
+ cell->setPort("\\B", wire);
+
+ wire = module->addWire("\\S");
+ wire->width = swidth;
+ wire->port_input = true;
+ cell->setPort("\\S", wire);
+
+ wire = module->addWire("\\Y");
+ wire->width = width;
+ wire->port_output = true;
+ cell->setPort("\\Y", wire);
+ }
+
if (cell_type == "$fa")
{
int width = 1 + xorshift32(8);
@@ -164,6 +191,41 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->setParam("\\LUT", config.as_const());
}
+ if (cell_type == "$sop")
+ {
+ int width = 1 + xorshift32(8);
+ int depth = 1 + xorshift32(8);
+
+ wire = module->addWire("\\A");
+ wire->width = width;
+ wire->port_input = true;
+ cell->setPort("\\A", wire);
+
+ wire = module->addWire("\\Y");
+ wire->port_output = true;
+ cell->setPort("\\Y", wire);
+
+ RTLIL::SigSpec config;
+ for (int i = 0; i < width*depth; i++)
+ switch (xorshift32(3)) {
+ case 0:
+ config.append(RTLIL::S1);
+ config.append(RTLIL::S0);
+ break;
+ case 1:
+ config.append(RTLIL::S0);
+ config.append(RTLIL::S1);
+ break;
+ case 2:
+ config.append(RTLIL::S0);
+ config.append(RTLIL::S0);
+ break;
+ }
+
+ cell->setParam("\\DEPTH", depth);
+ cell->setParam("\\TABLE", config.as_const());
+ }
+
if (cell_type_flags.find('A') != std::string::npos) {
wire = module->addWire("\\A");
wire->width = 1 + xorshift32(8);
@@ -270,6 +332,91 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->check();
}
+static void run_edges_test(RTLIL::Design *design, bool verbose)
+{
+ Module *module = *design->modules().begin();
+ Cell *cell = *module->cells().begin();
+
+ ezSatPtr ezptr;
+ ezSAT &ez = *ezptr.get();
+
+ SigMap sigmap(module);
+ SatGen satgen(&ez, &sigmap);
+
+ FwdCellEdgesDatabase edges_db(sigmap);
+ if (!edges_db.add_edges_from_cell(cell))
+ log_error("Creating edge database failed for this cell!\n");
+
+ dict<SigBit, pool<SigBit>> satgen_db;
+
+ satgen.setContext(&sigmap, "X:");
+ satgen.importCell(cell);
+
+ satgen.setContext(&sigmap, "Y:");
+ satgen.importCell(cell);
+
+ vector<tuple<SigBit, int, int>> input_db, output_db;
+
+ for (auto &conn : cell->connections())
+ {
+ SigSpec bits = sigmap(conn.second);
+
+ satgen.setContext(&sigmap, "X:");
+ std::vector<int> xbits = satgen.importSigSpec(bits);
+
+ satgen.setContext(&sigmap, "Y:");
+ std::vector<int> ybits = satgen.importSigSpec(bits);
+
+ for (int i = 0; i < GetSize(bits); i++)
+ if (cell->input(conn.first))
+ input_db.emplace_back(bits[i], xbits[i], ybits[i]);
+ else
+ output_db.emplace_back(bits[i], xbits[i], ybits[i]);
+ }
+
+ if (verbose)
+ log("\nSAT solving for all edges:\n");
+
+ for (int i = 0; i < GetSize(input_db); i++)
+ {
+ SigBit inbit = std::get<0>(input_db[i]);
+
+ if (verbose)
+ log(" Testing input signal %s:\n", log_signal(inbit));
+
+ vector<int> xinbits, yinbits;
+ for (int k = 0; k < GetSize(input_db); k++)
+ if (k != i) {
+ xinbits.push_back(std::get<1>(input_db[k]));
+ yinbits.push_back(std::get<2>(input_db[k]));
+ }
+
+ int xyinbit_ok = ez.vec_eq(xinbits, yinbits);
+
+ for (int k = 0; k < GetSize(output_db); k++)
+ {
+ SigBit outbit = std::get<0>(output_db[k]);
+ int xoutbit = std::get<1>(output_db[k]);
+ int youtbit = std::get<2>(output_db[k]);
+
+ bool is_edge = ez.solve(xyinbit_ok, ez.XOR(xoutbit, youtbit));
+
+ if (is_edge)
+ satgen_db[inbit].insert(outbit);
+
+ if (verbose) {
+ bool is_ref_edge = edges_db.db.count(inbit) && edges_db.db.at(inbit).count(outbit);
+ log(" %c %s %s\n", is_edge ? 'x' : 'o', log_signal(outbit), is_edge == is_ref_edge ? "OK" : "ERROR");
+ }
+ }
+ }
+
+ if (satgen_db == edges_db.db)
+ log("PASS.\n");
+ else
+ log_error("SAT-based edge table does not match the database!\n");
+}
+
static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std::string uut_name, std::ofstream &vlog_file)
{
log("Eval testing:%c", verbose ? '\n' : ' ');
@@ -534,7 +681,7 @@ struct TestCellPass : public Pass {
log(" pass this option to techmap.\n");
log("\n");
log(" -simlib\n");
- log(" use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n");
+ log(" use \"techmap -D SIMLIB_NOCHECKS -map +/simlib.v -max_iter 2 -autoproc\"\n");
log("\n");
log(" -aigmap\n");
log(" instead of calling \"techmap\", call \"aigmap\"\n");
@@ -555,6 +702,9 @@ struct TestCellPass : public Pass {
log(" -noeval\n");
log(" do not check const-eval models\n");
log("\n");
+ log(" -edges\n");
+ log(" test cell edges db creator against sat-based implementation\n");
+ log("\n");
log(" -v\n");
log(" print additional debug information to the console\n");
log("\n");
@@ -574,6 +724,7 @@ struct TestCellPass : public Pass {
bool constmode = false;
bool nosat = false;
bool noeval = false;
+ bool edges = false;
int argidx;
for (argidx = 1; argidx < GetSize(args); argidx++)
@@ -604,7 +755,7 @@ struct TestCellPass : public Pass {
continue;
}
if (args[argidx] == "-simlib") {
- techmap_cmd = "techmap -map +/simlib.v -max_iter 2 -autoproc";
+ techmap_cmd = "techmap -D SIMLIB_NOCHECKS -map +/simlib.v -max_iter 2 -autoproc";
continue;
}
if (args[argidx] == "-aigmap") {
@@ -627,6 +778,10 @@ struct TestCellPass : public Pass {
noeval = true;
continue;
}
+ if (args[argidx] == "-edges") {
+ edges = true;
+ continue;
+ }
if (args[argidx] == "-v") {
verbose = true;
continue;
@@ -690,13 +845,18 @@ struct TestCellPass : public Pass {
cell_types["$logic_and"] = "ABSY";
cell_types["$logic_or"] = "ABSY";
- // cell_types["$mux"] = "A";
- // cell_types["$pmux"] = "A";
+ if (edges) {
+ cell_types["$mux"] = "*";
+ cell_types["$pmux"] = "*";
+ }
+
// cell_types["$slice"] = "A";
// cell_types["$concat"] = "A";
// cell_types["$assert"] = "A";
+ // cell_types["$assume"] = "A";
cell_types["$lut"] = "*";
+ cell_types["$sop"] = "*";
cell_types["$alu"] = "ABSY";
cell_types["$lcu"] = "*";
cell_types["$macc"] = "*";
@@ -763,6 +923,9 @@ struct TestCellPass : public Pass {
create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv);
if (!write_prefix.empty()) {
Pass::call(design, stringf("write_ilang %s_%s_%05d.il", write_prefix.c_str(), cell_type.c_str()+1, i));
+ } else if (edges) {
+ Pass::call(design, "dump gold");
+ run_edges_test(design, verbose);
} else {
Pass::call(design, stringf("copy gold gate; cd gate; %s; cd ..; opt -fast gate", techmap_cmd.c_str()));
if (!nosat)