Skip to content

Commit a1e2484

Browse files
author
Moritz Scherer
committed
[ImportVerilog][Moore] Add real-to-int & int-to-real operators
This commit introduces explicit conversion operations between real and integer types in the Moore dialect, following IEEE 1800-2023 §6.24.1 *Cast operator* and §6.12 *Real, shortreal and realtime data types*. It also extends VerilogImport to recognize and materialize these conversions during AST translation. - **Dialect (`MooreOps.td`)** - Added `RealToIntOp` for rounding real/shortreal values to two-valued integers. - Added `IntToRealOp` for widening integer values to real/shortreal. - Both ops marked `Pure` with explicit assembly formats. - **Import logic (`Expressions.cpp`)** - Added conversion handling in `Context::materializeConversion`: - `RealType` -> `IntType` -> `RealToIntOp` - `IntType` -> `RealType` -> `IntToRealOp` - **Tests** - **SystemVerilog import** - Added `basic.sv` tests verifying correct lowering of `real'(expr)` and `int'(expr)` casts for all real/int width combinations (`f32/i32`, `f64/i64`). - Updated `builtins.sv` to expect `moore.int_to_real` instead of a generic `conversion` op. - **Dialect MLIR** - Added `basic.mlir` tests ensuring proper parsing/printing and type mapping for 32- and 64-bit conversions.
1 parent a570dbf commit a1e2484

File tree

5 files changed

+111
-1
lines changed

5 files changed

+111
-1
lines changed

include/circt/Dialect/Moore/MooreOps.td

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,37 @@ def LogicToTimeOp : MooreOp<"logic_to_time", [Pure]> {
703703
let hasFolder = 1;
704704
}
705705

706+
def RealToIntOp : MooreOp<"real_to_int", [
707+
Pure
708+
]> {
709+
let summary = "Convert a real value to a two-valued integer";
710+
let description = [{
711+
See IEEE 1800-2023 Section 6.24.1: "Cast operator" and 6.12:
712+
"Real, shortreal and realtime data types". Accordingly,
713+
output values are rounded.
714+
}];
715+
let arguments = (ins RealType:$input);
716+
let results = (outs TwoValuedIntType:$result);
717+
let assemblyFormat = [{
718+
$input attr-dict `:` type($input) `->` type($result)
719+
}];
720+
}
721+
722+
def IntToRealOp : MooreOp<"int_to_real", [
723+
Pure
724+
]> {
725+
let summary = "Convert an integer value to a real";
726+
let description = [{
727+
See IEEE 1800-2023 Section 6.24.1: "Cast operator" and 6.12:
728+
"Real, shortreal and realtime data types".
729+
}];
730+
let arguments = (ins TwoValuedIntType:$input);
731+
let results = (outs RealType:$result);
732+
let assemblyFormat = [{
733+
$input attr-dict `:` type($input) `->` type($result)
734+
}];
735+
}
736+
706737
//===----------------------------------------------------------------------===//
707738
// Resizing
708739
//===----------------------------------------------------------------------===//

lib/Conversion/ImportVerilog/Expressions.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,31 @@ Value Context::materializeConversion(Type type, Value value, bool isSigned,
17571757
return builder.createOrFold<moore::FormatStringOp>(loc, value);
17581758
}
17591759

1760+
// Handle Real To Int conversion
1761+
if (isa<moore::IntType>(type) && isa<moore::RealType>(value.getType())) {
1762+
auto twoValInt = builder.createOrFold<moore::RealToIntOp>(
1763+
loc, dyn_cast<moore::IntType>(type).getTwoValued(), value);
1764+
1765+
if (dyn_cast<moore::IntType>(type).getDomain() == moore::Domain::FourValued)
1766+
return materializePackedToSBVConversion(*this, twoValInt, loc);
1767+
return twoValInt;
1768+
}
1769+
1770+
// Handle Int to Real conversion
1771+
if (isa<moore::RealType>(type) && isa<moore::IntType>(value.getType())) {
1772+
Value twoValInt;
1773+
// Check if int needs to be converted to two-valued first
1774+
if (dyn_cast<moore::IntType>(value.getType()).getDomain() ==
1775+
moore::Domain::TwoValued)
1776+
twoValInt = value;
1777+
else
1778+
twoValInt = materializeConversion(
1779+
dyn_cast<moore::IntType>(value.getType()).getTwoValued(), value, true,
1780+
loc);
1781+
1782+
return builder.createOrFold<moore::IntToRealOp>(loc, type, twoValInt);
1783+
}
1784+
17601785
// TODO: Handle other conversions with dedicated ops.
17611786
if (value.getType() != type)
17621787
value = moore::ConversionOp::create(builder, loc, type, value);

