Skip to content

Commit f3e5bc9

Browse files
[Arc] Add option to observe registers and memories (#6477)
Instead of always making registers and memories observable for the user, add dedicated `--observe-registers` and `--observe-memories` options to `arcilator`. These allow the user to indicate whether they are interested in observing or register and memory state. If these options are set to false, don't attach "name" or "names" attributes to states and memories, such that other parts of the pipeline have a chance to delete unnecessary state.
1 parent faf4dba commit f3e5bc9

File tree

8 files changed

+72
-8
lines changed

8 files changed

+72
-8
lines changed

include/circt/Conversion/ConvertToArcs.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@
1313
#include <memory>
1414

1515
namespace circt {
16-
std::unique_ptr<OperationPass<ModuleOp>> createConvertToArcsPass();
16+
17+
#define GEN_PASS_DECL_CONVERTTOARCS
18+
#include "circt/Conversion/Passes.h.inc"
19+
20+
std::unique_ptr<OperationPass<ModuleOp>>
21+
createConvertToArcsPass(const ConvertToArcsOptions &options = {});
22+
1723
} // namespace circt
1824

1925
#endif // CIRCT_CONVERSION_CONVERTTOARCS_H

include/circt/Conversion/Passes.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,10 @@ def ConvertToArcs : Pass<"convert-to-arcs", "mlir::ModuleOp"> {
614614
}];
615615
let constructor = "circt::createConvertToArcsPass()";
616616
let dependentDialects = ["circt::arc::ArcDialect"];
617+
let options = [
618+
Option<"tapRegisters", "tap-registers", "bool", "true",
619+
"Make registers observable">,
620+
];
617621
}
618622

619623
//===----------------------------------------------------------------------===//

include/circt/Dialect/Arc/ArcPasses.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ def InferMemories : Pass<"arc-infer-memories", "mlir::ModuleOp"> {
7474
let options = [
7575
Option<"tapPorts", "tap-ports", "bool", "true",
7676
"Make memory ports observable">,
77+
Option<"tapMemories", "tap-memories", "bool", "true",
78+
"Make memory contents observable">,
7779
];
7880
}
7981

lib/Conversion/ConvertToArcs/ConvertToArcs.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ struct Converter {
5959

6060
/// The arc uses generated by `extractArcs`.
6161
SmallVector<StateOp> arcUses;
62+
63+
/// Whether registers should be made observable by assigning their arcs a
64+
/// "name" attribute.
65+
bool tapRegisters;
6266
};
6367
} // namespace
6468

