mirror of https://github.com/llvm/circt.git
[FIRRTL] Add helpers for the implementation of FIRRTL instance-like ops (#6484)
This commit is contained in:
parent
e6b326ea49
commit
79baf6c364
|
@ -0,0 +1,33 @@
|
|||
//===- FIRRTLInstanceImplementation.h - Instance-like utilities -*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides utility functions for implementing FIRRTL instance-like
|
||||
// operations, in particular, parsing, and printing common to instance-like
|
||||
// operations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CIRCT_DIALECT_FIRRTL_FIRRTLINSTANCEIMPLEMENTATION_H
|
||||
#define CIRCT_DIALECT_FIRRTL_FIRRTLINSTANCEIMPLEMENTATION_H
|
||||
|
||||
#include "circt/Support/LLVM.h"
|
||||
|
||||
namespace circt {
|
||||
namespace firrtl {
|
||||
namespace instance_like_impl {
|
||||
|
||||
/// Verify that the instance refers to a valid FIRRTL module.
|
||||
LogicalResult verifyReferencedModule(Operation *instanceOp,
|
||||
SymbolTableCollection &symbolTable,
|
||||
mlir::FlatSymbolRefAttr moduleName);
|
||||
|
||||
} // namespace instance_like_impl
|
||||
} // namespace firrtl
|
||||
} // namespace circt
|
||||
|
||||
#endif // CIRCT_DIALECT_FIRRTL_FIRRTLINSTANCEIMPLEMENTATION_H
|
|
@ -1,4 +1,4 @@
|
|||
//===- InstanceImplementation.h - Instance-like Op utilities ----*- C++ -*-===//
|
||||
//===- HWInstanceImplementation.h - Instance-like Op utilities --*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -12,8 +12,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CIRCT_DIALECT_HW_INSTANCEIMPLEMENTATION_H
|
||||
#define CIRCT_DIALECT_HW_INSTANCEIMPLEMENTATION_H
|
||||
#ifndef CIRCT_DIALECT_HW_HWINSTANCEIMPLEMENTATION_H
|
||||
#define CIRCT_DIALECT_HW_HWINSTANCEIMPLEMENTATION_H
|
||||
|
||||
#include "circt/Dialect/HW/PortImplementation.h"
|
||||
#include "circt/Support/LLVM.h"
|
||||
|
@ -105,4 +105,4 @@ SmallVector<PortInfo> getPortList(Operation *instanceOp);
|
|||
} // namespace hw
|
||||
} // namespace circt
|
||||
|
||||
#endif // CIRCT_DIALECT_HW_INSTANCEIMPLEMENTATION_H
|
||||
#endif // CIRCT_DIALECT_HW_HWINSTANCEIMPLEMENTATION_H
|
|
@ -13,9 +13,9 @@
|
|||
#ifndef CIRCT_DIALECT_HW_HWOPINTERFACES_H
|
||||
#define CIRCT_DIALECT_HW_HWOPINTERFACES_H
|
||||
|
||||
#include "circt/Dialect/HW/HWInstanceImplementation.h"
|
||||
#include "circt/Dialect/HW/HWTypes.h"
|
||||
#include "circt/Dialect/HW/InnerSymbolTable.h"
|
||||
#include "circt/Dialect/HW/InstanceImplementation.h"
|
||||
#include "circt/Support/InstanceGraphInterface.h"
|
||||
#include "circt/Support/LLVM.h"
|
||||
#include "mlir/IR/OpDefinition.h"
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
#ifndef CIRCT_DIALECT_SYSTEMC_SYSTEMCOPS_H
|
||||
#define CIRCT_DIALECT_SYSTEMC_SYSTEMCOPS_H
|
||||
|
||||
#include "circt/Dialect/HW/HWInstanceImplementation.h"
|
||||
#include "circt/Dialect/HW/HWOps.h"
|
||||
#include "circt/Dialect/HW/InstanceImplementation.h"
|
||||
#include "circt/Dialect/SystemC/SystemCAttributes.h"
|
||||
#include "circt/Dialect/SystemC/SystemCDialect.h"
|
||||
#include "circt/Dialect/SystemC/SystemCOpInterfaces.h"
|
||||
|
|
|
@ -8,6 +8,7 @@ set(CIRCT_FIRRTL_Sources
|
|||
FIRRTLFieldSource.cpp
|
||||
FIRRTLFolds.cpp
|
||||
FIRRTLInstanceGraph.cpp
|
||||
FIRRTLInstanceImplementation.cpp
|
||||
FIRRTLOpInterfaces.cpp
|
||||
FIRRTLOps.cpp
|
||||
FIRRTLTypes.cpp
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
//===- FIRRTLInstanceImplementation.cpp - Utilities for instance-like ops -===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLInstanceImplementation.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLOps.h"
|
||||
|
||||
using namespace circt;
|
||||
using namespace circt::firrtl;
|
||||
|
||||
LogicalResult
|
||||
instance_like_impl::verifyReferencedModule(Operation *instanceOp,
|
||||
SymbolTableCollection &symbolTable,
|
||||
mlir::FlatSymbolRefAttr moduleName) {
|
||||
auto module = instanceOp->getParentOfType<FModuleOp>();
|
||||
auto referencedModule =
|
||||
symbolTable.lookupNearestSymbolFrom<FModuleLike>(instanceOp, moduleName);
|
||||
if (!referencedModule) {
|
||||
return instanceOp->emitOpError("invalid symbol reference");
|
||||
}
|
||||
|
||||
// Check this is not a class.
|
||||
if (isa<ClassOp /* ClassLike */>(referencedModule))
|
||||
return instanceOp->emitOpError("must instantiate a module not a class")
|
||||
.attachNote(referencedModule.getLoc())
|
||||
<< "class declared here";
|
||||
|
||||
// Check that this instance doesn't recursively instantiate its wrapping
|
||||
// module.
|
||||
if (referencedModule == module) {
|
||||
auto diag = instanceOp->emitOpError()
|
||||
<< "is a recursive instantiation of its containing module";
|
||||
return diag.attachNote(module.getLoc())
|
||||
<< "containing module declared here";
|
||||
}
|
||||
|
||||
// Small helper add a note to the original declaration.
|
||||
auto emitNote = [&](InFlightDiagnostic &&diag) -> InFlightDiagnostic && {
|
||||
diag.attachNote(referencedModule->getLoc())
|
||||
<< "original module declared here";
|
||||
return std::move(diag);
|
||||
};
|
||||
|
||||
// Check that all the attribute arrays are the right length up front. This
|
||||
// lets us safely use the port name in error messages below.
|
||||
size_t numResults = instanceOp->getNumResults();
|
||||
size_t numExpected = referencedModule.getNumPorts();
|
||||
if (numResults != numExpected) {
|
||||
return emitNote(instanceOp->emitOpError()
|
||||
<< "has a wrong number of results; expected " << numExpected
|
||||
<< " but got " << numResults);
|
||||
}
|
||||
auto portDirections =
|
||||
instanceOp->getAttrOfType<IntegerAttr>("portDirections");
|
||||
if (portDirections.getValue().getBitWidth() != numExpected)
|
||||
return emitNote(
|
||||
instanceOp->emitOpError("the number of port directions should be "
|
||||
"equal to the number of results"));
|
||||
|
||||
auto portNames = instanceOp->getAttrOfType<ArrayAttr>("portNames");
|
||||
if (portNames.size() != numExpected)
|
||||
return emitNote(
|
||||
instanceOp->emitOpError("the number of port names should be "
|
||||
"equal to the number of results"));
|
||||
|
||||
auto portAnnotations =
|
||||
instanceOp->getAttrOfType<ArrayAttr>("portAnnotations");
|
||||
if (portAnnotations.size() != numExpected)
|
||||
return emitNote(
|
||||
instanceOp->emitOpError("the number of result annotations should be "
|
||||
"equal to the number of results"));
|
||||
|
||||
// Check that the port names match the referenced module.
|
||||
if (portNames != referencedModule.getPortNamesAttr()) {
|
||||
// We know there is an error, try to figure out whats wrong.
|
||||
auto moduleNames = referencedModule.getPortNamesAttr();
|
||||
// First compare the sizes:
|
||||
if (portNames.size() != moduleNames.size()) {
|
||||
return emitNote(instanceOp->emitOpError()
|
||||
<< "has a wrong number of directions; expected "
|
||||
<< moduleNames.size() << " but got " << portNames.size());
|
||||
}
|
||||
// Next check the values:
|
||||
for (size_t i = 0; i != numResults; ++i) {
|
||||
if (portNames[i] != moduleNames[i]) {
|
||||
return emitNote(instanceOp->emitOpError()
|
||||
<< "name for port " << i << " must be "
|
||||
<< moduleNames[i] << ", but got " << portNames[i]);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("should have found something wrong");
|
||||
}
|
||||
|
||||
// Check that the types match.
|
||||
for (size_t i = 0; i != numResults; i++) {
|
||||
auto resultType = instanceOp->getResult(i).getType();
|
||||
auto expectedType = referencedModule.getPortType(i);
|
||||
if (resultType != expectedType) {
|
||||
return emitNote(instanceOp->emitOpError()
|
||||
<< "result type for " << portNames[i] << " must be "
|
||||
<< expectedType << ", but got " << resultType);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the port directions are consistent with the referenced module's.
|
||||
if (portDirections != referencedModule.getPortDirectionsAttr()) {
|
||||
// We know there is an error, try to figure out whats wrong.
|
||||
auto moduleDirectionAttr = referencedModule.getPortDirectionsAttr();
|
||||
// First compare the sizes:
|
||||
auto expectedWidth = moduleDirectionAttr.getValue().getBitWidth();
|
||||
auto actualWidth = portDirections.getValue().getBitWidth();
|
||||
if (expectedWidth != actualWidth) {
|
||||
return emitNote(instanceOp->emitOpError()
|
||||
<< "has a wrong number of directions; expected "
|
||||
<< expectedWidth << " but got " << actualWidth);
|
||||
}
|
||||
// Next check the values.
|
||||
auto instanceDirs = direction::unpackAttribute(portDirections);
|
||||
auto moduleDirs = direction::unpackAttribute(moduleDirectionAttr);
|
||||
for (size_t i = 0; i != numResults; ++i) {
|
||||
if (instanceDirs[i] != moduleDirs[i]) {
|
||||
return emitNote(instanceOp->emitOpError()
|
||||
<< "direction for " << portNames[i] << " must be \""
|
||||
<< direction::toString(moduleDirs[i])
|
||||
<< "\", but got \""
|
||||
<< direction::toString(instanceDirs[i]) << "\"");
|
||||
}
|
||||
}
|
||||
llvm_unreachable("should have found something wrong");
|
||||
}
|
||||
|
||||
return success();
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
#include "circt/Dialect/FIRRTL/CHIRRTLDialect.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLAnnotations.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLAttributes.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLInstanceImplementation.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLTypes.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLUtils.h"
|
||||
#include "circt/Dialect/FIRRTL/FIRRTLVisitors.h"
|
||||
|
@ -2101,116 +2102,8 @@ InstanceOp::cloneAndInsertPorts(ArrayRef<std::pair<unsigned, PortInfo>> ports) {
|
|||
}
|
||||
|
||||
LogicalResult InstanceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
|
||||
auto module = (*this)->getParentOfType<FModuleOp>();
|
||||
auto referencedModule = symbolTable.lookupNearestSymbolFrom<FModuleLike>(
|
||||
*this, getModuleNameAttr());
|
||||
if (!referencedModule) {
|
||||
return emitOpError("invalid symbol reference");
|
||||
}
|
||||
|
||||
// Check this is not a class.
|
||||
if (isa<ClassOp /* ClassLike */>(referencedModule))
|
||||
return emitOpError("must instantiate a module not a class")
|
||||
.attachNote(referencedModule.getLoc())
|
||||
<< "class declared here";
|
||||
|
||||
// Check that this instance doesn't recursively instantiate its wrapping
|
||||
// module.
|
||||
if (referencedModule == module) {
|
||||
auto diag = emitOpError()
|
||||
<< "is a recursive instantiation of its containing module";
|
||||
return diag.attachNote(module.getLoc())
|
||||
<< "containing module declared here";
|
||||
}
|
||||
|
||||
// Small helper add a note to the original declaration.
|
||||
auto emitNote = [&](InFlightDiagnostic &&diag) -> InFlightDiagnostic && {
|
||||
diag.attachNote(referencedModule->getLoc())
|
||||
<< "original module declared here";
|
||||
return std::move(diag);
|
||||
};
|
||||
|
||||
// Check that all the attribute arrays are the right length up front. This
|
||||
// lets us safely use the port name in error messages below.
|
||||
size_t numResults = getNumResults();
|
||||
size_t numExpected = referencedModule.getNumPorts();
|
||||
if (numResults != numExpected) {
|
||||
return emitNote(emitOpError() << "has a wrong number of results; expected "
|
||||
<< numExpected << " but got " << numResults);
|
||||
}
|
||||
if (getPortDirections().getBitWidth() != numExpected)
|
||||
return emitNote(emitOpError("the number of port directions should be "
|
||||
"equal to the number of results"));
|
||||
if (getPortNames().size() != numExpected)
|
||||
return emitNote(emitOpError("the number of port names should be "
|
||||
"equal to the number of results"));
|
||||
if (getPortAnnotations().size() != numExpected)
|
||||
return emitNote(emitOpError("the number of result annotations should be "
|
||||
"equal to the number of results"));
|
||||
|
||||
// Check that the port names match the referenced module.
|
||||
if (getPortNamesAttr() != referencedModule.getPortNamesAttr()) {
|
||||
// We know there is an error, try to figure out whats wrong.
|
||||
auto instanceNames = getPortNames();
|
||||
auto moduleNames = referencedModule.getPortNamesAttr();
|
||||
// First compare the sizes:
|
||||
if (instanceNames.size() != moduleNames.size()) {
|
||||
return emitNote(emitOpError()
|
||||
<< "has a wrong number of directions; expected "
|
||||
<< moduleNames.size() << " but got "
|
||||
<< instanceNames.size());
|
||||
}
|
||||
// Next check the values:
|
||||
for (size_t i = 0; i != numResults; ++i) {
|
||||
if (instanceNames[i] != moduleNames[i]) {
|
||||
return emitNote(emitOpError()
|
||||
<< "name for port " << i << " must be "
|
||||
<< moduleNames[i] << ", but got " << instanceNames[i]);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("should have found something wrong");
|
||||
}
|
||||
|
||||
// Check that the types match.
|
||||
for (size_t i = 0; i != numResults; i++) {
|
||||
auto resultType = getResult(i).getType();
|
||||
auto expectedType = referencedModule.getPortType(i);
|
||||
if (resultType != expectedType) {
|
||||
return emitNote(emitOpError()
|
||||
<< "result type for " << getPortName(i) << " must be "
|
||||
<< expectedType << ", but got " << resultType);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the port directions are consistent with the referenced module's.
|
||||
if (getPortDirectionsAttr() != referencedModule.getPortDirectionsAttr()) {
|
||||
// We know there is an error, try to figure out whats wrong.
|
||||
auto instanceDirectionAttr = getPortDirectionsAttr();
|
||||
auto moduleDirectionAttr = referencedModule.getPortDirectionsAttr();
|
||||
// First compare the sizes:
|
||||
auto expectedWidth = moduleDirectionAttr.getValue().getBitWidth();
|
||||
auto actualWidth = instanceDirectionAttr.getValue().getBitWidth();
|
||||
if (expectedWidth != actualWidth) {
|
||||
return emitNote(emitOpError()
|
||||
<< "has a wrong number of directions; expected "
|
||||
<< expectedWidth << " but got " << actualWidth);
|
||||
}
|
||||
// Next check the values.
|
||||
auto instanceDirs = direction::unpackAttribute(instanceDirectionAttr);
|
||||
auto moduleDirs = direction::unpackAttribute(moduleDirectionAttr);
|
||||
for (size_t i = 0; i != numResults; ++i) {
|
||||
if (instanceDirs[i] != moduleDirs[i]) {
|
||||
return emitNote(emitOpError()
|
||||
<< "direction for " << getPortName(i) << " must be \""
|
||||
<< direction::toString(moduleDirs[i])
|
||||
<< "\", but got \""
|
||||
<< direction::toString(instanceDirs[i]) << "\"");
|
||||
}
|
||||
}
|
||||
llvm_unreachable("should have found something wrong");
|
||||
}
|
||||
|
||||
return success();
|
||||
return instance_like_impl::verifyReferencedModule(*this, symbolTable,
|
||||
getModuleNameAttr());
|
||||
}
|
||||
|
||||
StringRef InstanceOp::getInstanceName() { return getName(); }
|
||||
|
|
|
@ -4,12 +4,12 @@ set(CIRCT_HW_Sources
|
|||
HWAttributes.cpp
|
||||
HWDialect.cpp
|
||||
HWInstanceGraph.cpp
|
||||
HWInstanceImplementation.cpp
|
||||
HWModuleOpInterface.cpp
|
||||
HWOpInterfaces.cpp
|
||||
HWOps.cpp
|
||||
HWTypeInterfaces.cpp
|
||||
HWTypes.cpp
|
||||
InstanceImplementation.cpp
|
||||
ModuleImplementation.cpp
|
||||
InnerSymbolTable.cpp
|
||||
PortConverter.cpp
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "circt/Dialect/HW/InstanceImplementation.h"
|
||||
#include "circt/Dialect/HW/HWInstanceImplementation.h"
|
||||
#include "circt/Dialect/HW/HWOps.h"
|
||||
#include "circt/Dialect/HW/HWSymCache.h"
|
||||
|
|
@ -14,9 +14,9 @@
|
|||
#include "circt/Dialect/Comb/CombOps.h"
|
||||
#include "circt/Dialect/HW/CustomDirectiveImpl.h"
|
||||
#include "circt/Dialect/HW/HWAttributes.h"
|
||||
#include "circt/Dialect/HW/HWInstanceImplementation.h"
|
||||
#include "circt/Dialect/HW/HWSymCache.h"
|
||||
#include "circt/Dialect/HW/HWVisitors.h"
|
||||
#include "circt/Dialect/HW/InstanceImplementation.h"
|
||||
#include "circt/Dialect/HW/ModuleImplementation.h"
|
||||
#include "circt/Support/CustomDirectiveImpl.h"
|
||||
#include "circt/Support/Namespace.h"
|
||||
|
|
Loading…
Reference in New Issue