[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> std::unique_ptr<mlir::Pass>
createBlackBoxReaderPass(std::optional<mlir::StringRef> inputPrefix = {}); 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(); 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 constructor = "circt::firrtl::createGrandCentralPass()";
let dependentDialects = ["circt::sv::SVDialect", "circt::hw::HWDialect"]; 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 = [ let statistics = [
Statistic<"numViews", "num-views-created", Statistic<"numViews", "num-views-created",
"Number of top-level SystemVerilog interfaces that were 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 /// instantiate interfaces and to generate the "mappings" file that produces
/// cross-module references (XMRs) to drive the interface. /// cross-module references (XMRs) to drive the interface.
struct GrandCentralPass : public GrandCentralBase<GrandCentralPass> { struct GrandCentralPass : public GrandCentralBase<GrandCentralPass> {
GrandCentralPass(bool instantiateCompanionOnlyFlag) {
instantiateCompanionOnly = instantiateCompanionOnlyFlag;
}
void runOnOperation() override; void runOnOperation() override;
private: private:
@ -1116,7 +1120,8 @@ parseAugmentedType(ApplyState &state, DictionaryAttr augmentedType,
NamedAttrList attrs; NamedAttrList attrs;
attrs.append("class", classAttr); attrs.append("class", classAttr);
attrs.append("name", name); 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) if (!value)
return std::nullopt; return std::nullopt;
attrs.append("value", value); attrs.append("value", value);
@ -1890,7 +1895,11 @@ void GrandCentralPass::runOnOperation() {
return true; 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( (*instance)->setAttr(
"output_file", "output_file",
hw::OutputFileAttr::getFromFilename( 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 // Now, iterate over the worklist of interface-encoding annotations to create
// the interface and all its sub-interfaces (interfaces that it instantiates), // the interface and all its sub-interfaces (interfaces that it instantiates),
// instantiate the top-level interface, and generate a "mappings file" that // instantiate the top-level interface, and generate a "mappings file" that
@ -2250,6 +2267,7 @@ void GrandCentralPass::runOnOperation() {
// Pass Creation // Pass Creation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
std::unique_ptr<mlir::Pass> circt::firrtl::createGrandCentralPass() { std::unique_ptr<mlir::Pass>
return std::make_unique<GrandCentralPass>(); circt::firrtl::createGrandCentralPass(bool instantiateCompanionOnly) {
return std::make_unique<GrandCentralPass>(instantiateCompanionOnly);
} }