@@ -327,7 +331,7 @@ LogicalResult Converter::absorbRegs(HWModuleOp module) {
327331
"had a reset.");
328332
arc.getResetMutable().assign(reset);
329333
}
330-
if (llvm::any_of(absorbedNames, [](auto name) {
334+
if (tapRegisters && llvm::any_of(absorbedNames, [](auto name) {
331335
return !name.template cast<StringAttr>().getValue().empty();
332336
}))
333337
arc->setAttr("names", ArrayAttr::get(module.getContext(), absorbedNames));
@@ -399,7 +403,7 @@ LogicalResult Converter::absorbRegs(HWModuleOp module) {
399403
auto reset = std::get<1>(clockAndResetAndOp);
400404
if (reset)
401405
arcOp.getResetMutable().assign(reset);
402-
if (llvm::any_of(names, [](auto name) {
406+
if (tapRegisters && llvm::any_of(names, [](auto name) {
403407
return !name.template cast<StringAttr>().getValue().empty();
404408
}))
405409
arcOp->setAttr("names", builder.getArrayAttr(names));
@@ -420,16 +424,25 @@ LogicalResult Converter::absorbRegs(HWModuleOp module) {
420424
// Pass Infrastructure
421425
//===----------------------------------------------------------------------===//
422426

427+
namespace circt {
428+
#define GEN_PASS_DEF_CONVERTTOARCS
429+
#include "circt/Conversion/Passes.h.inc"
430+
} // namespace circt
431+
423432
namespace {
424-
struct ConvertToArcsPass : public ConvertToArcsBase<ConvertToArcsPass> {
433+
struct ConvertToArcsPass : public impl::ConvertToArcsBase<ConvertToArcsPass> {
434+
using ConvertToArcsBase::ConvertToArcsBase;
435+
425436
void runOnOperation() override {
426437
Converter converter;
438+
converter.tapRegisters = tapRegisters;
427439
if (failed(converter.run(getOperation())))
428440
signalPassFailure();
429441
}
430442
};
431443
} // namespace
432444

433-
std::unique_ptr<OperationPass<ModuleOp>> circt::createConvertToArcsPass() {
434-
return std::make_unique<ConvertToArcsPass>();
445+
std::unique_ptr<OperationPass<ModuleOp>>
446+
circt::createConvertToArcsPass(const ConvertToArcsOptions &options) {
447+
return std::make_unique<ConvertToArcsPass>(options);
435448
}

lib/Dialect/Arc/Transforms/InferMemories.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ void InferMemoriesPass::runOnOperation() {
116116
}
117117
auto memType = MemoryType::get(&getContext(), depth, wordType, addressTy);
118118
auto memOp = builder.create<MemoryOp>(memType);
119-
if (!instOp.getInstanceName().empty())
119+
if (tapMemories && !instOp.getInstanceName().empty())
120120
memOp->setAttr("name", instOp.getInstanceNameAttr());
121121

122122
unsigned argIdx = 0;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: circt-opt %s --convert-to-arcs="tap-registers=0" | FileCheck %s --check-prefixes=CHECK,CHECK-TAP-OFF
2+
// RUN: circt-opt %s --convert-to-arcs="tap-registers=1" | FileCheck %s --check-prefixes=CHECK,CHECK-TAP-ON
3+
4+
// CHECK-LABEL: hw.module @Trivial(
5+
hw.module @Trivial(in %clock: !seq.clock, in %i0: i4, in %reset: i1, out o0: i4) {
6+
// CHECK: arc.state {{@.+}}(%i0) clock %clock lat 1
7+
// CHECK-TAP-OFF-NOT: names = ["foo"]
8+
// CHECK-TAP-ON: names = ["foo"]
9+
%foo = seq.compreg %i0, %clock : i4
10+
hw.output %foo : i4
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: circt-opt %s --arc-infer-memories="tap-memories=0" | FileCheck %s --check-prefixes=CHECK,CHECK-TAP-OFF
2+
// RUN: circt-opt %s --arc-infer-memories="tap-memories=1" | FileCheck %s --check-prefixes=CHECK,CHECK-TAP-ON
3+
4+
// CHECK-LABEL: hw.module @TestMemory(
5+
hw.module @TestMemory(in %clock: !seq.clock, in %addr: i10, in %enable: i1, in %data: i8) {
6+
// CHECK: arc.memory <1024 x i8, i10>
7+
// CHECK-TAP-OFF-NOT: name = "foo"
8+
// CHECK-TAP-ON: name = "foo"
9+
hw.instance "foo" @Memory(W0_addr: %addr: i10, W0_en: %enable: i1, W0_clk: %clock: !seq.clock, W0_data: %data: i8) -> ()
10+
}
11+
12+
hw.generator.schema @FIRRTLMem, "FIRRTL_Memory", ["depth", "numReadPorts", "numWritePorts", "numReadWritePorts", "readLatency", "writeLatency", "width", "maskGran", "readUnderWrite", "writeUnderWrite", "writeClockIDs"]
13+
hw.module.generated @Memory, @FIRRTLMem(in %W0_addr: i10, in %W0_en: i1, in %W0_clk: !seq.clock, in %W0_data: i8) attributes {depth = 1024 : i64, maskGran = 8 : ui32, numReadPorts = 0 : ui32, numReadWritePorts = 0 : ui32, numWritePorts = 1 : ui32, readLatency = 1 : ui32, readUnderWrite = 0 : ui32, width = 8 : ui32, writeClockIDs = [], writeLatency = 1 : ui32, writeUnderWrite = 1 : i32}
14+

tools/arcilator/arcilator.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ static cl::opt<bool>
8989
cl::desc("Make values with `sv.namehint` observable"),
9090
cl::init(false), cl::cat(mainCategory));
9191

92+
static cl::opt<bool> observeRegisters("observe-registers",
93+
cl::desc("Make all registers observable"),
94+
cl::init(false), cl::cat(mainCategory));
95+
96+
static cl::opt<bool>
97+
observeMemories("observe-memories",
98+
cl::desc("Make all memory contents observable"),
99+
cl::init(false), cl::cat(mainCategory));
100+
92101
static cl::opt<std::string> stateFile("state-file", cl::desc("State file"),
93102
cl::value_desc("filename"), cl::init(""),
94103
cl::cat(mainCategory));
@@ -200,6 +209,7 @@ static void populatePipeline(PassManager &pm) {
200209
{
201210
arc::InferMemoriesOptions opts;
202211
opts.tapPorts = observePorts;
212+
opts.tapMemories = observeMemories;
203213
pm.addPass(arc::createInferMemoriesPass(opts));
204214
}
205215
pm.addPass(createCSEPass());
@@ -208,7 +218,11 @@ static void populatePipeline(PassManager &pm) {
208218
// Restructure the input from a `hw.module` hierarchy to a collection of arcs.
209219
if (untilReached(UntilArcConversion))
210220
return;
211-
pm.addPass(createConvertToArcsPass());
221+
{
222+
ConvertToArcsOptions opts;
223+
opts.tapRegisters = observeRegisters;
224+
pm.addPass(createConvertToArcsPass(opts));
225+
}
212226
if (shouldDedup)
213227
pm.addPass(arc::createDedupPass());
214228
pm.addPass(arc::createInlineModulesPass());

0 commit comments

Comments
 (0)