2012-11-25 19:13:05 +01:00
|
|
|
/*
|
2014-11-25 04:09:35 +01:00
|
|
|
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
2012-11-25 19:13:05 +01:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "pform_types.h"
|
|
|
|
|
# include "netlist.h"
|
2013-01-28 04:52:43 +01:00
|
|
|
# include "netclass.h"
|
2013-01-27 21:30:38 +01:00
|
|
|
# include "netdarray.h"
|
2013-12-05 00:25:14 +01:00
|
|
|
# include "netenum.h"
|
2014-09-02 18:23:54 +02:00
|
|
|
# include "netparray.h"
|
2013-01-11 03:48:15 +01:00
|
|
|
# include "netscalar.h"
|
2013-12-01 03:20:01 +01:00
|
|
|
# include "netstruct.h"
|
2012-11-25 19:13:05 +01:00
|
|
|
# include "netvector.h"
|
2013-04-15 03:03:21 +02:00
|
|
|
# include "netmisc.h"
|
2012-11-25 19:13:05 +01:00
|
|
|
# include <typeinfo>
|
|
|
|
|
# include "ivl_assert.h"
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
2014-12-23 22:52:38 +01:00
|
|
|
/*
|
|
|
|
|
* Some types have a list of ranges that need to be elaborated. This
|
|
|
|
|
* function elaborates the ranges referenced by "dims" into the vector
|
|
|
|
|
* "ranges".
|
|
|
|
|
*/
|
|
|
|
|
static void elaborate_array_ranges(Design*des, NetScope*scope,
|
|
|
|
|
vector<netrange_t>&ranges,
|
|
|
|
|
const list<pform_range_t>*dims)
|
|
|
|
|
{
|
|
|
|
|
if (dims == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (list<pform_range_t>::const_iterator cur = dims->begin()
|
|
|
|
|
; cur != dims->end() ; ++ cur) {
|
|
|
|
|
|
|
|
|
|
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
|
|
|
|
|
|
|
|
|
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
|
|
|
|
|
|
|
|
|
/* If elaboration failed for either expression, we
|
|
|
|
|
should have already reported the error, so just
|
|
|
|
|
skip the following evaluation to recover. */
|
|
|
|
|
|
|
|
|
|
long mnum = 0, lnum = 0;
|
|
|
|
|
if ( me && ! eval_as_long(mnum, me) ) {
|
|
|
|
|
assert(0);
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( le && ! eval_as_long(lnum, le) ) {
|
|
|
|
|
assert(0);
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ranges.push_back(netrange_t(mnum, lnum));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-25 03:36:49 +02:00
|
|
|
/*
|
|
|
|
|
* Elaborations of types may vary depending on the scope that it is
|
|
|
|
|
* done in, so keep a per-scope cache of the results.
|
|
|
|
|
*/
|
|
|
|
|
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
|
|
|
|
{
|
2014-09-16 02:33:56 +02:00
|
|
|
Definitions*use_definitions = scope;
|
|
|
|
|
if (use_definitions == 0)
|
|
|
|
|
use_definitions = des;
|
|
|
|
|
|
|
|
|
|
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
|
2015-07-10 18:50:37 +02:00
|
|
|
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
|
|
|
|
|
return pos->second;
|
2014-04-25 03:36:49 +02:00
|
|
|
|
|
|
|
|
ivl_type_s*tmp = elaborate_type_raw(des, scope);
|
|
|
|
|
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
2012-11-25 19:13:05 +01:00
|
|
|
{
|
|
|
|
|
cerr << get_fileline() << ": internal error: "
|
|
|
|
|
<< "Elaborate method not implemented for " << typeid(*this).name()
|
|
|
|
|
<< "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
|
2012-11-25 19:13:05 +01:00
|
|
|
{
|
|
|
|
|
switch (type_code) {
|
2013-01-11 03:48:15 +01:00
|
|
|
case 64:
|
|
|
|
|
if (signed_flag)
|
|
|
|
|
return &netvector_t::atom2s64;
|
|
|
|
|
else
|
|
|
|
|
return &netvector_t::atom2u64;
|
|
|
|
|
|
2012-11-25 19:13:05 +01:00
|
|
|
case 32:
|
|
|
|
|
if (signed_flag)
|
|
|
|
|
return &netvector_t::atom2s32;
|
|
|
|
|
else
|
|
|
|
|
return &netvector_t::atom2u32;
|
|
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
|
if (signed_flag)
|
|
|
|
|
return &netvector_t::atom2s16;
|
|
|
|
|
else
|
|
|
|
|
return &netvector_t::atom2u16;
|
|
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
|
if (signed_flag)
|
|
|
|
|
return &netvector_t::atom2s8;
|
|
|
|
|
else
|
|
|
|
|
return &netvector_t::atom2u8;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
cerr << get_fileline() << ": internal error: "
|
|
|
|
|
<< "atom2_type_t type_code=" << type_code << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-11 03:48:15 +01:00
|
|
|
|
2014-10-11 03:53:53 +02:00
|
|
|
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
|
2013-01-28 04:52:43 +01:00
|
|
|
{
|
2014-10-11 03:53:53 +02:00
|
|
|
ivl_assert(*this, save_elaborated_type);
|
|
|
|
|
return save_elaborated_type;
|
2013-01-28 04:52:43 +01:00
|
|
|
}
|
|
|
|
|
|
2013-12-18 07:16:59 +01:00
|
|
|
/*
|
|
|
|
|
* elaborate_type_raw for enumerations is actually mostly performed
|
|
|
|
|
* during scope elaboration so that the enumeration literals are
|
2014-01-29 00:50:27 +01:00
|
|
|
* available at the right time. At that time, the netenum_t* object is
|
2013-12-18 07:16:59 +01:00
|
|
|
* stashed in the scope so that I can retrieve it here.
|
|
|
|
|
*/
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
2013-12-05 00:25:14 +01:00
|
|
|
{
|
2013-12-18 07:16:59 +01:00
|
|
|
ivl_assert(*this, scope);
|
|
|
|
|
ivl_type_s*tmp = scope->enumeration_for_key(this);
|
|
|
|
|
if (tmp) return tmp;
|
|
|
|
|
|
|
|
|
|
tmp = des->enumeration_for_key(this);
|
|
|
|
|
return tmp;
|
2013-12-05 00:25:14 +01:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
2013-04-15 03:03:21 +02:00
|
|
|
{
|
|
|
|
|
vector<netrange_t> packed;
|
2014-12-23 22:52:38 +01:00
|
|
|
elaborate_array_ranges(des, scope, packed, pdims.get());
|
2013-04-15 03:03:21 +02:00
|
|
|
|
|
|
|
|
netvector_t*tmp = new netvector_t(packed, base_type);
|
|
|
|
|
tmp->set_signed(signed_flag);
|
|
|
|
|
tmp->set_isint(integer_flag);
|
|
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const
|
2013-01-11 03:48:15 +01:00
|
|
|
{
|
|
|
|
|
switch (type_code) {
|
|
|
|
|
case REAL:
|
|
|
|
|
return &netreal_t::type_real;
|
|
|
|
|
case SHORTREAL:
|
|
|
|
|
return &netreal_t::type_shortreal;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2013-01-14 02:14:40 +01:00
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
|
2013-01-14 02:14:40 +01:00
|
|
|
{
|
|
|
|
|
return &netstring_t::type_string;
|
|
|
|
|
}
|
2013-01-27 21:30:38 +01:00
|
|
|
|
2014-12-23 22:52:38 +01:00
|
|
|
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
2014-11-25 04:09:35 +01:00
|
|
|
{
|
2014-12-23 22:52:38 +01:00
|
|
|
vector<netrange_t>packed;
|
|
|
|
|
elaborate_array_ranges(des, scope, packed, dims.get());
|
|
|
|
|
|
|
|
|
|
ivl_type_t etype = base_type->elaborate_type(des, scope);
|
|
|
|
|
|
|
|
|
|
return new netparray_t(packed, etype);
|
2014-11-25 04:09:35 +01:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
2013-12-01 03:20:01 +01:00
|
|
|
{
|
|
|
|
|
netstruct_t*res = new netstruct_t;
|
|
|
|
|
|
|
|
|
|
res->packed(packed_flag);
|
|
|
|
|
|
|
|
|
|
if (union_flag)
|
|
|
|
|
res->union_flag(true);
|
|
|
|
|
|
|
|
|
|
for (list<struct_member_t*>::iterator cur = members->begin()
|
|
|
|
|
; cur != members->end() ; ++ cur) {
|
|
|
|
|
|
|
|
|
|
// Elaborate the type of the member.
|
|
|
|
|
struct_member_t*curp = *cur;
|
|
|
|
|
ivl_type_t mem_vec = curp->type->elaborate_type(des, scope);
|
2013-12-05 00:25:14 +01:00
|
|
|
if (mem_vec == 0)
|
|
|
|
|
continue;
|
2013-12-01 03:20:01 +01:00
|
|
|
|
|
|
|
|
// There may be several names that are the same type:
|
|
|
|
|
// <data_type> name1, name2, ...;
|
|
|
|
|
// Process all the member, and give them a type.
|
|
|
|
|
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
|
|
|
|
|
; name != curp->names->end() ; ++ name) {
|
|
|
|
|
decl_assignment_t*namep = *name;
|
|
|
|
|
|
|
|
|
|
netstruct_t::member_t memb;
|
|
|
|
|
memb.name = namep->name;
|
|
|
|
|
memb.net_type = mem_vec;
|
|
|
|
|
res->append_member(des, memb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 03:36:13 +01:00
|
|
|
ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
2013-01-27 21:30:38 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
ivl_type_t btype = base_type->elaborate_type(des, scope);
|
|
|
|
|
|
2014-09-02 18:23:54 +02:00
|
|
|
assert(dims->size() >= 1);
|
2013-01-27 21:30:38 +01:00
|
|
|
list<pform_range_t>::const_iterator cur = dims->begin();
|
2014-09-02 18:23:54 +02:00
|
|
|
|
|
|
|
|
// Special case: if the dimension is nil:nil, this is a
|
|
|
|
|
// dynamic array. Note that we only know how to handle dynamic
|
|
|
|
|
// arrays with 1 dimension at a time.
|
|
|
|
|
if (cur->first==0 && cur->second==0) {
|
|
|
|
|
assert(dims->size()==1);
|
|
|
|
|
ivl_type_s*res = new netdarray_t(btype);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<netrange_t> dimensions;
|
|
|
|
|
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
|
|
|
|
|
2014-09-16 02:33:56 +02:00
|
|
|
if (bad_range) {
|
|
|
|
|
cerr << get_fileline() << " : warning: "
|
|
|
|
|
<< "Bad dimensions for type here." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivl_assert(*this, btype);
|
2014-09-02 18:23:54 +02:00
|
|
|
ivl_type_s*res = new netuarray_t(dimensions, btype);
|
2013-01-27 21:30:38 +01:00
|
|
|
return res;
|
|
|
|
|
}
|