CIRCT 20.0.0git
Loading...
Searching...
No Matches
ExportSystemC.cpp
Go to the documentation of this file.
1//===- ExportSystemC.cpp - SystemC Emitter --------------------------------===//
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//
9// This is the main SystemC emitter implementation.
10//
11//===----------------------------------------------------------------------===//
12
14#include "EmissionPrinter.h"
15#include "RegisterAllEmitters.h"
19#include "mlir/Dialect/EmitC/IR/EmitC.h"
20#include "mlir/IR/BuiltinOps.h"
21#include "mlir/Support/FileUtilities.h"
22#include "mlir/Tools/mlir-translate/Translation.h"
23#include "llvm/Support/FileSystem.h"
24#include "llvm/Support/Path.h"
25#include "llvm/Support/ToolOutputFile.h"
26#include <regex>
27
28using namespace circt;
29using namespace circt::ExportSystemC;
30
31#define DEBUG_TYPE "export-systemc"
32
33/// Helper to convert a file-path to a macro name that can be used to guard a
34/// header file.
35static std::string pathToMacroName(StringRef path) {
36 // Replace characters that represent a path hierarchy with underscore to match
37 // the usual header guard formatting.
38 auto str = std::regex_replace(path.upper(), std::regex("[\\\\./]"), "_");
39 // Remove invalid characters. TODO: a digit is not allowed as the first
40 // character, but not fixed here.
41 return std::regex_replace(str, std::regex("[^a-zA-Z0-9_$]+"), "");
42}
43
44/// Emits the given operation to a file represented by the passed ostream and
45/// file-path.
46static LogicalResult emitFile(ArrayRef<Operation *> operations,
47 StringRef filePath, raw_ostream &os) {
48 mlir::raw_indented_ostream ios(os);
49
50 ios << "// " << filePath << "\n";
51 std::string macroname = pathToMacroName(filePath);
52 ios << "#ifndef " << macroname << "\n";
53 ios << "#define " << macroname << "\n\n";
54
55 bool failed = false;
56
57 if (!operations.empty()) {
58 OpEmissionPatternSet opPatterns;
59 registerAllOpEmitters(opPatterns, operations[0]->getContext());
60 TypeEmissionPatternSet typePatterns;
61 registerAllTypeEmitters(typePatterns);
62 AttrEmissionPatternSet attrPatterns;
63 registerAllAttrEmitters(attrPatterns);
64 EmissionPrinter printer(ios, opPatterns, typePatterns, attrPatterns,
65 operations[0]->getLoc());
66
67 for (auto *op : operations)
68 printer.emitOp(op);
69
70 failed = printer.exitState().failed();
71 }
72
73 ios << "\n#endif // " << macroname << "\n\n";
74
75 return failure(failed);
76}
77
78//===----------------------------------------------------------------------===//
79// Unified and Split Emitter implementation
80//===----------------------------------------------------------------------===//
81
82LogicalResult ExportSystemC::exportSystemC(ModuleOp module,
83 llvm::raw_ostream &os) {
84 return emitFile({module}, "stdout.h", os);
85}
86
87LogicalResult ExportSystemC::exportSplitSystemC(ModuleOp module,
88 StringRef directory) {
89 // Collect all includes to emit them in every file.
90 SmallVector<Operation *> includes;
91 module->walk([&](mlir::emitc::IncludeOp op) { includes.push_back(op); });
92
93 for (Operation &op : module.getRegion().front()) {
94 if (auto symbolOp = dyn_cast<mlir::SymbolOpInterface>(op)) {
95 // Create the output directory if needed.
96 if (std::error_code error = llvm::sys::fs::create_directories(directory))
97 return module.emitError("cannot create output directory \"")
98 << directory << "\": " << error.message();
99
100 // Open or create the output file.
101 std::string fileName = symbolOp.getName().str() + ".h";
102 SmallString<128> filePath(directory);
103 llvm::sys::path::append(filePath, fileName);
104 std::string errorMessage;
105 auto output = mlir::openOutputFile(filePath, &errorMessage);
106 if (!output)
107 return module.emitError(errorMessage);
108
109 // Emit the content to the file.
110 SmallVector<Operation *> opsInThisFile(includes);
111 opsInThisFile.push_back(symbolOp);
112 if (failed(emitFile(opsInThisFile, filePath, output->os())))
113 return symbolOp->emitError("failed to emit to file \"")
114 << filePath << "\"";
115
116 // Do not delete the file if emission was successful.
117 output->keep();
118 }
119 }
120
121 return success();
122}
123
124//===----------------------------------------------------------------------===//
125// circt-translate registration
126//===----------------------------------------------------------------------===//
127
129
130 static llvm::cl::opt<std::string> directory(
131 "export-dir", llvm::cl::desc("Directory path to write the files to."),
132 llvm::cl::init("./"));
133
134 static mlir::TranslateFromMLIRRegistration toSystemC(
135 "export-systemc", "export SystemC",
136 [](ModuleOp module, raw_ostream &output) {
137 return ExportSystemC::exportSystemC(module, output);
138 },
139 [](mlir::DialectRegistry &registry) {
140 registry.insert<hw::HWDialect, comb::CombDialect,
141 systemc::SystemCDialect, mlir::emitc::EmitCDialect>();
142 });
143
144 static mlir::TranslateFromMLIRRegistration toSplitSystemC(
145 "export-split-systemc", "export SystemC (split)",
146 [](ModuleOp module, raw_ostream &output) {
147 return ExportSystemC::exportSplitSystemC(module, directory);
148 },
149 [](mlir::DialectRegistry &registry) {
150 registry.insert<hw::HWDialect, comb::CombDialect,
151 systemc::SystemCDialect, mlir::emitc::EmitCDialect>();
152 });
153}
static std::string pathToMacroName(StringRef path)
Helper to convert a file-path to a macro name that can be used to guard a header file.
static LogicalResult emitFile(ArrayRef< Operation * > operations, StringRef filePath, raw_ostream &os)
Emits the given operation to a file represented by the passed ostream and file-path.
This class collects a set of emission patterns with base type 'PatternTy'.
This is intended to be the driving class for all pattern-based IR emission.
void emitOp(Operation *op)
Emit the given operation as a statement to the ostream associated with this printer according to the ...
LogicalResult exitState() const
Returns whether everything was printed successfully or some error occurred (e.g., there was an operat...
void registerExportSystemCTranslation()
LogicalResult exportSplitSystemC(ModuleOp module, StringRef directory)
void registerAllTypeEmitters(TypeEmissionPatternSet &patterns)
Collects the type emission patterns of all supported dialects.
LogicalResult exportSystemC(ModuleOp module, llvm::raw_ostream &os)
void registerAllOpEmitters(OpEmissionPatternSet &patterns, MLIRContext *context)
Collects the operation emission patterns of all supported dialects.
void registerAllAttrEmitters(AttrEmissionPatternSet &patterns)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.