Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIRRTL] Treat blackboxes in layers as "testbench" #6881

Merged
merged 2 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 8 additions & 5 deletions lib/Dialect/FIRRTL/Transforms/BlackBoxReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,6 @@ StringAttr BlackBoxReaderPass::loadFile(Operation *op, StringRef inputPath,
OutputFileInfo BlackBoxReaderPass::getOutputFile(Operation *origOp,
StringAttr fileNameAttr,
bool isCover) {
// If the original operation has a specified output file that is not a
// directory, then just use that.
auto outputFile = origOp->getAttrOfType<hw::OutputFileAttr>("output_file");
if (outputFile && !outputFile.isDirectory()) {
return {outputFile.getFilename(), Priority::TargetDir,
Expand All @@ -413,16 +411,19 @@ OutputFileInfo BlackBoxReaderPass::getOutputFile(Operation *origOp,
auto ext = llvm::sys::path::extension(fileName);
bool exclude = (ext == ".h" || ext == ".vh" || ext == ".svh");
auto outDir = std::make_pair(targetDir, Priority::TargetDir);
// If the original operation has a specified output file that is not a
// directory, then just use that.
if (outputFile)
outDir = {outputFile.getFilename(), Priority::Explicit};
// In order to output into the testbench directory, we need to have a
// testbench dir annotation, not have a blackbox target directory annotation
// (or one set to the current directory), have a DUT annotation, and the
// module needs to be in or under the DUT.
if (!testBenchDir.empty() && targetDir.equals(".") && dut && !isDut(origOp))
else if (!testBenchDir.empty() && targetDir.equals(".") && dut &&
!isDut(origOp))
outDir = {testBenchDir, Priority::TestBench};
else if (isCover)
outDir = {coverDir, Priority::Verification};
else if (outputFile)
outDir = {outputFile.getFilename(), Priority::Explicit};

// If targetDir is not set explicitly and this is a testbench module, then
// update the targetDir to be the "../testbench".
Expand All @@ -448,6 +449,8 @@ bool BlackBoxReaderPass::isDut(Operation *module) {
bool anyParentIsDut = false;
if (node)
for (auto *u : node->uses()) {
if (cast<InstanceOp>(u->getInstance().getOperation()).getLowerToBind())
return false;
// Recursively check the parents.
auto dut = isDut(u->getInstance()->getParentOfType<FModuleOp>());
// Cache the result.
Expand Down
76 changes: 69 additions & 7 deletions test/firtool/blackbox-directories.fir
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
;
; The test enumerates all possible combinations for a simple design that
; consists of a TestHarness top module, a DUT instantiated by the TestHarness,
; and a Grand Central companion module inside the DUT. This is summarized by
; the table below. A one in the "T" column indicates it is instantiated by the
; TestHarness, a one in the "D" column indicates it is instantiated by the DUT,
; and a one in the "G" column indicates it is instantiated by the Grand Central
; companion.
; and a Grand Central companion module inside the DUT. Additionally, both the
; DUT and the TestHarness have layerblocks of the Verification color. This is
; summarized by the table below. A one ("1") in the "T" column indicates it is
; instantiated by the TestHarness, a one in the "D" column indicates it is
; instantiated by the DUT, and a one in the "G" column indicates it is
; instantiated by the Grand Central companion. A zero ("0") indicates it is not
; instantiated. An "L" indicates that it is instantiated in a layer in that
; module.
;
; T D G Output
; --------------------
Expand All @@ -22,6 +25,9 @@
; Quz 1 0 1 gct/Quz.sv
; Corge 1 1 0 Corge.sv
; Grault 1 1 1 Grault
; Bazola 0 L 0 testbench/Bazola.sv
; Ztesch L 0 0 testbench/Ztesch.sv
; Thud L L 0 testbench/Thud.sv
;
; CHECK-LABEL: module DUT
;
Expand All @@ -32,8 +38,11 @@
; CHECK: FILE "gct{{[/\]}}Quz.sv"
; CHECK: FILE ".{{[/\]}}Corge.sv"
; CHECK: FILE ".{{[/\]}}Grault.sv"
; CHECK: FILE "testbench{{[/\]}}Bazola.sv"
; CHECK: FILE "testbench{{[/\]}}Ztesch.sv"
; CHECK: FILE "testbench{{[/\]}}Thud.sv"

FIRRTL version 3.0.0
FIRRTL version 4.0.0
circuit TestHarness: %[[
{
"class": "sifive.enterprise.grandcentral.ViewAnnotation",
Expand Down Expand Up @@ -148,8 +157,34 @@ circuit TestHarness: %[[
"target": "~TestHarness|BlackBox_Grault_GCT",
"name": "Grault.sv",
"text": "module Grault #(parameter X=hello)(output a);\nendmodule"
},
{
"class": "firrtl.transforms.BlackBoxInlineAnno",
"target": "~TestHarness|BlackBox_Bazola_DUT",
"name": "Bazola.sv",
"text": "module Bazola #(parameter X=hello)(output a);\nendmodule"
},
{
"class": "firrtl.transforms.BlackBoxInlineAnno",
"target": "~TestHarness|BlackBox_Ztesch_TestHarness",
"name": "Ztesch.sv",
"text": "module Ztesch #(parameter X=hello)(output a);\nendmodule"
},
{
"class": "firrtl.transforms.BlackBoxInlineAnno",
"target": "~TestHarness|BlackBox_Thud_TestHarness",
"name": "Thud.sv",
"text": "module Thud #(parameter X=hello)(output a);\nendmodule"
},
{
"class": "firrtl.transforms.BlackBoxInlineAnno",
"target": "~TestHarness|BlackBox_Thud_DUT",
"name": "Thud.sv",
"text": "module Thud #(parameter X=hello)(output a);\nendmodule"
}
]]
layer Verification, bind:

extmodule BlackBox_Foo_GCT:
output a: UInt<1>
defname = Foo
Expand Down Expand Up @@ -205,7 +240,26 @@ circuit TestHarness: %[[
defname = Grault
parameter X = "Grault_GCT"

module TestHarness:
extmodule BlackBox_Bazola_DUT:
output a: UInt<1>
defname = Bazola
parameter X = "Bazola_TestHarness"

extmodule BlackBox_Ztesch_TestHarness:
output a: UInt<1>
defname = Ztesch
parameter X = "Ztesch_TestHarness"

extmodule BlackBox_Thud_TestHarness:
output a: UInt<1>
defname = Thud
parameter X = "Thud_TestHarness"
extmodule BlackBox_Thud_DUT:
output a: UInt<1>
defname = Thud
parameter X = "Thud_DUT"

public module TestHarness:

inst dut of DUT

Expand All @@ -214,6 +268,10 @@ circuit TestHarness: %[[
inst blackBox_Corge_TestHarness of BlackBox_Corge_TestHarness
inst blackBox_Grault_TestHarness of BlackBox_Grault_TestHarness

layerblock Verification:
inst blackBox_Ztesch_TestHarness of BlackBox_Ztesch_TestHarness
inst blackBox_Thud_TestHarness of BlackBox_Thud_TestHarness

module DUT:

wire a: UInt<1>
Expand All @@ -226,6 +284,10 @@ circuit TestHarness: %[[
inst blackBox_Corge_DUT of BlackBox_Corge_DUT
inst blackBox_Grault_DUT of BlackBox_Grault_DUT

layerblock Verification:
inst blackBox_Bazola_DUT of BlackBox_Bazola_DUT
inst blackBox_Thud_DUT of BlackBox_Thud_DUT

module GrandCentral:

inst blackBox_Foo_GCT of BlackBox_Foo_GCT
Expand Down