Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/circt-c/Dialect/Moore.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetInt(MlirContext ctx, unsigned width);
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetLogic(MlirContext ctx,
unsigned width);
/// Create a real type.
MLIR_CAPI_EXPORTED MlirType mooreRealTypeGet(MlirContext ctx);
MLIR_CAPI_EXPORTED MlirType mooreRealTypeGet(MlirContext ctx, unsigned width);
/// Create a packed open array type.
MLIR_CAPI_EXPORTED MlirType mooreOpenArrayTypeGet(MlirType elementType);
/// Create a packed array type.
Expand Down
75 changes: 72 additions & 3 deletions include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ def RealLiteralOp : MooreOp<"real_constant", [Pure]> {
See IEEE 1800-2017 § 5.7.2 "Real literal constants".
}];
let arguments = (ins F64Attr:$value);
let results = (outs RealType:$result);
let results = (outs RealF64:$result);
let assemblyFormat = "$value attr-dict `:` type($result)";
}

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

//===----------------------------------------------------------------------===//
// Conversion Builtins
//===----------------------------------------------------------------------===//

def RealtobitsBIOp : Builtin<"realtobits"> {
let summary = "Convert a real-valued number to its logic vector representation";
let description = [{
Corresponds to the `$realtobits` system function. Returns a 64-bit
logic vector corresponding to the bit representation of the real number.
Note that this does not correspond to a cast to another type, but rather a no-op.

See IEEE 1800-2023 § 20.5 "Conversion functions".
}];

// Optional positional attribute for the seed
let arguments = (ins RealF64:$value);
let results = (outs TwoValuedI64:$result);
let assemblyFormat = "$value attr-dict";
}

def BitstorealBIOp : Builtin<"bitstoreal"> {
let summary = "Convert a logic vector representation to its real-valued number";
let description = [{
Corresponds to the `$bitstoreal` system function. Returns a real number
corresponding to the real number representation of the logic vector.
Note that this does not correspond to a cast to another type, but rather a no-op.

See IEEE 1800-2023 § 20.5 "Conversion functions".
}];

// Optional positional attribute for the seed
let arguments = (ins TwoValuedI64:$value);
let results = (outs RealF64:$result);
let assemblyFormat = "$value attr-dict`:` type($value)";
}


def ShortrealtobitsBIOp : Builtin<"shortrealtobits"> {
let summary = "Convert a real-valued number to its logic vector representation";
let description = [{
Corresponds to the `$shortrealtobits` system function. Returns a 64-bit
logic vector corresponding to the bit representation of the real number.
Note that this does not correspond to a cast to another type, but rather a no-op.

See IEEE 1800-2023 § 20.5 "Conversion functions".
}];

// Optional positional attribute for the seed
let arguments = (ins RealF32:$value);
let results = (outs TwoValuedI32:$result);
let assemblyFormat = "$value attr-dict";
}

def BitstoshortrealBIOp : Builtin<"bitstoshortreal"> {
let summary = "Convert a logic vector representation to its real-valued number";
let description = [{
Corresponds to the `$bitstoshortreal` system function. Returns a real number
corresponding to the real number representation of the logic vector.
Note that this does not correspond to a cast to another type, but rather a no-op.

See IEEE 1800-2023 § 20.5 "Conversion functions".
}];

// Optional positional attribute for the seed
let arguments = (ins TwoValuedI32:$value);
let results = (outs RealF32:$result);
let assemblyFormat = "$value attr-dict `:` type($value)";
}

//===----------------------------------------------------------------------===//
// True-Random and Pseudo-Random Generators
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1935,8 +2004,8 @@ class RealMathFunc<string mnemonic, list<Trait> traits = []> :

See IEEE 1800-2017 § 20.8.2 "Real math functions".
}];
let arguments = (ins RealType:$value);
let results = (outs RealType:$result);
let arguments = (ins RealF64:$value);
let results = (outs RealF64:$result);
let assemblyFormat = "$value attr-dict `:` type($value)";
}

Expand Down
10 changes: 10 additions & 0 deletions include/circt/Dialect/Moore/MooreTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,22 @@ enum class Domain {
FourValued,
};

/// The type of floating point / real number behind a RealType
enum class RealWidth {
/// A standard 32-Bit floating point number ("float")
f32 = 32,
/// A 64-bit double-precision floation point number ("double")
f64 = 64
};

/// Check if a type is an `IntType` type of the given width.
bool isIntType(Type type, unsigned width);
/// Check if a type is an `IntType` type of the given domain.
bool isIntType(Type type, Domain domain);
/// Check if a type is an `IntType` type of the given width and domain.
bool isIntType(Type type, unsigned width, Domain domain);
/// Check if a type is a `RealType` type of the given width.
bool isRealType(Type type, unsigned width);

