For the new concept of Moore dialect, some operations will be defined as memory-related operations. Modeling memref Dialect and LLVM dialect, the operation relationship is as follows:
ReadOp and blockingAssignOp are related to loadOp and storeOp.
VariableOp is related to allocaOp.
However, the operations mentioned below are for basic types. This PR will support nested types in the following way:
VariableOp with nested types is still related to allocaOp (will be replaced with structCreateOp and UnionCreateOp).
structExtractRefOp is related to storeOp.
structExtractOp is related to loadOp.
To implement this:
Since these operations will be lowered to the hw dialect, the design largely refers to the hw dialect.
Add the trait DestructurableAllocationOpInterface for VariableOp.
Add the trait DestructurableAccessorOpInterface for structExtractOp and structExtractRefOp.
Implement the DestructurableTypeInterface for structLikeType and the reftype of structLikeType.
For local variables:
Use the SROA (Scalar Replacement of Aggregates) Pass to destructure all nested-type variables into basic-type variables.
Use the Mem2Reg (Memory to Register) Pass to replace variables imported by SROA with constants.
For global/module-level variables:
When importing Verilog, use structInjectOp rather than blockingAssignOp, because structExtractRefOp has the Destructurable trait, but global variables should not be destructured.
structInjectOp means creating a new struct with new values and other old values.
Use the canonicalizer Pass to fold duplicate injecting same field operations.
Use the canonicalizer Pass to explicitly show new struct creation.
Use the canonicalizer Pass to send source values directly and remove structExtractOp.
Also, remove some unnecessary spaces in other code.
What's more:
Verify that the input of nested-type-related operations should match the field type defined.
To do:
Update the use of struct SSA values referring to the latest structInjectOp SSA values.
Design the method for union types.
Add and support the dbg dialect to keep local variables visible after SROA & Mem2Reg.
Co-authored-by: Théo Degioanni <degiotheo@gmail.com>
Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
Fix an issue where ImportVerilog would currently crash if an unbased,
unsized literal like `'0` is used to initialize or assign to a packed
struct. Instead, the integer literal should be constructed and then
converted to the packed aggregate type. In a later pass, this conversion
can be lowered to a more careful `moore.struct_create`.
[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>
* [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
* [ImportVerilog] Support member-access expression
Support member-access expression.
Add container multiSymbolValue for multi-symbols pointing one value.
Signed-off-by: mingzheTerapines <mingzhe.zhang@terapines.com>
* [ImportVerilog] Support member-access expression
Separate two containers and their annotations.
* [ImportVerilog] Support member-access expression3
use auto instead of const slang::ast::Expression *
declare concatName with expr.member.name
* [ImportVerilog] Support member-access expression4
Simplfy string allocation.
* [ImportVerilog] Support member-access expression
The signing of unpacked structures is not allowed.- IEEE Standard
* [ImportVerilog] Support member-access expression6
Add packed unsigned struct occasion for testing.
* [ImportVerilog] Support Union Type
Support Union Type
Modify uniont tyep to event type as error type example.
* [ImportVerilog]Add errors example
Add error example for unpacked union.
* [ImportVerilog] Add strucfield op
Define a struct field access op that can represent accesses into struct fields.
* [ImportVerilog] Add struct inject and extract op
Add struct inject and extract op.
Remove union support.
* [ImportVerilog] Support memberaccess
* Removed some useless include.
* fix test error
* Fix errors.sv
* remove space.
---------
Signed-off-by: mingzheTerapines <mingzhe.zhang@terapines.com>
The core type most SystemVerilog expressions are interested in and
operate on is a "simple bit vector type". These are individual integer
atoms like `bit` or `logic`, integral types like `int`, or packed arrays
with a single dimension and an integer atom inner type, like
`bit [42:0]`. So in a nutshell, simple bit vector types are MLIR's `i42`
in the two-valued (`bit`) case, or the four-valued equivalent (`logic`).
Up until this point, the Moore dialect reflected this pattern by
providing and `IntType` for the integer atoms like `bit` and `int`, and
using the `PackedRangeDim` for single dimension vectors of `bit`. A
`SimpleBitVectorType` helper struct would then summarize the _actual_
bit vector that was expressed by the packed range and integer atom. This
makes working with the types in TableGen files very annoying, since the
thing you are actually interested in -- the simple bit vector -- is not
a propery MLIR type, but more like a helper struct on the side.
This commit rips out the existing `IntType` and its composition with a
packed array dimension, and replaces it with a proper simple bit vector
type that is actually an MLIR type. As a result, SystemVerilog types
like `int unsigned`, `bit [42:0]`, `reg`, `logic signed [31:0]`, or
`integer` are all translated into the same MLIR type. This new simple
bit vector MLIR type retains the `IntType` name, and prints as
`!moore.i42` or `!moore.l42`, depending on whether it is a two-valued or
four-valued integer. Single `bit` and `logic` atoms become `i1` and `l1`
respectively.
This makes the Moore type system a lot easier to work with and removes
a lot of unnecessary noise. Operations can now simply use
`llvm::isa<IntType>` to check if a value is a simple bit vector.
Instead of annotating types as signed or unsigned, make Moore dialect
types signless and move the signedness into operations. This affects
division, modulus/remainder, and comparison operations. These now come
in a signed and unsigned flavor. ImportVerilog consults the Slang AST
type to determine signedness when creating Moore dialect ops. The Moore
types themselves now no longer carry any sign information. This
significantly simplifies the dialect and takes the type system one step
closer towards having just a basic two- and four-valued bit vector type.
Add support for pre and post increment and decrement expressions, like
`x++` and `--x`, as well as assign expressions, like `a += 5`. Slang
represents these assignments as `Assign(a, Add(LValueRef, 5))` in the
AST. The `LValueRef` node contextually refers to the parent assignment's
left-hand side. To deal with this, also add a corresponding lvalue stack
to the conversion context. Assignments push and pop their lvalues onto
and off of this stack.
These expressions require a mechanism in the IR to express _when_ a
variable is read. To capture this, add a new `moore.read_lvalue` op.
It currently looks like an identity operation with a `MemRead` side
effect. Further down the road, we may want to introduce a proper
reference type for variables, ports, nets, and other things, and have
`read_lvalue` and the various assigns operate on that type instead. This
sets the foundation for that.
Co-authored-by: Hailong Sun <hailong.sun@terapines.com>
Co-authored-by: ShiZuoye <albertethon@163.com>
Co-authored-by: hunterzju <hunter_ht@zju.edu.cn>
Co-authored-by: Anqi Yu <anqi.yu@terapines.com>
Extend the `ImportVerilog` conversion to support most of the basic
expressions that commonly appear in SystemVerilog input files. Also add
the correpsonding expression ops to the Moore dialect, and finally get
rid of the old MIR expressions file which is now obsolete.
Thanks @hailongSun2000 and @albertethon for doing a lot of the leg work
to get expression support in!
Co-authored-by: Hailong Sun <hailong.sun@terapines.com>
Co-authored-by: ShiZuoye <albertethon@163.com>
Co-authored-by: Martin Erhart <maerhart@outlook.com>
Add continuous, blocking, and non-blocking assignments to the Moore
dialect. These represent the corresponding constructs in SystemVerilog.
Add a `ScopedHashTable` to the ImportVerilog conversion context and add
variable declarations to it. This allows expression conversion to
resolve name expressions to the MLIR value that was generated for the
corresponding declaration. The Slang AST node pointer itself is used as
a lookup key, since the AST already has all names resolved.
Add a basic expression handling mechanism to the ImportVerilog
conversion. A new `convertExpression` entry point calls an `ExprVisitor`
to convert expression nodes in the Slang AST to the corresponding MLIR
operations. This currently only supports name expressions, which simply
looks up the converted MLIR value for whatever the name was resolved to,
and blocking and non-blocking assignments.
Extend the module conversion to properly handle continuous assignments
at the module level.
Thanks @albertethon, @hailongSun2000, and @angelzzzzz for the help to
get this started.
Co-authored-by: ShiZuoye <albertethon@163.com>
Co-authored-by: Hailong Sun <hailong.sun@terapines.com>
Co-authored-by: Anqi Yu <anqi.yu@terapines.com>