[ExportVerilog] Make `hoistNonSideEffectExpr` hoist inout chains (#2405)

This commit fixes the crash of disallowLocalVars mode for the IR with
array_index_inout/struct_field_inout and sv.read_inout.

Currently `hoistNonSideEffectExpr` doesn't hoist array_index_inout
and struct_field_inout because they are considered to be lvalues.
This is true only if they are not read. They might become rvalues
afterwards so we have to hoist them as well as read_inout op.
This commit is contained in:
Hideto Ueno 2022-01-10 06:50:54 +09:00 committed by GitHub
parent 31d5b4864b
commit 6be754b850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 4 deletions

View File

@ -309,9 +309,11 @@ static bool rewriteSideEffectingExpr(Operation *op) {
/// non-constant expressions out to the top level so they don't turn into local
/// variable declarations.
static bool hoistNonSideEffectExpr(Operation *op) {
// Never hoist "always inline" expressions - they will never generate a
// temporary and in fact must always be emitted inline.
if (isExpressionAlwaysInline(op) && !isa<sv::ReadInOutOp>(op))
// Never hoist "always inline" expressions except for inout stuffs - they will
// never generate a temporary and in fact must always be emitted inline.
if (isExpressionAlwaysInline(op) &&
!(isa<sv::ReadInOutOp>(op) ||
op->getResult(0).getType().isa<hw::InOutType>()))
return false;
// Scan to the top of the region tree to find out where to move the op.

View File

@ -153,4 +153,23 @@ hw.module @EmittedDespiteDisallowed(%clock: i1, %reset: i1) {
hw.output
}
// CHECK-LABEL: module ReadInoutAggregate(
hw.module @ReadInoutAggregate(%clock: i1) {
%register = sv.reg : !hw.inout<array<1xstruct<a: i32>>>
sv.always posedge %clock {
%c0_i16 = hw.constant 0 : i16
%false = hw.constant false
%0 = sv.array_index_inout %register[%false] : !hw.inout<array<1xstruct<a: i32>>>, i1
%1 = sv.struct_field_inout %0["a"] : !hw.inout<struct<a: i32>>
%2 = sv.read_inout %1 : !hw.inout<i32>
%3 = comb.extract %2 from 0 : (i32) -> i16
%4 = comb.concat %c0_i16, %3 : i16, i16
sv.passign %1, %4 : i32
}
// DISALLOW: localparam [[T:.+]] = 1'h0;
// DISALLOW-NEXT: wire [31:0] [[READ:.+]] = register{{\[}}[[T]]{{\]}}.a;
// DISALLOW-NEXT: wire [31:0] [[CONCAT:.+]] = {16'h0, [[READ]][15:0]};
// DISALLOW-NEXT: always @(
// DISALLOW-NEXT: register{{\[}}[[T]]{{\]}}.a <= [[CONCAT]];
hw.output
}