-
Notifications
You must be signed in to change notification settings - Fork 437
Expand file tree
/
Copy pathSVTraceIVerilog.cpp
More file actions
80 lines (70 loc) · 2.61 KB
/
SVTraceIVerilog.cpp
File metadata and controls
80 lines (70 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//===- SVTraceIVerilog.cpp - Generator Callout Pass -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass adds the necessary instrumentation to a HWModule to trigger
// tracing in an iverilog simulation.
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/HW/HWInstanceGraph.h"
#include "circt/Dialect/HW/HWOps.h"
#include "circt/Dialect/SV/SVOps.h"
#include "circt/Dialect/SV/SVPasses.h"
#include "mlir/IR/Builders.h"
#include "mlir/Pass/Pass.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
namespace circt {
namespace sv {
#define GEN_PASS_DEF_SVTRACEIVERILOG
#include "circt/Dialect/SV/SVPasses.h.inc"
} // namespace sv
} // namespace circt
using namespace circt;
using namespace sv;
using namespace hw;
//===----------------------------------------------------------------------===//
// SVTraceIVerilogPass
//===----------------------------------------------------------------------===//
namespace {
struct SVTraceIVerilogPass
: public circt::sv::impl::SVTraceIVerilogBase<SVTraceIVerilogPass> {
using Base::Base;
void runOnOperation() override;
};
} // end anonymous namespace
void SVTraceIVerilogPass::runOnOperation() {
mlir::ModuleOp mod = getOperation();
if (topOnly) {
auto &graph = getAnalysis<InstanceGraph>();
auto topLevelNodes = graph.getInferredTopLevelNodes();
if (failed(topLevelNodes) || topLevelNodes->size() != 1) {
mod.emitError("Expected exactly one top level node");
return signalPassFailure();
}
hw::HWModuleOp top =
dyn_cast_or_null<hw::HWModuleOp>(*topLevelNodes->front()->getModule());
if (!top) {
mod.emitError("top module is not a HWModuleOp");
return signalPassFailure();
}
targetModuleName.setValue(top.getName().str());
}
for (auto hwmod : mod.getOps<hw::HWModuleOp>()) {
if (!targetModuleName.empty() &&
hwmod.getName() != targetModuleName.getValue())
continue;
OpBuilder builder(hwmod.getBodyBlock(), hwmod.getBodyBlock()->begin());
std::string traceMacro;
llvm::raw_string_ostream ss(traceMacro);
auto modName = hwmod.getName();
ss << "initial begin\n $dumpfile (\"" << directoryName.getValue()
<< modName << ".vcd\");\n $dumpvars (0, " << modName
<< ");\n #1;\nend\n";
sv::VerbatimOp::create(builder, hwmod.getLoc(), ss.str());
}
}