[FIRRTL] Add GrandCentral no-bind option

Add an option to the GrandCentral pass that will _not_ bind in the
companion module and will _not_ emit the SV interface instantiation.
This is done to enable GrandCentral collateral to be synthesizable.
This is motivated by making all the assertions that are frequently
crammed into a Grand Central companion as eligible for synthesis.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
This commit is contained in:
Schuyler Eldridge 2023-01-27 15:46:15 -05:00
parent 8784c8c377
commit acb8ba5c61
No known key found for this signature in database
GPG Key ID: 50C5E9936AAD536D
3 changed files with 28 additions and 5 deletions

View File

@ -102,7 +102,8 @@ std::unique_ptr<mlir::Pass> createPrintNLATablePass();
std::unique_ptr<mlir::Pass>
createBlackBoxReaderPass(std::optional<mlir::StringRef> inputPrefix = {});
std::unique_ptr<mlir::Pass> createGrandCentralPass();
std::unique_ptr<mlir::Pass>
createGrandCentralPass(bool instantiateCompanionOnly = false);
std::unique_ptr<mlir::Pass> createCheckCombCyclesPass();

View File

@ -420,6 +420,10 @@ def GrandCentral : Pass<"firrtl-grand-central", "CircuitOp"> {
let constructor = "circt::firrtl::createGrandCentralPass()";
let dependentDialects = ["circt::sv::SVDialect", "circt::hw::HWDialect"];
let options = [
Option<"instantiateCompanionOnly", "instantiate-companion-only", "bool", "false",
"Instantiate the companion without a bind and drop the interface">
];
let statistics = [
Statistic<"numViews", "num-views-created",
"Number of top-level SystemVerilog interfaces that were created">,

View File

@ -577,6 +577,10 @@ struct InterfaceElemsBuilder {
/// instantiate interfaces and to generate the "mappings" file that produces
/// cross-module references (XMRs) to drive the interface.
struct GrandCentralPass : public GrandCentralBase<GrandCentralPass> {
GrandCentralPass(bool instantiateCompanionOnlyFlag) {
instantiateCompanionOnly = instantiateCompanionOnlyFlag;
}
void runOnOperation() override;
private:
@ -1116,7 +1120,8 @@ parseAugmentedType(ApplyState &state, DictionaryAttr augmentedType,
NamedAttrList attrs;
attrs.append("class", classAttr);
attrs.append("name", name);
auto value = tryGetAs<Attribute>(augmentedType, root, "value", loc, clazz, path);
auto value =
tryGetAs<Attribute>(augmentedType, root, "value", loc, clazz, path);
if (!value)
return std::nullopt;
attrs.append("value", value);
@ -1890,7 +1895,11 @@ void GrandCentralPass::runOnOperation() {
return true;
}
(*instance)->setAttr("lowerToBind", builder.getUnitAttr());
// Lower the companion to a bind unless the user told us
// explicitly not to.
if (!instantiateCompanionOnly)
(*instance)->setAttr("lowerToBind", builder.getUnitAttr());
(*instance)->setAttr(
"output_file",
hw::OutputFileAttr::getFromFilename(
@ -2024,6 +2033,14 @@ void GrandCentralPass::runOnOperation() {
}
});
// If we are in "instantiateCompanionOnly" mode, then just exit here. We
// don't need to create the interface. This is a janky hack for situations
// where you want to synthesize assertion logic included in the companion, but
// don't want to have a dead interface hanging around (or have problems with
// tools understanding interfaces).
if (instantiateCompanionOnly)
return;
// Now, iterate over the worklist of interface-encoding annotations to create
// the interface and all its sub-interfaces (interfaces that it instantiates),
// instantiate the top-level interface, and generate a "mappings file" that
@ -2250,6 +2267,7 @@ void GrandCentralPass::runOnOperation() {
// Pass Creation
//===----------------------------------------------------------------------===//
std::unique_ptr<mlir::Pass> circt::firrtl::createGrandCentralPass() {
return std::make_unique<GrandCentralPass>();
std::unique_ptr<mlir::Pass>
circt::firrtl::createGrandCentralPass(bool instantiateCompanionOnly) {
return std::make_unique<GrandCentralPass>(instantiateCompanionOnly);
}