mirror of https://github.com/llvm/circt.git
[ImportVerilog] Fix bit slicing into variables declared with offset (#8190)
This commit is contained in:
parent
3ef66cfdff
commit
c4e8859620
|
@ -708,6 +708,8 @@ def SubOp : BinaryOpBase<"sub"> {
|
|||
|
||||
See IEEE 1800-2017 § 11.4.3 "Arithmetic operators".
|
||||
}];
|
||||
|
||||
let hasFolder = 1;
|
||||
}
|
||||
|
||||
def MulOp : BinaryOpBase<"mul", [Commutative]> {
|
||||
|
|
|
@ -430,23 +430,54 @@ struct RvalueExprVisitor {
|
|||
return builder.create<moore::ReplicateOp>(loc, type, value);
|
||||
}
|
||||
|
||||
Value getSelectIndex(Value index, const slang::ConstantRange &range) const {
|
||||
auto indexType = cast<moore::UnpackedType>(index.getType());
|
||||
auto bw = std::max(llvm::Log2_32_Ceil(std::abs(range.upper())),
|
||||
indexType.getBitSize().value());
|
||||
auto intType =
|
||||
moore::IntType::get(index.getContext(), bw, indexType.getDomain());
|
||||
|
||||
if (range.isLittleEndian()) {
|
||||
if (range.lower() == 0)
|
||||
return index;
|
||||
|
||||
Value newIndex =
|
||||
builder.createOrFold<moore::ConversionOp>(loc, intType, index);
|
||||
Value offset =
|
||||
builder.create<moore::ConstantOp>(loc, intType, range.lower());
|
||||
return builder.createOrFold<moore::SubOp>(loc, newIndex, offset);
|
||||
}
|
||||
|
||||
if (range.upper() == 0)
|
||||
return builder.createOrFold<moore::NegOp>(loc, index);
|
||||
|
||||
Value newIndex =
|
||||
builder.createOrFold<moore::ConversionOp>(loc, intType, index);
|
||||
Value offset =
|
||||
builder.create<moore::ConstantOp>(loc, intType, range.upper());
|
||||
return builder.createOrFold<moore::SubOp>(loc, offset, newIndex);
|
||||
}
|
||||
|
||||
// Handle single bit selections.
|
||||
Value visit(const slang::ast::ElementSelectExpression &expr) {
|
||||
auto type = context.convertType(*expr.type);
|
||||
auto value = context.convertRvalueExpression(expr.value());
|
||||
if (!type || !value)
|
||||
return {};
|
||||
auto range = expr.value().type->getFixedRange();
|
||||
if (auto *constValue = expr.selector().constant) {
|
||||
assert(!constValue->hasUnknown());
|
||||
assert(constValue->size() <= 32);
|
||||
|
||||
auto lowBit = constValue->integer().as<uint32_t>().value();
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, lowBit);
|
||||
return builder.create<moore::ExtractOp>(loc, type, value,
|
||||
range.translateIndex(lowBit));
|
||||
}
|
||||
auto lowBit = context.convertRvalueExpression(expr.selector());
|
||||
if (!lowBit)
|
||||
return {};
|
||||
return builder.create<moore::DynExtractOp>(loc, type, value, lowBit);
|
||||
return builder.create<moore::DynExtractOp>(loc, type, value,
|
||||
getSelectIndex(lowBit, range));
|
||||
}
|
||||
|
||||
// Handle range bits selections.
|
||||
|
@ -509,9 +540,12 @@ struct RvalueExprVisitor {
|
|||
else
|
||||
dynLowBit = context.convertRvalueExpression(expr.left());
|
||||
}
|
||||
auto range = expr.value().type->getFixedRange();
|
||||
if (leftConst && rightConst)
|
||||
return builder.create<moore::ExtractOp>(loc, type, value, constLowBit);
|
||||
return builder.create<moore::DynExtractOp>(loc, type, value, dynLowBit);
|
||||
return builder.create<moore::ExtractOp>(
|
||||
loc, type, value, range.translateIndex(constLowBit));
|
||||
return builder.create<moore::DynExtractOp>(
|
||||
loc, type, value, getSelectIndex(dynLowBit, range));
|
||||
}
|
||||
|
||||
Value visit(const slang::ast::MemberAccessExpression &expr) {
|
||||
|
|
|
@ -1188,6 +1188,18 @@ LogicalResult PowUOp::canonicalize(PowUOp op, PatternRewriter &rewriter) {
|
|||
return failure();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SubOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
OpFoldResult SubOp::fold(FoldAdaptor adaptor) {
|
||||
if (auto intAttr = dyn_cast_or_null<FVIntegerAttr>(adaptor.getRhs()))
|
||||
if (intAttr.getValue().isZero())
|
||||
return getLhs();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TableGen generated logic.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -693,6 +693,10 @@ module Expressions;
|
|||
logic y;
|
||||
// CHECK: %vec_1 = moore.variable : <l32>
|
||||
logic [31:0] vec_1;
|
||||
// CHECK: %vec_1a = moore.variable : <l17>
|
||||
logic [31:15] vec_1a;
|
||||
// CHECK: %vec_1b = moore.variable : <l32>
|
||||
logic [-31:0] vec_1b;
|
||||
// CHECK: %vec_2 = moore.variable : <l32>
|
||||
logic [0:31] vec_2;
|
||||
// CHECK: %vec_3 = moore.variable : <l16>
|
||||
|
@ -890,7 +894,7 @@ module Expressions;
|
|||
// CHECK: moore.extract [[TMP1]] from 1 : l32 -> l3
|
||||
y = vec_1[3:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 2 : l32 -> l2
|
||||
// CHECK: moore.extract [[TMP1]] from 29 : l32 -> l2
|
||||
y = vec_2[2:3];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %d : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x : <i1>
|
||||
|
@ -907,8 +911,56 @@ module Expressions;
|
|||
// CHECK: moore.extract [[TMP1]] from 15 : l32 -> l1
|
||||
y = vec_1[15+:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2 : <l32>
|
||||
// CHECK: moore.extract [[TMP1]] from 0 : l32 -> l1
|
||||
// CHECK: moore.extract [[TMP1]] from 31 : l32 -> l1
|
||||
y = vec_2[0+:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2 : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.constant 31 : l32
|
||||
// CHECK: [[TMP4:%.+]] = moore.sub [[TMP3]], [[TMP2]] : l32
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP4]] : l32, l32 -> l2
|
||||
y = vec_2[vec_1+:2];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_2 : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.constant 31 : l32
|
||||
// CHECK: [[TMP4:%.+]] = moore.sub [[TMP3]], [[TMP2]] : l32
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP4]] : l32, l32 -> l1
|
||||
y = vec_2[vec_1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1a : <l17>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.constant 15 : l32
|
||||
// CHECK: [[TMP4:%.+]] = moore.sub [[TMP2]], [[TMP3]] : l32
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP4]] : l17, l32 -> l2
|
||||
y = vec_1a[vec_1+:2];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1a : <l17>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.constant 15 : l32
|
||||
// CHECK: [[TMP4:%.+]] = moore.sub [[TMP2]], [[TMP3]] : l32
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP4]] : l17, l32 -> l1
|
||||
y = vec_1a[vec_1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1b : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.neg [[TMP2]] : l32
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP3]] : l32, l32 -> l2
|
||||
y = vec_1b[vec_1+:2];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1b : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.neg [[TMP2]] : l32
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP3]] : l32, l32 -> l1
|
||||
y = vec_1b[vec_1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1a : <l17>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x : <i1>
|
||||
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP2]] : !moore.i1 -> !moore.i5
|
||||
// CHECK: [[TMP4:%.+]] = moore.constant 15 : i5
|
||||
// CHECK: [[TMP5:%.+]] = moore.sub [[TMP3]], [[TMP4]] : i5
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP5]] : l17, i5 -> l2
|
||||
y = vec_1a[x+:2];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1a : <l17>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %x : <i1>
|
||||
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP2]] : !moore.i1 -> !moore.i5
|
||||
// CHECK: [[TMP4:%.+]] = moore.constant 15 : i5
|
||||
// CHECK: [[TMP5:%.+]] = moore.sub [[TMP3]], [[TMP4]] : i5
|
||||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP5]] : l17, i5 -> l1
|
||||
y = vec_1a[x];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1
|
||||
// CHECK: [[TMP2:%.+]] = moore.constant 1 : i32
|
||||
// CHECK: [[TMP3:%.+]] = moore.read %a
|
||||
|
@ -918,9 +970,9 @@ module Expressions;
|
|||
// CHECK: moore.dyn_extract [[TMP1]] from [[TMP6]] : l32, i32 -> l1
|
||||
c = vec_1[1*a-:1];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %arr : <uarray<3 x uarray<6 x i4>>>
|
||||
// CHECK: [[TMP3:%.+]] = moore.extract [[TMP1]] from 3 : uarray<3 x uarray<6 x i4>> -> uarray<6 x i4>
|
||||
// CHECK: [[TMP5:%.+]] = moore.extract [[TMP3]] from 7 : uarray<6 x i4> -> i4
|
||||
// CHECK: moore.extract [[TMP5]] from 3 : i4 -> i2
|
||||
// CHECK: [[TMP3:%.+]] = moore.extract [[TMP1]] from 0 : uarray<3 x uarray<6 x i4>> -> uarray<6 x i4>
|
||||
// CHECK: [[TMP5:%.+]] = moore.extract [[TMP3]] from 0 : uarray<6 x i4> -> i4
|
||||
// CHECK: moore.extract [[TMP5]] from 2 : i4 -> i2
|
||||
c = arr[3][7][4:3];
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %vec_1 : <l32>
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %c : <i32>
|
||||
|
|
|
@ -291,3 +291,11 @@ func.func @MoveInitialOutOfSSAVariable() {
|
|||
func.call @useRef(%1) : (!moore.ref<i42>) -> ()
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @sub
|
||||
func.func @sub(%arg0: !moore.i32) -> !moore.i32 {
|
||||
%0 = moore.constant 0 : !moore.i32
|
||||
%1 = moore.sub %arg0, %0 : !moore.i32
|
||||
// CHECK: return %arg0 :
|
||||
return %1 : !moore.i32
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue