1 /*
2  * Copyright (c) 2011 Stephen Williams (steve@icarus.com)
3  *
4  *    This source code is free software; you can redistribute it
5  *    and/or modify it in source code form under the terms of the GNU
6  *    General Public License as published by the Free Software
7  *    Foundation; either version 2 of the License, or (at your option)
8  *    any later version.
9  *
10  *    This program is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU General Public License for more details.
14  *
15  *    You should have received a copy of the GNU General Public License
16  *    along with this program; if not, write to the Free Software
17  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 # include  "vtype.h"
21 # include  "parse_types.h"
22 # include  "compiler.h"
23 # include  <map>
24 # include  <typeinfo>
25 # include  <cassert>
26 # include  <algorithm>
27 
28 using namespace std;
29 
~VType()30 VType::~VType()
31 {
32 }
33 
show(ostream & out) const34 void VType::show(ostream&out) const
35 {
36       write_to_stream(out);
37 }
38 
get_generic_typename() const39 perm_string VType::get_generic_typename() const
40 {
41     char buf[16] = {0,};
42     snprintf(buf, 16, "type_%p", this);
43     return lex_strings.make(buf);
44 }
45 
VTypePrimitive(VTypePrimitive::type_t tt,bool packed)46 VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt, bool packed)
47 : type_(tt), packed_(packed)
48 {
49 }
50 
~VTypePrimitive()51 VTypePrimitive::~VTypePrimitive()
52 {
53 }
54 
show(ostream & out) const55 void VTypePrimitive::show(ostream&out) const
56 {
57       switch (type_) {
58 	  case BIT:
59 	    out << "BIT";
60 	    break;
61 	  case INTEGER:
62 	    out << "INTEGER";
63 	    break;
64 	  case NATURAL:
65 	    out << "NATURAL";
66 	    break;
67 	  case REAL:
68 	    out << "REAL";
69 	    break;
70 	  case STDLOGIC:
71 	    out << "STD_LOGIC";
72 	    break;
73 	  case TIME:
74 	    out << "TIME";
75 	    break;
76       }
77 }
78 
get_width(ScopeBase *) const79 int VTypePrimitive::get_width(ScopeBase*) const
80 {
81     switch(type_) {
82         case BIT:
83         case STDLOGIC:
84             return 1;
85 
86         case INTEGER:
87         case NATURAL:
88             return 32;
89 
90         default:
91             std::cerr << "sorry: primitive type " << type_ <<
92                 " has no get_width() implementation." << std::endl;
93             break;
94     }
95 
96     return -1;
97 }
98 
clone() const99 VTypeArray::range_t*VTypeArray::range_t::clone() const
100 {
101     return new VTypeArray::range_t(safe_clone(msb_), safe_clone(lsb_), direction_);
102 }
103 
VTypeArray(const VType * element,const vector<VTypeArray::range_t> & r,bool sv)104 VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv)
105 : etype_(element), ranges_(r), signed_flag_(sv), parent_(NULL)
106 {
107 }
108 
109 /*
110  * Create a VTypeArray range set from a list of parsed ranges.
111  * FIXME: We are copying pointers from the ExpRange object into the
112  * range_t. This means that we cannot delete the ExpRange object
113  * unless we invent a way to remove the pointers from that object. So
114  * this is a memory leak. Something to fix.
115  */
VTypeArray(const VType * element,std::list<ExpRange * > * r,bool sv)116 VTypeArray::VTypeArray(const VType*element, std::list<ExpRange*>*r, bool sv)
117 : etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL)
118 {
119       for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) {
120 	    ExpRange*curp = r->front();
121 	    r->pop_front();
122 	    ranges_[idx] = range_t(curp->msb(), curp->lsb(),
123 		(curp->direction() == ExpRange::DOWNTO
124 			? true
125 			: false));
126       }
127 }
128 
VTypeArray(const VType * element,int msb,int lsb,bool sv)129 VTypeArray::VTypeArray(const VType*element, int msb, int lsb, bool sv)
130 : etype_(element), ranges_(1), signed_flag_(sv), parent_(NULL)
131 {
132       bool down_to = msb > lsb;
133       ranges_[0] = range_t(new ExpInteger(msb), new ExpInteger(lsb), down_to);
134 }
135 
~VTypeArray()136 VTypeArray::~VTypeArray()
137 {
138 }
139 
clone() const140 VType*VTypeArray::clone() const {
141     std::vector<range_t> new_ranges;
142     new_ranges.reserve(ranges_.size());
143     for(std::vector<range_t>::const_iterator it = ranges_.begin();
144             it != ranges_.end(); ++it) {
145         new_ranges.push_back(*(it->clone()));
146     }
147     VTypeArray*a = new VTypeArray(etype_->clone(), new_ranges, signed_flag_);
148     a->set_parent_type(parent_);
149     return a;
150 }
151 
basic_type(bool typedef_allowed) const152 const VType* VTypeArray::basic_type(bool typedef_allowed) const
153 {
154     const VType*t = etype_;
155     const VTypeDef*tdef = NULL;
156     bool progress = false;
157 
158     do {
159         progress = false;
160 
161         if((tdef = dynamic_cast<const VTypeDef*>(t))) {
162             t = tdef->peek_definition();
163         }
164 
165         if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(t)) {
166             t = arr->element_type();
167             progress = true;
168         } else if(tdef) { // return the typedef if it does not define an array
169             t = typedef_allowed ? tdef : tdef->peek_definition();
170         }
171     } while(progress);
172 
173     return t;
174 }
175 
show(ostream & out) const176 void VTypeArray::show(ostream&out) const
177 {
178       out << "array ";
179       for (vector<range_t>::const_iterator cur = ranges_.begin()
180 		 ; cur != ranges_.end() ; ++cur) {
181 	    out << "(";
182 	    if (cur->msb())
183 		  cur->msb()->write_to_stream(out);
184 	    else
185 		  out << "<>";
186 	    out << " downto ";
187 	    if (cur->lsb())
188 		  cur->lsb()->write_to_stream(out);
189 	    else
190 		  out << "<>";
191 	    out << ")";
192       }
193       out << " of ";
194       if (signed_flag_)
195 	    out << "signed ";
196       if (etype_)
197 	    etype_->show(out);
198       else
199 	    out << "<nil>";
200 }
201 
get_width(ScopeBase * scope) const202 int VTypeArray::get_width(ScopeBase*scope) const
203 {
204       int64_t size = 1;
205 
206       for(vector<range_t>::const_iterator it = ranges_.begin();
207               it != ranges_.end(); ++it) {
208           const VTypeArray::range_t&dim = *it;
209           int64_t msb_val, lsb_val;
210 
211           if(dim.is_box())
212               return -1;
213 
214           if(!dim.msb()->evaluate(scope, msb_val))
215               return -1;
216 
217           if(!dim.lsb()->evaluate(scope, lsb_val))
218               return -1;
219 
220           size *= 1 + labs(msb_val - lsb_val);
221       }
222 
223       return element_type()->get_width(scope) * size;
224 }
225 
is_unbounded() const226 bool VTypeArray::is_unbounded() const {
227     for(std::vector<range_t>::const_iterator it = ranges_.begin();
228             it != ranges_.end(); ++it)
229     {
230         if(it->is_box())
231             return true;
232     }
233 
234     return etype_->is_unbounded();
235 }
236 
is_variable_length(ScopeBase * scope) const237 bool VTypeArray::is_variable_length(ScopeBase*scope) const {
238     int64_t dummy;
239 
240     if(is_unbounded())
241         return true;
242 
243     for(std::vector<range_t>::const_iterator it = ranges_.begin();
244             it != ranges_.end(); ++it)
245     {
246         if(!it->lsb()->evaluate(scope, dummy))
247             return true;
248 
249         if(!it->msb()->evaluate(scope, dummy))
250             return true;
251     }
252 
253     return etype_->is_variable_length(scope);
254 }
255 
evaluate_ranges(ScopeBase * scope)256 void VTypeArray::evaluate_ranges(ScopeBase*scope) {
257     for(std::vector<range_t>::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) {
258         int64_t lsb_val = -1, msb_val = -1;
259 
260         if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) {
261             assert(lsb_val >= 0);
262             assert(msb_val >= 0);
263             *it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), msb_val > lsb_val);
264         }
265     }
266 }
267 
VTypeRange(const VType * base)268 VTypeRange::VTypeRange(const VType*base)
269 : base_(base)
270 {
271 }
272 
~VTypeRange()273 VTypeRange::~VTypeRange()
274 {
275 }
276 
VTypeRangeConst(const VType * base,int64_t start_val,int64_t end_val)277 VTypeRangeConst::VTypeRangeConst(const VType*base, int64_t start_val, int64_t end_val)
278 : VTypeRange(base), start_(start_val), end_(end_val)
279 {
280 }
281 
VTypeRangeExpr(const VType * base,Expression * start_expr,Expression * end_expr,bool downto)282 VTypeRangeExpr::VTypeRangeExpr(const VType*base, Expression*start_expr,
283                                Expression*end_expr, bool downto)
284 : VTypeRange(base), start_(start_expr), end_(end_expr), downto_(downto)
285 {
286 }
287 
~VTypeRangeExpr()288 VTypeRangeExpr::~VTypeRangeExpr()
289 {
290     delete start_;
291     delete end_;
292 }
293 
clone() const294 VType*VTypeRangeExpr::clone() const {
295     return new VTypeRangeExpr(base_type()->clone(), start_->clone(),
296                               end_->clone(), downto_);
297 }
298 
VTypeEnum(const std::list<perm_string> * names)299 VTypeEnum::VTypeEnum(const std::list<perm_string>*names)
300 : names_(names->size())
301 {
302       size_t idx = 0;
303 
304       for (list<perm_string>::const_iterator cur = names->begin()
305 		 ; cur != names->end() ; ++cur, ++idx) {
306 	    names_[idx] = *cur;
307       }
308 }
309 
~VTypeEnum()310 VTypeEnum::~VTypeEnum()
311 {
312 }
313 
show(ostream & out) const314 void VTypeEnum::show(ostream&out) const
315 {
316       out << "(";
317       if (names_.size() >= 1)
318 	    out << names_[0];
319       for (size_t idx = 1 ; idx < names_.size() ; idx += 1)
320 	    out << ", " << names_[idx];
321       out << ")";
322 }
323 
has_name(perm_string name) const324 bool VTypeEnum::has_name(perm_string name) const
325 {
326       return std::find(names_.begin(), names_.end(), name) != names_.end();
327 }
328 
VTypeRecord(std::list<element_t * > * elements)329 VTypeRecord::VTypeRecord(std::list<element_t*>*elements)
330 : elements_(elements->size())
331 {
332       for (size_t idx = 0 ; idx < elements_.size() ; idx += 1) {
333 	    elements_[idx] = elements->front();
334 	    elements->pop_front();
335       }
336       delete elements;
337 }
338 
~VTypeRecord()339 VTypeRecord::~VTypeRecord()
340 {
341       for (size_t idx = 0 ; idx < elements_.size() ; idx += 1)
342 	    delete elements_[idx];
343 }
344 
show(ostream & out) const345 void VTypeRecord::show(ostream&out) const
346 {
347       write_to_stream(out);
348 }
349 
get_width(ScopeBase * scope) const350 int VTypeRecord::get_width(ScopeBase*scope) const
351 {
352     int width = 0;
353 
354     for(vector<element_t*>::const_iterator it = elements_.begin();
355             it != elements_.end(); ++it) {
356         int w = (*it)->peek_type()->get_width(scope);
357 
358         if(w < 0)
359             return -1;
360 
361         width += w;
362     }
363 
364     return width;
365 }
366 
element_by_name(perm_string name,int * index) const367 const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name, int*index) const
368 {
369       for (vector<element_t*>::const_iterator cur = elements_.begin()
370 		 ; cur != elements_.end() ; ++cur) {
371 	    element_t*curp = *cur;
372 	    if (curp->peek_name() == name) {
373 		  if (index)
374 		      *index = std::distance(elements_.begin(), cur);
375 
376 		  return curp;
377 	    }
378       }
379 
380       return 0;
381 }
382 
element_t(perm_string name,const VType * typ)383 VTypeRecord::element_t::element_t(perm_string name, const VType*typ)
384 : name_(name), type_(typ)
385 {
386 }
387 
VTypeDef(perm_string nam)388 VTypeDef::VTypeDef(perm_string nam)
389 : name_(nam), type_(0)
390 {
391 }
392 
VTypeDef(perm_string nam,const VType * typ)393 VTypeDef::VTypeDef(perm_string nam, const VType*typ)
394 : name_(nam), type_(typ)
395 {
396 }
397 
~VTypeDef()398 VTypeDef::~VTypeDef()
399 {
400 }
401 
set_definition(const VType * typ)402 void VTypeDef::set_definition(const VType*typ)
403 {
404       assert(type_ == 0);
405       type_ = typ;
406 }
407