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()};
72 for (state_num = 0; state_num < paths_found.size(); state_num++) {
77 hNodep h_switchcase =
new hNode( hNode::hdlopsEnum::hSwitchCase);
78 h_switchcase->
append(
new hNode(std::to_string(state_num), hNode::hdlopsEnum::hLiteral));
80 paths_found[state_num].size(),
81 state_num, h_switchcase);
82 hthreadblockcstmt->
append(h_switchcase);
87 hNodep h_switchcase =
new hNode( hNode::hdlopsEnum::hSwitchCase);
90 hthreadblockcstmt->
append(h_switchcase);
96 hNodep h_shadowvarsp =
new hNode(hNode::hdlopsEnum::hPortsigvarlist);
99 if (var.second.referenced) {
101 hNodep hs =
new hNode(var.second.h_vardeclp->getname(), var.second.h_vardeclp->getopc());
102 hs->
child_list = var.second.h_vardeclp->child_list;
103 h_shadowvarsp->
append(hs);
104 if (var.second.newn.find(hnode::gvar_prefix) != string::npos)
126 hthreadmainmethod->
append(
new hNode(threadname+
"_func", hNode::hdlopsEnum::hMethodCall));
132 hNodep hfunctop =
new hNode(threadname+
"_func", hNode::hdlopsEnum::hFunction);
133 hfunctop->
append(
new hNode(hNode::hdlopsEnum::hFunctionRetType));
134 hNodep hcstmttmp =
new hNode(hNode::hdlopsEnum::hCStmt);
136 hfunctop->
append(hcstmttmp);
149 hNodep hstatemethod =
new hNode(threadname+
"_state_update", hNode::hdlopsEnum::hMethod);
151 h_top->
append(hstatemethod);
153 h_top->
append(hthreadmainmethod);
157 std::remove_if( h_shadowvarsp->
child_list.begin(),
159 return (x->getname().find(hnode::gvar_prefix) != string::npos);}),
167 if (h_shadowvarsp->
size()>0) {
182 LLVM_DEBUG(llvm::dbgs() <<
"[[ Destructor HDLThread ]]\n");
186 if (isa<BreakStmt>(S))
return true;
187 if (isa<ContinueStmt>(S))
return true;
192 return ((hp->
child_list.size() >=1) and ((hp->
child_list.back())->getopc() == hNode::hdlopsEnum::hWait));
198 if ((oneop != NULL) && ((oneop->getopc() == hNode::hdlopsEnum::hVardecl) || (oneop->getopc() == hNode::hdlopsEnum::hSigdecl))) {
199 LLVM_DEBUG(llvm::dbgs() <<
"Detected vardecl for SG Block ID " << blockid <<
"\n");
203 LLVM_DEBUG(llvm::dbgs() <<
"SGVisited for blockid " <<
SGVisited[blockid]
204 <<
" " << blockid <<
"\n");
225 for (
auto *DI : declstmt->decls()) {
227 auto *vardecl = dyn_cast<VarDecl>(DI);
228 if (!vardecl)
continue;
229 if ( Expr *declinit = vardecl->getInit()) {
230 Stmt * cdeclinit = declinit;
233 hNodep varinitp =
new hNode(hNode::hdlopsEnum::hVarAssign);
235 hNode::hdlopsEnum::hVarref));
247 for (
const Stmt *K : S->children())
254 llvm::SmallDenseMap<const Stmt*, bool> Map;
257 for (
auto I = B.begin(); I != B.end(); ++I) {
259 if (
auto SE = E.getAs<CFGStmt>()) {
260 const Stmt *S = SE->getStmt();
261 for (
const Stmt *K : S->children())
266 if (B.getTerminator().isValid()) {
267 const Stmt *S = B.getTerminatorStmt();
268 for (
const Stmt *K : S->children())
272 for (
auto I = B.begin(); I != B.end(); ++I) {
274 if (
auto SE = E.getAs<CFGStmt>()) {
275 const Stmt *S = SE->getStmt();
276 if (Map.find(S) == Map.end()) {
284 llvm::SmallDenseMap<const Stmt*, bool> Map;
289 if (
auto SE = E.getAs<CFGStmt>()) {
290 const Stmt *S = SE->getStmt();
291 for (
const Stmt *K : S->children())
296 if ((B->
getCFGBlock())->getTerminator().isValid()) {
297 const Stmt *S = (B->
getCFGBlock())->getTerminatorStmt();
298 for (
const Stmt *K : S->children()) {
305 LLVM_DEBUG(llvm::dbgs() <<
"Stmt contains terminator\n");
312 if (
auto SE = E.getAs<CFGStmt>()) {
313 const Stmt *S = SE->getStmt();
314 if (Map.find(S) == Map.end()) {
323 auto sblock{pt[cond_node_ix].first};
324 auto supp_info{pt[cond_node_ix].second};
325 auto found_it{path_info_[state_num].find(supp_info.split_block_)};
327 LLVM_DEBUG(llvm::dbgs() <<
"Getting false path length of ");
328 LLVM_DEBUG(llvm::dbgs() <<
"(" << supp_info.path_idx_ <<
"," << sblock->getBlockID()
329 <<
"," << supp_info.false_idx_);
330 if (found_it != path_info_[state_num].end()) {
331 flen = found_it->second.getFalsePath().size();
333 LLVM_DEBUG(llvm::dbgs() <<
" |" << flen <<
"|");
334 LLVM_DEBUG(llvm::dbgs() <<
")\n");
341 int startix,
int num_ele,
342 int state_num,
hNodep h_switchcase)
345 LLVM_DEBUG(llvm::dbgs() <<
"Split Graph Group startix, num_ele, state_num are " << startix <<
" " << num_ele <<
" " << state_num <<
"\n");
348 while ( pvix<startix+num_ele) {
362 int state_num,
hNodep h_switchcase)
367 string blkid =
"S" + std::to_string(state_num) +
"_" + std::to_string(sgb->getBlockID());
377 LLVM_DEBUG(llvm::dbgs() <<
"Split Graph num ele, blockid are " << sgb->getNumOfElements() <<
" " << blkid <<
"\n");
378 if ((sgb->getCFGBlock())->getTerminator().isValid() && sgb->hasWait()) {
379 LLVM_DEBUG(llvm::dbgs() <<
"found valid terminator with hasWait(), num ele in block is " << sgb->getNumOfElements() <<
"\n");
381 if ((sgb->getCFGBlock())->getTerminator().isValid() && !sgb->hasWait()){
382 if (
isContinueorBreak(sgb->getCFGBlock()->getTerminatorStmt()) && (sgb->getNumOfElements() ==0)) {
383 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block is singleton continue or break\n");
388 const Stmt * S = sgb->getCFGBlock()->getTerminatorStmt();
389 hNodep hcondstmt =
new hNode(hNode::hdlopsEnum::hIfStmt);
392 hcondstmt->
set(hNode::hdlopsEnum::hCStmt);
395 if (
const WhileStmt *S1 = dyn_cast<WhileStmt> (S)) {
396 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " <<blkid <<
" is a while stmt\n");
399 else if (
const DoStmt *S1 = dyn_cast<DoStmt> (S)) {
400 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is a do stmt\n");
403 else if (
const ForStmt *S1 = dyn_cast<ForStmt> (S)) {
404 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is a for stmt\n");
417 else if (
const IfStmt *S1 = dyn_cast<IfStmt> (S)) {
418 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is an if stmt\n");
421 else if (
const ConditionalOperator *S1 = dyn_cast<ConditionalOperator>(S)) {
422 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" is conditional operator, skipping\n");
436 LLVM_DEBUG(llvm::dbgs() <<
"Terminator for block " << blkid <<
" not handled, is as follows\n");
437 LLVM_DEBUG(sgb->getCFGBlock()->getTerminatorStmt()->dump(llvm::dbgs(),
ast_context_));
443 int flseix = pt[thisix].second.getFalseId();
449 if2 =
new hNode(hNode::hdlopsEnum::hCStmt);
454 if (if2!=NULL && if2->
size() > 0) {
455 if (if1->
size()==0) {
456 if1->
set(hNode::hdlopsEnum::hNoop);
461 if (hcondstmt->
size() >0) h_switchcase->
append(hcondstmt);
466 if (sgb->getNumOfElements() > 0) {
470 std::vector<const Stmt *> SS;
477 if (sgb->hasWait()) iswait =
true;
478 LLVM_DEBUG(llvm::dbgs() <<
"Split Graph Stmt follows\n");
487 const DeclStmt *declstmt = dyn_cast<DeclStmt>(S);
488 if ((declstmt!=NULL) && (
SGVisited[blkid]>1))
492 LLVM_DEBUG(llvm::dbgs() <<
"after Run, htmp follows\n");
494 LLVM_DEBUG(htmp->
print(llvm::dbgs()));
523 hw->
set(hNode::hdlopsEnum::hBinop,
"=");
525 hw->
append(
new hNode(std::to_string(nxtstate), hNode::hdlopsEnum::hLiteral));
531 string waitarg = hnewinstr->
getname();
533 hw->
set( hNode::hdlopsEnum::hBinop,
"=");
535 hw->
append(
new hNode(waitarg, hNode::hdlopsEnum::hLiteral));
543 htmp->
append(
new hNode(hNode::hdlopsEnum::hReturnStmt));
548 hNodep hw =
new hNode(
"--", hNode::hdlopsEnum::hPostfix);
552 hw =
new hNode(hNode::hdlopsEnum::hIfStmt);
561 const string comb_assign =
"@=";
562 hNodep hifblock =
new hNode(hNode::hdlopsEnum::hIfStmt);
576 hNodep hcstmt =
new hNode(hNode::hdlopsEnum::hCStmt);
591 hcstmt =
new hNode(hNode::hdlopsEnum::hCStmt);
599 string s = onelocalvar->
getname();
603 hstatemethod->
append(hifblock);
609 hNodep hsigp =
new hNode(sname, hNode::hdlopsEnum::hVardecl);
610 hNodep htypeinfo =
new hNode(hNode::hdlopsEnum::hTypeinfo);
611 htypeinfo->
append(
new hNode(
"int", hNode::hdlopsEnum::hType));
617 hNodep newbinop =
new hNode(opname, hNode::hdlopsEnum::hBinop);
618 newbinop->
append(
new hNode(lhs, hNode::hdlopsEnum::hVarref));
619 newbinop->
append(
new hNode(rhs, rhs_is_literal ? hNode::hdlopsEnum::hLiteral :hNode::hdlopsEnum::hVarref));
627 std::vector<const CFGBlock *> succlist, nextsucclist;
630 for (
const auto &succ : BI.succs() ) {
631 const CFGBlock *SuccBlk = succ.getReachableBlock();
632 if (SuccBlk!=NULL) succlist.push_back(SuccBlk);
637 for (
const CFGBlock *si: succlist) {
638 if (CFGVisited.find(si->getBlockID()) == CFGVisited.end()) {
639 CFGVisited[si->getBlockID()]+= 1;
640 LLVM_DEBUG(llvm::dbgs() <<
"Visiting Block " << si->getBlockID() <<
"\n");
643 for (
auto sii: si->succs()) {
644 const CFGBlock *SuccBlk = sii.getReachableBlock();
645 if (SuccBlk!=NULL) nextsucclist.push_back(SuccBlk);
649 succlist = nextsucclist;
655 string blkid = std::to_string(BI.getBlockID());
657 hNodep h_body =
new hNode(
"B"+blkid, hNode::hdlopsEnum::hMethod);
660 std::vector<const Stmt *> SS;
664 for (
auto stmt: SS) {
665 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.
void dump() const
Dump member functions.
void generate_paths()
Generates the paths between wait statements.
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
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
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 AddThreadMethod(const CFGBlock &BI)
std::unordered_map< std::string, int > SGVisited
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