[Moore] Modify the tests related to the RefType.
Add a wrapper type(moore::RefType) to work for VariableOp/NetOp, ReadOp, and AssignOpBase, and it can wrap any SystemVerilog types. We added RefType in order to introduce Mem2Reg into moore to eliminate the local temporary variables. Meanwhile, we added a new op named moore.extract_ref which is the copy of moore.extract that explicitly works on the ref type. And moore.concat_ref is the copy of moore.concat. Later, we will tweak union/struct ops like moore.struct_create in order to support the ref type.
moore.variable/moore.net will return a result with ref<T>, it's similar to memref.alloca.
Change moore::ReadLValueOp to moore::ReadOp, it's similar to memref.load. Initially, we need moore.read_lvalue only to service for assigmen operations(like +=, *=, etc). However, moore. read is not only for assignment operations but also to take a value with RefType(ref) and return the current value with the nested type(T). For example, a = b + c, moore.read will take b and c(both are ref<T>), and then return a value with the nested type(T).
We think the MooreLValueType and VariableDeclOp(52a71a6) that had been removed eventually found their proper site.
We also divide convertExpression() into convertLvalueExpression() for the LHS of assignments and convertRvalueExpression() for the RHS of assignments. The former will return a value with RefType like ref<i32>, but the latter returns a value without RefType like i32.
Co-authored-by: Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
This changes pre-passes for ExportVerilog to run on HWEmittableModuleLike instead of HWModuleOp. #6977 is going to add a support for SV func op and legalization needed for SV func as well.
HWEmittableModuleLike is a new interface that inherits Emittable+HWModuleLike. I considered to use a trait but we cannot use a trait for pass scheduling so an interface is used.
Add module types and support for ports to the `moore.module` and
`moore.instance` operations. Also add a `moore.output` operation as a
terminator for modules, similar to the HW dialect. Extend ImportVerilog
to generate ports.
The ports on SVModuleOp follow a similar strategy as in HWModuleOp: all
input, inout, and ref ports are passed to the module as inputs and are
carried inside the module as block arguments, while output ports are
assigned by the OutputOp terminator. The Moore dialect reuses the
`hw::ModuleType` but does not use the `inout` direction. Instead, inout
ports will be represented as inputs with a `net<T>` wrapper type, while
ref ports will be wrapped as `ref<T>`.
Instances work identically to the HW dialect: input, inout, and ref port
connections are carried as operands, while output ports are represented
as results.
This commit also adds module and instance port support to the
ImportVerilog conversion. Regular ports are mapped to corresponding
ports on the module with the appropriate direction. Multi-ports, which
are a weird quirk of SystemVerilog that allow multiple ports to be
grouped up and presented to the outside as a single named port, are
split up into individual module ports. This is necessary since this
group can contain ports of different directions.
Inside a module Slang automatically generates local net or variable
declarations for all ports. The user may specify these declarations
themselves when using non-ANSI port lists, which Slang handles properly.
ImportVerilog inserts appropriate continuous assignments to drive the
actual input port value onto the local net or variable declaration, and
to drive the local declaration's value onto the actual output port of
the module. This properly adapts from SystemVerilog's assignable and
connectable ports that feel like nets or variables, to the Moore
dialect's by-value passing of inputs and outputs.
Instances in Slang have expressions connected to their ports. Input
ports lower this expression and directly use the result as an operand.
Output ports lower this expression and drive it through a continuous
assignment inserted after the instance, with the instance's
corresponding result on the right-hand side of the assignment.
Once we have a `ref<T>` type, and later potentially also a `net<T>`
type, the port lowering shall be revisited to ensure that inout and ref
ports are mapped to net and ref types, respectively. The lowering of
expressions connected to ports requires more care to ensure that they
are appropriately lowered to lvalues or rvalues, as needed by the port
direction. A `moore.short_circuit` operation or similar would help to
connect inout ports to the local net declarations in a module, and to
capture `alias` statements.
---------
Co-authored-by: cepheus <buyun.xu@terapines.com>
Co-authored-by: Hailong Sun <hailong.sun@terapines.com>
We stated in a comment that we copy the leading part of the
hierarchical path from the owning module to the start of the
annotation's NLA. But we never actually did that, so this adds (back)
that logic.
Fixes https://github.com/llvm/circt/issues/7125.
This turns the multiple-instantiation error into a warning in
ResolvePaths and LowerClasses. In real designs coming from Chisel
today, we are not yet able to enforce single instantiation. This was
never a requirement of the original way that we handled hierarchical
paths in EmitOMIR, so this removes the requirement for now. Adding it
back is tracked in https://github.com/llvm/circt/issues/7128.
With this change, the ResolvePaths logic was simplified to stop trying
to disambiguate paths in some cases, and instead allow the annotations
to simply convey the user's requested local or hierarchical path. In
LowerClasses, if there are multiple instances, this means we have
ambiguity. In practice, this logic will produce the same outputs as
EmitOMIR, once we fix https://github.com/llvm/circt/issues/7125.
Add a missing check for absent port location information to
`printModuleSignatureNew`. This would cause crashes if the
`--mlir-print-debuginfo` option was set during emission and there are
not port locations available. This mirrors what we already do for
port attributes.
Thanks @uenoku for pointing this out in #7112.
Create these constants as unsigned of unknown width,
instead of s64.
This way when connecting to the address, we don't emit
a connnect between s64 and something like u3
(requiring casts/trim/etc).
Fix a subtle issue in ImportVerilog's statement converter, where a call
to `convertExpression` returning a null value would not properly be
mapped to a `failure()` result.
The original line was `success(<value>)`, which apparently still returns
success even with a null value. Changing this to `failure(!<value>)`
fixes the issue.
While at it, remove all error test cases that simply check for Slang
frontend errors. These things are already tested in Slang. ImportVerilog
should only test for the errors it generates itself.
* [ImportVerilog]Support union types.
* [ImportVerilog]Rename structMember with structLikeMember
* [ImportVerilog] check the type of new Expressions.
* [ImportVerilog]Add value check for new Expressions.
* clang-format modify recommand
* [importVerilog]Remove useless inlcludes
* [ImportVerilog]Add union size and domain
* [ImportVerilog]Give more specefic errors
This has only been used for probes, but without input probes
this is no longer useful or necessary.
The HW-signal hoisting works well (if limited) and has no
known issues[1] but has yet to be used in practice due
primarily to passthroughs being intentional occasionally
and lacking a mechanism to capture or distill this intent
properly (it must be ""optimized"" yet not).
Since this is unused, and lacking traction on the above,
remove from pipeline and delete this for now instead of
having it bitrot and be a maintenance burden while
adding/completing new features.
Lives on in version control history!
[1] FWIW, see https://github.com/llvm/circt/pull/6115 for
both small example and before/after on chipyard, as well
as testing internally back when this was introduced.
Add the `FindInitialVectors` pass to the Arc dialect which finds
isomorphic operations at the same topological rank and groups them into
`arc.vectorize` ops. This is going to be the starting point for later
canonicalizations and optimization steps to improve the vectors and
apply a cost model.
Move the definitions of packed and unpacked struct types from C++ land
into `MooreTypes.td`. This removes a significant amount of complexity.
With all types moved into the TableGen file, a lot of redundant code can
finally be removed and the parsing/printing can be streamlined
significantly.
This change also drops the `StructKind` enum which was used to discern
structs, unions, and tagged unions, although the ImportVerilog
conversion never generated anything besides structs. Once we add support
for unions in the future, the intention is to define new types in ODS
for the unions and reuse the `StructMember`.
Operations defined through TableGen will use a version of type parsing
and printing that strips away the dialect prefix in case this does not
lead to ambiguities. If an op specifies a type like `UnpackedType`, the
generated parser and printer will call `UnpackedType::parse` and
`UnpackedType::print` in order to parse and print that type. This method
usually prints the type without any dialect prefixes, and often also
without the type name itself (as it is obvious given the type).
Add an implementation for `parse` and `print` to `UnpackedType` which
performs this stripped printing. This makes the assembly more compact
and in-line with what MLIR would generate by default if a
TableGen-specified op would use a TableGen-specified type.
This makes the integer flavor of `IntType` look exactly like the builtin
integer type, which will facilitate a future change from Moore's integer
type to the builtin integer. Parsing is unambiguous, since the stripped
form is only used when the type is clear from the op context.