CIRCT 23.0.0git
Loading...
Searching...
No Matches
SVLoweringUtils.cpp
Go to the documentation of this file.
1//===- SVLoweringUtils.cpp - Shared helpers for SV lowering ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
13#include "mlir/IR/SymbolTable.h"
14
15using namespace circt;
16
17namespace {
18
19static constexpr StringLiteral kFileDescriptorGetterSymName =
20 "__circt_lib_logging::FileDescriptor::get";
21static constexpr StringLiteral kFileDescriptorFragmentSymName =
22 "CIRCT_LIB_LOGGING_FRAGMENT";
23static constexpr StringLiteral kFileDescriptorMacroName = "__CIRCT_LIB_LOGGING";
24
25StringAttr getFileDescriptorGetterSymName(MLIRContext *context) {
26 return StringAttr::get(context, kFileDescriptorGetterSymName);
27}
28
29StringAttr getFileDescriptorFragmentSymName(MLIRContext *context) {
30 return StringAttr::get(context, kFileDescriptorFragmentSymName);
31}
32
33Value createProceduralFileDescriptorGetterCallImpl(OpBuilder &builder,
34 Location loc,
35 Value fileName) {
36 assert(isa<hw::StringType>(fileName.getType()) &&
37 "expected !hw.string file name");
38 return sv::FuncCallProceduralOp::create(
39 builder, loc, TypeRange{builder.getIntegerType(32)},
40 getFileDescriptorGetterSymName(builder.getContext()),
41 ValueRange{fileName})
42 ->getResult(0);
43}
44
45} // namespace
46
47FlatSymbolRefAttr sv::getFileDescriptorFragmentRef(MLIRContext *context) {
48 return FlatSymbolRefAttr::get(::getFileDescriptorFragmentSymName(context));
49}
50
51void sv::emitFileDescriptorRuntime(Operation *fileScopeOp,
52 ImplicitLocOpBuilder &builder) {
53 assert(fileScopeOp && "expected file-level symbol table op");
54 assert(fileScopeOp->hasTrait<mlir::OpTrait::SymbolTable>() &&
55 "expected fileScopeOp to define a symbol table");
56
57 OpBuilder::InsertionGuard guard(builder);
58 if (builder.getInsertionBlock() == nullptr ||
59 builder.getInsertionBlock()->getParentOp() != fileScopeOp)
60 builder.setInsertionPointToEnd(&fileScopeOp->getRegion(0).front());
61
62 auto getterSymName = ::getFileDescriptorGetterSymName(builder.getContext());
63 auto fragmentSymName =
64 ::getFileDescriptorFragmentSymName(builder.getContext());
65 auto macroSymName = builder.getStringAttr(kFileDescriptorMacroName);
66 SymbolTable symbolTable(fileScopeOp);
67
68 auto emitGuard = [&](StringRef guard, llvm::function_ref<void(void)> body) {
69 sv::IfDefOp::create(
70 builder, guard, [] {}, body);
71 };
72
73 if (!symbolTable.lookup(getterSymName)) {
74 SmallVector<hw::ModulePort> ports;
75 ports.push_back({builder.getStringAttr("name"),
76 hw::StringType::get(builder.getContext()),
77 hw::ModulePort::Direction::Input});
78 ports.push_back({builder.getStringAttr("fd"), builder.getIntegerType(32),
79 hw::ModulePort::Direction::Output});
80
81 SmallVector<NamedAttribute> explicitReturnAttrs;
82 explicitReturnAttrs.push_back(
83 {builder.getStringAttr(sv::FuncOp::getExplicitlyReturnedAttrName()),
84 builder.getUnitAttr()});
85 SmallVector<Attribute> perArgumentAttrs = {
86 builder.getDictionaryAttr({}),
87 builder.getDictionaryAttr(explicitReturnAttrs)};
88
89 auto func =
90 sv::FuncOp::create(builder, getterSymName,
91 hw::ModuleType::get(builder.getContext(), ports),
92 builder.getArrayAttr(perArgumentAttrs), ArrayAttr(),
93 ArrayAttr(), getterSymName);
94 func.setPrivate();
95 symbolTable.insert(func);
96 }
97
98 if (!symbolTable.lookup(macroSymName))
99 symbolTable.insert(sv::MacroDeclOp::create(builder, macroSymName));
100
101 if (symbolTable.lookup(fragmentSymName))
102 return;
103
104 auto fragment = emit::FragmentOp::create(builder, fragmentSymName, [&] {
105 emitGuard("SYNTHESIS", [&]() {
106 emitGuard(kFileDescriptorMacroName, [&]() {
107 sv::VerbatimOp::create(builder, R"(// CIRCT Logging Library
108package __circt_lib_logging;
109 class FileDescriptor;
110 static int global_id [string];
111 static function int get(string name);
112 if (global_id.exists(name) == 32'h0) begin
113 global_id[name] = $fopen(name, "w");
114 if (global_id[name] == 32'h0)
115 $error("Failed to open file %s", name);
116 end
117 return global_id[name];
118 endfunction
119 endclass
120endpackage
121)");
122
123 sv::MacroDefOp::create(builder, macroSymName, "");
124 });
125 });
126 });
127 symbolTable.insert(fragment);
128}
129
130Value sv::createProceduralFileDescriptorGetterCall(OpBuilder &builder,
131 Location loc,
132 Value fileName) {
133 return createProceduralFileDescriptorGetterCallImpl(builder, loc, fileName);
134}
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.