Move FIRRTL dialect attribute definitions into their own file as opposed
to having these live in the same file as type definitions. This is done
in preparation for adding more attributes representing parameters in the
FIRRTL dialect.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit adds basic basic statistics to IMConstantProp based on
mlir::Pass::Statistic. Here, `numFoldedOp`(number of operations
any of whose results are folded) and `numErasedOp` are added.
We can see stats by passing `--pass-statistics` to a command line.
This reduces the size of the extract, which allows recursive
folding into other operations. This shrinks the .v file generated
for RocketCore.fir by 3.3%, from 2994 to 2897 lines.
Since MLIR has gained the `NoTerminator` op trait in the meantime,
remove the LLHD `TerminatorOp` that was originally introduced to get
around a lack of this trait. This requires adjusting the code in a few
places where the terminator is handled explicitly.
Add a new mandatory attribute, "comment", to HWModuleOp that describes a
string comment that should be attached to that module when this module
is emitted by a backend.
Add support for emitting comments associated with HWModuleOps during
ExportVerilog. Use a simple line breaking algorithm to try to respect
the emittedLineLength option when reasonably possible. Respect manual
line breaks that a user may have included in the comment.
Add tests that comments are emitted and that line breaking changes as
expected with changes to emittedLineLength.
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This is a pass which flattens statically sized memories and indexing into them by elaborating multi-dimensional indexing into a tree of multipliers and adders. The motivation of this is currently to be able to lower programs having multi-dimensional memories through the handshake flow, which currently only supports single-dimensional memories when lowering to FIRRTL.
Co-authored-by: Mike Urbach <mikeurbach@gmail.com>
LLHD has the various `llhd.sig.*` operations to extract values from
structs and arrays behind signals. This adds the same for pointers,
which are necessary to capture Moore's output.
s/SharedPipelinedOperatorsProblem/SharedOperatorsProblem
The "pipelined" in the name is kind of redundant because fully-pipelined operators currently are the default assumption in the modeling.
This removes the restriction that a type scope is at the top-level,
and its special-cased visitors. Now, a type scope and its type
declarations can be visited just like any other statements. This
allows them to compose with other region-carrying ops, like ifdef.
Co-authored-by: John Demme <john.demme@microsoft.com>
Avoid calling `getAllModulePortInfos` for getting the name of every port.
The `port id` should be enough to compute the required information.
The `emitTextWithSubstitutions` was calling `getAllModulePortInfos` and
was causing a run-time blow up for a large design with a module > 100 ports,
with symbols on each of them which were used on a `VerbatimOp`.
(In particular, the `EmitOMIR` pass is creating this `VerbatimOp` and
adding a symbol to all the ports in the design.)
`ExportVerilog` runtime for a test case reduced from 580.3 sec to 152.1 sec
Since the limitations on zero-width `APInt`s have disappeared upstream,
the `firrtl.constant` operation can now properly create a zero-width
constant. This is useful since these degenerate types do tend to appear
in real designs.
Add a helper function to `InstanceOp` that replaces the instance with
a new operation that has certain ports entirely dropped. This reflects
the `erasePorts` method that is available on modules as well.
This (fairly monolithic) commit introduces a major overhaul of the Handshake IR syntax. The goal is to reduce verbosity by implementing custom parsers/printers. In doing so, we fold various attributes into being parts of the op syntax. This commits includes changes prior proposed by @stephenneuendorffer. Some work is still needed reducing the verbosity of `handshake.memory` operations, but I've decided to keep this commit as-is. While a major change, this is a mostly syntactical change, and underlying tests remain (largely) unmodified from a functional point of view.
Changes:
- the `handshake` dialect is now the default dialect within `handshake.func` operations, removing the need to prefix every single operation with `handshake.`
- Factors out "isControl" logic to an interface implemented by all handshake operations.
- Most ops now have "size, dataType" and "control" attributes as part of their arguments. This, alongside a shared operation syntax, is leveraged in the parsers. You'll notice that a SOST abbreviation is present in `HandshakeOps.cpp`. SOST being Sized Operation with Single Type.
- The `control` attribute is inferred from the "dataType" of the operation. This means that we no longer have "control = true" littered al over the IR. `control` is assumed whenever `dataType.isa<NoneType>()`.
- Examples added for all handshake ops in the TableGen file.
New syntaxes:
```mlir
%1:2 = fork [2] %0 : i32
%0 = merge %a, %b, %c : i32
%0 = mux %select [%data0, %data1, %data2] {attributes}: index, i32
%0, %idx = control_merge %a, %b, %c : i32
%1 = br %0 : i32
%true, %false = cond_br %cond, %data : i32
sink %data : i32
%0 = constant %ctrl {value = 42 : i32} : i32
%dataToSucc, %addr1ToMem, %addr2ToMem = load [%addr1, %addr2] %dataFromMem, %ctrl : i8, i16, index
%dataToMem, %addrToMem = store [%addr1, %addr2] %dataFromPred , %ctrl : i8, i16, index
%0 = join %a, %b, %c : i32
```
For now, the pipeline is expected to be created after it has been
fully scheduled. Make the II required to reflect this, and add
documentation about this restriction, with a link to an open issue for
discussion.
Add a canonicalization that maps a pad on an invalid value to an invalid
value of the appropriate width. This fixes#2197 and unblocks certain
parts of constant propagation around registers.
This add the necessary Python binding boilerplate to create
PhysicalBounds and PhysicalRegionRef attributes. A new API is added to
System, which inserts a PhysicalRegion. A wrapper class for
PhysicalRegion allows creating a region, adding bounds, and getting a
reference attribute suitable for use with the add_attribute API.
This attribute represents the initiation interval (II) of a
pipeline. For now, it is a simple integer representing the II computed
by the Scheduling infrastructure.
Factor the common base of `CircuitNamespace` into a new `NamespaceBase`
class and add a `ModuleNamespace` which captures the inner symbols of
the ports and declarations within a module. Also rename the header they
are in to `Namespace.h`.
Also, since `llvm::StringSet` internalizes the strings added to it and
`insert()` returns an iterator with the allocated key as a `StringRef`,
change the `newName()` function to return a `StringRef` instead of the
copying `std::string`.
* Revert "Revert "[StaticLogic] Add conversion pass for Affine loop nests. (#2157)""
This reverts commit 0ce0e99b7c.
The new pass wassing missing a CMake dependency on generated files.
This commit adds a new operation `handshake.extmemory` to the handshake dialect, for accessing external memories.
The `handshake.extmemory` operation has identical semantics to the `handshake.memory` operation in terms of how `handshake.load` and `handshake.store` interacts with it.
The op is lowered by creating a handshake interface for each referencing load- and store operation that referenced the `handshake.extmemory`. This is equivalent to taking the interface that would be generated for a similar `handshake.memory` and moving that interface to the top-level module. It is then up to the external environment to define the handshake'd access to the external memory.
This is just the start of a pass, but this is enough to use the
scheduling tools and build a pipeline. At the moment, this doesn't
make use of the schedule, it just sets up a loop template. This is
just enough to lower a single loop and generate the appropriate
induction variable increments. Checkpointing here before moving any
further.
After this, I plan to add a helper class to this pass to answer the
questions we will need to flesh out createStaticLogicPipeline.
My goal is to take something as simple as this and start threading it
through the Calyx lowering to get a very thin path working before
adding support for more cases.
Co-authored-by: Julian Oppermann <oppermann@esa.tu-darmstadt.de>
The dot printing and resource usage printing passes have nothing to do with StandardToHandshake. Passes are moved to a separate file, defining a new Handshake transformation library. Furthermore, dot printing and resource count are split to two separate passes.
Add indexed part-select op to the SV dialect.
Added two ops named `sv.part_select` and `sv.part_select_inout`,
that is lowered to the `indexed part-select` operation in SystemVerilog.
The `sv.part_select` is defined on `Integer` type input and
`sv.part_select_inout` is defined on `inout` type.
Part-select consists of 3 arguments, the input value,
a `width` and a `base` and an optional boolean attribute `decrement`.
The `width` shall be a compile-time constant expression.
The `base` can be a runtime integer expression.
The operation selects bits starting at the `base` and ascending
or descending the bit range. The number of bits selected is equal to the
`width` expression. The bit addressing is always ascending starting from the
`base`, unless the `decrement` attribute is specified.
Part-select is defined in section 11.5.1 of 1800-2017 spec.
This commit ensures that the `argNames` and `resNames` attributes are always present in a `handshake.func` operation. The names are either partially (if some names were already provided to the op during conversion) or fully inferred based on whatever information available when parsing or building the `handshake.func` op.
In doing so, we move signal name generation from handshakeToFIRRTL into being part of the operation itself.
This commit introduces a new interface `NamedIOInterface` for handshake operations. This interface is intended to capture the naming of the in- and output operands of a handshake operation. The interface implements a default naming convention equal to what's currently being used (in#, out#). However, operations can override this interface to provide more specialized naming, such as the `MuxOp` example used in the commit.
The interface is used in in HandshakeToFIRRTL through a class `PortNameGenerator`. This class handles port name generation for all operands which may be lowered into handshake modules. If the source operand was a handshake operand (which implements the `NamedIOInterface`) the interface is used to generate port names. Else, default names are generated.
Add an attribute to `msft.module` specifying the filename in which the
generated SystemVerilog should be placed. In PyCDE, use the module name
as the output filename.
This adds a helper build method to PipelineStageOp, which creates an
empty stage given the result types. Also adds accesors to get blocks
from the PipelineWhileOp and PipelineStageOp. These will be used in a
new pass.
This creates the op with its two single-block regions populated. The
blocks have the correct block arguments and a blank terminator. This
will be helpful for an upcoming pass to use.
This is a very simple start to Tcl support for PhysicalRegions. For
now physical region references and the PlacedInstances making the
reference are just stored in a vector that can be walked to emit the
necessary Tcl. More complex storage and queries for PhysicalRegions
can be added as the need arises.
A PhysicalRegion is a Symbol which can be referred to by ops to be
placed within it. It contains potentially multiple rectangular bounds
on the physical device.
Add an option to decide whether `LowerToHW` should treat non-constant
async reset values as warning or error. Have firtool keep these as
errors unless IMConstProp is disabled, in which case it is highlgy
likely that the user does not care about a full stop of the compilation
and his downstream tools will possibly break for a lot of other reasons.
Extend the FIRRTL dialect such that the `FModuleOp` and `FExtModuleOp`
operations can carry an optional symbol for each of their ports. This is
done in a similar fashion as port names, directions, and annotations, in
that there is a separate array attribute which tracks the symbol for
each port. Since leaving null attributes in the IR is a bit yucky, the
absence of a symbol is encoded as an empty string.
This extends module-like port lists to support the following:
firrtl.module @Foo(
in %a: !firrtl.uint<1> sym @symbolA,
out %b: !firrtl.uint<1> sym @symbolB
)
The change to the IR itself is pretty trivial, but causes a whole bunch
of follow-up fixes in all the places that build or modify modules. These
places are surprisingly numerous and would benefit from some later
cleanup. @youngar has looked into moving the module-like signature into
a separate single attribute, which may go a long way towards making this
prettier.
This also adds tests to ensure port symbols are properly represented
within the FIRRTL dialect, they carry over into the HW dialect as
expected, and that using FIRRTL port symbols in `sv.verbatim` operations
has the intended Verilog output result.
This PR enables a whole bunch of follow-up work to make metadata and
OMIR emission cleaner and more robust in the presence of renaming.