Skip to content

Commit

Permalink
[ImportVerilog] Fix bit slicing into variables declared with offset (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
maerhart authored Feb 6, 2025
1 parent 3ef66cf commit c4e8859
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 9 deletions.
2 changes: 2 additions & 0 deletions include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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]> {
Expand Down
42 changes: 38 additions & 4 deletions lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down
12 changes: 12 additions & 0 deletions lib/Dialect/Moore/MooreOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//===----------------------------------------------------------------------===//
Expand Down
62 changes: 57 additions & 5 deletions test/Conversion/ImportVerilog/basic.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand All @@ -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
Expand All @@ -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>
Expand Down
8 changes: 8 additions & 0 deletions test/Dialect/Moore/canonicalizers.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit c4e8859

Please sign in to comment.