Skip to content

Commit 8d47bf4

Browse files
author
MoritzScherer
authored
[Moore] Add shortreal type, bit <-> real conversions (#8985)
This PR disambiguates the RealType into 32-Bit real types ("shortreal") and 64-Bit real types ("real"). It adds support for materializing moore.shortreal from shortreal-specific statements like localparam shortreal sr = 4.532; as well. Apart from this new type disctinction, this PR also adds support for the builtins $shortrealtobits, $bitstoshortreal, $realtobits and $bitstoreal. When working through the builtins mentioned above, I noticed that the shortreal type was missing. I decided to add it as !moore.shortreal since the distinction between $shortrealtobits and $realtobits would not really make sense in the previous type system. To keep backwards compatibility (and also because most real values in Verilog are actually real, not shortreal), I chose to default the new width parameter of RealType to 64 and add a TypeBuilder that accepts "widthless" construction and defaults to 64 Bit. While Section 20.5 "Conversion functions" is unspecific about the domain of the "bits" end of the conversion functions, I infer these two lines to mean two-valued bit rather than logic vectors only: $realtobits converts values from a real type to a 64-bit vector representation of the real number. $bitstoreal converts a bit pattern created by $realtobits to a value of the real type.
1 parent da9a6d5 commit 8d47bf4

File tree

14 files changed

+234
-52
lines changed

14 files changed

+234
-52
lines changed

include/circt-c/Dialect/Moore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetInt(MlirContext ctx, unsigned width);
3939
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetLogic(MlirContext ctx,
4040
unsigned width);
4141
/// Create a real type.
42-
MLIR_CAPI_EXPORTED MlirType mooreRealTypeGet(MlirContext ctx);
42+
MLIR_CAPI_EXPORTED MlirType mooreRealTypeGet(MlirContext ctx, unsigned width);
4343
/// Create a packed open array type.
4444
MLIR_CAPI_EXPORTED MlirType mooreOpenArrayTypeGet(MlirType elementType);
4545
/// Create a packed array type.

include/circt/Dialect/Moore/MooreOps.td

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ def RealLiteralOp : MooreOp<"real_constant", [Pure]> {
548548
See IEEE 1800-2017 § 5.7.2 "Real literal constants".
549549
}];
550550
let arguments = (ins F64Attr:$value);
551-
let results = (outs RealType:$result);
551+
let results = (outs RealF64:$result);
552552
let assemblyFormat = "$value attr-dict `:` type($result)";
553553
}
554554

@@ -1762,6 +1762,75 @@ def FormatTimeOp : MooreOp<"fmt.time", [Pure]> {
17621762
class Builtin<string mnemonic, list<Trait> traits = []> :
17631763
MooreOp<"builtin." # mnemonic, traits>;
17641764

1765+
//===----------------------------------------------------------------------===//
1766+
// Conversion Builtins
1767+
//===----------------------------------------------------------------------===//
1768+
1769+
def RealtobitsBIOp : Builtin<"realtobits"> {
1770+
let summary = "Convert a real-valued number to its logic vector representation";
1771+
let description = [{
1772+
Corresponds to the `$realtobits` system function. Returns a 64-bit
1773+
logic vector corresponding to the bit representation of the real number.
1774+
Note that this does not correspond to a cast to another type, but rather a no-op.
1775+
1776+
See IEEE 1800-2023 § 20.5 "Conversion functions".
1777+
}];
1778+
1779+
// Optional positional attribute for the seed
1780+
let arguments = (ins RealF64:$value);
1781+
let results = (outs TwoValuedI64:$result);
1782+
let assemblyFormat = "$value attr-dict";
1783+
}
1784+
1785+
def BitstorealBIOp : Builtin<"bitstoreal"> {
1786+
let summary = "Convert a logic vector representation to its real-valued number";
1787+
let description = [{
1788+
Corresponds to the `$bitstoreal` system function. Returns a real number
1789+
corresponding to the real number representation of the logic vector.
1790+
Note that this does not correspond to a cast to another type, but rather a no-op.
1791+
1792+
See IEEE 1800-2023 § 20.5 "Conversion functions".
1793+
}];
1794+
1795+
// Optional positional attribute for the seed
1796+
let arguments = (ins TwoValuedI64:$value);
1797+
let results = (outs RealF64:$result);
1798+
let assemblyFormat = "$value attr-dict`:` type($value)";
1799+
}
1800+
1801+
1802+
def ShortrealtobitsBIOp : Builtin<"shortrealtobits"> {
1803+
let summary = "Convert a real-valued number to its logic vector representation";
1804+
let description = [{
1805+
Corresponds to the `$shortrealtobits` system function. Returns a 64-bit
1806+
logic vector corresponding to the bit representation of the real number.
1807+
Note that this does not correspond to a cast to another type, but rather a no-op.
1808+
1809+
See IEEE 1800-2023 § 20.5 "Conversion functions".
1810+
}];
1811+
1812+
// Optional positional attribute for the seed
1813+
let arguments = (ins RealF32:$value);
1814+
let results = (outs TwoValuedI32:$result);
1815+
let assemblyFormat = "$value attr-dict";
1816+
}
1817+
1818+
def BitstoshortrealBIOp : Builtin<"bitstoshortreal"> {
1819+
let summary = "Convert a logic vector representation to its real-valued number";
1820+
let description = [{
1821+
Corresponds to the `$bitstoshortreal` system function. Returns a real number
1822+
corresponding to the real number representation of the logic vector.
1823+
Note that this does not correspond to a cast to another type, but rather a no-op.
1824+
1825+
See IEEE 1800-2023 § 20.5 "Conversion functions".
1826+
}];
1827+
1828+
// Optional positional attribute for the seed
1829+
let arguments = (ins TwoValuedI32:$value);
1830+
let results = (outs RealF32:$result);
1831+
let assemblyFormat = "$value attr-dict `:` type($value)";
1832+
}
1833+
17651834
//===----------------------------------------------------------------------===//
17661835
// True-Random and Pseudo-Random Generators
17671836
//===----------------------------------------------------------------------===//
@@ -1935,8 +2004,8 @@ class RealMathFunc<string mnemonic, list<Trait> traits = []> :
19352004

19362005
See IEEE 1800-2017 § 20.8.2 "Real math functions".
19372006
}];
1938-
let arguments = (ins RealType:$value);
1939-
let results = (outs RealType:$result);
2007+
let arguments = (ins RealF64:$value);
2008+
let results = (outs RealF64:$result);
19402009
let assemblyFormat = "$value attr-dict `:` type($value)";
19412010
}
19422011

