1 #ifndef IVL_scope_H
2 #define IVL_scope_H
3 /*
4  * Copyright (c) 2011-2016 Stephen Williams (steve@icarus.com)
5  * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
6  *
7  *    This source code is free software; you can redistribute it
8  *    and/or modify it in source code form under the terms of the GNU
9  *    General Public License as published by the Free Software
10  *    Foundation; either version 2 of the License, or (at your option)
11  *    any later version.
12  *
13  *    This program is distributed in the hope that it will be useful,
14  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *    GNU General Public License for more details.
17  *
18  *    You should have received a copy of the GNU General Public License
19  *    along with this program; if not, write to the Free Software
20  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 # include  <algorithm>
24 # include  <list>
25 # include  <map>
26 # include  "StringHeap.h"
27 # include  "entity.h"
28 # include  "expression.h"
29 # include  "vsignal.h"
30 
31 class ActiveScope;
32 class Architecture;
33 class ComponentBase;
34 class Package;
35 class SubprogramHeader;
36 class VType;
37 class SequentialStmt;
38 
39 typedef list<SubprogramHeader*> SubHeaderList;
40 
41 template<typename T>
42 struct delete_object{
operatordelete_object43     void operator()(T* item) { delete item; }
44 };
45 
46 template<typename T>
47 struct delete_pair_second{
operatordelete_pair_second48     void operator()(pair<perm_string, T*> item){ delete item.second; }
49 };
50 
51 class ScopeBase {
52 
53     public:
ScopeBase()54       ScopeBase() : package_header_(0) { }
55       explicit ScopeBase(const ActiveScope&ref);
56       virtual ~ScopeBase() =0;
57 
58       ScopeBase* find_scope(perm_string name) const;
59       const VType* find_type(perm_string by_name);
60       virtual bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const;
61       Signal* find_signal(perm_string by_name) const;
62       virtual Variable* find_variable(perm_string by_name) const;
63       virtual const InterfacePort* find_param(perm_string by_name) const;
64       const InterfacePort* find_param_all(perm_string by_name) const;
65       SubHeaderList find_subprogram(perm_string by_name) const;
66 	// Checks if a string is one of possible enum values. If so, the enum
67 	// type is returned, otherwise NULL.
68       const VTypeEnum* is_enum_name(perm_string name) const;
69 
is_subprogram()70       virtual bool is_subprogram() const { return false; }
71 
72 	// Moves signals, variables and components from another scope to
73 	// this one. After the transfer new_* maps are cleared in the source scope.
74       enum transfer_type_t { SIGNALS = 1, VARIABLES = 2, COMPONENTS = 4, ALL = 0xffff };
75       void transfer_from(ScopeBase&ref, transfer_type_t what = ALL);
76 
bind_subprogram(perm_string name,SubprogramHeader * obj)77       inline void bind_subprogram(perm_string name, SubprogramHeader*obj)
78       { map<perm_string, SubHeaderList>::iterator it;
79         if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
80             it->second.remove(obj);
81         cur_subprograms_[name].push_back(obj);
82       }
83 
84 	// Adds a statement to implicit initializers list
85 	// (emitted in a 'initial block).
add_initializer(SequentialStmt * s)86       void add_initializer(SequentialStmt* s)
87       {
88         initializers_.push_back(s);
89       }
90 
91 	// Adds a statement to implicit finalizers list
92 	// (emitted in a 'final' block).
add_finalizer(SequentialStmt * s)93       void add_finalizer(SequentialStmt* s)
94       {
95         finalizers_.push_back(s);
96       }
97 
98       void dump_scope(ostream&out) const;
99 
100 	// Looks for a subprogram with specified name and parameter types.
101       SubprogramHeader*match_subprogram(perm_string name,
102                                         const list<const VType*>*params) const;
103 
peek_name()104       perm_string peek_name() const { return name_; }
105 
set_package_header(Package * pkg)106       void set_package_header(Package*pkg) {
107           assert(package_header_ == 0);
108           package_header_ = pkg;
109       }
110 
111     protected:
112       void cleanup();
113 
114       //containers' cleaning helper functions
delete_all(list<T * > & c)115       template<typename T> void delete_all(list<T*>& c)
116       {
117           for_each(c.begin(), c.end(), ::delete_object<T>());
118       }
delete_all(map<perm_string,T * > & c)119       template<typename T> void delete_all(map<perm_string, T*>& c)
120       {
121           for_each(c.begin(), c.end(), ::delete_pair_second<T>());
122       }
123 
124 	// The new_*_ maps below are managed only by the ActiveScope
125 	// derived class. When any scope is constructed from the
126 	// ActiveScope, the new_*_ and old_*_ maps are merged and
127 	// installed into the old_*_ maps. Thus, all other derived
128 	// classes should only use the old_*_ maps.
129 
130 	// Signal declarations...
131       std::map<perm_string,Signal*> old_signals_; //previous scopes
132       std::map<perm_string,Signal*> new_signals_; //current scope
133 	// Variable declarations...
134       std::map<perm_string,Variable*> old_variables_; //previous scopes
135       std::map<perm_string,Variable*> new_variables_; //current scope
136 	// Component declarations...
137       std::map<perm_string,ComponentBase*> old_components_; //previous scopes
138       std::map<perm_string,ComponentBase*> new_components_; //current scope
139 	// Type declarations...
140       std::map<perm_string,const VType*> use_types_; //imported types
141       std::map<perm_string,const VType*> cur_types_; //current types
142 	// Constant declarations...
143       struct const_t {
~const_tconst_t144         ~const_t() {delete val;}
const_tconst_t145         const_t(const VType*t, Expression* v) : typ(t), val(v) {};
146 
147 	    const VType*typ;
148 	    Expression*val;
149       };
150       std::map<perm_string, struct const_t*> use_constants_; //imported constants
151       std::map<perm_string, struct const_t*> cur_constants_; //current constants
152 
153       std::map<perm_string, SubHeaderList> use_subprograms_; //imported
154       std::map<perm_string, SubHeaderList> cur_subprograms_; //current
155 
156       std::map<perm_string, ScopeBase*> scopes_;
157 
158       std::list<const VTypeEnum*> use_enums_;
159 
160 	// List of statements that should be emitted in a 'initial' block
161       std::list<SequentialStmt*> initializers_;
162 
163 	// List of statements that should be emitted in a 'final' block
164       std::list<SequentialStmt*> finalizers_;
165 
166       void do_use_from(const ScopeBase*that);
167 
168       // If this is a package body, then there is a Package header
169       // already declared.
170       Package*package_header_;
171 
172       // Generates an unique name for the scope
173       void generate_name();
174 
175 private:
176       perm_string name_;
177 };
178 
179 class Scope : public ScopeBase {
180 
181     public:
Scope(const ActiveScope & ref)182       explicit Scope(const ActiveScope&ref) : ScopeBase(ref) {}
~Scope()183       virtual ~Scope() {}
184 
185       ComponentBase* find_component(perm_string by_name);
186 
187     protected:
188 	// Helper method for emitting signals in the scope.
189       int emit_signals(ostream&out, Entity*ent, ScopeBase*scope);
190       int emit_variables(ostream&out, Entity*ent, ScopeBase*scope);
191 };
192 
193 /*
194  * The active_scope object accumulates declarations for the scope that
195  * is in the process of being parsed. When the declarations are over,
196  * they are transferred over to the specific scope. The ActiveScope is
197  * used by the parser to build up scopes.
198  */
199 class ActiveScope : public ScopeBase {
200 
201     public:
ActiveScope()202       ActiveScope() : context_entity_(0) { }
203       explicit ActiveScope(const ActiveScope*par);
204 
~ActiveScope()205       ~ActiveScope() { }
206 
207 	// Pull items from "that" scope into "this" scope as is
208 	// defined by a "use" directive. The parser uses this method
209 	// to implement the "use <pkg>::*" directive.
use_from(const Scope * that)210       void use_from(const Scope*that) { do_use_from(that); }
211 
212 	// This function returns true if the name is a vectorable
213 	// name. The parser uses this to distinguish between function
214 	// calls and array index operations.
215       bool is_vector_name(perm_string name) const;
216 
217 	// Locate the subprogram by name. The subprogram body uses
218 	// this to locate the subprogram declaration. Note that the
219 	// subprogram may be in a package header.
220       SubprogramHeader* recall_subprogram(const SubprogramHeader*subp) const;
221 
222       /* All bind_name function check if the given name was present
223        * in previous scopes. If it is found, it is erased (but the pointer
224        * is not freed), in order to implement name shadowing. The pointer
225        * be freed only in the scope where the object was defined. This is
226        * done in ScopeBase::cleanup() function .*/
227 
bind_name(perm_string name,Signal * obj)228       void bind_name(perm_string name, Signal*obj)
229       { map<perm_string, Signal*>::iterator it;
230         if((it = old_signals_.find(name)) != old_signals_.end() )
231             old_signals_.erase(it);
232         new_signals_[name] = obj;
233       }
234 
bind_name(perm_string name,Variable * obj)235       void bind_name(perm_string name, Variable*obj)
236       { map<perm_string, Variable*>::iterator it;
237         if((it = old_variables_.find(name)) != old_variables_.end() )
238             old_variables_.erase(it);
239         new_variables_[name] = obj;
240       }
241 
bind_name(perm_string name,ComponentBase * obj)242       void bind_name(perm_string name, ComponentBase*obj)
243       { map<perm_string, ComponentBase*>::iterator it;
244         if((it = old_components_.find(name)) != old_components_.end() )
245             old_components_.erase(it);
246         new_components_[name] = obj;
247       }
248 
bind_name(perm_string name,const VType * t)249       void bind_name(perm_string name, const VType* t)
250       { map<perm_string, const VType*>::iterator it;
251         if((it = use_types_.find(name)) != use_types_.end() )
252             use_types_.erase(it);
253         cur_types_[name] = t;
254       }
255 
bind_scope(perm_string name,ScopeBase * scope)256       void bind_scope(perm_string name, ScopeBase*scope)
257       {
258           assert(scopes_.find(name) == scopes_.end());
259           scopes_[name] = scope;
260       }
261 
use_enum(const VTypeEnum * t)262       inline void use_enum(const VTypeEnum* t)
263       { use_enums_.push_back(t); }
264 
use_name(perm_string name,const VType * t)265       inline void use_name(perm_string name, const VType* t)
266       { use_types_[name] = t; }
267 
bind_name(perm_string name,const VType * obj,Expression * val)268       void bind_name(perm_string name, const VType*obj, Expression*val)
269       { map<perm_string, const_t*>::iterator it;
270         if((it = use_constants_.find(name)) != use_constants_.end() )
271             use_constants_.erase(it);
272         cur_constants_[name] = new const_t(obj, val);
273       }
274 
bind(Entity * ent)275       void bind(Entity*ent)
276       { context_entity_ = ent; }
277 
destroy_global_scope()278       void destroy_global_scope()
279       {
280           cleanup();
281       }
282 
283 	// Keep track of incomplete types until their proper
284 	// definition shows up.
285       std::map<perm_string,VTypeDef*> incomplete_types;
286 
287     private:
288       Entity*context_entity_;
289 };
290 
291 #endif /* IVL_scope_H */
292