CIRCT 22.0.0git
Loading...
Searching...
No Matches
FIRRTLInstanceImplementation.cpp
Go to the documentation of this file.
1//===- FIRRTLInstanceImplementation.cpp - Utilities for instance-like ops -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11
12using namespace circt;
13using namespace circt::firrtl;
14
15LogicalResult
17 SymbolTableCollection &symbolTable,
18 mlir::FlatSymbolRefAttr moduleName) {
19 auto referencedModule =
20 symbolTable.lookupNearestSymbolFrom<FModuleLike>(instanceOp, moduleName);
21 if (!referencedModule) {
22 return instanceOp->emitOpError("invalid symbol reference");
23 }
24
25 // Check this is not a class.
26 if (isa<ClassOp /* ClassLike */>(referencedModule))
27 return instanceOp->emitOpError("must instantiate a module not a class")
28 .attachNote(referencedModule.getLoc())
29 << "class declared here";
30
31 // Small helper add a note to the original declaration.
32 auto emitNote = [&](InFlightDiagnostic &&diag) -> InFlightDiagnostic && {
33 diag.attachNote(referencedModule->getLoc())
34 << "original module declared here";
35 return std::move(diag);
36 };
37
38 // Check that all the attribute arrays are the right length up front. This
39 // lets us safely use the port name in error messages below.
40 size_t numResults = instanceOp->getNumResults();
41 size_t numExpected = referencedModule.getNumPorts();
42 if (numResults != numExpected) {
43 return emitNote(instanceOp->emitOpError()
44 << "has a wrong number of results; expected " << numExpected
45 << " but got " << numResults);
46 }
47 auto portDirections =
48 instanceOp->getAttrOfType<mlir::DenseBoolArrayAttr>("portDirections");
49 if (static_cast<size_t>(portDirections.size()) != numExpected)
50 return emitNote(
51 instanceOp->emitOpError("the number of port directions should be "
52 "equal to the number of results"));
53
54 auto portNames = instanceOp->getAttrOfType<ArrayAttr>("portNames");
55 if (portNames.size() != numExpected)
56 return emitNote(
57 instanceOp->emitOpError("the number of port names should be "
58 "equal to the number of results"));
59
60 auto portAnnotations =
61 instanceOp->getAttrOfType<ArrayAttr>("portAnnotations");
62 if (portAnnotations.size() != numExpected)
63 return emitNote(
64 instanceOp->emitOpError("the number of result annotations should be "
65 "equal to the number of results"));
66
67 auto domainInfo = instanceOp->getAttrOfType<ArrayAttr>("domainInfo");
68 if (domainInfo.size() != numExpected)
69 return emitNote(
70 instanceOp->emitOpError()
71 << "has a wrong number of port domain info attributes; expected "
72 << numExpected << ", got " << domainInfo.size());
73
74 // Check that the port names match the referenced module.
75 if (portNames != referencedModule.getPortNamesAttr()) {
76 // We know there is an error, try to figure out whats wrong.
77 auto moduleNames = referencedModule.getPortNamesAttr();
78 // First compare the sizes:
79 if (portNames.size() != moduleNames.size()) {
80 return emitNote(instanceOp->emitOpError()
81 << "has a wrong number of directions; expected "
82 << moduleNames.size() << " but got " << portNames.size());
83 }
84 // Next check the values:
85 for (size_t i = 0; i != numResults; ++i) {
86 if (portNames[i] != moduleNames[i]) {
87 return emitNote(instanceOp->emitOpError()
88 << "name for port " << i << " must be "
89 << moduleNames[i] << ", but got " << portNames[i]);
90 }
91 }
92 llvm_unreachable("should have found something wrong");
93 }
94
95 // Check that the types match.
96 for (size_t i = 0; i != numResults; i++) {
97 auto resultType = instanceOp->getResult(i).getType();
98 auto expectedType = referencedModule.getPortType(i);
99 if (resultType != expectedType) {
100 return emitNote(instanceOp->emitOpError()
101 << "result type for " << portNames[i] << " must be "
102 << expectedType << ", but got " << resultType);
103 }
104 }
105
106 // Check that the port directions are consistent with the referenced module's.
107 if (portDirections != referencedModule.getPortDirectionsAttr()) {
108 // We know there is an error, try to figure out whats wrong.
109 auto moduleDirectionAttr = referencedModule.getPortDirectionsAttr();
110 // First compare the sizes:
111 auto expectedWidth = moduleDirectionAttr.size();
112 auto actualWidth = portDirections.size();
113 if (expectedWidth != actualWidth) {
114 return emitNote(instanceOp->emitOpError()
115 << "has a wrong number of directions; expected "
116 << expectedWidth << " but got " << actualWidth);
117 }
118 // Next check the values.
119 auto instanceDirs = portDirections;
120 for (size_t i = 0; i != numResults; ++i) {
121 if (instanceDirs[i] != moduleDirectionAttr[i]) {
122 return emitNote(instanceOp->emitOpError()
123 << "direction for " << portNames[i] << " must be \""
124 << direction::toString(moduleDirectionAttr[i])
125 << "\", but got \""
126 << direction::toString(instanceDirs[i]) << "\"");
127 }
128 }
129 llvm_unreachable("should have found something wrong");
130 }
131
132 // Check the domain info matches.
133 for (size_t i = 0; i < numResults; ++i) {
134 auto portDomainInfo = domainInfo[i];
135 auto modulePortDomainInfo = referencedModule.getDomainInfoAttrForPort(i);
136 if (portDomainInfo != modulePortDomainInfo)
137 return emitNote(instanceOp->emitOpError()
138 << "domain info for " << portNames[i] << " must be "
139 << modulePortDomainInfo << ", but got "
140 << portDomainInfo);
141 }
142
143 // Check that the instance op lists the correct layer requirements.
144 auto instanceLayers = instanceOp->getAttrOfType<ArrayAttr>("layers");
145 auto moduleLayers = referencedModule.getLayersAttr();
146 if (instanceLayers != moduleLayers)
147 return emitNote(instanceOp->emitOpError()
148 << "layers must be " << moduleLayers << ", but got "
149 << instanceLayers);
150
151 return success();
152}
static StringRef toString(Direction direction)
Definition FIRRTLEnums.h:44
LogicalResult verifyReferencedModule(Operation *instanceOp, SymbolTableCollection &symbolTable, mlir::FlatSymbolRefAttr moduleName)
Verify that the instance refers to a valid FIRRTL module.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.