Skip to content

Commit 020bfc4

Browse files
authoredFeb 7, 2025··
[FIRRTL] Add optional yaml parameter to view intrinsic, op (#8203)
1 parent ab69d42 commit 020bfc4

File tree

8 files changed

+98
-112
lines changed

8 files changed

+98
-112
lines changed
 

‎docs/Dialects/FIRRTL/FIRRTLIntrinsics.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,11 @@ This will become a SystemVerilog Interface that is driven by its arguments.
298298
This is _not_ a true SystemVerilog Interface, it is only lowered to one.
299299

300300

301-
| Parameter | Type | Description |
302-
| --------- | ------ | --------------------------------- |
303-
| name | string | Instance name of the view. |
304-
| info | string | JSON encoding the view structure. |
301+
| Parameter | Type | Description |
302+
| --------- | ------ | --------------------------------------- |
303+
| name | string | Instance name of the view. |
304+
| info | string | JSON encoding the view structure. |
305+
| yaml | string | Optional path to emit YAML description. |
305306

306307
| Argument | Type | Description |
307308
| -------- | ------ | ------------------------------- |

‎include/circt/Dialect/FIRRTL/FIRRTLIntrinsics.td

+2-2
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ def ViewIntrinsicOp : FIRRTLOp<"view", []> {
239239
debugging in a waveform. This is _not_ a true SystemVerilog Interface, it
240240
is only lowered to one.
241241
}];
242-
let arguments = (ins StrAttr:$name, AugmentedBundleType:$augmentedType, Variadic<GroundType>:$inputs);
243-
let assemblyFormat = "$name `,` $augmentedType (`,` $inputs^)? attr-dict (`:` type($inputs)^)?";
242+
let arguments = (ins StrAttr:$name, OptionalAttr<StrAttr>:$yamlFile, AugmentedBundleType:$augmentedType, Variadic<GroundType>:$inputs);
243+
let assemblyFormat = "$name `,` (`yaml` $yamlFile^ `,`)? $augmentedType (`,` $inputs^)? attr-dict (`:` type($inputs)^)?";
244244
}
245245

246246
#endif // CIRCT_DIALECT_FIRRTL_FIRRTLINTRINSICS_TD

‎lib/Dialect/FIRRTL/FIRRTLIntrinsics.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,8 @@ class ViewConverter : public IntrinsicConverter {
869869
GenericIntrinsicOpAdaptor adaptor,
870870
PatternRewriter &rewriter) override {
871871
// Check structure of the intrinsic.
872-
if (gi.hasNoOutput() || gi.namedParam("info") || gi.namedParam("name"))
872+
if (gi.hasNoOutput() || gi.namedParam("info") || gi.namedParam("name") ||
873+
gi.namedParam("yaml", true))
873874
return failure();
874875

875876
// Check operands.
@@ -944,9 +945,9 @@ class ViewConverter : public IntrinsicConverter {
944945
<< numLeaves << " leaf elements";
945946

946947
// Check complete, convert!
947-
948+
auto yaml = gi.getParamValue<StringAttr>("yaml");
948949
rewriter.replaceOpWithNewOp<ViewIntrinsicOp>(
949-
gi.op, nameAttr.getValue(), augmentedType, adaptor.getOperands());
950+
gi.op, nameAttr.getValue(), yaml, augmentedType, adaptor.getOperands());
950951
return success();
951952
}
952953
};

‎lib/Dialect/FIRRTL/Transforms/GrandCentral.cpp

+25-22
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,8 @@ struct GrandCentralPass
773773
DenseMap<Attribute, sv::InterfaceOp> interfaceMap;
774774

775775
/// Emit the hierarchy yaml file.
776-
void emitHierarchyYamlFile(SmallVectorImpl<sv::InterfaceOp> &intfs);
776+
void emitHierarchyYamlFile(StringRef yamlPath,
777+
SmallVectorImpl<sv::InterfaceOp> &intfs);
777778
};
778779

779780
} // namespace
@@ -1915,6 +1916,12 @@ void GrandCentralPass::runOnOperation() {
19151916
llvm::dbgs() << "\n";
19161917
});
19171918

