Jlm
Loading...
Searching...
No Matches
RhlsToFirrtlConverter.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Magnus Sjalander <work@sjalander.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#ifndef JLM_HLS_BACKEND_RHLS2FIRRTL_RHLSTOFIRRTLCONVERTER_HPP
7#define JLM_HLS_BACKEND_RHLS2FIRRTL_RHLSTOFIRRTLCONVERTER_HPP
8
10#include <jlm/hls/ir/hls.hpp>
17
18#include <mlir/IR/Builders.h>
19#include <mlir/IR/BuiltinOps.h>
20#include <mlir/IR/BuiltinTypes.h>
21#include <mlir/IR/Verifier.h>
22
23#include <circt/Dialect/FIRRTL/FIREmitter.h>
24#include <circt/Dialect/FIRRTL/FIRParser.h>
25#include <circt/Dialect/FIRRTL/FIRRTLDialect.h>
26#include <circt/Dialect/FIRRTL/FIRRTLOps.h>
27#include <circt/Dialect/FIRRTL/FIRRTLTypes.h>
28#include <circt/Dialect/FIRRTL/Namespace.h>
29#include <circt/Support/LLVM.h>
30
31namespace jlm::hls
32{
33
35{
37
38 std::string
39 extension() override
40 {
41 return ".fir";
42 }
43
44public:
45 std::string
47 {
48 return "MLIR/FIRRTL generator";
49 }
50
52 : Context_(std::make_unique<::mlir::MLIRContext>()),
53 DefaultFIRVersion_{ 4, 0, 0 }
54 {
55 Context_->getOrLoadDialect<circt::firrtl::FIRRTLDialect>();
56 Builder_ = std::make_unique<::mlir::OpBuilder>(Context_.get());
57 }
58
60
62
65
68
69 circt::firrtl::CircuitOp
71
72 void
73 WriteModuleToFile(const circt::firrtl::FModuleOp fModuleOp, const rvsdg::Node * node);
74
75 void
76 WriteCircuitToFile(const circt::firrtl::CircuitOp circuit, std::string name);
77
78 std::string
80 {
81 // Generate a FIRRTL circuit of the rvsdgModule
84 auto circuit = mlirGen.MlirGen(lambdaNode);
85 // Write the FIRRTL to a file
86 return mlirGen.toString(circuit);
87 }
88
89 std::unique_ptr<mlir::ModuleOp>
91 {
94 auto circuit = mlirGen.MlirGen(lambdaNode);
95 std::unique_ptr<mlir::ModuleOp> module =
96 std::make_unique<mlir::ModuleOp>(mlir::ModuleOp::create(Builder_->getUnknownLoc()));
97 module->push_back(circuit);
98 return module;
99 }
100
101private:
102 std::string
103 toString(const circt::firrtl::CircuitOp circuit);
104
105 std::unordered_map<std::string, circt::firrtl::FModuleLike> modules;
106 // FIRRTL generating functions
107 circt::firrtl::FModuleOp
108 MlirGen(LoopNode * loopNode, mlir::Block * circuitBody);
109 circt::firrtl::FModuleLike
110 MlirGen(rvsdg::Region * subRegion, mlir::Block * circuitBody);
111 circt::firrtl::FModuleLike
112 MlirGen(const jlm::rvsdg::SimpleNode * node);
113 // Operations
114 circt::firrtl::FModuleOp
116 circt::firrtl::FModuleOp
118 circt::firrtl::FModuleOp
120 circt::firrtl::FModuleOp
122 circt::firrtl::FModuleOp
130 circt::firrtl::FModuleOp
138 circt::firrtl::FModuleOp
140 circt::firrtl::FModuleOp
142 circt::firrtl::FModuleOp
144 circt::firrtl::FModuleOp
146 circt::firrtl::FModuleOp
148 circt::firrtl::FModuleOp
150 circt::firrtl::FModuleOp
152 circt::firrtl::FModuleOp
154 circt::firrtl::FModuleOp
156 circt::firrtl::FModuleOp
158 circt::firrtl::FModuleOp
160 circt::firrtl::FModuleOp
162 circt::firrtl::FModuleOp
164 circt::firrtl::FModuleOp
166 circt::firrtl::FExtModuleOp
168
169 // Helper functions
170 void
171 AddClockPort(::llvm::SmallVector<circt::firrtl::PortInfo> * ports);
172 void
173 AddResetPort(::llvm::SmallVector<circt::firrtl::PortInfo> * ports);
174 void
175 AddMemReqPort(::llvm::SmallVector<circt::firrtl::PortInfo> * ports);
176 void
177 AddMemResPort(::llvm::SmallVector<circt::firrtl::PortInfo> * ports);
178 void
180 ::llvm::SmallVector<circt::firrtl::PortInfo> * ports,
181 circt::firrtl::Direction direction,
182 std::string name,
183 circt::firrtl::FIRRTLBaseType type);
184 circt::firrtl::BundleType
185 GetBundleType(const circt::firrtl::FIRRTLBaseType & type);
186 circt::firrtl::SubfieldOp
187 GetSubfield(mlir::Block * body, mlir::Value value, int index);
188 circt::firrtl::SubfieldOp
189 GetSubfield(mlir::Block * body, mlir::Value value, ::llvm::StringRef fieldName);
190 mlir::OpResult
191 GetInstancePort(circt::firrtl::InstanceOp & instance, std::string portName);
192 mlir::BlockArgument
193 GetPort(circt::firrtl::FModuleOp & module, std::string portName);
194 mlir::BlockArgument
195 GetInPort(circt::firrtl::FModuleOp & module, size_t portNr);
196 mlir::BlockArgument
197 GetOutPort(circt::firrtl::FModuleOp & module, size_t portNr);
198 void
199 Connect(mlir::Block * body, mlir::Value sink, mlir::Value source);
200 // Primary operations
201 circt::firrtl::BitsPrimOp
202 AddBitsOp(mlir::Block * body, mlir::Value value, int high, int low);
203 circt::firrtl::AndPrimOp
204 AddAndOp(mlir::Block * body, mlir::Value first, mlir::Value second);
205 circt::firrtl::NodeOp
206 AddNodeOp(mlir::Block * body, mlir::Value value, std::string name);
207 circt::firrtl::XorPrimOp
208 AddXorOp(mlir::Block * body, mlir::Value first, mlir::Value second);
209 circt::firrtl::OrPrimOp
210 AddOrOp(mlir::Block * body, mlir::Value first, mlir::Value second);
211 circt::firrtl::NotPrimOp
212 AddNotOp(mlir::Block * body, mlir::Value first);
213 circt::firrtl::AddPrimOp
214 AddAddOp(mlir::Block * body, mlir::Value first, mlir::Value second);
215 circt::firrtl::SubPrimOp
216 AddSubOp(mlir::Block * body, mlir::Value first, mlir::Value second);
217 circt::firrtl::MulPrimOp
218 AddMulOp(mlir::Block * body, mlir::Value first, mlir::Value second);
219 circt::firrtl::DivPrimOp
220 AddDivOp(mlir::Block * body, mlir::Value first, mlir::Value second);
221 circt::firrtl::DShrPrimOp
222 AddDShrOp(mlir::Block * body, mlir::Value first, mlir::Value second);
223 circt::firrtl::DShlPrimOp
224 AddDShlOp(mlir::Block * body, mlir::Value first, mlir::Value second);
225 circt::firrtl::RemPrimOp
226 AddRemOp(mlir::Block * body, mlir::Value first, mlir::Value second);
227 circt::firrtl::EQPrimOp
228 AddEqOp(mlir::Block * body, mlir::Value first, mlir::Value second);
229 circt::firrtl::NEQPrimOp
230 AddNeqOp(mlir::Block * body, mlir::Value first, mlir::Value second);
231 circt::firrtl::GTPrimOp
232 AddGtOp(mlir::Block * body, mlir::Value first, mlir::Value second);
233 circt::firrtl::GEQPrimOp
234 AddGeqOp(mlir::Block * body, mlir::Value first, mlir::Value second);
235 circt::firrtl::LTPrimOp
236 AddLtOp(mlir::Block * body, mlir::Value first, mlir::Value second);
237 circt::firrtl::LEQPrimOp
238 AddLeqOp(mlir::Block * body, mlir::Value first, mlir::Value second);
239 circt::firrtl::MuxPrimOp
240 AddMuxOp(mlir::Block * body, mlir::Value select, mlir::Value high, mlir::Value low);
241 circt::firrtl::AsSIntPrimOp
242 AddAsSIntOp(mlir::Block * body, mlir::Value value);
243 circt::firrtl::AsUIntPrimOp
244 AddAsUIntOp(mlir::Block * body, mlir::Value value);
245 circt::firrtl::PadPrimOp
246 AddPadOp(mlir::Block * body, mlir::Value value, int amount);
247 circt::firrtl::CvtPrimOp
248 AddCvtOp(mlir::Block * body, mlir::Value value);
249 circt::firrtl::WireOp
250 AddWireOp(mlir::Block * body, std::string name, int size);
251 circt::firrtl::WhenOp
252 AddWhenOp(mlir::Block * body, mlir::Value condition, bool elseStatment);
253 circt::firrtl::InstanceOp
254 AddInstanceOp(mlir::Block * circuitBody, jlm::rvsdg::Node * node);
255 circt::firrtl::ConstantOp
256 GetConstant(mlir::Block * body, int size, int value);
257 circt::firrtl::InvalidValueOp
258 GetInvalid(mlir::Block * body, int size);
259 void
260 ConnectInvalid(mlir::Block * body, mlir::Value value);
261
262 circt::firrtl::BitsPrimOp
263 DropMSBs(mlir::Block * body, mlir::Value value, int amount);
264
267
270
271 void
272 InitializeMemReq(circt::firrtl::FModuleOp module);
273 circt::firrtl::BundleType::BundleElement
275 circt::firrtl::BundleType::BundleElement
277 mlir::BlockArgument
278 GetClockSignal(circt::firrtl::FModuleOp module);
279 mlir::BlockArgument
280 GetResetSignal(circt::firrtl::FModuleOp module);
281 circt::firrtl::FModuleOp
282 nodeToModule(const jlm::rvsdg::Node * node, bool mem = false);
283 circt::firrtl::IntType
284 GetIntType(int size);
285 circt::firrtl::IntType
286 GetIntType(const jlm::rvsdg::Type * type, int extend = 0);
287 circt::firrtl::FIRRTLBaseType
288 GetFirrtlType(const jlm::rvsdg::Type * type);
289 std::string
290 GetModuleName(const rvsdg::Node * node);
291 bool
293 void
294 check_module(circt::firrtl::FModuleOp & module);
295
296 std::unique_ptr<::mlir::OpBuilder> Builder_;
297 std::unique_ptr<::mlir::MLIRContext> Context_;
298 const circt::firrtl::FIRVersion DefaultFIRVersion_;
299};
300
301} // namespace jlm::hls
302
303#endif // JLM_HLS_BACKEND_RHLS2FIRRTL_RHLSTOFIRRTLCONVERTER_HPP
const rvsdg::LambdaNode * get_hls_lambda(llvm::LlvmRvsdgModule &rm)
Definition base-hls.cpp:136
circt::firrtl::InstanceOp AddInstanceOp(mlir::Block *circuitBody, jlm::rvsdg::Node *node)
RhlsToFirrtlConverter(const RhlsToFirrtlConverter &)=delete
circt::firrtl::GEQPrimOp AddGeqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenBuffer(const jlm::rvsdg::SimpleNode *node)
mlir::BlockArgument GetPort(circt::firrtl::FModuleOp &module, std::string portName)
circt::firrtl::FModuleOp MlirGenHlsMemReq(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::EQPrimOp AddEqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::LTPrimOp AddLtOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::BitsPrimOp AddBitsOp(mlir::Block *body, mlir::Value value, int high, int low)
void check_module(circt::firrtl::FModuleOp &module)
RhlsToFirrtlConverter & operator=(const RhlsToFirrtlConverter &)=delete
circt::firrtl::XorPrimOp AddXorOp(mlir::Block *body, mlir::Value first, mlir::Value second)
std::unique_ptr<::mlir::MLIRContext > Context_
circt::firrtl::FModuleOp MlirGenNDMux(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::BundleType GetBundleType(const circt::firrtl::FIRRTLBaseType &type)
circt::firrtl::BitsPrimOp DropMSBs(mlir::Block *body, mlir::Value value, int amount)
circt::firrtl::WireOp AddWireOp(mlir::Block *body, std::string name, int size)
void AddMemResPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::RemPrimOp AddRemOp(mlir::Block *body, mlir::Value first, mlir::Value second)
std::string ToString(llvm::LlvmRvsdgModule &rvsdgModule)
std::unordered_map< std::string, circt::firrtl::FModuleLike > modules
circt::firrtl::FModuleOp MlirGenFork(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FModuleOp nodeToModule(const jlm::rvsdg::Node *node, bool mem=false)
void WriteModuleToFile(const circt::firrtl::FModuleOp fModuleOp, const rvsdg::Node *node)
rvsdg::Output * TraceStructuralOutput(rvsdg::StructuralOutput *out)
circt::firrtl::NodeOp AddNodeOp(mlir::Block *body, mlir::Value value, std::string name)
circt::firrtl::FModuleOp MlirGenTrigger(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::DShrPrimOp AddDShrOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::NEQPrimOp AddNeqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenPrint(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FModuleOp MlirGenHlsMemResp(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::BundleType::BundleElement GetReadyElement()
std::string GetText(llvm::LlvmRvsdgModule &) override
circt::firrtl::BundleType::BundleElement GetValidElement()
void AddResetPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::FModuleOp MlirGenStateGate(const jlm::rvsdg::SimpleNode *node)
const circt::firrtl::FIRVersion DefaultFIRVersion_
void InitializeMemReq(circt::firrtl::FModuleOp module)
circt::firrtl::FModuleOp MlirGenSink(const jlm::rvsdg::SimpleNode *node)
void Connect(mlir::Block *body, mlir::Value sink, mlir::Value source)
circt::firrtl::FModuleOp MlirGenHlsStore(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FIRRTLBaseType GetFirrtlType(const jlm::rvsdg::Type *type)
void AddMemReqPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::DShlPrimOp AddDShlOp(mlir::Block *body, mlir::Value first, mlir::Value second)
void WriteCircuitToFile(const circt::firrtl::CircuitOp circuit, std::string name)
bool IsIdentityMapping(const rvsdg::MatchOperation &op)
circt::firrtl::CircuitOp MlirGen(const rvsdg::LambdaNode *lamdaNode)
circt::firrtl::FModuleOp MlirGenSimpleNode(const jlm::rvsdg::SimpleNode *node)
mlir::BlockArgument GetResetSignal(circt::firrtl::FModuleOp module)
std::string toString(const circt::firrtl::CircuitOp circuit)
circt::firrtl::ConstantOp GetConstant(mlir::Block *body, int size, int value)
circt::firrtl::InvalidValueOp GetInvalid(mlir::Block *body, int size)
RhlsToFirrtlConverter & operator=(RhlsToFirrtlConverter &&)=delete
mlir::BlockArgument GetOutPort(circt::firrtl::FModuleOp &module, size_t portNr)
circt::firrtl::FModuleOp MlirGenBranch(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::SubPrimOp AddSubOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::PadPrimOp AddPadOp(mlir::Block *body, mlir::Value value, int amount)
circt::firrtl::MuxPrimOp AddMuxOp(mlir::Block *body, mlir::Value select, mlir::Value high, mlir::Value low)
circt::firrtl::WhenOp AddWhenOp(mlir::Block *body, mlir::Value condition, bool elseStatment)
circt::firrtl::AsUIntPrimOp AddAsUIntOp(mlir::Block *body, mlir::Value value)
circt::firrtl::FModuleOp MlirGenPredicationBuffer(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::NotPrimOp AddNotOp(mlir::Block *body, mlir::Value first)
circt::firrtl::FModuleOp MlirGenAddrQueue(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::GTPrimOp AddGtOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FExtModuleOp MlirGenExtModule(const jlm::rvsdg::SimpleNode *node)
void AddClockPort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports)
circt::firrtl::FModuleOp MlirGenHlsDLoad(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::FModuleOp MlirGenLoopConstBuffer(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::OrPrimOp AddOrOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::IntType GetIntType(int size)
std::unique_ptr< mlir::ModuleOp > ConvertToMduleOp(llvm::LlvmRvsdgModule &rvsdgModule)
circt::firrtl::MulPrimOp AddMulOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::LEQPrimOp AddLeqOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenHlsLocalMem(const jlm::rvsdg::SimpleNode *node)
std::string GetModuleName(const rvsdg::Node *node)
jlm::rvsdg::Output * TraceArgument(rvsdg::RegionArgument *arg)
std::unique_ptr<::mlir::OpBuilder > Builder_
circt::firrtl::AsSIntPrimOp AddAsSIntOp(mlir::Block *body, mlir::Value value)
circt::firrtl::FModuleOp MlirGenDMux(const jlm::rvsdg::SimpleNode *node)
circt::firrtl::DivPrimOp AddDivOp(mlir::Block *body, mlir::Value first, mlir::Value second)
circt::firrtl::FModuleOp MlirGenHlsLoad(const jlm::rvsdg::SimpleNode *node)
RhlsToFirrtlConverter(RhlsToFirrtlConverter &&)=delete
circt::firrtl::AddPrimOp AddAddOp(mlir::Block *body, mlir::Value first, mlir::Value second)
mlir::BlockArgument GetInPort(circt::firrtl::FModuleOp &module, size_t portNr)
circt::firrtl::CvtPrimOp AddCvtOp(mlir::Block *body, mlir::Value value)
circt::firrtl::SubfieldOp GetSubfield(mlir::Block *body, mlir::Value value, int index)
mlir::OpResult GetInstancePort(circt::firrtl::InstanceOp &instance, std::string portName)
mlir::BlockArgument GetClockSignal(circt::firrtl::FModuleOp module)
circt::firrtl::AndPrimOp AddAndOp(mlir::Block *body, mlir::Value first, mlir::Value second)
void ConnectInvalid(mlir::Block *body, mlir::Value value)
circt::firrtl::FModuleOp MlirGenMem(const jlm::rvsdg::SimpleNode *node)
void AddBundlePort(::llvm::SmallVector< circt::firrtl::PortInfo > *ports, circt::firrtl::Direction direction, std::string name, circt::firrtl::FIRRTLBaseType type)
Represents the argument of a region.
Definition region.hpp:41
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872