Skip to content

Commit c259d1b

Browse files
committed
[FIRRTL] Rewrite, extend InstanceInfo for GC Views
Rewrite the `CheckLayers` pass to more directly rely on the `InstanceInfo` analysis. Instead of the top-down walk (which was there from the original architecture which did not have access to `InstanceInfo` and was originally pushing layer information down), use only a bottom-up walk and rely on the `InstanceInfo` analysis to determine when modules could be problematic. This preserves a similar style of the original verbose errors/notes which reports transitive errors (modules which do not contain layers, but instantiate modules that do), but switches to something that is easier to work with. Extend the `CheckLayers` pass to now properly handle Grand Central companion modules. These are conceptually the same as layers and are now lumped under the "under layer" bucket by `InstanceInfo`. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
1 parent 94c9b6b commit c259d1b

File tree

2 files changed

+152
-52
lines changed

2 files changed

+152
-52
lines changed

lib/Dialect/FIRRTL/Transforms/CheckLayers.cpp

Lines changed: 71 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "circt/Analysis/FIRRTLInstanceInfo.h"
10+
#include "circt/Dialect/FIRRTL/AnnotationDetails.h"
1011
#include "circt/Dialect/FIRRTL/FIRRTLInstanceGraph.h"
1112
#include "circt/Dialect/FIRRTL/FIRRTLOps.h"
1213
#include "circt/Dialect/FIRRTL/Passes.h"
@@ -31,44 +32,79 @@ class CheckLayers {
3132
CheckLayers(InstanceGraph &instanceGraph, InstanceInfo &instanceInfo)
3233
: iGraph(instanceGraph), iInfo(instanceInfo) {}
3334

34-
/// Walk a module, reporting any illegal instantation of layers under layers,
35-
/// and record if this module contains any layerblocks.
35+
/// Walk a module and record any illegal layerblocks/Grand Central companions
36+
/// under layerblocks/Grand Central companions. This function should be run
37+
/// on children before parents for accurate reporting.
3638
void run(FModuleOp moduleOp) {
37-
// No instance is under a layer block. No further examination is necessary.
39+
40+
// The module is _never_ instantiated under a layer. There is nothing to do
41+
// because erroneous instantiations are reported when examining the module.
42+
// Note: Grand Central companions are under a layer (because InstanceInfo
43+
// uses the inclusive definition of "under" to be consistent with how the
44+
// design-under-test module is "under" the design).
3845
if (!iInfo.anyInstanceUnderLayer(moduleOp))
3946
return;
4047

41-
// The module is under a layer block. Verify that it has no layer blocks.
42-
LayerBlockOp layerBlockOp;
43-
moduleOp.getBodyBlock()->walk([&](LayerBlockOp op) {
44-
layerBlockOp = op;
45-
return WalkResult::interrupt();
48+
// Check if this module has any layerblock ops. If these exist, then these
49+
// may be errors.
50+
SmallVector<Operation *> layerBlockOps;
51+
moduleOp->walk([&](LayerBlockOp layerBlockOp) {
52+
layerBlockOps.push_back(layerBlockOp);
4653
});
47-
if (!layerBlockOp)
54+
55+
bool isGCCompanion =
56+
AnnotationSet::hasAnnotation(moduleOp, companionAnnoClass);
57+
58+
// Both Grand Central copmanions and modules that transitively instantiate
59+
// layerblocks/Grand Central companions require analysis of their
60+
// instantiation sites. However, if this is a normal module instantiated
61+
// under a layer and it contains no layerblocks, then early exit to avoid
62+
// unnecessarily examining instantiation sites.
63+
if (!isGCCompanion && !transitiveModules.contains(moduleOp) &&
64+
layerBlockOps.empty())
4865
return;
4966

50-
// The module contains layer blocks and is instantiated under a layer block.
51-
// Walk up the instance hierarchy to find the first instance which is
52-
// directly under a layer block.
53-
error = true;
54-
for (auto *node : llvm::inverse_depth_first(iGraph.lookup(moduleOp))) {
55-
auto modOp = node->getModule();
56-
if (previousErrors.contains(node) || !iInfo.anyInstanceUnderLayer(modOp))
57-
continue;
58-
for (auto *instNode : node->uses()) {
59-
auto instanceOp = instNode->getInstance();
60-
if (instanceOp->getParentOfType<LayerBlockOp>()) {
61-
auto moduleName = modOp.getModuleNameAttr();
62-
auto diag = emitError(instanceOp.getLoc())
63-
<< "cannot instantiate " << moduleName
64-
<< " under a layerblock, because " << moduleName
65-
<< " contains a layerblock";
66-
diag.attachNote(layerBlockOp->getLoc()) << "layerblock here";
67-
previousErrors.insert(node);
68-
continue;
69-
}
67+
// Record instantiations of this module under layerblocks or modules that
68+
// are under layer blocks. Update transitive modules.
69+
SmallVector<Operation *> instUnderLayerBlock, instUnderLayerModule;
70+
for (auto *instNode : iGraph.lookup(moduleOp)->uses()) {
71+
auto *instOp = instNode->getInstance().getOperation();
72+
if (instOp->getParentOfType<LayerBlockOp>())
73+
instUnderLayerBlock.push_back(instOp);
74+
else if (auto parent = instOp->getParentOfType<FModuleOp>();
75+
iInfo.anyInstanceUnderLayer(parent)) {
76+
transitiveModules.insert(parent);
77+
instUnderLayerModule.push_back(instOp);
7078
}
7179
}
80+
81+
// The module _may_ contain no errors if it is a Grand Central companion or
82+
// a transitive module. Do a final check to ensure that an error exists.
83+
if (layerBlockOps.empty() && instUnderLayerBlock.empty() &&
84+
instUnderLayerModule.empty())
85+
return;
86+
87+
// Record that an error occurred and print out an error message on the
88+
// module with notes for more information.
89+
error = true;
90+
auto diag = moduleOp->emitOpError();
91+
if (isGCCompanion)
92+
diag
93+
<< "is a Grand Central companion that either contains layerblocks or";
94+
95+
else
96+
diag << "either contains layerblocks or";
97+
diag << " has at least one instance that is or contains a Grand Central "
98+
"companion or layerblocks";
99+
100+
for (auto *layerBlockOp : layerBlockOps)
101+
diag.attachNote(layerBlockOp->getLoc()) << "illegal layerblock here";
102+
for (auto *instUnderLayerBlock : instUnderLayerBlock)
103+
diag.attachNote(instUnderLayerBlock->getLoc())
104+
<< "illegal instantiation under a layerblock here";
105+
for (auto *instUnderLayerModule : instUnderLayerModule)
106+
diag.attachNote(instUnderLayerModule->getLoc())
107+
<< "illegal instantiation in a module under a layer here";
72108
}
73109

74110
public:
@@ -77,7 +113,7 @@ class CheckLayers {
77113
CheckLayers checkLayers(instanceGraph, instanceInfo);
78114
DenseSet<InstanceGraphNode *> visited;
79115
for (auto *root : instanceGraph) {
80-
for (auto *node : llvm::inverse_post_order_ext(root, visited)) {
116+
for (auto *node : llvm::post_order_ext(root, visited)) {
81117
if (auto moduleOp = dyn_cast<FModuleOp>(node->getModule<Operation *>()))
82118
checkLayers.run(moduleOp);
83119
}
@@ -90,9 +126,11 @@ class CheckLayers {
90126
InstanceGraph &iGraph;
91127
InstanceInfo &iInfo;
92128

93-
/// This records modules for which we have already generated errors when doing
94-
/// a top-down walk.
95-
DenseSet<const InstanceGraphNode *> previousErrors;
129+
/// A module whose instances (transitively) contain layerblocks or Grand
130+
/// Central companions. This is used so that every illegal instantiation can
131+
/// be reported. This is populated by `run` and requires child modules to be
132+
/// visited before parents.
133+
DenseSet<Operation *> transitiveModules;
96134

97135
/// Indicates if this checker found an error.
98136
bool error = false;

test/Dialect/FIRRTL/check-layers-errors.mlir

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ firrtl.circuit "Simple" {
44
firrtl.layer @A bind {}
55
firrtl.module @Simple() {
66
firrtl.layerblock @A {
7-
// expected-error @below {{cannot instantiate "Layers" under a layerblock, because "Layers" contains a layerblock}}
7+
// expected-note @below {{illegal instantiation under a layerblock here}}
88
firrtl.instance layers @Layers()
99
}
1010
}
11+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
1112
firrtl.module @Layers() {
12-
// expected-note @below {{layerblock here}}
13+
// expected-note @below {{illegal layerblock here}}
1314
firrtl.layerblock @A {}
1415
}
1516
}
@@ -20,15 +21,18 @@ firrtl.circuit "Transitive" {
2021
firrtl.layer @A bind {}
2122
firrtl.module @Transitive() {
2223
firrtl.layerblock @A {
23-
// expected-error @below {{cannot instantiate "Middle" under a layerblock, because "Middle" contains a layerblock}}
24+
// expected-note @below {{illegal instantiation under a layerblock here}}
2425
firrtl.instance middle @Middle()
2526
}
2627
}
28+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
2729
firrtl.module @Middle() {
30+
// expected-note @below {{illegal instantiation in a module under a layer here}}
2831
firrtl.instance layers @Layers()
2932
}
33+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
3034
firrtl.module @Layers() {
31-
// expected-note @below {{layerblock here}}
35+
// expected-note @below {{illegal layerblock here}}
3236
firrtl.layerblock @A {}
3337
}
3438
}
@@ -39,13 +43,15 @@ firrtl.circuit "FirstLayerBLockFound" {
3943
firrtl.layer @A bind {}
4044
firrtl.module @FirstLayerBLockFound() {
4145
firrtl.layerblock @A {
42-
// expected-error @below {{cannot instantiate "Layers" under a layerblock, because "Layers" contains a layerblock}}
46+
// expected-note @below {{illegal instantiation under a layerblock here}}
4347
firrtl.instance layers @Layers()
4448
}
4549
}
50+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
4651
firrtl.module @Layers() {
47-
// expected-note @below {{layerblock here}}
52+
// expected-note @below {{illegal layerblock here}}
4853
firrtl.layerblock @A {}
54+
// expected-note @below {{illegal layerblock here}}
4955
firrtl.layerblock @A {}
5056
}
5157
}
@@ -56,40 +62,44 @@ firrtl.circuit "MultipleErrors" {
5662
firrtl.layer @A bind {}
5763
firrtl.module @MultipleErrors() {
5864
firrtl.layerblock @A {
59-
// expected-error @below {{cannot instantiate "Layers1" under a layerblock, because "Layers1" contains a layerblock}}
65+
// expected-note @below {{illegal instantiation under a layerblock here}}
6066
firrtl.instance layers1 @Layers1()
61-
// expected-error @below {{cannot instantiate "Layers2" under a layerblock, because "Layers2" contains a layerblock}}
67+
// expected-note @below {{illegal instantiation under a layerblock here}}
6268
firrtl.instance layers2 @Layers2()
6369
}
6470
}
71+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
6572
firrtl.module @Layers1() {
66-
// expected-note @below {{layerblock here}}
73+
// expected-note @below {{illegal layerblock here}}
6774
firrtl.layerblock @A {}
6875
}
76+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
6977
firrtl.module @Layers2() {
70-
// expected-note @below {{layerblock here}}
78+
// expected-note @below {{illegal layerblock here}}
7179
firrtl.layerblock @A {}
7280
}
7381
}
7482

83+
7584
// -----
7685

7786
firrtl.circuit "MultipleErrors" {
7887
firrtl.layer @A bind {}
7988
firrtl.module @MultipleErrors() {
8089
firrtl.layerblock @A {
81-
// expected-error @below {{cannot instantiate "Layers" under a layerblock, because "Layers" contains a layerblock}}
90+
// expected-note @below {{illegal instantiation under a layerblock here}}
8291
firrtl.instance layers1 @Layers()
8392
}
8493
}
8594
firrtl.module @OtherTop() {
8695
firrtl.layerblock @A {
87-
// expected-error @below {{cannot instantiate "Layers" under a layerblock, because "Layers" contains a layerblock}}
96+
// expected-note @below {{illegal instantiation under a layerblock here}}
8897
firrtl.instance layers1 @Layers()
8998
}
9099
}
100+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
91101
firrtl.module @Layers() {
92-
// expected-note @+1 {{layerblock here}}
102+
// expected-note @below {{illegal layerblock here}}
93103
firrtl.layerblock @A {}
94104
}
95105
}
@@ -100,19 +110,21 @@ firrtl.circuit "NestedLayers" {
100110
firrtl.layer @A bind {}
101111
firrtl.module @NestedLayers() {
102112
firrtl.layerblock @A {
103-
// expected-error @below {{cannot instantiate "LayerA" under a layerblock, because "LayerA" contains a layerblock}}
113+
// expected-note @below {{illegal instantiation under a layerblock here}}
104114
firrtl.instance layera @LayerA()
105115
}
106116
}
117+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
107118
firrtl.module @LayerA() {
108-
// expected-note @below {{layerblock here}}
119+
// expected-note @below {{illegal layerblock here}}
109120
firrtl.layerblock @A {
110-
// expected-error @below {{cannot instantiate "LayerB" under a layerblock, because "LayerB" contains a layerblock}}
121+
// expected-note @below {{illegal instantiation under a layerblock here}}
111122
firrtl.instance layerb @LayerB()
112123
}
113124
}
125+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
114126
firrtl.module @LayerB() {
115-
// expected-note @below {{layerblock here}}
127+
// expected-note @below {{illegal layerblock here}}
116128
firrtl.layerblock @A {}
117129
}
118130
}
@@ -124,17 +136,67 @@ firrtl.circuit "RegionOps" {
124136
firrtl.module @RegionOps(in %in : !firrtl.uint<1>) {
125137
firrtl.when %in : !firrtl.uint<1> {
126138
firrtl.layerblock @A {
127-
// expected-error @below {{cannot instantiate "Layers" under a layerblock, because "Layers" contains a layerblock}}
139+
// expected-note @below {{illegal instantiation under a layerblock here}}
128140
%layers_in = firrtl.instance layers @Layers(in in : !firrtl.enum<a: uint<1>>)
129141
}
130142
}
131143
}
144+
// expected-error @below {{either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
132145
firrtl.module @Layers(in %in : !firrtl.enum<a: uint<1>>) {
133146
firrtl.match %in : !firrtl.enum<a: uint<1>> {
134147
case a(%arg0) {
135-
// expected-note @below {{layerblock here}}
148+
// expected-note @below {{illegal layerblock here}}
136149
firrtl.layerblock @A {}
137150
}
138151
}
139152
}
140153
}
154+
155+
// -----
156+
157+
// A Grand Central companion cannot contain layerblocks.
158+
firrtl.circuit "Foo" {
159+
firrtl.layer @A bind {}
160+
// expected-error @below {{is a Grand Central companion that either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
161+
firrtl.module @Bar() attributes {
162+
annotations = [
163+
{
164+
class = "sifive.enterprise.grandcentral.ViewAnnotation.companion",
165+
defName = "GroundView",
166+
id = 0 : i64,
167+
name = "GroundView"
168+
}
169+
]
170+
} {
171+
// expected-note @below {{illegal layerblock here}}
172+
firrtl.layerblock @A {}
173+
}
174+
firrtl.module @Foo() {
175+
firrtl.instance bar @Bar()
176+
}
177+
}
178+
179+
// -----
180+
181+
// A Grand Central companion cannot contain layerblocks.
182+
firrtl.circuit "Foo" {
183+
firrtl.layer @A bind {}
184+
// expected-error @below {{is a Grand Central companion that either contains layerblocks or has at least one instance that is or contains a Grand Central companion or layerblocks}}
185+
firrtl.module @Bar() attributes {
186+
annotations = [
187+
{
188+
class = "sifive.enterprise.grandcentral.ViewAnnotation.companion",
189+
defName = "GroundView",
190+
id = 0 : i64,
191+
name = "GroundView"
192+
}
193+
]
194+
} {
195+
}
196+
firrtl.module @Foo() {
197+
firrtl.layerblock @A {
198+
// expected-note @below {{illegal instantiation under a layerblock here}}
199+
firrtl.instance bar @Bar()
200+
}
201+
}
202+
}

0 commit comments

Comments
 (0)