1919+
// per-YAML output list of interfaces.
1920+
llvm::SmallMapVector<StringAttr, SmallVector<sv::InterfaceOp, 0>, 1>
1921+
interfaceYAMLMap;
1922+
if (maybeHierarchyFileYAML.has_value())
1923+
interfaceYAMLMap[maybeHierarchyFileYAML.value()] = {};
1924+
19181925
// Scan entire design for View operations.
19191926
SmallVector<ViewIntrinsicOp> views;
19201927
circuitOp.walk([&views](ViewIntrinsicOp view) { views.push_back(view); });
@@ -1923,8 +1930,8 @@ void GrandCentralPass::runOnOperation() {
19231930
// built exist. However, still generate the YAML file if the annotation for
19241931
// this was passed in because some flows expect this.
19251932
if (worklist.empty() && views.empty()) {
1926-
SmallVector<sv::InterfaceOp, 0> interfaceVec;
1927-
emitHierarchyYamlFile(interfaceVec);
1933+
for (auto &[yamlPath, intfs] : interfaceYAMLMap)
1934+
emitHierarchyYamlFile(yamlPath.getValue(), intfs);
19281935
return markAllAnalysesPreserved();
19291936
}
19301937

@@ -2254,8 +2261,8 @@ void GrandCentralPass::runOnOperation() {
22542261
mod->erase();
22552262
}
22562263

2257-
SmallVector<sv::InterfaceOp, 0> interfaceVec;
2258-
emitHierarchyYamlFile(interfaceVec);
2264+
for (auto &[yamlPath, intfs] : interfaceYAMLMap)
2265+
emitHierarchyYamlFile(yamlPath.getValue(), intfs);
22592266
return;
22602267
}
22612268

