mirror of https://github.com/llvm/circt.git
[ImportVerilog] Add type conversion and basic variables (#6755)
Implement the conversion from SystemVerilog types in Slang's AST to the corresponding MLIR types in the Moore dialect. To facilitate testing, add a basic `moore.variable` op and convert module-level variable declarations to this new op. This requires converting the variable's type. We may choose to have variables return a special lvalue or pointer wrapper type in the future once such a need arises to clearly demarcate variable reading and assignment. Since we don't support expressions yet, variables with an initializer expression cause an error for the time being.
This commit is contained in:
parent
8afd534537
commit
a249766958
|
@ -11,6 +11,7 @@
|
|||
|
||||
include "circt/Dialect/Moore/MooreDialect.td"
|
||||
include "circt/Dialect/Moore/MooreTypes.td"
|
||||
include "mlir/IR/OpAsmInterface.td"
|
||||
include "mlir/IR/OpBase.td"
|
||||
include "mlir/IR/RegionKindInterface.td"
|
||||
include "mlir/IR/SymbolInterfaces.td"
|
||||
|
@ -72,4 +73,25 @@ def InstanceOp : MooreOp<"instance", [
|
|||
}];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declarations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def VariableOp : MooreOp<"variable", [
|
||||
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
|
||||
OptionalTypesMatchWith<"initial value and variable types match",
|
||||
"result", "initial", "$_self">,
|
||||
]> {
|
||||
let summary = "A variable declaration";
|
||||
let description = [{
|
||||
See IEEE 1800-2017 § 6.8 "Variable declarations".
|
||||
}];
|
||||
let arguments = (ins StrAttr:$name, Optional<UnpackedType>:$initial);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
`` custom<ImplicitSSAName>($name) ($initial^)? attr-dict
|
||||
`:` type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
#endif // CIRCT_DIALECT_MOORE_MOOREOPS
|
||||
|
|
|
@ -31,6 +31,7 @@ endif ()
|
|||
add_circt_translation_library(CIRCTImportVerilog
|
||||
ImportVerilog.cpp
|
||||
Structure.cpp
|
||||
Types.cpp
|
||||
|
||||
DEPENDS
|
||||
slang_slang
|
||||
|
|
|
@ -41,6 +41,13 @@ struct Context {
|
|||
/// Convert a slang `SourceLocation` into an MLIR `Location`.
|
||||
Location convertLocation(slang::SourceLocation loc);
|
||||
|
||||
/// Convert a slang type into an MLIR type. Returns null on failure. Uses the
|
||||
/// provided location for error reporting, or tries to guess one from the
|
||||
/// given type. Types tend to have unreliable location information, so it's
|
||||
/// generally a good idea to pass in a location.
|
||||
Type convertType(const slang::ast::Type &type, LocationAttr loc = {});
|
||||
Type convertType(const slang::ast::DeclaredType &type);
|
||||
|
||||
/// Convert hierarchy and structure AST nodes to MLIR ops.
|
||||
LogicalResult convertCompilation(slang::ast::Compilation &compilation);
|
||||
moore::SVModuleOp
|
||||
|
|
|
@ -25,11 +25,21 @@ struct MemberVisitor {
|
|||
MemberVisitor(Context &context, Location loc)
|
||||
: context(context), loc(loc), builder(context.builder) {}
|
||||
|
||||
/// Skip semicolons.
|
||||
// Skip empty members (stray semicolons).
|
||||
LogicalResult visit(const slang::ast::EmptyMemberSymbol &) {
|
||||
return success();
|
||||
}
|
||||
|
||||
// Skip members that are implicitly imported from some other scope for the
|
||||
// sake of name resolution, such as enum variant names.
|
||||
LogicalResult visit(const slang::ast::TransparentMemberSymbol &) {
|
||||
return success();
|
||||
}
|
||||
|
||||
// Skip typedefs.
|
||||
LogicalResult visit(const slang::ast::TypeAliasType &) { return success(); }
|
||||
|
||||
// Handle instances.
|
||||
LogicalResult visit(const slang::ast::InstanceSymbol &instNode) {
|
||||
auto targetModule = context.convertModuleHeader(&instNode.body);
|
||||
if (!targetModule)
|
||||
|
@ -42,6 +52,23 @@ struct MemberVisitor {
|
|||
return success();
|
||||
}
|
||||
|
||||
// Handle variables.
|
||||
LogicalResult visit(const slang::ast::VariableSymbol &varNode) {
|
||||
auto type = context.convertType(*varNode.getDeclaredType());
|
||||
if (!type)
|
||||
return failure();
|
||||
|
||||
Value initial;
|
||||
if (const auto *initNode = varNode.getInitializer()) {
|
||||
return mlir::emitError(loc,
|
||||
"variable initializer expressions not supported");
|
||||
}
|
||||
|
||||
builder.create<moore::VariableOp>(
|
||||
loc, type, builder.getStringAttr(varNode.name), initial);
|
||||
return success();
|
||||
}
|
||||
|
||||
/// Emit an error for all other members.
|
||||
template <typename T>
|
||||
LogicalResult visit(T &&node) {
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
//===- Types.cpp - Slang type conversion ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ImportVerilogInternals.h"
|
||||
#include "slang/ast/ASTVisitor.h"
|
||||
#include "slang/ast/Symbol.h"
|
||||
#include "slang/ast/symbols/CompilationUnitSymbols.h"
|
||||
#include "slang/ast/symbols/InstanceSymbols.h"
|
||||
#include "slang/ast/symbols/VariableSymbols.h"
|
||||
#include "slang/ast/types/AllTypes.h"
|
||||
#include "slang/ast/types/Type.h"
|
||||
#include "slang/syntax/SyntaxVisitor.h"
|
||||
|
||||
using namespace circt;
|
||||
using namespace ImportVerilog;
|
||||
|
||||
namespace {
|
||||
struct TypeVisitor {
|
||||
Context &context;
|
||||
Location loc;
|
||||
TypeVisitor(Context &context, Location loc) : context(context), loc(loc) {}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
std::optional<moore::Sign> sign =
|
||||
type.isSigned ? moore::Sign::Signed : moore::Sign::Unsigned;
|
||||
if (sign == moore::IntType::getDefaultSign(kind))
|
||||
sign = {};
|
||||
|
||||
return moore::IntType::get(context.getContext(), kind, sign);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::FloatingType &type) {
|
||||
moore::RealType::Kind kind;
|
||||
switch (type.floatKind) {
|
||||
case slang::ast::FloatingType::Real:
|
||||
kind = moore::RealType::Real;
|
||||
break;
|
||||
case slang::ast::FloatingType::ShortReal:
|
||||
kind = moore::RealType::ShortReal;
|
||||
break;
|
||||
case slang::ast::FloatingType::RealTime:
|
||||
kind = moore::RealType::RealTime;
|
||||
break;
|
||||
}
|
||||
|
||||
return moore::RealType::get(context.getContext(), kind);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::optional<moore::Sign> sign =
|
||||
type.isSigned ? moore::Sign::Signed : moore::Sign::Unsigned;
|
||||
if (sign == moore::IntType::getDefaultSign(kind))
|
||||
sign = {};
|
||||
|
||||
return moore::IntType::get(context.getContext(), kind, sign);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::PackedArrayType &type) {
|
||||
auto innerType = type.elementType.visit(*this);
|
||||
if (!innerType)
|
||||
return {};
|
||||
// The Slang frontend guarantees the inner type to be packed.
|
||||
auto packedInnerType = cast<moore::PackedType>(innerType);
|
||||
return moore::PackedRangeDim::get(
|
||||
packedInnerType, moore::Range(type.range.left, type.range.right));
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::QueueType &type) {
|
||||
auto innerType = type.elementType.visit(*this);
|
||||
if (!innerType)
|
||||
return {};
|
||||
return moore::UnpackedQueueDim::get(cast<moore::UnpackedType>(innerType),
|
||||
type.maxBound);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::AssociativeArrayType &type) {
|
||||
auto innerType = type.elementType.visit(*this);
|
||||
if (!innerType)
|
||||
return {};
|
||||
auto indexType = type.indexType->visit(*this);
|
||||
if (!indexType)
|
||||
return {};
|
||||
return moore::UnpackedAssocDim::get(cast<moore::UnpackedType>(innerType),
|
||||
cast<moore::UnpackedType>(indexType));
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::FixedSizeUnpackedArrayType &type) {
|
||||
auto innerType = type.elementType.visit(*this);
|
||||
if (!innerType)
|
||||
return {};
|
||||
return moore::UnpackedRangeDim::get(
|
||||
cast<moore::UnpackedType>(innerType),
|
||||
moore::Range(type.range.left, type.range.right));
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::DynamicArrayType &type) {
|
||||
auto innerType = type.elementType.visit(*this);
|
||||
if (!innerType)
|
||||
return {};
|
||||
return moore::UnpackedUnsizedDim::get(cast<moore::UnpackedType>(innerType));
|
||||
}
|
||||
|
||||
// Handle type defs.
|
||||
Type visit(const slang::ast::TypeAliasType &type) {
|
||||
auto innerType = type.targetType.getType().visit(*this);
|
||||
if (!innerType)
|
||||
return {};
|
||||
auto loc = context.convertLocation(type.location);
|
||||
if (auto packedInnerType = dyn_cast<moore::PackedType>(innerType))
|
||||
return moore::PackedNamedType::get(packedInnerType, type.name, loc);
|
||||
return moore::UnpackedNamedType::get(cast<moore::UnpackedType>(innerType),
|
||||
type.name, loc);
|
||||
}
|
||||
|
||||
// Handle enums.
|
||||
Type visit(const slang::ast::EnumType &type) {
|
||||
auto baseType = type.baseType.visit(*this);
|
||||
if (!baseType)
|
||||
return {};
|
||||
return moore::EnumType::get(StringAttr{}, loc,
|
||||
cast<moore::PackedType>(baseType));
|
||||
}
|
||||
|
||||
// Collect the members in a struct or union.
|
||||
LogicalResult collectMembers(const slang::ast::Scope &structType,
|
||||
SmallVectorImpl<moore::StructMember> &members,
|
||||
bool enforcePacked) {
|
||||
for (auto &field : structType.membersOfType<slang::ast::FieldSymbol>()) {
|
||||
auto loc = context.convertLocation(field.location);
|
||||
auto name = StringAttr::get(context.getContext(), field.name);
|
||||
auto innerType = context.convertType(*field.getDeclaredType());
|
||||
if (!innerType)
|
||||
return failure();
|
||||
// The Slang frontend guarantees the inner type to be packed if the struct
|
||||
// is packed.
|
||||
assert(!enforcePacked || isa<moore::PackedType>(innerType));
|
||||
members.push_back({name, loc, cast<moore::UnpackedType>(innerType)});
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle packed and unpacked structs.
|
||||
Type visit(const slang::ast::PackedStructType &type) {
|
||||
auto loc = context.convertLocation(type.location);
|
||||
SmallVector<moore::StructMember> members;
|
||||
if (failed(collectMembers(type, members, true)))
|
||||
return {};
|
||||
return moore::PackedStructType::get(moore::StructKind::Struct, members,
|
||||
StringAttr{}, loc);
|
||||
}
|
||||
|
||||
Type visit(const slang::ast::UnpackedStructType &type) {
|
||||
auto loc = context.convertLocation(type.location);
|
||||
SmallVector<moore::StructMember> members;
|
||||
if (failed(collectMembers(type, members, false)))
|
||||
return {};
|
||||
return moore::UnpackedStructType::get(moore::StructKind::Struct, members,
|
||||
StringAttr{}, loc);
|
||||
}
|
||||
|
||||
/// Emit an error for all other types.
|
||||
template <typename T>
|
||||
Type visit(T &&node) {
|
||||
auto d = mlir::emitError(loc, "unsupported type: ")
|
||||
<< slang::ast::toString(node.kind);
|
||||
d.attachNote() << node.template as<slang::ast::Type>().toString();
|
||||
return {};
|
||||
}
|
||||
// NOLINTEND(misc-no-recursion)
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// NOLINTBEGIN(misc-no-recursion)
|
||||
Type Context::convertType(const slang::ast::Type &type, LocationAttr loc) {
|
||||
if (!loc)
|
||||
loc = convertLocation(type.location);
|
||||
return type.visit(TypeVisitor(*this, loc));
|
||||
}
|
||||
|
||||
Type Context::convertType(const slang::ast::DeclaredType &type) {
|
||||
LocationAttr loc;
|
||||
if (auto *ts = type.getTypeSyntax())
|
||||
loc = convertLocation(ts->sourceRange().start());
|
||||
return convertType(type.getType(), loc);
|
||||
}
|
||||
// NOLINTEND(misc-no-recursion)
|
|
@ -15,6 +15,7 @@ add_circt_dialect_library(CIRCTMoore
|
|||
Support
|
||||
|
||||
LINK_LIBS PUBLIC
|
||||
CIRCTSupport
|
||||
MLIRIR
|
||||
MLIRInferTypeOpInterface
|
||||
)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "circt/Dialect/Moore/MooreOps.h"
|
||||
#include "circt/Support/CustomDirectiveImpl.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
|
||||
using namespace circt;
|
||||
|
@ -36,6 +37,14 @@ LogicalResult InstanceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
|
|||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// VariableOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void VariableOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
||||
setNameFn(getResult(), getName());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConcatOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -36,3 +36,9 @@ endmodule
|
|||
module Parent;
|
||||
Child child();
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: moore.module @Foo
|
||||
module Foo;
|
||||
// CHECK: %myVar = moore.variable
|
||||
var myVar;
|
||||
endmodule
|
||||
|
|
|
@ -50,3 +50,10 @@ endpackage
|
|||
|
||||
module Bar;
|
||||
endmodule
|
||||
|
||||
// -----
|
||||
|
||||
module Foo;
|
||||
// expected-error @below {{variable initializer expressions not supported}}
|
||||
int a = 0;
|
||||
endmodule
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// RUN: circt-translate --import-verilog --verify-diagnostics --split-input-file %s
|
||||
// REQUIRES: slang
|
||||
|
||||
// Internal issue in Slang v3 about jump depending on uninitialised value.
|
||||
// UNSUPPORTED: valgrind
|
||||
|
||||
module Foo;
|
||||
// expected-error @below {{unsupported type}}
|
||||
// expected-note @below {{}}
|
||||
union { bit a; logic b; } x;
|
||||
endmodule
|
|
@ -0,0 +1,173 @@
|
|||
// RUN: circt-translate --import-verilog %s | FileCheck %s
|
||||
// REQUIRES: slang
|
||||
|
||||
// Internal issue in Slang v3 about jump depending on uninitialised value.
|
||||
// UNSUPPORTED: valgrind
|
||||
|
||||
// CHECK-LABEL: moore.module @Enums
|
||||
module Enums;
|
||||
typedef enum shortint { MAGIC } myEnum;
|
||||
|
||||
// CHECK-NEXT: %e0 = moore.variable : !moore.enum<int, loc(
|
||||
// CHECK-NEXT: %e1 = moore.variable : !moore.enum<byte, loc(
|
||||
// CHECK-NEXT: %e2 = moore.variable : !moore.packed<named<"myEnum", enum<shortint, loc(
|
||||
enum { FOO, BAR } e0;
|
||||
enum byte { HELLO = 0, WORLD = 1 } e1;
|
||||
myEnum e2;
|
||||
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
|
||||
logic d0;
|
||||
bit d1;
|
||||
reg d2;
|
||||
int d3;
|
||||
shortint d4;
|
||||
longint d5;
|
||||
integer d6;
|
||||
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<unsigned>
|
||||
// CHECK-NEXT: %u4 = moore.variable : !moore.shortint<unsigned>
|
||||
// CHECK-NEXT: %u5 = moore.variable : !moore.longint<unsigned>
|
||||
// CHECK-NEXT: %u6 = moore.variable : !moore.integer<unsigned>
|
||||
// CHECK-NEXT: %u7 = moore.variable : !moore.byte<unsigned>
|
||||
// CHECK-NEXT: %u8 = moore.variable : !moore.time
|
||||
logic unsigned u0;
|
||||
bit unsigned u1;
|
||||
reg unsigned u2;
|
||||
int unsigned u3;
|
||||
shortint unsigned u4;
|
||||
longint unsigned u5;
|
||||
integer unsigned u6;
|
||||
byte unsigned u7;
|
||||
time unsigned u8;
|
||||
|
||||
// CHECK-NEXT: %s0 = moore.variable : !moore.logic<signed>
|
||||
// CHECK-NEXT: %s1 = moore.variable : !moore.bit<signed>
|
||||
// CHECK-NEXT: %s2 = moore.variable : !moore.reg<signed>
|
||||
// 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<signed>
|
||||
logic signed s0;
|
||||
bit signed s1;
|
||||
reg signed s2;
|
||||
int signed s3;
|
||||
shortint signed s4;
|
||||
longint signed s5;
|
||||
integer signed s6;
|
||||
byte signed s7;
|
||||
time signed s8;
|
||||
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>>
|
||||
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>>
|
||||
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>>>
|
||||
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>>
|
||||
logic [2:0] d0;
|
||||
logic [0:2] d1;
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: moore.module @RealType
|
||||
module RealType;
|
||||
// CHECK-NEXT: %d0 = moore.variable : !moore.real
|
||||
// CHECK-NEXT: %d1 = moore.variable : !moore.realtime
|
||||
// CHECK-NEXT: %d2 = moore.variable : !moore.shortreal
|
||||
real d0;
|
||||
realtime d1;
|
||||
shortreal d2;
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: moore.module @Structs
|
||||
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 loc({{.+}}), bar: logic loc({{.+}})}, loc({{.+}})>>
|
||||
// CHECK-NEXT: %s1 = moore.variable : !moore.unpacked<struct<{many: assoc<bit, int> loc({{.+}})}, loc({{.+}})>>
|
||||
// CHECK-NEXT: %s2 = moore.variable : !moore.packed<named<"myStructA", struct<{a: byte loc({{.+}}), b: int loc({{.+}})}, loc({{.+}})>, loc({{.+}})>>
|
||||
// CHECK-NEXT: %s3 = moore.variable : !moore.unpacked<named<"myStructB", struct<{x: byte loc({{.+}}), y: int loc({{.+}})}, loc({{.+}})>, loc({{.+}})>>
|
||||
struct packed { bit foo; logic bar; } s0;
|
||||
struct { bit many[int]; } s1;
|
||||
myStructA s2;
|
||||
myStructB s3;
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: moore.module @Typedefs
|
||||
module Typedefs;
|
||||
typedef logic [2:0] myType1;
|
||||
typedef logic myType2 [2:0];
|
||||
|
||||
// CHECK-NEXT: %v0 = moore.variable : !moore.packed<named<"myType1", range<logic, 2:0>, loc(
|
||||
// CHECK-NEXT: %v1 = moore.variable : !moore.unpacked<named<"myType2", range<logic, 2:0>, loc(
|
||||
myType1 v0;
|
||||
myType2 v1;
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: moore.module @UnpackedAssocDim
|
||||
module UnpackedAssocDim;
|
||||
// CHECK-NEXT: %d0 = moore.variable : !moore.unpacked<assoc<logic, int>>
|
||||
// CEECK-NEXT: %d1 = moore.variable : !moore.unpacked<assoc<logic, logic>>
|
||||
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>>
|
||||
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>>
|
||||
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>>
|
||||
logic d0 [];
|
||||
endmodule
|
|
@ -4,6 +4,10 @@
|
|||
moore.module @Foo {
|
||||
// CHECK: moore.instance "foo" @Foo
|
||||
moore.instance "foo" @Foo
|
||||
// CHECK: %myVar = moore.variable : !moore.bit
|
||||
%myVar = moore.variable : !moore.bit
|
||||
// CHECK: [[TMP:%.+]] = moore.variable name "myVar" : !moore.bit
|
||||
moore.variable name "myVar" : !moore.bit
|
||||
}
|
||||
|
||||
// CHECK-LABEL: moore.module @Bar
|
||||
|
|
Loading…
Reference in New Issue