//===----------------------------------------------------------------------===//
// Unpacked Type
Expand Down
56 changes: 44 additions & 12 deletions include/circt/Dialect/Moore/MooreTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -138,21 +138,25 @@ def IntType : MooreTypeDef<"Int", [], "moore::PackedType"> {
//===----------------------------------------------------------------------===//

def RealType : MooreTypeDef<"Real", [], "moore::UnpackedType"> {
let mnemonic = "real";
let typeName = "moore.real";
let summary = "a SystemVerilog real type";
let parameters = (ins "RealWidth":$width);
let description = [{
This type represents the SystemVerilog real type. Since the Moore dialect
does not fully handle real-valued expressions properly yet, we coalesce the
`shortreal`, `real`, and `realtime` types in the SystemVerilgo standard to
This type represents the SystemVerilog real type. We coalesce the
`f32`, `f64`, and `realtime` types in the SystemVerilog standard to
this common `!moore.real` type. The standard specifies these types to be of
at least 32, 64, and 64 bits, respectively. The `!moore.real` type is 64
bits wide.

| Verilog | Moore Dialect |
|-------------|---------------|
| `shortreal` | `!moore.real` |
| `real` | `!moore.real` |
| `realtime` | `!moore.time` |
at least 32, 64, and 64 bits, respectively.

| Verilog | Moore Dialect |
|-------------|--------------------|
| `shortreal` | `!moore.f32` |
| `real` | `!moore.f64` |
| `realtime` | `!moore.time` |
}];
let extraClassDeclaration = [{
// Convenience helpers
static RealType getShortReal(MLIRContext *ctx) { return get(ctx, RealWidth::f32); }
static RealType getReal (MLIRContext *ctx) { return get(ctx, RealWidth::f64); }
}];
}

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

/// A 32-bit four-valued integer.
def FourValuedI32 : MooreType<CPred<[{
moore::isIntType($_self, 32, moore::Domain::FourValued)
}]>, "32-bit four-valued integer type", "moore::IntType"> {
let builderCall = "IntType::getLogic($_builder.getContext(), 32)";
}

// A 64-bit two-valued integer.
def TwoValuedI64 : MooreType<CPred<[{
moore::isIntType($_self, 64, moore::Domain::TwoValued)
}]>, "64-bit two-valued integer type", "moore::IntType"> {
let builderCall = "IntType::getInt($_builder.getContext(), 64)";
}

// A 32-bit two-valued integer.
def TwoValuedI32 : MooreType<CPred<[{
moore::isIntType($_self, 32, moore::Domain::TwoValued)
}]>, "32-bit two-valued integer type", "moore::IntType"> {
let builderCall = "IntType::getInt($_builder.getContext(), 32)";
}

// A 32-bit real value.
def RealF32 : MooreType<CPred<[{
moore::isRealType($_self, 32)
}]>, "32-bit real type, aka. shortreal", "moore::RealType"> {
let builderCall = "RealType::getShortReal($_builder.getContext())";
}

// A 64-bit real value.
def RealF64 : MooreType<CPred<[{
moore::isRealType($_self, 64)
}]>, "64-bit real type, aka. real", "moore::RealType"> {
let builderCall = "RealType::getReal($_builder.getContext())";
}

/// A packed or unpacked array type with a fixed size.
def AnyStaticArrayType : MooreType<
Or<[ArrayType.predicate, UnpackedArrayType.predicate]>,
Expand Down
8 changes: 6 additions & 2 deletions lib/CAPI/Dialect/Moore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ MlirType mooreIntTypeGetLogic(MlirContext ctx, unsigned width) {
}

/// Create a real type.
MlirType mooreRealTypeGet(MlirContext ctx) {
return wrap(RealType::get(unwrap(ctx)));
MlirType mooreRealTypeGet(MlirContext ctx, unsigned width) {
if (width == 32)
return wrap(RealType::get(unwrap(ctx), RealWidth::f32));
if (width == 64)
return wrap(RealType::get(unwrap(ctx), RealWidth::f32));
return {};
}

MlirType mooreOpenArrayTypeGet(MlirType elementType) {
Expand Down
18 changes: 18 additions & 0 deletions lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1708,6 +1708,24 @@ Context::convertSystemCallArity1(const slang::ast::SystemSubroutine &subroutine,
[&]() -> Value {
return moore::RandomBIOp::create(builder, loc, value);
})
.Case("$realtobits",
[&]() -> Value {
return moore::RealtobitsBIOp::create(builder, loc, value);
})
.Case("$bitstoreal",
[&]() -> Value {
return moore::BitstorealBIOp::create(builder, loc, value);
})
.Case("$shortrealtobits",
[&]() -> Value {
return moore::ShortrealtobitsBIOp::create(builder, loc,
value);
})
.Case("$bitstoshortreal",
[&]() -> Value {
return moore::BitstoshortrealBIOp::create(builder, loc,
value);
})
.Default([&]() -> Value { return {}; });
return systemCallRes();
}
2 changes: 1 addition & 1 deletion lib/Conversion/ImportVerilog/FormatStrings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ struct FormatStringParser {
// Ensures that the given value is moore.real
// i.e. $display("%f", 4) -> 4.000000, but 4 is not necessarily of real type
auto value = context.convertRvalueExpression(
arg, moore::RealType::get(context.getContext()));
arg, moore::RealType::get(context.getContext(), moore::RealWidth::f64));

if (!value)
return failure();
Expand Down
4 changes: 3 additions & 1 deletion lib/Conversion/ImportVerilog/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ struct TypeVisitor {
Type visit(const slang::ast::FloatingType &type) {
if (type.floatKind == slang::ast::FloatingType::Kind::RealTime)
return moore::TimeType::get(context.getContext());
return moore::RealType::get(context.getContext());
if (type.floatKind == slang::ast::FloatingType::Kind::Real)
return moore::RealType::get(context.getContext(), moore::RealWidth::f64);
return moore::RealType::get(context.getContext(), moore::RealWidth::f32);
}

Type visit(const slang::ast::PredefinedIntegerType &type) {
Expand Down
28 changes: 27 additions & 1 deletion lib/Dialect/Moore/MooreTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ bool moore::isIntType(Type type, unsigned width, Domain domain) {
return false;
}

bool moore::isRealType(Type type, unsigned width) {
if (auto realType = dyn_cast<RealType>(type))
if (realType.getWidth() == RealWidth::f32)
return width == 32;
return width == 64;
}

static LogicalResult parseMembers(AsmParser &parser,
SmallVector<StructLikeMember> &members);
static void printMembers(AsmPrinter &printer,
Expand Down Expand Up @@ -69,7 +76,8 @@ Domain UnpackedType::getDomain() const {
std::optional<unsigned> UnpackedType::getBitSize() const {
return TypeSwitch<UnpackedType, std::optional<unsigned>>(*this)
.Case<PackedType>([](auto type) { return type.getBitSize(); })
.Case<RealType>([](auto type) { return 64; })
.Case<RealType>(
[](auto type) { return type.getWidth() == RealWidth::f32 ? 32 : 64; })
.Case<UnpackedArrayType>([](auto type) -> std::optional<unsigned> {
if (auto size = type.getElementType().getBitSize())
return (*size) * type.getSize();
Expand Down Expand Up @@ -388,6 +396,16 @@ static ParseResult parseMooreType(AsmParser &parser, Type &type) {
return success();
}

if (mnemonic == "f32") {
type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f32);
return success();
}

if (mnemonic == "f64") {
type = moore::RealType::get(parser.getContext(), /*width=*/RealWidth::f64);
return success();
}

parser.emitError(loc) << "unknown type `" << mnemonic
<< "` in dialect `moore`";
return failure();
Expand All @@ -401,6 +419,14 @@ static void printMooreType(Type type, AsmPrinter &printer) {
printer << intType.getWidth();
return;
}
if (auto rt = dyn_cast<moore::RealType>(type)) {
if (rt.getWidth() == RealWidth::f32) {
printer << "f32";
return;
}
printer << "f64";
return;
}

// Otherwise fall back to the generated printer.
if (succeeded(generatedTypePrinter(type, printer)))
Expand Down
10 changes: 5 additions & 5 deletions test/Conversion/ImportVerilog/basic.sv
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,8 @@ module Expressions;
int a, b;
} c, d;
} union1;
// CHECK: %r1 = moore.variable : <real>
// CHECK: %r2 = moore.variable : <real>
// CHECK: %r1 = moore.variable : <f64>
// CHECK: %r2 = moore.variable : <f64>
real r1,r2;
// CHECK: %arrayInt = moore.variable : <array<2 x i32>>
bit [1:0][31:0] arrayInt;
Expand Down Expand Up @@ -1363,12 +1363,12 @@ module Expressions;
c = x ? a : b;

// CHECK: [[X_COND:%.+]] = moore.read %x
// CHECK: moore.conditional [[X_COND]] : i1 -> real {
// CHECK: moore.conditional [[X_COND]] : i1 -> f64 {
// CHECK: [[R1_READ:%.+]] = moore.read %r1
// CHECK: moore.yield [[R1_READ]] : real
// CHECK: moore.yield [[R1_READ]] : f64
// CHECK: } {
// CHECK: [[R2_READ:%.+]] = moore.read %r2
// CHECK: moore.yield [[R2_READ]] : real
// CHECK: moore.yield [[R2_READ]] : f64
// CHECK: }
r1 = x ? r1 : r2;

Expand Down
Loading