Doing ABC runs in parallel can actually make things slower when every ABC run requires
spawning an ABC subprocess --- especially when using popen(), which on glibc does not
use vfork(). What seems to happen is that constant fork()ing keeps making the main
process data pages copy-on-write, so the main process code that is setting up each ABC
call takes a lot of minor page-faults, slowing it down.
The solution is pretty straightforward although a little tricky to implement.
We just reuse ABC subprocesses. Instead of passing the ABC script name on the command
line, we spawn an ABC REPL and pipe a command into it to source the script. When that's
done we echo an `ABC_DONE` token instead of exiting. Yosys then puts the ABC process
onto a stack which we can pull from the next time we do an ABC run.
For one of our large designs, this is an additional 5x speedup of the primary AbcPass.
It does 5155 ABC runs, all very small; runtime of the AbcPass goes from 760s to 149s
(not very scientific benchmarking but the effect size is large).
Large circuits can run hundreds or thousands of ABCs in a single AbcPass.
For some circuits, some of those ABC runs can run for hundreds of seconds.
Running ABCs in parallel with each other and in parallel with main-thread
processing (reading and writing BLIF files, copying ABC BLIF output into
the design) can give large speedups.
Use Bison's typed midrule actions to construct AST_FCALL nodes
with std::unique_ptr, replacing manual 'new' and extra->ast_stack
management. This improves type safety, ensures proper ownership, and
eliminates potential memory leaks.
Ref: https://www.gnu.org/software/bison/manual/html_node/Typed-Midrule-Actions.html
The YosysHQ Verific Extensions are compiled separately using their own
stripped-down version of the Yosys headers. To maintain ABI
compatibility with older extension builds post C++-ification of Yosys's
logging APIs, which are backwards compatible on the API but not ABI
level, this commit adds ABI compatible versions of a subset of the old
logging API used by the extensions.
The code in memory_libmap expects `clk_en` to be initialized for all
`PortVariant`s but the parsing in memlib.cc didn't initialize it for
variants of kind `PortKind::Ar` (async read ports).
While this fixes the immediate CI failure, it would be best to refactor
the code so it becomes obvious if something isn't initialized.