mirror of https://github.com/llvm/circt.git
[Moore] Introduce a new operation - netOp for net declaration (#6884)
* [Moore] Add the netOp for net declaration in SV NetOp is for variable declaration. Net Types defines different types of net connections in SV. There are twelve built-in net types defined `supply0`, `supply1`, `tri`, `triand`, `trior`, `trireg`, `tri0`, `tri1`, `uwire`, `wire`, `wand`, `wor`, and three special net types: `interconnect`, `userdefined`, `unknown`. The special ones are marked as unsupported because we have no plan to support them currently. Corresponding test cases have been added to the parser/print and ImportVerilog pass tests. Add two expected failed netkind test cases - `interconnect` & `user-defined`. --------- Co-authored-by: Fabian Schuiki <fabian@schuiki.ch> Co-authored-by: Hailong Sun <hailong.sun@terapines.com>
This commit is contained in:
parent
77a0808750
commit
61a18fe046
|
@ -146,7 +146,60 @@ def VariableOp : MooreOp<"variable", [
|
|||
let arguments = (ins StrAttr:$name, Optional<UnpackedType>:$initial);
|
||||
let results = (outs Res<UnpackedType, "", [MemAlloc]>:$result);
|
||||
let assemblyFormat = [{
|
||||
`` custom<ImplicitSSAName>($name) ($initial^)? attr-dict
|
||||
custom<ImplicitSSAName>($name) ($initial^)? attr-dict
|
||||
`:` type($result)
|
||||
}];
|
||||
}
|
||||
|
||||
def NetKindAttr : I32EnumAttr<"NetKind", "Net type kind", [
|
||||
I32EnumAttrCase<"Supply0", 0, "supply0">,
|
||||
I32EnumAttrCase<"Supply1", 1, "supply1">,
|
||||
I32EnumAttrCase<"Tri", 2, "tri">,
|
||||
I32EnumAttrCase<"TriAnd", 3, "triand">,
|
||||
I32EnumAttrCase<"TriOr", 4, "trior">,
|
||||
I32EnumAttrCase<"TriReg", 5, "trireg">,
|
||||
I32EnumAttrCase<"Tri0", 6, "tri0">,
|
||||
I32EnumAttrCase<"Tri1", 7, "tri1">,
|
||||
I32EnumAttrCase<"UWire", 8, "uwire">,
|
||||
I32EnumAttrCase<"Wire", 9, "wire">,
|
||||
I32EnumAttrCase<"WAnd", 10, "wand">,
|
||||
I32EnumAttrCase<"WOr", 11, "wor">,
|
||||
I32EnumAttrCase<"Interconnect", 12, "interconnect">,
|
||||
I32EnumAttrCase<"UserDefined", 13, "userdefined">,
|
||||
I32EnumAttrCase<"Unknown", 14, "unknown">,
|
||||
]> {
|
||||
let cppNamespace = "::circt::moore";
|
||||
}
|
||||
|
||||
def NetOp : MooreOp<"net", [
|
||||
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
|
||||
OptionalTypesMatchWith<"assigned value and variable types match",
|
||||
"result", "assignment", "$_self">,
|
||||
]> {
|
||||
let summary = "A net declaration";
|
||||
let description = [{
|
||||
The `moore.net' operation is a net declaration. Net types defines different types
|
||||
of net connection in SV. There are twelve built-in net types defined in the official
|
||||
standard construct of the operation:
|
||||
`supply0`, `supply1`, `tri`, `triand`, `trior`, `trireg`, `tri0`, `tri1`, `uwire`,
|
||||
`wire`, `wand`, `wor`.
|
||||
Optional assignment argument allows net operation to be initialized with specific
|
||||
values as soon as it is created. Only one net declaration assignment can be made for
|
||||
a particular net. See IEEE 1800-2017 § 10.3.1 "The net declaration assignment" for
|
||||
the differences between net declaration assignments and continuous assign statements.
|
||||
It has some features that are not supported: declaring an interconnect net and using
|
||||
user-defined types in the net operation.
|
||||
|
||||
See IEEE 1800-2017 § 6.7 "Net declarations".
|
||||
}];
|
||||
let arguments = (ins
|
||||
StrAttr:$name,
|
||||
NetKindAttr:$kind,
|
||||
Optional<UnpackedType>:$assignment
|
||||
);
|
||||
let results = (outs UnpackedType:$result);
|
||||
let assemblyFormat = [{
|
||||
``custom<ImplicitSSAName>($name) $kind ($assignment^)? attr-dict
|
||||
`:` type($result)
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -35,6 +35,42 @@ convertProcedureKind(slang::ast::ProceduralBlockKind kind) {
|
|||
llvm_unreachable("all procedure kinds handled");
|
||||
}
|
||||
|
||||
static moore::NetKind convertNetKind(slang::ast::NetType::NetKind kind) {
|
||||
switch (kind) {
|
||||
case slang::ast::NetType::Supply0:
|
||||
return moore::NetKind::Supply0;
|
||||
case slang::ast::NetType::Supply1:
|
||||
return moore::NetKind::Supply1;
|
||||
case slang::ast::NetType::Tri:
|
||||
return moore::NetKind::Tri;
|
||||
case slang::ast::NetType::TriAnd:
|
||||
return moore::NetKind::TriAnd;
|
||||
case slang::ast::NetType::TriOr:
|
||||
return moore::NetKind::TriOr;
|
||||
case slang::ast::NetType::TriReg:
|
||||
return moore::NetKind::TriReg;
|
||||
case slang::ast::NetType::Tri0:
|
||||
return moore::NetKind::Tri0;
|
||||
case slang::ast::NetType::Tri1:
|
||||
return moore::NetKind::Tri1;
|
||||
case slang::ast::NetType::UWire:
|
||||
return moore::NetKind::UWire;
|
||||
case slang::ast::NetType::Wire:
|
||||
return moore::NetKind::Wire;
|
||||
case slang::ast::NetType::WAnd:
|
||||
return moore::NetKind::WAnd;
|
||||
case slang::ast::NetType::WOr:
|
||||
return moore::NetKind::WOr;
|
||||
case slang::ast::NetType::Interconnect:
|
||||
return moore::NetKind::Interconnect;
|
||||
case slang::ast::NetType::UserDefined:
|
||||
return moore::NetKind::UserDefined;
|
||||
case slang::ast::NetType::Unknown:
|
||||
return moore::NetKind::Unknown;
|
||||
}
|
||||
llvm_unreachable("all net kinds handled");
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct MemberVisitor {
|
||||
Context &context;
|
||||
|
@ -73,8 +109,8 @@ struct MemberVisitor {
|
|||
|
||||
// Handle variables.
|
||||
LogicalResult visit(const slang::ast::VariableSymbol &varNode) {
|
||||
auto type = context.convertType(*varNode.getDeclaredType());
|
||||
if (!type)
|
||||
auto loweredType = context.convertType(*varNode.getDeclaredType());
|
||||
if (!loweredType)
|
||||
return failure();
|
||||
|
||||
Value initial;
|
||||
|
@ -83,16 +119,44 @@ struct MemberVisitor {
|
|||
if (!initial)
|
||||
return failure();
|
||||
|
||||
if (initial.getType() != type)
|
||||
initial = builder.create<moore::ConversionOp>(loc, type, initial);
|
||||
if (initial.getType() != loweredType)
|
||||
initial =
|
||||
builder.create<moore::ConversionOp>(loc, loweredType, initial);
|
||||
}
|
||||
|
||||
auto varOp = builder.create<moore::VariableOp>(
|
||||
loc, type, builder.getStringAttr(varNode.name), initial);
|
||||
loc, loweredType, builder.getStringAttr(varNode.name), initial);
|
||||
context.valueSymbols.insert(&varNode, varOp);
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle nets.
|
||||
LogicalResult visit(const slang::ast::NetSymbol &netNode) {
|
||||
auto loweredType = context.convertType(*netNode.getDeclaredType());
|
||||
if (!loweredType)
|
||||
return failure();
|
||||
|
||||
Value assignment;
|
||||
if (netNode.getInitializer()) {
|
||||
assignment = context.convertExpression(*netNode.getInitializer());
|
||||
if (!assignment)
|
||||
return failure();
|
||||
}
|
||||
|
||||
auto netkind = convertNetKind(netNode.netType.netKind);
|
||||
if (netkind == moore::NetKind::Interconnect ||
|
||||
netkind == moore::NetKind::UserDefined ||
|
||||
netkind == moore::NetKind::Unknown)
|
||||
return mlir::emitError(loc, "unsupported net kind `")
|
||||
<< netNode.netType.name << "`";
|
||||
|
||||
auto netOp = builder.create<moore::NetOp>(
|
||||
loc, loweredType, builder.getStringAttr(netNode.name), netkind,
|
||||
assignment);
|
||||
context.valueSymbols.insert(&netNode, netOp);
|
||||
return success();
|
||||
}
|
||||
|
||||
// Handle continuous assignments.
|
||||
LogicalResult visit(const slang::ast::ContinuousAssignSymbol &assignNode) {
|
||||
if (const auto *delay = assignNode.getDelay()) {
|
||||
|
@ -129,8 +193,8 @@ struct MemberVisitor {
|
|||
|
||||
// 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; end`,
|
||||
// will create the procedure with a block and variable declaration as
|
||||
// procedure with a variable declaration, such as `initial begin int x;
|
||||
// end`, will create the procedure with a block and variable declaration as
|
||||
// expected, but will also create a `StatementBlockSymbol` with just the
|
||||
// variable layout _next to_ the initial procedure.
|
||||
LogicalResult visit(const slang::ast::StatementBlockSymbol &) {
|
||||
|
|
|
@ -45,6 +45,14 @@ void VariableOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
|||
setNameFn(getResult(), getName());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NetOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void NetOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
|
||||
setNameFn(getResult(), getName());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConstantOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -46,6 +46,33 @@ module Basic;
|
|||
int v1;
|
||||
int v2 = v1;
|
||||
|
||||
// CHECK: %w0 = moore.net wire : !moore.logic
|
||||
// CHECK: %w1 = moore.net wire %w0 : !moore.logic
|
||||
wire w0;
|
||||
wire w1 = w0;
|
||||
// CHECK: %w2 = moore.net uwire %w0 : !moore.logic
|
||||
uwire w2 = w0;
|
||||
// CHECK: %w3 = moore.net tri %w0 : !moore.logic
|
||||
tri w3 = w0;
|
||||
// CHECK: %w4 = moore.net triand %w0 : !moore.logic
|
||||
triand w4 = w0;
|
||||
// CHECK: %w5 = moore.net trior %w0 : !moore.logic
|
||||
trior w5 = w0;
|
||||
// CHECK: %w6 = moore.net wand %w0 : !moore.logic
|
||||
wand w6 = w0;
|
||||
// CHECK: %w7 = moore.net wor %w0 : !moore.logic
|
||||
wor w7 = w0;
|
||||
// CHECK: %w8 = moore.net trireg %w0 : !moore.logic
|
||||
trireg w8 = w0;
|
||||
// CHECK: %w9 = moore.net tri0 %w0 : !moore.logic
|
||||
tri0 w9 = w0;
|
||||
// CHECK: %w10 = moore.net tri1 %w0 : !moore.logic
|
||||
tri1 w10 = w0;
|
||||
// CHECK: %w11 = moore.net supply0 : !moore.logic
|
||||
supply0 w11;
|
||||
// CHECK: %w12 = moore.net supply1 : !moore.logic
|
||||
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
|
||||
|
|
|
@ -44,6 +44,21 @@ endmodule
|
|||
|
||||
// -----
|
||||
|
||||
module Foo;
|
||||
// expected-error @below {{unsupported construct}}
|
||||
nettype real x;
|
||||
endmodule
|
||||
|
||||
// -----
|
||||
|
||||
module Foo;
|
||||
// expected-error @+2 {{unsupported type}}
|
||||
// expected-note @+1 {{untyped}}
|
||||
interconnect x;
|
||||
endmodule
|
||||
|
||||
// -----
|
||||
|
||||
// expected-error @below {{unsupported construct}}
|
||||
package Foo;
|
||||
endpackage
|
||||
|
|
|
@ -10,6 +10,33 @@ moore.module @Foo {
|
|||
// CHECK: [[TMP:%.+]] = moore.variable name "v1" %v2 : !moore.bit
|
||||
moore.variable name "v1" %v2 : !moore.bit
|
||||
|
||||
// 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: moore.procedure initial {
|
||||
// CHECK: moore.procedure final {
|
||||
// CHECK: moore.procedure always {
|
||||
|
|
Loading…
Reference in New Issue