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