8#define DEBUG_TYPE "HDL"
25 clang::DiagnosticsEngine &diag_engine,
28 : efc_(efc), h_top_{h_top}, diag_e{diag_engine}, ast_context_{ast_context},
29 mod_vname_map_{mod_vname_map}, allmethodecls_{allmethodecls}, overridden_method_map_{overridden_method_map},
30 h_resetvarinfo_{h_resetvarinfo}, scfg{const_cast<ASTContext &>(ast_context), efc->getEntryMethod()} {
32 LLVM_DEBUG(llvm::dbgs() <<
"Entering HDLThread constructor (thread body)\n");
39 string threadname = h_top->
getname();
57 hNodep hthreadblockcstmt =
new hNode(hNode::hdlopsEnum::hCStmt);
63 LLVM_DEBUG(llvm::dbgs() <<
"Dumping scfg paths.\n");
67 const llvm::SmallVectorImpl<llvm::SmallVector<SplitCFG::SplitCFGPathPair>> &paths_found{
scfg.
getPathsFound()};
76 for (state_num = 0; state_num < paths_found.size(); state_num++) {
81 hNodep h_switchcase =
new hNode( hNode::hdlopsEnum::hSwitchCase);
82 h_switchcase->
append(
new hNode(std::to_string(state_num), hNode::hdlopsEnum::hLiteral));
84 paths_found[state_num].size(),
85 state_num, h_switchcase);
86 hthreadblockcstmt->
append(h_switchcase);
91 hNodep h_switchcase =
new hNode( hNode::hdlopsEnum::hSwitchCase);
94 hthreadblockcstmt->
append(h_switchcase);
100 hNodep h_shadowvarsp =
new hNode(hNode::hdlopsEnum::hPortsigvarlist);
103 if (var.second.referenced) {
105 hNodep hs =
new hNode(var.second.h_vardeclp->getname(), var.second.h_vardeclp->getopc());
106 hs->
child_list = var.second.h_vardeclp->child_list;
107 h_shadowvarsp->
append(hs);
108 if (var.second.newn.find(hnode::gvar_prefix) != string::npos)
130 hthreadmainmethod->
append(
new hNode(threadname+
"_func", hNode::hdlopsEnum::hMethodCall));
136 hNodep hfunctop =
new hNode(threadname+
"_func", hNode::hdlopsEnum::hFunction);
137 hfunctop->
append(
new hNode(hNode::hdlopsEnum::hFunctionRetType));
138 hNodep hcstmttmp =
new hNode(hNode::hdlopsEnum::hCStmt);
140 hfunctop->
append(hcstmttmp);
153 hNodep hstatemethod =
new hNode(threadname+
"_state_update", hNode::hdlopsEnum::hMethod);
155 h_top->
append(hstatemethod);
157 h_top->
append(hthreadmainmethod);
161 std::remove_if( h_shadowvarsp->
child_list.begin(),
163 return (x->getname().find(hnode::gvar_prefix) != string::npos);}),
171 if (h_shadowvarsp->
size()>0) {
186 LLVM_DEBUG(llvm::dbgs() <<
"[[ Destructor HDLThread ]]\n");
190 if (isa<BreakStmt>(S))
return true;
191 if (isa<ContinueStmt>(S))
return true;
196 return ((hp->
child_list.size() >=1) and ((hp->
child_list.back())->getopc() == hNode::hdlopsEnum::hWait));
202 if ((oneop != NULL) && ((oneop->getopc() == hNode::hdlopsEnum::hVardecl) || (oneop->getopc() == hNode::hdlopsEnum::hSigdecl))) {
203 LLVM_DEBUG(llvm::dbgs() <<
"Detected vardecl for SG Block ID " << blockid <<
"\n");
207 LLVM_DEBUG(llvm::dbgs() <<
"SGVisited for blockid " <<
SGVisited[blockid]
208 <<
" " << blockid <<
"\n");
229 for (
auto *DI : declstmt->decls()) {
231 auto *vardecl = dyn_cast<VarDecl>(DI);
232 if (!vardecl)
continue;
233 if ( Expr *declinit = vardecl->getInit()) {
234 Stmt * cdeclinit = declinit;
237 hNodep varinitp =
new hNode(hNode::hdlopsEnum::hVarAssign);
239 hNode::hdlopsEnum::hVarref));
251 for (
const Stmt *K : S->children())
258 llvm::SmallDenseMap<const Stmt*, bool> Map;
261 for (
auto I = B.begin(); I != B.end(); ++I) {
263 if (
auto SE = E.getAs<CFGStmt>()) {
264 const Stmt *S = SE->getStmt();
265 for (
const Stmt *K : S->children())
270 if (B.getTerminator().isValid()) {
271 const Stmt *S = B.getTerminatorStmt();
272 for (
const Stmt *K : S->children())
276 for (
auto I = B.begin(); I != B.end(); ++I) {
278 if (
auto SE = E.getAs<CFGStmt>()) {
279 const Stmt *S = SE->getStmt();
280 if (Map.find(S) == Map.end()) {
288 llvm::SmallDenseMap<const Stmt*, bool> Map;
293 if (
auto SE = E.getAs<CFGStmt>()) {
294 const Stmt *S = SE->getStmt();
295 for (
const Stmt *K : S->children())
300 if ((B->
getCFGBlock())->getTerminator().isValid()) {
301 const Stmt *S = (B->
getCFGBlock())->getTerminatorStmt();
302 for (
const Stmt *K : S->children()) {
309 LLVM_DEBUG(llvm::dbgs() <<
"Stmt contains terminator\n");
316 if (
auto SE = E.getAs<CFGStmt>()) {
317 const Stmt *S = SE->getStmt();
318 if (Map.find(S) == Map.end()) {
327 auto sblock{pt[cond_node_ix].first};
328 auto supp_info{pt[cond_node_ix].second};
329 auto found_it{path_info_[state_num].find(supp_info.split_block_)};
331 LLVM_DEBUG(llvm::dbgs() <<
"Getting false path length of ");
332 LLVM_DEBUG(llvm::dbgs() <<
"(" << supp_info.path_idx_ <<
"," << sblock->getBlockID()
333 <<
"," << supp_info.false_idx_);
334 if (found_it != path_info_[state_num].end()) {
335 flen = found_it->second.getFalsePath().size();
337 LLVM_DEBUG(llvm::dbgs() <<
" |" << flen <<
"|");
338 LLVM_DEBUG(llvm::dbgs() <<
")\n");
345 int startix,
int num_ele,
346 int state_num,
hNodep h_switchcase)
349 LLVM_DEBUG(llvm::dbgs() <<
"Split Graph Group startix, num_ele, state_num are " << startix <<
" " << num_ele <<
" " << state_num <<
"\n");
352 while ( pvix<startix+num_ele) {
366 int state_num,
hNodep h_switchcase)
371 string blkid =
"S" + std::to_string(state_num) +
"_" + std::to_string(sgb->getBlockID());
381 LLVM_DEBUG(llvm::dbgs() <<
"Split Graph num ele, blockid are " << sgb->getNumOfElements() <<
" " << blkid <<
"\n");
382 if ((sgb->getCFGBlock())->getTerminator().isValid() && sgb->hasWait()) {
383 LLVM_DEBUG(llvm::dbgs() <<
"found valid terminator with hasWait(), num ele in block is " << sgb->getNumOfElements() <<
"\n");
385 if ((sgb->getCFGBlock())->getTerminator().isValid() && !sgb->hasWait()){
386 if (
isContinueorBreak(sgb->getCFGBlock()->getTerminatorStmt()) && (sgb->getNumOfElements() ==0)) {
387 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block is singleton continue or break\n");
392 const Stmt * S = sgb->getCFGBlock()->getTerminatorStmt();
393 hNodep hcondstmt =
new hNode(hNode::hdlopsEnum::hIfStmt);
396 hcondstmt->
set(hNode::hdlopsEnum::hCStmt);
399 if (
const WhileStmt *S1 = dyn_cast<WhileStmt> (S)) {
400 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " <<blkid <<
" is a while stmt\n");
403 else if (
const DoStmt *S1 = dyn_cast<DoStmt> (S)) {
404 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is a do stmt\n");
407 else if (
const ForStmt *S1 = dyn_cast<ForStmt> (S)) {
408 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is a for stmt\n");
421 else if (
const IfStmt *S1 = dyn_cast<IfStmt> (S)) {
422 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is an if stmt\n");
425 else if (
const ConditionalOperator *S1 = dyn_cast<ConditionalOperator>(S)) {
426 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is conditional operator, skipping (not?)\n");
427 LLVM_DEBUG(sgb->getCFGBlock()->getTerminatorStmt()->dump(llvm::dbgs(),
ast_context_));
432 condcfgb = conflmapit->second;
434 LLVM_DEBUG(llvm::dbgs() <<
"confluence block " << condcfgb->
getBlockID() <<
"\n");
435 for (
int i = thisix; i < pt.size(); i++) {
436 LLVM_DEBUG(llvm::dbgs() <<
"splitgraph block " << pt[i].first->getBlockID() <<
"\n");
440 if ((pt[i].first != condcfgb) &&
447 LLVM_DEBUG(llvm::dbgs() <<
"Confluence block for block " << blkid <<
" not found, skipping \n");
462 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" not handled, is as follows\n");
463 LLVM_DEBUG(sgb->getCFGBlock()->getTerminatorStmt()->dump(llvm::dbgs(),
ast_context_));
469 int flseix = pt[thisix].second.getFalseId();
475 if2 =
new hNode(hNode::hdlopsEnum::hCStmt);
480 if (if2!=NULL && if2->
size() > 0) {
481 if (if1->
size()==0) {
482 if1->
set(hNode::hdlopsEnum::hNoop);
487 if (hcondstmt->
size() >0) h_switchcase->
append(hcondstmt);
492 if (sgb->getNumOfElements() > 0) {
496 std::vector<const Stmt *> SS;
503 if (sgb->hasWait()) iswait =
true;
504 LLVM_DEBUG(llvm::dbgs() <<
"Split Graph Stmt follows\n");
513 const DeclStmt *declstmt = dyn_cast<DeclStmt>(S);
514 if ((declstmt!=NULL) && (
SGVisited[blkid]>1))
518 LLVM_DEBUG(llvm::dbgs() <<
"after Run, htmp follows\n");
520 LLVM_DEBUG(htmp->
print(llvm::dbgs()));
549 hw->
set(hNode::hdlopsEnum::hBinop,
"=");
551 hw->
append(
new hNode(std::to_string(nxtstate), hNode::hdlopsEnum::hLiteral));
557 string waitarg = hnewinstr->
getname();
559 hw->
set( hNode::hdlopsEnum::hBinop,
"=");
561 hw->
append(
new hNode(waitarg, hNode::hdlopsEnum::hLiteral));
569 htmp->
append(
new hNode(hNode::hdlopsEnum::hReturnStmt));
574 hNodep hw =
new hNode(
"--", hNode::hdlopsEnum::hPostfix);
578 hw =
new hNode(hNode::hdlopsEnum::hIfStmt);
587 const string comb_assign =
"@=";
588 hNodep hifblock =
new hNode(hNode::hdlopsEnum::hIfStmt);
603 hNodep hcstmt =
new hNode(hNode::hdlopsEnum::hCStmt);
618 hcstmt =
new hNode(hNode::hdlopsEnum::hCStmt);
626 string s = onelocalvar->
getname();
630 hstatemethod->
append(hifblock);
636 hNodep hsigp =
new hNode(sname, hNode::hdlopsEnum::hVardecl);
637 hNodep htypeinfo =
new hNode(hNode::hdlopsEnum::hTypeinfo);
638 htypeinfo->
append(
new hNode(
"int", hNode::hdlopsEnum::hType));
644 hNodep newbinop =
new hNode(opname, hNode::hdlopsEnum::hBinop);
645 newbinop->
append(
new hNode(lhs, hNode::hdlopsEnum::hVarref));
646 newbinop->
append(
new hNode(rhs, rhs_is_literal ? hNode::hdlopsEnum::hLiteral :hNode::hdlopsEnum::hVarref));
654 std::vector<const CFGBlock *> succlist, nextsucclist;
657 for (
const auto &succ : BI.succs() ) {
658 const CFGBlock *SuccBlk = succ.getReachableBlock();
659 if (SuccBlk!=NULL) succlist.push_back(SuccBlk);
664 for (
const CFGBlock *si: succlist) {
665 if (CFGVisited.find(si->getBlockID()) == CFGVisited.end()) {
666 CFGVisited[si->getBlockID()]+= 1;
667 LLVM_DEBUG(llvm::dbgs() <<
"Visiting Block " << si->getBlockID() <<
"\n");
670 for (
auto sii: si->succs()) {
671 const CFGBlock *SuccBlk = sii.getReachableBlock();
672 if (SuccBlk!=NULL) nextsucclist.push_back(SuccBlk);
676 succlist = nextsucclist;
682 string blkid = std::to_string(BI.getBlockID());
684 hNodep h_body =
new hNode(
"B"+blkid, hNode::hdlopsEnum::hMethod);
687 std::vector<const Stmt *> SS;
691 for (
auto stmt: SS) {
692 LLVM_DEBUG(llvm::dbgs() <<
"Stmt follows\n");
void set(hdlopsEnum h, string s="")
std::vector< hNodep > child_list
void print(llvm::raw_ostream &modelout=llvm::outs(), unsigned int indnt=2)
void insertall(hfunc_name_map_t newmap)
string find_entry_newn(T declp, bool set_ref=false)
void insertall(newname_map_t< T > newmap)
const std::pair< std::string, const clang::Expr * > getResetSignal() const
const std::pair< std::string, const clang::Expr * > getResetEdge() const
clang::CXXMethodDecl * getEntryMethod()
const VectorCFGElementPtrImpl & getElements() const
Returns the elements in this block.
const clang::CFGBlock * getCFGBlock() const
Returns the pointer to the original CFGBlock from which the SplitCFGBlock was created.
unsigned int getBlockID() const
Returns the block ID for the SplitCFGBlock.
void dump() const
Dump member functions.
void generate_paths()
Generates the paths between wait statements.
std::set< SplitCFGBlock * > identifySkipBlocks()
const llvm::SmallVectorImpl< llvm::SmallVector< SplitCFGPathPair > > & getPathsFound()
Returns the paths that were found in the SCCFG.
llvm::SmallVector< SplitCFGPathPair > SplitCFGPath
const llvm::SmallVector< std::unordered_map< const SplitCFGBlock *, SplitCFGPathInfo > > & getAllPathInfo() const
std::map< SplitCFGBlock *, SplitCFGBlock * > getConfluenceBlocks() const
Rework.
hdecl_name_map_t vname_map
hfunc_name_map_t methodecls
void Run(Stmt *stmt, hNodep &h_top, HDLBodyMode runmode, HDLType *HDLt_userclassesp=NULL)
void ProcessSplitGraphGroup(const SplitCFG::SplitCFGPath pt, int startix, int num_ele, int state_num, hNodep h_switchcase)
string nextwaitctr_string
string waitnextstate_string
void GenerateStateVar(string sname)
int GetFalseLength(const SplitCFG::SplitCFGPath &pt, int cond_node_ix, int state_num)
void GenerateStateUpdate(hNodep hstatemethod, hNodep hlocalvarsp)
string savewaitnextstate_string
bool isContinueorBreak(const Stmt *S)
clang::DiagnosticsEngine & diag_e
void CheckVardecls(hNodep &hp, string &cfgblockid)
const clang::ASTContext & ast_context_
hdecl_name_map_t & mod_vname_map_
const string statestringsymbol
std::map< SplitCFGBlock *, SplitCFGBlock * > condexp_confluence_block_map
hfunc_name_map_t allmethodecls_
void ProcessHWait(hNodep htmp, int nxtstate)
const string shadowstring
void ProcessSplitGraphBlock(const SplitCFG::SplitCFGPath &pt, int thisix, int state_num, hNodep h_switchcase)
hfunc_name_map_t methodecls
void updatepnvisited(int i)
void AddThreadMethod(const CFGBlock &BI)
std::unordered_map< std::string, int > SGVisited
std::set< SplitCFGBlock * > condexp_skip_block_set
std::unordered_set< int > pathnodevisited
void MarkStatements(const Stmt *S, llvm::SmallDenseMap< const Stmt *, bool > &Map)
hNodep GenerateBinop(string opname, string lhs, string rhs, bool rhs_is_literal=true)
void ProcessBB(const CFGBlock &BI)
string NameNext(string &s)
void GenerateWaitCntUpdate(hNodep h_switchcase)
bool IsWaitStmt(hNodep hp)
HDLThread(EntryFunctionContainer *efc, hNodep &h_top, hNodep &h_portsigvarlist, clang::DiagnosticsEngine &diag_engine, const ASTContext &ast_context, hdecl_name_map_t &mod_vname_map, hfunc_name_map_t &allmethods, overridden_method_map_t &overridden_method_map, hNodep h_resetvarinfo)
void FindStatements(const CFGBlock &B, std::vector< const Stmt * > &SS)
EntryFunctionContainer * efc_
hdecl_name_map_t thread_vname_map
void ProcessDeclStmt(const DeclStmt *declstmt, hNodep htmp)
std::unordered_map< const CXXMethodDecl *, const CXXMethodDecl * > overridden_method_map_t