13 using namespace circt;
18 Operation *instanceOp,
19 mlir::FlatSymbolRefAttr moduleName) {
24 auto topLevelModuleOp = instanceOp->getParentOfType<ModuleOp>();
25 return topLevelModuleOp.lookupSymbol(moduleName.getValue());
29 Operation *instanceOp, SymbolTableCollection &symbolTable,
30 mlir::FlatSymbolRefAttr moduleName, Operation *&module) {
32 if (module ==
nullptr)
33 return instanceOp->emitError(
"Cannot find module definition '")
34 << moduleName.getValue() <<
"'";
37 if (!isa<HWModuleLike>(module))
38 return instanceOp->emitError(
"symbol reference '")
39 << moduleName.getValue() <<
"' isn't a module";
45 Location loc, ArrayAttr parameters, ArrayRef<Type> types,
46 SmallVectorImpl<Type> &resolvedTypes,
const EmitErrorFn &emitError) {
47 for (
auto type : types) {
49 if (failed(expectedType)) {
50 emitError([&](
auto &diag) {
51 diag <<
"failed to resolve parametric input of instantiated module";
57 resolvedTypes.push_back(*expectedType);
64 ArrayAttr moduleArgNames,
66 ArrayRef<Type> moduleInputTypes,
69 if (moduleInputTypes.size() != inputTypes.size()) {
70 emitError([&](
auto &diag) {
71 diag <<
"has a wrong number of operands; expected "
72 << moduleInputTypes.size() <<
" but got " << inputTypes.size();
78 if (argNames.size() != inputTypes.size()) {
79 emitError([&](
auto &diag) {
80 diag <<
"has a wrong number of input port names; expected "
81 << inputTypes.size() <<
" but got " << argNames.size();
87 for (
size_t i = 0; i != inputTypes.size(); ++i) {
88 auto expectedType = moduleInputTypes[i];
89 auto operandType = inputTypes[i];
91 if (operandType != expectedType) {
92 emitError([&](
auto &diag) {
93 diag <<
"operand type #" << i <<
" must be " << expectedType
94 <<
", but got " << operandType;
100 if (argNames[i] != moduleArgNames[i]) {
101 emitError([&](
auto &diag) {
102 diag <<
"input label #" << i <<
" must be " << moduleArgNames[i]
103 <<
", but got " << argNames[i];
114 ArrayAttr resultNames, ArrayAttr moduleResultNames, TypeRange resultTypes,
115 ArrayRef<Type> moduleResultTypes,
const EmitErrorFn &emitError) {
117 if (moduleResultTypes.size() != resultTypes.size()) {
118 emitError([&](
auto &diag) {
119 diag <<
"has a wrong number of results; expected "
120 << moduleResultTypes.size() <<
" but got " << resultTypes.size();
126 if (resultNames.size() != resultTypes.size()) {
127 emitError([&](
auto &diag) {
128 diag <<
"has a wrong number of results port labels; expected "
129 << resultTypes.size() <<
" but got " << resultNames.size();
135 for (
size_t i = 0; i != resultTypes.size(); ++i) {
136 auto expectedType = moduleResultTypes[i];
137 auto resultType = resultTypes[i];
139 if (resultType != expectedType) {
140 emitError([&](
auto &diag) {
141 diag <<
"result type #" << i <<
" must be " << expectedType
142 <<
", but got " << resultType;
148 if (resultNames[i] != moduleResultNames[i]) {
149 emitError([&](
auto &diag) {
150 diag <<
"result label #" << i <<
" must be " << moduleResultNames[i]
151 <<
", but got " << resultNames[i];
163 ArrayAttr moduleParameters,
166 auto numParameters = parameters.size();
167 if (numParameters != moduleParameters.size()) {
168 emitError([&](
auto &diag) {
169 diag <<
"expected " << moduleParameters.size() <<
" parameters but had "
176 for (
size_t i = 0; i != numParameters; ++i) {
177 auto param = parameters[i].cast<ParamDeclAttr>();
178 auto modParam = moduleParameters[i].cast<ParamDeclAttr>();
180 auto paramName = param.getName();
181 if (paramName != modParam.getName()) {
182 emitError([&](
auto &diag) {
183 diag <<
"parameter #" << i <<
" should have name " << modParam.getName()
184 <<
" but has name " << paramName;
190 if (param.getType() != modParam.getType()) {
191 emitError([&](
auto &diag) {
192 diag <<
"parameter " << paramName <<
" should have type "
193 << modParam.getType() <<
" but has type " << param.getType();
201 if (!param.getValue()) {
202 emitError([&](
auto &diag) {
203 diag <<
"parameter " << paramName <<
" must have a value";
214 Operation *instance, FlatSymbolRefAttr moduleRef, OperandRange
inputs,
215 TypeRange results, ArrayAttr argNames, ArrayAttr resultNames,
216 ArrayAttr parameters, SymbolTableCollection &symbolTable) {
228 [&](
const std::function<bool(InFlightDiagnostic & diag)> &fn) {
229 auto diag = instance->emitOpError();
231 diag.attachNote(module->getLoc()) <<
"module declared here";
235 auto mod = cast<HWModuleLike>(module);
238 auto modResultNames =
241 ArrayRef<Type> resolvedModInputTypesRef =
getModuleType(module).getInputs();
242 SmallVector<Type> resolvedModInputTypes;
245 instance->getLoc(), parameters,
getModuleType(module).getInputs(),
246 resolvedModInputTypes, emitError)))
248 resolvedModInputTypesRef = resolvedModInputTypes;
251 argNames, modArgNames,
inputs.getTypes(), resolvedModInputTypesRef,
256 ArrayRef<Type> resolvedModResultTypesRef =
getModuleType(module).getResults();
257 SmallVector<Type> resolvedModResultTypes;
260 instance->getLoc(), parameters,
getModuleType(module).getResults(),
261 resolvedModResultTypes, emitError)))
263 resolvedModResultTypesRef = resolvedModResultTypes;
266 resultNames, modResultNames, results, resolvedModResultTypesRef,
272 ArrayAttr modParameters = module->getAttrOfType<ArrayAttr>(
"parameters");
283 ArrayAttr moduleParameters,
287 for (
auto param : parameters) {
288 auto paramAttr = param.cast<ParamDeclAttr>();
289 auto value = paramAttr.getValue();
295 auto typedValue = value.dyn_cast<mlir::TypedAttr>();
297 emitError([&](
auto &diag) {
298 diag <<
"parameter " << paramAttr
299 <<
" should have a typed value; has value " << value;
305 if (typedValue.getType() != paramAttr.getType()) {
306 emitError([&](
auto &diag) {
307 diag <<
"parameter " << paramAttr <<
" should have type "
308 << paramAttr.getType() <<
"; has type " << typedValue.getType();
322 if (names && idx < names.size())
323 return names[idx].cast<StringAttr>();
329 SmallVector<Attribute> newNames(oldNames.begin(), oldNames.end());
330 if (newNames[i] == name)
337 StringRef instanceName,
338 ArrayAttr resultNames,
339 ValueRange results) {
341 std::string name = instanceName.str() +
".";
342 size_t baseNameLen = name.size();
344 for (
size_t i = 0, e = resultNames.size(); i != e; ++i) {
345 auto resName =
getName(resultNames, i);
346 name.resize(baseNameLen);
347 if (resName && !resName.getValue().empty())
348 name += resName.getValue().str();
350 name += std::to_string(i);
351 setNameFn(results[i], name);
llvm::SmallVector< StringAttr > inputs
This stores lookup tables to make manipulating and working with the IR more efficient.
mlir::Operation * getDefinition(mlir::Attribute attr) const override
Lookup a definition for 'symbol' in the cache.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
LogicalResult verifyParameterStructure(ArrayAttr parameters, ArrayAttr moduleParameters, const EmitErrorFn &emitError)
Check that all the parameter values specified to the instance are structurally valid.
Operation * getReferencedModule(const HWSymbolCache *cache, Operation *instanceOp, mlir::FlatSymbolRefAttr moduleName)
Return a pointer to the referenced module operation.
std::function< void(std::function< bool(InFlightDiagnostic &)>)> EmitErrorFn
Whenever the nested function returns true, a note referring to the referenced module is attached to t...
LogicalResult verifyOutputs(ArrayAttr resultNames, ArrayAttr moduleResultNames, TypeRange resultTypes, ArrayRef< Type > moduleResultTypes, const EmitErrorFn &emitError)
Verify that the list of outputs of the instance and the module match in terms of length,...
LogicalResult verifyInstanceOfHWModule(Operation *instance, FlatSymbolRefAttr moduleRef, OperandRange inputs, TypeRange results, ArrayAttr argNames, ArrayAttr resultNames, ArrayAttr parameters, SymbolTableCollection &symbolTable)
Combines verifyReferencedModule, verifyInputs, verifyOutputs, and verifyParameters.
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
LogicalResult resolveParametricTypes(Location loc, ArrayAttr parameters, ArrayRef< Type > types, SmallVectorImpl< Type > &resolvedTypes, const EmitErrorFn &emitError)
Stores a resolved version of each type in.
LogicalResult verifyInputs(ArrayAttr argNames, ArrayAttr moduleArgNames, TypeRange inputTypes, ArrayRef< Type > moduleInputTypes, const EmitErrorFn &emitError)
Verify that the list of inputs of the instance and the module match in terms of length,...
ArrayAttr updateName(ArrayAttr oldNames, size_t i, StringAttr name)
Change the name at the specified index of the.
LogicalResult verifyReferencedModule(Operation *instanceOp, SymbolTableCollection &symbolTable, mlir::FlatSymbolRefAttr moduleName, Operation *&module)
Verify that the instance refers to a valid HW module.
void getAsmResultNames(OpAsmSetValueNameFn setNameFn, StringRef instanceName, ArrayAttr resultNames, ValueRange results)
Suggest a name for each result value based on the saved result names attribute.
LogicalResult verifyParameters(ArrayAttr parameters, ArrayAttr moduleParameters, const EmitErrorFn &emitError)
Verify that the parameter lists of the instance and the module match in terms of length,...
FunctionType getModuleType(Operation *module)
Return the signature for the specified module as a function type.
LogicalResult checkParameterInContext(Attribute value, Operation *module, Operation *usingOp, bool disallowParamRefs=false)
Check parameter specified by value to see if it is valid within the scope of the specified module mod...
enum PEO uint32_t mlir::FailureOr< mlir::Type > evaluateParametricType(mlir::Location loc, mlir::ArrayAttr parameters, mlir::Type type)
Returns a resolved version of 'type' wherein any parameter reference has been evaluated based on the ...
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn