systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
HDLHnode.cpp
Go to the documentation of this file.
1// clang-format off
2
3#include <assert.h>
4#include "HDLHnode.h"
5
6#include "assert.h"
7
8#include "clang/Basic/Diagnostic.h"
9
10// clang-format on
11
13#undef DEBUG_TYPE
14#define DEBUG_TYPE "HDL"
15
22namespace systemc_hdl {
23
24 bool is_numeric(string &s) {
25 for (char c : s) {
26 if (!isdigit(c)) return false;
27 }
28 return true;
29 }
30
32 bool ret;
33 //hVarAssign NONAME [
34 // hVarref mc_proc_handle_u_fifo_local_0 NOLIST
35 // hBuiltinFunction create_method_process [
36 // hLiteral 0 NOLIST
37 // hUnop & [
38 // hMethodCall fifo_ccfp_t11_52_5_true_false_false__mc_proc:mc_proc NOLIST
39 // ]
40 // hLiteral 0 NOLIST
41 // ]
42 // ]
43
44 if ((hp->getopc()==hNode::hdlopsEnum::hVarAssign) &&
45 (hp->size()>0) &&
46 (hp->child_list[0]->getopc() == hNode::hdlopsEnum::hVarref) &&
47 (hp->child_list[0]->getname().find("_handle_")!=std::string::npos))
48 return true;
49
50 //hVardeclrn mc_proc_handle_u_fifo_local_0 [
51 // hTypeinfo NONAME [
52 // hType sc_process_handle NOLIST
53 // ]
54 // hLiteral mc_proc_handle NOLIST
55
56 if ((hp->getopc()==hNode::hdlopsEnum::hVardeclrn) &&
57 (hp->getname().find("_handle_")!=std::string::npos))
58 return true;
59 if (hp->getname() == "sc_process_handle") return true;
60 if ((hp->getopc()==hNode::hdlopsEnum::hBuiltinFunction) &&
61 (hp->getname().find("create_method_process")!=std::string::npos))
62 return true;
63 return false;
64 }
65
67
68 hp->child_list.erase( std::remove_if( hp->child_list.begin(), hp->child_list.end(), [&] (hNodep x) {
69 return (
70 //((x->h_op==hNode::hdlopsEnum::hVarAssign) &&
71 //(x->child_list.size()==2) &&
72 //(x->child_list.back()->h_op != hNode::hdlopsEnum::hLiteral)) ||
73 (x->h_op == hNode::hdlopsEnum::hVardecl) || // index variables
74 //(x->h_op == hNode::hdlopsEnum::hMethodCall) || // sc_method
75 (x->h_op == hNode::hdlopsEnum::hReturnStmt) || // remove return stmt in init block
76 (x->h_op == hNode::hdlopsEnum::hUnimpl));}), hp->child_list.end() );
77
78 for (hNodep hpi :hp->child_list)
79 RemoveSCMethod(hpi);
80 }
81
83 for (hNodep hpi :hp->child_list)
84 CleanupInitHcode(hpi);
85 hp->child_list.erase( std::remove_if( hp->child_list.begin(), hp->child_list.end(), [] (hNodep x) {
86 return (
87 ((x->h_op==hNode::hdlopsEnum::hBinop) &&
88 (x->h_name==pbstring) || (x->h_name==sensop))
89 ||
90 //hVarAssign NONAME [
91 // hVarref mc_proc_handle_u_fifo_local_0 NOLIST
92 // hBuiltinFunction create_method_process [
93 // hLiteral 0 NOLIST
94 // hUnop & [
95 // hMethodCall fifo_ccfp_t11_52_5_true_false_false__mc_proc:mc_proc NOLIST
96 // ]
97 // hLiteral 0 NOLIST
98 // ]
99 // ]
100 (((x->getopc()==hNode::hdlopsEnum::hVarAssign) || (x->getopc()==hNode::hdlopsEnum::hSensvar)) &&
101 (x->size()>0) &&
102 (x->child_list[0]->getopc() == hNode::hdlopsEnum::hVarref) &&
103 (x->child_list[0]->getname().find("_handle_")!=std::string::npos))
104 ||
105
106 //hVardeclrn mc_proc_handle_u_fifo_local_0 [
107 // hTypeinfo NONAME [
108 // hType sc_process_handle NOLIST
109 // ]
110 // hLiteral mc_proc_handle NOLIST
111
112 ((x->getopc()==hNode::hdlopsEnum::hVardeclrn) &&
113 (x->getname().find("_handle_")!=std::string::npos))
114 ||
115
116 //(isSimRelated(x)) ||
117 //((x->h_op == hNode::hdlopsEnum::hSensvar) && // gratuitous sim method sens vars
118 //(x->child_list[0]->h_name.find(localstr) != std::string::npos)) ||
119 //(x->h_op==hNode::hdlopsEnum::hForStmt) ||
120 //(x->h_op == hNode::hdlopsEnum::hVardeclrn) || // renamed index variables
121 ((x->h_op==hNode::hdlopsEnum::hCStmt) &&
122 (x->child_list.empty())) ||
123 //(x->h_op==hNode::hdlopsEnum::hVarAssign) ||
124 ((x->h_op == hNode::hdlopsEnum::hVarref) && (x->h_name == "sensitive")) ||
125 (isMorF(x->h_op) && (x->h_name.find(strsccore) !=std::string::npos)) ||
126 ((x->h_op == hNode::hdlopsEnum::hNoop) &&
127 (x->h_name==arrsub)));}), hp->child_list.end());
128 // for (hNodep hpi :hp->child_list)
129 // CleanupInitHcode(hpi);
130
131 }
132
162
163 void HDLConstructorHcode::PushRange(hNodep &hp, std::vector<for_info_t> &for_info) {
164
165 for_info_t tmp{"FORNAME", 0, 1, 1, 0};
166 for_info.push_back(tmp);
167 return; // using generate, no need to symbolically traverse for loop to unroll bindings
168
169 hNodep hlo = hp->child_list[0];
170 hNodep hi = hp->child_list[1];
171 hNodep hstep = hp->child_list[2];
172
173 if ((hlo->h_op == hNode::hdlopsEnum::hVarAssign) &&
174 (hlo->child_list.size() == 2) &&
175 (hlo->child_list[0]-> h_op == hNode::hdlopsEnum::hVarref) &&
176 (hlo->child_list[1]->h_op == hNode::hdlopsEnum::hLiteral)) {
177 tmp.name = hlo->child_list[0]->h_name;
178 //FIXME -- put in error message if not a numeric constant
179 if (is_numeric(hlo->child_list[1]->h_name))
180 tmp.lo = stoi(hlo->child_list[1]->h_name);
181 }
182 if ((hi->h_op == hNode::hdlopsEnum::hBinop) &&
183 (hlo->child_list.size() == 2) &&
184 (hlo->child_list[0]-> h_op == hNode::hdlopsEnum::hVarref) &&
185 (hlo->child_list[1]->h_op == hNode::hdlopsEnum::hLiteral)) {
186 //FIXME -- check that names are same ... tmp.name = hi->child_list[0]->h_name;
187 //FIXME -- put in error message if not a numeric constant
188 if (is_numeric(hi->child_list[1]->h_name))
189 tmp.hi = stoi(hi->child_list[1]->h_name);
190 }
191 for_info.push_back(tmp);
192
193 }
194
195 void HDLConstructorHcode::PopRange(std::vector<for_info_t> &for_info) {
196 for_info.pop_back();
197 }
198
199 void HDLConstructorHcode::SubstituteIndex(hNodep &hp, std::vector<for_info_t> &for_info) {
200 for (int i=0; i < for_info.size(); i++) {
201 if ((hp->h_op == hNode::hdlopsEnum::hVarref) && (hp->h_name == for_info[i].name)) {
202 hp->h_name = to_string(for_info[i].curix);
203 hp->h_op = hNode::hdlopsEnum::hLiteral;
204 break;
205 }
206 }
207 for (hNodep hpi : hp->child_list)
208 SubstituteIndex(hpi, for_info);
209 }
210
212 hNodep h_ret = new hNode(hp->h_name, hp->h_op);
213 for (hNodep hchild : hp->child_list) {
214 h_ret->child_list.push_back(HnodeDeepCopy(hchild));
215 }
216 return h_ret;
217 }
218
220 string tmpstr;
221 if (hp == NULL) return "";
222 if ((hp->getopc() == hNode::hdlopsEnum::hBinop) && (hp->getname() == "ARRAYSUBSCRIPT")) {
223 return ExtractModuleName(hp->child_list[0]);
224 }
225 else if (hp->getopc() == hNode::hdlopsEnum::hVarref) {
226 if (hp->size() == 0) {
227 tmpstr = hp->getname();
228 int delimix = tmpstr.find(fielddelim);
229 if (delimix != string::npos) {
230 hp->set(tmpstr.substr(tmpstr.find(fielddelim)+fielddelim.size()));
231 return tmpstr.substr(0, tmpstr.find(fielddelim));
232 }
233 else return tmpstr;
234 }
235 else { // Varref with child node(s)
236 return ExtractModuleName(hp->child_list[0]);
237 }
238 }
239 return "";
240
241 }
242
243 void HDLConstructorHcode::UnrollBinding(hNodep &hp_orig, std::vector<for_info_t> &for_info) {
244
245 assert ((hp_orig->h_op == hNode::hdlopsEnum::hBinop) && (hp_orig->h_name == pbstring));
246 hp_orig->set(hNode::hdlopsEnum::hPortbinding, ExtractModuleName(hp_orig->child_list[0]));
247 hnewpb->append(hp_orig);
248 return;
249 }
250
251
253
254 // hMethodCall sc_coresc_simcontextcreate_method_process:create_method_process [
255 // hMethodCall sc_coresc_get_curr_simcontext:sc_get_curr_simcontext NOLIST
256 // hUnimpl StringLiteral NOLIST
257 // hLiteral 0 NOLIST
258 // hUnop & [
259 // hMethodCall zhwencode_blockfp_t11_52_2mc_proc:mc_proc NOLIST
260 // ]
261 // hUnimpl CXXThisExpr NOLIST
262 // hLiteral 0 NOLIST
263 // ]
264
265 if (isMorF(hp->h_op)) {
266 for (hNodep hpi: hp->child_list) {
267 if (hpi->h_op == hNode::hdlopsEnum::hUnop) {
268 std::size_t found = (hpi->child_list[0]->h_name).find(qualnamedelim);
269 if ( found != std::string::npos) { // should be SC_METHOD name
270 hnewsens.push_back(new hNode(hpi->child_list[0]->h_name.substr(found+1),
271 hNode::hdlopsEnum::hSenslist));
272 return true; // got the name
273 }
274 else { // couldn't find the ":"
275 hnewsens.push_back(new hNode(hpi->child_list[0]->h_name, hNode::hdlopsEnum::hSenslist));
276 return true;
277 }
278 }
279 }
280 }
281 return false;
282 }
283
284 void HDLConstructorHcode::UnrollSensitem(hNodep &hp_orig, std::vector<for_info_t> &for_info) {
285
286 // hBinop << [
287 // hVarref sensitive NOLIST
288 // hNoop pos [
289 // hVarref clk NOLIST
290 // ]
291 // ]
292
293 // check for list of sens items
294 if (isInitSensitem(hp_orig->child_list[0])) {
295 UnrollSensitem(hp_orig->child_list[0], for_info);
296 }
297
298 // at a primitive sens item
299 hNodep hp = HnodeDeepCopy(hp_orig); // need to keep the subtrees when the original tree gets released
300
301 hp->h_op = hNode::hdlopsEnum::hSensvar;
302 hp->h_name = noname;
303
304 delete hp->child_list[0]; // release that hnode
305 hp->child_list.erase(hp->child_list.begin()); // remove the first item
306 // if (!for_info.empty()) {
307 // SubstituteIndex(hp, for_info);
308 //}
309
310 // check for edge sensitivity
311 // eg
312 // hSensvar pos [ <-- hp
313 // hNoop pos [ <-- hedge
314 // hVarref clk NOLIST <-- hedge->child_list[0]
315 // ]
316 // ]
317
318 if (isEdge(hp->child_list[0]->h_name)) {
319 hNodep hedge = hp->child_list[0];
320 hp->child_list[0] = hedge->child_list[0];
321 hedge->child_list.pop_back();
322 hp->child_list.push_back(hedge);
323 }
324 else {
325
326 if (isSimEvent(hp->child_list[0]->h_name)) {
327
328 // hSensvar NONAME [
329 // hNoop value_changed_event [
330 // hVarref c_fp##ready NOLIST
331 // ]
332 // hNoop always NOLIST
333 // ]
334
335 hNodep htmp = hp->child_list[0]->child_list[0];
336 hp->child_list.erase(hp->child_list.begin());
337 hp->child_list.push_back(htmp);
338 }
339
340 hp->child_list.push_back(new hNode("always", hNode::hdlopsEnum::hNoop));
341 };
342
343 if (!for_info.empty()) {
344 if (hnewsens.size() >0) hp->set(hnewsens.back()->getname());
345 hp_orig = hp; // this caused the array sens item to be generated in the for loop.
346 }
347
348 else hnewsens.back()->child_list.push_back(hp);
349
350 }
351
352 void HDLConstructorHcode::HDLLoop(hNodep &hp, std::vector<for_info_t> &for_info ) {
353 // check in order of expected frequency
354 if (isInitPB(hp)) {
355 UnrollBinding(hp, for_info);
356 }
357 else if (isInitSensitem(hp)) {
358 UnrollSensitem(hp, for_info);
359 }
360
361 else if ((hp->h_op == hNode::hdlopsEnum::hForStmt) && (hp->child_list.size() > 3)) {
362 PushRange(hp, for_info); // fill in name, lo, hi, step
363 for (int forloopix = for_info.back().lo; forloopix < for_info.back().hi; forloopix+=for_info.back().step) {
364 for_info.back().curix = forloopix;
365 for (int i=3; i<hp->child_list.size(); i++) {
366 if (isInitPB(hp->child_list[i])) {// hcode indicating port binding
367 UnrollBinding(hp->child_list[i], for_info); // unroll all bindings in this range
368 }
369 else if (isInitSensitem(hp->child_list[i])) { // hcode indicating sensitivity item
370 UnrollSensitem(hp->child_list[i], for_info); // unroll all sensitems in this range
371 }
372 else if ((hp->child_list[i]->h_op == hNode::hdlopsEnum::hForStmt) ||
373 (hp->child_list[i]->h_op == hNode::hdlopsEnum::hCStmt))
374 HDLLoop(hp->child_list[i], for_info);
375 }
376 }
377 for_info.pop_back();
378 }
379 else if (hp->h_op == hNode::hdlopsEnum::hCStmt) {
380 for (hNodep hpc:hp->child_list) {
381 HDLLoop(hpc, for_info);
382 }
383 }
384 else if (isMethodCall(hp)) { // hVarAssign child[1] is a method call;
385 if (!SetupSenslist(hp->child_list[1])) { // points to first hMethodCall, push SC_METHOD name onto hnewsens
386 // oops couldn't parse it
387 hnewsens.push_back(new hNode( "METHOD ???", hNode::hdlopsEnum::hSenslist));
388 }
389 }
390 else {
391 // check for thread sensitivity declarations
392 int threadsensitem = isThreadSensitem(hp);
393 if (threadsensitem >0 ) {
394 // e.g. hMethodCall sc_core__sc_module__async_reset_signal_is:async_reset_signal_is [
395 // hVarref reset NOLIST
396 // hLiteral 0 NOLIST
397 // ]
398 LLVM_DEBUG(llvm::dbgs() << "HDLHNode: found thread sens item " << "\n");
399 hNodep hpsens = HnodeDeepCopy(hp); // need to keep the subtrees when the original tree gets released
400
401 hpsens->set(hNode::hdlopsEnum::hSensvar, threadsensitem == reset_async? "ASYNC": "SYNC");
402 if (hnewsens.size()==0) // this shouldn't be the case, but whatever
403 hnewsens.push_back(new hNode( "METHOD ???", hNode::hdlopsEnum::hSenslist));
404 hnewsens.back()->append(hpsens);
405 }
406 }
407 }
408
409
411
412 std::vector<for_info_t> for_info;
413
414 if (xconstructor==nullptr) return xconstructor;
415
416 // this is a workaround to make lldb find dumphcode
417 // since lldb doesn't pick up default parameters in print
418 // and doesn't recognize llvm::outs()
419 { int junk =2; if (junk!=2) xconstructor->dumphcode();}
420
421 RemoveSCMethod(xconstructor);
422 hnewpb = new hNode(xconstructor->h_name, hNode::hdlopsEnum::hPortbindings);
423 // FIXME name should be the SC_METHOD name
424 //hnewsens = new hNode(xconstructor->h_name, hNode::hdlopsEnum::hSenslist);
425 for (hNodep hp : xconstructor->child_list)
426 HDLLoop(hp, for_info);
427 // if (!hnewpb->child_list.empty()) {
428 // xconstructor->child_list.push_back(hnewpb);
429 // }
430 if (!hnewsens.empty()) {
431 if ( (xconstructor->size() == 1) && (xconstructor->child_list[0]->getopc()==hNode::hdlopsEnum::hCStmt)) {
432 hNodep hcstmtp = xconstructor->child_list[0];
433 hcstmtp->child_list.insert(hcstmtp->child_list.end(), hnewsens.begin(), hnewsens.end());
434 }
435 else xconstructor->child_list.insert( xconstructor->child_list.end(), hnewsens.begin(), hnewsens.end());
436 }
437 CleanupInitHcode(xconstructor);
438 return xconstructor;
439 }
440
441 // legacy code to manyally unroll for loop bindings
442 #if 0
443 // Generate a port binding
444 // need to dismantle modname##field:
445 // modname is the h_name for the portbinding
446 // and field is the varref, e.g.
447 // Case 0: hBinop () [
448 // hVarref u_fwd_cast##clk NOLIST
449 // hVarref clk NOLIST
450 // but if the submod instance/port is ARRAYSUBSCRIPT in loop,
451 // can have (if submodule is not an array of submods)
452 // Case 1: hBinop () [
453 // hBinop ARRAYSUBSCRIPT [
454 // hVarref u_fwd_cast##m_block NOLIST
455 // hVarref _local_0 NOLIST
456 // ]
457 // hBinop ARRAYSUBSCRIPT [
458 // hVarref c_fc_block NOLIST
459 // hVarref _local_0 NOLIST
460 // ]
461 // ]
462 // ]
463
464 // or it will look like this if submod is array ( u_yt[_local_0].clk:clk )
465 // Case 2: hBinop () [
466 // hVarref clk [
467 // hBinop ARRAYSUBSCRIPT [
468 // hVarref u_yt NOLIST
469 // hVarref _local_0 NOLIST
470 // ]
471 // ]
472 // hVarref clk NOLIST
473 // ]
474 // or for module instance array ref and port array ref
475 //
476 // Case 3: hBinop () [
477 // hBinop ARRAYSUBSCRIPT [
478 // hVarref m_port [
479 // hBinop ARRAYSUBSCRIPT [
480 // hVarref u_xt NOLIST
481 // hVarref _local_0 NOLIST
482 // ]
483 // ]
484 // hVarref _local_1 NOLIST
485 // ]
486 // hBinop ARRAYSUBSCRIPT [
487 // hBinop ARRAYSUBSCRIPT [
488 // hVarref c_xt_data NOLIST
489 // hVarref _local_0 NOLIST
490 // ]
491 // hVarref _local_1 NOLIST
492 // ]
493 // ]
494 void HDLConstructorHcode::UnrollBindingNotUsed(hNodep &hp_orig, std::vector<for_info_t> &for_info) {
495
496 assert ((hp_orig->h_op == hNode::hdlopsEnum::hBinop) && (hp_orig->h_name == pbstring));
497 hp_orig->set(hNode::hdlopsEnum::hPortbinding, ExtractModuleName(hp_orig->child_list[0]));
498 hnewpb->append(hp_orig);
499 return;
500
501 // Case 0
502 if (for_info.empty()) { // simple case, not in a for loop
503 string submodport;
504 string thismodsig;
505 hNodep hpb;
506 if (hp_orig->child_list[0]->getopc() == hNode::hdlopsEnum::hVarref) {
507 submodport = hp_orig->child_list[0]->h_name;
508 // part before delimiter is submodule name, after delimiter is port name
509
510 hpb = new hNode(submodport.substr(0, submodport.find(fielddelim)),
511 hNode::hdlopsEnum::hPortbinding);
512 hpb->child_list.push_back(new hNode(submodport.substr(submodport.find(fielddelim)+fielddelim.size()),
513 hNode::hdlopsEnum::hVarref));
514 }
515 else {
516 submodport = ExtractModuleName(hp_orig->child_list[0]);
517 hpb = new hNode(submodport, hNode::hdlopsEnum::hPortbinding);
518 hpb->append(hp_orig->child_list[0]); // need to remove module name
519 }
520 if (hp_orig->child_list[1]->getopc() == hNode::hdlopsEnum::hVarref) {
521 thismodsig = hp_orig->child_list[1]->h_name;
522 hpb->child_list.push_back(new hNode(thismodsig, hNode::hdlopsEnum::hVarref));
523 }
524 else {
525 hpb->append(hp_orig->child_list[1]); // need to remove module name
526 }
527 hnewpb->child_list.push_back(hpb);
528 return;
529 }
530
531 hNodep hp = HnodeDeepCopy(hp_orig); // will be modifying subtrees, so make a copy
532
533 hNodep hsubmodport = hp->child_list[0]; // submoduleport being bound
534 hNodep hthismodsig = hp->child_list[1];
535
536 string submodport{"XXX"}, thismodsig{"YYY"};
537 string submod{"SUBMOD"};
538
539 // Case 2
540 if ((hsubmodport->h_op == hNode::hdlopsEnum::hVarref) && (hsubmodport->child_list.size() > 0)) {
541
542 // in a for loop, unroll the port bindings
543 // hVarref clk [
544 // hBinop ARRAYSUBSCRIPT [
545 // hVarref u_yt NOLIST
546 // hVarref _local_0 NOLIST // changed to hLiteral by Substitute index
547 // ]
548 // ]
549 // hVarref clk NOLIST
550 // ]
551 hNodep hportchild = hsubmodport->child_list[0];
552 hNodep hparent = hsubmodport;
553 std::vector<hNodep> hmodarrix;
554 // look for submodule name
555 while ((hportchild != nullptr) && (hportchild->h_name == arrsub)) {
556 hmodarrix.push_back(hportchild->child_list[1]); // save i in A[i]
557 if ((hportchild->child_list[0]->h_op == hNode::hdlopsEnum::hVarref) &&
558 (hportchild->child_list[0]->child_list.empty())) { // simple varref of A
559 submod = hportchild->child_list[0]->h_name;
560 break;
561 }
562 hparent = hportchild;
563 hportchild = hportchild->child_list[0];
564 }
565 for (hNodep hsubmodixname:hmodarrix) {
566 // assume simple case of "i" not "i+1" or "i+j"
567 assert((hsubmodixname->h_op == hNode::hdlopsEnum::hVarref) && "Submodule index must be simple loop variable name");
568 string ixname = hsubmodixname->h_name;
569 for (int i = 0; i < for_info.size(); i++) {
570 if (for_info[i].name == ixname) {
571 submod+=tokendelim+to_string(for_info[i].curix);
572 break;
573 }
574 }
575 }
576 if (hsubmodport->child_list[0]->h_name == arrsub) {
577 hsubmodport->child_list.erase(hsubmodport->child_list.begin());
578 }
579 }
580 else if (hsubmodport->h_name == arrsub) { // check Case 1, 3
581 // Case 1: hBinop () [
582 // hBinop ARRAYSUBSCRIPT [
583 // hVarref u_fwd_cast##m_block NOLIST
584 // hVarref _local_0 NOLIST
585 // ]
586 // hBinop ARRAYSUBSCRIPT [
587 // hVarref c_fc_block NOLIST
588 // hVarref _local_0 NOLIST
589 // ]
590 // ]
591 // ]
592
593 // Case 3: hBinop () [
594 // hBinop ARRAYSUBSCRIPT [
595 // hVarref m_port [
596 // hBinop ARRAYSUBSCRIPT [
597 // hVarref u_xt NOLIST
598 // hVarref _local_0 NOLIST
599 // ]
600 // ]
601 // hVarref _local_1 NOLIST
602 // ]
603 // hBinop ARRAYSUBSCRIPT [
604 // hBinop ARRAYSUBSCRIPT [
605 // hVarref c_xt_data NOLIST
606 // hVarref _local_0 NOLIST
607 // ]
608 // hVarref _local_1 NOLIST
609 // ]
610 // ]
611
612 hNodep hportchild = hsubmodport->child_list[0];
613 hNodep hparent = hsubmodport;
614 std::vector<hNodep> hmodarrix;
615
616 while ((hportchild != nullptr) &&
617 ((hportchild->h_name == arrsub) ||
618 ((hportchild->h_op == hNode::hdlopsEnum::hVarref) &&
619 (hportchild->child_list.size() > 0)))) {
620 if (hportchild->h_name == arrsub) {
621 hmodarrix.push_back(hportchild->child_list[1]); // save i in A[i]
622 }
623 hparent = hportchild;
624 hportchild = hportchild->child_list[0];
625 }
626 if ((hportchild != nullptr) && (hportchild->h_op == hNode::hdlopsEnum::hVarref)) {
627 if (hportchild->child_list.empty()) { // Case 1
628 submod = hportchild->h_name;
629 size_t found = submod.find(fielddelim);
630 if ( found != std::string::npos) { // module name prefix, not a vector of modules
631 hportchild->h_name = submod.substr(found+fielddelim.size());
632 submod = submod.substr(0, found);
633 }
634 else { // Varref has child; need to handle Case 3 by removing the (arraysubscript submod ix) node
635 for (hNodep hsubmodixname:hmodarrix) {
636 // assume simple case of "i" not "i+1" or "i+j"
637 assert((hsubmodixname->h_op == hNode::hdlopsEnum::hVarref) && "Submodule index must be simple loop variable name");
638 string ixname = hsubmodixname->h_name;
639 for (int i = 0; i < for_info.size(); i++) {
640 if (for_info[i].name == ixname) {
641 submod+=tokendelim+to_string(for_info[i].curix);
642 break;
643 }
644 }
645 }
646 hparent = hsubmodport;
647 hportchild = hsubmodport->child_list[0];
648 while ((hportchild != nullptr) && (hportchild->h_name != arrsub)) {
649 hparent = hportchild;
650 hportchild = hportchild->child_list[0];
651 }
652 if (hportchild != nullptr) { // it's an array subscript
653 hparent->child_list.erase(hparent->child_list.begin());
654 }
655 }
656 }
657 }
658 }
659
660 hNodep hpb = new hNode( submod, hNode::hdlopsEnum::hPortbinding);
661 //hpb->child_list.push_back(new hNode(submodport+tokendelim+to_string(i), hNode::hdlopsEnum::hVarref));
662 //hpb->child_list.push_back(new hNode(thismodsig+tokendelim+to_string(i), hNode::hdlopsEnum::hVarref));
663
664 hpb->child_list.push_back(hsubmodport);
665 hpb->child_list.push_back(hthismodsig);
666 SubstituteIndex(hpb, for_info);
667 hnewpb->child_list.push_back(hpb);
668 }
669
670#endif
671}
void dumphcode()
Definition hNode.h:211
hdlopsEnum h_op
Definition hNode.h:107
hdlopsEnum getopc()
Definition hNode.h:173
string getname()
Definition hNode.h:169
string h_name
Definition hNode.h:106
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 UnrollSensitem(hNodep &hp_orig, std::vector< for_info_t > &for_info)
Definition HDLHnode.cpp:284
void UnrollBinding(hNodep &hp_orig, std::vector< for_info_t > &for_info)
Definition HDLHnode.cpp:243
void SubstituteIndex(hNodep &hp, std::vector< for_info_t > &for_info)
Definition HDLHnode.cpp:199
hNodep ProcessCXXConstructorHcode(hNodep xconstructor)
Definition HDLHnode.cpp:410
void PushRange(hNodep &hp, std::vector< for_info_t > &for_info)
Definition HDLHnode.cpp:163
void CleanupInitHcode(hNodep &hp)
Definition HDLHnode.cpp:82
string ExtractModuleName(hNodep hp)
Definition HDLHnode.cpp:219
void PopRange(std::vector< for_info_t > &for_info)
Definition HDLHnode.cpp:195
void RemoveSCMethod(hNodep &hp)
Definition HDLHnode.cpp:66
hNodep HnodeDeepCopy(hNodep hp)
Definition HDLHnode.cpp:211
void HDLLoop(hNodep &hp, std::vector< for_info_t > &for_info)
Definition HDLHnode.cpp:352
std::vector< hNodep > hnewsens
Definition HDLHnode.h:104
std::string to_string(T *pointer)
Definition ProcessDecl.h:18
bool is_numeric(string &s)
Definition HDLHnode.cpp:24