Skip to content

Commit

Permalink
[ImportVerilog] Support parameter constants. (#7083)
Browse files Browse the repository at this point in the history
  • Loading branch information
angelzzzzz authored May 30, 2024
1 parent 21269d5 commit 76b65f8
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 0 deletions.
30 changes: 30 additions & 0 deletions include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,36 @@ def ConstantOp : MooreOp<"constant", [Pure]> {
];
}

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,
UnpackedType:$value);
let results = (outs UnpackedType:$result);
let assemblyFormat = [{
`` custom<ImplicitSSAName>($name) $kind $value attr-dict
`:` type($result)
}];
}

def ConversionOp : MooreOp<"conversion", [Pure]> {
let summary = "A type conversion";
let description = [{
Expand Down
49 changes: 49 additions & 0 deletions lib/Conversion/ImportVerilog/Structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,55 @@ struct MemberVisitor {
return context.convertStatement(procNode.getBody());
}

// Handle parameters.
LogicalResult visit(const slang::ast::ParameterSymbol &paramNode) {
auto type = context.convertType(*paramNode.getDeclaredType());
if (!type)
return failure();

const auto *init = paramNode.getInitializer();
// skip parameters without value.
if (!init)
return success();
Value initial = context.convertExpression(*init);
if (!initial)
return failure();

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),
initial);
context.valueSymbols.insert(&paramNode, namedConstantOp);
return success();
}

// Handle specparam.
LogicalResult visit(const slang::ast::SpecparamSymbol &spNode) {
auto type = context.convertType(*spNode.getDeclaredType());
if (!type)
return failure();

const auto *init = spNode.getInitializer();
// skip specparam without value.
if (!init)
return success();
Value initial = context.convertExpression(*init);
if (!initial)
return failure();

auto namedConstantOp = builder.create<moore::NamedConstantOp>(
loc, type, builder.getStringAttr(spNode.name),
moore::NamedConstAttr::get(context.getContext(),
moore::NamedConst::SpecParameter),
initial);
context.valueSymbols.insert(&spNode, namedConstantOp);
return success();
}

// Ignore statement block symbols. These get generated by Slang for blocks
// with variables and other declarations. For example, having an initial
// procedure with a variable declaration, such as `initial begin int x;
Expand Down
8 changes: 8 additions & 0 deletions lib/Dialect/Moore/MooreOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ void ConstantOp::build(OpBuilder &builder, OperationState &result, IntType type,
APInt(type.getWidth(), (uint64_t)value, /*isSigned=*/true));
}

//===----------------------------------------------------------------------===//
// NamedConstantOp
//===----------------------------------------------------------------------===//

void NamedConstantOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
setNameFn(getResult(), getName());
}

//===----------------------------------------------------------------------===//
// ConcatOp
//===----------------------------------------------------------------------===//
Expand Down
19 changes: 19 additions & 0 deletions test/Conversion/ImportVerilog/basic.sv
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ module Basic;
bit [0:0] b1;
bit b2 = b1;

// CHECK: [[TMP1:%.+]] = moore.constant 1 : i32
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
// CHECK: %p1 = moore.named_constant parameter [[TMP2]] : l32
parameter p1 = 1;
// CHECK: %p2 = moore.named_constant parameter %p1 : l32
parameter p2 = p1;
// CHECK: [[TMP1:%.+]] = moore.constant 2 : i32
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
// CHECK: %lp1 = moore.named_constant localparam [[TMP2]] : l32
localparam lp1 = 2;
// CHECK: %lp2 = moore.named_constant localparam %lp1 : l32
localparam lp2 = lp1;
// CHECK: [[TMP1:%.+]] = moore.constant 3 : i32
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
// CHECK: %sp1 = moore.named_constant specparam [[TMP2]] : l32
specparam sp1 = 3;
// CHECK: %sp2 = moore.named_constant specparam %sp1 : l32
specparam sp2 = sp1;

// CHECK: moore.procedure initial {
// CHECK: }
initial;
Expand Down

0 comments on commit 76b65f8

Please sign in to comment.