mirror of https://github.com/llvm/circt.git
[FIRRTL] add an initial FIRRTL dialect rationale doc.
This commit is contained in:
parent
cd43293360
commit
a42bb3ddc1
|
@ -0,0 +1,103 @@
|
|||
FIRRTL Dialect Rationale
|
||||
========================
|
||||
|
||||
This document describes various design points of the FIRRTL dialect, why it is
|
||||
the way it is, and current status and progress. This follows in the spirit of
|
||||
other [MLIR Rationale docs](https://mlir.llvm.org/docs/Rationale/).
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
[The FIRRTL project](https://github.com/chipsalliance/firrtl) is an existing
|
||||
open source compiler infrastructure used by the Chisel framework to lower ".fir"
|
||||
files to Verilog. It provides a number of useful compiler passes and
|
||||
infrastructure that allows the development of domain specific passes. The
|
||||
FIRRTL project includes a [well documented IR specification](https://github.com/chipsalliance/firrtl/blob/master/spec/spec.pdf)
|
||||
that explains the semantics of its IR and the [Antlr
|
||||
grammar](https://github.com/chipsalliance/firrtl/blob/master/src/main/antlr4/FIRRTL.g4)
|
||||
includes some extensions beyond it. This document generally assumes that
|
||||
you've read and have a basic grasp of the IR spec, and it can be occasionally
|
||||
helpful to refer to the grammar.
|
||||
|
||||
The FIRRTL dialect in CIRCT is designed to follow the FIRRTL IR very closely,
|
||||
but does diverge for a variety of reasons. Here we capture some of those
|
||||
reasons and why. They generally boil down to simplifying compiler
|
||||
transformations and taking advantages of the properties of SSA form.
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
The FIRRTL dialect and FIR parser is a generally complete implementation of
|
||||
the FIRRTL specification (including some undocumented features, and "CHIRRTL")
|
||||
and is actively maintained, tracking new enhancements.
|
||||
|
||||
There are some exceptions:
|
||||
|
||||
1) We don't support the `'raw string'` syntax for strings.
|
||||
2) We don't support the `Fixed` types for fixed point numbers, and some
|
||||
primitives associated with them.
|
||||
|
||||
Some of these may be research efforts that didn't gain broad adoption, in which
|
||||
case we don't want to support them. However, if there is a good reason and a
|
||||
community that would benefit from adding support for these, we can do so.
|
||||
|
||||
Type system
|
||||
===========
|
||||
|
||||
Not using standard types
|
||||
------------------------
|
||||
|
||||
At one point we tried to use the integer types in the standard dialect, like
|
||||
`si42` instead of `!firrtl.sint<42>`, but we backed away from this. The reason
|
||||
is that while it originally seemed appealing to use those types, FIRRTL
|
||||
operations generally need to work with "unknown width" integer types (i.e.
|
||||
`!firrtl.sint`).
|
||||
|
||||
Having the known width and unknown width types implemented with two different
|
||||
classes was awkward, led to casting bugs, and prevented having a `FIRRTLType`
|
||||
class that unified all the FIRRTL dialect types.
|
||||
|
||||
Canonicalized Flip Types
|
||||
------------------------
|
||||
|
||||
One significant difference between the CIRCT and Scala implementation of FIRRTL
|
||||
is that the CIRCT implementation of the FIRRTL type system always canonicalizes
|
||||
flip types, according to the following rules:
|
||||
|
||||
1) `flip(flip(x))` == `x`
|
||||
2) `flip(bundle(a,b,c,d))` == `bundle(flip(a), flip(b), flip(c), flip(d))` when
|
||||
the bundle has non-passive type. This forces the flip into the subelements,
|
||||
where it recursively merges with the non-passive subelement.
|
||||
3) `flip(vector(a, n))` == `vector(flip(a), n)` when the vector has non-passive
|
||||
type. This forces the flip into the element type, generally canceling it
|
||||
out.
|
||||
|
||||
The result of this is that FIRRTL types are guaranteed to have a canonical
|
||||
representation, and can therefore be tested for pointer equality.
|
||||
|
||||
As a further consequence of this, the `FlipType::get(x)` method may not return a
|
||||
flip type!
|
||||
|
||||
Operations
|
||||
==========
|
||||
|
||||
`input` and `output` Module Ports
|
||||
---------------------------------
|
||||
|
||||
The FIRRTL specification describes two kinds of ports: `input` and `output`.
|
||||
In the `firrtl.module` declaration we don't track this distinction, instead we
|
||||
just represent `output` ports as having a flipped type compared to its
|
||||
specification.
|
||||
|
||||
**Rationale:**: This simplifies the IR and provides a more canonical
|
||||
representation of the same concept.
|
||||
|
||||
More things are represented as primitives
|
||||
-----------------------------------------
|
||||
|
||||
The FIRRTL dialect describes `mux` and `validif` expressions to be "primitives",
|
||||
whereas the spec and grammar implement them as special kinds of expressions.
|
||||
The only reason we do this is to simplify the implementation. These expression
|
||||
have the same structure as primitives, and modeling them as such allows reuse
|
||||
of the parsing logic instead of duplication of grammar rules.
|
||||
|
Loading…
Reference in New Issue