2011-02-07 05:55:31 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
|
|
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2011-02-07 05:55:31 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "vtype.h"
|
2011-11-05 23:55:17 +01:00
|
|
|
# include "parse_types.h"
|
2015-01-22 11:32:28 +01:00
|
|
|
# include "compiler.h"
|
2011-04-18 02:19:09 +02:00
|
|
|
# include <map>
|
2011-02-14 04:01:21 +01:00
|
|
|
# include <typeinfo>
|
2012-05-06 00:15:45 +02:00
|
|
|
# include <cassert>
|
2015-02-06 10:44:22 +01:00
|
|
|
# include <algorithm>
|
2011-02-07 05:55:31 +01:00
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
VType::~VType()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-14 04:01:21 +01:00
|
|
|
void VType::show(ostream&out) const
|
|
|
|
|
{
|
2013-05-06 04:05:46 +02:00
|
|
|
write_to_stream(out);
|
2011-02-14 04:01:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-22 11:32:28 +01:00
|
|
|
perm_string VType::get_generic_typename() const
|
|
|
|
|
{
|
|
|
|
|
char buf[16] = {0,};
|
|
|
|
|
snprintf(buf, 16, "type_%p", this);
|
|
|
|
|
return lex_strings.make(buf);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-22 10:45:02 +02:00
|
|
|
VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt, bool packed)
|
|
|
|
|
: type_(tt), packed_(packed)
|
2011-02-07 05:55:31 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VTypePrimitive::~VTypePrimitive()
|
|
|
|
|
{
|
|
|
|
|
}
|
2011-02-14 01:37:10 +01:00
|
|
|
|
2011-02-14 04:01:21 +01:00
|
|
|
void VTypePrimitive::show(ostream&out) const
|
|
|
|
|
{
|
|
|
|
|
switch (type_) {
|
|
|
|
|
case BOOLEAN:
|
|
|
|
|
out << "BOOLEAN";
|
|
|
|
|
break;
|
|
|
|
|
case BIT:
|
|
|
|
|
out << "BIT";
|
|
|
|
|
break;
|
2013-05-13 00:31:48 +02:00
|
|
|
case CHARACTER:
|
|
|
|
|
out << "CHARACTER";
|
|
|
|
|
break;
|
2011-02-14 04:01:21 +01:00
|
|
|
case INTEGER:
|
|
|
|
|
out << "INTEGER";
|
|
|
|
|
break;
|
2015-02-17 14:58:33 +01:00
|
|
|
case NATURAL:
|
|
|
|
|
out << "NATURAL";
|
|
|
|
|
break;
|
2014-08-06 15:00:35 +02:00
|
|
|
case REAL:
|
2014-08-22 10:45:02 +02:00
|
|
|
out << "REAL";
|
|
|
|
|
break;
|
2011-02-14 04:01:21 +01:00
|
|
|
case STDLOGIC:
|
2015-02-17 14:58:33 +01:00
|
|
|
out << "STD_LOGIC";
|
2011-02-14 04:01:21 +01:00
|
|
|
break;
|
2015-05-20 18:53:29 +02:00
|
|
|
case TIME:
|
|
|
|
|
out << "TIME";
|
|
|
|
|
break;
|
2011-02-14 04:01:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 14:33:26 +01:00
|
|
|
int VTypePrimitive::get_width(ScopeBase*) const
|
2015-02-26 13:27:47 +01:00
|
|
|
{
|
|
|
|
|
switch(type_) {
|
|
|
|
|
case BOOLEAN:
|
|
|
|
|
case BIT:
|
|
|
|
|
case STDLOGIC:
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case INTEGER:
|
|
|
|
|
case NATURAL:
|
|
|
|
|
return 32;
|
|
|
|
|
|
|
|
|
|
case CHARACTER:
|
|
|
|
|
return 8;
|
2015-03-27 11:43:09 +01:00
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
std::cerr << "sorry: primitive type " << type_ <<
|
|
|
|
|
" has no get_width() implementation." << std::endl;
|
|
|
|
|
break;
|
2015-02-26 13:27:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-02 11:00:59 +01:00
|
|
|
VTypeArray::range_t*VTypeArray::range_t::clone() const
|
|
|
|
|
{
|
|
|
|
|
return new VTypeArray::range_t(safe_clone(msb_), safe_clone(lsb_), direction_);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 05:09:31 +01:00
|
|
|
VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv)
|
2015-01-23 17:07:19 +01:00
|
|
|
: etype_(element), ranges_(r), signed_flag_(sv), parent_(NULL)
|
2011-02-14 01:37:10 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-05 23:55:17 +01:00
|
|
|
/*
|
|
|
|
|
* Create a VTypeArray range set from a list of parsed ranges.
|
|
|
|
|
* FIXME: We are copying pointers from the prange_t object into the
|
|
|
|
|
* range_t. This means that we cannot delete the prange_t object
|
|
|
|
|
* unless we invent a way to remove the pointers from that object. So
|
|
|
|
|
* this is a memory leak. Something to fix.
|
|
|
|
|
*/
|
|
|
|
|
VTypeArray::VTypeArray(const VType*element, std::list<prange_t*>*r, bool sv)
|
2015-01-23 17:07:19 +01:00
|
|
|
: etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL)
|
2011-11-05 23:55:17 +01:00
|
|
|
{
|
|
|
|
|
for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) {
|
|
|
|
|
prange_t*curp = r->front();
|
|
|
|
|
r->pop_front();
|
|
|
|
|
Expression*msb = curp->msb();
|
|
|
|
|
Expression*lsb = curp->lsb();
|
2014-09-10 14:32:02 +02:00
|
|
|
bool dir = curp->is_downto();
|
|
|
|
|
ranges_[idx] = range_t(msb, lsb, dir);
|
2011-11-05 23:55:17 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-27 13:56:59 +01:00
|
|
|
VTypeArray::VTypeArray(const VType*element, int msb, int lsb, bool sv)
|
|
|
|
|
: etype_(element), ranges_(1), signed_flag_(sv), parent_(NULL)
|
|
|
|
|
{
|
|
|
|
|
bool down_to = msb > lsb;
|
|
|
|
|
ranges_[0] = range_t(new ExpInteger(msb), new ExpInteger(lsb), down_to);
|
|
|
|
|
}
|
2011-11-05 23:55:17 +01:00
|
|
|
|
2011-02-14 01:37:10 +01:00
|
|
|
VTypeArray::~VTypeArray()
|
|
|
|
|
{
|
|
|
|
|
}
|
2011-02-14 04:01:21 +01:00
|
|
|
|
2015-02-02 11:00:59 +01:00
|
|
|
VType*VTypeArray::clone() const {
|
|
|
|
|
std::vector<range_t> new_ranges;
|
|
|
|
|
new_ranges.reserve(ranges_.size());
|
|
|
|
|
for(std::vector<range_t>::const_iterator it = ranges_.begin();
|
|
|
|
|
it != ranges_.end(); ++it) {
|
|
|
|
|
new_ranges.push_back(*(it->clone()));
|
|
|
|
|
}
|
|
|
|
|
VTypeArray*a = new VTypeArray(etype_->clone(), new_ranges, signed_flag_);
|
|
|
|
|
a->set_parent_type(parent_);
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-15 11:08:14 +02:00
|
|
|
const VType* VTypeArray::basic_type(bool typedef_allowed) const
|
|
|
|
|
{
|
|
|
|
|
const VType*t = etype_;
|
|
|
|
|
const VTypeDef*tdef = NULL;
|
|
|
|
|
bool progress = false;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
progress = false;
|
|
|
|
|
|
|
|
|
|
if((tdef = dynamic_cast<const VTypeDef*>(t))) {
|
|
|
|
|
t = tdef->peek_definition();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(t)) {
|
|
|
|
|
t = arr->element_type();
|
|
|
|
|
progress = true;
|
|
|
|
|
} else if(tdef) { // return the typedef if it does not define an array
|
|
|
|
|
t = typedef_allowed ? tdef : tdef->peek_definition();
|
|
|
|
|
}
|
|
|
|
|
} while(progress);
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
2011-02-14 04:01:21 +01:00
|
|
|
|
|
|
|
|
void VTypeArray::show(ostream&out) const
|
|
|
|
|
{
|
|
|
|
|
out << "array ";
|
|
|
|
|
for (vector<range_t>::const_iterator cur = ranges_.begin()
|
|
|
|
|
; cur != ranges_.end() ; ++cur) {
|
2011-11-06 01:22:30 +01:00
|
|
|
out << "(";
|
|
|
|
|
if (cur->msb())
|
|
|
|
|
cur->msb()->write_to_stream(out);
|
|
|
|
|
else
|
|
|
|
|
out << "<>";
|
|
|
|
|
out << " downto ";
|
|
|
|
|
if (cur->lsb())
|
|
|
|
|
cur->lsb()->write_to_stream(out);
|
|
|
|
|
else
|
|
|
|
|
out << "<>";
|
|
|
|
|
out << ")";
|
2011-02-14 04:01:21 +01:00
|
|
|
}
|
|
|
|
|
out << " of ";
|
2011-02-26 05:09:31 +01:00
|
|
|
if (signed_flag_)
|
|
|
|
|
out << "signed ";
|
2011-02-14 04:01:21 +01:00
|
|
|
if (etype_)
|
|
|
|
|
etype_->show(out);
|
|
|
|
|
else
|
|
|
|
|
out << "<nil>";
|
|
|
|
|
}
|
2011-04-18 02:19:09 +02:00
|
|
|
|
2015-03-02 14:33:26 +01:00
|
|
|
int VTypeArray::get_width(ScopeBase*scope) const
|
2015-02-26 13:27:47 +01:00
|
|
|
{
|
|
|
|
|
int64_t size = 1;
|
|
|
|
|
|
|
|
|
|
for(vector<range_t>::const_iterator it = ranges_.begin();
|
|
|
|
|
it != ranges_.end(); ++it) {
|
|
|
|
|
const VTypeArray::range_t&dim = *it;
|
|
|
|
|
int64_t msb_val, lsb_val;
|
|
|
|
|
|
|
|
|
|
if(dim.is_box())
|
2015-02-24 16:06:55 +01:00
|
|
|
return -1;
|
2015-02-26 13:27:47 +01:00
|
|
|
|
2015-03-02 14:33:26 +01:00
|
|
|
if(!dim.msb()->evaluate(scope, msb_val))
|
2015-02-26 13:27:47 +01:00
|
|
|
return -1;
|
|
|
|
|
|
2015-03-02 14:33:26 +01:00
|
|
|
if(!dim.lsb()->evaluate(scope, lsb_val))
|
2015-02-26 13:27:47 +01:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
size *= 1 + labs(msb_val - lsb_val);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 14:33:26 +01:00
|
|
|
return element_type()->get_width(scope) * size;
|
2015-02-26 13:27:47 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-22 11:17:33 +01:00
|
|
|
bool VTypeArray::is_unbounded() const {
|
|
|
|
|
for(std::vector<range_t>::const_iterator it = ranges_.begin();
|
|
|
|
|
it != ranges_.end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
if(it->is_box())
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return etype_->is_unbounded();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 11:15:57 +01:00
|
|
|
bool VTypeArray::is_variable_length(ScopeBase*scope) const {
|
2015-01-23 17:24:00 +01:00
|
|
|
int64_t dummy;
|
|
|
|
|
|
2015-01-26 11:15:57 +01:00
|
|
|
if(is_unbounded())
|
|
|
|
|
return true;
|
|
|
|
|
|
2015-01-23 17:24:00 +01:00
|
|
|
for(std::vector<range_t>::const_iterator it = ranges_.begin();
|
|
|
|
|
it != ranges_.end(); ++it)
|
|
|
|
|
{
|
2015-01-26 11:15:57 +01:00
|
|
|
if(!it->lsb()->evaluate(scope, dummy))
|
2015-01-23 17:24:00 +01:00
|
|
|
return true;
|
|
|
|
|
|
2015-01-26 11:15:57 +01:00
|
|
|
if(!it->msb()->evaluate(scope, dummy))
|
2015-01-23 17:24:00 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 11:15:57 +01:00
|
|
|
return etype_->is_variable_length(scope);
|
2015-01-23 17:24:00 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-26 17:51:42 +01:00
|
|
|
void VTypeArray::evaluate_ranges(ScopeBase*scope) {
|
|
|
|
|
for(std::vector<range_t>::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) {
|
|
|
|
|
int64_t lsb_val = -1, msb_val = -1;
|
|
|
|
|
bool dir = it->is_downto();
|
|
|
|
|
|
|
|
|
|
if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) {
|
|
|
|
|
assert(lsb_val >= 0);
|
|
|
|
|
assert(msb_val >= 0);
|
|
|
|
|
*it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), dir);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-24 17:00:21 +02:00
|
|
|
VTypeRange::VTypeRange(const VType*base, int64_t end_val, int64_t start_val)
|
|
|
|
|
: base_(base), end_(end_val), start_(start_val)
|
2011-04-18 02:19:09 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VTypeRange::~VTypeRange()
|
|
|
|
|
{
|
|
|
|
|
}
|
2011-10-02 02:04:04 +02:00
|
|
|
|
|
|
|
|
VTypeEnum::VTypeEnum(const std::list<perm_string>*names)
|
|
|
|
|
: names_(names->size())
|
|
|
|
|
{
|
|
|
|
|
size_t idx = 0;
|
|
|
|
|
|
|
|
|
|
for (list<perm_string>::const_iterator cur = names->begin()
|
|
|
|
|
; cur != names->end() ; ++cur, ++idx) {
|
|
|
|
|
names_[idx] = *cur;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VTypeEnum::~VTypeEnum()
|
|
|
|
|
{
|
|
|
|
|
}
|
2011-10-10 00:25:35 +02:00
|
|
|
|
|
|
|
|
void VTypeEnum::show(ostream&out) const
|
|
|
|
|
{
|
|
|
|
|
out << "(";
|
|
|
|
|
if (names_.size() >= 1)
|
|
|
|
|
out << names_[0];
|
|
|
|
|
for (size_t idx = 1 ; idx < names_.size() ; idx += 1)
|
|
|
|
|
out << ", " << names_[idx];
|
|
|
|
|
out << ")";
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 10:44:22 +01:00
|
|
|
bool VTypeEnum::has_name(perm_string name) const
|
|
|
|
|
{
|
|
|
|
|
return std::find(names_.begin(), names_.end(), name) != names_.end();
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
VTypeRecord::VTypeRecord(std::list<element_t*>*elements)
|
|
|
|
|
: elements_(elements->size())
|
|
|
|
|
{
|
|
|
|
|
for (size_t idx = 0 ; idx < elements_.size() ; idx += 1) {
|
|
|
|
|
elements_[idx] = elements->front();
|
|
|
|
|
elements->pop_front();
|
|
|
|
|
}
|
|
|
|
|
delete elements;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VTypeRecord::~VTypeRecord()
|
|
|
|
|
{
|
|
|
|
|
for (size_t idx = 0 ; idx < elements_.size() ; idx += 1)
|
|
|
|
|
delete elements_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VTypeRecord::show(ostream&out) const
|
|
|
|
|
{
|
2012-03-18 19:21:23 +01:00
|
|
|
write_to_stream(out);
|
2012-03-17 23:03:19 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 14:33:26 +01:00
|
|
|
int VTypeRecord::get_width(ScopeBase*scope) const
|
2015-02-26 13:27:47 +01:00
|
|
|
{
|
|
|
|
|
int width = 0;
|
|
|
|
|
|
|
|
|
|
for(vector<element_t*>::const_iterator it = elements_.begin();
|
|
|
|
|
it != elements_.end(); ++it) {
|
2015-03-02 14:33:26 +01:00
|
|
|
int w = (*it)->peek_type()->get_width(scope);
|
2015-02-26 13:27:47 +01:00
|
|
|
|
|
|
|
|
if(w < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
width += w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return width;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-17 16:32:56 +02:00
|
|
|
const VTypeRecord::element_t* VTypeRecord::element_by_name(perm_string name, int*index) const
|
2012-04-02 03:48:19 +02:00
|
|
|
{
|
|
|
|
|
for (vector<element_t*>::const_iterator cur = elements_.begin()
|
|
|
|
|
; cur != elements_.end() ; ++cur) {
|
|
|
|
|
element_t*curp = *cur;
|
2014-09-17 16:32:56 +02:00
|
|
|
if (curp->peek_name() == name) {
|
|
|
|
|
if (index)
|
|
|
|
|
*index = std::distance(elements_.begin(), cur);
|
|
|
|
|
|
2012-04-02 03:48:19 +02:00
|
|
|
return curp;
|
2014-09-17 16:32:56 +02:00
|
|
|
}
|
2012-04-02 03:48:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-17 23:03:19 +01:00
|
|
|
VTypeRecord::element_t::element_t(perm_string name, const VType*typ)
|
|
|
|
|
: name_(name), type_(typ)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-06 00:15:45 +02:00
|
|
|
VTypeDef::VTypeDef(perm_string nam)
|
|
|
|
|
: name_(nam), type_(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-10 00:25:35 +02:00
|
|
|
VTypeDef::VTypeDef(perm_string nam, const VType*typ)
|
|
|
|
|
: name_(nam), type_(typ)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VTypeDef::~VTypeDef()
|
|
|
|
|
{
|
|
|
|
|
}
|
2012-05-06 00:15:45 +02:00
|
|
|
|
|
|
|
|
void VTypeDef::set_definition(const VType*typ)
|
|
|
|
|
{
|
|
|
|
|
assert(type_ == 0);
|
|
|
|
|
type_ = typ;
|
|
|
|
|
}
|