[Moore] Make simple bit vectors a proper MLIR type (#7011)

The core type most SystemVerilog expressions are interested in and
operate on is a "simple bit vector type". These are individual integer
atoms like `bit` or `logic`, integral types like `int`, or packed arrays
with a single dimension and an integer atom inner type, like
`bit [42:0]`. So in a nutshell, simple bit vector types are MLIR's `i42`
in the two-valued (`bit`) case, or the four-valued equivalent (`logic`).

Up until this point, the Moore dialect reflected this pattern by
providing and `IntType` for the integer atoms like `bit` and `int`, and
using the `PackedRangeDim` for single dimension vectors of `bit`. A
`SimpleBitVectorType` helper struct would then summarize the _actual_
bit vector that was expressed by the packed range and integer atom. This
makes working with the types in TableGen files very annoying, since the
thing you are actually interested in -- the simple bit vector -- is not
a propery MLIR type, but more like a helper struct on the side.

This commit rips out the existing `IntType` and its composition with a
packed array dimension, and replaces it with a proper simple bit vector
type that is actually an MLIR type. As a result, SystemVerilog types
like `int unsigned`, `bit [42:0]`, `reg`, `logic signed [31:0]`, or
`integer` are all translated into the same MLIR type. This new simple
bit vector MLIR type retains the `IntType` name, and prints as
`!moore.i42` or `!moore.l42`, depending on whether it is a two-valued or
four-valued integer. Single `bit` and `logic` atoms become `i1` and `l1`
respectively.

This makes the Moore type system a lot easier to work with and removes
a lot of unnecessary noise. Operations can now simply use
`llvm::isa<IntType>` to check if a value is a simple bit vector.
This commit is contained in:
Fabian Schuiki 2024-05-09 15:52:20 -07:00 committed by GitHub
parent 5ac765214c
commit 6a2b628129
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 664 additions and 1106 deletions

View File

@ -14,6 +14,22 @@ In contrast, the `sv` dialect is geared towards emission of SystemVerilog text,
## Types
### Simple Bit Vector Type
The `moore.iN` and `moore.lN` types represent a two-valued or four-valued simple bit vector of width `N`.
| Verilog | Moore Dialect |
|------------|---------------|
| `bit` | `!moore.i1` |
| `logic` | `!moore.l1` |
| `reg` | `!moore.l1` |
| `byte` | `!moore.i8` |
| `shortint` | `!moore.i16` |
| `int` | `!moore.i32` |
| `integer` | `!moore.l32` |
| `longint` | `!moore.i64` |
| `time` | `!moore.l64` |
[include "Dialects/MooreTypes.md"]

View File

@ -25,30 +25,6 @@ MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Moore, moore);
// Types
//===----------------------------------------------------------------------===//
enum MooreIntKind {
// The integer vector types. These are the builtin single-bit integer types.
/// A `bit`.
MooreBit,
/// A `logic`.
MooreLogic,
/// A `reg`.
MooreReg,
// The integer atom types. These are the builtin multi-bit integer types.
/// A `byte`.
MooreByte,
/// A `shortint`.
MooreShortInt,
/// An `int`.
MooreInt,
/// A `longint`.
MooreLongInt,
/// An `integer`.
MooreInteger,
/// A `time`.
MooreTime,
};
enum MooreRealKind {
/// A `shortreal`.
MooreShortReal,
@ -66,15 +42,11 @@ MLIR_CAPI_EXPORTED MlirType mooreStringTypeGet(MlirContext ctx);
MLIR_CAPI_EXPORTED MlirType mooreChandleTypeGet(MlirContext ctx);
/// Create an event type.
MLIR_CAPI_EXPORTED MlirType mooreEventTypeGet(MlirContext ctx);
/// Create an int type.
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGet(MlirContext ctx,
enum MooreIntKind kind);
/// Create a `logic` type.
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetLogic(MlirContext ctx);
/// Create an `int` type.
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetInt(MlirContext ctx);
/// Create a `time` type.
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetTime(MlirContext ctx);
/// Create a two-valued simple bit vector type.
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetInt(MlirContext ctx, unsigned width);
/// Create a four-valued simple bit vector type.
MLIR_CAPI_EXPORTED MlirType mooreIntTypeGetLogic(MlirContext ctx,
unsigned width);
/// Create a real type.
MLIR_CAPI_EXPORTED MlirType mooreRealTypeGet(MlirContext ctx,
enum MooreRealKind kind);
@ -104,18 +76,10 @@ MLIR_CAPI_EXPORTED MlirType mooreUnpackedQueueDimTypeGet(MlirType inner);
/// Create a unpacked queue dimension type with bound.
MLIR_CAPI_EXPORTED MlirType
mooreUnpackedQueueDimTypeGetWithBound(MlirType inner, unsigned bound);
// TODO: PackedStructType
// TODO: UnpackedStructType
/// Create a simple bit-vector type.
MLIR_CAPI_EXPORTED MlirType mooreSimpleBitVectorTypeGet(MlirContext ctx,
bool isFourValued,
unsigned size);
/// Checks whether the passed UnpackedType is a two-valued type.
MLIR_CAPI_EXPORTED bool mooreIsTwoValuedType(MlirType type);
/// Checks whether the passed UnpackedType is a four-valued type.
MLIR_CAPI_EXPORTED bool mooreIsFourValuedType(MlirType type);
/// Checks whether the passed type is a simple bit-vector.
MLIR_CAPI_EXPORTED bool mooreIsSimpleBitVectorType(MlirType type);
/// Returns the size of a simple bit-vector type in bits.
MLIR_CAPI_EXPORTED unsigned mooreGetSimpleBitVectorSize(MlirType type);
#ifdef __cplusplus
}

View File

