mirror of https://github.com/llvm/circt.git
[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:
parent
5ac765214c
commit
6a2b628129
|
@ -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"]
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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)
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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<{}>>,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue