mirror of https://github.com/llvm/circt.git
[Moore] Drop named_constant op in favor of dbg.variable (#7624)
Remove the `NamedConstantOp` and replace its uses with `VariableOp` from the debug dialect. The op was originally added to track the value of constant parameters, localparams, and specparams in the IR. In ImportVerilog, such parameters would generate a corresponding `named_constant` op and all references to the parameter by name would be replaced with the `named_constant`'s result. This doesn't really work well for parameters defined outside a module, such as in packages or at the root of the Verilog source file. (Modules are isolated from above, preventing the use of `named_constant`s from outside the module.) Therefore expressions would generally fall back to materializing constants directly where they were used. Since the named constant ops are only there to track a constant value in the IR for the user's debugging convenience, using the debug dialect directly feels a lot more appropriate.
This commit is contained in:
parent
0ecbd6f3b8
commit
687f7fb38f
|
@ -459,7 +459,7 @@ def DetectEventOp : MooreOp<"detect_event", [
|
|||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expressions
|
||||
// Constants
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def ConstantOp : MooreOp<"constant", [Pure, ConstantLike]> {
|
||||
|
@ -476,37 +476,6 @@ def ConstantOp : MooreOp<"constant", [Pure, ConstantLike]> {
|
|||
];
|
||||
}
|
||||
|
||||
def Parameter : I32EnumAttrCase<"Parameter", 0, "parameter">;
|
||||
def LocalParameter : I32EnumAttrCase<"LocalParameter", 1, "localparam">;
|
||||
def SpecParameter : I32EnumAttrCase<"SpecParameter", 2, "specparam">;
|
||||
|
||||
def NamedConstAttr : I32EnumAttr<"NamedConst", "elaboration-time constants",
|
||||
[Parameter, LocalParameter, SpecParameter]>{
|
||||
let cppNamespace = "circt::moore";
|
||||
}
|
||||
|
||||
def NamedConstantOp : MooreOp<"named_constant", [
|
||||
SameOperandsAndResultType,
|
||||
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
|
||||
]>{
|
||||
let summary = "An elaboration time constant expression";
|
||||
let description = [{
|
||||
Constants are named data objects that never change. SystemVerilog provides
|
||||
three elaboration-time constants: parameter, localparam, and specparam.
|
||||
|
||||
See IEEE 1800-2017 § 6.20 "Constants".
|
||||
}];
|
||||
let arguments = (ins StrAttr:$name,
|
||||
NamedConstAttr:$kind,
|
||||
IntType:$value);
|
||||
let results = (outs IntType:$result);
|
||||
let assemblyFormat = [{
|
||||
$kind
|
||||
``custom<ImplicitSSAName>($name)
|
||||
$value `:` type($result) attr-dict
|
||||
}];
|
||||
}
|
||||
|
||||
def StringConstantOp : MooreOp<"string_constant", [Pure]> {
|
||||
let summary = "Produce a constant string value";
|
||||
let description = [{
|
||||
|
@ -522,6 +491,10 @@ def StringConstantOp : MooreOp<"string_constant", [Pure]> {
|
|||
let assemblyFormat = "$value attr-dict `:` type($result)";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expressions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def ConversionOp : MooreOp<"conversion", [Pure]> {
|
||||
let summary = "A type conversion";
|
||||
let description = [{
|
||||
|
|
|
@ -40,6 +40,7 @@ add_circt_translation_library(CIRCTImportVerilog
|
|||
slang_slang
|
||||
|
||||
LINK_LIBS PUBLIC
|
||||
CIRCTDebug
|
||||
CIRCTHW
|
||||
CIRCTMoore
|
||||
MLIRFuncDialect
|
||||
|
|
|
@ -264,8 +264,9 @@ LogicalResult ImportDriver::importVerilog(ModuleOp module) {
|
|||
return success();
|
||||
|
||||
// Traverse the parsed Verilog AST and map it to the equivalent CIRCT ops.
|
||||
mlirContext->loadDialect<moore::MooreDialect, hw::HWDialect,
|
||||
cf::ControlFlowDialect, func::FuncDialect>();
|
||||
mlirContext
|
||||
->loadDialect<moore::MooreDialect, hw::HWDialect, cf::ControlFlowDialect,
|
||||
func::FuncDialect, debug::DebugDialect>();
|
||||
auto conversionTimer = ts.nest("Verilog to dialect mapping");
|
||||
Context context(options, *compilation, module, driver.sourceManager,
|
||||
bufferFilePaths);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define CONVERSION_IMPORTVERILOG_IMPORTVERILOGINTERNALS_H
|
||||
|
||||
#include "circt/Conversion/ImportVerilog.h"
|
||||
#include "circt/Dialect/Debug/DebugOps.h"
|
||||
#include "circt/Dialect/HW/HWOps.h"
|
||||
#include "circt/Dialect/Moore/MooreOps.h"
|
||||
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
|
||||
|
|
|
@ -12,6 +12,21 @@
|
|||
using namespace circt;
|
||||
using namespace ImportVerilog;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utilities
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void guessNamespacePrefix(const slang::ast::Symbol &symbol,
|
||||
SmallString<64> &prefix) {
|
||||
if (symbol.kind != slang::ast::SymbolKind::Package)
|
||||
return;
|
||||
guessNamespacePrefix(symbol.getParentScope()->asSymbol(), prefix);
|
||||
if (!symbol.name.empty()) {
|
||||
prefix += symbol.name;
|
||||
prefix += "::";
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Base Visitor
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -20,6 +35,13 @@ namespace {
|
|||
/// Base visitor which ignores AST nodes that are handled by Slang's name
|
||||
/// resolution and type checking.
|
||||
struct BaseVisitor {
|
||||
Context &context;
|
||||
Location loc;
|
||||
OpBuilder &builder;
|
||||
|
||||
BaseVisitor(Context &context, Location loc)
|
||||
: context(context), loc(loc), builder(context.builder) {}
|
||||
|
||||
// Skip semicolons.
|
||||
LogicalResult visit(const slang::ast::EmptyMemberSymbol &) {
|
||||
return success();
|
||||
|
@ -41,6 +63,46 @@ struct BaseVisitor {
|
|||
LogicalResult visit(const slang::ast::WildcardImportSymbol &) {
|
||||
return success();
|
||||
}
|
||||
|
||||
// Skip type parameters. The Slang AST is already monomorphized.
|
||||
LogicalResult visit(const slang::ast::TypeParameterSymbol &) {
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle parameters.
|
||||
LogicalResult visit(const slang::ast::ParameterSymbol ¶m) {
|
||||
visitParameter(param);
|
||||
return success();
|
||||
}
|
||||
|
||||
LogicalResult visit(const slang::ast::SpecparamSymbol ¶m) {
|
||||
visitParameter(param);
|
||||
return success();
|
||||
}
|
||||
|
||||
template <class Node>
|
||||
void visitParameter(const Node ¶m) {
|
||||
// If debug info is enabled, try to materialize the parameter's constant
|
||||
// value on a best-effort basis and create a `dbg.variable` to track the
|
||||
// value.
|
||||
if (!context.options.debugInfo)
|
||||
return;
|
||||
auto value =
|
||||
context.materializeConstant(param.getValue(), param.getType(), loc);
|
||||
if (!value)
|
||||
return;
|
||||
if (builder.getInsertionBlock()->getParentOp() == context.intoModuleOp)
|
||||
context.orderedRootOps.insert({param.location, value.getDefiningOp()});
|
||||
|
||||
// Prefix the parameter name with the surrounding namespace to create
|
||||
// somewhat sane names in the IR.
|
||||
SmallString<64> paramName;
|
||||
guessNamespacePrefix(param.getParentScope()->asSymbol(), paramName);
|
||||
paramName += param.name;
|
||||
|
||||
builder.create<debug::VariableOp>(loc, builder.getStringAttr(paramName),
|
||||
value, Value{});
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
@ -50,15 +112,9 @@ struct BaseVisitor {
|
|||
|
||||
namespace {
|
||||
struct RootVisitor : public BaseVisitor {
|
||||
using BaseVisitor::BaseVisitor;
|
||||
using BaseVisitor::visit;
|
||||
|
||||
Context &context;
|
||||
Location loc;
|
||||
OpBuilder &builder;
|
||||
|
||||
RootVisitor(Context &context, Location loc)
|
||||
: context(context), loc(loc), builder(context.builder) {}
|
||||
|
||||
// Handle packages.
|
||||
LogicalResult visit(const slang::ast::PackageSymbol &package) {
|
||||
return context.convertPackage(package);
|
||||
|
@ -85,22 +141,9 @@ struct RootVisitor : public BaseVisitor {
|
|||
|
||||
namespace {
|
||||
struct PackageVisitor : public BaseVisitor {
|
||||
using BaseVisitor::BaseVisitor;
|
||||
using BaseVisitor::visit;
|
||||
|
||||
Context &context;
|
||||
Location loc;
|
||||
OpBuilder &builder;
|
||||
|
||||
PackageVisitor(Context &context, Location loc)
|
||||
: context(context), loc(loc), builder(context.builder) {}
|
||||
|
||||
// Ignore parameters. These are materialized on-the-fly as `ConstantOp`s.
|
||||
LogicalResult visit(const slang::ast::ParameterSymbol &) { return success(); }
|
||||
LogicalResult visit(const slang::ast::SpecparamSymbol &) { return success(); }
|
||||
LogicalResult visit(const slang::ast::TypeParameterSymbol &) {
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle functions and tasks.
|
||||
LogicalResult visit(const slang::ast::SubroutineSymbol &subroutine) {
|
||||
return context.convertFunction(subroutine);
|
||||
|
@ -177,15 +220,9 @@ static moore::NetKind convertNetKind(slang::ast::NetType::NetKind kind) {
|
|||
|
||||
namespace {
|
||||
struct ModuleVisitor : public BaseVisitor {
|
||||
using BaseVisitor::BaseVisitor;
|
||||
using BaseVisitor::visit;
|
||||
|
||||
Context &context;
|
||||
Location loc;
|
||||
OpBuilder &builder;
|
||||
|
||||
ModuleVisitor(Context &context, Location loc)
|
||||
: context(context), loc(loc), builder(context.builder) {}
|
||||
|
||||
// Skip ports which are already handled by the module itself.
|
||||
LogicalResult visit(const slang::ast::PortSymbol &) { return success(); }
|
||||
LogicalResult visit(const slang::ast::MultiPortSymbol &) { return success(); }
|
||||
|
@ -453,45 +490,6 @@ struct ModuleVisitor : public BaseVisitor {
|
|||
return success();
|
||||
}
|
||||
|
||||
// Handle parameters.
|
||||
LogicalResult visit(const slang::ast::ParameterSymbol ¶mNode) {
|
||||
auto type = cast<moore::IntType>(context.convertType(paramNode.getType()));
|
||||
if (!type)
|
||||
return failure();
|
||||
|
||||
auto valueInt = paramNode.getValue().integer().as<uint64_t>().value();
|
||||
Value value = builder.create<moore::ConstantOp>(loc, type, valueInt);
|
||||
|
||||
auto namedConstantOp = builder.create<moore::NamedConstantOp>(
|
||||
loc, type, builder.getStringAttr(paramNode.name),
|
||||
paramNode.isLocalParam()
|
||||
? moore::NamedConstAttr::get(context.getContext(),
|
||||
moore::NamedConst::LocalParameter)
|
||||
: moore::NamedConstAttr::get(context.getContext(),
|
||||
moore::NamedConst::Parameter),
|
||||
value);
|
||||
context.valueSymbols.insert(¶mNode, namedConstantOp);
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle specparam.
|
||||
LogicalResult visit(const slang::ast::SpecparamSymbol &spNode) {
|
||||
auto type = cast<moore::IntType>(context.convertType(spNode.getType()));
|
||||
if (!type)
|
||||
return failure();
|
||||
|
||||
auto valueInt = spNode.getValue().integer().as<uint64_t>().value();
|
||||
Value value = builder.create<moore::ConstantOp>(loc, type, valueInt);
|
||||
|
||||
auto namedConstantOp = builder.create<moore::NamedConstantOp>(
|
||||
loc, type, builder.getStringAttr(spNode.name),
|
||||
moore::NamedConstAttr::get(context.getContext(),
|
||||
moore::NamedConst::SpecParameter),
|
||||
value);
|
||||
context.valueSymbols.insert(&spNode, namedConstantOp);
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle generate block.
|
||||
LogicalResult visit(const slang::ast::GenerateBlockSymbol &genNode) {
|
||||
if (!genNode.isUninstantiated) {
|
||||
|
@ -794,17 +792,6 @@ Context::convertPackage(const slang::ast::PackageSymbol &package) {
|
|||
return success();
|
||||
}
|
||||
|
||||
static void guessNamespacePrefix(const slang::ast::Symbol &symbol,
|
||||
SmallString<64> &prefix) {
|
||||
if (symbol.kind == slang::ast::SymbolKind::Root)
|
||||
return;
|
||||
guessNamespacePrefix(symbol.getParentScope()->asSymbol(), prefix);
|
||||
if (!symbol.name.empty()) {
|
||||
prefix += symbol.name;
|
||||
prefix += "::";
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a function and its arguments to a function declaration in the IR.
|
||||
/// This does not convert the function body.
|
||||
FunctionLowering *
|
||||
|
|
|
@ -515,35 +515,6 @@ struct ConstantOpConv : public OpConversionPattern<ConstantOp> {
|
|||
}
|
||||
};
|
||||
|
||||
struct NamedConstantOpConv : public OpConversionPattern<NamedConstantOp> {
|
||||
using OpConversionPattern::OpConversionPattern;
|
||||
|
||||
LogicalResult
|
||||
matchAndRewrite(NamedConstantOp op, OpAdaptor adaptor,
|
||||
ConversionPatternRewriter &rewriter) const override {
|
||||
|
||||
Type resultType = typeConverter->convertType(op.getResult().getType());
|
||||
SmallString<32> symStr;
|
||||
switch (op.getKind()) {
|
||||
case NamedConst::Parameter:
|
||||
symStr = "parameter";
|
||||
break;
|
||||
case NamedConst::LocalParameter:
|
||||
symStr = "localparameter";
|
||||
break;
|
||||
case NamedConst::SpecParameter:
|
||||
symStr = "specparameter";
|
||||
break;
|
||||
}
|
||||
auto symAttr =
|
||||
rewriter.getStringAttr(symStr + Twine("_") + adaptor.getName());
|
||||
rewriter.replaceOpWithNewOp<hw::WireOp>(op, resultType, adaptor.getValue(),
|
||||
op.getNameAttr(),
|
||||
hw::InnerSymAttr::get(symAttr));
|
||||
return success();
|
||||
}
|
||||
};
|
||||
|
||||
struct ConcatOpConversion : public OpConversionPattern<ConcatOp> {
|
||||
using OpConversionPattern::OpConversionPattern;
|
||||
LogicalResult
|
||||
|
@ -1375,7 +1346,7 @@ static void populateOpConversion(RewritePatternSet &patterns,
|
|||
// Patterns of miscellaneous operations.
|
||||
ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
|
||||
ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
|
||||
ConversionOpConversion, ReadOpConversion, NamedConstantOpConv,
|
||||
ConversionOpConversion, ReadOpConversion,
|
||||
StructExtractOpConversion, StructExtractRefOpConversion,
|
||||
ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion,
|
||||
YieldOpConversion, OutputOpConversion,
|
||||
|
|
|
@ -633,14 +633,6 @@ OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
|
|||
return getValueAttr();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NamedConstantOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void NamedConstantOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
||||
setNameFn(getResult(), getName());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConcatOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: circt-translate --import-verilog %s | FileCheck %s
|
||||
// RUN: circt-verilog --parse-only -g %s | FileCheck %s
|
||||
// RUN: circt-verilog --ir-moore %s
|
||||
// REQUIRES: slang
|
||||
|
||||
|
@ -132,30 +132,6 @@ module Basic;
|
|||
bit [0:0] b1;
|
||||
bit b2 = b1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: %p1 = moore.named_constant parameter [[TMP]] : l32
|
||||
parameter p1 = 1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: %p2 = moore.named_constant parameter [[TMP]] : l32
|
||||
parameter p2 = p1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : l32
|
||||
// CHECK: %lp1 = moore.named_constant localparam [[TMP]] : l32
|
||||
localparam lp1 = 2;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : l32
|
||||
// CHECK: %lp2 = moore.named_constant localparam [[TMP]] : l32
|
||||
localparam lp2 = lp1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 3 : l32
|
||||
// CHECK: %sp1 = moore.named_constant specparam [[TMP]] : l32
|
||||
specparam sp1 = 3;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 3 : l32
|
||||
// CHECK: %sp2 = moore.named_constant specparam [[TMP]] : l32
|
||||
specparam sp2 = sp1;
|
||||
|
||||
// CHECK: moore.procedure initial {
|
||||
// CHECK: }
|
||||
initial;
|
||||
|
@ -236,11 +212,62 @@ endmodule
|
|||
// CHECK-LABEL: func.func private @dummyB(
|
||||
// CHECK-LABEL: func.func private @dummyC(
|
||||
// CHECK-LABEL: func.func private @dummyD(
|
||||
// CHECK-LABEL: func.func private @dummyE(
|
||||
// CHECK-LABEL: func.func private @dummyF(
|
||||
function void dummyA(); endfunction
|
||||
function void dummyB(); endfunction
|
||||
function void dummyC(); endfunction
|
||||
function void dummyD(int a); endfunction
|
||||
function bit dummyE(bit a); return a; endfunction
|
||||
function void dummyF(integer a); endfunction
|
||||
|
||||
// CHECK-LABEL: moore.module @Parameters(
|
||||
module Parameters;
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: dbg.variable "p1", [[TMP]] : !moore.l32
|
||||
parameter p1 = 1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: dbg.variable "p2", [[TMP]] : !moore.l32
|
||||
parameter p2 = p1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : l32
|
||||
// CHECK: dbg.variable "lp1", [[TMP]] : !moore.l32
|
||||
localparam lp1 = 2;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : l32
|
||||
// CHECK: dbg.variable "lp2", [[TMP]] : !moore.l32
|
||||
localparam lp2 = lp1;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 3 : l32
|
||||
// CHECK: dbg.variable "sp1", [[TMP]] : !moore.l32
|
||||
specparam sp1 = 3;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 3 : l32
|
||||
// CHECK: dbg.variable "sp2", [[TMP]] : !moore.l32
|
||||
specparam sp2 = sp1;
|
||||
|
||||
initial begin
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: func.call @dummyF([[TMP]])
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: func.call @dummyF([[TMP]])
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : l32
|
||||
// CHECK: func.call @dummyF([[TMP]])
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : l32
|
||||
// CHECK: func.call @dummyF([[TMP]])
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 3 : l32
|
||||
// CHECK: func.call @dummyF([[TMP]])
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 3 : l32
|
||||
// CHECK: func.call @dummyF([[TMP]])
|
||||
dummyF(p1);
|
||||
dummyF(p2);
|
||||
dummyF(lp1);
|
||||
dummyF(lp2);
|
||||
dummyF(sp1);
|
||||
dummyF(sp2);
|
||||
end
|
||||
endmodule
|
||||
|
||||
// CHECK-LABEL: func.func private @ConditionalStatements(
|
||||
// CHECK-SAME: %arg0: !moore.i1
|
||||
|
@ -1529,27 +1556,28 @@ endmodule
|
|||
// CHECK-LABEL: moore.module @GenerateConstructs()
|
||||
module GenerateConstructs;
|
||||
genvar i;
|
||||
parameter p=2;
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2
|
||||
// CHECK: dbg.variable "p", [[TMP]]
|
||||
parameter p = 2;
|
||||
|
||||
generate
|
||||
// CHECK: [[TMP1:%.+]] = moore.constant 0 : l32
|
||||
// CHECK: %i = moore.named_constant localparam [[TMP1]] : l32
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion %i : !moore.l32 -> !moore.i32
|
||||
// CHECK: %g1 = moore.variable [[TMP2]] : <i32>
|
||||
// CHECK: [[TMP3:%.+]] = moore.constant 1 : l32
|
||||
// CHECK: %i_0 = moore.named_constant localparam name "i" [[TMP3]] : l32
|
||||
// CHECK: [[TMP4:%.+]] = moore.conversion %i_0 : !moore.l32 -> !moore.i32
|
||||
// CHECK: %g1_1 = moore.variable name "g1" [[TMP4]] : <i32>
|
||||
for(i=0; i<2; i=i+1) begin
|
||||
int g1 = i;
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 0
|
||||
// CHECK: dbg.variable "i", [[TMP]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 0
|
||||
// CHECK: %g1 = moore.variable [[TMP]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1
|
||||
// CHECK: dbg.variable "i", [[TMP]]
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 1
|
||||
// CHECK: moore.variable name "g1" [[TMP]]
|
||||
for (i = 0; i < 2; i = i + 1) begin
|
||||
integer g1 = i;
|
||||
end
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 2 : i32
|
||||
// CHECK: %g2 = moore.variable [[TMP]] : <i32>
|
||||
if(p == 2) begin
|
||||
if (p == 2) begin
|
||||
int g2 = 2;
|
||||
end
|
||||
else begin
|
||||
end else begin
|
||||
int g2 = 3;
|
||||
end
|
||||
|
||||
|
@ -1558,10 +1586,10 @@ module GenerateConstructs;
|
|||
case (p)
|
||||
2: begin
|
||||
int g3 = 2;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
int g3 = 3;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
endgenerate
|
||||
endmodule
|
||||
|
@ -1979,3 +2007,21 @@ module ImmediateAssertiWithActionBlock;
|
|||
// CHEK: }
|
||||
assert (x) a = 1; else a = 0;
|
||||
endmodule
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 42 : i32
|
||||
// CHECK: dbg.variable "rootParam1", [[TMP]] : !moore.i32
|
||||
parameter int rootParam1 = 42;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 9001 : i32
|
||||
// CHECK: dbg.variable "rootParam2", [[TMP]] : !moore.i32
|
||||
localparam int rootParam2 = 9001;
|
||||
|
||||
package ParamPackage;
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 42 : i32
|
||||
// CHECK: dbg.variable "ParamPackage::param1", [[TMP]] : !moore.i32
|
||||
parameter int param1 = 42;
|
||||
|
||||
// CHECK: [[TMP:%.+]] = moore.constant 9001 : i32
|
||||
// CHECK: dbg.variable "ParamPackage::param2", [[TMP]] : !moore.i32
|
||||
localparam int param2 = 9001;
|
||||
endpackage
|
||||
|
|
|
@ -362,25 +362,6 @@ moore.module private @SubModule_0(in %a : !moore.l1, in %b : !moore.l1, out c :
|
|||
moore.output %0 : !moore.l1
|
||||
}
|
||||
|
||||
// CHECK-LABEL: hw.module @ParamTest() {
|
||||
moore.module @ParamTest(){
|
||||
|
||||
// CHECK-NEXT: [[Pa:%.+]] = hw.constant 1 : i32
|
||||
// CHECK-NEXT: %p1 = hw.wire [[Pa]] sym @parameter_p1 : i32
|
||||
%0 = moore.constant 1 : l32
|
||||
%p1 = moore.named_constant parameter %0 : l32
|
||||
|
||||
// CHECK-NEXT: [[LPa:%.+]] = hw.constant 2 : i32
|
||||
// CHECK-NEXT: %lp1 = hw.wire [[LPa]] sym @localparameter_lp1 : i32
|
||||
%1 = moore.constant 2 : l32
|
||||
%lp1 = moore.named_constant localparam %1 : l32
|
||||
|
||||
// CHECK-NEXT: [[SPa:%.+]] = hw.constant 3 : i32
|
||||
// CHECK-NEXT: %sp1 = hw.wire [[SPa]] sym @specparameter_sp1 : i32
|
||||
%2 = moore.constant 3 : l32
|
||||
%sp1 = moore.named_constant specparam %2 : l32
|
||||
}
|
||||
|
||||
moore.module @Variable() {
|
||||
// CHECK: [[TMP0:%.+]] = hw.constant 0 : i32
|
||||
// CHECK: %a = llhd.sig [[TMP0]] : i32
|
||||
|
|
Loading…
Reference in New Issue