@ -22,6 +22,17 @@ include "mlir/Interfaces/SideEffectInterfaces.td"
class MooreOp<string mnemonic, list<Trait> traits = []> :
Op<MooreDialect, mnemonic, traits>;
//===----------------------------------------------------------------------===//
// Constraints
//===----------------------------------------------------------------------===//
class ResultIsSingleBitMatchingInputDomain<string result, string input> :
TypesMatchWith<"result is single bit matching input domain",
input, result, [{
IntType::get($_self.getContext(), 1,
llvm::cast<UnpackedType>($_self).getDomain())
}]>;
//===----------------------------------------------------------------------===//
// Structure
//===----------------------------------------------------------------------===//
@ -277,8 +288,8 @@ def ConstantOp : MooreOp<"constant", [Pure]> {
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
let builders = [
OpBuilder<(ins "Type":$type, "const APInt &":$value)>,
OpBuilder<(ins "Type":$type, "int64_t":$value)>,
OpBuilder<(ins "IntType":$type, "const APInt &":$value)>,
OpBuilder<(ins "IntType":$type, "int64_t":$value)>,
];
}
@ -353,12 +364,7 @@ def NotOp : MooreOp<"not", [Pure, SameOperandsAndResultType]> {
class ReduceOpBase<string mnemonic, string operatorName> : MooreOp<mnemonic, [
Pure,
TypesMatchWith<"result is single bit of input", "input", "result", [{
llvm::cast<UnpackedType>($_self)
.getSimpleBitVector()
.toSingleBit()
.getType($_self.getContext())
}]>
ResultIsSingleBitMatchingInputDomain<"result", "input">
]> {
let arguments = (ins SimpleBitVectorType:$input);
let results = (outs AnySingleBitType:$result);
@ -382,11 +388,7 @@ def ReduceXorOp : ReduceOpBase<"reduce_xor", "XOR">;
def BoolCastOp : MooreOp<"bool_cast", [
Pure,
TypesMatchWith<"result is single bit matching input domain",
"input", "result", [{
IntType::get($_self.getContext(),
IntType::getAtomForDomain(llvm::cast<UnpackedType>($_self).getDomain()))
}]>
ResultIsSingleBitMatchingInputDomain<"result", "input">
]> {
let summary = "Cast a value to a single bit boolean";
let description = [{
@ -574,11 +576,7 @@ class LogicalEqOpBase<string mnemonic> : MooreOp<mnemonic, [
Pure,
Commutative,
SameTypeOperands,
TypesMatchWith<"result is single bit matching input domain",
"lhs", "result", [{
IntType::get($_self.getContext(),
IntType::getAtomForDomain(llvm::cast<UnpackedType>($_self).getDomain()))
}]>
ResultIsSingleBitMatchingInputDomain<"result", "lhs">
]> {
let description = [{
Compares the bits in the left- and right-hand side operand and returns a
@ -631,11 +629,7 @@ def CaseNeOp : CaseEqOpBase<"case_ne"> { let summary = "Case inequality"; }
class WildcardEqOpBase<string mnemonic> : MooreOp<mnemonic, [
Pure,
SameTypeOperands,
TypesMatchWith<"result is single bit matching input domain",
"lhs", "result", [{
IntType::get($_self.getContext(),
IntType::getAtomForDomain(llvm::cast<UnpackedType>($_self).getDomain()))
}]>
ResultIsSingleBitMatchingInputDomain<"result", "lhs">
]> {
let description = [{
Compares the bits in the left- and right-hand side operand and returns a
@ -664,11 +658,7 @@ def WildcardNeOp : WildcardEqOpBase<"wildcard_ne"> {
class RelationalOpBase<string mnemonic> : MooreOp<mnemonic, [
Pure,
SameTypeOperands,
TypesMatchWith<"result is single bit matching input domain",
"lhs", "result", [{
IntType::get($_self.getContext(),
IntType::getAtomForDomain(llvm::cast<UnpackedType>($_self).getDomain()))
}]>
ResultIsSingleBitMatchingInputDomain<"result", "lhs">
]> {
let description = [{
Compares the left- and right-hand side operand and returns a single bit 0,

View File

@ -125,51 +125,6 @@ Os &operator<<(Os &os, const Range &range) {
class PackedType;
/// A simple bit vector type.
///
/// The SystemVerilog standard somewhat loosely defines a "Simple Bit Vector"
/// type. In essence, this is a zero or one-dimensional integer type. For
/// example, `bit`, `logic [0:0]`, `reg [31:0]`, or `int` are SBVs, but `bit
/// [1:0][2:0]`, `int [4:0]`, `bit [5:2]`, or `bit []` are not.
struct SimpleBitVectorType {
/// Create a null SBVT.
SimpleBitVectorType() {}
/// Create a new SBVT with the given domain and size.
SimpleBitVectorType(Domain domain, unsigned size)
: size(size), domain(domain) {
assert(size > 0 && "SBVT requires non-zero size");
}
/// Convert this SBVT to an actual type.
PackedType getType(MLIRContext *context) const;
/// Get a single bit version of this type by setting its size to 1.
SimpleBitVectorType toSingleBit() const {
auto type = *this;
type.size = 1;
return type;
}
/// Check whether this type is equivalent to another.
bool operator==(const SimpleBitVectorType &other) const {
return domain == other.domain && size == other.size;
}
/// Check whether this is a null type.
operator bool() const { return size > 0; }
/// The size of the vector.
unsigned size = 0;
/// The domain, which dictates whether this is a `bit` or `logic` vector.
Domain domain : 8;
};
// NOLINTNEXTLINE(readability-identifier-naming)
inline llvm::hash_code hash_value(const SimpleBitVectorType &x) {
return llvm::hash_combine(x.size, x.domain);
}
namespace detail {
struct RealTypeStorage;
struct IntTypeStorage;
@ -241,40 +196,6 @@ public:
/// a queue, or the core type itself has no known size.
std::optional<unsigned> getBitSize() const;
/// Get this type as a simple bit vector, if it is one. Returns a null type
/// otherwise.
SimpleBitVectorType getSimpleBitVectorOrNull() const;
/// Check whether this is a simple bit vector type.
bool isSimpleBitVector() const { return !!getSimpleBitVectorOrNull(); }
/// Get this type as a simple bit vector. Aborts if it is no simple bit
/// vector.
SimpleBitVectorType getSimpleBitVector() const {
auto sbv = getSimpleBitVectorOrNull();
assert(sbv && "getSimpleBitVector called on type that is no SBV");
return sbv;
}
/// Cast this type to a simple bit vector. Returns null if this type cannot be
/// cast to a simple bit vector.
SimpleBitVectorType castToSimpleBitVectorOrNull() const;
/// Check whether this type can be cast to a simple bit vector type.
bool isCastableToSimpleBitVector() const {
return !!castToSimpleBitVectorOrNull();
}
/// Cast this type to a simple bit vector. Aborts if this type cannot be cast
/// to a simple bit vector.
SimpleBitVectorType castToSimpleBitVector() const {
auto sbv = castToSimpleBitVectorOrNull();
assert(
sbv &&
"castToSimpleBitVector called on type that cannot be cast to an SBV");
return sbv;
}
protected:
using SVType::SVType;
};
@ -332,69 +253,27 @@ protected:
// Packed Integers
//===----------------------------------------------------------------------===//
/// An integer vector or atom type.
/// A signed or unsigned, two- or four-valued bit vector. SystemVerilog calls
/// these "simple bit vectors".
class IntType
: public Type::TypeBase<IntType, PackedType, detail::IntTypeStorage> {
public:
enum Kind {
// The integer vector types. These are the builtin single-bit integer types.
/// A `bit`.
Bit,
/// A `logic`.
Logic,
/// A `reg`.
Reg,
/// Return the width of the integer.
unsigned getWidth() const;
/// Return whether this is a two- or four-valued integer.
Domain getDomain() const;
// The integer atom types. These are the builtin multi-bit integer types.
/// A `byte`.
Byte,
/// A `shortint`.
ShortInt,
/// An `int`.
Int,
/// A `longint`.
LongInt,
/// An `integer`.
Integer,
/// A `time`.
Time,
};
static IntType get(MLIRContext *context, unsigned width, Domain domain);
/// Get the integer type that corresponds to a keyword (like `bit`).
static std::optional<Kind> getKindFromKeyword(StringRef keyword);
/// Get the keyword (like `bit`) for one of the integer types.
static StringRef getKeyword(Kind kind);
/// Get the value domain for one of the integer types.
static Domain getDomain(Kind kind);
/// Get the size of one of the integer types.
static unsigned getBitSize(Kind kind);
/// Get the integer type that corresponds to a single bit of the given domain.
static Kind getAtomForDomain(Domain domain);
/// Get the integer type that corresponds to a domain and bit size. For
/// example, returns `int` for `(TwoValued, 32)`.
static std::optional<Kind> getKindFromDomainAndSize(Domain domain,
unsigned size);
/// Create a signless `bit [width-1:0]` type.
static IntType getInt(MLIRContext *context, unsigned width) {
return get(context, width, Domain::TwoValued);
}
static IntType get(MLIRContext *context, Kind kind);
/// Create a `logic` type.
static IntType getLogic(MLIRContext *context) { return get(context, Logic); }
/// Create a `int` type.
static IntType getInt(MLIRContext *context) { return get(context, Int); }
/// Create a `time` type.
static IntType getTime(MLIRContext *context) { return get(context, Time); }
/// Get the concrete integer vector or atom type.
Kind getKind() const;
/// Get the keyword (like `bit`) for this type.
StringRef getKeyword() const { return getKeyword(getKind()); }
/// Get the value domain for this type.
Domain getDomain() const { return getDomain(getKind()); }
/// Get the size of this type.
unsigned getBitSize() const { return getBitSize(getKind()); }
/// Create a signless `logic [width-1:0]` type.
static IntType getLogic(MLIRContext *context, unsigned width) {
return get(context, width, Domain::FourValued);
}
static constexpr StringLiteral name = "moore.int";

View File

@ -61,24 +61,23 @@ def UnpackedType : MooreType<CPred<"llvm::isa<moore::UnpackedType>($_self)">,
/// A simple bit vector type.
def SimpleBitVectorType : MooreType<CPred<[{
llvm::isa<moore::UnpackedType>($_self) &&
llvm::cast<moore::UnpackedType>($_self).isSimpleBitVector()
}]>, "simple bit vector type", "moore::UnpackedType">;
llvm::isa<moore::IntType>($_self)
}]>, "simple bit vector type", "moore::IntType">;
/// A single bit type (`bit`, `logic`, `reg`).
/// A single two or four-valued bit.
def AnySingleBitType : MooreType<CPred<[{
llvm::isa<moore::IntType>($_self) &&
llvm::cast<moore::IntType>($_self).getBitSize() == 1
llvm::cast<moore::IntType>($_self).getWidth() == 1
}]>, "single bit type", "moore::IntType">;
/// A `bit` type.
/// A single two-valued bit.
def BitType : MooreType<CPred<[{
llvm::isa<moore::IntType>($_self) &&
llvm::cast<moore::IntType>($_self).getBitSize() == 1 &&
llvm::cast<moore::IntType>($_self).getWidth() == 1 &&
llvm::cast<moore::IntType>($_self).getDomain() == moore::Domain::TwoValued
}]>, "`bit` type", "moore::IntType"> {
let builderCall = [{
$_builder.getType<moore::IntType>(IntType::Kind::Bit)
IntType::getInt($_builder.getContext(), 1)
}];
}

View File

@ -26,31 +26,6 @@ MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Moore, moore, MooreDialect)
// Types
//===----------------------------------------------------------------------===//
static IntType::Kind convertMooreIntKind(enum MooreIntKind kind) {
switch (kind) {
case MooreIntKind::MooreBit:
return IntType::Kind::Bit;
case MooreIntKind::MooreLogic:
return IntType::Kind::Logic;
case MooreIntKind::MooreReg:
return IntType::Kind::Reg;
case MooreIntKind::MooreByte:
return IntType::Kind::Byte;
case MooreIntKind::MooreShortInt:
return IntType::Kind::ShortInt;
case MooreIntKind::MooreInt:
return IntType::Kind::Int;
case MooreIntKind::MooreLongInt:
return IntType::Kind::LongInt;
case MooreIntKind::MooreInteger:
return IntType::Kind::Integer;
case MooreIntKind::MooreTime:
return IntType::Kind::Time;
}
llvm_unreachable("All cases should be covered.");
}
static RealType::Kind convertMooreRealKind(enum MooreRealKind kind) {
switch (kind) {
case MooreRealKind::MooreShortReal:
@ -83,24 +58,14 @@ MlirType mooreEventTypeGet(MlirContext ctx) {
return wrap(EventType::get(unwrap(ctx)));
}
/// Create an int type.
MlirType mooreIntTypeGet(MlirContext ctx, enum MooreIntKind kind) {
return wrap(IntType::get(unwrap(ctx), convertMooreIntKind(kind)));
/// Create a two-valued simple bit vector type.
MlirType mooreIntTypeGetInt(MlirContext ctx, unsigned width) {
return wrap(IntType::getInt(unwrap(ctx), width));
}
/// Create a `logic` type.
MlirType mooreIntTypeGetLogic(MlirContext ctx) {
return wrap(IntType::getLogic(unwrap(ctx)));
}
/// Create an `int` type.
MlirType mooreIntTypeGetInt(MlirContext ctx) {
return wrap(IntType::getInt(unwrap(ctx)));
}
/// Create a `time` type.
MlirType mooreIntTypeGetTime(MlirContext ctx) {
return wrap(IntType::getTime(unwrap(ctx)));
/// Create a four-valued simple bit vector type.
MlirType mooreIntTypeGetLogic(MlirContext ctx, unsigned width) {
return wrap(IntType::getLogic(unwrap(ctx), width));
}
/// Create a real type.
@ -161,24 +126,12 @@ MlirType mooreUnpackedQueueDimTypeGetWithBound(MlirType inner, unsigned bound) {
return wrap(UnpackedQueueDim::get(cast<UnpackedType>(unwrap(inner)), bound));
}
/// Create a simple bit-vector type.
MlirType mooreSimpleBitVectorTypeGet(MlirContext ctx, bool isFourValued,
unsigned size) {
Domain domain = isFourValued ? Domain::FourValued : Domain::TwoValued;
return wrap(SimpleBitVectorType(domain, size).getType(unwrap(ctx)));
/// Checks whether the passed UnpackedType is a two-valued type.
bool mooreIsTwoValuedType(MlirType type) {
return cast<UnpackedType>(unwrap(type)).getDomain() == Domain::TwoValued;
}
/// Checks whether the passed UnpackedType is a four-valued type.
bool mooreIsFourValuedType(MlirType type) {
return cast<UnpackedType>(unwrap(type)).getDomain() == Domain::FourValued;
}
/// Checks whether the passed type is a simple bit-vector.
bool mooreIsSimpleBitVectorType(MlirType type) {
return cast<UnpackedType>(unwrap(type)).isSimpleBitVector();
}
/// Returns the size of a simple bit-vector type in bits.
unsigned mooreGetSimpleBitVectorSize(MlirType type) {
return cast<UnpackedType>(unwrap(type)).getSimpleBitVector().size;
}

View File

@ -27,13 +27,8 @@ struct ExprVisitor {
Value convertToSimpleBitVector(Value value) {
if (!value)
return {};
if (auto type = dyn_cast_or_null<moore::UnpackedType>(value.getType())) {
if (type.isSimpleBitVector())
return value;
if (auto sbvt = type.castToSimpleBitVectorOrNull())
return builder.create<moore::ConversionOp>(
loc, sbvt.getType(builder.getContext()), value);
}
if (isa<moore::IntType>(value.getType()))
return value;
mlir::emitError(loc, "expression of type ")
<< value.getType() << " cannot be cast to a simple bit vector";
return {};
@ -125,7 +120,8 @@ struct ExprVisitor {
if (!preValue)
return {};
preValue = builder.create<moore::ReadLValueOp>(loc, preValue);
auto one = builder.create<moore::ConstantOp>(loc, preValue.getType(), 1);
auto one = builder.create<moore::ConstantOp>(
loc, cast<moore::IntType>(preValue.getType()), 1);
auto postValue =
isInc ? builder.create<moore::AddOp>(loc, preValue, one).getResult()
: builder.create<moore::SubOp>(loc, preValue, one).getResult();
@ -352,7 +348,8 @@ struct ExprVisitor {
return {};
}
auto truncValue = value.as<uint64_t>().value();
return builder.create<moore::ConstantOp>(loc, type, truncValue);
return builder.create<moore::ConstantOp>(loc, cast<moore::IntType>(type),
truncValue);
}
// Handle `'0`, `'1`, `'x`, and `'z` literals.

View File

@ -209,7 +209,7 @@ struct StmtVisitor {
auto count = context.convertExpression(stmt.count);
if (!count)
return failure();
auto type = count.getType();
auto type = cast<moore::IntType>(count.getType());
auto whileOp = builder.create<scf::WhileOp>(loc, type, count);
OpBuilder::InsertionGuard guard(builder);

View File

@ -11,6 +11,7 @@
using namespace circt;
using namespace ImportVerilog;
using moore::Domain;
namespace {
struct TypeVisitor {
@ -18,22 +19,16 @@ struct TypeVisitor {
Location loc;
TypeVisitor(Context &context, Location loc) : context(context), loc(loc) {}
// Handle simple bit vector types such as `bit`, `int`, or `bit [41:0]`.
Type getSimpleBitVectorType(const slang::ast::IntegralType &type) {
return moore::IntType::get(context.getContext(), type.bitWidth,
type.isFourState ? Domain::FourValued
: Domain::TwoValued);
}
// NOLINTBEGIN(misc-no-recursion)
Type visit(const slang::ast::ScalarType &type) {
moore::IntType::Kind kind;
switch (type.scalarKind) {
case slang::ast::ScalarType::Bit:
kind = moore::IntType::Bit;
break;
case slang::ast::ScalarType::Logic:
kind = moore::IntType::Logic;
break;
case slang::ast::ScalarType::Reg:
kind = moore::IntType::Reg;
break;
}
return moore::IntType::get(context.getContext(), kind);
return getSimpleBitVectorType(type);
}
Type visit(const slang::ast::FloatingType &type) {
@ -54,32 +49,15 @@ struct TypeVisitor {
}
Type visit(const slang::ast::PredefinedIntegerType &type) {
moore::IntType::Kind kind;
switch (type.integerKind) {
case slang::ast::PredefinedIntegerType::Int:
kind = moore::IntType::Int;
break;
case slang::ast::PredefinedIntegerType::ShortInt:
kind = moore::IntType::ShortInt;
break;
case slang::ast::PredefinedIntegerType::LongInt:
kind = moore::IntType::LongInt;
break;
case slang::ast::PredefinedIntegerType::Integer:
kind = moore::IntType::Integer;
break;
case slang::ast::PredefinedIntegerType::Byte:
kind = moore::IntType::Byte;
break;
case slang::ast::PredefinedIntegerType::Time:
kind = moore::IntType::Time;
break;
}
return moore::IntType::get(context.getContext(), kind);
return getSimpleBitVectorType(type);
}
Type visit(const slang::ast::PackedArrayType &type) {
// Handle simple bit vector types of the form `bit [41:0]`.
if (type.elementType.as_if<slang::ast::ScalarType>())
return getSimpleBitVectorType(type);
// Handle all other packed arrays.
auto innerType = type.elementType.visit(*this);
if (!innerType)
return {};

View File

@ -160,16 +160,13 @@ struct BoolCastOpConversion : public OpConversionPattern<BoolCastOp> {
LogicalResult
matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
if (cast<UnpackedType>(op.getInput().getType())
.castToSimpleBitVectorOrNull()) {
Type resultType = typeConverter->convertType(op.getInput().getType());
Type resultType = typeConverter->convertType(op.getInput().getType());
if (isa_and_nonnull<IntegerType>(resultType)) {
Value zero = rewriter.create<hw::ConstantOp>(op->getLoc(), resultType, 0);
rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
adaptor.getInput(), zero);
return success();
}
return failure();
}
};
@ -415,15 +412,13 @@ static void populateLegality(ConversionTarget &target) {
static void populateTypeConversion(TypeConverter &typeConverter) {
typeConverter.addConversion([&](IntType type) {
return mlir::IntegerType::get(type.getContext(), type.getBitSize());
return mlir::IntegerType::get(type.getContext(), type.getWidth());
});
// Directly map simple bit vector types to a compact integer type. This needs
// to be added after all of the other conversions above, such that SBVs
// conversion gets tried first before any of the others.
typeConverter.addConversion([&](UnpackedType type) -> std::optional<Type> {
if (auto sbv = type.getSimpleBitVectorOrNull())
return mlir::IntegerType::get(type.getContext(), sbv.size);
if (isa<UnpackedRangeDim, PackedRangeDim>(type))
return mlir::IntegerType::get(type.getContext(),
type.getBitSize().value());

View File

@ -74,37 +74,31 @@ ParseResult ConstantOp::parse(OpAsmParser &parser, OperationState &result) {
parser.parseOptionalAttrDict(result.attributes) || parser.parseColon())
return failure();
// Parse the result type..
UnpackedType type;
auto typeLoc = parser.getCurrentLocation();
// Parse the result type.
IntType type;
if (parser.parseType(type))
return failure();
// Ensure that the result type is a simple bit vector type.
auto sbvt = type.getSimpleBitVectorOrNull();
if (!sbvt)
return parser.emitError(typeLoc, "expected simple bit vector type");
// Extend or truncate the constant value to match the size of the type.
if (sbvt.size > value.getBitWidth()) {
if (type.getWidth() > value.getBitWidth()) {
// sext is always safe here, even for unsigned values, because the
// parseOptionalInteger method will return something with a zero in the
// top bits if it is a positive number.
value = value.sext(sbvt.size);
} else if (sbvt.size < value.getBitWidth()) {
value = value.sext(type.getWidth());
} else if (type.getWidth() < value.getBitWidth()) {
// The parser can return an unnecessarily wide result with leading
// zeros. This isn't a problem, but truncating off bits is bad.
unsigned neededBits =
value.isNegative() ? value.getSignificantBits() : value.getActiveBits();
if (sbvt.size < neededBits)
if (type.getWidth() < neededBits)
return parser.emitError(valueLoc,
"constant out of range for result type ")
<< type;
value = value.trunc(sbvt.size);
value = value.trunc(type.getWidth());
}
// Build the attribute and op.
auto attrType = IntegerType::get(parser.getContext(), sbvt.size);
auto attrType = IntegerType::get(parser.getContext(), type.getWidth());
auto attrValue = IntegerAttr::get(attrType, value);
result.addAttribute("value", attrValue);
@ -113,32 +107,30 @@ ParseResult ConstantOp::parse(OpAsmParser &parser, OperationState &result) {
}
LogicalResult ConstantOp::verify() {
auto sbvt = getType().getSimpleBitVector();
auto width = getValue().getBitWidth();
if (width != sbvt.size)
auto attrWidth = getValue().getBitWidth();
auto typeWidth = getType().getWidth();
if (attrWidth != typeWidth)
return emitError("attribute width ")
<< width << " does not match return type's width " << sbvt.size;
<< attrWidth << " does not match return type's width " << typeWidth;
return success();
}
void ConstantOp::build(OpBuilder &builder, OperationState &result, Type type,
void ConstantOp::build(OpBuilder &builder, OperationState &result, IntType type,
const APInt &value) {
auto sbvt = cast<UnpackedType>(type).getSimpleBitVector();
assert(sbvt.size == value.getBitWidth() &&
"APInt width must match simple bit vector's bit width");
assert(type.getWidth() == value.getBitWidth() &&
"APInt width must match type width");
build(builder, result, type,
builder.getIntegerAttr(builder.getIntegerType(sbvt.size), value));
builder.getIntegerAttr(builder.getIntegerType(type.getWidth()), value));
}
/// This builder allows construction of small signed integers like 0, 1, -1
/// matching a specified MLIR type. This shouldn't be used for general constant
/// folding because it only works with values that can be expressed in an
/// `int64_t`.
void ConstantOp::build(OpBuilder &builder, OperationState &result, Type type,
void ConstantOp::build(OpBuilder &builder, OperationState &result, IntType type,
int64_t value) {
auto sbvt = cast<UnpackedType>(type).getSimpleBitVector();
build(builder, result, type,
APInt(sbvt.size, (uint64_t)value, /*isSigned=*/true));
APInt(type.getWidth(), (uint64_t)value, /*isSigned=*/true));
}
//===----------------------------------------------------------------------===//
@ -150,14 +142,14 @@ LogicalResult ConcatOp::inferReturnTypes(
DictionaryAttr attrs, mlir::OpaqueProperties properties,
mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
Domain domain = Domain::TwoValued;
unsigned size = 0;
unsigned width = 0;
for (auto operand : operands) {
auto type = cast<UnpackedType>(operand.getType()).getSimpleBitVector();
if (type.domain == Domain::FourValued)
auto type = cast<IntType>(operand.getType());
if (type.getDomain() == Domain::FourValued)
domain = Domain::FourValued;
size += type.size;
width += type.getWidth();
}
results.push_back(SimpleBitVectorType(domain, size).getType(context));
results.push_back(IntType::get(context, width, domain));
return success();
}

View File

@ -59,25 +59,6 @@ StringRef moore::getKeywordFromSign(const Sign &sign) {
llvm_unreachable("all signs should be handled");
}
//===----------------------------------------------------------------------===//
// Simple Bit Vector Type
//===----------------------------------------------------------------------===//
PackedType SimpleBitVectorType::getType(MLIRContext *context) const {
if (!*this)
return {};
// Build the core integer bit type.
auto kind = domain == Domain::TwoValued ? IntType::Bit : IntType::Logic;
auto intType = IntType::get(context, kind);
// If the vector is wider than a single bit, or the dimension was explicit in
// the original type, add a dimension around the bit type.
if (size > 1)
return PackedRangeDim::get(intType, size);
return intType;
}
//===----------------------------------------------------------------------===//
// Unpacked Type
//===----------------------------------------------------------------------===//
@ -110,57 +91,6 @@ std::optional<unsigned> UnpackedType::getBitSize() const {
.Default([](auto) { return std::nullopt; });
}
/// Map an `IntType` to the corresponding SBVT. Never returns a null type.
static SimpleBitVectorType getSimpleBitVectorFromIntType(IntType type) {
return SimpleBitVectorType(type.getDomain(), type.getBitSize());
}
SimpleBitVectorType UnpackedType::getSimpleBitVectorOrNull() const {
return TypeSwitch<UnpackedType, SimpleBitVectorType>(*this)
.Case<IntType>([](auto type) {
// Integer types trivially map to SBVTs.
return getSimpleBitVectorFromIntType(type);
})
.Case<PackedRangeDim>([](auto rangeType) {
// Inner type must be an integer.
auto innerType = llvm::dyn_cast<IntType>(rangeType.getInner());
if (!innerType)
return SimpleBitVectorType{};
// Inner type must be a single-bit integer. Cannot have integer atom
// vectors like `int [31:0]`.
if (innerType.getBitSize() > 1)
return SimpleBitVectorType{};
// Range must be have non-zero size, and go downwards to zero.
auto range = rangeType.getRange();
if (range.size == 0 || range.offset != 0 || range.dir != RangeDir::Down)
return SimpleBitVectorType{};
auto sbv = getSimpleBitVectorFromIntType(innerType);
sbv.size = range.size;
return sbv;
})
.Default([](auto) { return SimpleBitVectorType{}; });
}
SimpleBitVectorType UnpackedType::castToSimpleBitVectorOrNull() const {
// If the type is already a valid SBVT, return that immediately without
// casting.
if (auto sbv = getSimpleBitVectorOrNull())
return sbv;
// All packed types with a known size (i.e., with no `[]` dimensions) can be
// cast to an SBVT.
auto packed = llvm::dyn_cast<PackedType>(*this);
if (!packed)
return {};
auto bitSize = packed.getBitSize();
if (!bitSize || *bitSize == 0)
return {};
return SimpleBitVectorType(packed.getDomain(), *bitSize);
}
//===----------------------------------------------------------------------===//
// Packed Type
//===----------------------------------------------------------------------===//
@ -177,7 +107,7 @@ Domain PackedType::getDomain() const {
std::optional<unsigned> PackedType::getBitSize() const {
return TypeSwitch<PackedType, std::optional<unsigned>>(*this)
.Case<VoidType>([](auto) { return 0; })
.Case<IntType>([](auto type) { return type.getBitSize(); })
.Case<IntType>([](auto type) { return type.getWidth(); })
.Case<PackedUnsizedDim>([](auto) { return std::nullopt; })
.Case<PackedRangeDim>([](auto type) -> std::optional<unsigned> {
if (auto size = type.getInner().getBitSize())
@ -197,143 +127,32 @@ namespace moore {
namespace detail {
struct IntTypeStorage : TypeStorage {
using KeyTy = unsigned;
using Kind = IntType::Kind;
IntTypeStorage(KeyTy key) : kind(static_cast<Kind>(key)) {}
static KeyTy pack(Kind kind) { return static_cast<unsigned>(kind); }
bool operator==(const KeyTy &key) const { return pack(kind) == key; }
IntTypeStorage(KeyTy key)
: width(key >> 1), domain(static_cast<Domain>((key >> 0) & 1)) {}
static KeyTy pack(unsigned width, Domain domain) {
assert((width >> 31) == 0 && "width must fit in 31 bits");
return width << 1 | unsigned(domain) << 0;
}
bool operator==(const KeyTy &key) const { return pack(width, domain) == key; }
static IntTypeStorage *construct(TypeStorageAllocator &allocator,
const KeyTy &key) {
return new (allocator.allocate<IntTypeStorage>()) IntTypeStorage(key);
}
Kind kind;
unsigned width;
Domain domain;
};
} // namespace detail
} // namespace moore
} // namespace circt
std::optional<IntType::Kind> IntType::getKindFromKeyword(StringRef keyword) {
return StringSwitch<std::optional<Kind>>(keyword)
.Case("bit", IntType::Bit)
.Case("logic", IntType::Logic)
.Case("reg", IntType::Reg)
.Case("byte", IntType::Byte)
.Case("shortint", IntType::ShortInt)
.Case("int", IntType::Int)
.Case("longint", IntType::LongInt)
.Case("integer", IntType::Integer)
.Case("time", IntType::Time)
.Default({});
IntType IntType::get(MLIRContext *context, unsigned width, Domain domain) {
return Base::get(context, detail::IntTypeStorage::pack(width, domain));
}
StringRef IntType::getKeyword(Kind kind) {
switch (kind) {
case IntType::Bit:
return "bit";
case IntType::Logic:
return "logic";
case IntType::Reg:
return "reg";
case IntType::Byte:
return "byte";
case IntType::ShortInt:
return "shortint";
case IntType::Int:
return "int";
case IntType::LongInt:
return "longint";
case IntType::Integer:
return "integer";
case IntType::Time:
return "time";
}
llvm_unreachable("all kinds should be handled");
}
Domain IntType::getDomain(Kind kind) {
switch (kind) {
case IntType::Bit:
case IntType::Byte:
case IntType::ShortInt:
case IntType::Int:
case IntType::LongInt:
case IntType::Time:
return Domain::TwoValued;
case IntType::Logic:
case IntType::Reg:
case IntType::Integer:
return Domain::FourValued;
}
llvm_unreachable("all kinds should be handled");
}
unsigned IntType::getBitSize(Kind kind) {
switch (kind) {
case IntType::Bit:
case IntType::Logic:
case IntType::Reg:
return 1;
case IntType::Byte:
return 8;
case IntType::ShortInt:
return 16;
case IntType::Int:
return 32;
case IntType::LongInt:
return 64;
case IntType::Integer:
return 32;
case IntType::Time:
return 64;
}
llvm_unreachable("all kinds should be handled");
}
IntType::Kind IntType::getAtomForDomain(Domain domain) {
switch (domain) {
case Domain::TwoValued:
return IntType::Bit;
case Domain::FourValued:
return IntType::Logic;
}
llvm_unreachable("all domains should be handled");
}
std::optional<IntType::Kind> IntType::getKindFromDomainAndSize(Domain domain,
unsigned size) {
if (size == 1)
return getAtomForDomain(domain);
switch (domain) {
case Domain::TwoValued:
switch (size) {
case 8:
return IntType::Byte;
case 16:
return IntType::ShortInt;
case 32:
return IntType::Int;
case 64:
return IntType::LongInt;
default:
return {};
}
case Domain::FourValued:
switch (size) {
case 32:
return IntType::Integer;
default:
return {};
}
}
llvm_unreachable("all domains should be handled");
}
IntType IntType::get(MLIRContext *context, Kind kind) {
return Base::get(context, detail::IntTypeStorage::pack(kind));
}
IntType::Kind IntType::getKind() const { return getImpl()->kind; }
unsigned IntType::getWidth() const { return getImpl()->width; }
Domain IntType::getDomain() const { return getImpl()->domain; }
//===----------------------------------------------------------------------===//
// Unpacked Reals
@ -720,8 +539,14 @@ static OptionalParseResult customTypeParser(DialectAsmParser &parser,
}
// Packed primary types.
if (auto kind = IntType::getKindFromKeyword(mnemonic)) {
return yieldPacked(IntType::get(context, *kind));
if (mnemonic.size() > 1 && (mnemonic[0] == 'i' || mnemonic[0] == 'l') &&
isdigit(mnemonic[1])) {
auto domain = mnemonic[0] == 'i' ? Domain::TwoValued : Domain::FourValued;
auto spelling = mnemonic.drop_front(1);
unsigned width;
if (spelling.getAsInteger(10, width))
return parser.emitError(loc, "integer width invalid");
return yieldPacked(IntType::get(context, width, domain));
}
// Unpacked primary types.
@ -852,7 +677,8 @@ static LogicalResult customTypePrinter(Type type, DialectAsmPrinter &printer,
return TypeSwitch<Type, LogicalResult>(type)
// Integers and reals
.Case<IntType>([&](auto type) {
printer << type.getKeyword();
printer << (type.getDomain() == Domain::TwoValued ? "i" : "l");
printer << type.getWidth();
return success();
})
.Case<RealType>(

View File

@ -39,43 +39,42 @@ endmodule
// CHECK-LABEL: moore.module @Basic
module Basic;
// CHECK: %v0 = moore.variable : !moore.logic
// CHECK: %v1 = moore.variable : !moore.int
// CHECK: %v2 = moore.variable %v1 : !moore.int
// CHECK: %v0 = moore.variable : !moore.l1
// CHECK: %v1 = moore.variable : !moore.i32
// CHECK: %v2 = moore.variable %v1 : !moore.i32
var v0;
int v1;
int v2 = v1;
// CHECK: %w0 = moore.net wire : !moore.logic
// CHECK: %w1 = moore.net wire %w0 : !moore.logic
// CHECK: %w0 = moore.net wire : !moore.l1
// CHECK: %w1 = moore.net wire %w0 : !moore.l1
wire w0;
wire w1 = w0;
// CHECK: %w2 = moore.net uwire %w0 : !moore.logic
// CHECK: %w2 = moore.net uwire %w0 : !moore.l1
uwire w2 = w0;
// CHECK: %w3 = moore.net tri %w0 : !moore.logic
// CHECK: %w3 = moore.net tri %w0 : !moore.l1
tri w3 = w0;
// CHECK: %w4 = moore.net triand %w0 : !moore.logic
// CHECK: %w4 = moore.net triand %w0 : !moore.l1
triand w4 = w0;
// CHECK: %w5 = moore.net trior %w0 : !moore.logic
// CHECK: %w5 = moore.net trior %w0 : !moore.l1
trior w5 = w0;
// CHECK: %w6 = moore.net wand %w0 : !moore.logic
// CHECK: %w6 = moore.net wand %w0 : !moore.l1
wand w6 = w0;
// CHECK: %w7 = moore.net wor %w0 : !moore.logic
// CHECK: %w7 = moore.net wor %w0 : !moore.l1
wor w7 = w0;
// CHECK: %w8 = moore.net trireg %w0 : !moore.logic
// CHECK: %w8 = moore.net trireg %w0 : !moore.l1
trireg w8 = w0;
// CHECK: %w9 = moore.net tri0 %w0 : !moore.logic
// CHECK: %w9 = moore.net tri0 %w0 : !moore.l1
tri0 w9 = w0;
// CHECK: %w10 = moore.net tri1 %w0 : !moore.logic
// CHECK: %w10 = moore.net tri1 %w0 : !moore.l1
tri1 w10 = w0;
// CHECK: %w11 = moore.net supply0 : !moore.logic
// CHECK: %w11 = moore.net supply0 : !moore.l1
supply0 w11;
// CHECK: %w12 = moore.net supply1 : !moore.logic
// CHECK: %w12 = moore.net supply1 : !moore.l1
supply1 w12;
// CHECK: %b1 = moore.variable : !moore.packed<range<bit, 0:0>>
// CHECK: [[TMP:%.+]] = moore.conversion %b1 : !moore.packed<range<bit, 0:0>> -> !moore.bit
// CHECK: %b2 = moore.variable [[TMP]] : !moore.bit
// CHECK: %b1 = moore.variable : !moore.i1
// CHECK: %b2 = moore.variable %b1 : !moore.i1
bit [0:0] b1;
bit b2 = b1;
@ -110,7 +109,7 @@ module Basic;
// CHECK: }
always_ff @* begin end
// CHECK: moore.assign %v1, %v2 : !moore.int
// CHECK: moore.assign %v1, %v2 : !moore.i32
assign v1 = v2;
endmodule
@ -119,28 +118,28 @@ module Statements;
bit x, y, z;
int i;
initial begin
// CHECK: %a = moore.variable : !moore.int
// CHECK: %a = moore.variable : !moore.i32
automatic int a;
// CHECK moore.blocking_assign %i, %a : !moore.int
// CHECK moore.blocking_assign %i, %a : !moore.i32
i = a;
//===------------------------------------------------------------------===//
// Conditional statements
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.i1 -> i1
// CHECK: scf.if [[COND]] {
// CHECK: moore.blocking_assign %x, %y
// CHECK: }
if (x) x = y;
// CHECK: [[COND0:%.+]] = moore.and %x, %y
// CHECK: [[COND1:%.+]] = moore.conversion [[COND0]] : !moore.bit -> i1
// CHECK: [[COND1:%.+]] = moore.conversion [[COND0]] : !moore.i1 -> i1
// CHECK: scf.if [[COND1]] {
// CHECK: moore.blocking_assign %x, %y
// CHECK: }
if (x &&& y) x = y;
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.i1 -> i1
// CHECK: scf.if [[COND]] {
// CHECK: moore.blocking_assign %x, %z
// CHECK: } else {
@ -148,11 +147,11 @@ module Statements;
// CHECK: }
if (x) x = z; else x = y;
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.i1 -> i1
// CHECK: scf.if [[COND]] {
// CHECK: moore.blocking_assign %x, %x
// CHECK: } else {
// CHECK: [[COND:%.+]] = moore.conversion %y : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %y : !moore.i1 -> i1
// CHECK: scf.if [[COND]] {
// CHECK: moore.blocking_assign %x, %y
// CHECK: } else {
@ -170,46 +169,46 @@ module Statements;
//===------------------------------------------------------------------===//
// Case statements
// CHECK: [[TMP1:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.bit -> i1
// CHECK: [[TMP1:%.+]] = moore.eq %x, %x : !moore.i1 -> !moore.i1
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i1 -> i1
// CHECK: scf.if [[TMP2]] {
// CHECK: moore.blocking_assign %x, %x : !moore.bit
// CHECK: moore.blocking_assign %x, %x : !moore.i1
// CHECK: }
// CHECK: [[TMP3:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP4:%.+]] = moore.eq %x, %y : !moore.bit -> !moore.bit
// CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.bit
// CHECK: [[TMP6:%.+]] = moore.conversion [[TMP5]] : !moore.bit -> i1
// CHECK: [[TMP3:%.+]] = moore.eq %x, %x : !moore.i1 -> !moore.i1
// CHECK: [[TMP4:%.+]] = moore.eq %x, %y : !moore.i1 -> !moore.i1
// CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.i1
// CHECK: [[TMP6:%.+]] = moore.conversion [[TMP5]] : !moore.i1 -> i1
// CHECK: scf.if [[TMP6]] {
// CHECK: moore.blocking_assign %x, %y : !moore.bit
// CHECK: moore.blocking_assign %x, %y : !moore.i1
// CHECK: }
case (x)
x: x = x;
x, y: x = y;
endcase
// CHECK: [[TMP1:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.bit -> i1
// CHECK: [[TMP1:%.+]] = moore.eq %x, %x : !moore.i1 -> !moore.i1
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i1 -> i1
// CHECK: scf.if [[TMP2]] {
// CHECK: moore.blocking_assign %x, %x : !moore.bit
// CHECK: moore.blocking_assign %x, %x : !moore.i1
// CHECK: }
// CHECK: [[TMP3:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP4:%.+]] = moore.eq %x, %y : !moore.bit -> !moore.bit
// CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.bit
// CHECK: [[TMP6:%.+]] = moore.conversion [[TMP5]] : !moore.bit -> i1
// CHECK: [[TMP3:%.+]] = moore.eq %x, %x : !moore.i1 -> !moore.i1
// CHECK: [[TMP4:%.+]] = moore.eq %x, %y : !moore.i1 -> !moore.i1
// CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.i1
// CHECK: [[TMP6:%.+]] = moore.conversion [[TMP5]] : !moore.i1 -> i1
// CHECK: scf.if [[TMP6]] {
// CHECK: moore.blocking_assign %x, %y : !moore.bit
// CHECK: moore.blocking_assign %x, %y : !moore.i1
// CHECK: }
// CHECK: [[TMP7:%.+]] = moore.eq %x, %z : !moore.bit -> !moore.bit
// CHECK: [[TMP8:%.+]] = moore.conversion [[TMP7]] : !moore.bit -> i1
// CHECK: [[TMP7:%.+]] = moore.eq %x, %z : !moore.i1 -> !moore.i1
// CHECK: [[TMP8:%.+]] = moore.conversion [[TMP7]] : !moore.i1 -> i1
// CHECK: scf.if [[TMP8]] {
// CHECK: moore.blocking_assign %x, %z : !moore.bit
// CHECK: moore.blocking_assign %x, %z : !moore.i1
// CHECK: }
// CHECK: [[TMP9:%.+]] = moore.or [[TMP5]], [[TMP7]] : !moore.bit
// CHECK: [[TMP10:%.+]] = moore.or [[TMP1]], [[TMP9]] : !moore.bit
// CHECK: [[TMP11:%.+]] = moore.not [[TMP10]] : !moore.bit
// CHECK: [[TMP12:%.+]] = moore.conversion [[TMP11]] : !moore.bit -> i1
// CHECK: [[TMP9:%.+]] = moore.or [[TMP5]], [[TMP7]] : !moore.i1
// CHECK: [[TMP10:%.+]] = moore.or [[TMP1]], [[TMP9]] : !moore.i1
// CHECK: [[TMP11:%.+]] = moore.not [[TMP10]] : !moore.i1
// CHECK: [[TMP12:%.+]] = moore.conversion [[TMP11]] : !moore.i1 -> i1
// CHECK: scf.if [[TMP12]] {
// CHECK: moore.blocking_assign %x, %x : !moore.bit
// CHECK: moore.blocking_assign %x, %x : !moore.i1
// CHECK: }
case (x)
x: x = x;
@ -223,7 +222,7 @@ module Statements;
// CHECK: moore.blocking_assign %y, %x
// CHECK: scf.while : () -> () {
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.i1 -> i1
// CHECK: scf.condition([[COND]])
// CHECK: } do {
// CHECK: moore.blocking_assign %x, %y
@ -232,21 +231,21 @@ module Statements;
// CHECK: }
for (y = x; x; x = z) x = y;
// CHECK: scf.while (%arg0 = %i) : (!moore.int) -> !moore.int {
// CHECK: [[TMP0:%.+]] = moore.bool_cast %arg0 : !moore.int -> !moore.bit
// CHECK: [[TMP1:%.+]] = moore.conversion [[TMP0]] : !moore.bit -> i1
// CHECK: scf.condition([[TMP1]]) %arg0 : !moore.int
// CHECK: scf.while (%arg0 = %i) : (!moore.i32) -> !moore.i32 {
// CHECK: [[TMP0:%.+]] = moore.bool_cast %arg0 : !moore.i32 -> !moore.i1
// CHECK: [[TMP1:%.+]] = moore.conversion [[TMP0]] : !moore.i1 -> i1
// CHECK: scf.condition([[TMP1]]) %arg0 : !moore.i32
// CHECK: } do {
// CHECK: ^bb0(%arg0: !moore.int):
// CHECK: ^bb0(%arg0: !moore.i32):
// CHECK: moore.blocking_assign %x, %y
// CHECK: [[TMP0:%.+]] = moore.constant 1 : !moore.int
// CHECK: [[TMP1:%.+]] = moore.sub %arg0, [[TMP0]] : !moore.int
// CHECK: scf.yield [[TMP1]] : !moore.int
// CHECK: [[TMP0:%.+]] = moore.constant 1 : !moore.i32
// CHECK: [[TMP1:%.+]] = moore.sub %arg0, [[TMP0]] : !moore.i32
// CHECK: scf.yield [[TMP1]] : !moore.i32
// CHECK: }
repeat (i) x = y;
// CHECK: scf.while : () -> () {
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.i1 -> i1
// CHECK: scf.condition([[COND]])
// CHECK: } do {
// CHECK: moore.blocking_assign %x, %y
@ -256,7 +255,7 @@ module Statements;
// CHECK: scf.while : () -> () {
// CHECK: moore.blocking_assign %x, %y
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.bit -> i1
// CHECK: [[COND:%.+]] = moore.conversion %x : !moore.i1 -> i1
// CHECK: scf.condition([[COND]])
// CHECK: } do {
// CHECK: scf.yield
@ -275,23 +274,32 @@ module Statements;
//===------------------------------------------------------------------===//
// Assignments
// CHECK: moore.blocking_assign %x, %y : !moore.bit
// CHECK: moore.blocking_assign %x, %y : !moore.i1
x = y;
// CHECK: moore.blocking_assign %y, %z : !moore.bit
// CHECK: moore.blocking_assign %x, %z : !moore.bit
// CHECK: moore.blocking_assign %y, %z : !moore.i1
// CHECK: moore.blocking_assign %x, %z : !moore.i1
x = (y = z);
// CHECK: moore.nonblocking_assign %x, %y : !moore.bit
// CHECK: moore.nonblocking_assign %x, %y : !moore.i1
x <= y;
end
endmodule
// CHECK-LABEL: moore.module @Expressions {
module Expressions;
// CHECK: %a = moore.variable : !moore.int
// CHECK: %b = moore.variable : !moore.int
// CHECK: %c = moore.variable : !moore.int
// CHECK: %a = moore.variable : !moore.i32
// CHECK: %b = moore.variable : !moore.i32
// CHECK: %c = moore.variable : !moore.i32
// CHECK: %u = moore.variable : !moore.i32
// CHECK: %v = moore.variable : !moore.packed<range<i4, 1:0>>
// CHECK: %d = moore.variable : !moore.l32
// CHECK: %e = moore.variable : !moore.l32
// CHECK: %f = moore.variable : !moore.l32
// CHECK: %x = moore.variable : !moore.i1
// CHECK: %y = moore.variable : !moore.l1
// CHECK: %vec_1 = moore.variable : !moore.l32
// CHECK: %vec_2 = moore.variable : !moore.l32
int a, b, c;
int unsigned u, w;
bit [1:0][3:0] v;
@ -305,115 +313,115 @@ module Expressions;
bit [3:2] s;
initial begin
// CHECK: moore.constant 0 : !moore.packed<range<bit, 31:0>>
// CHECK: moore.constant 0 : !moore.i32
c = '0;
// CHECK: moore.constant -1 : !moore.packed<range<bit, 31:0>>
// CHECK: moore.constant -1 : !moore.i32
c = '1;
// CHECK: moore.constant 42 : !moore.int
// CHECK: moore.constant 42 : !moore.i32
c = 42;
// CHECK: moore.constant 42 : !moore.packed<range<bit, 18:0>>
// CHECK: moore.constant 42 : !moore.i19
c = 19'd42;
// CHECK: moore.constant 42 : !moore.packed<range<bit, 18:0>>
// CHECK: moore.constant 42 : !moore.i19
c = 19'sd42;
// CHECK: moore.concat %a, %b, %c : (!moore.int, !moore.int, !moore.int) -> !moore.packed<range<bit, 95:0>>
// CHECK: moore.concat %a, %b, %c : (!moore.i32, !moore.i32, !moore.i32) -> !moore.i96
a = {a, b, c};
// CHECK: moore.concat %d, %e : (!moore.integer, !moore.integer) -> !moore.packed<range<logic, 63:0>>
// CHECK: moore.concat %d, %e : (!moore.l32, !moore.l32) -> !moore.l64
d = {d, e};
// CHECK: %[[VAL_1:.*]] = moore.constant false : !moore.packed<range<bit, 0:0>>
// CHECK: %[[VAL_2:.*]] = moore.concat %[[VAL_1]] : (!moore.packed<range<bit, 0:0>>) -> !moore.bit
// CHECK: %[[VAL_3:.*]] = moore.replicate %[[VAL_2]] : (!moore.bit) -> !moore.packed<range<bit, 31:0>>
// CHECK: %[[VAL_1:.*]] = moore.constant false : !moore.i1
// CHECK: %[[VAL_2:.*]] = moore.concat %[[VAL_1]] : (!moore.i1) -> !moore.i1
// CHECK: %[[VAL_3:.*]] = moore.replicate %[[VAL_2]] : (!moore.i1) -> !moore.i32
a = {32{1'b0}};
// CHECK: %[[VAL:.*]] = moore.constant 1 : !moore.int
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.packed<range<logic, 3:1>>
// CHECK: %[[VAL:.*]] = moore.constant 1 : !moore.i32
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.l32, !moore.i32 -> !moore.l3
y = vec_1[3:1];
// CHECK: %[[VAL:.*]] = moore.constant 2 : !moore.int
// CHECK: moore.extract %vec_2 from %[[VAL]] : !moore.packed<range<logic, 0:31>>, !moore.int -> !moore.packed<range<logic, 2:3>>
// CHECK: %[[VAL:.*]] = moore.constant 2 : !moore.i32
// CHECK: moore.extract %vec_2 from %[[VAL]] : !moore.l32, !moore.i32 -> !moore.l2
y = vec_2[2:3];
// CHECK: moore.extract %d from %x : !moore.integer, !moore.bit -> !moore.logic
// CHECK: moore.extract %d from %x : !moore.l32, !moore.i1 -> !moore.l1
y = d[x];
// CHECK: moore.extract %a from %x : !moore.int, !moore.bit -> !moore.bit
// CHECK: moore.extract %a from %x : !moore.i32, !moore.i1 -> !moore.i1
y = a[x];
// CHECK: %[[VAL:.*]] = moore.constant 15 : !moore.int
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.logic
// CHECK: %[[VAL:.*]] = moore.constant 15 : !moore.i32
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.l32, !moore.i32 -> !moore.l1
y = vec_1[15];
// CHECK: %[[VAL:.*]] = moore.constant 15 : !moore.int
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.packed<range<logic, 15:15>>
// CHECK: %[[VAL:.*]] = moore.constant 15 : !moore.i32
// CHECK: moore.extract %vec_1 from %[[VAL]] : !moore.l32, !moore.i32 -> !moore.l1
y = vec_1[15+:1];
// CHECK: %[[VAL:.*]] = moore.constant 0 : !moore.int
// CHECK: moore.extract %vec_2 from %[[VAL]] : !moore.packed<range<logic, 0:31>>, !moore.int -> !moore.packed<range<logic, 0:0>>
// CHECK: %[[VAL:.*]] = moore.constant 0 : !moore.i32
// CHECK: moore.extract %vec_2 from %[[VAL]] : !moore.l32, !moore.i32 -> !moore.l1
y = vec_2[0+:1];
// CHECK: %[[VAL_1:.*]] = moore.constant 1 : !moore.int
// CHECK: %[[VAL_2:.*]] = moore.mul %[[VAL_1]], %a : !moore.int
// CHECK: moore.extract %vec_1 from %[[VAL_2]] : !moore.packed<range<logic, 31:0>>, !moore.int -> !moore.packed<range<logic, 31:31>>
// CHECK: %[[VAL_1:.*]] = moore.constant 1 : !moore.i32
// CHECK: %[[VAL_2:.*]] = moore.mul %[[VAL_1]], %a : !moore.i32
// CHECK: moore.extract %vec_1 from %[[VAL_2]] : !moore.l32, !moore.i32 -> !moore.l1
y = vec_1[1*a-:1];
// CHECK: %[[VAL_1:.*]] = moore.constant 3 : !moore.int
// CHECK: %[[VAL_2:.*]] = moore.extract %arr from %[[VAL_1]] : !moore.unpacked<range<range<packed<range<bit, 4:1>>, 2:7>, 1:3>>, !moore.int -> !moore.unpacked<range<packed<range<bit, 4:1>>, 2:7>>
// CHECK: %[[VAL_3:.*]] = moore.constant 7 : !moore.int
// CHECK: %[[VAL_4:.*]] = moore.extract %[[VAL_2]] from %[[VAL_3]] : !moore.unpacked<range<packed<range<bit, 4:1>>, 2:7>>, !moore.int -> !moore.packed<range<bit, 4:1>>
// CHECK: %[[VAL_5:.*]] = moore.constant 3 : !moore.int
// CHECK: moore.extract %[[VAL_4]] from %[[VAL_5]] : !moore.packed<range<bit, 4:1>>, !moore.int -> !moore.packed<range<bit, 4:3>>
// CHECK: %[[VAL_1:.*]] = moore.constant 3 : !moore.i32
// CHECK: %[[VAL_2:.*]] = moore.extract %arr from %[[VAL_1]] : !moore.unpacked<range<range<i4, 2:7>, 1:3>>, !moore.i32 -> !moore.unpacked<range<i4, 2:7>>
// CHECK: %[[VAL_3:.*]] = moore.constant 7 : !moore.i32
// CHECK: %[[VAL_4:.*]] = moore.extract %[[VAL_2]] from %[[VAL_3]] : !moore.unpacked<range<i4, 2:7>>, !moore.i32 -> !moore.i4
// CHECK: %[[VAL_5:.*]] = moore.constant 3 : !moore.i32
// CHECK: moore.extract %[[VAL_4]] from %[[VAL_5]] : !moore.i4, !moore.i32 -> !moore.i2
s = arr[3][7][4:3];
// CHECK: moore.extract %vec_1 from %s : !moore.packed<range<logic, 31:0>>, !moore.packed<range<bit, 3:2>> -> !moore.logic
// CHECK: moore.extract %vec_1 from %s : !moore.l32, !moore.i2 -> !moore.l1
y = vec_1[s];
//===------------------------------------------------------------------===//
// Unary operators
// CHECK: moore.blocking_assign %c, %a : !moore.int
// CHECK: moore.blocking_assign %c, %a : !moore.i32
c = +a;
// CHECK: moore.neg %a : !moore.int
// CHECK: moore.neg %a : !moore.i32
c = -a;
// CHECK: [[TMP1:%.+]] = moore.conversion %v : !moore.packed<range<range<bit, 3:0>, 1:0>> -> !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP2:%.+]] = moore.neg [[TMP1]] : !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP2]] : !moore.packed<range<bit, 31:0>> -> !moore.int
// CHECK: [[TMP1:%.+]] = moore.conversion %v : !moore.packed<range<i4, 1:0>> -> !moore.i32
// CHECK: [[TMP2:%.+]] = moore.neg [[TMP1]] : !moore.i32
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP2]] : !moore.i32 -> !moore.i32
c = -v;
// CHECK: moore.not %a : !moore.int
// CHECK: moore.not %a : !moore.i32
c = ~a;
// CHECK: moore.reduce_and %a : !moore.int -> !moore.bit
// CHECK: moore.reduce_and %a : !moore.i32 -> !moore.i1
x = &a;
// CHECK: moore.reduce_and %d : !moore.integer -> !moore.logic
// CHECK: moore.reduce_and %d : !moore.l32 -> !moore.l1
y = &d;
// CHECK: moore.reduce_or %a : !moore.int -> !moore.bit
// CHECK: moore.reduce_or %a : !moore.i32 -> !moore.i1
x = |a;
// CHECK: moore.reduce_xor %a : !moore.int -> !moore.bit
// CHECK: moore.reduce_xor %a : !moore.i32 -> !moore.i1
x = ^a;
// CHECK: [[TMP:%.+]] = moore.reduce_and %a : !moore.int -> !moore.bit
// CHECK: moore.not [[TMP]] : !moore.bit
// CHECK: [[TMP:%.+]] = moore.reduce_and %a : !moore.i32 -> !moore.i1
// CHECK: moore.not [[TMP]] : !moore.i1
x = ~&a;
// CHECK: [[TMP:%.+]] = moore.reduce_or %a : !moore.int -> !moore.bit
// CHECK: moore.not [[TMP]] : !moore.bit
// CHECK: [[TMP:%.+]] = moore.reduce_or %a : !moore.i32 -> !moore.i1
// CHECK: moore.not [[TMP]] : !moore.i1
x = ~|a;
// CHECK: [[TMP:%.+]] = moore.reduce_xor %a : !moore.int -> !moore.bit
// CHECK: moore.not [[TMP]] : !moore.bit
// CHECK: [[TMP:%.+]] = moore.reduce_xor %a : !moore.i32 -> !moore.i1
// CHECK: moore.not [[TMP]] : !moore.i1
x = ~^a;
// CHECK: [[TMP:%.+]] = moore.reduce_xor %a : !moore.int -> !moore.bit
// CHECK: moore.not [[TMP]] : !moore.bit
// CHECK: [[TMP:%.+]] = moore.reduce_xor %a : !moore.i32 -> !moore.i1
// CHECK: moore.not [[TMP]] : !moore.i1
x = ^~a;
// CHECK: [[TMP:%.+]] = moore.bool_cast %a : !moore.int -> !moore.bit
// CHECK: moore.not [[TMP]] : !moore.bit
// CHECK: [[TMP:%.+]] = moore.bool_cast %a : !moore.i32 -> !moore.i1
// CHECK: moore.not [[TMP]] : !moore.i1
x = !a;
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.int
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.int
// CHECK: [[POST:%.+]] = moore.add [[PRE]], [[TMP]] : !moore.int
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.i32
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.i32
// CHECK: [[POST:%.+]] = moore.add [[PRE]], [[TMP]] : !moore.i32
// CHECK: moore.blocking_assign %a, [[POST]]
// CHECK: moore.blocking_assign %c, [[PRE]]
c = a++;
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.int
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.int
// CHECK: [[POST:%.+]] = moore.sub [[PRE]], [[TMP]] : !moore.int
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.i32
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.i32
// CHECK: [[POST:%.+]] = moore.sub [[PRE]], [[TMP]] : !moore.i32
// CHECK: moore.blocking_assign %a, [[POST]]
// CHECK: moore.blocking_assign %c, [[PRE]]
c = a--;
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.int
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.int
// CHECK: [[POST:%.+]] = moore.add [[PRE]], [[TMP]] : !moore.int
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.i32
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.i32
// CHECK: [[POST:%.+]] = moore.add [[PRE]], [[TMP]] : !moore.i32
// CHECK: moore.blocking_assign %a, [[POST]]
// CHECK: moore.blocking_assign %c, [[POST]]
c = ++a;
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.int
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.int
// CHECK: [[POST:%.+]] = moore.sub [[PRE]], [[TMP]] : !moore.int
// CHECK: [[PRE:%.+]] = moore.read_lvalue %a : !moore.i32
// CHECK: [[TMP:%.+]] = moore.constant 1 : !moore.i32
// CHECK: [[POST:%.+]] = moore.sub [[PRE]], [[TMP]] : !moore.i32
// CHECK: moore.blocking_assign %a, [[POST]]
// CHECK: moore.blocking_assign %c, [[POST]]
c = --a;
@ -421,110 +429,110 @@ module Expressions;
//===------------------------------------------------------------------===//
// Binary operators
// CHECK: moore.add %a, %b : !moore.int
// CHECK: moore.add %a, %b : !moore.i32
c = a + b;
// CHECK: [[TMP1:%.+]] = moore.conversion %a : !moore.int -> !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP2:%.+]] = moore.conversion %v : !moore.packed<range<range<bit, 3:0>, 1:0>> -> !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP3:%.+]] = moore.add [[TMP1]], [[TMP2]] : !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.packed<range<bit, 31:0>> -> !moore.int
// CHECK: [[TMP1:%.+]] = moore.conversion %a : !moore.i32 -> !moore.i32
// CHECK: [[TMP2:%.+]] = moore.conversion %v : !moore.packed<range<i4, 1:0>> -> !moore.i32
// CHECK: [[TMP3:%.+]] = moore.add [[TMP1]], [[TMP2]] : !moore.i32
// CHECK: [[TMP4:%.+]] = moore.conversion [[TMP3]] : !moore.i32 -> !moore.i32
c = a + v;
// CHECK: moore.sub %a, %b : !moore.int
// CHECK: moore.sub %a, %b : !moore.i32
c = a - b;
// CHECK: moore.mul %a, %b : !moore.int
// CHECK: moore.mul %a, %b : !moore.i32
c = a * b;
// CHECK: moore.divu %h, %k : !moore.integer
// CHECK: moore.divu %h, %k : !moore.l32
g = h / k;
// CHECK: moore.divs %d, %e : !moore.integer
// CHECK: moore.divs %d, %e : !moore.l32
f = d / e;
// CHECK: moore.modu %h, %k : !moore.integer
// CHECK: moore.modu %h, %k : !moore.l32
g = h % k;
// CHECK: moore.mods %d, %e : !moore.integer
// CHECK: moore.mods %d, %e : !moore.l32
f = d % e;
// CHECK: moore.and %a, %b : !moore.int
// CHECK: moore.and %a, %b : !moore.i32
c = a & b;
// CHECK: moore.or %a, %b : !moore.int
// CHECK: moore.or %a, %b : !moore.i32
c = a | b;
// CHECK: moore.xor %a, %b : !moore.int
// CHECK: moore.xor %a, %b : !moore.i32
c = a ^ b;
// CHECK: [[TMP:%.+]] = moore.xor %a, %b : !moore.int
// CHECK: moore.not [[TMP]] : !moore.int
// CHECK: [[TMP:%.+]] = moore.xor %a, %b : !moore.i32
// CHECK: moore.not [[TMP]] : !moore.i32
c = a ~^ b;
// CHECK: [[TMP:%.+]] = moore.xor %a, %b : !moore.int
// CHECK: moore.not [[TMP]] : !moore.int
// CHECK: [[TMP:%.+]] = moore.xor %a, %b : !moore.i32
// CHECK: moore.not [[TMP]] : !moore.i32
c = a ^~ b;
// CHECK: moore.eq %a, %b : !moore.int -> !moore.bit
// CHECK: moore.eq %a, %b : !moore.i32 -> !moore.i1
x = a == b;
// CHECK: moore.eq %d, %e : !moore.integer -> !moore.logic
// CHECK: moore.eq %d, %e : !moore.l32 -> !moore.l1
y = d == e;
// CHECK: moore.ne %a, %b : !moore.int -> !moore.bit
// CHECK: moore.ne %a, %b : !moore.i32 -> !moore.i1
x = a != b ;
// CHECK: moore.case_eq %a, %b : !moore.int
// CHECK: moore.case_eq %a, %b : !moore.i32
x = a === b;
// CHECK: moore.case_ne %a, %b : !moore.int
// CHECK: moore.case_ne %a, %b : !moore.i32
x = a !== b;
// CHECK: moore.wildcard_eq %a, %b : !moore.int -> !moore.bit
// CHECK: moore.wildcard_eq %a, %b : !moore.i32 -> !moore.i1
x = a ==? b;
// CHECK: [[TMP:%.+]] = moore.conversion %a : !moore.int -> !moore.integer
// CHECK: moore.wildcard_eq [[TMP]], %d : !moore.integer -> !moore.logic
// CHECK: [[TMP:%.+]] = moore.conversion %a : !moore.i32 -> !moore.l32
// CHECK: moore.wildcard_eq [[TMP]], %d : !moore.l32 -> !moore.l1
y = a ==? d;
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.int -> !moore.integer
// CHECK: moore.wildcard_eq %d, [[TMP]] : !moore.integer -> !moore.logic
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.i32 -> !moore.l32
// CHECK: moore.wildcard_eq %d, [[TMP]] : !moore.l32 -> !moore.l1
y = d ==? b;
// CHECK: moore.wildcard_eq %d, %e : !moore.integer -> !moore.logic
// CHECK: moore.wildcard_eq %d, %e : !moore.l32 -> !moore.l1
y = d ==? e;
// CHECK: moore.wildcard_ne %a, %b : !moore.int -> !moore.bit
// CHECK: moore.wildcard_ne %a, %b : !moore.i32 -> !moore.i1
x = a !=? b;
// CHECK: moore.uge %u, %w : !moore.int -> !moore.bit
// CHECK: moore.uge %u, %w : !moore.i32 -> !moore.i1
c = u >= w;
// CHECK: moore.ugt %u, %w : !moore.int -> !moore.bit
// CHECK: moore.ugt %u, %w : !moore.i32 -> !moore.i1
c = u > w;
// CHECK: moore.ule %u, %w : !moore.int -> !moore.bit
// CHECK: moore.ule %u, %w : !moore.i32 -> !moore.i1
c = u <= w;
// CHECK: moore.ult %u, %w : !moore.int -> !moore.bit
// CHECK: moore.ult %u, %w : !moore.i32 -> !moore.i1
c = u < w;
// CHECK: moore.sge %a, %b : !moore.int -> !moore.bit
// CHECK: moore.sge %a, %b : !moore.i32 -> !moore.i1
c = a >= b;
// CHECK: moore.sgt %a, %b : !moore.int -> !moore.bit
// CHECK: moore.sgt %a, %b : !moore.i32 -> !moore.i1
c = a > b;
// CHECK: moore.sle %a, %b : !moore.int -> !moore.bit
// CHECK: moore.sle %a, %b : !moore.i32 -> !moore.i1
c = a <= b;
// CHECK: moore.slt %a, %b : !moore.int -> !moore.bit
// CHECK: moore.slt %a, %b : !moore.i32 -> !moore.i1
c = a < b;
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.int -> !moore.bit
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.int -> !moore.bit
// CHECK: moore.and [[A]], [[B]] : !moore.bit
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.i32 -> !moore.i1
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.i32 -> !moore.i1
// CHECK: moore.and [[A]], [[B]] : !moore.i1
c = a && b;
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.int -> !moore.bit
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.int -> !moore.bit
// CHECK: moore.or [[A]], [[B]] : !moore.bit
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.i32 -> !moore.i1
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.i32 -> !moore.i1
// CHECK: moore.or [[A]], [[B]] : !moore.i1
c = a || b;
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.int -> !moore.bit
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.int -> !moore.bit
// CHECK: [[NOT_A:%.+]] = moore.not [[A]] : !moore.bit
// CHECK: moore.or [[NOT_A]], [[B]] : !moore.bit
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.i32 -> !moore.i1
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.i32 -> !moore.i1
// CHECK: [[NOT_A:%.+]] = moore.not [[A]] : !moore.i1
// CHECK: moore.or [[NOT_A]], [[B]] : !moore.i1
c = a -> b;
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.int -> !moore.bit
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.int -> !moore.bit
// CHECK: [[NOT_A:%.+]] = moore.not [[A]] : !moore.bit
// CHECK: [[NOT_B:%.+]] = moore.not [[B]] : !moore.bit
// CHECK: [[BOTH:%.+]] = moore.and [[A]], [[B]] : !moore.bit
// CHECK: [[NOT_BOTH:%.+]] = moore.and [[NOT_A]], [[NOT_B]] : !moore.bit
// CHECK: moore.or [[BOTH]], [[NOT_BOTH]] : !moore.bit
// CHECK: [[A:%.+]] = moore.bool_cast %a : !moore.i32 -> !moore.i1
// CHECK: [[B:%.+]] = moore.bool_cast %b : !moore.i32 -> !moore.i1
// CHECK: [[NOT_A:%.+]] = moore.not [[A]] : !moore.i1
// CHECK: [[NOT_B:%.+]] = moore.not [[B]] : !moore.i1
// CHECK: [[BOTH:%.+]] = moore.and [[A]], [[B]] : !moore.i1
// CHECK: [[NOT_BOTH:%.+]] = moore.and [[NOT_A]], [[NOT_B]] : !moore.i1
// CHECK: moore.or [[BOTH]], [[NOT_BOTH]] : !moore.i1
c = a <-> b;
// CHECK: moore.shl %a, %b : !moore.int, !moore.int
// CHECK: moore.shl %a, %b : !moore.i32, !moore.i32
c = a << b;
// CHECK: moore.shr %a, %b : !moore.int, !moore.int
// CHECK: moore.shr %a, %b : !moore.i32, !moore.i32
c = a >> b;
// CHECK: moore.shl %a, %b : !moore.int, !moore.int
// CHECK: moore.shl %a, %b : !moore.i32, !moore.i32
c = a <<< b;
// CHECK: moore.ashr %a, %b : !moore.int, !moore.int
// CHECK: moore.ashr %a, %b : !moore.i32, !moore.i32
c = a >>> b;
// CHECK: moore.shr %u, %b : !moore.int, !moore.int
// CHECK: moore.shr %u, %b : !moore.i32, !moore.i32
c = u >>> b;
//===------------------------------------------------------------------===//
@ -605,27 +613,27 @@ endmodule
module Conversion;
// Implicit conversion.
// CHECK: %a = moore.variable
// CHECK: [[TMP:%.+]] = moore.conversion %a : !moore.shortint -> !moore.int
// CHECK: [[TMP:%.+]] = moore.conversion %a : !moore.i16 -> !moore.i32
// CHECK: %b = moore.variable [[TMP]]
shortint a;
int b = a;
// Explicit conversion.
// CHECK: [[TMP1:%.+]] = moore.conversion %a : !moore.shortint -> !moore.byte
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.byte -> !moore.int
// CHECK: [[TMP1:%.+]] = moore.conversion %a : !moore.i16 -> !moore.i8
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i8 -> !moore.i32
// CHECK: %c = moore.variable [[TMP2]]
int c = byte'(a);
// Sign conversion.
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.int -> !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.i32 -> !moore.i32
// CHECK: %d1 = moore.variable [[TMP]]
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.int -> !moore.packed<range<bit, 31:0>>
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.i32 -> !moore.i32
// CHECK: %d2 = moore.variable [[TMP]]
bit signed [31:0] d1 = signed'(b);
bit [31:0] d2 = unsigned'(b);
// Width conversion.
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.int -> !moore.packed<range<bit, 18:0>>
// CHECK: [[TMP:%.+]] = moore.conversion %b : !moore.i32 -> !moore.i19
// CHECK: %e = moore.variable [[TMP]]
bit signed [18:0] e = 19'(b);
endmodule

View File

@ -8,9 +8,9 @@
module Enums;
typedef enum shortint { MAGIC } myEnum;
// CHECK-NEXT: %e0 = moore.variable : !moore.int
// CHECK-NEXT: %e1 = moore.variable : !moore.byte
// CHECK-NEXT: %e2 = moore.variable : !moore.shortint
// CHECK-NEXT: %e0 = moore.variable : !moore.i32
// CHECK-NEXT: %e1 = moore.variable : !moore.i8
// CHECK-NEXT: %e2 = moore.variable : !moore.i16
enum { FOO, BAR } e0;
enum byte { HELLO = 0, WORLD = 1 } e1;
myEnum e2;
@ -18,15 +18,15 @@ endmodule
// CHECK-LABEL: moore.module @IntAtoms
module IntAtoms;
// CHECK-NEXT: %d0 = moore.variable : !moore.logic
// CHECK-NEXT: %d1 = moore.variable : !moore.bit
// CHECK-NEXT: %d2 = moore.variable : !moore.reg
// CHECK-NEXT: %d3 = moore.variable : !moore.int
// CHECK-NEXT: %d4 = moore.variable : !moore.shortint
// CHECK-NEXT: %d5 = moore.variable : !moore.longint
// CHECK-NEXT: %d6 = moore.variable : !moore.integer
// CHECK-NEXT: %d7 = moore.variable : !moore.byte
// CHECK-NEXT: %d8 = moore.variable : !moore.time
// CHECK-NEXT: %d0 = moore.variable : !moore.l1
// CHECK-NEXT: %d1 = moore.variable : !moore.i1
// CHECK-NEXT: %d2 = moore.variable : !moore.l1
// CHECK-NEXT: %d3 = moore.variable : !moore.i32
// CHECK-NEXT: %d4 = moore.variable : !moore.i16
// CHECK-NEXT: %d5 = moore.variable : !moore.i64
// CHECK-NEXT: %d6 = moore.variable : !moore.l32
// CHECK-NEXT: %d7 = moore.variable : !moore.i8
// CHECK-NEXT: %d8 = moore.variable : !moore.l64
logic d0;
bit d1;
reg d2;
@ -37,15 +37,15 @@ module IntAtoms;
byte d7;
time d8;
// CHECK-NEXT: %u0 = moore.variable : !moore.logic
// CHECK-NEXT: %u1 = moore.variable : !moore.bit
// CHECK-NEXT: %u2 = moore.variable : !moore.reg
// CHECK-NEXT: %u3 = moore.variable : !moore.int
// CHECK-NEXT: %u4 = moore.variable : !moore.shortint
// CHECK-NEXT: %u5 = moore.variable : !moore.longint
// CHECK-NEXT: %u6 = moore.variable : !moore.integer
// CHECK-NEXT: %u7 = moore.variable : !moore.byte
// CHECK-NEXT: %u8 = moore.variable : !moore.time
// CHECK-NEXT: %u0 = moore.variable : !moore.l1
// CHECK-NEXT: %u1 = moore.variable : !moore.i1
// CHECK-NEXT: %u2 = moore.variable : !moore.l1
// CHECK-NEXT: %u3 = moore.variable : !moore.i32
// CHECK-NEXT: %u4 = moore.variable : !moore.i16
// CHECK-NEXT: %u5 = moore.variable : !moore.i64
// CHECK-NEXT: %u6 = moore.variable : !moore.l32
// CHECK-NEXT: %u7 = moore.variable : !moore.i8
// CHECK-NEXT: %u8 = moore.variable : !moore.l64
logic unsigned u0;
bit unsigned u1;
reg unsigned u2;
@ -56,15 +56,15 @@ module IntAtoms;
byte unsigned u7;
time unsigned u8;
// CHECK-NEXT: %s0 = moore.variable : !moore.logic
// CHECK-NEXT: %s1 = moore.variable : !moore.bit
// CHECK-NEXT: %s2 = moore.variable : !moore.reg
// CHECK-NEXT: %s3 = moore.variable : !moore.int
// CHECK-NEXT: %s4 = moore.variable : !moore.shortint
// CHECK-NEXT: %s5 = moore.variable : !moore.longint
// CHECK-NEXT: %s6 = moore.variable : !moore.integer
// CHECK-NEXT: %s7 = moore.variable : !moore.byte
// CHECK-NEXT: %s8 = moore.variable : !moore.time
// CHECK-NEXT: %s0 = moore.variable : !moore.l1
// CHECK-NEXT: %s1 = moore.variable : !moore.i1
// CHECK-NEXT: %s2 = moore.variable : !moore.l1
// CHECK-NEXT: %s3 = moore.variable : !moore.i32
// CHECK-NEXT: %s4 = moore.variable : !moore.i16
// CHECK-NEXT: %s5 = moore.variable : !moore.i64
// CHECK-NEXT: %s6 = moore.variable : !moore.l32
// CHECK-NEXT: %s7 = moore.variable : !moore.i8
// CHECK-NEXT: %s8 = moore.variable : !moore.l64
logic signed s0;
bit signed s1;
reg signed s2;
@ -78,30 +78,30 @@ endmodule
// CHECK-LABEL: moore.module @MultiPackedRangeDim
module MultiPackedRangeDim;
// CHECK-NEXT: %v0 = moore.variable : !moore.packed<range<range<logic, 2:0>, 5:0>>
// CHECK-NEXT: %v1 = moore.variable : !moore.packed<range<range<logic, 2:0>, 0:5>>
// CHECK-NEXT: %v0 = moore.variable : !moore.packed<range<l3, 5:0>>
// CHECK-NEXT: %v1 = moore.variable : !moore.packed<range<l3, 0:5>>
logic [5:0][2:0] v0;
logic [0:5][2:0] v1;
endmodule
// CHECK-LABEL: moore.module @MultiUnpackedRangeDim
module MultiUnpackedRangeDim;
// CHECK-NEXT: %v0 = moore.variable : !moore.unpacked<range<range<logic, 2:0>, 5:0>>
// CHECK-NEXT: %v1 = moore.variable : !moore.unpacked<range<range<logic, 2:0>, 0:5>>
// CHECK-NEXT: %v0 = moore.variable : !moore.unpacked<range<range<l1, 2:0>, 5:0>>
// CHECK-NEXT: %v1 = moore.variable : !moore.unpacked<range<range<l1, 2:0>, 0:5>>
logic v0 [5:0][2:0];
logic v1 [0:5][2:0];
endmodule
// CHECK-LABEL: moore.module @MultiUnpackedUnsizedDim
module MultiUnpackedUnsizedDim;
// CHECK-NEXT: %v0 = moore.variable : !moore.unpacked<unsized<unsized<logic>>>
// CHECK-NEXT: %v0 = moore.variable : !moore.unpacked<unsized<unsized<l1>>>
logic v0 [][];
endmodule
// CHECK-LABEL: moore.module @PackedRangeDim
module PackedRangeDim;
// CHECK-NEXT: %d0 = moore.variable : !moore.packed<range<logic, 2:0>>
// CHECK-NEXT: %d1 = moore.variable : !moore.packed<range<logic, 0:2>>
// CHECK-NEXT: %d0 = moore.variable : !moore.l3
// CHECK-NEXT: %d1 = moore.variable : !moore.l3
logic [2:0] d0;
logic [0:2] d1;
endmodule
@ -121,10 +121,10 @@ module Structs;
typedef struct packed { byte a; int b; } myStructA;
typedef struct { byte x; int y; } myStructB;
// CHECK-NEXT: %s0 = moore.variable : !moore.packed<struct<{foo: bit, bar: logic}>>
// CHECK-NEXT: %s1 = moore.variable : !moore.unpacked<struct<{many: assoc<bit, int>}>>
// CHECK-NEXT: %s2 = moore.variable : !moore.packed<struct<{a: byte, b: int}>>
// CHECK-NEXT: %s3 = moore.variable : !moore.unpacked<struct<{x: byte, y: int}>>
// CHECK-NEXT: %s0 = moore.variable : !moore.packed<struct<{foo: i1, bar: l1}>>
// CHECK-NEXT: %s1 = moore.variable : !moore.unpacked<struct<{many: assoc<i1, i32>}>>
// CHECK-NEXT: %s2 = moore.variable : !moore.packed<struct<{a: i8, b: i32}>>
// CHECK-NEXT: %s3 = moore.variable : !moore.unpacked<struct<{x: i8, y: i32}>>
struct packed { bit foo; logic bar; } s0;
struct { bit many[int]; } s1;
myStructA s2;
@ -136,38 +136,38 @@ module Typedefs;
typedef logic [2:0] myType1;
typedef logic myType2 [2:0];
// CHECK-NEXT: %v0 = moore.variable : !moore.packed<range<logic, 2:0>>
// CHECK-NEXT: %v1 = moore.variable : !moore.unpacked<range<logic, 2:0>>
// CHECK-NEXT: %v0 = moore.variable : !moore.l3
// CHECK-NEXT: %v1 = moore.variable : !moore.unpacked<range<l1, 2:0>>
myType1 v0;
myType2 v1;
endmodule
// CHECK-LABEL: moore.module @UnpackedAssocDim
module UnpackedAssocDim;
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<assoc<logic, int>>
// CHECK-NEXT: %d1 = moore.variable : !moore.unpacked<assoc<logic, logic>>
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<assoc<l1, i32>>
// CHECK-NEXT: %d1 = moore.variable : !moore.unpacked<assoc<l1, l1>>
logic d0 [int];
logic d1 [logic];
endmodule
// CHECK-LABEL: moore.module @UnpackedQueueDim
module UnpackedQueueDim;
//CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<queue<logic, 0>>
//CHECK-NEXT: %d1 = moore.variable : !moore.unpacked<queue<logic, 2>>
//CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<queue<l1, 0>>
//CHECK-NEXT: %d1 = moore.variable : !moore.unpacked<queue<l1, 2>>
logic d0[$];
logic d1[$:2];
endmodule
// CHECK-LABEL: moore.module @UnpackedRangeDim
module UnpackedRangeDim;
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<range<logic, 2:0>>
// CHECK-NEXT: %d1 = moore.variable : !moore.unpacked<range<logic, 0:2>>
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<range<l1, 2:0>>
// CHECK-NEXT: %d1 = moore.variable : !moore.unpacked<range<l1, 0:2>>
logic d0 [2:0];
logic d1 [0:2];
endmodule
// CHECK-LABEL: moore.module @UnpackedUnsizedDim
module UnpackedUnsizedDim;
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<unsized<logic>>
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<unsized<l1>>
logic d0 [];
endmodule

View File

@ -2,73 +2,73 @@
// CHECK-LABEL: func @FuncArgsAndReturns
// CHECK-SAME: (%arg0: i8, %arg1: i32, %arg2: i1) -> i8
func.func @FuncArgsAndReturns(%arg0: !moore.byte, %arg1: !moore.int, %arg2: !moore.bit) -> !moore.byte {
func.func @FuncArgsAndReturns(%arg0: !moore.i8, %arg1: !moore.i32, %arg2: !moore.i1) -> !moore.i8 {
// CHECK-NEXT: return %arg0 : i8
return %arg0 : !moore.byte
return %arg0 : !moore.i8
}
// CHECK-LABEL: func @ControlFlow
// CHECK-SAME: (%arg0: i32, %arg1: i1)
func.func @ControlFlow(%arg0: !moore.int, %arg1: i1) {
func.func @ControlFlow(%arg0: !moore.i32, %arg1: i1) {
// CHECK-NEXT: cf.br ^bb1(%arg0 : i32)
// CHECK-NEXT: ^bb1(%0: i32):
// CHECK-NEXT: cf.cond_br %arg1, ^bb1(%0 : i32), ^bb2(%arg0 : i32)
// CHECK-NEXT: ^bb2(%1: i32):
// CHECK-NEXT: return
cf.br ^bb1(%arg0: !moore.int)
^bb1(%0: !moore.int):
cf.cond_br %arg1, ^bb1(%0 : !moore.int), ^bb2(%arg0 : !moore.int)
^bb2(%1: !moore.int):
cf.br ^bb1(%arg0: !moore.i32)
^bb1(%0: !moore.i32):
cf.cond_br %arg1, ^bb1(%0 : !moore.i32), ^bb2(%arg0 : !moore.i32)
^bb2(%1: !moore.i32):
return
}
// CHECK-LABEL: func @Calls
// CHECK-SAME: (%arg0: i8, %arg1: i32, %arg2: i1) -> i8
func.func @Calls(%arg0: !moore.byte, %arg1: !moore.int, %arg2: !moore.bit) -> !moore.byte {
func.func @Calls(%arg0: !moore.i8, %arg1: !moore.i32, %arg2: !moore.i1) -> !moore.i8 {
// CHECK-NEXT: %true =
// CHECK-NEXT: call @ControlFlow(%arg1, %true) : (i32, i1) -> ()
// CHECK-NEXT: [[TMP:%.+]] = call @FuncArgsAndReturns(%arg0, %arg1, %arg2) : (i8, i32, i1) -> i8
// CHECK-NEXT: return [[TMP]] : i8
%true = hw.constant true
call @ControlFlow(%arg1, %true) : (!moore.int, i1) -> ()
%0 = call @FuncArgsAndReturns(%arg0, %arg1, %arg2) : (!moore.byte, !moore.int, !moore.bit) -> !moore.byte
return %0 : !moore.byte
call @ControlFlow(%arg1, %true) : (!moore.i32, i1) -> ()
%0 = call @FuncArgsAndReturns(%arg0, %arg1, %arg2) : (!moore.i8, !moore.i32, !moore.i1) -> !moore.i8
return %0 : !moore.i8
}
// CHECK-LABEL: func @UnrealizedConversionCast
func.func @UnrealizedConversionCast(%arg0: !moore.byte) -> !moore.shortint {
func.func @UnrealizedConversionCast(%arg0: !moore.i8) -> !moore.i16 {
// CHECK-NEXT: [[TMP:%.+]] = comb.concat %arg0, %arg0 : i8, i8
// CHECK-NEXT: return [[TMP]] : i16
%0 = builtin.unrealized_conversion_cast %arg0 : !moore.byte to i8
%0 = builtin.unrealized_conversion_cast %arg0 : !moore.i8 to i8
%1 = comb.concat %0, %0 : i8, i8
%2 = builtin.unrealized_conversion_cast %1 : i16 to !moore.shortint
return %2 : !moore.shortint
%2 = builtin.unrealized_conversion_cast %1 : i16 to !moore.i16
return %2 : !moore.i16
}
// CHECK-LABEL: func @Expressions
func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.packed<range<bit, 5:0>>, %arg3: !moore.packed<range<bit, 4:0>>, %arg4: !moore.bit) {
func.func @Expressions(%arg0: !moore.i1, %arg1: !moore.l1, %arg2: !moore.i6, %arg3: !moore.i5, %arg4: !moore.i1) {
// CHECK-NEXT: %0 = comb.concat %arg0, %arg0 : i1, i1
// CHECK-NEXT: %1 = comb.concat %arg1, %arg1 : i1, i1
moore.concat %arg0, %arg0 : (!moore.bit, !moore.bit) -> !moore.packed<range<bit, 1:0>>
moore.concat %arg1, %arg1 : (!moore.logic, !moore.logic) -> !moore.packed<range<logic, 1:0>>
moore.concat %arg0, %arg0 : (!moore.i1, !moore.i1) -> !moore.i2
moore.concat %arg1, %arg1 : (!moore.l1, !moore.l1) -> !moore.l2
// CHECK-NEXT: comb.replicate %arg0 : (i1) -> i2
// CHECK-NEXT: comb.replicate %arg1 : (i1) -> i2
moore.replicate %arg0 : (!moore.bit) -> !moore.packed<range<bit, 1:0>>
moore.replicate %arg1 : (!moore.logic) -> !moore.packed<range<logic, 1:0>>
moore.replicate %arg0 : (!moore.i1) -> !moore.i2
moore.replicate %arg1 : (!moore.l1) -> !moore.l2
// CHECK-NEXT: %c12_i32 = hw.constant 12 : i32
// CHECK-NEXT: %c3_i6 = hw.constant 3 : i6
moore.constant 12 : !moore.int
moore.constant 3 : !moore.packed<range<bit, 5:0>>
moore.constant 12 : !moore.i32
moore.constant 3 : !moore.i6
// CHECK-NEXT: hw.bitcast %arg0 : (i1) -> i1
moore.conversion %arg0 : !moore.bit -> !moore.logic
moore.conversion %arg0 : !moore.i1 -> !moore.l1
// CHECK-NEXT: [[V0:%.+]] = hw.constant 0 : i5
// CHECK-NEXT: [[V1:%.+]] = comb.concat [[V0]], %arg0 : i5, i1
// CHECK-NEXT: comb.shl %arg2, [[V1]] : i6
moore.shl %arg2, %arg0 : !moore.packed<range<bit, 5:0>>, !moore.bit
moore.shl %arg2, %arg0 : !moore.i6, !moore.i1
// CHECK-NEXT: [[V2:%.+]] = comb.extract %arg2 from 5 : (i6) -> i1
// CHECK-NEXT: [[V3:%.+]] = hw.constant false
@ -77,15 +77,15 @@ func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.pac
// CHECK-NEXT: [[V6:%.+]] = hw.constant -1 : i5
// CHECK-NEXT: [[V7:%.+]] = comb.mux [[V4]], [[V5]], [[V6]] : i5
// CHECK-NEXT: comb.shl %arg3, [[V7]] : i5
moore.shl %arg3, %arg2 : !moore.packed<range<bit, 4:0>>, !moore.packed<range<bit, 5:0>>
moore.shl %arg3, %arg2 : !moore.i5, !moore.i6
// CHECK-NEXT: [[V8:%.+]] = hw.constant 0 : i5
// CHECK-NEXT: [[V9:%.+]] = comb.concat [[V8]], %arg0 : i5, i1
// CHECK-NEXT: comb.shru %arg2, [[V9]] : i6
moore.shr %arg2, %arg0 : !moore.packed<range<bit, 5:0>>, !moore.bit
moore.shr %arg2, %arg0 : !moore.i6, !moore.i1
// CHECK-NEXT: comb.shrs %arg2, %arg2 : i6
moore.ashr %arg2, %arg2 : !moore.packed<range<bit, 5:0>>, !moore.packed<range<bit, 5:0>>
moore.ashr %arg2, %arg2 : !moore.i6, !moore.i6
// CHECK-NEXT: [[V10:%.+]] = comb.extract %arg2 from 5 : (i6) -> i1
// CHECK-NEXT: [[V11:%.+]] = hw.constant false
@ -94,10 +94,10 @@ func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.pac
// CHECK-NEXT: [[V14:%.+]] = hw.constant -1 : i5
// CHECK-NEXT: [[V15:%.+]] = comb.mux [[V12]], [[V13]], [[V14]] : i5
// CHECK-NEXT: comb.shrs %arg3, [[V15]] : i5
moore.ashr %arg3, %arg2 : !moore.packed<range<bit, 4:0>>, !moore.packed<range<bit, 5:0>>
moore.ashr %arg3, %arg2 : !moore.i5, !moore.i6
// CHECK-NEXT: %c2_i32 = hw.constant 2 : i32
%2 = moore.constant 2 : !moore.int
%2 = moore.constant 2 : !moore.i32
// CHECK-NEXT: [[V16:%.+]] = comb.extract %c2_i32 from 6 : (i32) -> i26
// CHECK-NEXT: %c0_i26 = hw.constant 0 : i26
@ -107,7 +107,7 @@ func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.pac
// CHECK-NEXT: [[V19:%.+]] = comb.mux [[V17]], [[V18]], %c-1_i6 : i6
// CHECK-NEXT: [[V20:%.+]] = comb.shru %arg2, [[V19]] : i6
// CHECK-NEXT: comb.extract [[V20]] from 0 : (i6) -> i2
moore.extract %arg2 from %2 : !moore.packed<range<bit, 5:0>>, !moore.int -> !moore.packed<range<bit, 3:2>>
moore.extract %arg2 from %2 : !moore.i6, !moore.i32 -> !moore.i2
// CHECK-NEXT: [[V21:%.+]] = comb.extract %c2_i32 from 6 : (i32) -> i26
// CHECK-NEXT: %c0_i26_3 = hw.constant 0 : i26
@ -117,26 +117,26 @@ func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.pac
// CHECK-NEXT: [[V24:%.+]] = comb.mux [[V22]], [[V23]], %c-1_i6_4 : i6
// CHECK-NEXT: [[V25:%.+]] = comb.shru %arg2, [[V24]] : i6
// CHECK-NEXT: comb.extract [[V25]] from 0 : (i6) -> i1
moore.extract %arg2 from %2 : !moore.packed<range<bit, 5:0>>, !moore.int -> !moore.bit
moore.extract %arg2 from %2 : !moore.i6, !moore.i32 -> !moore.i1
// CHECK-NEXT: [[V26:%.+]] = hw.constant -1 : i6
// CHECK-NEXT: comb.icmp eq %arg2, [[V26]] : i6
moore.reduce_and %arg2 : !moore.packed<range<bit, 5:0>> -> !moore.bit
moore.reduce_and %arg2 : !moore.i6 -> !moore.i1
// CHECK-NEXT: [[V27:%.+]] = hw.constant false
// CHECK-NEXT: comb.icmp ne %arg0, [[V27]] : i1
moore.reduce_or %arg0 : !moore.bit -> !moore.bit
moore.reduce_or %arg0 : !moore.i1 -> !moore.i1
// CHECK-NEXT: comb.parity %arg1 : i1
moore.reduce_xor %arg1 : !moore.logic -> !moore.logic
moore.reduce_xor %arg1 : !moore.l1 -> !moore.l1
// CHECK-NEXT: [[V28:%.+]] = hw.constant 0 : i6
// CHECK-NEXT: comb.icmp ne %arg2, [[V28]] : i6
moore.bool_cast %arg2 : !moore.packed<range<bit, 5:0>> -> !moore.bit
moore.bool_cast %arg2 : !moore.i6 -> !moore.i1
// CHECK-NEXT: [[V29:%.+]] = hw.constant -1 : i6
// CHECK-NEXT: comb.xor %arg2, [[V29]] : i6
moore.not %arg2 : !moore.packed<range<bit, 5:0>>
moore.not %arg2 : !moore.i6
// CHECK-NEXT: comb.add %arg1, %arg1 : i1
// CHECK-NEXT: comb.sub %arg1, %arg1 : i1
@ -148,34 +148,34 @@ func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.pac
// CHECK-NEXT: comb.and %arg0, %arg0 : i1
// CHECK-NEXT: comb.or %arg0, %arg0 : i1
// CHECK-NEXT: comb.xor %arg0, %arg0 : i1
moore.add %arg1, %arg1 : !moore.logic
moore.sub %arg1, %arg1 : !moore.logic
moore.mul %arg1, %arg1 : !moore.logic
moore.divu %arg0, %arg0 : !moore.bit
moore.divs %arg4, %arg4 : !moore.bit
moore.modu %arg0, %arg0 : !moore.bit
moore.mods %arg4, %arg4 : !moore.bit
moore.and %arg0, %arg0 : !moore.bit
moore.or %arg0, %arg0 : !moore.bit
moore.xor %arg0, %arg0 : !moore.bit
moore.add %arg1, %arg1 : !moore.l1
moore.sub %arg1, %arg1 : !moore.l1
moore.mul %arg1, %arg1 : !moore.l1
moore.divu %arg0, %arg0 : !moore.i1
moore.divs %arg4, %arg4 : !moore.i1
moore.modu %arg0, %arg0 : !moore.i1
moore.mods %arg4, %arg4 : !moore.i1
moore.and %arg0, %arg0 : !moore.i1
moore.or %arg0, %arg0 : !moore.i1
moore.xor %arg0, %arg0 : !moore.i1
// CHECK-NEXT: comb.icmp ult %arg1, %arg1 : i1
// CHECK-NEXT: comb.icmp ule %arg0, %arg0 : i1
// CHECK-NEXT: comb.icmp ugt %arg0, %arg0 : i1
// CHECK-NEXT: comb.icmp uge %arg0, %arg0 : i1
moore.ult %arg1, %arg1 : !moore.logic -> !moore.logic
moore.ule %arg0, %arg0 : !moore.bit -> !moore.bit
moore.ugt %arg0, %arg0 : !moore.bit -> !moore.bit
moore.uge %arg0, %arg0 : !moore.bit -> !moore.bit
moore.ult %arg1, %arg1 : !moore.l1 -> !moore.l1
moore.ule %arg0, %arg0 : !moore.i1 -> !moore.i1
moore.ugt %arg0, %arg0 : !moore.i1 -> !moore.i1
moore.uge %arg0, %arg0 : !moore.i1 -> !moore.i1
// CHECK-NEXT: comb.icmp slt %arg4, %arg4 : i1
// CHECK-NEXT: comb.icmp sle %arg4, %arg4 : i1
// CHECK-NEXT: comb.icmp sgt %arg4, %arg4 : i1
// CHECK-NEXT: comb.icmp sge %arg4, %arg4 : i1
moore.slt %arg4, %arg4 : !moore.bit -> !moore.bit
moore.sle %arg4, %arg4 : !moore.bit -> !moore.bit
moore.sgt %arg4, %arg4 : !moore.bit -> !moore.bit
moore.sge %arg4, %arg4 : !moore.bit -> !moore.bit
moore.slt %arg4, %arg4 : !moore.i1 -> !moore.i1
moore.sle %arg4, %arg4 : !moore.i1 -> !moore.i1
moore.sgt %arg4, %arg4 : !moore.i1 -> !moore.i1
moore.sge %arg4, %arg4 : !moore.i1 -> !moore.i1
// CHECK-NEXT: comb.icmp eq %arg1, %arg1 : i1
// CHECK-NEXT: comb.icmp ne %arg0, %arg0 : i1
@ -183,12 +183,12 @@ func.func @Expressions(%arg0: !moore.bit, %arg1: !moore.logic, %arg2: !moore.pac
// CHECK-NEXT: comb.icmp cne %arg0, %arg0 : i1
// CHECK-NEXT: comb.icmp weq %arg0, %arg0 : i1
// CHECK-NEXT: comb.icmp wne %arg0, %arg0 : i1
moore.eq %arg1, %arg1 : !moore.logic -> !moore.logic
moore.ne %arg0, %arg0 : !moore.bit -> !moore.bit
moore.case_eq %arg0, %arg0 : !moore.bit
moore.case_ne %arg0, %arg0 : !moore.bit
moore.wildcard_eq %arg0, %arg0 : !moore.bit -> !moore.bit
moore.wildcard_ne %arg0, %arg0 : !moore.bit -> !moore.bit
moore.eq %arg1, %arg1 : !moore.l1 -> !moore.l1
moore.ne %arg0, %arg0 : !moore.i1 -> !moore.i1
moore.case_eq %arg0, %arg0 : !moore.i1
moore.case_ne %arg0, %arg0 : !moore.i1
moore.wildcard_eq %arg0, %arg0 : !moore.i1 -> !moore.i1
moore.wildcard_ne %arg0, %arg0 : !moore.i1 -> !moore.i1
// CHECK-NEXT: return
return

View File

@ -4,38 +4,38 @@
moore.module @Foo {
// CHECK: moore.instance "foo" @Foo
moore.instance "foo" @Foo
// CHECK: %v1 = moore.variable : !moore.bit
%v1 = moore.variable : !moore.bit
%v2 = moore.variable : !moore.bit
// CHECK: [[TMP:%.+]] = moore.variable name "v1" %v2 : !moore.bit
moore.variable name "v1" %v2 : !moore.bit
// CHECK: %v1 = moore.variable : !moore.i1
%v1 = moore.variable : !moore.i1
%v2 = moore.variable : !moore.i1
// CHECK: [[TMP:%.+]] = moore.variable name "v1" %v2 : !moore.i1
moore.variable name "v1" %v2 : !moore.i1
// CHECK: %w0 = moore.net wire : !moore.logic
%w0 = moore.net wire : !moore.logic
// CHECK: %w1 = moore.net wire %w0 : !moore.logic
%w1 = moore.net wire %w0 : !moore.logic
// CHECK: %w2 = moore.net uwire %w0 : !moore.logic
%w2 = moore.net uwire %w0 : !moore.logic
// CHECK: %w3 = moore.net tri %w0 : !moore.logic
%w3 = moore.net tri %w0 : !moore.logic
// CHECK: %w4 = moore.net triand %w0 : !moore.logic
%w4 = moore.net triand %w0 : !moore.logic
// CHECK: %w5 = moore.net trior %w0 : !moore.logic
%w5 = moore.net trior %w0 : !moore.logic
// CHECK: %w6 = moore.net wand %w0 : !moore.logic
%w6 = moore.net wand %w0 : !moore.logic
// CHECK: %w7 = moore.net wor %w0 : !moore.logic
%w7 = moore.net wor %w0 : !moore.logic
// CHECK: %w8 = moore.net trireg %w0 : !moore.logic
%w8 = moore.net trireg %w0 : !moore.logic
// CHECK: %w9 = moore.net tri0 %w0 : !moore.logic
%w9 = moore.net tri0 %w0 : !moore.logic
// CHECK: %w10 = moore.net tri1 %w0 : !moore.logic
%w10 = moore.net tri1 %w0 : !moore.logic
// CHECK: %w11 = moore.net supply0 : !moore.logic
%w11 = moore.net supply0 : !moore.logic
// CHECK: %w12 = moore.net supply1 : !moore.logic
%w12 = moore.net supply1 : !moore.logic
// CHECK: %w0 = moore.net wire : !moore.l1
%w0 = moore.net wire : !moore.l1
// CHECK: %w1 = moore.net wire %w0 : !moore.l1
%w1 = moore.net wire %w0 : !moore.l1
// CHECK: %w2 = moore.net uwire %w0 : !moore.l1
%w2 = moore.net uwire %w0 : !moore.l1
// CHECK: %w3 = moore.net tri %w0 : !moore.l1
%w3 = moore.net tri %w0 : !moore.l1
// CHECK: %w4 = moore.net triand %w0 : !moore.l1
%w4 = moore.net triand %w0 : !moore.l1
// CHECK: %w5 = moore.net trior %w0 : !moore.l1
%w5 = moore.net trior %w0 : !moore.l1
// CHECK: %w6 = moore.net wand %w0 : !moore.l1
%w6 = moore.net wand %w0 : !moore.l1
// CHECK: %w7 = moore.net wor %w0 : !moore.l1
%w7 = moore.net wor %w0 : !moore.l1
// CHECK: %w8 = moore.net trireg %w0 : !moore.l1
%w8 = moore.net trireg %w0 : !moore.l1
// CHECK: %w9 = moore.net tri0 %w0 : !moore.l1
%w9 = moore.net tri0 %w0 : !moore.l1
// CHECK: %w10 = moore.net tri1 %w0 : !moore.l1
%w10 = moore.net tri1 %w0 : !moore.l1
// CHECK: %w11 = moore.net supply0 : !moore.l1
%w11 = moore.net supply0 : !moore.l1
// CHECK: %w12 = moore.net supply1 : !moore.l1
%w12 = moore.net supply1 : !moore.l1
// CHECK: moore.procedure initial {
// CHECK: moore.procedure final {
@ -50,16 +50,16 @@ moore.module @Foo {
moore.procedure always_latch {}
moore.procedure always_ff {}
// CHECK: moore.assign %v1, %v2 : !moore.bit
moore.assign %v1, %v2 : !moore.bit
// CHECK: moore.assign %v1, %v2 : !moore.i1
moore.assign %v1, %v2 : !moore.i1
moore.procedure always {
// CHECK: moore.blocking_assign %v1, %v2 : !moore.bit
moore.blocking_assign %v1, %v2 : !moore.bit
// CHECK: moore.nonblocking_assign %v1, %v2 : !moore.bit
moore.nonblocking_assign %v1, %v2 : !moore.bit
// CHECK: %a = moore.variable : !moore.int
%a = moore.variable : !moore.int
// CHECK: moore.blocking_assign %v1, %v2 : !moore.i1
moore.blocking_assign %v1, %v2 : !moore.i1
// CHECK: moore.nonblocking_assign %v1, %v2 : !moore.i1
moore.nonblocking_assign %v1, %v2 : !moore.i1
// CHECK: %a = moore.variable : !moore.i32
%a = moore.variable : !moore.i32
}
}
@ -69,123 +69,130 @@ moore.module @Bar {
// CHECK-LABEL: moore.module @Expressions
moore.module @Expressions {
%b1 = moore.variable : !moore.bit
%l1 = moore.variable : !moore.logic
%b5 = moore.variable : !moore.packed<range<bit, 4:0>>
%int = moore.variable : !moore.int
%int2 = moore.variable : !moore.int
%integer = moore.variable : !moore.integer
%integer2 = moore.variable : !moore.integer
%arr = moore.variable : !moore.unpacked<range<range<packed<range<bit, 7:0>>, 0:3>, 0:1>>
%b1 = moore.variable : !moore.i1
%l1 = moore.variable : !moore.l1
%b5 = moore.variable : !moore.i5
%int = moore.variable : !moore.i32
%int2 = moore.variable : !moore.i32
%integer = moore.variable : !moore.l32
%integer2 = moore.variable : !moore.l32
%arr = moore.variable : !moore.unpacked<range<range<i8, 0:3>, 0:1>>
// CHECK: moore.constant 0 : !moore.int
moore.constant 0 : !moore.int
// CHECK: moore.constant -2 : !moore.packed<range<bit, 1:0>>
moore.constant 2 : !moore.packed<range<bit, 1:0>>
// CHECK: moore.constant -2 : !moore.packed<range<bit, 1:0>>
moore.constant -2 : !moore.packed<range<bit, 1:0>>
// CHECK: moore.constant 0 : !moore.i32
moore.constant 0 : !moore.i32
// CHECK: moore.constant -2 : !moore.i2
moore.constant 2 : !moore.i2
// CHECK: moore.constant -2 : !moore.i2
moore.constant -2 : !moore.i2
// CHECK: moore.conversion %b5 : !moore.packed<range<bit, 4:0>> -> !moore.packed<range<logic, 4:0>>
moore.conversion %b5 : !moore.packed<range<bit, 4:0>> -> !moore.packed<range<logic, 4:0>>
// CHECK: moore.conversion %b5 : !moore.i5 -> !moore.l5
moore.conversion %b5 : !moore.i5 -> !moore.l5
// CHECK: moore.neg %int : !moore.int
moore.neg %int : !moore.int
// CHECK: moore.not %int : !moore.int
moore.not %int : !moore.int
// CHECK: moore.neg %int : !moore.i32
moore.neg %int : !moore.i32
// CHECK: moore.not %int : !moore.i32
moore.not %int : !moore.i32
// CHECK: moore.reduce_and %int : !moore.int -> !moore.bit
moore.reduce_and %int : !moore.int -> !moore.bit
// CHECK: moore.reduce_or %int : !moore.int -> !moore.bit
moore.reduce_or %int : !moore.int -> !moore.bit
// CHECK: moore.reduce_xor %int : !moore.int -> !moore.bit
moore.reduce_xor %int : !moore.int -> !moore.bit
// CHECK: moore.reduce_xor %integer : !moore.integer -> !moore.logic
moore.reduce_xor %integer : !moore.integer -> !moore.logic
// CHECK: moore.reduce_and %int : !moore.i32 -> !moore.i1
moore.reduce_and %int : !moore.i32 -> !moore.i1
// CHECK: moore.reduce_or %int : !moore.i32 -> !moore.i1
moore.reduce_or %int : !moore.i32 -> !moore.i1
// CHECK: moore.reduce_xor %int : !moore.i32 -> !moore.i1
moore.reduce_xor %int : !moore.i32 -> !moore.i1
// CHECK: moore.reduce_xor %integer : !moore.l32 -> !moore.l1
moore.reduce_xor %integer : !moore.l32 -> !moore.l1
// CHECK: moore.bool_cast %int : !moore.int -> !moore.bit
moore.bool_cast %int : !moore.int -> !moore.bit
// CHECK: moore.bool_cast %integer : !moore.integer -> !moore.logic
moore.bool_cast %integer : !moore.integer -> !moore.logic
// CHECK: moore.bool_cast %int : !moore.i32 -> !moore.i1
moore.bool_cast %int : !moore.i32 -> !moore.i1
// CHECK: moore.bool_cast %integer : !moore.l32 -> !moore.l1
moore.bool_cast %integer : !moore.l32 -> !moore.l1
// CHECK: moore.add %int, %int2 : !moore.int
moore.add %int, %int2 : !moore.int
// CHECK: moore.sub %int, %int2 : !moore.int
moore.sub %int, %int2 : !moore.int
// CHECK: moore.mul %int, %int2 : !moore.int
moore.mul %int, %int2 : !moore.int
// CHECK: moore.divu %int, %int2 : !moore.int
moore.divu %int, %int2 : !moore.int
// CHECK: moore.divs %int, %int2 : !moore.int
moore.divs %int, %int2 : !moore.int
// CHECK: moore.modu %int, %int2 : !moore.int
moore.modu %int, %int2 : !moore.int
// CHECK: moore.mods %int, %int2 : !moore.int
moore.mods %int, %int2 : !moore.int
// CHECK: moore.add %int, %int2 : !moore.i32
moore.add %int, %int2 : !moore.i32
// CHECK: moore.sub %int, %int2 : !moore.i32
moore.sub %int, %int2 : !moore.i32
// CHECK: moore.mul %int, %int2 : !moore.i32
moore.mul %int, %int2 : !moore.i32
// CHECK: moore.divu %int, %int2 : !moore.i32
moore.divu %int, %int2 : !moore.i32
// CHECK: moore.divs %int, %int2 : !moore.i32
moore.divs %int, %int2 : !moore.i32
// CHECK: moore.modu %int, %int2 : !moore.i32
moore.modu %int, %int2 : !moore.i32
// CHECK: moore.mods %int, %int2 : !moore.i32
moore.mods %int, %int2 : !moore.i32
// CHECK: moore.shl %l1, %b1 : !moore.logic, !moore.bit
moore.shl %l1, %b1 : !moore.logic, !moore.bit
// CHECK: moore.shr %l1, %b1 : !moore.logic, !moore.bit
moore.shr %l1, %b1 : !moore.logic, !moore.bit
// CHECK: moore.ashr %b5, %b1 : !moore.packed<range<bit, 4:0>>, !moore.bit
moore.ashr %b5, %b1 : !moore.packed<range<bit, 4:0>>, !moore.bit
// CHECK: moore.and %int, %int2 : !moore.i32
moore.and %int, %int2 : !moore.i32
// CHECK: moore.or %int, %int2 : !moore.i32
moore.or %int, %int2 : !moore.i32
// CHECK: moore.xor %int, %int2 : !moore.i32
moore.xor %int, %int2 : !moore.i32
// CHECK: moore.eq %int, %int2 : !moore.int -> !moore.bit
moore.eq %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.ne %int, %int2 : !moore.int -> !moore.bit
moore.ne %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.ne %integer, %integer2 : !moore.integer -> !moore.logic
moore.ne %integer, %integer2 : !moore.integer -> !moore.logic
// CHECK: moore.case_eq %int, %int2 : !moore.int
moore.case_eq %int, %int2 : !moore.int
// CHECK: moore.case_ne %int, %int2 : !moore.int
moore.case_ne %int, %int2 : !moore.int
// CHECK: moore.wildcard_eq %int, %int2 : !moore.int -> !moore.bit
moore.wildcard_eq %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.wildcard_ne %int, %int2 : !moore.int -> !moore.bit
moore.wildcard_ne %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.wildcard_ne %integer, %integer2 : !moore.integer -> !moore.logic
moore.wildcard_ne %integer, %integer2 : !moore.integer -> !moore.logic
// CHECK: moore.shl %l1, %b1 : !moore.l1, !moore.i1
moore.shl %l1, %b1 : !moore.l1, !moore.i1
// CHECK: moore.shr %l1, %b1 : !moore.l1, !moore.i1
moore.shr %l1, %b1 : !moore.l1, !moore.i1
// CHECK: moore.ashr %b5, %b1 : !moore.i5, !moore.i1
moore.ashr %b5, %b1 : !moore.i5, !moore.i1
// CHECK: moore.ult %int, %int2 : !moore.int -> !moore.bit
moore.ult %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.ule %int, %int2 : !moore.int -> !moore.bit
moore.ule %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.ugt %int, %int2 : !moore.int -> !moore.bit
moore.ugt %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.uge %int, %int2 : !moore.int -> !moore.bit
moore.uge %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.slt %int, %int2 : !moore.int -> !moore.bit
moore.slt %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.sle %int, %int2 : !moore.int -> !moore.bit
moore.sle %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.sgt %int, %int2 : !moore.int -> !moore.bit
moore.sgt %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.sge %int, %int2 : !moore.int -> !moore.bit
moore.sge %int, %int2 : !moore.int -> !moore.bit
// CHECK: moore.uge %integer, %integer2 : !moore.integer -> !moore.logic
moore.uge %integer, %integer2 : !moore.integer -> !moore.logic
// CHECK: moore.eq %int, %int2 : !moore.i32 -> !moore.i1
moore.eq %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.ne %int, %int2 : !moore.i32 -> !moore.i1
moore.ne %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.ne %integer, %integer2 : !moore.l32 -> !moore.l1
moore.ne %integer, %integer2 : !moore.l32 -> !moore.l1
// CHECK: moore.case_eq %int, %int2 : !moore.i32
moore.case_eq %int, %int2 : !moore.i32
// CHECK: moore.case_ne %int, %int2 : !moore.i32
moore.case_ne %int, %int2 : !moore.i32
// CHECK: moore.wildcard_eq %int, %int2 : !moore.i32 -> !moore.i1
moore.wildcard_eq %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.wildcard_ne %int, %int2 : !moore.i32 -> !moore.i1
moore.wildcard_ne %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.wildcard_ne %integer, %integer2 : !moore.l32 -> !moore.l1
moore.wildcard_ne %integer, %integer2 : !moore.l32 -> !moore.l1
// CHECK: moore.concat %b1 : (!moore.bit) -> !moore.bit
moore.concat %b1 : (!moore.bit) -> !moore.bit
// CHECK: moore.concat %b5, %b1 : (!moore.packed<range<bit, 4:0>>, !moore.bit) -> !moore.packed<range<bit, 5:0>>
moore.concat %b5, %b1 : (!moore.packed<range<bit, 4:0>>, !moore.bit) -> !moore.packed<range<bit, 5:0>>
// CHECK: moore.concat %l1, %l1, %l1 : (!moore.logic, !moore.logic, !moore.logic) -> !moore.packed<range<logic, 2:0>>
moore.concat %l1, %l1, %l1 : (!moore.logic, !moore.logic, !moore.logic) -> !moore.packed<range<logic, 2:0>>
// CHECK: moore.replicate %b1 : (!moore.bit) -> !moore.packed<range<bit, 3:0>>
moore.replicate %b1 : (!moore.bit) -> !moore.packed<range<bit, 3:0>>
// CHECK: moore.ult %int, %int2 : !moore.i32 -> !moore.i1
moore.ult %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.ule %int, %int2 : !moore.i32 -> !moore.i1
moore.ule %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.ugt %int, %int2 : !moore.i32 -> !moore.i1
moore.ugt %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.uge %int, %int2 : !moore.i32 -> !moore.i1
moore.uge %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.slt %int, %int2 : !moore.i32 -> !moore.i1
moore.slt %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.sle %int, %int2 : !moore.i32 -> !moore.i1
moore.sle %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.sgt %int, %int2 : !moore.i32 -> !moore.i1
moore.sgt %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.sge %int, %int2 : !moore.i32 -> !moore.i1
moore.sge %int, %int2 : !moore.i32 -> !moore.i1
// CHECK: moore.uge %integer, %integer2 : !moore.l32 -> !moore.l1
moore.uge %integer, %integer2 : !moore.l32 -> !moore.l1
// CHECK: moore.extract %b5 from %b1 : !moore.packed<range<bit, 4:0>>, !moore.bit -> !moore.bit
moore.extract %b5 from %b1 : !moore.packed<range<bit, 4:0>>, !moore.bit -> !moore.bit
// CHECK: [[VAL1:%.*]] = moore.constant 0 : !moore.int
// CHECK: [[VAL2:%.*]] = moore.extract %arr from [[VAL1]] : !moore.unpacked<range<range<packed<range<bit, 7:0>>, 0:3>, 0:1>>, !moore.int -> !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>
%1 = moore.constant 0 : !moore.int
%2 = moore.extract %arr from %1 : !moore.unpacked<range<range<packed<range<bit, 7:0>>, 0:3>, 0:1>>, !moore.int -> !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>
// CHECK: [[VAL3:%.*]] = moore.constant 3 : !moore.int
// CHECK: [[VAL4:%.*]] = moore.extract [[VAL2]] from [[VAL3]] : !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>, !moore.int -> !moore.packed<range<bit, 7:0>>
%3 = moore.constant 3 : !moore.int
%4 = moore.extract %2 from %3 : !moore.unpacked<range<packed<range<bit, 7:0>>, 0:3>>, !moore.int -> !moore.packed<range<bit, 7:0>>
// CHECK: [[VAL5:%.*]] = moore.constant 2 : !moore.int
// CHECK: moore.extract [[VAL4]] from [[VAL5]] : !moore.packed<range<bit, 7:0>>, !moore.int -> !moore.packed<range<bit, 6:2>>
%5 = moore.constant 2 : !moore.int
moore.extract %4 from %5 : !moore.packed<range<bit, 7:0>>, !moore.int -> !moore.packed<range<bit, 6:2>>
// CHECK: moore.concat %b1 : (!moore.i1) -> !moore.i1
moore.concat %b1 : (!moore.i1) -> !moore.i1
// CHECK: moore.concat %b5, %b1 : (!moore.i5, !moore.i1) -> !moore.i6
moore.concat %b5, %b1 : (!moore.i5, !moore.i1) -> !moore.i6
// CHECK: moore.concat %l1, %l1, %l1 : (!moore.l1, !moore.l1, !moore.l1) -> !moore.l3
moore.concat %l1, %l1, %l1 : (!moore.l1, !moore.l1, !moore.l1) -> !moore.l3
// CHECK: moore.replicate %b1 : (!moore.i1) -> !moore.i4
moore.replicate %b1 : (!moore.i1) -> !moore.i4
// CHECK: moore.extract %b5 from %b1 : !moore.i5, !moore.i1 -> !moore.i1
moore.extract %b5 from %b1 : !moore.i5, !moore.i1 -> !moore.i1
// CHECK: [[VAL1:%.*]] = moore.constant 0 : !moore.i32
// CHECK: [[VAL2:%.*]] = moore.extract %arr from [[VAL1]] : !moore.unpacked<range<range<i8, 0:3>, 0:1>>, !moore.i32 -> !moore.unpacked<range<i8, 0:3>>
%1 = moore.constant 0 : !moore.i32
%2 = moore.extract %arr from %1 : !moore.unpacked<range<range<i8, 0:3>, 0:1>>, !moore.i32 -> !moore.unpacked<range<i8, 0:3>>
// CHECK: [[VAL3:%.*]] = moore.constant 3 : !moore.i32
// CHECK: [[VAL4:%.*]] = moore.extract [[VAL2]] from [[VAL3]] : !moore.unpacked<range<i8, 0:3>>, !moore.i32 -> !moore.i8
%3 = moore.constant 3 : !moore.i32
%4 = moore.extract %2 from %3 : !moore.unpacked<range<i8, 0:3>>, !moore.i32 -> !moore.i8
// CHECK: [[VAL5:%.*]] = moore.constant 2 : !moore.i32
// CHECK: moore.extract [[VAL4]] from [[VAL5]] : !moore.i8, !moore.i32 -> !moore.i5
%5 = moore.constant 2 : !moore.i32
moore.extract %4 from %5 : !moore.i8, !moore.i32 -> !moore.i5
}

View File

@ -1,11 +1,11 @@
// RUN: circt-opt --canonicalize %s | FileCheck %s
// CHECK-LABEL: func.func @Casts
func.func @Casts(%arg0: !moore.bit) -> (!moore.bit, !moore.bit) {
func.func @Casts(%arg0: !moore.i1) -> (!moore.i1, !moore.i1) {
// CHECK-NOT: moore.conversion
// CHECK-NOT: moore.bool_cast
%0 = moore.conversion %arg0 : !moore.bit -> !moore.bit
%1 = moore.bool_cast %arg0 : !moore.bit -> !moore.bit
%0 = moore.conversion %arg0 : !moore.i1 -> !moore.i1
%1 = moore.bool_cast %arg0 : !moore.i1 -> !moore.i1
// CHECK: return %arg0, %arg0
return %0, %1 : !moore.bit, !moore.bit
return %0, %1 : !moore.i1, !moore.i1
}

View File

@ -11,15 +11,15 @@ moore.module @Bar {
// -----
// expected-error @below {{constant out of range for result type '!moore.bit'}}
moore.constant 42 : !moore.bit
// expected-error @below {{constant out of range for result type '!moore.i1'}}
moore.constant 42 : !moore.i1
// -----
// expected-error @below {{constant out of range for result type '!moore.bit'}}
moore.constant -2 : !moore.bit
// expected-error @below {{constant out of range for result type '!moore.i1'}}
moore.constant -2 : !moore.i1
// -----
// expected-error @below {{attribute width 9 does not match return type's width 8}}
"moore.constant" () {value = 42 : i9} : () -> !moore.byte
"moore.constant" () {value = 42 : i9} : () -> !moore.i8

View File

@ -1,11 +1,11 @@
// RUN: circt-opt --verify-diagnostics --split-input-file %s
// expected-error @+1 {{ambiguous packing; wrap `unsized` in `packed<...>` or `unpacked<...>` to disambiguate}}
func.func @Foo(%arg0: !moore.unsized<bit>) { return }
func.func @Foo(%arg0: !moore.unsized<i1>) { return }
// -----
// expected-error @+1 {{ambiguous packing; wrap `range` in `packed<...>` or `unpacked<...>` to disambiguate}}
func.func @Foo(%arg0: !moore.range<bit, 3:0>) { return }
func.func @Foo(%arg0: !moore.range<i1, 3:0>) { return }
// -----
// expected-error @+1 {{ambiguous packing; wrap `struct` in `packed<...>` or `unpacked<...>` to disambiguate}}

View File

@ -14,24 +14,10 @@ func.func @UnitTypes(
// CHECK-LABEL: func @IntTypes(
func.func @IntTypes(
// CHECK-SAME: %arg0: !moore.bit
// CHECK-SAME: %arg1: !moore.logic
// CHECK-SAME: %arg2: !moore.reg
// CHECK-SAME: %arg3: !moore.byte
// CHECK-SAME: %arg4: !moore.shortint
// CHECK-SAME: %arg5: !moore.int
// CHECK-SAME: %arg6: !moore.longint
// CHECK-SAME: %arg7: !moore.integer
// CHECK-SAME: %arg8: !moore.time
%arg0: !moore.bit,
%arg1: !moore.logic,
%arg2: !moore.reg,
%arg3: !moore.byte,
%arg4: !moore.shortint,
%arg5: !moore.int,
%arg6: !moore.longint,
%arg7: !moore.integer,
%arg8: !moore.time
// CHECK-SAME: %arg0: !moore.i42
// CHECK-SAME: %arg1: !moore.l42
%arg0: !moore.i42,
%arg1: !moore.l42
) { return }
// CHECK-LABEL: func @RealTypes(
@ -46,24 +32,24 @@ func.func @RealTypes(
// CHECK-LABEL: func @DimTypes(
func.func @DimTypes(
// CHECK-SAME: %arg0: !moore.packed<unsized<bit>>,
// CHECK-SAME: %arg1: !moore.packed<range<bit, 4:-5>>,
%arg0: !moore.packed<unsized<bit>>,
%arg1: !moore.packed<range<bit, 4:-5>>,
// CHECK-SAME: %arg2: !moore.unpacked<unsized<bit>>,
// CHECK-SAME: %arg3: !moore.unpacked<array<bit, 42>>,
// CHECK-SAME: %arg4: !moore.unpacked<range<bit, 4:-5>>,
// CHECK-SAME: %arg5: !moore.unpacked<assoc<bit>>,
// CHECK-SAME: %arg6: !moore.unpacked<assoc<bit, string>>,
// CHECK-SAME: %arg7: !moore.unpacked<queue<bit>>,
// CHECK-SAME: %arg8: !moore.unpacked<queue<bit, 9001>>
%arg2: !moore.unpacked<unsized<bit>>,
%arg3: !moore.unpacked<array<bit, 42>>,
%arg4: !moore.unpacked<range<bit, 4:-5>>,
%arg5: !moore.unpacked<assoc<bit>>,
%arg6: !moore.unpacked<assoc<bit, string>>,
%arg7: !moore.unpacked<queue<bit>>,
%arg8: !moore.unpacked<queue<bit, 9001>>
// CHECK-SAME: %arg0: !moore.packed<unsized<i1>>,
// CHECK-SAME: %arg1: !moore.packed<range<i1, 4:-5>>,
%arg0: !moore.packed<unsized<i1>>,
%arg1: !moore.packed<range<i1, 4:-5>>,
// CHECK-SAME: %arg2: !moore.unpacked<unsized<i1>>,
// CHECK-SAME: %arg3: !moore.unpacked<array<i1, 42>>,
// CHECK-SAME: %arg4: !moore.unpacked<range<i1, 4:-5>>,
// CHECK-SAME: %arg5: !moore.unpacked<assoc<i1>>,
// CHECK-SAME: %arg6: !moore.unpacked<assoc<i1, string>>,
// CHECK-SAME: %arg7: !moore.unpacked<queue<i1>>,
// CHECK-SAME: %arg8: !moore.unpacked<queue<i1, 9001>>
%arg2: !moore.unpacked<unsized<i1>>,
%arg3: !moore.unpacked<array<i1, 42>>,
%arg4: !moore.unpacked<range<i1, 4:-5>>,
%arg5: !moore.unpacked<assoc<i1>>,
%arg6: !moore.unpacked<assoc<i1, string>>,
%arg7: !moore.unpacked<queue<i1>>,
%arg8: !moore.unpacked<queue<i1, 9001>>
) {
return
}
@ -71,9 +57,9 @@ func.func @DimTypes(
// CHECK-LABEL: func @StructTypes(
func.func @StructTypes(
// CHECK-SAME: %arg0: !moore.packed<struct<{}>>
// CHECK-SAME: %arg1: !moore.packed<struct<{foo: bit, bar: int}>>
// CHECK-SAME: %arg1: !moore.packed<struct<{foo: i1, bar: i32}>>
%arg0: !moore.packed<struct<{}>>,
%arg1: !moore.packed<struct<{foo: bit, bar: int}>>,
%arg1: !moore.packed<struct<{foo: i1, bar: i32}>>,
// CHECK-SAME: %arg2: !moore.unpacked<struct<{}>>
// CHECK-SAME: %arg3: !moore.unpacked<struct<{foo: string, bar: event}>>
%arg2: !moore.unpacked<struct<{}>>,

View File

@ -68,23 +68,14 @@ TEST(TypesTest, PackedInt) {
MLIRContext context;
context.loadDialect<MooreDialect>();
std::tuple<IntType::Kind, StringRef, Domain, Sign> pairs[] = {
{IntType::Bit, "bit", Domain::TwoValued, Sign::Unsigned},
{IntType::Logic, "logic", Domain::FourValued, Sign::Unsigned},
{IntType::Reg, "reg", Domain::FourValued, Sign::Unsigned},
{IntType::Byte, "byte", Domain::TwoValued, Sign::Signed},
{IntType::ShortInt, "shortint", Domain::TwoValued, Sign::Signed},
{IntType::Int, "int", Domain::TwoValued, Sign::Signed},
{IntType::LongInt, "longint", Domain::TwoValued, Sign::Signed},
{IntType::Integer, "integer", Domain::FourValued, Sign::Signed},
{IntType::Time, "time", Domain::TwoValued, Sign::Unsigned},
};
auto i42 = IntType::getInt(&context, 42);
auto l42 = IntType::getLogic(&context, 42);
for (auto pair : pairs) {
auto kind = std::get<0>(pair);
auto type = IntType::get(&context, kind);
ASSERT_EQ(type.getDomain(), std::get<2>(pair));
}
ASSERT_EQ(i42.getBitSize(), 42u);
ASSERT_EQ(l42.getBitSize(), 42u);
ASSERT_EQ(i42.getDomain(), Domain::TwoValued);
ASSERT_EQ(l42.getDomain(), Domain::FourValued);
}
TEST(TypesTest, Reals) {
@ -108,15 +99,13 @@ TEST(TypesTest, PackedDim) {
MLIRContext context;
context.loadDialect<MooreDialect>();
auto bitType = IntType::get(&context, IntType::Bit);
auto arrayType1 = PackedRangeDim::get(bitType, 3);
auto arrayType1 = IntType::getInt(&context, 3);
auto arrayType2 = PackedRangeDim::get(arrayType1, 2);
auto arrayType3 = PackedUnsizedDim::get(arrayType2);
ASSERT_EQ(arrayType1.getRange(), Range(3));
ASSERT_EQ(arrayType2.getRange(), Range(2));
ASSERT_EQ(arrayType3.getRange(), std::nullopt);
ASSERT_EQ(arrayType1.getSize(), 3u);
ASSERT_EQ(arrayType2.getSize(), 2u);
ASSERT_EQ(arrayType3.getSize(), std::nullopt);
}
@ -147,9 +136,9 @@ TEST(TypesTest, Structs) {
auto foo = StringAttr::get(&context, "foo");
auto bar = StringAttr::get(&context, "bar");
auto bitType = IntType::get(&context, IntType::Bit);
auto logicType = IntType::get(&context, IntType::Logic);
auto bit8Type = PackedRangeDim::get(bitType, 8);
auto bitType = IntType::getInt(&context, 1);
auto logicType = IntType::getLogic(&context, 1);
auto bit8Type = IntType::getInt(&context, 8);
auto bitDynArrayType = PackedUnsizedDim::get(bitType);
auto s0 = UnpackedStructType::get(&context, StructKind::Struct,
@ -165,8 +154,10 @@ TEST(TypesTest, Structs) {
{StructMember{foo, bitType}, StructMember{bar, bitDynArrayType}});
// Value domain
ASSERT_EQ(s0.getDomain(), Domain::TwoValued);
ASSERT_EQ(s1.getDomain(), Domain::TwoValued);
ASSERT_EQ(s2.getDomain(), Domain::FourValued);
ASSERT_EQ(s3.getDomain(), Domain::TwoValued);
// Bit size
ASSERT_EQ(s0.getBitSize(), 1u);
@ -175,27 +166,4 @@ TEST(TypesTest, Structs) {
ASSERT_EQ(s3.getBitSize(), std::nullopt);
}
TEST(TypesTest, SimpleBitVectorTypes) {
MLIRContext context;
context.loadDialect<MooreDialect>();
// Unpacked types have no SBV equivalent.
auto stringType = StringType::get(&context);
ASSERT_FALSE(stringType.isSimpleBitVector());
ASSERT_FALSE(stringType.isCastableToSimpleBitVector());
// Void is packed but cannot be cast to an SBV.
auto voidType = VoidType::get(&context);
ASSERT_FALSE(voidType.isSimpleBitVector());
ASSERT_FALSE(voidType.isCastableToSimpleBitVector());
// Integer atoms with a dimension are no SBVT, but can be cast to one.
auto intTy = IntType::get(&context, IntType::Int);
auto intArray = PackedRangeDim::get(intTy, 8);
ASSERT_FALSE(intArray.isSimpleBitVector());
ASSERT_TRUE(intArray.isCastableToSimpleBitVector());
ASSERT_EQ(intArray.castToSimpleBitVector(),
SimpleBitVectorType(Domain::TwoValued, 256));
}
} // namespace