Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ImportVerilog] add real literal support, refine real type, and add real format support #8020

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
40 changes: 38 additions & 2 deletions include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,24 @@ def StringConstantOp : MooreOp<"string_constant", [Pure]> {
let assemblyFormat = "$value attr-dict `:` type($result)";
}

def RealLiteralOp : MooreOp<"real_constant", [Pure]> {
let summary = "Produce a constant real value";
let description = [{
Produces a constant value of real type.

Example:
```mlir
%0 = moore.real_constant 1.23
```

The default type for fixed-point format (e.g., 1.2), and exponent format (e.g., 2.0e10) shall be real.
See IEEE 1800-2017 § 5.7.2 "Real literal constants".
}];
let arguments = (ins F64Attr:$value);
let results = (outs RealType:$result);
let assemblyFormat = "$value attr-dict `:` type($result)";
}

//===----------------------------------------------------------------------===//
// Casting and Resizing
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -683,8 +701,8 @@ def BoolCastOp : MooreOp<"bool_cast", [

class BinaryOpBase<string mnemonic, list<Trait> traits = []> :
MooreOp<mnemonic, traits # [Pure, SameOperandsAndResultType]> {
let arguments = (ins SimpleBitVectorType:$lhs, SimpleBitVectorType:$rhs);
let results = (outs SimpleBitVectorType:$result);
let arguments = (ins NumericType:$lhs, NumericType:$rhs);
let results = (outs NumericType:$result);
let assemblyFormat = [{
$lhs `,` $rhs attr-dict `:` type($result)
}];
Expand Down Expand Up @@ -1495,6 +1513,24 @@ def FormatIntOp : MooreOp<"fmt.int", [Pure]> {
}];
}

def FormatFloatOp : MooreOp<"fmt.float", [Pure]> {
let summary = "Format an float value";
let description = [{
Format an float value as a string according to the specified format.

See IEEE 1800-2017 § 21.2.1.2 "Format specifications".
}];
let arguments = (ins
FloatType:$value
);
let results = (outs FormatStringType:$result);
let assemblyFormat = [{
$value `,`
attr-dict `:` type($value)
Comment on lines +1528 to +1529
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$value `,`
attr-dict `:` type($value)
$value `,` attr-dict `:` type($value)

}];
}


