[ImportVerilog] Fix single unit preprocessor option (#6682)

Make `ImportVerilog` honor the `singleUnit` option by either adding all
source files to a single preprocessor (single unit), or creating a fresh
preprocessor for every single file (multiple units).

Fixes #6680.
This commit is contained in:
Fabian Schuiki 2024-02-09 09:15:43 -08:00 committed by GitHub
parent 6dd88f8ee1
commit 512cc7a817
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 7 deletions

View File

@ -244,13 +244,10 @@ LogicalResult ImportContext::importVerilog(ModuleOp module) {
/// stream.
LogicalResult ImportContext::preprocessVerilog(llvm::raw_ostream &os) {
auto parseTimer = ts.nest("Verilog preprocessing");
for (auto &buffer : driver.buffers) {
slang::BumpAllocator alloc;
slang::Diagnostics diagnostics;
slang::parsing::Preprocessor preprocessor(
driver.sourceManager, alloc, diagnostics, driver.createOptionBag());
preprocessor.pushSource(buffer);
// Run the preprocessor to completion across all sources previously added with
// `pushSource`, report diagnostics, and print the output.
auto preprocessAndPrint = [&](slang::parsing::Preprocessor &preprocessor) {
slang::syntax::SyntaxPrinter output;
output.setIncludeComments(false);
while (true) {
@ -260,14 +257,44 @@ LogicalResult ImportContext::preprocessVerilog(llvm::raw_ostream &os) {
break;
}
for (auto &diag : diagnostics) {
for (auto &diag : preprocessor.getDiagnostics()) {
if (diag.isError()) {
driver.diagEngine.issue(diag);
return failure();
}
}
os << output.str();
return success();
};
// Depending on whether the single-unit option is set, either add all source
// files to a single preprocessor such that they share define macros and
// directives, or create a separate preprocessor for each, such that each
// source file is in its own compilation unit.
auto optionBag = driver.createOptionBag();
if (driver.options.singleUnit == true) {
slang::BumpAllocator alloc;
slang::Diagnostics diagnostics;
slang::parsing::Preprocessor preprocessor(driver.sourceManager, alloc,
diagnostics, optionBag);
// Sources have to be pushed in reverse, as they form a stack in the
// preprocessor. Last pushed source is processed first.
for (auto &buffer : slang::make_reverse_range(driver.buffers))
preprocessor.pushSource(buffer);
if (failed(preprocessAndPrint(preprocessor)))
return failure();
} else {
for (auto &buffer : driver.buffers) {
slang::BumpAllocator alloc;
slang::Diagnostics diagnostics;
slang::parsing::Preprocessor preprocessor(driver.sourceManager, alloc,
diagnostics, optionBag);
preprocessor.pushSource(buffer);
if (failed(preprocessAndPrint(preprocessor)))
return failure();
}
}
return success();
}

View File

@ -0,0 +1,19 @@
// RUN: split-file %s %t
// RUN: circt-verilog %t/a.sv %t/b.sv -E | FileCheck %s --check-prefixes=CHECK-MULTI-UNIT
// RUN: circt-verilog %t/a.sv %t/b.sv -E --single-unit | FileCheck %s --check-prefixes=CHECK-SINGLE-UNIT
// REQUIRES: slang
// CHECK-MULTI-UNIT: import hello::undefined;
// CHECK-SINGLE-UNIT: import hello::defined;
//--- a.sv
`define HELLO
//--- b.sv
`ifdef HELLO
import hello::defined;
`else
import hello::undefined;
`endif