@@ -2311,7 +2318,6 @@ void GrandCentralPass::runOnOperation() {
23112318
// will use XMRs to drive the interface. If extraction info is available,
23122319
// then the top-level instantiate interface will be marked for extraction via
23132320
// a SystemVerilog bind.
2314-
SmallVector<sv::InterfaceOp, 2> interfaceVec;
23152321
SmallDenseMap<FModuleLike, SmallVector<InterfaceElemsBuilder>>
23162322
companionToInterfaceMap;
23172323
auto compareInterfaceSignal = [&](InterfaceElemsBuilder &lhs,
@@ -2481,7 +2487,8 @@ void GrandCentralPass::runOnOperation() {
24812487

24822488
++numViews;
24832489

2484-
interfaceVec.push_back(topIface);
2490+
if (maybeHierarchyFileYAML.has_value())
2491+
interfaceYAMLMap[maybeHierarchyFileYAML.value()].push_back(topIface);
24852492

24862493
// Instantiate the interface inside the companion.
24872494
builder.setInsertionPointToStart(companionModule.getBodyBlock());
@@ -2567,6 +2574,7 @@ void GrandCentralPass::runOnOperation() {
25672574
sv::InterfaceOp topIface;
25682575
auto containingOutputFileAttr =
25692576
viewParentMod->getAttrOfType<hw::OutputFileAttr>("output_file");
2577+
auto yamlPath = view.getYamlFileAttr();
25702578
for (const auto &ifaceBuilder : interfaceBuilder) {
25712579
auto builder = OpBuilder::atBlockEnd(getOperation().getBodyBlock());
25722580
auto loc = getOperation().getLoc();
@@ -2599,7 +2607,7 @@ void GrandCentralPass::runOnOperation() {
25992607
// If we need to generate a YAML representation of this interface,
26002608
// then add an attribute indicating that this `sv::VerbatimOp` is
26012609
// actually a description.
2602-
if (maybeHierarchyFileYAML)
2610+
if (yamlPath)
26032611
descriptionOp->setAttr("firrtl.grandcentral.yaml.type",
26042612
builder.getStringAttr("description"));
26052613
}
@@ -2609,7 +2617,7 @@ void GrandCentralPass::runOnOperation() {
26092617

26102618
// If we need to generate a YAML representation of the interface, then
26112619
// add attributes that describe what this `sv::VerbatimOp` is.
2612-
if (maybeHierarchyFileYAML) {
2620+
if (yamlPath) {
26132621
if (str->instantiation)
26142622
instanceOp->setAttr("firrtl.grandcentral.yaml.type",
26152623
builder.getStringAttr("instance"));
@@ -2634,7 +2642,8 @@ void GrandCentralPass::runOnOperation() {
26342642

26352643
++numViews;
26362644

2637-
interfaceVec.push_back(topIface);
2645+
if (yamlPath)
2646+
interfaceYAMLMap[yamlPath].push_back(topIface);
26382647

26392648
// Instantiate the interface before the view and the XMR's we inserted
26402649
// above.
@@ -2646,7 +2655,8 @@ void GrandCentralPass::runOnOperation() {
26462655
view.erase();
26472656
}
26482657

2649-
emitHierarchyYamlFile(interfaceVec);
2658+
for (auto &[yamlPath, intfs] : interfaceYAMLMap)
2659+
emitHierarchyYamlFile(yamlPath.getValue(), intfs);
26502660

26512661
// Signal pass failure if any errors were found while examining circuit
26522662
// annotations.
@@ -2656,13 +2666,7 @@ void GrandCentralPass::runOnOperation() {
26562666
}
26572667

26582668
void GrandCentralPass::emitHierarchyYamlFile(
2659-
SmallVectorImpl<sv::InterfaceOp> &intfs) {
2660-
// If a `GrandCentralHierarchyFileAnnotation` was passed in, generate a YAML
2661-
// representation of the interfaces that we produced with the filename that
2662-
// that annotation provided.
2663-
if (!maybeHierarchyFileYAML)
2664-
return;
2665-
2669+
StringRef yamlPath, SmallVectorImpl<sv::InterfaceOp> &intfs) {
26662670
CircuitOp circuitOp = getOperation();
26672671

26682672
std::string yamlString;
@@ -2673,10 +2677,9 @@ void GrandCentralPass::emitHierarchyYamlFile(
26732677

26742678
auto builder = OpBuilder::atBlockBegin(circuitOp.getBodyBlock());
26752679
builder.create<sv::VerbatimOp>(builder.getUnknownLoc(), yamlString)
2676-
->setAttr("output_file",
2677-
hw::OutputFileAttr::getFromFilename(
2678-
&getContext(), maybeHierarchyFileYAML->getValue(),
2679-
/*excludeFromFileList=*/true));
2680+
->setAttr("output_file", hw::OutputFileAttr::getFromFilename(
2681+
&getContext(), yamlPath,
2682+
/*excludeFromFileList=*/true));
26802683
LLVM_DEBUG({ llvm::dbgs() << "Generated YAML:" << yamlString << "\n"; });
26812684
}
26822685

‎test/Dialect/FIRRTL/grand-central-view.mlir

+9-49
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,7 @@
44
// types. All the interfaces share a common, simple circuit that provides two
55
// signals, "foo" and "bar".
66

7-
firrtl.circuit "InterfaceGroundType" attributes {
8-
annotations = [
9-
{
10-
class = "sifive.enterprise.grandcentral.ExtractGrandCentralAnnotation",
11-
directory = "gct-dir",
12-
filename = "bindings.sv"
13-
},
14-
{
15-
class = "sifive.enterprise.grandcentral.GrandCentralHierarchyFileAnnotation",
16-
filename = "gct.yaml"
17-
}
18-
]
19-
} {
7+
firrtl.circuit "InterfaceGroundType" {
208
firrtl.module @Companion() {
219
// These are dummy references created for the purposes of the test.
2210
%_ui0 = firrtl.verbatim.expr "???" : () -> !firrtl.uint<0>
@@ -38,7 +26,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
3826
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
3927
%c-1_si2 = firrtl.constant -1 : !firrtl.sint<2>
4028

41-
firrtl.view "GroundView", <{
29+
firrtl.view "GroundView", yaml "gct.yaml", <{
4230
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
4331
defName = "GroundView",
4432
elements = [
@@ -55,7 +43,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
5543
]
5644
}>, %foo, %bar : !firrtl.uint<1>, !firrtl.uint<2>
5745

58-
firrtl.view "VectorView", <{
46+
firrtl.view "VectorView", yaml "gct.yaml", <{
5947
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
6048
defName = "VectorView",
6149
elements = [
@@ -77,7 +65,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
7765
}>, %foo, %foo : !firrtl.uint<1>, !firrtl.uint<1>
7866

7967

80-
firrtl.view "BundleView", <{
68+
firrtl.view "BundleView", yaml "gct.yaml", <{
8169
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
8270
defName = "BundleView",
8371
elements = [
@@ -99,7 +87,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
9987
]
10088
}>, %foo, %bar : !firrtl.uint<1>, !firrtl.uint<2>
10189

102-
firrtl.view "VectorOfBundleView", <{
90+
firrtl.view "VectorOfBundleView", yaml "gct.yaml", <{
10391
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
10492
defName = "VectorOfBundleView",
10593
elements = [
@@ -127,7 +115,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
127115
]
128116
}>, %foo, %bar : !firrtl.uint<1>, !firrtl.uint<2>
129117

130-
firrtl.view "VectorOfVectorView", <{
118+
firrtl.view "VectorOfVectorView", yaml "gct.yaml", <{
131119
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
132120
defName = "VectorOfVectorView",
133121
elements = [
@@ -178,7 +166,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
178166
]
179167
}>, %bar, %bar, %bar, %bar, %bar, %bar : !firrtl.uint<2>, !firrtl.uint<2>, !firrtl.uint<2>, !firrtl.uint<2>, !firrtl.uint<2>, !firrtl.uint<2>
180168

181-
firrtl.view "ConstantView", <{
169+
firrtl.view "ConstantView", yaml "gct.yaml", <{
182170
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
183171
defName = "ConstantView",
184172
elements = [
@@ -194,7 +182,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
194182
]
195183
}>, %c0_ui1, %c-1_si2 : !firrtl.uint<1>, !firrtl.sint<2>
196184

197-
firrtl.view "ZeroWidthView", <{
185+
firrtl.view "ZeroWidthView", yaml "gct.yaml", <{
198186
class = "sifive.enterprise.grandcentral.AugmentedBundleType",
199187
defName = "ZeroWidthView",
200188
elements = [
@@ -210,13 +198,6 @@ firrtl.circuit "InterfaceGroundType" attributes {
210198
}
211199
}
212200

213-
// All AugmentedBundleType annotations are removed from the circuit.
214-
//
215-
// CHECK-LABEL: firrtl.circuit "InterfaceGroundType" {{.+}} {annotations =
216-
// CHECK-SAME: class = "sifive.enterprise.grandcentral.ExtractGrandCentralAnnotation"
217-
// CHECK-NOT: class = "sifive.enterprise.grandcentral.AugmentedBundleType"
218-
// CHECK-SAME: {
219-
220201
// Check YAML Output.
221202
//
222203
// Note: Built-in vector serialization works slightly differently than
@@ -420,15 +401,7 @@ firrtl.circuit "InterfaceGroundType" attributes {
420401

421402
// -----
422403

423-
firrtl.circuit "Top" attributes {
424-
annotations = [
425-
{
426-
class = "sifive.enterprise.grandcentral.ExtractGrandCentralAnnotation",
427-
directory = ".",
428-
filename = "bindings.sv"
429-
}
430-
]
431-
} {
404+
firrtl.circuit "Top" {
432405
firrtl.module private @Companion_w1(in %_gen_uint: !firrtl.uint<1>) {
433406
%view_uintrefPort = firrtl.node %_gen_uint : !firrtl.uint<1>
434407
firrtl.view "View_w1", <{
@@ -501,19 +474,6 @@ firrtl.circuit "Top" attributes {
501474

502475
// -----
503476

504-
firrtl.circuit "NoInterfaces" attributes {
505-
annotations = [
506-
{class = "sifive.enterprise.grandcentral.GrandCentralHierarchyFileAnnotation",
507-
filename = "gct.yaml"}]} {
508-
firrtl.module @NoInterfaces() {}
509-
}
510-
511-
// CHECK-LABEL: module {
512-
// CHECK: sv.verbatim
513-
// CHECK-SAME: []
514-
515-
// -----
516-
517477
firrtl.circuit "SetOutputDir" {
518478
firrtl.module @SetOutputDir() attributes {output_file = #hw.output_file<"path/">} {
519479
firrtl.view "view", <{

‎test/Dialect/FIRRTL/lower-intrinsics.mlir

+4
Original file line numberDiff line numberDiff line change
@@ -228,5 +228,9 @@ firrtl.circuit "Foo" {
228228
// CHECK-SAME: }>,
229229
// Check operands and types.
230230
// CHECK-SAME: %4, %3, %2, %1, %0 : !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1>
231+
232+
firrtl.int.generic "circt_view" <name: none = "view2", yaml: none = "views.yml", info: none = "{\"class\":\"sifive.enterprise.grandcentral.AugmentedBundleType\",\"defName\":\"ViewName\",\"elements\":[]}"> : () -> ()
233+
234+
// CHECK: firrtl.view "view2", yaml "views.yml", <{
231235
}
232236
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
; RUN: firtool %s | FileCheck %s
2+
; RUN: firtool %s | FileCheck %s --check-prefix=YAML
3+
4+
FIRRTL version 4.2.0
5+
circuit ViewInLayer:
6+
layer Views, bind, "views/":
7+
layer Other, bind, "other/":
8+
layer A, bind, "other/A/":
9+
layer B, inline:
10+
11+
public module ViewInLayer:
12+
input x : UInt<1>
13+
input y : UInt<1>
14+
intrinsic(circt_view<name="view", info="{\"class\":\"sifive.enterprise.grandcentral.AugmentedBundleType\", \"defName\": \"Root\", \"elements\": [{\"name\": \"foo\", \"tpe\":{\"class\":\"sifive.enterprise.grandcentral.AugmentedGroundType\"}}]}">, x)
15+
16+
layerblock Views:
17+
intrinsic(circt_view<name="view", info="{\"class\":\"sifive.enterprise.grandcentral.AugmentedBundleType\", \"defName\": \"MyView\", \"elements\": [{\"name\": \"foo\", \"tpe\":{\"class\":\"sifive.enterprise.grandcentral.AugmentedGroundType\"}}]}">, x)
18+
19+
layerblock Other:
20+
node n = and(x, y)
21+
layerblock A:
22+
; TODO: Maybe the YAML path should be relative to governing output directory?
23+
intrinsic(circt_view<name="view_a", yaml="other/views.yml", info="{\"class\":\"sifive.enterprise.grandcentral.AugmentedBundleType\", \"defName\": \"AView\", \"elements\": [{\"name\": \"foo\", \"tpe\":{\"class\":\"sifive.enterprise.grandcentral.AugmentedGroundType\"}}]}">, n)
24+
layerblock B:
25+
intrinsic(circt_view<name="view_b", yaml="other/views.yml", info="{\"class\":\"sifive.enterprise.grandcentral.AugmentedBundleType\", \"defName\": \"BView\", \"elements\": [{\"name\": \"foo\", \"tpe\":{\"class\":\"sifive.enterprise.grandcentral.AugmentedGroundType\"}}]}">, n)
26+
27+
; CHECK-NOT: FILE
28+
; CHECK: module ViewInLayer
29+
; CHECK-NOT: FILE
30+
; CHECK: interface Root
31+
32+
; CHECK-DAG: FILE "views{{[/\]}}MyView.sv"
33+
; CHECK-DAG: FILE "other{{[/\]}}A{{[/\]}}AView.sv"
34+
; CHECK-DAG: FILE "other{{[/\]}}BView.sv"
35+
; CHECK-DAG: FILE "other{{[/\]}}views.yml"
36+
37+
; YAML: FILE "other{{[/\]}}views.yml"
38+
; YAML: - name: AView
39+
; YAML-NEXT: fields:
40+
; YAML-NEXT: - name: foo
41+
; YAML-NEXT: dimensions: [ ]
42+
; YAML-NEXT: width: 1
43+
; YAML-NEXT: instances: []
44+
; YAML-NEXT: - name: BView
45+
; YAML-NEXT: fields:
46+
; YAML-NEXT: - name: foo
47+
; YAML-NEXT: dimensions: [ ]
48+
; YAML-NEXT: width: 1
49+
; YAML-NEXT: instances: []

‎test/firtool/views-directories.fir

-32
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.