Add tri-state support for const eval and add tribuf -propagate option #4661
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What are the reasons/motivation for this change?
I am working on a non-synthesizable project (https://github.com/emu-russia/dmgcpu) that makes extensive use of tri-state signals. This causes problems because projects like Verilator and Yosys don't handle those very well.
Explain how this is achieved.
Yosys already has the
tribuf -logic
pass, which can merge signals driven by multiple tribuf cells into a$pmux
, allowing the elimination of tristate signals in a design. However, it didn't handle tristates nested in muxes.This change implements the
-propagate
option, which propagates tri-state buffers through muxes.This allows for eliminating all tristate usage in a design by flattening the module hierarchy, detecting and propagating all tribuf cells, and resolving them as a
$pmux
. See emu-russia/dmgcpu#292 for this being done in practice.If applicable, please suggest to reviewers how they can test the change.
The change includes the test file
tests/techmap/tribuf.ys
, which tests many of the cases the implementation handles and exemplifies how the command is used.Summary of changes
The PR can be split into these changes:
-assert
option to theeval
command.consteval.cc
.-propagate
option to thetribuf
command.-force
option to thetribuf
command.The main change is the
-propagate
option, and the two above are only used to allow automatic testing of that change. If you prefer, I can split up this PR.eval -assert
Asserts that a signal evaluates to a specific value. This is used in conjunction with
equiv_make
to check if the modifications applied maintain the circuit behavior. I think most tests usedmiter -equiv
instead, but I'm not sure if that works with designs with tristate signals (at least it didn't work before adding tri-state support to consteval).When
-table
is used, it asserts the same value for each input combination. The command will first print the result or table before erroring out.Consteval tri-state signals
This change makes
consteval.cc
resolve signals from multiple drivers, following the Verilog spec but ignoring signal strength.The old implementation contained a
SigMap values_map
that mapped the signals to their constant value. This was split into aConstMap
that maps a sigbit to its possibly partially evaluatedState
, and aSigPool evaluated
that tells if a sigbit was fully evaluated.ConstEval::add
handles resolving the new value assigned to a sigbit with its previous value, like resolving conflicting values tox
, or keeping one value when the other isz
.Stopped using
ConstEval::set
internally, replacing it withConstEval::assign
.ConstEval::set
is now only used externally and marks a value asevaluated
.tribuf -propagate
Propagates tri-state signals through muxes and tribuf cells. Also reworks the implementation of
-merge
, making it work at sigbit granularity and splitting tribuf cells when necessary.tribuf -logic -force
By default,
tribuf -logic
will not replace a tribuf cell that is driving an output port.-force
allows doing something liketribuf -logic -force w:OutPort %ci1
in case the output port is not actually a tristate port.