systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
HDLMain.cpp
Go to the documentation of this file.
1// clang-format off
2#include <regex>
3#include <tuple>
4#include <unordered_map>
5#include "SystemCClang.h"
6#include "PortBinding.h"
7#include "ArrayTypeUtils.h"
8#include "Tree.h"
9#include "HDLMain.h"
10//#include "TemplateParametersMatcher.h"
11#include "SensitivityMatcher.h"
12#include "clang/Basic/FileManager.h"
13#include "llvm/Support/Debug.h"
14#include "clang/Basic/Diagnostic.h"
15
16#include "HDLHnode.h"
17#include "HDLThread.h"
18
19#include <iostream>
20
21#include "APIntUtils.h"
22// clang-format on
24#undef DEBUG_TYPE
25#define DEBUG_TYPE "HDL"
26
27using namespace std;
28using namespace hnode;
29using namespace systemc_clang;
30using namespace clang;
31
32namespace systemc_hdl {
33
34 std::unique_ptr<clang::tooling::FrontendActionFactory>
35 newFrontendActionFactory(const std::string &top_module) {
36 return std::unique_ptr<tooling::FrontendActionFactory>(
37 new HDLFrontendActionFactory(top_module));
38 }
39
40
50 Model *model = getSystemCModel();
51
52 std::error_code ec;
53 string outputfn;
54
56 //
57
58 LLVM_DEBUG(llvm::dbgs() << "HDL-FILE-OUTPUT: " << hdl_file_out_ << "\n"; );
59
60 FileID fileID = getSourceManager().getMainFileID();
61 const FileEntry *fileentry = getSourceManager().getFileEntryForID(fileID);
62 if (hdl_file_out_ == "") {
63 if (!fileentry) {
64 outputfn = "HCodeout";
65 LLVM_DEBUG(llvm::dbgs()
66 << "Null file entry for tranlation unit for this astcontext\n");
67 } else {
68 outputfn = fileentry->getName().str();
69 regex r("\\.cpp");
70 outputfn = regex_replace(outputfn, r, "_hdl");
71
72 LLVM_DEBUG(llvm::dbgs() << "File name is " << outputfn << "\n");
73 }
74 } else {
75 outputfn = hdl_file_out_;
76 }
77
78 llvm::raw_fd_ostream HCodeOut(outputfn + ".txt", ec,
79 llvm::sys::fs::CD_CreateAlways);
80 LLVM_DEBUG(llvm::dbgs() << "file " << outputfn
81 << ".txt, create error code is " << ec.value()
82 << "\n");
83
84 LLVM_DEBUG(llvm::dbgs() << "\n SC HDL plugin\n");
85
86 // typedef std::vector< modulePairType > moduleMapType;
87 // typedef std::pair<std::string, ModuleInstance *> modulePairType;
88
89
90 ModuleInstance *modinstance{model->getRootModuleInstance()};
91 if (modinstance == nullptr) {
92 LLVM_DEBUG(llvm::dbgs() << "\nRoot instance not found, exiting\n");
93 return false;
94 }
95
96 // generate module instance for top module and its submodules
97
98 //string modname = modinstance->getName()+mod_newn.newname(); // include original name for readability
99
100 hNodep h_module = new hNode(hNode::hdlopsEnum::hModule);
101
102 // need to provide an old name for module instance decl
103 // since it's not derived from clang NamedDecl and doesn't have
104 // a str() class to dereference llvm:StringRef
105
106 mod_name_map.add_entry(modinstance, modinstance->getName(), h_module);
107 LLVM_DEBUG(llvm::dbgs() << "\ntop level module " << modinstance->getName()
108 << " renamed " << h_module->getname() << "\n");
109
110 //mod_name_map[modinstance] = {modinstance->getName(),
111 // modname, h_module};
112
113 SCmodule2hcode(modinstance, h_module, HCodeOut);
114 // h_module->print(HCodeOut);
115
116 LLVM_DEBUG(llvm::dbgs() << "User Types Map\n");
117
118 while (!HDLt.usertype_info.usertypes.empty()) {
123 for (auto t : usertypestmp) {
124 LLVM_DEBUG(llvm::dbgs()
125 << "User Type --------\n"
126 << t.first << ":" << t.second.getTypePtr() << t.second.getAsString() <<"\n");
127 LLVM_DEBUG(t.second->dump(llvm::dbgs(), getContext()));
128 LLVM_DEBUG(llvm::dbgs() << "---------\n");
129 HDLt.addtype(t.first, t.second, getContext())->print(HCodeOut);
130 }
131 }
132 return true;
133 }
134
136 llvm::raw_fd_ostream &HCodeOut) {
137 const std::vector<ModuleInstance *> &submodv = mod->getNestedModuleInstances();
138 const std::vector<ModuleInstance *> &basemods = mod->getBaseInstances();
139
144 overridden_method_map_t overridden_method_map;
145
146 LLVM_DEBUG( llvm::dbgs() << "Processing module " << mod->getName() << " instance " << mod->getInstanceName() << "\n");
147 LLVM_DEBUG( llvm::dbgs() << "dumping base instances \n");
148 LLVM_DEBUG(mod->dump_base_instances(llvm::dbgs()));
149 LLVM_DEBUG( llvm::dbgs() << "end base instances \n");
150
151 const CXXRecordDecl *cdecl{mod->getModuleClassDecl()};
152 LLVM_DEBUG( llvm::dbgs() << "Methods in this module\n");
153 for (const auto &method : cdecl->methods()) {
154 if (isValidMethod(method)) {
155 if (method->isVirtual()) {
156 LLVM_DEBUG( llvm::dbgs() << "Virtual ");
157 }
158 LLVM_DEBUG(llvm::dbgs() << "Method name is " << method->getParent()->getNameAsString() << "::" << method->getNameAsString()
159 << "\n");
160 QualType qtype{method->getThisType()};
161 LLVM_DEBUG(qtype.getTypePtr()->dump());
162 LLVM_DEBUG(llvm::dbgs() << "\n");
163 if (method->getBody() != NULL) {
164 LLVM_DEBUG(llvm::dbgs() << "Body of method non-null\n");
165 //LLVM_DEBUG(method->getBody()->dump());
166 }
167 else LLVM_DEBUG(llvm::dbgs() << "Empty method body\n");
168
169 for (const auto &ometh : method->overridden_methods()) {
170 LLVM_DEBUG(llvm::dbgs() << " overridden method " << ometh->getParent()->getNameAsString() << "::" << ometh->getNameAsString() << "\n");
171 if (ometh->hasBody()) {
172 overridden_method_map[ometh] = method;
173 }
174 else LLVM_DEBUG(llvm::dbgs() << "Empty overridden method body\n");
175 }
176 }
177 }
178
179 LLVM_DEBUG(llvm::dbgs() <<"Overridden method map\n");
180 for (auto ov: overridden_method_map) {
181 LLVM_DEBUG(llvm::dbgs() << "Overridden method\n");
182 LLVM_DEBUG(ov.first->dump(llvm::dbgs()));
183 LLVM_DEBUG(llvm::dbgs() << "Overriding method\n");
184 LLVM_DEBUG(ov.second->dump(llvm::dbgs()));
185 }
186 LLVM_DEBUG(llvm::dbgs() <<"end Overridden method map\n");
187 LLVM_DEBUG( llvm::dbgs() << "End Methods in this module\n\n");
188
189 // look at constructor
190
191 // LLVM_DEBUG(llvm::dbgs() << "dumping module constructor stmt\n");
192
193 // LLVM_DEBUG(mod->getConstructorStmt()->dump(llvm::dbgs()));
194 //LLVM_DEBUG( llvm::dbgs() << "dumping module constructor decl body\n");
195 //LLVM_DEBUG(mod->getConstructorDecl()->getBody()->dump());
196 //LLVM_DEBUG( llvm::dbgs() << "end dumping module constructor decl body\n");
197 //LLVM_DEBUG(mod->getConstructorDecl()->dump(llvm::dbgs()));
198
199 LLVM_DEBUG(llvm::dbgs() << "submodule count is " << submodv.size() << "\n");
200
201 hdecl_name_map_t mod_vname_map("_scclang_global_");
202 xbodyp = new HDLBody(main_diag_engine, getContext(), mod_vname_map, allmethodecls, overridden_method_map);
203
205 module_vars.clear();
206 threadresetmap.clear();
207
208 // Ports
209 hNodep h_ports =
210 new hNode(hNode::hdlopsEnum::hPortsigvarlist); // list of ports, signals
211 h_module->child_list.push_back(h_ports);
212
213 // generate port, sig, var for module inheritance chain
214 ModuleInstance *mod_i = mod;
215 for (int i = 0; i <= basemods.size(); i++) {
216 SCport2hcode(mod_i->getIPorts(), hNode::hdlopsEnum::hPortin, h_ports, mod_vname_map);
217 SCport2hcode(mod_i->getInputStreamPorts(), hNode::hdlopsEnum::hPortin, h_ports, mod_vname_map);
218 SCport2hcode(mod_i->getOPorts(), hNode::hdlopsEnum::hPortout, h_ports, mod_vname_map);
219 SCport2hcode(mod_i->getOutputStreamPorts(), hNode::hdlopsEnum::hPortout,
220 h_ports, mod_vname_map);
221 SCport2hcode(mod_i->getIOPorts(), hNode::hdlopsEnum::hPortio, h_ports, mod_vname_map);
222
223 // Signals
224 SCsig2hcode(mod_i->getSignals(), hNode::hdlopsEnum::hSigdecl, h_ports, mod_vname_map);
225
226 SCport2hcode(mod_i->getOtherVars(), hNode::hdlopsEnum::hVardecl, h_ports, mod_vname_map);
227 if (i == basemods.size()) break;
228 mod_i = basemods[i];
229 }
230
231 // add the submodule declarations
232
233 for (const auto &smod : submodv) {
234 std::vector<std::string> instnames;
235 if (smod->getInstanceInfo().isArrayType()) {
236 LLVM_DEBUG(llvm::dbgs() << "Array submodule " << smod->getInstanceInfo().getVarName() << "\n");
237 }
238 else {
239 LLVM_DEBUG(llvm::dbgs() << "Non-Array submodule " << smod->getInstanceInfo().getVarName() << "\n");
240 }
241
242 // we generate instance names based on the array indices so that the names match
243 // names used in the portbindings for each instance, which are generated in
244 // for loops (see HDLHNode.cpp code to unroll portbindings).
245
246 GenerateInstanceNames(smod, instnames);
247 bool frsttime = true;
248 for (auto instname: instnames) {
249 LLVM_DEBUG(llvm::dbgs() << "Instance " << instname << "\n");
250
251 hNodep h_smod =
252 new hNode(instname, hNode::hdlopsEnum::hModdecl);
253 h_ports->child_list.push_back(h_smod);
254 hNodep h_smodtypinfo = new hNode(hNode::hdlopsEnum::hTypeinfo);
255 if (frsttime) { // only enter the first one into the map
256 mod_name_map.add_entry(smod, smod->getName(), h_smod);
257 h_smod->set(instname); // override name inserted by map service
258 frsttime = false;
259 }
260 h_smodtypinfo->child_list.push_back(
261 new hNode(mod_name_map.find_entry_newn(smod), hNode::hdlopsEnum::hType));
262 h_smod->child_list.push_back(h_smodtypinfo);
263 }
264 }
265
266 // look at sensitivitiy list info
267 // init block
268 mod_i = mod;
269 hNodep h_modinitblockhead = new hNode( hNode::hdlopsEnum::hNoop); // hold list of module constructors
270 hNodep h_constructor;
271 hNodep h_allsenslists = new hNode( hNode::hdlopsEnum::hNoop);
272 for (int i = 0; i <= basemods.size(); i++) {
273 if (mod_i->getConstructorDecl() ==NULL) continue; // null constructor
274 h_constructor = new hNode(mod_i->getInstanceInfo().getVarName()+ (mod_i->getInstanceInfo().isArrayType()? "_0" :""),
275 hNode::hdlopsEnum::hModinitblock);
276 // SenseMapType sensmap = mod_i->getSensitivityMap();
277 // for (auto sensitem : sensmap) {
278 // sensitem->dump();
279 // }
280 xbodyp->Run(mod_i->getConstructorDecl()->getBody(), h_constructor,rmodinit);
281 LLVM_DEBUG(llvm::dbgs() << "HDL output for module constructor body\n");
282 LLVM_DEBUG(h_constructor->print(llvm::dbgs()));
283 HDLConstructorHcode hcxxbody;
284 hNodep modinithp = hcxxbody.ProcessCXXConstructorHcode(h_constructor);
285 if (modinithp->child_list.size() != 0) { // if there was an initblock
286 h_modinitblockhead->child_list.push_back(modinithp);
287 // need to add these nodes to h_senshead
288 std::vector<hNodep> slvec;
289 hcxxbody.GetSensLists(slvec);
290 h_allsenslists->child_list.insert(h_allsenslists->child_list.end(), slvec.begin(), slvec.end());
291 }
292
293 //h_constructor->print(HCodeOut);
294 if (i == basemods.size()) break;
295 mod_i = basemods[i];
296 }
297
298 //LLVM_DEBUG(llvm::dbgs() << "Module sensitivity lists follow\n");
299 //LLVM_DEBUG(h_allsenslists->print(llvm::dbgs()));
300 //LLVM_DEBUG(llvm::dbgs() << "Module sensitivity lists end\n");
301
302 // build map of thread name to reset var name for this module
303 MakeResetMap(threadresetmap, h_allsenslists);
304
305 LLVM_DEBUG(llvm::dbgs() << "Module vname map size is " << mod_vname_map.size() << " \n");
306
307 // Processes
308 hNodep h_processes = new hNode(hNode::hdlopsEnum::hProcesses);
309 mod_i = mod;
310 for (int i = 0; i <= basemods.size(); i++) {
311 // send portsigvarlist (h_ports) to proc code gen so thread vars get promoted to module level
312 SCproc2hcode(mod_i->getProcessMap(), h_processes, h_ports, mod_vname_map, overridden_method_map, threadresetmap);
313 if (i == basemods.size()) break;
314 mod_i = basemods[i];
315 }
316 // add all the processes (including those in the inheritance chain) to the module
317 if (!h_processes->child_list.empty()) h_module->child_list.push_back(h_processes);
318
319 // add extra sig and var decls to shadow those referenced in threads
320 for (auto const &var: mod_vname_map) {
321 if (var.second.referenced) {
322 hNodep hvp = new hNode("_main_"+var.second.h_vardeclp->getname(), var.second.h_vardeclp->getopc());
323 hvp->child_list = var.second.h_vardeclp->child_list;
324 h_ports->append(hvp);
325 }
326 }
327
328
329 // now add init block
330 if (h_modinitblockhead->size()>0) {
331 h_module->append(h_modinitblockhead->child_list[0]);
332 //h_module->child_list.insert(h_module->child_list.end(), h_modinitblockhead->child_list.begin(), h_modinitblockhead->child_list.end());
333 hNodep hfirstblock = h_modinitblockhead->child_list[0];
334 for (int i = 1; i< h_modinitblockhead->size(); i++) { // in case of multiple modinit blocks due to inheritance
335 // join all their child_lists under the first mod_int
336 hfirstblock->child_list.insert(hfirstblock->child_list.end(),
337 h_modinitblockhead->child_list[i]->child_list.begin(),
338 h_modinitblockhead->child_list[i]->child_list.end());
339
340 }
341 }
342
343 // Functions
344 // Initially these are functions that were referenced in the module's sc_methods/threads
345 // Function calls within functions get added to all methodecls.
346
347 std::set<Decl *> generated_functions;
348 bool addfunc = false;
349 //while (allmethodecls.size() > 0) {
350 while (allmethodecls.size()>generated_functions.size()) {
351 LLVM_DEBUG(llvm::dbgs() << "Module Method/Function Map\n");
352
353 hfunc_name_map_t &modmethodecls = allmethodecls;
354 //modmethodecls =
355 // std::move(allmethodecls); // procedures/functions found in this module
356 LLVM_DEBUG(llvm::dbgs()
357 << "size of allmethodecls is " << allmethodecls.size() << "\n");
358 LLVM_DEBUG(allmethodecls.print(llvm::dbgs()));
359 LLVM_DEBUG(llvm::dbgs()
360 << "size of generated_functions is " << generated_functions.size() << "\n");
361 LLVM_DEBUG(llvm::dbgs()
362 << "size of modmethodecls is " << modmethodecls.size() << "\n");
363 //LLVM_DEBUG(modmethodecls.print(llvm::dbgs()));
364 LLVM_DEBUG(HDLt.print(llvm::dbgs()));
365 for (auto const &m : modmethodecls) {
366 //for (auto const &m : allmethodecls) {
367 LLVM_DEBUG(llvm::dbgs() << "Method --------\n"
368 << m.first << " " << m.second.newn << " generatedcount is " << generated_functions.count(m.first)<< "\n");
369 LLVM_DEBUG(m.first->dump(llvm::dbgs()));
370 LLVM_DEBUG(llvm::dbgs() << "---------\n");
371 if (generated_functions.count(m.first) > 0) continue; // already generated this one !!!!!
372 generated_functions.insert(m.first);
373 //clang::DiagnosticsEngine &diag_engine{getContext().getDiagnostics()};
374 if (m.first->hasBody()) {
375 //if (generated_functions.count(m.first) > 0) continue; // already generated this one !!!!!
376 //generated_functions.insert(m.first);
377 hNodep hfunc = new hNode(m.second.newn, hNode::hdlopsEnum::hFunction);
378 QualType qrettype = m.first->getReturnType(); // m.first->getDeclaredReturnType();
379 const clang::Type *rettype = qrettype.getTypePtr();
381 te->Enumerate(rettype);
382 HDLType HDLt2;
383 // what about returning an array type? this isn't handled
384 HDLt2.SCtype2hcode("", te->getTemplateArgTreePtr(), NULL,
385 hNode::hdlopsEnum::hFunctionRetType, hfunc);
386 CXXMethodDecl * thismethod = dyn_cast<CXXMethodDecl>(m.first);
387 bool isUserDefinedMethod = (thismethod != NULL) && (modmethodecls.methodobjtypemap.count(thismethod));//modmethodecls.methodobjtypemap.count(thismethod));
388 if (thismethod != NULL) {
389 LLVM_DEBUG(llvm::dbgs() << thismethod->getParent()->getQualifiedNameAsString() << " " << m.second.newn << " is a Method\n");
390 }
391 else LLVM_DEBUG(llvm::dbgs() << m.second.newn << " is a Function\n");
392 if ((m.first->getNumParams() > 0) || (thismethod != NULL)) {
393 hNodep hparams = new hNode(hNode::hdlopsEnum::hFunctionParams);
394 hNodep hparam_assign_list = new hNode(hNode::hdlopsEnum::hCStmt);
395 hfunc->child_list.push_back(hparams);
396
397 if (isUserDefinedMethod) { // user defined non scmodule method
398 hNodep hthisparam = new hNode("hthis", hNode::hdlopsEnum::hFunctionParamIO);
399 hNodep hthistype = new hNode(hNode::hdlopsEnum::hTypeinfo);
400 const clang::Type * tp = modmethodecls.methodobjtypemap[thismethod];// modmethodecls.methodobjtypemap[thismethod];
401 if (tp == NULL) {
402 LLVM_DEBUG(llvm::dbgs() <<"Couldn't find methodobjtypemap entry for " << thismethod << "\n");
403 }
404 else {
405 if (HDLt.usertype_info.userrectypes.count(tp)) {
406 LLVM_DEBUG(llvm::dbgs() << "Found methodobjtypemap entry for " << thismethod << " and userrectypes gives " << HDLt.usertype_info.userrectypes[tp] << "\n");
407 }
408 else {
409 LLVM_DEBUG(llvm::dbgs() << "Couldn't find userrectypes entry for " << tp << "\n");
410 LLVM_DEBUG(HDLt.print(llvm::dbgs()));
411 }
412 }
413 hthistype->append(new hNode(HDLt.usertype_info.userrectypes[tp],
414 hNode::hdlopsEnum::hType));
415 hthisparam->append(hthistype);
416 hparams->append(hthisparam);
417 }
418 for (int i = 0; i < m.first->getNumParams(); i++) {
419 ParmVarDecl *vardecl = m.first->getParamDecl(i);
420 QualType q = vardecl->getType();
421 const clang::Type *tp = q.getTypePtr();
422 LLVM_DEBUG(llvm::dbgs() << "ProcessParmVarDecl type name is "
423 << q.getAsString() << "\n");
425 te->Enumerate(tp);
426 HDLType HDLt1;
427 std::vector<llvm::APInt> array_sizes = sc_ast_matchers::utils::array_type::getConstantArraySizes(vardecl);
428 hNode::hdlopsEnum paramtype;
429 // special case if sc_min, max, abs, treat parameters as input
430 // unfortunately simulation library makes them I/O
431 //if (mutil.is_sc_macro(m.first)) paramtype = hNode::hdlopsEnum::hFunctionParamI;
432
433 // ============= CHECK ==============
434 //bool t1 = mutil.isSCByFunctionDecl(m.first);
435 bool t1 = mutil.checkNamespace(m.first);
436 bool t2 = mutil.isSCMacro(m.second.oldn);
437
438 if (t1 != t2) {
439 llvm::dbgs() << "@@@@ isSCMacro does not match. t1 = " << t1 << ", t2 = " << t2 << " " << m.second.oldn << "\n";
440 assert(0 && "isSCMacro does not match");
441 }
442 // ============= END CHECK ==============
443 //
444 if (mutil.isSCMacro(m.second.oldn)) {
445 paramtype = hNode::hdlopsEnum::hFunctionParamI;
446 }
447 else if ((vardecl->getType()->isReferenceType()) && !(vardecl->getType().getNonReferenceType().isConstQualified()))
448 paramtype = hNode::hdlopsEnum::hFunctionParamRef;
449 else { // handle actual parameter
450
451 paramtype = hNode::hdlopsEnum::hFunctionParamI;
452 // create an entry in mod_vname_map for this parameter's local variable
453 string objname = vardecl->getName().str()+"_actual";
454
455 HDLt1.SCtype2hcode(objname, te->getTemplateArgTreePtr(),
456 &array_sizes, hNode::hdlopsEnum::hVardecl, h_ports);
457 mod_vname_map.add_entry(vardecl, objname, h_ports->child_list.back());
458 hNodep hparam_assign = new hNode("=", hNode::hdlopsEnum::hBinop);
459 hNodep hv = new hNode(mod_vname_map.find_entry_newn(vardecl), hNode::hdlopsEnum::hVarref);
460 hparam_assign->append(hv);
461 hv = new hNode(vardecl->getName().str(), hNode::hdlopsEnum::hVarref);
462 hparam_assign->append(hv);
463 hparam_assign_list->append(hparam_assign);
464 }
465
466 HDLt1.SCtype2hcode(vardecl->getName().str(), te->getTemplateArgTreePtr(),
467 &array_sizes, paramtype, hparams);
468 }
469
470 if (hparam_assign_list->child_list.size()>0) { // there were some actual parameters
471 hNodep htmpf = new hNode( hNode::hdlopsEnum::hCStmt);
472 if (isUserDefinedMethod) {
473 xbodyp->Run(m.first->getBody(), htmpf, ruserdefclass, &HDLt); // suppress output of unqualified name
474 }
475 else {
476 xbodyp->Run(m.first->getBody(), htmpf,rnomode);
477 }
478
479 hNodep hfunccstmt = htmpf->child_list.back(); // htmpf is list of vardecls followed by function body in a cstmt
480 hfunccstmt->child_list.insert(hfunccstmt->child_list.begin(), hparam_assign_list->child_list.begin(), hparam_assign_list->child_list.end());
481
482 hfunc->child_list.insert(hfunc->child_list.end(), htmpf->child_list.begin(), htmpf->child_list.end());
483
484 }
485 else {
486 if (isUserDefinedMethod) {
487 xbodyp->Run(m.first->getBody(), hfunc, ruserdefclass, &HDLt); // suppress output of unqualified name
488 }
489 else {
490 xbodyp->Run(m.first->getBody(), hfunc,rnomode);
491 }
492 }
493 } // num of parameters > 0
494 else {
495 LLVM_DEBUG(llvm::dbgs() << " No parameters found for " << m.second.newn << "\n");
496 hNodep htmpf = new hNode( hNode::hdlopsEnum::hCStmt);
497 xbodyp->Run(m.first->getBody(), htmpf,rnomode);
498 hfunc->child_list.insert(hfunc->child_list.end(), htmpf->child_list.begin(), htmpf->child_list.end());
499 }
500 // If this function invoked other functions, add them to the list to be generated
501 allmethodecls.insertall(xbodyp->methodecls); // if a function called
502 h_processes->child_list.push_back(hfunc);
503 // LLVM_DEBUG(m.second->dump(llvm::dbgs()));
504 } // end non-null body
505 }
506 }
507
508 h_module->print(HCodeOut);
509 // now generate submodules
510 delete xbodyp; // release this hdlbody
511
512 for (const auto &smod : submodv) {
513
514 string modname = mod_name_map.find_entry_newn(smod);
515 LLVM_DEBUG(llvm::dbgs() << "generate submodule " << smod->getName()
516 << " renamed " << modname << "\n");
517 hNodep h_submod = new hNode(modname, hNode::hdlopsEnum::hModule);
518 SCmodule2hcode(smod, h_submod, HCodeOut);
519 // }
520 }
521 }
522
523 void HDLMain::GenerateInstanceNames(ModuleInstance *smod, std::vector<std::string> &instnames) {
524 string basevarname = smod->getInstanceInfo().getVarName();
525 std::vector<llvm::APInt> arraysizes = smod->getInstanceInfo().getArraySizes();
526 //instnames = smod->getInstanceInfo().getInstanceNames();
527 int ndim = smod->getInstanceInfo().getArrayDimension();
528
529 if (ndim==0) {
530 instnames.push_back(basevarname);
531 return;
532 }
533
534 // convert the annoying APInt datatype
535 int array_dim[ndim];
536 for (int i = 0; i<ndim; i++) {
537 array_dim[i] = arraysizes[i].getSExtValue();
538 }
539
540 // in order of likelihood
541 // only handle up to 3D (front end restriction)
542 if (ndim==1) {
543 for (int i = 0; i < array_dim[0]; i++) {
544 string varname = basevarname;
545 varname.append("_" + to_string(i));
546 instnames.push_back(varname);
547 }
548 return;
549 }
550
551 if (ndim == 2) {
552 for (int i = 0; i < array_dim[0]; i++)
553 for (int j = 0; j < array_dim[1]; j++) {
554 string varname = basevarname;
555 varname.append("_" + to_string(i)+"_" + to_string(j));
556 instnames.push_back(varname);
557 }
558 return;
559 }
560
561 for (int i = 0; i <= array_dim[0]; i++)
562 for (int j = 0; j < array_dim[1]; j++)
563 for (int k = 0; k < array_dim[2]; k++) {
564 string varname = basevarname;
565 varname.append("_" + to_string(1)+"_" + to_string(j-1)+"_" + to_string(k-1));
566 instnames.push_back(varname);
567 }
568 }
569
570 bool HDLMain::isValidMethod(CXXMethodDecl *method) {
571 if ((method->getNameAsString() != (method->getParent()->getNameAsString() )) && // constructor
572 (method->getNameAsString() != "~"+ (method->getParent()->getNameAsString() )) && // destructor
573 (method->getBody() !=NULL)) // get rid of methods with empty body
574 return true;
575 else return false;
576 }
577
579 hNodep &h_info, hdecl_name_map_t &mod_vname_map) {
580 //clang::DiagnosticsEngine &diag_engine{getContext().getDiagnostics()};
581
582 const unsigned cxx_record_id1 = main_diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Remark, "Pointer type not synthesized, '%0' skipped.");
583 for (ModuleInstance::portMapType::iterator mit = pmap.begin(); mit != pmap.end();
584 mit++) {
585 string objname = get<0>(*mit);
586
587 LLVM_DEBUG(llvm::dbgs() << "object name is " << objname << " and h_op is "
588 << h_op << "\n");
589
590 PortDecl *pd = get<1>(*mit);
591 if (pd->isPointerType()) {
592 NamedDecl * decl = pd->getAsVarDecl();
593 if (decl == NULL) decl = pd->getAsFieldDecl();
594 if (decl !=NULL) {
595 clang::DiagnosticBuilder diag_builder{main_diag_engine.Report(decl->getLocation(), cxx_record_id1)};
596 diag_builder << decl->getName();
597 return;
598 }
599 return;
600 }
601
602 Tree<TemplateType> *template_argtp =
603 (pd->getTemplateType())->getTemplateArgTreePtr();
604
605 std::vector<llvm::APInt> array_sizes = pd->getArraySizes();
606
607 HDLt.SCtype2hcode(objname, template_argtp, &array_sizes, h_op,
608 h_info); // passing the sigvarlist
609
610 // if this is a duplicate name due to inheritance
611 // create a new name and add it to the module level vname map
612 // this map will be passed to all calls to HDLBody to merge into
613 // its vname_map
614
615 NamedDecl * portdecl = pd->getAsVarDecl();
616 if (!portdecl)
617 portdecl = pd->getAsFieldDecl();
618 if (module_vars.count(objname)) {
619 LLVM_DEBUG(llvm::dbgs() << "duplicate object " << objname << "\n");
620 if (portdecl) mod_vname_map.add_entry(portdecl, objname, h_info->child_list.back());
621 }
622 else {
623 module_vars.insert(objname);
624 // don't make new names for ports, will break logic in the modinit hcode processing
625 if ((h_op == hNode::hdlopsEnum::hVardecl) && (portdecl)) mod_vname_map.add_entry(portdecl, objname, h_info->child_list.back());
626 }
627
628 // check for initializer
629 if (h_op == hNode::hdlopsEnum::hVardecl) {
630 VarDecl *vard = pd->getAsVarDecl();
631 if (vard) {
632 LLVM_DEBUG(llvm::dbgs() << "var decl dump follows\n");
633 LLVM_DEBUG(vard->dump(llvm::dbgs()));
634 if (vard->hasInit()) {
635 APValue *apval = vard->getEvaluatedValue();
636 if (apval && apval->isInt()) {
637 hNodep h_lit = new hNode((systemc_clang::utils::apint::toString(apval->getInt())),
638 hNode::hdlopsEnum::hLiteral);
639 hNodep h_varinit = new hNode(hNode::hdlopsEnum::hVarInit);
640 h_varinit->child_list.push_back(h_lit);
641 (h_info->child_list.back())->child_list.push_back(h_varinit);
642 }
643 }
644 } else {
645 FieldDecl *fieldd = pd->getAsFieldDecl();
646 if (fieldd) {
647 LLVM_DEBUG(llvm::dbgs() << "field decl dump follows\n");
648 LLVM_DEBUG(fieldd->dump(llvm::dbgs()));
649 Expr* initializer = fieldd->getInClassInitializer();
650 if (initializer != NULL) {
651 LLVM_DEBUG(llvm::dbgs() << "field initializer dump follows\n");
652 LLVM_DEBUG(initializer->dump(llvm::dbgs(), getContext()));
653 hNodep h_init = new hNode(hNode::hdlopsEnum::hVarInit);
654 if (const CXXConstructExpr *ce = dyn_cast<CXXConstructExpr>(initializer->IgnoreUnlessSpelledInSource())) {
655 if (ce->isListInitialization()) {
656 for (const auto arg : ce->arguments()) {
657 const Expr *ex{arg->IgnoreUnlessSpelledInSource()};
658
659 if (auto il = dyn_cast<IntegerLiteral>(ex)) {
660 llvm::dbgs() << ">> IntegerLiteral value is " << il->getValue() << "\n";
661 h_init->append(new hNode(systemc_clang::utils::apint::toString(il->getValue()), hNode::hdlopsEnum::hLiteral));
662 }
663
664 if (auto booll = dyn_cast<CXXBoolLiteralExpr>(ex)) {
665 bool val = booll->getValue();
666 llvm::dbgs() << ">> CXXBoolLiteralExpr value is " << val << "\n";
667 h_init->append(new hNode(to_string(val), hNode::hdlopsEnum::hLiteral));
668 (h_info->child_list.back())->child_list.push_back(h_init);
669 }
670 }
671 }
672 }
673 else {
674 xbodyp->Run(initializer, h_init, rnomode);
675 (h_info->child_list.back())->child_list.push_back(h_init);
676 }
677 }
678 }
679 }
680 }
681 }
682 }
683
685 hNode::hdlopsEnum h_op, hNodep &h_info, hdecl_name_map_t &mod_vname_map) {
686
687 const unsigned cxx_record_id1 = main_diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Remark, "Pointer type not synthesized, '%0' skipped.");
688 const unsigned cxx_record_id2 = main_diag_engine.getCustomDiagID(clang::DiagnosticsEngine::Remark, "Class Constructor at module level not supported.");
689 for (ModuleInstance::signalMapType::iterator mit = pmap.begin();
690 mit != pmap.end(); mit++) {
691 string objname = get<0>(*mit);
692
693 // Unfortunately due to portdecl and sigdecl having incompatible data structures,
694 // the same code has to be repeated in both.
695 LLVM_DEBUG(llvm::dbgs() << "object name is " << objname << "\n");
696
697 SignalDecl *pd = get<1>(*mit);
698
699 if (pd->isPointerType()) {
700 NamedDecl * decl = pd->getAsVarDecl();
701 if (decl == NULL) decl = pd->getAsFieldDecl();
702 if (decl !=NULL) {
703 clang::DiagnosticBuilder diag_builder{main_diag_engine.Report(decl->getLocation(), cxx_record_id1)};
704 diag_builder << decl->getName();
705 return;
706 }
707 return;
708 }
709
710 Tree<TemplateType> *template_argtp =
711 (pd->getTemplateTypes())->getTemplateArgTreePtr();
712
713 int arr_size = pd->getArraySizes().size() > 0
714 ? pd->getArraySizes()[0].getLimitedValue()
715 : 0;
716 std::vector<llvm::APInt> array_sizes = pd->getArraySizes();
717 HDLt.SCtype2hcode(objname, template_argtp, &array_sizes, h_op,
718 h_info); // passing the sigvarlist
719
720 // if this is a duplicate name due to inheritance
721 // create a new name and add it to the module level vname map
722 // this map will be passed to all calls to HDLBody to merge into
723 // its vname_map
724
725 NamedDecl * portdecl = pd->getAsVarDecl();
726 if (!portdecl)
727 portdecl = pd->getAsFieldDecl();
728 else {
729 if (((VarDecl *)portdecl)->hasInit()) {
730 clang::DiagnosticBuilder diag_builder{main_diag_engine.Report(portdecl->getLocation(), cxx_record_id2)};
731 diag_builder << portdecl->getName();
732 }
733 }
734 // ValueDecl * vd = (ValueDecl *)portdecl;
735 // LLVM_DEBUG(llvm::dbgs() << "Sig type is " << vd->getType().getAsString() << "\n");
736 if (module_vars.count(objname)) {
737 LLVM_DEBUG(llvm::dbgs() << "duplicate object " << objname << "\n");
738 if (portdecl)
739 mod_vname_map.add_entry(portdecl, objname, h_info->child_list.back());
740 //string newn = mod_newn.newname();
741 //objname+="_var"+newn;
742 }
743 else {
744 module_vars.insert(objname);
745 if (portdecl) mod_vname_map.add_entry(portdecl, objname, h_info->child_list.back());
746 }
747 }
748 }
749
751 hdecl_name_map_t &mod_vname_map, overridden_method_map_t &overridden_method_map, resetvar_map_t &threadresetmap) {
752 // typedef std::map<std::string, ProcessDecl *> processMapType;
753 // processMapType getProcessMap();
754 // ProcessDecl::getEntryFunction() returns EntryFunctionContainer*
755
757 //
758 //clang::DiagnosticsEngine &diag_engine{getContext().getDiagnostics()};
759
760 const unsigned cxx_record_id1 = main_diag_engine.getCustomDiagID(
761 clang::DiagnosticsEngine::Remark, "non-SC_METHOD/THREAD '%0' skipped.");
762
763 for (auto const &pm_entry : pm) {
764 ProcessDecl *pd{get<1>(pm_entry)};
765 EntryFunctionContainer *efc{pd->getEntryFunction()};
766 if (efc->getProcessType() == PROCESS_TYPE::METHOD) {
767 hNodep h_process = new hNode(efc->getName(), hNode::hdlopsEnum::hProcess);
768 LLVM_DEBUG(llvm::dbgs() << "process " << efc->getName() << "\n");
769 CXXMethodDecl *emd = efc->getEntryMethod();
770 if (emd->hasBody()) {
771 hNodep h_body = new hNode(efc->getName(), hNode::hdlopsEnum::hMethod);
772 LLVM_DEBUG(llvm::dbgs() << "HDLMain allmethodecls_ size is " << allmethodecls.size() << "\n");
773 //HDLBody xmethod(emd, h_body, main_diag_engine, getContext(), mod_vname_map);
774 xbodyp->Run(emd->getBody(), h_body, rmethod);
776 h_process->child_list.push_back(h_body);
777 h_top->child_list.push_back(h_process);
778 } else {
779 LLVM_DEBUG(llvm::dbgs() << "Entry Method is null\n");
780 }
781 } else {
782 if ((efc->getProcessType() == PROCESS_TYPE::THREAD) ||
783 (efc->getProcessType() == PROCESS_TYPE::CTHREAD)) {
784 hNodep h_thread = new hNode(efc->getName(), hNode::hdlopsEnum::hProcess);
785 LLVM_DEBUG(llvm::dbgs() << "thread " << efc->getName() << "\n");
786 CXXMethodDecl *emd = efc->getEntryMethod();
787 if (emd->hasBody()) {
788
789 auto got = threadresetmap.find(efc->getName());
790 // should be an error if there isn't a reset var for this thread
791 clang::DiagnosticBuilder diag_builder{main_diag_engine.Report(
792 (efc->getEntryMethod())->getLocation(),
793 main_diag_engine.getCustomDiagID(
794 clang::DiagnosticsEngine::Remark, "Reset not found in SC_[C]THREAD."))};
795 diag_builder << "\n";
796 auto h_resetvarinfo = (got == threadresetmap.end() ? NULL : got->second);
797
798 // params includes portsigvarlist so thread local vars get promoted to module level
799 // have to pass efc to get the reset info
800
801 HDLThread xthread(efc, h_thread, h_port, main_diag_engine, getContext(), mod_vname_map, allmethodecls, overridden_method_map, h_resetvarinfo );
803 //h_thread->child_list.push_back(h_body);
804 h_top->child_list.push_back(h_thread);
805 } else {
806 LLVM_DEBUG(llvm::dbgs() << "Entry Thread is null\n");
807 }
808 }
809 else {
810 clang::DiagnosticBuilder diag_builder{main_diag_engine.Report((efc->getEntryMethod())->getLocation(), cxx_record_id1)};
811 diag_builder << efc->getName();
812
813 LLVM_DEBUG(llvm::dbgs() << "process " << efc->getName()
814 << " not SC_METHOD, THREAD, or CTHREAD, skipping\n");
815 }
816 }
817 }
818 }
819
820 void HDLMain::MakeResetMap( resetvar_map_t &threadresetmap, hNodep h_allsenslists)
821 {
822 // top node is a noop, then child list has the sensitivity lists:
823 //hNoop NONAME [
824 //hSenslist mc_proc [
825 //hSensvar NONAME [
826 //hVarref s_fp##valid NOLIST
827 //hNoop always NOLIST
828 // ]
829 // hSensvar NONAME [
830 // hVarref s_fp##data NOLIST
831 // hNoop always NOLIST
832 // ]
833 // or
834 //hSenslist break_in_for_wait0 [
835 // hSensvar ASYNC [
836 // hVarref arst NOLIST
837 // hLiteral 0 NOLIST
838 // ]
839 // ]
840
841 if (h_allsenslists != NULL) {
842 for (hNodep h_onesenslist : h_allsenslists->child_list) {
843 string threadname = h_onesenslist->getname();
844 for ( hNodep h_sensvar : h_onesenslist->child_list) {
845 if (h_sensvar->getname() == "NONAME") continue; // non-reset var has null hSensvar name
846 threadresetmap[threadname] = h_sensvar; // only one reset per thread
847 break;
848 }
849 }
850 }
851 }
852
853 // this is obsolete. It has been supeseded by HDLHnode.cpp
854 // due to possibility of for-loops enclosing port bindings
856 //systemc_clang::ModuleInstance::portBindingMapType portbindingmap,
857 hNodep &h_pbs) {
859 for (auto const &pb : portbindingmap) {
860 PortBinding *binding{get<1>(pb)};
861 string port_name{binding->getCallerPortName()};
862 LLVM_DEBUG(llvm::dbgs() << "SC port binding found Caller port name " << port_name
863 << " caller instance name " << binding->getCallerInstanceName()
864 << " <==> callee port name " << binding->getCalleePortName() <<
865 " callee instance name "
866 << binding->getCalleeInstanceName() << "\n");
867 if (binding->getCallerArraySubscripts().size() >0)
868 {
869 LLVM_DEBUG(llvm::dbgs() << "Caller Subscript vector length is " <<
870 binding->getCallerArraySubscripts().size() << "\n");
871 for (auto subscriptex: binding->getCallerArraySubscripts()) {
872 LLVM_DEBUG(subscriptex->dump(llvm::dbgs(), getContext()));
873 }
874 }
875 if (binding->getCalleeArraySubscripts().size()>0) {
876 LLVM_DEBUG(llvm::dbgs() << "Callee Subscript vector length is " <<
877 binding->getCalleeArraySubscripts().size() << "\n");
878 for (auto subscriptex: binding->getCalleeArraySubscripts()) {
879 LLVM_DEBUG(subscriptex->dump(llvm::dbgs(), getContext()));
880 }
881 }
882
883 hNodep hpb = new hNode(binding->getCallerInstanceName(), hNode::hdlopsEnum::hPortbinding);
884 // caller module name
885 hNodep hpb_caller = new hNode(port_name, hNode::hdlopsEnum::hVarref);
886 if (binding->getCallerPortArraySubscripts().size() >0) {
887 hpb_caller->child_list.push_back(new hNode("INDEX", hNode::hdlopsEnum::hLiteral)); //placeholder
888 }
889 hpb->child_list.push_back(hpb_caller);
890 string mapped_name = binding->getCalleeInstanceName();
891
892 // hpb->child_list.push_back(new hNode(binding->getBoundToName(),
893 // hNode::hdlopsEnum::hVarref));
894 hNodep hpb_callee = new hNode(mapped_name, hNode::hdlopsEnum::hVarref);
895 if (binding->getCalleeArraySubscripts().size() >0) {
896 hpb_callee->child_list.push_back(new hNode("INDEX", hNode::hdlopsEnum::hLiteral)); //placeholder
897 }
898 hpb->child_list.push_back(hpb_callee);
899
900 h_pbs->child_list.push_back(hpb);
901 }
902 }
903
904}
std::unordered_map< string, QualType > usertype_map_t
Definition HDLType.h:20
hNodep addtype(string typname, QualType qtyp, ASTContext &astcontext)
Definition HDLType.cpp:178
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
Definition HDLType.h:45
usertype_info_t usertype_info
Definition HDLType.h:44
void SCtype2hcode(string prefix, Tree< TemplateType > *template_argtp, std::vector< llvm::APInt > *arr_sizes, hNode::hdlopsEnum h_op, hNodep &h_info)
Definition HDLType.cpp:29
std::unordered_map< const clang::Type *, string > userrectype_map_t
Definition HDLType.h:21
string getname()
Definition hNode.h:169
void set(hdlopsEnum h, string s="")
Definition hNode.h:148
std::vector< hNodep > child_list
Definition hNode.h:109
void append(hNodep hnew)
Definition hNode.h:157
int size()
Definition hNode.h:161
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
Definition hNode.h:188
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
Definition hNode.h:617
method_object_map_t methodobjtypemap
Definition hNode.h:612
void insertall(hfunc_name_map_t newmap)
Definition hNode.h:613
void add_entry(T declp, string old_name, hNodep hnp)
Definition hNode.h:539
string find_entry_newn(T declp, bool set_ref=false)
Definition hNode.h:552
bool checkNamespace(const FunctionDecl *fd)
Definition hNode.h:267
bool isSCMacro(const std::string &str_in)
Definition hNode.h:430
Tree< TemplateType > * getTemplateArgTreePtr()
void Enumerate(const clang::Type *type)
ModuleInstance * getRootModuleInstance() const
Definition Model.cpp:29
Forward declarations.
const portMapType & getOtherVars()
const clang::CXXRecordDecl * getModuleClassDecl()
const portMapType & getIOPorts()
const portMapType & getOPorts()
const std::vector< ModuleInstance * > & getNestedModuleInstances() const
const portMapType & getOutputStreamPorts()
const portMapType & getInputStreamPorts()
const portBindingMapType & getPortBindings()
ModuleInstanceType getInstanceInfo()
std::string getInstanceName() const
void dump_base_instances(llvm::raw_ostream &os)
std::map< std::string, PortBinding * > portBindingMapType
const clang::CXXConstructorDecl * getConstructorDecl() const
const std::vector< ModuleInstance * > & getBaseInstances()
std::map< std::string, ProcessDecl * > processMapType
std::map< std::string, SignalDecl * > signalMapType
const processMapType & getProcessMap()
std::vector< std::tuple< std::string, PortDecl * > > portMapType
const portMapType & getIPorts()
const signalMapType & getSignals() const
const std::string getCallerPortName() const
Definition PortBinding.h:58
clang::VarDecl * getAsVarDecl() const
Definition PortDecl.cpp:83
clang::FieldDecl * getAsFieldDecl() const
Definition PortDecl.cpp:79
FindTemplateTypes * getTemplateType()
Definition PortDecl.cpp:87
std::vector< llvm::APInt > getArraySizes() const
Definition PortDecl.cpp:73
bool isPointerType() const
Definition PortDecl.cpp:56
FindTemplateTypes * getTemplateTypes()
Return the template types that were found.
clang::SourceManager & getSourceManager() const
clang::ASTContext & getContext() const
hfunc_name_map_t methodecls
Definition HDLBody.h:84
void Run(Stmt *stmt, hNodep &h_top, HDLBodyMode runmode, HDLType *HDLt_userclassesp=NULL)
Definition HDLBody.cpp:75
hNodep ProcessCXXConstructorHcode(hNodep xconstructor)
Definition HDLHnode.cpp:541
void GetSensLists(std::vector< hNodep > &hsens)
Definition HDLHnode.h:84
void SCport2hcode(ModuleInstance::portMapType pmap, hNode::hdlopsEnum h_op, hNodep &h_info, hdecl_name_map_t &mod_vname_map)
Definition HDLMain.cpp:578
clang::DiagnosticsEngine & main_diag_engine
Definition HDLMain.h:58
void SCportbindings2hcode(ModuleInstance *mod, hNodep &h_pb)
Definition HDLMain.cpp:855
hmodinst_name_map_t mod_name_map
Definition HDLMain.h:75
void SCmodule2hcode(ModuleInstance *mod, hNodep &h_module, llvm::raw_fd_ostream &SCout)
Definition HDLMain.cpp:135
void MakeResetMap(resetvar_map_t &threadresetmap, hNodep h_allsenslists)
Definition HDLMain.cpp:820
void SCsig2hcode(ModuleInstance::signalMapType pmap, hNode::hdlopsEnum h_op, hNodep &h_info, hdecl_name_map_t &mod_vname_map)
Definition HDLMain.cpp:684
void SCproc2hcode(ModuleInstance::processMapType pm, hNodep &h_top, hNodep &h_port, hdecl_name_map_t &mod_vname_map, overridden_method_map_t &overridden_method_map, resetvar_map_t &threadresetmap)
Definition HDLMain.cpp:750
HDLBody * xbodyp
Definition HDLMain.h:68
void GenerateInstanceNames(ModuleInstance *smod, std::vector< std::string > &instnames)
Definition HDLMain.cpp:523
resetvar_map_t threadresetmap
Definition HDLMain.h:64
std::unordered_set< string > module_vars
Definition HDLMain.h:62
bool isValidMethod(CXXMethodDecl *method)
Definition HDLMain.cpp:570
hfunc_name_map_t allmethodecls
Definition HDLMain.h:60
std::string hdl_file_out_
Command line options.
Definition HDLMain.h:78
hfunc_name_map_t methodecls
Definition HDLThread.h:32
Clang forward declarations.
Definition FindArgument.h:6
Definition hNode.h:24
std::unordered_map< string, hNodep > resetvar_map_t
Definition hNode.h:631
std::unordered_map< const CXXMethodDecl *, const CXXMethodDecl * > overridden_method_map_t
Definition hNode.h:628
ArraySizesType getConstantArraySizes(const clang::ValueDecl *fd)
std::string toString(const T &i)
Definition APIntUtils.h:14
std::string to_string(T *pointer)
Definition ProcessDecl.h:18
std::unique_ptr< clang::tooling::FrontendActionFactory > newFrontendActionFactory(const std::string &top_module)
Definition HDLMain.cpp:35
@ ruserdefclass
Definition HDLBody.h:32
userrectype_map_t userrectypes
Definition HDLType.h:28
usertype_map_t usertypes
Definition HDLType.h:25
unsigned int getArrayDimension() const
Return the array dimension, if the module instance is an array. 0 means a single instance k means kD ...
std::vector< llvm::APInt > getArraySizes()