Commit Graph

32 Commits

Author SHA1 Message Date
Fabian Schuiki d42d00e6ee
[ImportVerilog] Add support for $stop/$finish/$exit (#7634)
Add support for the simulation control system tasks `$stop`, `$finish`,
and `$exit`. Also add corresponding ops to the Moore dialect that handle
the orthogonal pieces of functionality represented by these tasks.
2024-09-26 22:06:24 -07:00
Fabian Schuiki 24715e4d31
[ImportVerilog] Refactor constant materialization; NFC
Factor the materialization of Slang `SVInt`s and `ConstantValue`s out
into a helper function on the import context. This will allow for easier
access to constant materialization from outside the expression
conversion code.
2024-09-24 16:48:17 -07:00
Fabian Schuiki d71e6e30c3
[Moore] Improve WaitEventOp, lower to LLHD (#7518)
Rework the `moore.wait_event` op to be able to accurately model the
semantics of SystemVerilog's `@...` event control statements. The op now
has a body region which is executed to detect a relevant change in one
or more interesting values. A new `moore.detect_event` op serves as the
mechanism to encode whether a posedge, negedge, both, or any change at
all on a value should be detected as an event.

Based on this new `moore.wait_event` op we can properly convert most of
the event control statements in `ImportVerilog` to a corresponding MLIR
op. Delay control like `#1ns` is not handled yet.

In the MooreToCore conversion this new op allows us to properly generate
`llhd.wait` operations at the right place that suspend process execution
until an interesting event has occurred. This now also allows us to
support almost all SystemVerilog processes in the lowering. The only
missing ones are `always_comb` and `always_latch` which require an
implicit `llhd.wait` to be inserted. @maerhart has a version of that
lowering almost ready though.

This commit also adds an `llhd.final` op in order to be able to lower
`final` procedures.

Fixes #7482.

Co-authored-by: Martin Erhart <maerhart@outlook.com>
2024-08-16 13:14:12 -07:00
Fabian Schuiki 42401036d8
[MooreToCore] Support ConditionalOp (#7501)
Add a lowering pattern from `moore.conditional` to `scf.if`. This
currently relies on the condition being a two-valued integer after
lowering. Once we support four-valued integers at the core dialect
level, the lowering of `moore.conditional` will become a lot more
complicated.
2024-08-10 11:46:18 -07:00
Will Dietz b3a54e3557
LLVM bump to include upstream verifier performance fix. (#7496)
Bump LLVM [1] to include an upstream verifier performance fix [2].

This required two minor fixes to CIRCT:

  * [HW] Qualify types for safer use in other dialects.
  * [ImportVerilog] Fix ternary with diff types, both become Value.

[1]: 5689cccead...c69b8c445a
[2]: 7a98071da2
2024-08-09 19:56:27 -04:00
Fabian Schuiki d8c1f6dbad
[Moore] Support four-valued integers in ConstantOp (#7463)
Extend Moore's `ConstantOp` to use the new `FVIntegerAttr`, which now
allows us to materialize four-valued integer constants in the IR. Also
adjust ImportVerilog to finally properly captured integer literals with
X and Z bits.

With this change, `circt-verilog` is now capable of fully parsing the
Snitch RISC-V core used as a benchmark in the original LLHD paper at
PLDI 2020, and to produce a corresponding blob of IR.

Examples of the extended op:

    moore.constant 0 : i32
    moore.constant 2 : i2
    moore.constant -2 : i2
    moore.constant h123456789ABCDEF0 : i64
    moore.constant h123456789ABCDEF0XZ : l72
    moore.constant b1010 : i8
    moore.constant b1010XZ : l8
2024-08-08 10:38:33 -07:00
Fabian Schuiki 7df593d081
[ImportVerilog] Fix value domain mismatch for logic/ternary ops
Fix an issue in the mapping of the logical `&&`, `||`, `->`, and `<->`
operators, where the left and right-hand side could have different value
domains in the AST (one `logic`, one `bit`).

Similarly, fix an issue with the `?:` ternary operator where the true
and false expressions could have different but cast-compatible types.
2024-08-04 12:33:37 -07:00
Fabian Schuiki e95e92dd19
[ImportVerilog] Add rvalue assignment pattern support (#7428)
Add support for assignment patterns like `'{42, 9001}` in rvalue
position. These are roughly SystemVerilog's equivalent of
`struct_create` and `array_create`. This commit also adds an
`array_create` op to support assignment patterns for arrays.
2024-08-04 11:01:00 -07:00
Fabian Schuiki 272af6c158
[ImportVerilog] Add missing conversions, various fixes
Add missing conversions for cases where the Slang AST has expressions
operating directly on packed structs/arrays, but the Moore IR expects
a conversion to a simple bit vector type.

Also clean up a few things and remove an invalid `struct_inject`
conversion.
2024-08-02 11:37:43 -07:00
wenhu1024 41841ebb86
[ImportVerilog] Support for String Types, String Literals (#7403)
Co-authored-by: itaras20 <ian.taras20@gmail.com>
2024-07-31 13:52:11 +08:00
Fabian Schuiki b7b82fda8b
[Moore] Clean up struct ops and add missing tests (#7392)
Rework the Moore dialect operations that manipulate struct values. These
are intended to operate on `StructType` and `UnpackedStructType` values
directly, but were defined in ODS as operating on references to structs.
This was likely a hold-over from early development where we were still
figuring out the distinction between ref types and value types in SV.

This commit adjusts the struct ops such that they actually operate on
struct values instead of references to structs. It also moves more
operand constraints into ODS and simplifies the op verifiers by
factoring out some common code into helper functions.

Enhance the `struct_inject` canonicalizer to also consider
`struct_create` operations as part of the inject chain. This allows an
initial `struct_create` that is modified by a subsequent inject to be
canonicalized into a new `struct_create` with updated values.

Add missing basic and error tests for the struct-related ops, and
simplify the variable destructuring test by removing unrelated
operations.

Also fixes an issue in variable op destructuring where a variable with
initial value would have its initial value discarded during
destructuring. Initial values now prevent destructuring. Alternatively,
we may choose to insert appropriate `struct_extract` ops to destructure
the initial value in the future.
2024-07-30 12:26:08 -07:00
Fabian Schuiki 756166e6ee
[ImportVerilog] Support the power operator (#7395)
Add support for the `**` operator.
2024-07-27 14:05:55 -07:00
Fabian Schuiki e02c0150df
[ImportVerilog] Support large integer constants (#7391)
Remove the 64 bit limitation on SV integer constants and allow for
arbitrary Slang `SVInt`s to be converted to MLIR `APInt`s.
2024-07-26 15:19:14 -07:00
Hailong Sun 6a634ae429
[Moore] Distinguish the dynamic and constant extract. (#7340)
Divide the extract into a dynamic extract named moore.dyn_extract and a constant extract named moore.extract, the former has a variable as its low bit like arr[x], but the latter has a constant value as its low bit like arr[1].

Co-authored-by: Fabian Schuiki <fabian@schuiki.ch>
2024-07-24 14:28:53 +08:00
fzi-hielscher 31145f72bb
[ImportVerilog] Fix use after free (#7368) 2024-07-22 22:23:08 +02:00
Fabian Schuiki 1345859484
[ImportVerilog] Add basic function support (#7349)
Add basic support for function definitions and calls to such functions.

Input function arguments are currently passed into the function by
value, while output, inout, ref, and const ref arguments are passed by
reference at the moment. Later on we may want to be more faithful to the
SV spec and make output and inout arguments also pass by value.

Calls to void functions are slightly strange in that they don't really
have a result value, but the `convertExpression` function really wants
a valid `Value` to return. To work around this, these calls generate an
additional `!moore.void` value using `unrealized_conversion_cast`, which
gets deleted again by the statement conversion code.
2024-07-22 11:31:28 -07:00
Fabian Schuiki 846139b8ba
[ImportVerilog] Allow enum variants in expressions (#7339)
Add support for enum variants in expressions. Until now, ImportVerilog
would emit a "unknown name" diagnostic when an enum variant is used in
an expression. This is due to the lowering of named value expressions
simply checking whether an MLIR value is present in the `valueSymbols`
table for the referenced symbol name. This works for variables which
create dedicated declarations, but not for enum variants which
potentially live outside the current module's scope.

Instead, ImportVerilog will now check if the named value is a constant,
for example a parameter or an enum variant, and materialize that
constant directly as a `moore.constant` op. This will also be able to
deal with parameters declared inside of packages, for which the table of
value symbols of the current module does not contain any value. (Local
parameters inside the module generate a `moore.named_constant` op that
is present in the table.)
2024-07-18 10:56:57 -07:00
Fabian Schuiki a3b94620f0
[ImportVerilog] Handle $signed/$unsigned system tasks (#7337)
Handle calls to the `$signed` and `$unsigned` system tasks by simply
passing through the argument. The casting is handled by Slang during
type checking and is materialized as a type conversion node in the AST.
The call itself has no function after that.

The `visitCall` function is going to be the place to add handling for
other system calls in the future. IEEE 1800-2017 section 20 defines a
fairly substantial list of builtin system tasks. Most of these will want
to have a dedicated `moore.builtin.*` op in the future.
2024-07-18 09:55:48 -07:00
mingzheTerapines b7afc536db
[ImportVerilog] [SROA] [Mem2Reg][Canonicalizers]Support Passes for Nested Type (#7158)
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>
2024-07-18 10:56:37 +08:00
Fabian Schuiki cdc9964385
[ImportVerilog] Fix unbased unsized literals of packed aggregate type (#7336)
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`.
2024-07-17 15:39:54 -07:00
Hailong Sun e2b4cb9c72
[ImportVerilog] Distinguish the index up or down on the range selection. (#7280) 2024-07-10 13:21:04 +08:00
Hailong Sun 69085ea0e5
[Moore] Tweak Variable and ReadLValue ops. (#7095)
[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>
2024-06-07 11:08:17 +08:00
Anqi Yu c76eb120d6
[ImportVerilog] Add conditional operator. (#6950) 2024-06-05 10:44:55 +08:00
mingzheTerapines 00edb48ed5
[ImportVerilog][Moore] Support union type (#7084)
* [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
2024-05-29 13:23:20 +08:00
Anqi Yu 851a1de172
[ImportVerilog] Support set membership operator. (#7066) 2024-05-23 14:32:47 +08:00
mingzheTerapines 9006a44b07
[ImportVerilog] Support member-access expression (#7039)
* [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>
2024-05-23 10:51:21 +08:00
Fabian Schuiki 6a2b628129
[Moore] Make simple bit vectors a proper MLIR type (#7011)
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.
2024-05-09 15:52:20 -07:00
Fabian Schuiki 63c794f24e
[Moore] Move signedness from types into ops
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.
2024-05-08 15:52:10 -07:00
Hailong Sun 80c6602d37
[ImportVerilog] Add replicate and extract operations. (#6906) 2024-04-22 09:57:29 +08:00
Fabian Schuiki 8ec05233d1
[ImportVerilog] Add assign and pre/post increment/decrement expressions (#6859)
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>
2024-03-22 00:28:24 -07:00
Fabian Schuiki c970974165
[ImportVerilog] Add basic expressions (#6788)
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>
2024-03-13 16:57:53 -07:00
Fabian Schuiki 5c9fb8f3a7
[ImportVerilog] Add assignment statements (#6773)
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>
2024-03-02 20:55:36 -08:00