CIRCT  19.0.0git
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 
12 using namespace circt;
13 using namespace circt::firrtl;
14 
15 LogicalResult
17  SymbolTableCollection &symbolTable,
18  mlir::FlatSymbolRefAttr moduleName) {
19  auto module = instanceOp->getParentOfType<FModuleOp>();
20  auto referencedModule =
21  symbolTable.lookupNearestSymbolFrom<FModuleLike>(instanceOp, moduleName);
22  if (!referencedModule) {
23  return instanceOp->emitOpError("invalid symbol reference");
24  }
25 
26  // Check this is not a class.
27  if (isa<ClassOp /* ClassLike */>(referencedModule))
28  return instanceOp->emitOpError("must instantiate a module not a class")
29  .attachNote(referencedModule.getLoc())
30  << "class declared here";
31 
32  // Check that this instance doesn't recursively instantiate its wrapping
33  // module.
34  if (referencedModule == module) {
35  auto diag = instanceOp->emitOpError()
36  << "is a recursive instantiation of its containing module";
37  return diag.attachNote(module.getLoc())
38  << "containing module declared here";
39  }
40 
41  // Small helper add a note to the original declaration.
42  auto emitNote = [&](InFlightDiagnostic &&diag) -> InFlightDiagnostic && {
43  diag.attachNote(referencedModule->getLoc())
44  << "original module declared here";
45  return std::move(diag);
46  };
47 
48  // Check that all the attribute arrays are the right length up front. This
49  // lets us safely use the port name in error messages below.
50  size_t numResults = instanceOp->getNumResults();
51  size_t numExpected = referencedModule.getNumPorts();
52  if (numResults != numExpected) {
53  return emitNote(instanceOp->emitOpError()
54  << "has a wrong number of results; expected " << numExpected
55  << " but got " << numResults);
56  }
57  auto portDirections =
58  instanceOp->getAttrOfType<mlir::DenseBoolArrayAttr>("portDirections");
59  if (static_cast<size_t>(portDirections.size()) != numExpected)
60  return emitNote(
61  instanceOp->emitOpError("the number of port directions should be "
62  "equal to the number of results"));
63 
64  auto portNames = instanceOp->getAttrOfType<ArrayAttr>("portNames");
65  if (portNames.size() != numExpected)
66  return emitNote(
67  instanceOp->emitOpError("the number of port names should be "
68  "equal to the number of results"));
69 
70  auto portAnnotations =
71  instanceOp->getAttrOfType<ArrayAttr>("portAnnotations");
72  if (portAnnotations.size() != numExpected)
73  return emitNote(
74  instanceOp->emitOpError("the number of result annotations should be "
75  "equal to the number of results"));
76 
77  // Check that the port names match the referenced module.
78  if (portNames != referencedModule.getPortNamesAttr()) {
79  // We know there is an error, try to figure out whats wrong.
80  auto moduleNames = referencedModule.getPortNamesAttr();
81  // First compare the sizes:
82  if (portNames.size() != moduleNames.size()) {
83  return emitNote(instanceOp->emitOpError()
84  << "has a wrong number of directions; expected "
85  << moduleNames.size() << " but got " << portNames.size());
86  }
87  // Next check the values:
88  for (size_t i = 0; i != numResults; ++i) {
89  if (portNames[i] != moduleNames[i]) {
90  return emitNote(instanceOp->emitOpError()
91  << "name for port " << i << " must be "
92  << moduleNames[i] << ", but got " << portNames[i]);
93  }
94  }
95  llvm_unreachable("should have found something wrong");
96  }
97 
98  // Check that the types match.
99  for (size_t i = 0; i != numResults; i++) {
100  auto resultType = instanceOp->getResult(i).getType();
101  auto expectedType = referencedModule.getPortType(i);
102  if (resultType != expectedType) {
103  return emitNote(instanceOp->emitOpError()
104  << "result type for " << portNames[i] << " must be "
105  << expectedType << ", but got " << resultType);
106  }
107  }
108 
109  // Check that the port directions are consistent with the referenced module's.
110  if (portDirections != referencedModule.getPortDirectionsAttr()) {
111  // We know there is an error, try to figure out whats wrong.
112  auto moduleDirectionAttr = referencedModule.getPortDirectionsAttr();
113  // First compare the sizes:
114  auto expectedWidth = moduleDirectionAttr.size();
115  auto actualWidth = portDirections.size();
116  if (expectedWidth != actualWidth) {
117  return emitNote(instanceOp->emitOpError()
118  << "has a wrong number of directions; expected "
119  << expectedWidth << " but got " << actualWidth);
120  }
121  // Next check the values.
122  auto instanceDirs = portDirections;
123  for (size_t i = 0; i != numResults; ++i) {
124  if (instanceDirs[i] != moduleDirectionAttr[i]) {
125  return emitNote(instanceOp->emitOpError()
126  << "direction for " << portNames[i] << " must be \""
127  << direction::toString(moduleDirectionAttr[i])
128  << "\", but got \""
129  << direction::toString(instanceDirs[i]) << "\"");
130  }
131  }
132  llvm_unreachable("should have found something wrong");
133  }
134 
135  // Check that the instance op lists the correct layer requirements.
136  auto instanceLayers = instanceOp->getAttrOfType<ArrayAttr>("layers");
137  auto moduleLayers = referencedModule.getLayersAttr();
138  if (instanceLayers != moduleLayers)
139  return emitNote(instanceOp->emitOpError()
140  << "layers must be " << moduleLayers << ", but got "
141  << instanceLayers);
142 
143  return success();
144 }
static StringRef toString(Direction direction)
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.
Definition: DebugAnalysis.h:21