//===----------------------------------------------------------------------===//
// Builtin System Tasks and Functions
//===----------------------------------------------------------------------===//
Expand Down
5 changes: 3 additions & 2 deletions include/circt/Dialect/Moore/MooreTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class OpenUnpackedArrayType;
class PackedType;
class QueueType;
class RealType;
class ShortRealType;
class StringType;
class StructType;
class UnionType;
Expand Down Expand Up @@ -82,7 +83,7 @@ enum class Domain {
class UnpackedType : public Type {
public:
static bool classof(Type type) {
return llvm::isa<PackedType, StringType, ChandleType, EventType, RealType,
return llvm::isa<PackedType, StringType, ChandleType, EventType,
UnpackedArrayType, OpenUnpackedArrayType, AssocArrayType,
QueueType, UnpackedStructType, UnpackedUnionType>(type);
}
Expand Down Expand Up @@ -133,7 +134,7 @@ class UnpackedType : public Type {
class PackedType : public UnpackedType {
public:
static bool classof(Type type) {
return llvm::isa<VoidType, IntType, ArrayType, OpenArrayType, StructType,
return llvm::isa<VoidType, IntType, ArrayType, OpenArrayType, StructType, RealType, ShortRealType,
UnionType>(type);
}

Expand Down
35 changes: 22 additions & 13 deletions include/circt/Dialect/Moore/MooreTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -97,22 +97,27 @@ def IntType : MooreTypeDef<"Int", [], "moore::PackedType"> {
// RealType
//===----------------------------------------------------------------------===//

def RealType : MooreTypeDef<"Real", [], "moore::UnpackedType"> {
def RealType : MooreTypeDef<"Real", [], "moore::PackedType"> {
let mnemonic = "real";
let summary = "a SystemVerilog real type";
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 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.real` |
SystemVerilog real type. The real data type is the same as a C double.
The realtime declarations shall be treated synonymously with real
declarations and can be used interchangeably.

| Verilog | Moore Dialect |
|-------------|--------------------|
| `shortreal` | `!moore.shortreal` |
| `real` | `!moore.real` |
| `realtime` | `!moore.real` |
}];
}

def ShortRealType : MooreTypeDef<"ShortReal", [], "moore::PackedType"> {
let mnemonic = "shortreal";
let summary = "a SystemVerilog short real type";
let description = [{
The shortreal data type is the same as a C float.
}];
}

Expand Down Expand Up @@ -421,6 +426,10 @@ def BitType : MooreType<CPred<[{
}];
}

def FloatType : MooreType<Or<[RealType.predicate, ShortRealType.predicate]>, "float point type in moore", "moore::PackedType">;

def NumericType : MooreType<Or<[FloatType.predicate, SimpleBitVectorType.predicate]>, "numeric type in moore", "moore::PackedType">;

/// A packed or unpacked array type with a fixed size.
def AnyStaticArrayType : MooreType<
Or<[ArrayType.predicate, UnpackedArrayType.predicate]>,
Expand Down
2 changes: 2 additions & 0 deletions include/circt/Dialect/Sim/SimOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static inline mlir::Value getFormattedValue(mlir::Operation *fmtOp) {
return fmt.getValue();
if (auto fmt = llvm::dyn_cast_or_null<circt::sim::FormatCharOp>(fmtOp))
return fmt.getValue();
if (auto fmt = llvm::dyn_cast_or_null<circt::sim::FormatFloatOp>(fmtOp))
return fmt.getValue();
return {};
}

Expand Down
14 changes: 14 additions & 0 deletions include/circt/Dialect/Sim/SimOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,20 @@ def FormatCharOp : SimOp<"fmt.char", [Pure]> {
let assemblyFormat = "$value attr-dict `:` qualified(type($value))";
}

def FormatFloatOp : SimOp<"fmt.float", [Pure]> {
let summary = "Float format specifier";
let description = [{
}];
Comment on lines +283 to +284
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let description = [{
}];


let arguments = (ins AnyFloat:$value);
let results = (outs FormatStringType:$result);

let hasFolder = true;

let assemblyFormat = "$value attr-dict `:` qualified(type($value))";
}


def FormatStringConcatOp : SimOp<"fmt.concat", [Pure]> {
let summary = "Concatenate format strings";
let description = [{
Expand Down
40 changes: 34 additions & 6 deletions lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "ImportVerilogInternals.h"
#include "circt/Dialect/Moore/MooreTypes.h"
#include "slang/ast/SystemSubroutine.h"
#include "slang/syntax/AllSyntax.h"

Expand Down Expand Up @@ -221,12 +222,32 @@ struct RvalueExprVisitor {
// pass them into a binary op.
template <class ConcreteOp>
Value createBinary(Value lhs, Value rhs) {
lhs = context.convertToSimpleBitVector(lhs);
if (!lhs)
return {};
rhs = context.convertToSimpleBitVector(rhs);
if (!rhs)
return {};
auto lhsType = lhs.getType();
auto rhsType = rhs.getType();

// The result of using logical or relational operators or the inside operator on real operands shall be a
// single-bit scalar value.
// For other operators, if any operand, except before the ? in the conditional operator, is real, the result is
// real. Otherwise, if any operand, except before the ? in the conditional operator, is shortreal, the result is
// shortreal.
if(isa<moore::RealType>(lhsType) || isa<moore::RealType>(rhsType)) {
if(!isa<moore::RealType>(lhsType))
lhs = builder.create<moore::ConversionOp>(lhs.getLoc(), moore::RealType::get(context.getContext()), lhs);
if(!isa<moore::RealType>(rhsType))
rhs = builder.create<moore::ConversionOp>(rhs.getLoc(), moore::RealType::get(context.getContext()), rhs);
} else if(isa<moore::ShortRealType>(lhsType) || isa<moore::ShortRealType>(rhsType)) {
if(!isa<moore::ShortRealType>(lhsType))
lhs = builder.create<moore::ConversionOp>(lhs.getLoc(), moore::ShortRealType::get(context.getContext()), lhs);
if(!isa<moore::ShortRealType>(rhsType))
rhs = builder.create<moore::ConversionOp>(rhs.getLoc(), moore::ShortRealType::get(context.getContext()), rhs);
Comment on lines +228 to +242
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to limit code <= 80 chars.

} else {
lhs = context.convertToSimpleBitVector(lhs);
if (!lhs)
return {};
rhs = context.convertToSimpleBitVector(rhs);
if (!rhs)
return {};
}
return builder.create<ConcreteOp>(loc, lhs, rhs);
}

Expand Down Expand Up @@ -879,6 +900,10 @@ struct RvalueExprVisitor {
return builder.create<moore::ConcatOp>(loc, slicedOperands);
}

Value visit(const slang::ast::RealLiteral &expr) {
return builder.create<moore::RealLiteralOp>(loc, builder.getF64FloatAttr(expr.getValue()));
}

/// Emit an error for all other expressions.
template <typename T>
Value visit(T &&node) {
Expand Down Expand Up @@ -1243,6 +1268,9 @@ Value Context::materializeConversion(Type type, Value value, bool isSigned,
return value;
auto dstPacked = dyn_cast<moore::PackedType>(type);
auto srcPacked = dyn_cast<moore::PackedType>(value.getType());
if(isa<moore::RealType>(type) || isa<moore::ShortRealType>(type)) {
return builder.create<moore::ConversionOp>(value.getLoc(), type, value);
}

// Resize the value if needed.
if (dstPacked && srcPacked && dstPacked.getBitSize() &&
Expand Down
10 changes: 10 additions & 0 deletions lib/Conversion/ImportVerilog/FormatStrings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ struct FormatStringParser {
return mlir::emitError(argLoc)
<< "expression cannot be formatted as string";

case 'f':
return emitFloat(arg, options);

default:
return mlir::emitError(loc)
<< "unsupported format specifier `" << fullSpecifier << "`";
Expand Down Expand Up @@ -182,6 +185,13 @@ struct FormatStringParser {
return success();
}

LogicalResult emitFloat(const slang::ast::Expression &arg, const FormatOptions &options) {
auto value = context.convertRvalueExpression(arg);

fragments.push_back(builder.create<moore::FormatFloatOp>(loc, value));
return success();
}

/// Emit an expression argument with the appropriate default formatting.
LogicalResult emitDefault(const slang::ast::Expression &expr) {
FormatOptions options;
Expand Down
12 changes: 11 additions & 1 deletion lib/Conversion/ImportVerilog/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//

#include "ImportVerilogInternals.h"
#include "circt/Dialect/Moore/MooreTypes.h"
#include "slang/ast/types/AllTypes.h"
#include "slang/syntax/AllSyntax.h"

using namespace circt;
Expand Down Expand Up @@ -36,7 +38,15 @@ struct TypeVisitor {
}

Type visit(const slang::ast::FloatingType &type) {
return moore::RealType::get(context.getContext());
switch(type.floatKind) {
case slang::ast::FloatingType::ShortReal:
return moore::ShortRealType::get(context.getContext());
case slang::ast::FloatingType::Real:
case slang::ast::FloatingType::RealTime:
return moore::RealType::get(context.getContext());
default:
return {};
}
}

Type visit(const slang::ast::PredefinedIntegerType &type) {
Expand Down
13 changes: 13 additions & 0 deletions lib/Conversion/MooreToCore/MooreToCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,18 @@ struct FormatIntOpConversion : public OpConversionPattern<FormatIntOp> {
}
};

struct FormatFloatOpConversion : public OpConversionPattern<FormatFloatOp> {
using OpConversionPattern::OpConversionPattern;

LogicalResult
matchAndRewrite(FormatFloatOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
// TODO: These should honor the width, alignment, and padding.
return success();
}
};


struct DisplayBIOpConversion : public OpConversionPattern<DisplayBIOp> {
using OpConversionPattern::OpConversionPattern;

Expand Down Expand Up @@ -1730,6 +1742,7 @@ static void populateOpConversion(RewritePatternSet &patterns,
FormatLiteralOpConversion,
FormatConcatOpConversion,
FormatIntOpConversion,
FormatFloatOpConversion,
DisplayBIOpConversion
>(typeConverter, context);
// clang-format on
Expand Down
4 changes: 4 additions & 0 deletions lib/Dialect/Moore/MooreTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ Domain PackedType::getDomain() const {
.Case<IntType>([&](auto type) { return type.getDomain(); })
.Case<ArrayType, OpenArrayType>(
[&](auto type) { return type.getElementType().getDomain(); })
.Case<ShortRealType>([](auto) { return Domain::TwoValued;})
.Case<RealType>([](auto) { return Domain::TwoValued; })
.Case<StructType, UnionType>([](auto type) {
for (const auto &member : type.getMembers())
if (member.type.getDomain() == Domain::FourValued)
Expand Down Expand Up @@ -143,6 +145,8 @@ std::optional<unsigned> PackedType::getBitSize() const {
}
return size;
})
.Case<ShortRealType>([](auto) { return 32; })
.Case<RealType>([](auto) { return 64; })
.Default([](auto) { return std::nullopt; });
}

Expand Down
11 changes: 11 additions & 0 deletions lib/Dialect/Sim/SimOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ OpFoldResult FormatCharOp::fold(FoldAdaptor adaptor) {
return {};
}

OpFoldResult FormatFloatOp::fold(FoldAdaptor adaptor) {
if (auto floatAttr = llvm::dyn_cast_or_null<FloatAttr>(adaptor.getValue())) {
SmallVector<char, 32> strBuf;
floatAttr.getValue().toString(strBuf);
return StringAttr::get(getContext(), Twine(strBuf));
}

return {};
}


static StringAttr concatLiterals(MLIRContext *ctxt, ArrayRef<StringRef> lits) {
assert(!lits.empty() && "No literals to concatenate");
if (lits.size() == 1)
Expand Down
Loading
Loading