[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>
This commit is contained in:
mingzheTerapines 2024-05-23 10:51:21 +08:00 committed by GitHub
parent 8a8fd29595
commit 9006a44b07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 146 additions and 1 deletions

View File

@ -17,6 +17,7 @@ include "mlir/IR/RegionKindInterface.td"
include "mlir/IR/SymbolInterfaces.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/MemorySlotInterfaces.td"
// Base class for the operations in this dialect.
class MooreOp<string mnemonic, list<Trait> traits = []> :
@ -783,9 +784,111 @@ def ExtractOp : MooreOp<"extract"> {
let arguments = (ins UnpackedType:$input, UnpackedType:$lowBit);
let results = (outs UnpackedType:$result);
let assemblyFormat = [{
$input `from` $lowBit attr-dict `:`
$input `from` $lowBit attr-dict `:`
type($input) `,` type($lowBit) `->` type($result)
}];
}
def StructCreateOp : MooreOp<"struct_create", [SameOperandsAndResultType]> {
let summary = "Struct Create operation";
let description = [{
A structure represents a collection of data types
that can be referenced as a whole, or the individual data types
that make up the structure can be referenced by name.
By default, structures are unpacked, meaning that there is
an implementation-dependent packing of the data types.
Unpacked structures can contain any data type.
See IEEE 1800-2017 § 7.2 "Structures"
Example:
```
struct { bit [7:0] opcode; bit [23:0] addr; }IR;
IR.opcode = 1; // set field in IR.
// anonymous structure
// defines variable IR
typedef struct {
bit [7:0] opcode;
bit [23:0] addr;
} instruction; // named structure type
instruction IR; // define variable
```
See IEEE 1800-2017 § 7.2. "Structures".
}];
let arguments = (ins UnpackedType:$structName);
let results = (outs UnpackedType:$result);
let hasCustomAssemblyFormat = 1;
let assemblyFormat = [{
$structName attr-dict `:` type($structName)
}];
}
def StructExtractOp : MooreOp<"struct_extract"> {
let summary = "Struct Extract operation";
let description = [{
Structures can be converted to bits preserving the bit pattern.
In other words, they can be converted back to the same value
without any loss of information. When unpacked data are converted
to the packed representation, the order of the data in the packed
representation is such that the first field in the structure
occupies the MSBs. The effect is the same as a concatenation of
the data items (struct fields or array elements) in order.
The type of the elements in an unpacked structure or array
shall be valid for a packed representation in order to be
cast to any other type, whether packed or unpacked.
See IEEE 1800-2017 § 6.24.1 "Cast operator"
Example:
```
typedef struct {
int addr = 1 + constant;
int crc;
byte data [4] = '{4{1}};
} packet1;
packet1 p1; // initialization defined by the typedef.
// p1.crc will use the default value for an int
```
See IEEE 1800-2017 § 7.2.1 "Assigning to structures".
}];
let arguments = (ins StrAttr:$memberName, UnpackedType:$structName);
let results = (outs UnpackedType:$result);
let assemblyFormat = [{
$structName `,` $memberName attr-dict `:`
type($structName) `->` type($result)
}];
}
def StructInjectOp : MooreOp<"struct_inject"> {
let summary = "Struct Field operation";
let description = [{
A structure can be assigned as a whole and passed to
or from a subroutine as a whole. Members of a structure
data type can be assigned individual default member
values by using an initial assignment with the declaration
of each member. The assigned expression shall be
a constant expression.
See IEEE 1800-2017 § 7.2.2 "Assigning to structures"
Example:
```
typedef struct {
int addr = 1 + constant;
int crc;
byte data [4] = '{4{1}};
} packet1;
packet1 p1; // initialization defined by the typedef.
// p1.crc will use the default value for an int
```
See IEEE 1800-2017 § 7.2. "Assigning to structures".
}];
let arguments = (ins UnpackedType:$LHS, StrAttr:$memberName,
UnpackedType:$RHS);
let results = (outs UnpackedType:$result);
let assemblyFormat = [{
$LHS `,` $memberName `,` $RHS
attr-dict `:` type($LHS) type($RHS) `->` type($result)
}];
}
#endif // CIRCT_DIALECT_MOORE_MOOREOPS

View File

@ -428,6 +428,13 @@ struct ExprVisitor {
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
}
Value visit(const slang::ast::MemberAccessExpression &expr) {
return builder.create<moore::StructExtractOp>(
loc, context.convertType(*expr.type),
builder.getStringAttr(expr.member.name),
context.convertExpression(expr.value()));
}
/// Emit an error for all other expressions.
template <typename T>
Value visit(T &&node) {

View File

@ -300,6 +300,9 @@ module Expressions;
// CHECK: %y = moore.variable : !moore.l1
// CHECK: %vec_1 = moore.variable : !moore.l32
// CHECK: %vec_2 = moore.variable : !moore.l32
// CHECK: %myStruct = moore.variable : !moore.packed<struct<{a: i32, b: i32}>>
// CHECK: %myStruct2 = moore.variable : !moore.packed<struct<{c: struct<{a: i32, b: i32}>, d: struct<{a: i32, b: i32}>}>>
// CHECK: %myStruct3 = moore.variable : !moore.packed<struct<{a: i32, b: i32}>>
int a, b, c;
int unsigned u, w;
bit [1:0][3:0] v;
@ -311,6 +314,12 @@ module Expressions;
logic [0:31] vec_2;
bit [4:1] arr [1:3][2:7];
bit [3:2] s;
typedef struct packed signed {int a, b;} structTemp;
structTemp myStruct;
typedef struct packed signed {structTemp c,d;} structTemp2;
structTemp2 myStruct2;
typedef struct packed unsigned {int a, b;} structTemp3;
structTemp3 myStruct3;
initial begin
// CHECK: moore.constant 0 : !moore.i32
@ -606,6 +615,32 @@ module Expressions;
// CHECK: [[TMP2:%.+]] = moore.add [[A_ADD]], [[TMP1]]
// CHECK: moore.blocking_assign %a, [[TMP2]]
a += (a *= a--);
// CHECK: [[A_STRUCT:%.+]] = moore.struct_extract %myStruct, "a" : !moore.packed<struct<{a: i32, b: i32}>> -> !moore.i32
// CHECK: moore.blocking_assign [[A_STRUCT]], %a : !moore.i32
myStruct.a = a;
// CHECK: [[B_STRUCT:%.+]] = moore.struct_extract %myStruct, "b" : !moore.packed<struct<{a: i32, b: i32}>> -> !moore.i32
// CHECK: moore.blocking_assign %b, [[B_STRUCT]] : !moore.i32
b = myStruct.b;
// CHECK: [[C_STRUCT:%.+]] = moore.struct_extract %myStruct2, "c" : !moore.packed<struct<{c: struct<{a: i32, b: i32}>, d: struct<{a: i32, b: i32}>}>> -> !moore.packed<struct<{a: i32, b: i32}>>
// CHECK: [[D_STRUCT:%.+]] = moore.struct_extract [[C_STRUCT]], "a" : !moore.packed<struct<{a: i32, b: i32}>> -> !moore.i32
// CHECK: moore.blocking_assign [[D_STRUCT]], %a : !moore.i32
myStruct2.c.a = a;
// CHECK: [[E_STRUCT:%.+]] = moore.struct_extract %myStruct2, "d" : !moore.packed<struct<{c: struct<{a: i32, b: i32}>, d: struct<{a: i32, b: i32}>}>> -> !moore.packed<struct<{a: i32, b: i32}>>
// CHECK: [[F_STRUCT:%.+]] = moore.struct_extract [[E_STRUCT]], "b" : !moore.packed<struct<{a: i32, b: i32}>> -> !moore.i32
// CHECK: moore.blocking_assign %b, [[F_STRUCT]] : !moore.i32
b = myStruct2.d.b;
// CHECK: [[G_STRUCT:%.+]] = moore.struct_extract %myStruct3, "a" : !moore.packed<struct<{a: i32, b: i32}>> -> !moore.i32
// CHECK: moore.blocking_assign [[G_STRUCT]], %a : !moore.i3
myStruct3.a = a;
// CHECK: [[H_STRUCT:%.+]] = moore.struct_extract %myStruct3, "b" : !moore.packed<struct<{a: i32, b: i32}>> -> !moore.i32
// CHECK: moore.blocking_assign %b, [[H_STRUCT]] : !moore.i32
b = myStruct3.b;
end
endmodule