test/Conversion/ImportVerilog/basic.sv

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,3 +3308,39 @@ task NonBlockingAssignment(
33083308
// CHECK-NEXT: moore.delayed_nonblocking_assign [[A]], [[NOTB]], [[TIME]]
33093309
a <= #1ns ~b;
33103310
endtask
3311+
3312+
// CHECK-LABEL: func.func private @RealConversion(
3313+
// CHECK-SAME: [[SR:%[^,]+]]: !moore.f32
3314+
// CHECK-SAME: [[LR:%[^,]+]]: !moore.f64
3315+
// CHECK-SAME: [[INT:%[^,]+]]: !moore.i42
3316+
// CHECK-SAME: [[LINT:%[^,]+]]: !moore.i64
3317+
function automatic void RealConversion(shortreal sr, real r, bit[41:0] i, longint longi);
3318+
// CHECK: [[INTTEST:%.+]] = moore.real_to_int [[SR]] : f32 -> i32
3319+
int intTest = int'(sr);
3320+
// CHECK: [[INTTEST2:%.+]] = moore.real_to_int [[LR]] : f64 -> i32
3321+
int intTest2 = int'(r);
3322+
// CHECK: [[LINTTEST:%.+]] = moore.real_to_int [[SR]] : f32 -> i64
3323+
longint longIntTest = longint'(sr);
3324+
// CHECK: [[LINTTEST2:%.+]] = moore.real_to_int [[LR]] : f64 -> i64
3325+
longint longIntTest2 = longint'(r);
3326+
3327+
3328+
// CHECK: [[SRTEST:%.+]] = moore.int_to_real [[INT]] : i42 -> f32
3329+
shortreal srTest = shortreal'(i);
3330+
// CHECK: [[SRTEST2:%.+]] = moore.int_to_real [[LINT]] : i64 -> f32
3331+
shortreal srTest2 = shortreal'(longi);
3332+
// CHECK: [[RTEST:%.+]] = moore.int_to_real [[INT]] : i42 -> f64
3333+
real rTest = real'(i);
3334+
// CHECK: [[RTEST2:%.+]] = moore.int_to_real [[LINT]] : i64 -> f64
3335+
real rTest2 = real'(longi);
3336+
3337+
// CHECK: [[IMM:%.+]] = moore.real_to_int [[LR]] : f64 -> i32
3338+
// CHECK-NEXT: [[F:%.+]] = moore.int_to_logic [[IMM]] : i32
3339+
// CHECK-NEXT: [[logicTest:%.+]] = moore.variable [[F]] : <l32>
3340+
logic [31:0] logicTest = r;
3341+
3342+
// CHECK: [[R:%.+]] = moore.read [[logicTest]] : <l32>
3343+
// CHECK-NEXT: [[IMM2:%.+]] = moore.logic_to_int [[R]] : l32
3344+
// CHECK-Next: [[F2:%.+]] = moore.int_to_real [[IMM2]] : i32 -> f64
3345+
real realTest = real'(logicTest);
3346+
endfunction

test/Conversion/ImportVerilog/builtins.sv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function void DisplayAndSeverityBuiltins(int x, real r);
9292

9393
// CHECK: moore.fmt.real float [[R]]
9494
$write("%f", r);
95-
// CHECK: [[XR:%.+]] = moore.conversion [[X]] : !moore.i32 -> !moore.f64
95+
// CHECK: [[XR:%.+]] = moore.int_to_real [[X]] : i32 -> f64
9696
// CHECK: [[TMP:%.+]] = moore.fmt.real float [[XR]]
9797
// CHECK: moore.builtin.display [[TMP]]
9898
$write("%f", x);

test/Dialect/Moore/basic.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,21 @@ func.func @TimeConversion(%arg0: !moore.time, %arg1: !moore.l64) {
468468
moore.logic_to_time %arg1
469469
return
470470
}
471+
472+
// CHECK-LABEL: func.func @RealConversion32(%arg0: !moore.f32, %arg1: !moore.i42)
473+
func.func @RealConversion32(%arg0: !moore.f32, %arg1: !moore.i42) {
474+
// CHECK: %0 = moore.real_to_int %arg0 : f32 -> i42
475+
%0 = moore.real_to_int %arg0 : f32 -> i42
476+
// CHECK: %1 = moore.int_to_real %arg1 : i42 -> f32
477+
%1 = moore.int_to_real %arg1 : i42 -> f32
478+
return
479+
}
480+
481+
// CHECK-LABEL: func.func @RealConversion64(%arg0: !moore.f64, %arg1: !moore.i42)
482+
func.func @RealConversion64(%arg0: !moore.f64, %arg1: !moore.i42) {
483+
// CHECK: %0 = moore.real_to_int %arg0 : f64 -> i42
484+
%0 = moore.real_to_int %arg0 : f64 -> i42
485+
// CHECK: %1 = moore.int_to_real %arg1 : i42 -> f64
486+
%1 = moore.int_to_real %arg1 : i42 -> f64
487+
return
488+
}

0 commit comments

Comments
 (0)