-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add commands for analysis of VHDL via Yosys #1700
Conversation
Right now this is probably subtly broken in a bunch of ways. But, I can translate a simple FSM and the resulting term appears to behave correctly!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I certainly can't pretend to be able to review a large PR like this in detail, especially as it represents months of work and many lessons learned. However, I will point out that this PR is almost entirely new functionality, and only very lightly changes existing functionality just enough to add in the new yosys-related SAW script commands and values. Thus, it should not (and as far as CI is concerned doesn't) affect any of the existing SAW functionality. In addition, it includes a number of tests for this new functionality that will be run as part of CI. Given all this, I feel like this PR is ready to be approved.
I concur with @eddywestbrook's analysis. Do shout if you think there are parts of this PR that deserve closer scrutiny, of course. |
This pull request implements experimental support for analysis of hardware descriptions written in VHDL (via GHDL) through an intermediate representation produced by Yosys.
This generally follows the same conventions and idioms used in the rest of SAWSCript.
Processing VHDL With Yosys
Given a VHDL file
test.vhd
containing an entitytest
, one can generate an intermediate representationtest.json
suitable for loading into SAW:It can sometimes be helpful to invoke additional Yosys passes between the
ghdl
andwrite_json
commands.For example, at present SAW does not support the
$pmux
cell type.Yosys is able to convert
$pmux
cells into trees of$mux
cells using thepmuxtree
command.We expect there are many other situations where Yosys' considerable library of commands is valuable for pre-processing.
Analyzing Combinational Circuits
SAW is able to import Yosys modules as
Term
values, much like it can import Cryptol functions.Consider three VHDL entities.
First, a half-adder:
Next, a one-bit adder built atop that half-adder:
Finally, a four-bit adder:
Using GHDL and Yosys, we can convert the VHDL source above into a format that SAW can import.
If all of the code above is in a file
adder.vhd
, we can run the following commands:The produced file
adder.json
can then be loaded into SAW withyosys_import
:yosys_import
returns aTerm
with a Cryptol record type, where the fields correspond to each VHDL module.We can access the fields of this record like we would any Cryptol record, and call the functions within like any Cryptol function.
We can also use all of SAW's infrastructure for asking solvers about
Term
s, such as thesat
andprove
commands.For example:
The full library of
ProofScript
tactics is available in this setting.If necessary, proof tactics like
simplify
can be used to rewrite goals before querying a solver.Special support is provided for the common case of equivalence proofs between HDL modules and other
Term
s (e.g. Cryptol functions, other HDL modules, or "extracted" imperative LLVM or JVM code).The command
yosys_verify
has an interface similar tollvm_verify
: given a specification, some lemmas, and a proof tactic, it produces evidence of a proven equivalence that may be passed as a lemma to future calls ofyosys_verify
.For example, consider the following Cryptol specifications for one-bit and four-bit adders:
We can prove equivalence between
cryfull
and the VHDLfull
module:The result
full_spec
can then be used as an "override" when proving equivalence betweencryadd4
and the VHDLadd4
module:The above could also be accomplished through the use of
prove_print
and term rewriting, but it is much more verbose.yosys_verify
may also be given a list of preconditions under which the equivalence holds.For example, consider the following Cryptol specification for
full
that ignores thecin
bit:This is not equivalent to
full
in general, but it is if constrained to inputs wherecin = 0
.We may express that precondition like so:
The resulting override
full_nocarry_spec
may still be used in the proof foradd4
(this is accomplished by rewriting to a conditional expression).Analyzing Sequential Circuits
SAW is also capable of importing sequential circuits, although there are some quirks and caveats to be aware of.
The main entrypoint to this functionality is the
yosys_import_sequential
command, which takes the name of a Yosys module and a path to a Yosys JSON file and produces a representation of the named module.This representation can then be converted to a
Term
or sent to a model checker alongside a query using an assortment of other commands.For example,
yosys_extract_sequential_raw
will produce aTerm
with a__state__
field encoding the state of the circuit in the input and output records.There are some additional restrictions on the sorts of sequential Yosys modules that may be analyzed when compared to the combinational mode.
First, the module must be "flat" - it must use only primitive cell types, not other user-defined modules.
Yosys is able to convert more complex module hierarchies into a flat module using the
flatten
command.Further, the only stateful cell that is currently supported is the
$dff
cell.Other stateful cells can be converted to
$dff
using thememory
anddffunmap
commands.API
N.B: The following commands must first be enabled using
enable_experimental
.yosys_import : String -> TopLevel Term
produces aTerm
given the path to a JSON file produced by the Yosyswrite_json
command.The resulting term is a Cryptol record, where each field corresponds to one HDL module exported by Yosys.
Each HDL module is in turn represented by a function from a record of input port values to a record of output port values.
For example, consider a Yosys JSON file derived from the following VHDL entities:
The resulting
Term
will have the type:yosys_verify : Term -> [Term] -> Term -> [YosysTheorem] -> ProofScript () -> TopLevel YosysTheorem
proves equality between an HDL module and a specification.The first parameter is the HDL module - given a record
m
fromyosys_import
, this will typically look something like{{ m.foo }}
.The second parameter is a list of preconditions for the equality.
The third parameter is the specification, a term of the same type as the HDL module, which will typically be some Cryptol function or another HDL module.
The fourth parameter is a list of "overrides", which witness the results of previous
yosys_verify
proofs.These overrides can be used to simplify terms by replacing use sites of submodules with their specifications.
Note that
Term
s derived from HDL modules are "first class", and are not restricted toyosys_verify
: they may also be used with SAW's typicalTerm
infrastructure likesat
,prove_print
, term rewriting, etc.yosys_verify
simply provides a convenient and familiar interface, similar tollvm_verify
orjvm_verify
.yosys_import_sequential : String -> String -> TopLevel YosysSequential
imports a particular sequential module.The first parameter is the module name, the second is the path to the Yosys JSON file.
The resulting value is an opaque representation of the sequential circuit that can be extracted to a
Term
or sent to solvers in various ways.SAW expects the sequential module to exist entirely within a single Yosys module - the Yosys
flatten
command will collapse the module hierarchy into a single module.The only supported sequential element is the basic
$dff
cell.Memory cells and more complex flip-flops can be translated into
$dff
s using thememory
anddffunmap
Yosys commands.yosys_extract_sequential_raw : YosysSequential -> TopLevel Term
extracts aTerm
from a sequential module.This term has explicit fields for the state of the circuit in the input and output record types.
yosys_extract_sequential : YosysSequential -> Int -> TopLevel Term
extracts a term with the state eliminated by iterating the term over the given concrete number of cycles.The resulting term has no state field in the inputs or outputs, and each input and output field is replaced with an array of that field's type (array length being the number of cycles).
This term can be used like a normal SAW term - it may be embedded in Cryptol expressions, used in
prove
andsat
, etc.yosys_verify_sequential_offline_sally : YosysSequential -> String -> Term -> [String] -> TopLevel Term
exports a query over the given sequential module to an input file for the Sally model checker.The first parameter is the sequential module.
The second parameter is the path to write the resulting Sally input.
The third parameter is the query, which should be a boolean function of three parameters: an 8-bit cycle counter, a record of "fixed" inputs, and a record of circuit outputs.
The fourth parameter is a list of strings specifying certain circuit inputs as fixed - these inputs are assumed to remain unchanged across cycles, and are therefore accesible from the query function.