-
Notifications
You must be signed in to change notification settings - Fork 383
[ImportVerilog] Fix missing RValue conversion for struct_create #8988
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
51b4e31 to
d58d3b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Excellent find π! Might be worth extending to the arrays as well π
| if (auto arrayType = dyn_cast<moore::ArrayType>(type)) { | ||
| assert(arrayType.getSize() == elements.size()); | ||
| return moore::ArrayCreateOp::create(builder, loc, arrayType, elements); | ||
| auto elements = convertElements(expr, {}, replCount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to pass the expected element type in for arrays? They might suffer from the same issue as the struct patterns. You could have an std::variant<Type, ArrayRef<Type>> on convertElements to distinguish between a uniform type across all elements, and a specific type per element. Or maybe a separate Type uniformType operand? Or treat expectedTypes of size 1 as the uniform type for all elements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can definitely adapt that. I haven't been able to produce the same bug for Array conversions though - should we still go for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored to use a std::variant<Type, ArrayRef<Type>> and applying it to array elements as well.
Since int-casts are anyway on the "direct and happy path" in convertRvalueExpression and the current code treats IntType assignment over optionally multiple RValues, I left those out as it seems unsafe (e.g. you could concat a 2-bit and two 1-bit expressions to a 4-bit expression, explicit casts would mess this up, probably).
|
|
||
| // CHECK-LABEL: func.func private @StructCreateConversion( | ||
| // CHECK-SAME: [[ARRAY:%.+]]: !moore.array<8 x l8> | ||
| // CHECK-SAME: [[IMM:%.+]]: !moore.l64 | ||
| function void StructCreateConversion (logic [7:0][7:0] array, logic [63:0] immediate); | ||
|
|
||
| typedef struct packed { | ||
| logic [63:0] structField; | ||
| } testStruct; | ||
|
|
||
| // CHECK: [[TS:%.+]] = moore.struct_create [[IMM]] : !moore.l64 -> struct<{structField: l64}> | ||
| testStruct ts = '{structField: immediate}; | ||
| // CHECK: [[CAST:%.+]] = moore.packed_to_sbv [[ARRAY]] : array<8 x l8> | ||
| // CHECK-NEXT: [[TS2:%.+]] = moore.struct_create [[CAST]] : !moore.l64 -> struct<{structField: l64}> | ||
| testStruct ts2 = '{structField: array}; | ||
|
|
||
| endfunction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This exact pattern might also break for arrays. Might be worth a test to see if you can trigger the issue there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think arrays are okay; I tried the following:
logic [7:0][7:0] array;
logic [63:0] ts3 = array;And it gets lowered correctly to:
%arg0: !moore.array<8 x l8>
...
%3 = moore.packed_to_sbv %arg0 : array<8 x l8>
%ts3 = moore.variable %3 : <l64>There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also tried struct -> arrary, which also works.
typedef struct packed {
logic [63:0] structField;
} testStruct;
logic [63:0] immediate;
testStruct ts = '{structField: immediate};
logic [7:0][7:0] ts3 = ts;turns into
%0 = moore.struct_create %arg1 : !moore.l64 -> struct<{structField: l64}>
%ts = moore.variable %0 : <struct<{structField: l64}>>
...
%3 = moore.read %ts : <struct<{structField: l64}>>
%4 = moore.packed_to_sbv %3 : struct<{structField: l64}>
%5 = moore.sbv_to_packed %4 : array<8 x l8>
%ts3 = moore.variable %5 : <array<8 x l8>>There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's very interesting! So might truly just be the structs that have this behavior. π No need to fix stuff that isn't broken π
| assert(intType.getWidth() == elements.size()); | ||
| std::reverse(elements.begin(), elements.end()); | ||
| return moore::ConcatOp::create(builder, loc, intType, elements); | ||
| auto elements = convertElements(expr, {}, replCount); | ||
|
|
||
| if (failed(elements)) | ||
| return {}; | ||
|
|
||
| assert(intType.getWidth() == elements->size()); | ||
| std::reverse(elements->begin(), elements->end()); | ||
| return moore::ConcatOp::create(builder, loc, intType, *elements); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integers might also suffer from this lack of a cast. Maybe we need to convert all elements to simple bit vectors with the same domain as the intType? Probably worth adding a test to see if you can produce the same failure you've seen for structs also for an assignment pattern to an integer π€
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I've tried so far I haven't been able to trigger the same issue with direct-to-int assignment.
I adapted the test code described above for int ts, logic [63:0] ts, and integer ts. All seem to work fine on my end.
b90bb83 to
8ceae1a
Compare
This PR fixes a bug where RValue Conversion is not called when a struct is created from immediate values.
Per IEEE 1800-2023 Section 10.9.2 "Structure assignment patterns", the following assignment pattern is valid:
structType st = '{member: value, memberTwo: valueTwo, ...};
In ImportVerilog, this pattern is recognized and mapped to a moore:StructCreate operator.
Until now the RValue expressions for value and valueTwo were converted without a target type.
This leads to a failure to convert e.g. between ArrayType instances and IntType instances.
This PR fixes this by passing the structType member types to the convertRValueExpression function to have them be cast explicitly.
8ceae1a to
2751081
Compare
|
As far as I can tell I've addressed all comments, please feel free to raise more or point out ones I might've missed. Otherwise I am okay to merge π |
This PR fixes a bug where RValue Conversion is not called when a struct is created from immediate values.
Per IEEE 1800-2023 Section 10.9.2 "Structure assignment patterns", the following assignment pattern is valid:
In ImportVerilog, this pattern is recognized and mapped to a
moore:StructCreateoperator.Until now the RValue expressions for
valueandvalueTwowere converted without a target type.This leads to a failure to convert e.g. between
ArrayTypeinstances andIntTypeinstances.This PR fixes this by passing the structType member types to the convertRValueExpression function to have them be cast explicitly.