include/circt/Dialect/Moore/MooreTypes.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,22 @@ enum class Domain {
5252
FourValued,
5353
};
5454

55+
/// The type of floating point / real number behind a RealType
56+
enum class RealWidth {
57+
/// A standard 32-Bit floating point number ("float")
58+
f32 = 32,
59+
/// A 64-bit double-precision floation point number ("double")
60+
f64 = 64
61+
};
62+
5563
/// Check if a type is an `IntType` type of the given width.
5664
bool isIntType(Type type, unsigned width);
5765
/// Check if a type is an `IntType` type of the given domain.
5866
bool isIntType(Type type, Domain domain);
5967
/// Check if a type is an `IntType` type of the given width and domain.
6068
bool isIntType(Type type, unsigned width, Domain domain);
69+
/// Check if a type is a `RealType` type of the given width.
70+
bool isRealType(Type type, unsigned width);
6171

6272
//===----------------------------------------------------------------------===//
6373
// Unpacked Type

include/circt/Dialect/Moore/MooreTypes.td

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,21 +138,25 @@ def IntType : MooreTypeDef<"Int", [], "moore::PackedType"> {
138138
//===----------------------------------------------------------------------===//
139139

140140
def RealType : MooreTypeDef<"Real", [], "moore::UnpackedType"> {
141-
let mnemonic = "real";
141+
let typeName = "moore.real";
142142
let summary = "a SystemVerilog real type";
143+
let parameters = (ins "RealWidth":$width);
143144
let description = [{
144-
This type represents the SystemVerilog real type. Since the Moore dialect
145-
does not fully handle real-valued expressions properly yet, we coalesce the
146-
`shortreal`, `real`, and `realtime` types in the SystemVerilgo standard to
145+
This type represents the SystemVerilog real type. We coalesce the
146+
`f32`, `f64`, and `realtime` types in the SystemVerilog standard to
147147
this common `!moore.real` type. The standard specifies these types to be of
148-
at least 32, 64, and 64 bits, respectively. The `!moore.real` type is 64
149-
bits wide.
150-
151-
| Verilog | Moore Dialect |
152-
|-------------|---------------|
153-
| `shortreal` | `!moore.real` |
154-
| `real` | `!moore.real` |
155-
| `realtime` | `!moore.time` |
148+
at least 32, 64, and 64 bits, respectively.
149+
150+
| Verilog | Moore Dialect |
151+
|-------------|--------------------|
152+
| `shortreal` | `!moore.f32` |
153+
| `real` | `!moore.f64` |
154+
| `realtime` | `!moore.time` |
155+
}];
156+
let extraClassDeclaration = [{
157+
// Convenience helpers
158+
static RealType getShortReal(MLIRContext *ctx) { return get(ctx, RealWidth::f32); }
159+
static RealType getReal (MLIRContext *ctx) { return get(ctx, RealWidth::f64); }
156160
}];
157161
}
158162

@@ -483,13 +487,41 @@ def FourValuedI64 : MooreType<CPred<[{
483487
let builderCall = "IntType::getLogic($_builder.getContext(), 64)";
484488
}
485489

490+
/// A 32-bit four-valued integer.
491+
def FourValuedI32 : MooreType<CPred<[{
492+
moore::isIntType($_self, 32, moore::Domain::FourValued)
493+
}]>, "32-bit four-valued integer type", "moore::IntType"> {
494+
let builderCall = "IntType::getLogic($_builder.getContext(), 32)";
495+
}
496+
497+
// A 64-bit two-valued integer.
498+
def TwoValuedI64 : MooreType<CPred<[{
499+
moore::isIntType($_self, 64, moore::Domain::TwoValued)
500+
}]>, "64-bit two-valued integer type", "moore::IntType"> {
501+
let builderCall = "IntType::getInt($_builder.getContext(), 64)";
502+
}
503+
486504
// A 32-bit two-valued integer.
487505
def TwoValuedI32 : MooreType<CPred<[{
488506
moore::isIntType($_self, 32, moore::Domain::TwoValued)
489507
}]>, "32-bit two-valued integer type", "moore::IntType"> {
490508
let builderCall = "IntType::getInt($_builder.getContext(), 32)";
491509
}
492510

511+
// A 32-bit real value.
512+
def RealF32 : MooreType<CPred<[{
513+
moore::isRealType($_self, 32)
514+
}]>, "32-bit real type, aka. shortreal", "moore::RealType"> {
515+
let builderCall = "RealType::getShortReal($_builder.getContext())";
516+
}
517+
518+
// A 64-bit real value.
519+
def RealF64 : MooreType<CPred<[{
520+
moore::isRealType($_self, 64)
521+
}]>, "64-bit real type, aka. real", "moore::RealType"> {
522+
let builderCall = "RealType::getReal($_builder.getContext())";
523+
}
524+
493525
/// A packed or unpacked array type with a fixed size.
494526
def AnyStaticArrayType : MooreType<
495527
Or<[ArrayType.predicate, UnpackedArrayType.predicate]>,

lib/CAPI/Dialect/Moore.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ MlirType mooreIntTypeGetLogic(MlirContext ctx, unsigned width) {
5757
}
5858

5959
/// Create a real type.
60-
MlirType mooreRealTypeGet(MlirContext ctx) {
61-
return wrap(RealType::get(unwrap(ctx)));
60+
MlirType mooreRealTypeGet(MlirContext ctx, unsigned width) {
61+
if (width == 32)
62+
return wrap(RealType::get(unwrap(ctx), RealWidth::f32));
63+
if (width == 64)
64+
return wrap(RealType::get(unwrap(ctx), RealWidth::f32));
65+
return {};
6266
}
6367

6468
MlirType mooreOpenArrayTypeGet(MlirType elementType) {

lib/Conversion/ImportVerilog/Expressions.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,24 @@ Context::convertSystemCallArity1(const slang::ast::SystemSubroutine &subroutine,
17081708
[&]() -> Value {
17091709
return moore::RandomBIOp::create(builder, loc, value);
17101710
})
1711+
.Case("$realtobits",
1712+
[&]() -> Value {
1713+
return moore::RealtobitsBIOp::create(builder, loc, value);
1714+
})
1715+
.Case("$bitstoreal",
1716+
[&]() -> Value {
1717+
return moore::BitstorealBIOp::create(builder, loc, value);
1718+
})
1719+
.Case("$shortrealtobits",
1720+
[&]() -> Value {
1721+
return moore::ShortrealtobitsBIOp::create(builder, loc,
1722+
value);
1723+
})
1724+
.Case("$bitstoshortreal",
1725+
[&]() -> Value {
1726+
return moore::BitstoshortrealBIOp::create(builder, loc,
1727+
value);
1728+
})
17111729
.Default([&]() -> Value { return {}; });
17121730
return systemCallRes();
17131731
}

lib/Conversion/ImportVerilog/FormatStrings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ struct FormatStringParser {
197197
// Ensures that the given value is moore.real
198198
// i.e. $display("%f", 4) -> 4.000000, but 4 is not necessarily of real type
199199
auto value = context.convertRvalueExpression(
200-
arg, moore::RealType::get(context.getContext()));
200+
arg, moore::RealType::get(context.getContext(), moore::RealWidth::f64));
201201

202202
if (!value)
203203
return failure();

lib/Conversion/ImportVerilog/Types.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ struct TypeVisitor {
3838
Type visit(const slang::ast::FloatingType &type) {
3939
if (type.floatKind == slang::ast::FloatingType::Kind::RealTime)
4040
return moore::TimeType::get(context.getContext());
41-
return moore::RealType::get(context.getContext());
41+
if (type.floatKind == slang::ast::FloatingType::Kind::Real)
42+
return moore::RealType::get(context.getContext(), moore::RealWidth::f64);
43+
return moore::RealType::get(context.getContext(), moore::RealWidth::f32);
4244
}
4345

4446
Type visit(const slang::ast::PredefinedIntegerType &type) {

lib/Dialect/Moore/MooreTypes.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ bool moore::isIntType(Type type, unsigned width, Domain domain) {
3939
return false;
4040
}
4141

42+
bool moore::isRealType(Type type, unsigned width) {
43+
if (auto realType = dyn_cast<RealType>(type))
44+
if (realType.getWidth() == RealWidth::f32)
45+
return width == 32;
46+
return width == 64;
47+
}
48+
4249
static LogicalResult parseMembers(AsmParser &parser,
4350
SmallVector<StructLikeMember> &members);
4451
static void printMembers(AsmPrinter &printer,
@@ -69,7 +76,8 @@ Domain UnpackedType::getDomain() const {
6976
std::optional<unsigned> UnpackedType::getBitSize() const {
7077
return TypeSwitch<UnpackedType, std::optional<unsigned>>(*this)
7178
.Case<PackedType>([](auto type) { return type.getBitSize(); })
72-
.Case<RealType>([](auto type) { return 64; })
79+
.Case<RealType>(
80+
[](auto type) { return type.getWidth() == RealWidth::f32 ? 32 : 64; })
7381
.Case<UnpackedArrayType>([](auto type) -> std::optional<unsigned> {
7482
if (auto size = type.getElementType().getBitSize())
7583
return (*size) * type.getSize();
@@ -388,6 +396,16 @@ static ParseResult parseMooreType(AsmParser &parser, Type &type) {
388396
return success();
389397
}
390398

399+
if (mnemonic == "f32") {
400+
type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f32);
401+
return success();
402+
}
403+
404+
if (mnemonic == "f64") {
405+
type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f64);
406+
return success();
407+
}
408+
391409
parser.emitError(loc) << "unknown type `" << mnemonic
392410
<< "` in dialect `moore`";
393411
return failure();
@@ -401,6 +419,14 @@ static void printMooreType(Type type, AsmPrinter &printer) {
401419
printer << intType.getWidth();
402420
return;
403421
}
422+
if (auto rt = dyn_cast<moore::RealType>(type)) {
423+
if (rt.getWidth() == RealWidth::f32) {
424+
printer << "f32";
425+
return;
426+
}
427+
printer << "f64";
428+
return;
429+
}
404430

405431
// Otherwise fall back to the generated printer.
406432
if (succeeded(generatedTypePrinter(type, printer)))

test/Conversion/ImportVerilog/basic.sv

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,8 @@ module Expressions;
742742
int a, b;
743743
} c, d;
744744
} union1;
745-
// CHECK: %r1 = moore.variable : <real>
746-
// CHECK: %r2 = moore.variable : <real>
745+
// CHECK: %r1 = moore.variable : <f64>
746+
// CHECK: %r2 = moore.variable : <f64>
747747
real r1,r2;
748748
// CHECK: %arrayInt = moore.variable : <array<2 x i32>>
749749
bit [1:0][31:0] arrayInt;
@@ -1363,12 +1363,12 @@ module Expressions;
13631363
c = x ? a : b;
13641364

13651365
// CHECK: [[X_COND:%.+]] = moore.read %x
1366-
// CHECK: moore.conditional [[X_COND]] : i1 -> real {
1366+
// CHECK: moore.conditional [[X_COND]] : i1 -> f64 {
13671367
// CHECK: [[R1_READ:%.+]] = moore.read %r1
1368-
// CHECK: moore.yield [[R1_READ]] : real
1368+
// CHECK: moore.yield [[R1_READ]] : f64
13691369
// CHECK: } {
13701370
// CHECK: [[R2_READ:%.+]] = moore.read %r2
1371-
// CHECK: moore.yield [[R2_READ]] : real
1371+
// CHECK: moore.yield [[R2_READ]] : f64
13721372
// CHECK: }
13731373
r1 = x ? r1 : r2;
13741374

0 commit comments

Comments
 (0)