Inferno  0.2
systemc_detection.cpp
Go to the documentation of this file.
00001 
00002 #include "systemc_detection.hpp"
00003 #include "tree/cpptree.hpp"
00004 #include "tree/typeof.hpp"
00005 #include "inferno_patterns.hpp"
00006 
00007 using namespace CPPTree;
00008 using namespace SCTree;
00009 using namespace Steps;
00010 
00011 
00012 
00013 /// spot SystemC type by its name and replace with inferno node 
00014 /** We look for the decl and remeove it since the inferno
00015  Node does not require declaration. Then just switch each appearance
00016  over to the new node, using a slave */
00017 template< class SCNODE>
00018 class DetectSCType : public CompareReplace  // Note not SearchReplace
00019 {
00020 public:
00021     DetectSCType()
00022     {
00023         MakeTreePtr< Overlay<Node> > over;
00024         MakeTreePtr< Scope > s_scope, r_scope;
00025         MakeTreePtr< Star<Declaration> > decls;
00026         MakeTreePtr< UserType > s_usertype;
00027         MakeTreePtr< SCNODE > lr_scnode;
00028         MakeTreePtr< TypeIdentifierByName > s_token( lr_scnode->GetToken() );                
00029         MakeTreePtr< SlaveSearchReplace<Node> > r_slave( over, s_token, lr_scnode );    
00030         
00031         // Eliminate the declaration that came from isystemc.h
00032         over->through = s_scope;
00033         over->overlay = r_scope;
00034         s_scope->members = (decls, s_usertype);
00035         s_usertype->identifier = s_token;
00036         
00037         r_scope->members = (decls);          
00038            
00039         Configure( over, r_slave );
00040     }
00041 };
00042 
00043 
00044 /// spot SystemC base class by its name and replace with inferno node 
00045 /** We look for the decl and remove it since the inferno
00046  Node does not require declaration. Then replace all class nodes
00047  that inherit from the suppleid base with the new inferno node and 
00048  remove the base */
00049 template< class SCCLASS>
00050 class DetectSCBase : public CompareReplace  // Note not SearchReplace
00051 {
00052 public:
00053     DetectSCBase()
00054     {
00055         MakeTreePtr< Overlay<Node> > over;
00056         MakeTreePtr< Scope > s_scope, r_scope;
00057         MakeTreePtr< Star<Declaration> > decls, l_decls;
00058         MakeTreePtr< Star<Base> > l_bases;
00059         MakeTreePtr< UserType > s_usertype;
00060         MakeTreePtr< SCCLASS > lr_scclass;
00061         MakeTreePtr< InheritanceRecord > ls_class;
00062         MakeTreePtr< Base > ls_base;            
00063         MakeTreePtr< TypeIdentifier > l_tid;
00064         MakeTreePtr< TypeIdentifierByName > s_token( lr_scclass->GetToken() ); 
00065         MakeTreePtr< SlaveSearchReplace<Node> > r_slave( over, ls_class, lr_scclass );    
00066         
00067         // Eliminate the declaration that came from isystemc.h
00068         over->through = s_scope;
00069         over->overlay = r_scope;
00070         s_scope->members = (decls, s_usertype);
00071         s_usertype->identifier = s_token;        
00072         r_scope->members = (decls);   
00073         
00074         ls_class->identifier = l_tid;       
00075         ls_class->members = (l_decls);
00076         ls_class->bases = (l_bases, ls_base);       
00077         ls_base->record = s_token;
00078         lr_scclass->identifier = l_tid;       
00079         lr_scclass->members = (l_decls);
00080         lr_scclass->bases = (l_bases);
00081            
00082         Configure( over, r_slave );
00083     }
00084 };
00085 
00086 
00087 template<class SCFUNC>
00088 class DetectSCDynamic : public SearchReplace
00089 {
00090 public:
00091     DetectSCDynamic()
00092     {
00093         MakeTreePtr< SCFUNC > r_dynamic;
00094         MakeTreePtr< Call > s_call;
00095         MakeTreePtr< MapOperand > s_arg;            
00096         MakeTreePtr< InstanceIdentifierByName > s_token( r_dynamic->GetToken() ); 
00097         MakeTreePtr< InstanceIdentifierByName > s_param_id( "p1" ); 
00098         MakeTreePtr< TransformOf<Expression> > eexpr( &TypeOf::instance ); 
00099                         
00100         s_call->callee = s_token;       
00101         s_call->operands = (s_arg);
00102         s_arg->identifier = s_param_id;
00103         s_arg->value = eexpr;
00104         eexpr->pattern = MakeTreePtr<Event>();
00105         r_dynamic->event = eexpr;       
00106           
00107         Configure( s_call, r_dynamic );
00108     }
00109 };
00110 
00111 template<class SCFUNC>
00112 class DetectSCStatic : public SearchReplace
00113 {
00114 public:
00115     DetectSCStatic()
00116     {
00117         MakeTreePtr< SCFUNC > r_static;
00118         MakeTreePtr< Call > s_call;
00119         MakeTreePtr< InstanceIdentifierByName > s_token( r_static->GetToken() ); 
00120                           
00121         s_call->callee = s_token;   
00122         //s_call->operands = ();       
00123            
00124         Configure( s_call, r_static );
00125     }
00126 };
00127 
00128 template<class SCFUNC>
00129 class DetectSCDelta : public SearchReplace
00130 {
00131 public:
00132     DetectSCDelta()
00133     {
00134         MakeTreePtr< SCFUNC > r_delta;
00135         MakeTreePtr< Call > s_call;
00136         MakeTreePtr< MapOperand > s_arg;            
00137         MakeTreePtr< InstanceIdentifierByName > s_token( r_delta->GetToken() ); 
00138         MakeTreePtr< InstanceIdentifierByName > s_param_id( "p1" ); 
00139         MakeTreePtr< InstanceIdentifierByName > s_arg_id( "SC_ZERO_TIME" ); 
00140                         
00141         s_call->callee = s_token;       
00142         s_call->operands = (s_arg);
00143         s_arg->identifier = s_param_id;
00144         s_arg->value = s_arg_id;
00145           
00146         Configure( s_call, r_delta );
00147     }
00148 };
00149 
00150 
00151 /// spot syscall exit() or equivalent function by its name and replace with inferno node 
00152 /** We look for the decl and remove it since the inferno
00153  Node does not require declaration. Then replace all calls to 
00154  the function with the explicit statement node. Bring arguments
00155  across by name match as per Inferno's MapOperator style. */
00156 template<class SCFUNC>
00157 class DetectTerminationFunction : public SearchReplace
00158 {
00159 public:
00160     DetectTerminationFunction()
00161     {
00162         MakeTreePtr< SCFUNC > r_tf;
00163         MakeTreePtr< Expression > event;
00164         MakeTreePtr< Call > s_call;
00165         MakeTreePtr< MapOperand > s_arg;            
00166         MakeTreePtr< InstanceIdentifierByName > s_token( r_tf->GetToken() ); 
00167         MakeTreePtr< InstanceIdentifierByName > s_param_id( "p1" ); 
00168                 
00169         s_call->callee = s_token;       
00170         s_call->operands = (s_arg);
00171         s_arg->identifier = s_param_id;
00172         s_arg->value = event;
00173         r_tf->code = event;       
00174           
00175         Configure( s_call, r_tf );
00176     }
00177 };
00178 
00179 
00180 class DetectSCProcess : public CompareReplace // Note not SearchReplace
00181 {
00182 public:
00183     DetectSCProcess( TreePtr< Process > lr_scprocess )
00184     {
00185         MakeTreePtr< Overlay<Node> > over;
00186         MakeTreePtr< Scope > s_scope, r_scope;
00187         MakeTreePtr< Star<Declaration> > decls, l_decls, l_cdecls;
00188         MakeTreePtr< Static > s_instance;
00189         MakeTreePtr< Compound > ls_comp, lr_comp;
00190         MakeTreePtr< Module > l_module;
00191         MakeTreePtr< Call > ls_pcall;
00192         MakeTreePtr< MapOperand > ls_arg;            
00193         MakeTreePtr< Overlay<Instance> > l_overcons;
00194         MakeTreePtr< Overlay<Type> > l_overtype;
00195         MakeTreePtr< Instance > ls_cons, lr_cons, l_process;
00196         MakeTreePtr< Star<Statement> > l_pre, l_post;
00197         MakeTreePtr< InstanceIdentifier > ls_id;
00198         MakeTreePtr< Star<Base> > l_bases;        
00199         MakeTreePtr<Constructor> l_ctype;
00200         MakeTreePtr< InstanceIdentifierByName > s_token( lr_scprocess->GetToken() ); 
00201         MakeTreePtr< InstanceIdentifierByName > s_arg_id( "func" );
00202         MakeTreePtr< SlaveSearchReplace<Node> > r_slave( over, l_module, l_module );            
00203         
00204         // Eliminate the declaration that came from isystemc.h
00205         over->through = s_scope;
00206         over->overlay = r_scope;
00207         s_scope->members = (decls, s_instance);
00208         s_instance->identifier = s_token;        
00209         s_instance->type = MakeTreePtr<Callable>(); // just narrow things a little        
00210         r_scope->members = (decls);   
00211                 
00212         l_module->members = (l_overcons, l_process, l_decls);
00213         l_module->bases = (l_bases);
00214         l_overcons->through = ls_cons;
00215         ls_cons->type = MakeTreePtr<Constructor>();        
00216         ls_cons->initialiser = ls_comp;
00217         ls_comp->members = l_cdecls;
00218         ls_comp->statements = (l_pre, ls_pcall, l_post);
00219         ls_cons->type = l_ctype;
00220         l_ctype->members = (MakeTreePtr<Automatic>()); // one parameter
00221         ls_pcall->callee = s_token;
00222         ls_pcall->operands = (ls_arg);
00223         ls_arg->identifier = s_arg_id;
00224         ls_arg->value = ls_id;
00225         l_overcons->overlay = lr_cons;
00226         lr_cons->initialiser = lr_comp;
00227         lr_comp->members = l_cdecls;
00228         lr_comp->statements = (l_pre, l_post);
00229         lr_cons->type = l_ctype;
00230         
00231         l_process->identifier = ls_id;
00232         l_process->type = l_overtype;
00233         l_overtype->through = MakeTreePtr<Callable>();
00234         l_overtype->overlay = lr_scprocess;
00235         
00236         Configure( over, r_slave );
00237     }
00238 };
00239 
00240 
00241 
00242 /// spot SystemC notify() method by its name and replace with inferno node 
00243 /** Look for myevent.notify() and replace with Notify->myevent. No need to 
00244     eliminate the notify decl - that disappeared with the sc_event class */
00245 class DetectSCNotifyImmediate : public SearchReplace  
00246 {
00247 public:
00248     DetectSCNotifyImmediate()
00249     {
00250         MakeTreePtr<Call> s_call;
00251         MakeTreePtr<Lookup> s_lookup;
00252         MakeTreePtr<Event> s_event;
00253         MakeTreePtr<NotifyImmediate> r_notify;
00254         MakeTreePtr< InstanceIdentifierByName > s_token( r_notify->GetToken() );                
00255         MakeTreePtr< TransformOf<Expression> > eexpr( &TypeOf::instance ); 
00256         //MakeTreePtr< Expression > eexpr; 
00257                 
00258         s_call->callee = s_lookup;
00259         //s_call->operands = ();
00260         s_lookup->base = eexpr;          
00261         eexpr->pattern = s_event;     // ensure base really evaluates to an event 
00262         s_lookup->member = s_token;        
00263 
00264         r_notify->event = eexpr;
00265            
00266         Configure( s_call, r_notify );
00267     }
00268 };
00269 
00270 
00271 /// spot SystemC notify(SC_ZERO_TIME) method by its name and replace with inferno node 
00272 /** Look for myevent.notify(SC_ZERO_TIME) and replace with Notify->myevent. No need to 
00273     eliminate the notify decl - that disappeared with the sc_event class */
00274 class DetectSCNotifyDelta : public SearchReplace  
00275 {
00276 public:
00277     DetectSCNotifyDelta()
00278     {
00279         MakeTreePtr<Call> s_call;
00280         MakeTreePtr<Lookup> s_lookup;
00281         MakeTreePtr<Event> s_event;
00282         MakeTreePtr<NotifyDelta> r_notify;
00283         MakeTreePtr<MapOperand> s_arg;
00284         MakeTreePtr< InstanceIdentifierByName > s_zero_token( "SC_ZERO_TIME" );                
00285         MakeTreePtr< InstanceIdentifierByName > s_arg_id( "p1" ); 
00286         MakeTreePtr< InstanceIdentifierByName > s_token( r_notify->GetToken() );                
00287         MakeTreePtr< TransformOf<Expression> > eexpr( &TypeOf::instance ); 
00288         //MakeTreePtr< Expression > eexpr; 
00289                 
00290         s_call->callee = s_lookup;
00291         s_call->operands = (s_arg);
00292         s_arg->identifier = s_arg_id;
00293         s_arg->value = s_zero_token;        
00294         s_lookup->base = eexpr;          
00295         eexpr->pattern = s_event;     // ensure base really evaluates to an event 
00296         s_lookup->member = s_token;        
00297 
00298         r_notify->event = eexpr;
00299            
00300         Configure( s_call, r_notify );
00301     }
00302 };
00303 
00304 
00305 /// Remove constructors in SC modules that are now empty thanks to earlier steps
00306 /// Must also remove explicit calls to constructor (which would not do anything)
00307 class RemoveEmptyModuleConstructors : public CompareReplace
00308 {
00309 public:
00310     RemoveEmptyModuleConstructors()
00311     {
00312         MakeTreePtr< Stuff<Scope> > stuff;
00313         MakeTreePtr< Overlay<Scope> > over;
00314         MakeTreePtr< Star<Declaration> > decls, l_decls;
00315         MakeTreePtr< Star<Statement> > l_pre, l_post;
00316         MakeTreePtr< Star<MapOperand> > ls_args;
00317         MakeTreePtr< Compound > s_comp, ls_comp, lr_comp;
00318         MakeTreePtr< Module > s_module, r_module;
00319         MakeTreePtr< Call > ls_call;
00320         MakeTreePtr< Lookup > ls_lookup;
00321         MakeTreePtr< Instance > s_cons;
00322         MakeTreePtr< InstanceIdentifier > s_id;
00323         MakeTreePtr< Star<Automatic> > s_params;
00324         MakeTreePtr<Constructor> s_ctype;
00325         MakeTreePtr< Star<Base> > bases;        
00326         MakeTreePtr< SlaveSearchReplace<Node> > r_slave( stuff, ls_comp, lr_comp );            
00327                         
00328         // dispense with an empty constructor                 
00329         stuff->terminus = over;
00330         over->through = s_module;
00331         over->overlay = r_module;
00332         s_module->members = (s_cons, decls);
00333         s_module->bases = (bases);
00334         s_cons->type = MakeTreePtr<Constructor>();        
00335         s_cons->initialiser = s_comp;
00336         // s_comp's members and statements left empty to signify empty constructor
00337         s_cons->identifier = s_id;
00338         s_cons->type = s_ctype;
00339         s_ctype->members = (s_params); // any parameters
00340         r_module->members = (decls);
00341         r_module->bases = (bases);
00342                 
00343         // dispense with any calls to it
00344         ls_comp->members = (l_decls);
00345         ls_comp->statements = (l_pre, ls_call, l_post);
00346         ls_call->callee = ls_lookup;
00347         ls_call->operands = ls_args; // any number of args, it doesn't matter, ctor is still empty so does nothing
00348         ls_lookup->member = s_id;        
00349         lr_comp->members = (l_decls);
00350         lr_comp->statements = (l_pre, l_post);
00351                 
00352         Configure( stuff, r_slave );
00353     }
00354 };
00355 
00356 
00357 /// Remove top-level instances that are of type void
00358 /** isystemc.h declares void variables to satisfy parser. Hoover them all up
00359     efficiently here. */
00360 class RemoveVoidInstances : public CompareReplace  // Note not SearchReplace
00361 {
00362 public:
00363     RemoveVoidInstances()
00364     {
00365         MakeTreePtr<Program> s_scope, r_scope;
00366         MakeTreePtr< Star<Declaration> > decls;
00367         MakeTreePtr<Static> s_instance;
00368         MakeTreePtr< MatchAny<Type> > s_any;
00369         MakeTreePtr<CallableParams> s_callable;
00370         MakeTreePtr< Star<Instance> > s_params;
00371         MakeTreePtr<Instance> s_void_param;
00372         
00373         // Eliminate the declaration that came from isystemc.h
00374         s_scope->members = (decls, s_instance);
00375         s_instance->type = s_any;
00376         s_any->patterns = (s_callable, MakeTreePtr<Void>() ); // match void instances (pointless) or functions as below...
00377         s_callable->members = (s_params, s_void_param); // one void param is enough, but don't match no params
00378         s_void_param->type = MakeTreePtr<Void>();
00379         
00380         r_scope->members = (decls);   
00381            
00382         Configure( s_scope, r_scope );
00383     }
00384 };
00385 
00386 
00387 
00388 
00389 DetectAllSCTypes::DetectAllSCTypes()
00390 {
00391     push_back( shared_ptr<Transformation>( new DetectSCType<Event> ) );    
00392     push_back( shared_ptr<Transformation>( new DetectSCBase<Module> ) );    
00393     push_back( shared_ptr<Transformation>( new DetectSCBase<Interface> ) );    
00394     push_back( shared_ptr<Transformation>( new DetectSCDynamic<WaitDynamic> ) );        
00395     push_back( shared_ptr<Transformation>( new DetectSCStatic<WaitStatic> ) );        
00396     push_back( shared_ptr<Transformation>( new DetectSCDelta<WaitDelta> ) );        
00397     push_back( shared_ptr<Transformation>( new DetectSCDynamic<NextTriggerDynamic> ) );        
00398     push_back( shared_ptr<Transformation>( new DetectSCStatic<NextTriggerStatic> ) );        
00399     push_back( shared_ptr<Transformation>( new DetectSCDelta<NextTriggerDelta> ) );        
00400     push_back( shared_ptr<Transformation>( new DetectTerminationFunction<Exit> ) );    
00401     push_back( shared_ptr<Transformation>( new DetectTerminationFunction<Cease> ) );    
00402     push_back( shared_ptr<Transformation>( new DetectSCProcess( MakeTreePtr<Thread>() ) ) );    
00403     push_back( shared_ptr<Transformation>( new DetectSCProcess( MakeTreePtr<ClockedThread>() ) ) );    
00404     push_back( shared_ptr<Transformation>( new DetectSCProcess( MakeTreePtr<Method>() ) ) );    
00405     push_back( shared_ptr<Transformation>( new DetectSCNotifyImmediate ) );    
00406     push_back( shared_ptr<Transformation>( new DetectSCNotifyDelta ) );    
00407     push_back( shared_ptr<Transformation>( new RemoveEmptyModuleConstructors ) );    
00408     push_back( shared_ptr<Transformation>( new RemoveVoidInstances ) );    
00409 }
00410