Merge branch 'work12'

This commit is contained in:
Stephen Williams 2012-09-14 17:28:50 -07:00
commit 6137566385
43 changed files with 1238 additions and 489 deletions

View File

@ -363,7 +363,7 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
const NetExpr*ex1, *ex2;
scope = symbol_search(0, des, scope, path_, net, par, eve, ex1, ex2);
scope = symbol_search(this, des, scope, path_, net, par, eve, ex1, ex2);
if (scope)
return scope->is_auto();

View File

@ -29,7 +29,7 @@ PWire::PWire(perm_string n,
: name_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), enum_type_(0), struct_type_(0),
error_cnt_(0), set_data_type_(0),
discipline_(0)
{
if (t == NetNet::INTEGER) {
@ -253,18 +253,10 @@ void PWire::set_unpacked_idx(const list<pform_range_t>&ranges)
}
}
void PWire::set_enumeration(enum_type_t*enum_type)
void PWire::set_packed_type(data_type_t*type)
{
assert(enum_type_ == 0);
assert(struct_type_ == 0);
enum_type_ = enum_type;
}
void PWire::set_struct_type(struct_type_t*type)
{
assert(enum_type_ == 0);
assert(struct_type_ == 0);
struct_type_ = type;
assert(set_data_type_ == 0);
set_data_type_ = type;
}
void PWire::set_discipline(ivl_discipline_t d)

View File

@ -81,8 +81,7 @@ class PWire : public LineInfo {
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
void set_enumeration(enum_type_t*enum_type);
void set_struct_type(struct_type_t*type);
void set_packed_type(data_type_t*type);
void set_discipline(ivl_discipline_t);
ivl_discipline_t get_discipline(void) const;
@ -119,8 +118,7 @@ class PWire : public LineInfo {
// me the size and address ranges of the memory.
std::list<pform_range_t>unpacked_;
enum_type_t*enum_type_;
struct_type_t*struct_type_;
data_type_t*set_data_type_;
ivl_discipline_t discipline_;

View File

@ -229,7 +229,10 @@ ostream&operator<<(ostream&out, const vector<netrange_t>&rlist)
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name()
<< unpacked_dims_ << " unpacked dims=" << unpacked_dimensions() << " count=" << pin_count();
<< unpacked_dims_ << " unpacked dims=" << unpacked_dimensions();
if (!packed_dims_.empty())
o << " packed dims=" << packed_dims_;
o << " pin_count=" << pin_count();
if (local_flag_)
o << " (local)";
o << " " << data_type_;
@ -264,6 +267,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
if (! packed_dims_.empty())
o << " packed dims: " << packed_dims_;
if (net_type_)
o << " net_type_=" << typeid(*net_type_).name();
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());

View File

@ -1553,7 +1553,9 @@ bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
*/
static NetExpr* check_for_struct_members(const LineInfo*li,
Design*des, NetScope*scope,
NetNet*net, const name_component_t&comp)
NetNet*net,
const list<index_component_t>&base_index,
const name_component_t&comp)
{
unsigned long off;
const netstruct_t::member_t*mem = get_struct_member(li, des, 0, net,
@ -1563,12 +1565,14 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
unsigned use_width = mem->width();
if (debug_elaborate) {
cerr << li->get_fileline() << ": check_for_struct_members: "
cerr << li->get_fileline() << ": debug: check_for_struct_members: "
<< "Found struct member " << mem->name
<< " At offset " << off
<< ", member width = " << use_width << endl;
}
// The struct member may be a packed array. Process index
// expression that address the member element.
if ( ! comp.index.empty() ) {
// Evaluate all but the last index expression, into prefix_indices.
list<long>prefix_indices;
@ -1597,7 +1601,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
prefix_to_slice(mem->packed_dims, prefix_indices, poff, loff, lwid);
if (debug_elaborate) {
cerr << li->get_fileline() << ": check_for_struct_members: "
cerr << li->get_fileline() << ": debug: check_for_struct_members: "
<< "Evaluate prefix gives slice loff=" << loff
<< ", lwid=" << lwid << ", part select pwid=" << pwid << endl;
}
@ -1609,8 +1613,44 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
use_width = lwid;
}
// If the base symbol has dimensions, then this is a packed
// array of structures. Convert an array of indices to a
// single part select. For example, "net" is a packed array
// of struct, and "mem" is the struct member. In Verilog it
// looks something like "net[idx].mem". We've already
// converted "mem" to an offset into the packed struct, so now
// we just canonicalize "[idx]" and add the ".mem" offset to
// get a collapsed index.
NetExpr*packed_base = 0;
if(net->packed_dimensions() > 1) {
list<index_component_t>tmp_index = base_index;
index_component_t member_select;
member_select.sel = index_component_t::SEL_BIT;
member_select.msb = new PENumber(new verinum(off));
tmp_index.push_back(member_select);
packed_base = collapse_array_exprs(des, scope, li, net, tmp_index);
ivl_assert(*li, packed_base);
if (debug_elaborate) {
cerr << li->get_fileline() << ": debug: check_for_struct_members: "
<< "Got collapsed array expr: " << *packed_base << endl;
}
}
long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) {
off = tmp;
delete packed_base;
packed_base = 0;
}
NetESignal*sig = new NetESignal(net);
NetEConst*base = make_const_val(off);
NetExpr *base = packed_base? packed_base : make_const_val(off);
if (debug_elaborate) {
cerr << li->get_fileline() << ": debug: check_for_struct_members: "
<< "Convert packed indices/member select into part select: " << *base << endl;
}
NetESelect*sel = new NetESelect(sig, base, use_width);
return sel;
}
@ -2263,7 +2303,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
const NetExpr*ex1, *ex2;
NetScope*found_in = symbol_search(0, des, scope, path_, net, par, eve,
NetScope*found_in = symbol_search(this, des, scope, path_, net, par, eve,
ex1, ex2);
// If there is a part/bit select expression, then process it
@ -2352,7 +2392,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
ivl_assert(*this, use_enum != 0);
expr_type_ = use_enum->base_type();
expr_width_ = use_enum->base_width();
expr_width_ = use_enum->packed_width();
min_width_ = expr_width_;
signed_flag_ = par_enum->has_sign();
@ -2400,9 +2440,17 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
// Check to see if we have a net and if so is it a structure?
if (net != 0) {
// If this net is a struct, the method name may be
// a struct member.
// a struct member. If it is, then we know the
// width of this identifier my knowing the width
// of the member. We don't even need to know
// anything about positions in containing arrays.
if (net->struct_type() != 0) {
ivl_assert(*this, use_path.back().index.empty());
if (debug_elaborate) {
cerr << get_fileline() << ": debug: PEIdent::test_width: "
<< "Net " << use_path << " is a struct, "
<< "checking width of member " << method_name << endl;
}
const netstruct_t::member_t*mem;
unsigned long unused;
@ -2603,10 +2651,19 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
// If this net is a struct, the method name may be
// a struct member.
if (net->struct_type() != 0) {
ivl_assert(*this, use_path.back().index.empty());
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "PEIdent::elaborate_expr: "
<< "Ident " << use_path
<< " is a struct."
<< " Expecting " << net->packed_dims().size()
<< "-1 dimensions, "
<< "got " << use_path.back().index.size() << "." << endl;
}
return check_for_struct_members(this, des, scope,
net, member_comp);
net, use_path.back().index,
member_comp);
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -682,6 +683,11 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: elaborate lval packed member: "
<< "path_=" << path_ << endl;
}
if (! struct_type->packed()) {
cerr << get_fileline() << ": sorry: Only packed structures "
<< "are supported in l-value." << endl;
@ -689,6 +695,27 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
return false;
}
// Shouldn't be seeing unpacked arrays of packed structs...
ivl_assert(*this, reg->unpacked_dimensions() == 0);
// This is a packed member, so the name is of the form
// "a.b[...].c[...]" which means that the path_ must have at
// least 2 components. We are processing "c[...]" at that
// point (otherwise known as member_name) so we'll save a
// reference to it in name_tail. We are also processing "b[]"
// so save that as name_base.
ivl_assert(*this, path_.size() >= 2);
pform_name_t::const_reverse_iterator name_idx = path_.rbegin();
ivl_assert(*this, name_idx->name == member_name);
const name_component_t&name_tail = *name_idx;
++ name_idx;
const name_component_t&name_base = *name_idx;
// Calculate the offset within the packed structure of the
// member, and any indices. We will add in the offset of the
// struct into the packed array later.
unsigned long off;
const netstruct_t::member_t* member = struct_type->packed_member(member_name, off);
@ -701,14 +728,8 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
unsigned long use_width = member->width();
// We are processing the tail of a string of names. For
// example, the verilog may be "a.b.c", so we are processing
// "c" at this point. Of course, "c" is the name of the member
// we are working on and "a.b" is the name of reg.
const name_component_t&name_tail = path_.back();
if (name_tail.index.size() > member->packed_dims.size()) {
cerr << get_fileline() << ": error: Too make index expressions for member." << endl;
cerr << get_fileline() << ": error: Too many index expressions for member." << endl;
des->errors += 1;
return false;
}
@ -749,10 +770,48 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
use_width = lwid;
}
// The dimenions in the expression must match the packed
// dimensions that are declared for the variable. For example,
// if foo is a packed array of struct, then this expression
// must be "b[n][m]" with the right number of dimensions to
// match the declaration of "b".
// Note that one of the packed dimensions is the packed struct
// itself.
ivl_assert(*this, name_base.index.size()+1 == reg->packed_dimensions());
// Generate an expression that takes the input array of
// expressions and generates a canonical offset into the
// packed array.
NetExpr*packed_base = 0;
if (reg->packed_dimensions() > 1) {
list<index_component_t>tmp_index = name_base.index;
index_component_t member_select;
member_select.sel = index_component_t::SEL_BIT;
member_select.msb = new PENumber(new verinum(off));
tmp_index.push_back(member_select);
packed_base = collapse_array_indices(des, scope, reg, tmp_index);
}
long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) {
off = tmp;
delete packed_base;
packed_base = 0;
}
if (packed_base == 0) {
lv->set_part(new NetEConst(verinum(off)), use_width);
return true;
}
// Oops, packed_base is not fully evaluated, so I don't know
// yet what to do with it.
cerr << get_fileline() << ": internal error: "
<< "I don't know how to handle this index expression? " << *packed_base << endl;
ivl_assert(*this, 0);
return false;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
{
cerr << get_fileline() << ": error: Constant values not allowed "

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -418,15 +419,20 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0;
}
// Break the path_ into the tail name and the prefix. For
// example, a name "a.b.c" is broken into name_tail="c" and
// path_prefix="a.b".
const name_component_t&path_tail = path_.back();
pform_name_t path_prefix = path_;
path_prefix.pop_back();
/* If the signal is not found, check to see if this is a
member of a struct. Take the name of the form "a.b.member",
remove the member and store it into method_name, and retry
the search with "a.b". */
if (sig == 0 && path_.size() >= 2) {
pform_name_t use_path = path_;
method_name = peek_tail_name(use_path);
use_path.pop_back();
symbol_search(this, des, scope, use_path, sig, par, eve);
method_name = path_tail.name;
symbol_search(this, des, scope, path_prefix, sig, par, eve);
// Whoops, not a struct signal, so give up on this avenue.
if (sig && sig->struct_type() == 0) {
@ -467,14 +473,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// The default word select is the first.
long widx = 0;
const name_component_t&name_tail = path_.back();
list<long> unpacked_indices_const;
netstruct_t*struct_type = 0;
if ((struct_type = sig->struct_type()) && !method_name.nil()) {
// Detect the variable is a structure and there was a
// method name detected.
// method name detected. We've already found that
// the path_ is <>.sig.method_name and signal
// (NetNet). We also know that sig is struct_type(), so
// look for a method named method_name.
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Signal " << sig->name() << " is a structure, "
@ -489,13 +497,50 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
lidx = member_off;
midx = lidx + member->width() - 1;
// The dimensions of the tail of the prefix must match
// the dimensions of the signal at this point. (The sig
// has a packed dimension for the packed struct size.)
// For example, if the path_=a[<m>][<n>].member, then
// sig must have 3 packed dimenions: one for the struct
// members and two actual packed dimensions.
ivl_assert(*this, path_prefix.back().index.size()+1 == sig->packed_dimensions());
// Elaborate an expression from the packed indices and
// the member offset (into the structure) to get a
// canonical expression into the packed signal vector.
NetExpr*packed_base = 0;
if (sig->packed_dimensions() > 1) {
list<index_component_t>tmp_index = path_prefix.back().index;
index_component_t member_select;
member_select.sel = index_component_t::SEL_BIT;
member_select.msb = new PENumber(new verinum(member_off));
tmp_index.push_back(member_select);
packed_base = collapse_array_indices(des, scope, sig, tmp_index);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "packed_base expression = " << *packed_base << endl;
}
}
long tmp;
if (packed_base && eval_as_long(tmp, packed_base)) {
lidx = tmp;
midx = lidx + member->width() - 1;
delete packed_base;
packed_base = 0;
}
// Currently, only support const dimensions here.
ivl_assert(*this, packed_base == 0);
} else if (sig->unpacked_dimensions() > 0) {
// Make sure there are enough indices to address an array element.
if (name_tail.index.size() < sig->unpacked_dimensions()) {
if (path_tail.index.size() < sig->unpacked_dimensions()) {
cerr << get_fileline() << ": error: Array " << path()
<< " needs " << sig->unpacked_dimensions() << " indices,"
<< " but got only " << name_tail.index.size() << "." << endl;
<< " but got only " << path_tail.index.size() << "." << endl;
des->errors += 1;
return 0;
}
@ -504,7 +549,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// "unpacked_indices" array.
list<NetExpr*>unpacked_indices;
bool flag = indices_to_expressions(des, scope, this,
name_tail.index, sig->unpacked_dimensions(),
path_tail.index, sig->unpacked_dimensions(),
true,
unpacked_indices,
unpacked_indices_const);
@ -539,7 +584,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< " to index l-value array." << endl;
/* The array has a part/bit select at the end. */
if (name_tail.index.size() > sig->unpacked_dimensions()) {
if (path_tail.index.size() > sig->unpacked_dimensions()) {
if (sig->get_scalar()) {
cerr << get_fileline() << ": error: "
<< "can not select part of ";
@ -566,7 +611,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
lidx = lidx_tmp;
}
} else if (!name_tail.index.empty()) {
} else if (!path_tail.index.empty()) {
if (sig->get_scalar()) {
cerr << get_fileline() << ": error: "
<< "can not select part of ";

View File

@ -181,12 +181,12 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
verinum max_value (0);
if (enum_type->signed_flag) {
min_value = v_not((pow(verinum(2),
verinum(use_enum->base_width()-1)))) +
verinum(use_enum->packed_width()-1)))) +
one_value;
max_value = pow(verinum(2), verinum(use_enum->base_width()-1)) -
max_value = pow(verinum(2), verinum(use_enum->packed_width()-1)) -
one_value;
} else {
max_value = pow(verinum(2), verinum(use_enum->base_width())) -
max_value = pow(verinum(2), verinum(use_enum->packed_width())) -
one_value;
}
min_value.has_sign(true);
@ -249,15 +249,15 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
// The values are explicitly sized to the width of the
// base type of the enumeration.
verinum tmp_val (0);
if (cur_value.len() < use_enum->base_width()) {
if (cur_value.len() < use_enum->packed_width()) {
// Pad the current value if it is narrower than the final
// width of the enum.
tmp_val = pad_to_width (cur_value, use_enum->base_width());
tmp_val = pad_to_width (cur_value, use_enum->packed_width());
tmp_val.has_len(true);
} else {
// Truncate an oversized value. We report out of bound
// values above. This may create duplicates.
tmp_val = verinum(cur_value, use_enum->base_width());
tmp_val = verinum(cur_value, use_enum->packed_width());
}
tmp_val.has_sign(enum_type->signed_flag);

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -19,6 +20,7 @@
# include "config.h"
# include <typeinfo>
# include <cstdlib>
# include <iostream>
@ -35,9 +37,12 @@
# include "netenum.h"
# include "netstruct.h"
# include "netdarray.h"
# include "netparray.h"
# include "util.h"
# include "ivl_assert.h"
using namespace std;
static bool get_const_argument(NetExpr*exp, verinum&res)
{
switch (exp->expr_type()) {
@ -892,6 +897,35 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
return res;
}
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
list<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
ivl_assert(*data_type, !bad_range);
netparray_t*res = new netparray_t(packed_dimensions);
//res->set_line(*data_type);
return res;
}
static nettype_base_t*elaborate_type(Design*des, NetScope*scope,
data_type_t*pform_type)
{
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
return use_type;
}
cerr << pform_type->get_fileline() << ": sorry: I don't know how to elaborate "
<< typeid(*pform_type).name() << " here." << endl;
des->errors += 1;
return 0;
}
bool test_ranges_eeq(const list<netrange_t>&lef, const list<netrange_t>&rig)
{
if (lef.size() != rig.size())
@ -1158,8 +1192,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// If this is a struct type, then build the net with the
// struct type.
if (struct_type_) {
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type_);
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype;
if (use_type->packed())
@ -1172,23 +1206,22 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
sig = new NetNet(scope, name_, wtype, use_type);
} else if (enum_type_) {
ivl_assert(*this, struct_type_ == 0);
ivl_assert(*this, ! enum_type_->names->empty());
list<named_pexpr_t>::const_iterator sample_name = enum_type_->names->begin();
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " enumeration "
<< name_ << " in scope " << scope_path(scope) << endl;
<< name_ << " in scope " << scope_path(scope)
<< " with packed_dimensions=" << packed_dimensions
<< " and packed_width=" << use_enum->packed_width() << endl;
}
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum);
} else if (netarray) {
ivl_assert(*this, struct_type_==0);
ivl_assert(*this, enum_type_==0);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
@ -1200,6 +1233,35 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
ivl_assert(*this, unpacked_dimensions.empty());
sig = new NetNet(scope, name_, wtype, netarray);
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
// The pform gives us a parray_type_t for packed arrays
// that show up in type definitions. This can be handled
// a lot like packed dimensions from other means.
// The trick here is that the parray type has an
// arbitrary sub-type, and not just a scalar bit...
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
// Should not be getting packed dimensions other then
// through the parray type declaration.
ivl_assert(*this, packed_dimensions.empty());
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype
<< " parray=" << use_type->packed_dimensions()
<< " " << name_ << unpacked_dimensions
<< " in scope " << scope_path(scope) << endl;
}
nettype_base_t*base_type = elaborate_type(des, scope, parray_type->base_type);
#if 0
cerr << get_fileline() << ": sorry: Packed array of "
<< typeid(*parray_type->base_type).name()
<< " not supported." << endl;
des->errors += 1;
#endif
sig = new NetNet(scope, name_, wtype, use_type->packed_dimensions(), unpacked_dimensions, base_type);
} else {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype;

View File

@ -163,6 +163,26 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
return 0;
}
/*
* This method locates a scope in the design, given its rooted
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope(const hname_t&path) const
{
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); ++ scope ) {
NetScope*cur = *scope;
if (path.peek_name() == cur->basename())
return cur;
}
return 0;
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@ -206,6 +226,43 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
return find_scope(path);
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
* I do not find the scope within the passed scope, start looking in
* parent scopes until I find it, or I run out of parent scopes.
*/
NetScope* Design::find_scope(NetScope*scope, const hname_t&path,
NetScope::TYPE type) const
{
assert(scope);
for ( ; scope ; scope = scope->parent()) {
NetScope*cur = scope;
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE)
&& cur->module_name()==path.peek_name()) {
/* Up references may match module name */
} else {
cur = cur->child( path );
}
if (cur) return cur;
}
// Last chance. Look for the name starting at the root.
list<hname_t>path_list;
path_list.push_back(path);
return find_scope(path_list);
}
/*
* This method runs through the scope, noticing the defparam
* statements that were collected during the elaborate_scope pass and

View File

@ -334,7 +334,7 @@ NetESFunc::NetESFunc(const char*n, netenum_t*enum_type, unsigned np)
: name_(0), type_(enum_type->base_type()), enum_type_(enum_type), parms_(np)
{
name_ = lex_strings.add(n);
expr_width(enum_type->base_width());
expr_width(enum_type->packed_width());
}
NetESFunc::~NetESFunc()

View File

@ -32,6 +32,14 @@ netenum_t::~netenum_t()
{
}
long netenum_t::packed_width() const
{
if (msb_ >= lsb_)
return msb_ - lsb_ + 1;
else
return lsb_ - msb_ + 1;
}
bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val)
{
std::pair<std::map<perm_string,verinum>::iterator, bool> res;

View File

@ -37,7 +37,7 @@ class netenum_t : public LineInfo, public nettype_base_t {
~netenum_t();
ivl_variable_type_t base_type() const;
unsigned base_width() const;
long packed_width() const;
bool has_sign() const;
// The size() is the number of enumeration literals.
@ -73,14 +73,6 @@ class netenum_t : public LineInfo, public nettype_base_t {
inline ivl_variable_type_t netenum_t::base_type() const
{ return base_type_; }
inline unsigned netenum_t::base_width() const
{
if (msb_ >= lsb_)
return msb_ - lsb_ + 1;
else
return lsb_ - msb_ + 1;
}
inline size_t netenum_t::size() const { return names_.size(); }
inline bool netenum_t::has_sign() const { return signed_flag_; }

View File

@ -476,6 +476,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
// Synthesize a single range to describe this canonical vector.
packed_dims_.push_back(netrange_t(npins-1, 0));
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
@ -521,6 +522,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
eref_count_(0), lref_count_(0)
{
packed_dims_ = packed;
calculate_slice_widths_from_packed_dims_();
assert(s);
Link::DIR dir = Link::PASSIVE;
@ -564,6 +566,32 @@ static unsigned calculate_count(const list<netrange_t>&unpacked)
return sum;
}
template <class T> static unsigned calculate_count(T*type)
{
long wid = type->packed_width();
if (wid >= 0)
return wid;
else
return 1;
}
void NetNet::calculate_slice_widths_from_packed_dims_(void)
{
if (packed_dims_.empty()) {
slice_wids_.clear();
return;
}
slice_wids_.resize(packed_dims_.size());
slice_wids_[0] = netrange_width(packed_dims_);
list<netrange_t>::const_iterator cur = packed_dims_.begin();
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
}
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
const list<netrange_t>&packed,
const list<netrange_t>&unpacked,
@ -576,6 +604,9 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
eref_count_(0), lref_count_(0)
{
packed_dims_ = packed;
if (net_type)
packed_dims_.push_back(netrange_t(calculate_count(net_type)-1, 0));
calculate_slice_widths_from_packed_dims_();
size_t idx = 0;
for (list<netrange_t>::const_iterator cur = unpacked.begin()
; cur != unpacked.end() ; ++cur, idx += 1) {
@ -611,15 +642,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
s->add_signal(this);
}
static unsigned calculate_count(netstruct_t*type)
{
long wid = type->packed_width();
if (wid >= 0)
return wid;
else
return 1;
}
/*
* When we create a netnet for a packed struct, create a single
* vector with the msb_/lsb_ chosen to name enough bits for the entire
@ -634,6 +656,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
eref_count_(0), lref_count_(0)
{
packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
switch (t) {
@ -820,6 +843,25 @@ netdarray_t* NetNet::darray_type(void) const
return dynamic_cast<netdarray_t*> (net_type_);
}
/*
* "depth" is the number of index expressions that the user is using
* to index this identifer. So consider if Net was declared like so:
*
* reg [5:0][3:0] foo;
*
* In this case, slice_width(2) == 1 (slice_width(N) where N is the
* number of dimensions will always be 1.) and represents
* $bits(foo[a][b]). Then, slice_width(1)==4 ($bits(foo[a]) and slice_width(0)==24.
*/
unsigned long NetNet::slice_width(size_t depth) const
{
if (depth > slice_wids_.size())
return 0;
if (depth == slice_wids_.size())
return 1;
return slice_wids_[depth];
}
ivl_discipline_t NetNet::get_discipline() const
{
return discipline_;

View File

@ -77,6 +77,7 @@ class NetEvWait;
class PExpr;
class PFunction;
class netdarray_t;
class netparray_t;
class netenum_t;
class netstruct_t;
@ -614,6 +615,7 @@ class NetNet : public NetObj, public PortType {
// This form builds a NetNet from its record/enum definition.
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type);
//explicit NetNet(NetScope*s, perm_string n, Type t, netparray_t*type);
virtual ~NetNet();
@ -662,7 +664,7 @@ class NetNet : public NetObj, public PortType {
/* The vector_width returns the bit width of the packed array,
vector or scaler that is this NetNet object. */
unsigned long vector_width() const { return netrange_width(packed_dims_); }
inline unsigned long vector_width() const { return slice_width(0); }
/* Given a prefix of indices, figure out how wide the
resulting slice would be. This is a generalization of the
@ -694,6 +696,10 @@ class NetNet : public NetObj, public PortType {
indices. (Currently only one array index is supported.) */
inline unsigned unpacked_dimensions() const { return unpacked_dims_.size(); }
/* This methor returns 0 for scalars, but vectors and other
PACKED arrays have packed dimensions. */
inline size_t packed_dimensions() const { return packed_dims_.size(); }
// This is the number of array elements.
unsigned unpacked_count() const;
@ -738,6 +744,14 @@ class NetNet : public NetObj, public PortType {
std::list<netrange_t> packed_dims_;
std::vector<netrange_t> unpacked_dims_;
// These are the widths of the various slice depths. There is
// one entry in this vector for each packed dimension. The
// value at N is the slice width if N indices are provided.
//
// For example: slice_wids_[0] is vector_width().
void calculate_slice_widths_from_packed_dims_(void);
std::vector<unsigned long> slice_wids_;
unsigned eref_count_;
unsigned lref_count_;
@ -4161,6 +4175,12 @@ class Design {
path is taken as an absolute scope name. Otherwise, the
scope is located starting at the passed scope and working
up if needed. */
NetScope* find_scope(const hname_t&path) const;
NetScope* find_scope(NetScope*, const hname_t&name,
NetScope::TYPE type = NetScope::MODULE) const;
// Note: Try to remove these versions of find_scope. Avoid
// using these in new code, use the above forms (or
// symbol_search) instead.
NetScope* find_scope(const std::list<hname_t>&path) const;
NetScope* find_scope(NetScope*, const std::list<hname_t>&path,
NetScope::TYPE type = NetScope::MODULE) const;

View File

@ -180,6 +180,21 @@ static NetExpr* make_add_expr(NetExpr*expr, long val)
return res;
}
static NetExpr* make_add_expr(const LineInfo*loc, NetExpr*expr1, NetExpr*expr2)
{
bool use_signed = expr1->has_sign() && expr2->has_sign();
unsigned use_wid = expr1->expr_width();
if (expr2->expr_width() > use_wid)
use_wid = expr2->expr_width();
expr1 = pad_to_width(expr1, use_wid, *loc);
expr2 = pad_to_width(expr2, use_wid, *loc);
NetEBAdd*tmp = new NetEBAdd('+', expr1, expr2, use_wid, use_signed);
return tmp;
}
/*
* Subtract an existing expression from a signed constant.
*/
@ -254,6 +269,8 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb,
if (is_up) offset -= wid - 1;
/* Calculate the space needed for the offset. */
unsigned min_wid = num_bits(offset);
if (num_bits(soff) > min_wid)
min_wid = num_bits(soff);
/* We need enough space for the larger of the offset or the
* base expression. */
if (min_wid < base->expr_width()) min_wid = base->expr_width();
@ -287,6 +304,8 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb,
if ((soff-offset) == 0) return base;
/* Calculate the space needed for the offset. */
unsigned min_wid = num_bits(-offset);
if (num_bits(soff) > min_wid)
min_wid = num_bits(soff);
/* We need enough space for the larger of the offset or the
* base expression. */
if (min_wid < base->expr_width()) min_wid = base->expr_width();
@ -835,7 +854,8 @@ bool eval_as_double(double&value, NetExpr*expr)
* expression if it is present.
*/
hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp)
const name_component_t&comp,
bool&error_flag)
{
// No index expression, so the path component is an undecorated
// name, for example "foo".
@ -873,6 +893,7 @@ hname_t eval_path_component(Design*des, NetScope*scope,
return res;
}
#if 1
// Darn, the expression doesn't evaluate to a constant. That's
// an error to be reported. And make up a fake index value to
// return to the caller.
@ -880,6 +901,8 @@ hname_t eval_path_component(Design*des, NetScope*scope,
<< "Scope index expression is not constant: "
<< *index.msb << endl;
des->errors += 1;
#endif
error_flag = true;
delete tmp;
return hname_t (comp.name, 0);
@ -888,15 +911,20 @@ hname_t eval_path_component(Design*des, NetScope*scope,
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
bool path_error_flag = false;
list<hname_t> res;
typedef pform_name_t::const_iterator pform_path_it;
for (pform_path_it cur = path.begin() ; cur != path.end(); ++ cur ) {
const name_component_t&comp = *cur;
res.push_back( eval_path_component(des,scope,comp) );
res.push_back( eval_path_component(des,scope,comp,path_error_flag) );
}
#if 0
if (path_error_flag) {
cerr << "XXXXX: Errors evaluating path " << path << endl;
}
#endif
return res;
}
@ -1127,3 +1155,85 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
return true;
}
/*
* Evaluate the indices. The chain of indices are applied to the
* packed indices of a NetNet to generate a canonical expression to
* replace the exprs.
*/
NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
const LineInfo*loc, NetNet*net,
const list<index_component_t>&indices)
{
// First elaborate all the expressions as far as possible.
list<NetExpr*> exprs;
list<long> exprs_const;
bool flag = indices_to_expressions(des, scope, loc, indices,
net->packed_dimensions(),
false, exprs, exprs_const);
ivl_assert(*loc, exprs.size() == net->packed_dimensions());
// Special Case: there is only 1 packed dimension, so the
// single expression should already be naturally canonical.
if (net->slice_width(1) == 1) {
return *exprs.begin();
}
const std::list<netrange_t>&pdims = net->packed_dims();
std::list<netrange_t>::const_iterator pcur = pdims.begin();
list<NetExpr*>::iterator ecur = exprs.begin();
NetExpr* base = 0;
for (size_t idx = 0 ; idx < net->packed_dimensions() ; idx += 1, ++pcur, ++ecur) {
unsigned cur_slice_width = net->slice_width(idx+1);
// This normalizes the expression of this index based on
// the msb/lsb values.
NetExpr*tmp = normalize_variable_base(*ecur, pcur->get_msb(),
pcur->get_lsb(),
cur_slice_width, true);
// If this slice has width, then scale it.
if (net->slice_width(idx+1) != 1) {
unsigned min_wid = tmp->expr_width();
if (num_bits(cur_slice_width) >= min_wid) {
min_wid = num_bits(cur_slice_width)+1;
tmp = pad_to_width(tmp, min_wid, *loc);
}
tmp = make_mult_expr(tmp, cur_slice_width);
}
// Now add it to the position we've accumulated so far.
if (base) {
base = make_add_expr(loc, base, tmp);
} else {
base = tmp;
}
}
return base;
}
/*
* Given a list of indices, treat them as packed indices and convert
* them to an expression that normalizes the list to a single index
* expression over a canonical equivilent 1-dimensional array.
*/
NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net,
const list<index_component_t>&indices)
{
list<long>prefix_indices;
bool rc = evaluate_index_prefix(des, scope, prefix_indices, indices);
assert(rc);
const index_component_t&back_index = indices.back();
assert(back_index.sel == index_component_t::SEL_BIT);
assert(back_index.msb && !back_index.lsb);
NetExpr*base = elab_and_eval(des, scope, back_index.msb, -1, true);
NetExpr*res = normalize_variable_bit_base(prefix_indices, base, net);
eval_expr(res, -1);
return res;
}

View File

@ -256,18 +256,14 @@ void eval_expr(NetExpr*&expr, int context_width =-1);
bool eval_as_long(long&value, NetExpr*expr);
bool eval_as_double(double&value, NetExpr*expr);
/*
* Evaluate the component of a scope path to get an hname_t value. Do
* the evaluation in the context of the given scope.
*/
extern hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp);
/*
* Evaluate an entire scope path in the context of the given scope.
*/
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
extern hname_t eval_path_component(Design*des, NetScope*scope,
const name_component_t&comp,
bool&error_flag);
/*
* Return true if the data type is a type that is normally available
@ -310,4 +306,12 @@ extern void collapse_partselect_pv_to_concat(Design*des, NetNet*sig);
extern bool evaluate_index_prefix(Design*des, NetScope*scope,
list<long>&prefix_indices,
const list<index_component_t>&indices);
extern NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net,
const std::list<index_component_t>&indices);
extern NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
const LineInfo*loc, NetNet*net,
const list<index_component_t>&indices);
#endif

View File

@ -17,31 +17,36 @@
*
* 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.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include "nettypes.h"
# include <vector>
class netarray_t : public LineInfo {
/*
* Packed arrays.
*/
class netparray_t : public nettype_base_t, public LineInfo {
public:
explicit netarray_t(const std::list<netrange_t>&packed);
~netarray_t();
explicit netparray_t(const std::list<netrange_t>&packed);
~netparray_t();
unsigned packed_width() const;
inline const std::list<netrange_t>& packed_dimensions() const
{ return packed_dims_; }
private:
std::list<netrange_t> packed_dims_;
};
inline netarray_t::netarray_t(const std::list<netrange_t>&packed)
inline netparray_t::netparray_t(const std::list<netrange_t>&packed)
: packed_dims_(packed)
{
}
netarray_t::~netarray_t()
inline netparray_t::~netparray_t()
{
}

View File

@ -26,6 +26,11 @@ nettype_base_t::~nettype_base_t()
{
}
long nettype_base_t::packed_width(void) const
{
return 0;
}
unsigned long netrange_width(const list<netrange_t>&packed)
{
unsigned wid = 1;

View File

@ -30,6 +30,7 @@
class nettype_base_t {
public:
virtual ~nettype_base_t() =0;
virtual long packed_width(void) const;
};
class netrange_t {

111
parse.y
View File

@ -2,6 +2,7 @@
%{
/*
* Copyright (c) 1998-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -566,7 +567,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <nettype> net_type var_type net_type_opt
%type <gatetype> gatetype switchtype
%type <porttype> port_direction port_direction_opt
%type <vartype> primitive_type primitive_type_opt bit_logic
%type <vartype> bit_logic
%type <vartype> integer_vector_type
%type <parmvalue> parameter_value_opt
@ -894,7 +895,7 @@ data_type /* IEEE1800-2005: A.2.2.1 */
$$ = tmp;
}
| TYPE_IDENTIFIER range_opt
{ if ($2) $$ = new array_type_t($1, $2);
{ if ($2) $$ = new parray_type_t($1, $2);
else $$ = $1;
}
| K_string
@ -1842,11 +1843,11 @@ block_item_decl
recovering from an error. */
| data_type register_variable_list ';'
{ if ($1) pform_set_data_type(@1, $1, $2, attributes_in_context);
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
}
| K_reg data_type register_variable_list ';'
{ if ($2) pform_set_data_type(@2, $2, $3, attributes_in_context);
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
}
| K_event list_of_identifiers ';'
@ -3891,31 +3892,24 @@ module_item
/* Modules can contain further sub-module definitions. */
: module
/* This rule detects net declarations that possibly include a
primitive type, an optional vector range and signed flag. This
also includes an optional delay set. The values are then applied
to a list of names. If the primitive type is not specified, then
resort to the default type LOGIC. */
| attribute_list_opt net_type data_type_or_implicit delay3_opt net_variable_list ';'
| attribute_list_opt net_type
primitive_type_opt unsigned_signed_opt range_opt
delay3_opt
net_variable_list ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_makewire(@2, $5, $4, $7, $2, NetNet::NOT_A_PORT, dtype, $1);
if ($6 != 0) {
yyerror(@6, "sorry: net delays not supported.");
delete $6;
{ data_type_t*data_type = $3;
if (data_type == 0) {
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
FILE_NAME(data_type, @2);
}
pform_set_data_type(@2, data_type, $5, $2, $1);
if ($4 != 0) {
yyerror(@2, "sorry: net delays not supported.");
delete $4;
}
delete $1;
}
| attribute_list_opt K_wreal delay3 net_variable_list ';'
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
{ real_type_t*tmpt = new real_type_t(real_type_t::REAL);
pform_set_data_type(@2, tmpt, $4, NetNet::WIRE, $1);
if ($3 != 0) {
yyerror(@3, "sorry: net delays not supported.");
delete $3;
@ -3924,8 +3918,8 @@ module_item
}
| attribute_list_opt K_wreal net_variable_list ';'
{ pform_makewire(@2, 0, true, $3, NetNet::WIRE,
NetNet::NOT_A_PORT, IVL_VT_REAL, $1);
{ real_type_t*tmpt = new real_type_t(real_type_t::REAL);
pform_set_data_type(@2, tmpt, $3, NetNet::WIRE, $1);
delete $1;
}
@ -3933,15 +3927,13 @@ module_item
net_decl_assigns, which are <name> = <expr> assignment
declarations. */
| attribute_list_opt net_type
primitive_type_opt unsigned_signed_opt range_opt
delay3_opt net_decl_assigns ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_makewire(@2, $5, $4, $6,
str_strength, $7, $2, dtype);
| attribute_list_opt net_type data_type_or_implicit delay3_opt net_decl_assigns ';'
{ data_type_t*data_type = $3;
if (data_type == 0) {
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
FILE_NAME(data_type, @2);
}
pform_makewire(@2, $4, str_strength, $5, $2, data_type);
if ($1) {
yyerror(@2, "sorry: Attributes not supported "
"on net declaration assignments.");
@ -3949,42 +3941,26 @@ module_item
}
}
/* Allow struct nets. */
| attribute_list_opt net_type struct_data_type net_variable_list ';'
{ pform_makewire(@2, $3, NetNet::NOT_A_PORT, $4, $1);
delete $1;
}
| attribute_list_opt net_type struct_data_type error ';'
{ yyerror(@5, "error: Errors in net variable list.");
}
| attribute_list_opt net_type TYPE_IDENTIFIER net_variable_list ';'
{ yyerror(@2, "sorry: Nets of named types not supported."); }
/* This form doesn't have the range, but does have strengths. This
gives strength to the assignment drivers. */
| attribute_list_opt net_type
primitive_type_opt unsigned_signed_opt
drive_strength net_decl_assigns ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
dtype = IVL_VT_LOGIC;
pform_makewire(@2, 0, $4, 0, $5, $6, $2, dtype);
| attribute_list_opt net_type data_type_or_implicit drive_strength net_decl_assigns ';'
{ data_type_t*data_type = $3;
if (data_type == 0) {
data_type = new vector_type_t(IVL_VT_LOGIC, false, 0);
FILE_NAME(data_type, @2);
}
pform_makewire(@2, 0, $4, $5, $2, data_type);
if ($1) {
yyerror(@2, "sorry: Attributes not supported "
"on net declaration assignments.");
delete $1;
}
}
| attribute_list_opt K_wreal net_decl_assigns ';'
{ pform_makewire(@2, 0, true, 0, str_strength, $3,
NetNet::WIRE, IVL_VT_REAL);
{ real_type_t*data_type = new real_type_t(real_type_t::REAL);
pform_makewire(@2, 0, str_strength, $3, NetNet::WIRE, data_type);
if ($1) {
yyerror(@2, "sorry: Attributes not supported "
"on net declaration assignments.");
@ -4369,20 +4345,11 @@ net_decl_assigns
}
;
primitive_type
: K_logic { $$ = IVL_VT_LOGIC; }
| K_bool { $$ = IVL_VT_BOOL; /* Icarus Verilog xtypes */}
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
| K_real { $$ = IVL_VT_REAL; }
;
bit_logic
: K_logic { $$ = IVL_VT_LOGIC; }
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
;
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
net_type
: K_wire { $$ = NetNet::WIRE; }
| K_tri { $$ = NetNet::TRI; }
@ -4890,10 +4857,10 @@ function_range_or_type_opt
so that bit ranges can be assigned. */
register_variable
: IDENTIFIER dimensions_opt
{ perm_string ident_name = lex_strings.make($1);
pform_makewire(@1, ident_name, NetNet::REG,
{ perm_string name = lex_strings.make($1);
pform_makewire(@1, name, NetNet::REG,
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
pform_set_reg_idx(ident_name, $2);
pform_set_reg_idx(name, $2);
$$ = $1;
}
| IDENTIFIER '=' expression

190
pform.cc
View File

@ -1563,6 +1563,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
* and the name that I receive only has the tail component.
*/
static void pform_set_net_range(perm_string name,
NetNet::Type net_type,
const list<pform_range_t>*range,
bool signed_flag,
ivl_variable_type_t dt,
@ -1574,6 +1575,19 @@ static void pform_set_net_range(perm_string name,
VLerror("error: name is not a valid net.");
return;
}
// If this is not implicit ("implicit" meaning we don't
// know what the type is yet) then set the type now.
if (net_type != NetNet::IMPLICIT && net_type != NetNet::NONE) {
bool rc = cur->set_wire_type(net_type);
if (rc == false) {
ostringstream msg;
msg << name << " " << net_type
<< " definition conflicts with " << cur->get_wire_type()
<< " definition at " << cur->get_fileline()
<< ".";
VLerror(msg.str().c_str());
}
}
if (range == 0) {
/* This is the special case that we really mean a
@ -1591,16 +1605,17 @@ static void pform_set_net_range(perm_string name,
pform_bind_attributes(cur->attributes, attr, true);
}
void pform_set_net_range(list<perm_string>*names,
static void pform_set_net_range(list<perm_string>*names,
list<pform_range_t>*range,
bool signed_flag,
ivl_variable_type_t dt,
NetNet::Type net_type,
std::list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_net_range(txt, range, signed_flag, dt, SR_NET, attr);
pform_set_net_range(txt, net_type, range, signed_flag, dt, SR_NET, attr);
}
delete names;
@ -1997,7 +2012,7 @@ void pform_module_define_port(const struct vlltype&li,
}
} else if ((struct_type = dynamic_cast<struct_type_t*>(vtype))) {
data_type = figure_struct_base_type(struct_type);
data_type = struct_type->figure_packed_base_type();
signed_flag = false;
range = 0;
@ -2017,7 +2032,7 @@ void pform_module_define_port(const struct vlltype&li,
cur->set_signed(signed_flag);
if (struct_type) {
cur->set_struct_type(struct_type);
cur->set_packed_type(struct_type);
} else if (range == 0) {
cur->set_range_scalar((type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH);
@ -2144,7 +2159,7 @@ void pform_makewire(const vlltype&li,
pform_makewire(li, txt, type, pt, dt, attr);
/* This has already been done for real variables. */
if (dt != IVL_VT_REAL) {
pform_set_net_range(txt, range, signed_flag, dt, rt, 0);
pform_set_net_range(txt, type, range, signed_flag, dt, rt, 0);
}
}
@ -2156,27 +2171,31 @@ void pform_makewire(const vlltype&li,
* This form makes nets with delays and continuous assignments.
*/
void pform_makewire(const vlltype&li,
list<pform_range_t>*range,
bool signed_flag,
list<PExpr*>*delay,
str_pair_t str,
net_decl_assign_t*decls,
NetNet::Type type,
ivl_variable_type_t dt)
data_type_t*data_type)
{
// The decls pointer is a circularly linked list.
net_decl_assign_t*first = decls->next;
decls->next = 0;
list<perm_string>*names = new list<perm_string>;
// Go through the circularly linked list non-destructively.
do {
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
names->push_back(first->name);
first = first->next;
} while (first != decls->next);
pform_set_data_type(li, data_type, names, type, 0);
// This time, go through the list, deleting cells as I'm done.
first = decls->next;
decls->next = 0;
while (first) {
net_decl_assign_t*next = first->next;
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, dt, 0);
/* This has already been done for real variables. */
if (dt != IVL_VT_REAL) {
pform_set_net_range(first->name, range, signed_flag, dt,
SR_NET, 0);
}
PWire*cur = pform_get_wire_in_scope(first->name);
if (cur != 0) {
PEIdent*lval = new PEIdent(first->name);
@ -2705,7 +2724,7 @@ void pform_set_port_type(const struct vlltype&li,
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_port_type(txt, pt, li.text, li.first_line);
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE,
pform_set_net_range(txt, NetNet::NONE, range, signed_flag, IVL_VT_NO_TYPE,
SR_PORT, 0);
}
@ -2764,9 +2783,9 @@ void pform_set_reg_time(list<perm_string>*names, list<named_pexpr_t>*attr)
delete names;
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name, list<named_pexpr_t>*attr)
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_BOOL);
PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_BOOL);
assert(cur);
cur->set_signed(signed_flag);
@ -2780,84 +2799,56 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_strin
pform_bind_attributes(cur->attributes, attr, true);
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names, list<named_pexpr_t>*attr)
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_integer_2atom(width, signed_flag, txt, attr);
pform_set_integer_2atom(width, signed_flag, txt, net_type, attr);
}
delete names;
}
/*
* This function detects the derived class for the given type and
* dispatches the type to the proper subtype function.
*/
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names, list<named_pexpr_t>*attr)
template <class T> static void pform_set2_data_type(const struct vlltype&li, T*data_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, attr);
return;
ivl_variable_type_t base_type = data_type->figure_packed_base_type();
if (base_type == IVL_VT_NO_TYPE) {
VLerror(li, "Compound type is not PACKED in this context.");
}
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
pform_set_struct_type(struct_type, names, attr);
return;
PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type);
net->set_packed_type(data_type);
pform_bind_attributes(net->attributes, attr, true);
}
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
pform_set_enum(li, enum_type, names, attr);
return;
template <class T> static void pform_set2_data_type(const struct vlltype&li, T*data_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
pform_set2_data_type(li, data_type, *cur, net_type, attr);
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
pform_set_net_range(names, vec_type->pdims.get(),
vec_type->signed_flag,
vec_type->base_type, attr);
return;
}
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
pform_set_net_range(names, 0, true, IVL_VT_REAL, attr);
return;
}
if (/*class_type_t*class_type =*/ dynamic_cast<class_type_t*> (data_type)) {
VLerror(li, "sorry: Class types not supported.");
return;
}
if (/*array_type_t*array_type = */ dynamic_cast<array_type_t*> (data_type)) {
VLerror(li, "sorry: General array types not supported.");
return;
}
if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
pform_set_string_type(string_type, names, attr);
return;
}
assert(0);
}
static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
perm_string name, std::list<named_pexpr_t>*attr)
perm_string name, NetNet::Type net_type,
std::list<named_pexpr_t>*attr)
{
(void) li; // The line information is not currently needed.
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, enum_type->base_type);
PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, enum_type->base_type);
assert(cur);
cur->set_signed(enum_type->signed_flag);
assert(enum_type->range.get() != 0);
assert(enum_type->range->size() == 1);
cur->set_range(*enum_type->range, SR_NET);
cur->set_enumeration(enum_type);
//XXXXcur->set_range(*enum_type->range, SR_NET);
cur->set_packed_type(enum_type);
pform_bind_attributes(cur->attributes, attr, true);
}
void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names, std::list<named_pexpr_t>*attr)
static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
list<perm_string>*names, NetNet::Type net_type,
std::list<named_pexpr_t>*attr)
{
// By definition, the base type can only be IVL_VT_LOGIC or
// IVL_VT_BOOL.
@ -2877,12 +2868,69 @@ void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_st
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
perm_string txt = *cur;
pform_set_enum(li, enum_type, txt, attr);
pform_set_enum(li, enum_type, txt, net_type, attr);
}
delete names;
}
/*
* This function detects the derived class for the given type and
* dispatches the type to the proper subtype function.
*/
void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
if (data_type == 0) {
VLerror(li, "internal error: data_type==0.");
assert(0);
}
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr);
return;
}
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
pform_set_struct_type(struct_type, names, net_type, attr);
return;
}
if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
pform_set_enum(li, enum_type, names, net_type, attr);
return;
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
pform_set_net_range(names, vec_type->pdims.get(),
vec_type->signed_flag,
vec_type->base_type, net_type, attr);
return;
}
if (/*real_type_t*real_type =*/ dynamic_cast<real_type_t*> (data_type)) {
pform_set_net_range(names, 0, true, IVL_VT_REAL, net_type, attr);
return;
}
if (/*class_type_t*class_type =*/ dynamic_cast<class_type_t*> (data_type)) {
VLerror(li, "sorry: Class types not supported.");
return;
}
if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
pform_set2_data_type(li, array_type, names, net_type, attr);
return;
}
if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
pform_set_string_type(string_type, names, net_type, attr);
return;
}
VLerror(li, "internal error: Unexpected data_type.");
assert(0);
}
svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
{
svector<PWire*>*out = new svector<PWire*>(names->size());

19
pform.h
View File

@ -265,13 +265,11 @@ extern void pform_makewire(const struct vlltype&li,
/* This form handles assignment declarations. */
extern void pform_makewire(const struct vlltype&li,
list<pform_range_t>*range,
bool signed_flag,
list<PExpr*>*delay,
str_pair_t str,
net_decl_assign_t*assign_list,
NetNet::Type type,
ivl_variable_type_t);
data_type_t*data_type);
/* This form handles nets declared as structures. (See pform_struct_type.cc) */
extern void pform_makewire(const struct vlltype&li,
@ -292,25 +290,16 @@ extern void pform_set_port_type(const struct vlltype&li,
bool signed_flag,
NetNet::PortType);
extern void pform_set_net_range(list<perm_string>*names,
list<pform_range_t>*,
bool signed_flag,
ivl_variable_type_t,
std::list<named_pexpr_t>*attr);
extern void pform_set_reg_idx(perm_string name,
std::list<pform_range_t>*indices);
extern void pform_set_reg_integer(list<perm_string>*names, list<named_pexpr_t>*attr);
extern void pform_set_reg_time(list<perm_string>*names, list<named_pexpr_t>*attr);
//XXXXextern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names);
extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr);
extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list<perm_string>*names, list<named_pexpr_t>*attr);
extern void pform_set_struct_type(struct_type_t*struct_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
extern void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, list<perm_string>*names, std::list<named_pexpr_t>*attr);
extern void pform_set_struct_type(struct_type_t*struct_type, std::list<perm_string>*names, std::list<named_pexpr_t>*attr);
extern void pform_set_string_type(string_type_t*string_type, std::list<perm_string>*names, std::list<named_pexpr_t>*attr);
extern void pform_set_string_type(string_type_t*string_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
/* pform_set_attrib and pform_set_type_attrib exist to support the
$attribute syntax, which can only set string values to

View File

@ -146,6 +146,13 @@ void data_type_t::pform_dump(ostream&out, unsigned indent) const
out << setw(indent) << "" << typeid(*this).name() << endl;
}
void parray_type_t::pform_dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << "Packed array " << "[...]"
<< " of:" << endl;
base_type->pform_dump(out, indent+4);
}
static void dump_attributes_map(ostream&out,
const map<perm_string,PExpr*>&attributes,
int ind)
@ -391,6 +398,10 @@ void PWire::dump(ostream&out, unsigned ind) const
}
out << ";" << endl;
if (set_data_type_) {
set_data_type_->pform_dump(out, 8);
}
dump_attributes_map(out, attributes, 8);
}

View File

@ -21,17 +21,17 @@
# include "parse_misc.h"
# include "ivl_assert.h"
static void pform_set_string_type(string_type_t*string_type, perm_string name, list<named_pexpr_t>*attr)
static void pform_set_string_type(string_type_t*string_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_STRING);
PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_STRING);
pform_bind_attributes(net->attributes, attr, true);
}
void pform_set_string_type(string_type_t*string_type, list<perm_string>*names, list<named_pexpr_t>*attr)
void pform_set_string_type(string_type_t*string_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
pform_set_string_type(string_type, *cur, attr);
pform_set_string_type(string_type, *cur, net_type, attr);
}
}

View File

@ -21,12 +21,15 @@
# include "parse_misc.h"
# include "ivl_assert.h"
ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type)
ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const
{
if (! packed_flag)
return IVL_VT_NO_TYPE;
ivl_variable_type_t base_type = IVL_VT_BOOL;
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
; cur != struct_type->members->end() ; ++ cur) {
for (list<struct_member_t*>::iterator cur = members->begin()
; cur != members->end() ; ++ cur) {
struct_member_t*tmp = *cur;
@ -48,19 +51,19 @@ ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type)
* out the base type of the packed variable. Elaboration, later on,
* well figure out the rest.
*/
static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, list<named_pexpr_t>*attr)
static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
ivl_variable_type_t base_type = figure_struct_base_type(struct_type);
ivl_variable_type_t base_type = struct_type->figure_packed_base_type();
PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, base_type);
net->set_struct_type(struct_type);
PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type);
net->set_packed_type(struct_type);
pform_bind_attributes(net->attributes, attr, true);
}
static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, list<named_pexpr_t>*attr)
static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
if (struct_type->packed_flag) {
pform_set_packed_struct(struct_type, name, attr);
pform_set_packed_struct(struct_type, name, net_type, attr);
return;
}
@ -68,11 +71,11 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, l
ivl_assert(*struct_type, 0);
}
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names, list<named_pexpr_t>*attr)
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
pform_set_struct_type(struct_type, *cur, attr);
pform_set_struct_type(struct_type, *cur, net_type, attr);
}
}
@ -82,11 +85,11 @@ static void pform_makewire(const struct vlltype&li,
perm_string name,
list<named_pexpr_t>*)
{
ivl_variable_type_t base_type = figure_struct_base_type(struct_type);
ivl_variable_type_t base_type = struct_type->figure_packed_base_type();
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::WIRE, ptype, base_type);
FILE_NAME(cur, li);
cur->set_struct_type(struct_type);
cur->set_packed_type(struct_type);
}
void pform_makewire(const struct vlltype&li,

View File

@ -27,3 +27,18 @@ data_type_t::~data_type_t()
string_type_t::~string_type_t()
{
}
ivl_variable_type_t data_type_t::figure_packed_base_type(void) const
{
return IVL_VT_NO_TYPE;
}
ivl_variable_type_t parray_type_t::figure_packed_base_type(void) const
{
return base_type->figure_packed_base_type();
}
ivl_variable_type_t vector_type_t::figure_packed_base_type(void) const
{
return base_type;
}

View File

@ -69,9 +69,12 @@ struct decl_assignment_t {
* "data_type" rule in the parse rule. We make the type virtual so
* that dynamic types will work.
*/
struct data_type_t : public LineInfo {
class data_type_t : public LineInfo {
public:
virtual ~data_type_t() = 0;
// This method is used to figure out the base type of a packed
// compound object. Return IVL_VT_NO_TYPE if the type is not packed.
virtual ivl_variable_type_t figure_packed_base_type(void)const;
// This method is used by the pform dumper to diagnostic dump.
virtual void pform_dump(std::ostream&out, unsigned indent) const;
};
@ -97,10 +100,10 @@ struct struct_member_t : public LineInfo {
};
struct struct_type_t : public data_type_t {
virtual ivl_variable_type_t figure_packed_base_type(void)const;
bool packed_flag;
std::auto_ptr< list<struct_member_t*> > members;
};
extern ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type);
struct atom2_type_t : public data_type_t {
inline explicit atom2_type_t(int tc, bool flag)
@ -132,6 +135,8 @@ struct vector_type_t : public data_type_t {
inline explicit vector_type_t(ivl_variable_type_t bt, bool sf,
std::list<pform_range_t>*pd)
: base_type(bt), signed_flag(sf), reg_flag(false), implicit_flag(false), pdims(pd) { }
virtual ivl_variable_type_t figure_packed_base_type(void)const;
ivl_variable_type_t base_type;
bool signed_flag;
bool reg_flag; // True if "reg" was used
@ -141,11 +146,16 @@ struct vector_type_t : public data_type_t {
/*
* The array_type_t is a generalization of the vector_type_t in that
* the base type is another general data type.
* the base type is another general data type. Ultimately, the subtype
* must also be packed (as this is a packed array) but that may be
* worked out during elaboration.
*/
struct array_type_t : public data_type_t {
inline explicit array_type_t(data_type_t*btype, std::list<pform_range_t>*pd)
struct parray_type_t : public data_type_t {
inline explicit parray_type_t(data_type_t*btype, std::list<pform_range_t>*pd)
: base_type(btype), packed_dims(pd) { }
virtual ivl_variable_type_t figure_packed_base_type(void)const;
virtual void pform_dump(std::ostream&out, unsigned indent) const;
data_type_t*base_type;
std::auto_ptr< list<pform_range_t> > packed_dims;
};

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -19,12 +20,145 @@
# include "netlist.h"
# include "netmisc.h"
# include <cassert>
# include "ivl_assert.h"
/*
* Search for the hierarchical name.
*/
struct symbol_search_results {
inline symbol_search_results() {
scope = 0;
net = 0;
par_val = 0;
par_msb = 0;
par_lsb = 0;
eve = 0;
}
inline bool is_scope() const {
if (net) return false;
if (eve) return false;
if (par_val) return false;
if (scope) return true;
return false;
}
// Scope where symbol was located. This is set in all cases,
// assuming the search succeeded.
NetScope*scope;
// If this was a net, the signal itself.
NetNet*net;
// If this was a parameter, the value expression and the
// optional value dimensions.
const NetExpr*par_val;
const NetExpr*par_msb;
const NetExpr*par_lsb;
// If this is a named event, ...
NetEvent*eve;
};
bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
pform_name_t path, struct symbol_search_results*res,
NetScope*start_scope = 0)
{
assert(scope);
bool prefix_scope = false;
bool recurse_flag = false;
name_component_t path_tail = path.back();
path.pop_back();
// If this is a recursive call, then we need to know that so
// that we can enable the search for scopes. Set the
// recurse_flag to true if this is a recurse.
if (start_scope==0)
start_scope = scope;
else
recurse_flag = true;
// If there are components ahead of the tail, symbol_search
// recursively. Ideally, the result is a scope that we search
// for the tail key, but there are other special cases as well.
if (path.size() > 0) {
symbol_search_results recurse;
bool flag = symbol_search(li, des, scope, path, &recurse, start_scope);
if (! flag)
return false;
// The prefix is found to be a scope, so switch to that
// scoke, set the hier_path to turn of upwards searches,
// and continue our search for the tail.
if (recurse.is_scope()) {
scope = recurse.scope;
prefix_scope = true;
if (scope->is_auto() && li) {
cerr << li->get_fileline() << ": error: Hierarchical "
"reference to automatically allocated item "
"`" << path_tail.name << "' in path `" << path << "'" << endl;
des->errors += 1;
}
}
}
while (scope) {
if (NetNet*net = scope->find_signal(path_tail.name)) {
res->scope = scope;
res->net = net;
return true;
}
if (NetEvent*eve = scope->find_event(path_tail.name)) {
res->scope = scope;
res->eve = eve;
return true;
}
if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->par_msb, res->par_lsb)) {
res->scope = scope;
res->par_val = par;
return true;
}
if (recurse_flag) {
bool flag = false;
hname_t path_item = eval_path_component(des, start_scope, path_tail, flag);
if (flag) {
cerr << li->get_fileline() << ": XXXXX: Errors evaluating scope index" << endl;
} else if (NetScope*chld = des->find_scope(scope, path_item)) {
res->scope = chld;
return true;
}
}
// Don't scan up past a module boundary.
if (scope->type()==NetScope::MODULE && !scope->nested_module())
break;
// Don't scan up if we are searching within a prefixed scope.
if (prefix_scope)
break;
scope = scope->parent();
}
// Last chance: this is a single name, so it might be the name
// of a root scope. Ask the design if this is a root
// scope. This is only possible if there is no prefix.
if (prefix_scope==false) {
hname_t path_item (path_tail.name);
scope = des->find_scope(path_item);
if (scope) {
res->scope = scope;
return true;
}
}
return false;
}
/*
* Compatibility version. Remove me!
*/
NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
pform_name_t path,
NetNet*&net,
@ -32,58 +166,19 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
NetEvent*&eve,
const NetExpr*&ex1, const NetExpr*&ex2)
{
assert(scope);
bool hier_path = false;
/* Get the tail name of the object we are looking for. */
perm_string key = peek_tail_name(path);
path.pop_back();
/* Initialize output argument to cleared. */
net = 0;
par = 0;
eve = 0;
/* If the path has a scope part, then search for the specified
scope that we are supposed to search. */
if (! path.empty()) {
list<hname_t> path_list = eval_scope_path(des, scope, path);
assert(path_list.size() <= path.size());
// If eval_scope_path returns a short list, then some
// part of the scope was not found. Abort.
if (path_list.size() < path.size())
return 0;
scope = des->find_scope(scope, path_list);
if (scope && scope->is_auto() && li) {
cerr << li->get_fileline() << ": error: Hierarchical "
"reference to automatically allocated item "
"`" << key << "' in path `" << path << "'" << endl;
des->errors += 1;
}
hier_path = true;
}
while (scope) {
if ( (net = scope->find_signal(key)) )
return scope;
if ( (eve = scope->find_event(key)) )
return scope;
if ( (par = scope->get_parameter(des, key, ex1, ex2)) )
return scope;
/* We can't look up if we are at the enclosing module scope
* or if a hierarchical path was given. */
if ((scope->type()==NetScope::MODULE && !scope->nested_module()) || hier_path)
scope = 0;
else
scope = scope->parent();
}
symbol_search_results recurse;
bool flag = symbol_search(li, des, scope, path, &recurse);
if (! flag) {
return 0;
}
if (recurse.is_scope())
return recurse.scope;
net = recurse.net;
par = recurse.par_val;
ex1 = recurse.par_msb;
ex2 = recurse.par_lsb;
eve = recurse.eve;
return recurse.scope;
}

View File

@ -259,7 +259,7 @@ extern "C" ivl_variable_type_t ivl_enum_type(ivl_enumtype_t net)
extern "C" unsigned ivl_enum_width(ivl_enumtype_t net)
{
assert(net);
return net->base_width();
return net->packed_width();
}
extern "C" int ivl_enum_signed(ivl_enumtype_t net)

View File

@ -22,6 +22,7 @@
# include "parse_types.h"
// Need this for parse_errors?
# include "parse_api.h"
# include <cassert>
using namespace std;
@ -38,6 +39,54 @@ Architecture::~Architecture()
ScopeBase::cleanup();
}
void Architecture::push_genvar_type(perm_string gname, const VType*gtype)
{
genvar_type_t tmp;
tmp.name = gname;
tmp.vtype = gtype;
genvar_type_stack_.push_back(tmp);
}
void Architecture::pop_genvar_type(void)
{
assert(! genvar_type_stack_.empty());
genvar_type_stack_.pop_back();
}
const VType* Architecture::probe_genvar_type(perm_string gname)
{
for (std::list<genvar_type_t>::reverse_iterator cur = genvar_type_stack_.rbegin()
; cur != genvar_type_stack_.rend() ; ++cur) {
if (cur->name == gname)
return cur->vtype;
}
return 0;
}
void Architecture::push_genvar_emit(perm_string gname, const GenerateStatement*gen)
{
genvar_emit_t tmp;
tmp.name = gname;
tmp.gen = gen;
genvar_emit_stack_.push_back(tmp);
}
void Architecture::pop_genvar_emit(void)
{
assert(! genvar_emit_stack_.empty());
genvar_emit_stack_.pop_back();
}
const GenerateStatement* Architecture::probe_genvar_emit(perm_string gname)
{
for (std::list<genvar_emit_t>::reverse_iterator cur = genvar_emit_stack_.rbegin()
; cur != genvar_emit_stack_.rend() ; ++cur) {
if (cur->name == gname)
return cur->gen;
}
return 0;
}
Architecture::Statement::Statement()
{
}

View File

@ -29,6 +29,7 @@ class ComponentBase;
class Entity;
class Expression;
class ExpName;
class GenerateStatement;
class SequentialStmt;
class Signal;
class named_expr_t;
@ -71,6 +72,18 @@ class Architecture : public Scope, public LineInfo {
// Elaborate this architecture in the context of the given entity.
int elaborate(Entity*entity);
// These methods are used while in the scope of a generate
// block to mark that a name is a genvar at this point.
const VType* probe_genvar_type(perm_string);
void push_genvar_type(perm_string gname, const VType*gtype);
void pop_genvar_type(void);
// These methods are used during EMIT to check for names that
// are genvar names.
const GenerateStatement* probe_genvar_emit(perm_string);
void push_genvar_emit(perm_string gname, const GenerateStatement*);
void pop_genvar_emit(void);
// Emit this architecture to the given out file in the context
// of the specified entity. This method is used by the
// elaborate code to display generated code to the specified
@ -85,6 +98,18 @@ class Architecture : public Scope, public LineInfo {
// Concurrent statements local to this architecture
std::list<Architecture::Statement*> statements_;
struct genvar_type_t {
perm_string name;
const VType*vtype;
};
std::list<genvar_type_t> genvar_type_stack_;
struct genvar_emit_t {
perm_string name;
const GenerateStatement*gen;
};
std::list<genvar_emit_t> genvar_emit_stack_;
private: // Not implemented
};
@ -98,9 +123,9 @@ class GenerateStatement : public Architecture::Statement {
GenerateStatement(perm_string gname, std::list<Architecture::Statement*>&s);
~GenerateStatement();
protected:
inline perm_string get_name() { return name_; }
inline perm_string get_name() const { return name_; }
protected:
int elaborate_statements(Entity*ent, Architecture*arc);
int emit_statements(ostream&out, Entity*ent, Architecture*arc);
void dump_statements(ostream&out, int indent) const;

View File

@ -133,7 +133,9 @@ int GenerateStatement::elaborate_statements(Entity*ent, Architecture*arc)
int ForGenerate::elaborate(Entity*ent, Architecture*arc)
{
int errors = 0;
arc->push_genvar_type(genvar_, lsb_->probe_type(ent, arc));
errors += elaborate_statements(ent, arc);
arc->pop_genvar_type();
return errors;
}

View File

@ -183,16 +183,19 @@ int GenerateStatement::emit_statements(ostream&out, Entity*ent, Architecture*arc
int ForGenerate::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;
out << "genvar \\" << genvar_ << " ;" << endl;
out << "for (\\" << genvar_ << " = ";
out << "genvar \\" << get_name() << ":" << genvar_ << " ;" << endl;
out << "for (\\" << get_name() << ":" << genvar_ << " = ";
errors += lsb_->emit(out, ent, arc);
out << "; \\" << genvar_ << " <= ";
out << "; \\" << get_name() << ":" << genvar_ << " <= ";
errors += msb_->emit(out, ent, arc);
out << "; \\" << genvar_ << " = \\" << genvar_ << " + 1)"
out << "; \\" << get_name() << ":" << genvar_ << " = \\" << get_name() << ":" << genvar_ << " + 1)"
<< " begin : \\" << get_name() << endl;
arc->push_genvar_emit(genvar_, this);
errors += emit_statements(out, ent, arc);
arc->pop_genvar_emit();
out << "end" << endl;
return errors;

View File

@ -20,12 +20,16 @@
*/
# include "StringHeap.h"
# include <fstream>
const int GN_KEYWORD_2008 = 0x0001;
// TRUE if processing is supposed to dump progress to stderr.
extern bool verbose_flag;
extern bool debug_elaboration;
extern std::ofstream debug_log_file;
extern StringHeapLex lex_strings;
extern StringHeapLex filename_strings;

View File

@ -424,3 +424,15 @@ void prange_t::dump(ostream&out, int indent) const
out << setw(indent) << "" << (direction_ ? "downto" : "to");
right_->dump(out, indent);
}
ostream& Expression::dump_inline(ostream&out) const
{
out << typeid(*this).name();
return out;
}
ostream& ExpInteger::dump_inline(ostream&out) const
{
out << value_;
return out;
}

View File

@ -50,28 +50,6 @@ bool Expression::symbolic_compare(const Expression*) const
return false;
}
bool ExpName::symbolic_compare(const Expression*that) const
{
const ExpName*that_name = dynamic_cast<const ExpName*> (that);
if (that_name == 0)
return false;
if (name_ != that_name->name_)
return false;
if (that_name->index_ && !index_)
return false;
if (index_ && !that_name->index_)
return false;
if (index_) {
assert(that_name->index_);
return index_->symbolic_compare(that_name->index_);
}
return true;
}
ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam)
: base_(bas), name_(nam)
{
@ -366,6 +344,36 @@ const char* ExpName::name() const
return name_;
}
bool ExpName::symbolic_compare(const Expression*that) const
{
const ExpName*that_name = dynamic_cast<const ExpName*> (that);
if (that_name == 0)
return false;
if (name_ != that_name->name_)
return false;
if (that_name->index_ && !index_)
return false;
if (index_ && !that_name->index_)
return false;
if (index_) {
assert(that_name->index_);
return index_->symbolic_compare(that_name->index_);
}
return true;
}
void ExpName::set_range(Expression*msb, Expression*lsb)
{
assert(index_==0);
index_ = msb;
assert(lsb_==0);
lsb_ = lsb;
}
ExpRelation::ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2)
: ExpBinary(op1, op2), fun_(ty)
{

View File

@ -111,6 +111,7 @@ class Expression : public LineInfo {
// Debug dump of the expression.
virtual void dump(ostream&out, int indent = 0) const =0;
virtual ostream& dump_inline(ostream&out) const;
protected:
// This function is called by the derived class during
@ -131,6 +132,11 @@ static inline void FILE_NAME(Expression*tgt, const LineInfo*src)
tgt->set_line(*src);
}
static inline ostream& operator <<(ostream&out, const Expression&exp)
{
return exp.dump_inline(out);
}
class ExpUnary : public Expression {
public:
@ -473,6 +479,7 @@ class ExpInteger : public Expression {
bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
virtual ostream& dump_inline(ostream&out) const;
private:
int64_t value_;
@ -528,6 +535,8 @@ class ExpName : public Expression {
void dump(ostream&out, int indent = 0) const;
const char* name() const;
void set_range(Expression*msb, Expression*lsb);
private:
const VType* elaborate_adjust_type_with_range_(Entity*ent, Architecture*arc, const VType*type);

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -25,6 +26,7 @@
# include <iostream>
# include <typeinfo>
# include "parse_types.h"
# include "compiler.h"
# include "ivl_assert.h"
using namespace std;
@ -87,6 +89,17 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
{
int errors = 0;
if (debug_elaboration) {
debug_log_file << get_fileline() << ": ExpName::elaborate_lval_: "
<< "name_=" << name_
<< ", suffix->name()=" << suffix->name();
if (index_)
debug_log_file << ", index_=" << *index_;
if (lsb_)
debug_log_file << ", lsb_=" << *lsb_;
debug_log_file << endl;
}
if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to elaborate "
<< "ExpName prefix of " << name_
@ -128,8 +141,40 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
found_type = var->peek_type();
}
// Resolve type definition to get an actual type.
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*> (found_type)) {
found_type = tdef->peek_definition();
if (debug_elaboration) {
debug_log_file << get_fileline() << ": ExpName::elaborate_lval_: "
<< "Resolve typedef " << tdef->peek_name()
<< " to defined type=" << typeid(*found_type).name()
<< endl;
}
}
ivl_assert(*this, found_type);
// If the prefix type is an array, then we may actually have a
// case of an array of structs. For example:
// foo(n).bar
// where foo is an array, (n) is an array index and foo(n) is
// something that takes a suffix. For the purpose of our
// expression type calculations, we need the element type.
if (const VTypeArray*array = dynamic_cast<const VTypeArray*> (found_type)) {
found_type = array->element_type();
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*> (found_type)) {
found_type = tdef->peek_definition();
}
if (debug_elaboration) {
debug_log_file << get_fileline() << ": ExpName::elaborate_lval_: "
<< "Extract array element type=" << typeid(*found_type).name()
<< endl;
}
}
const VType*suffix_type = 0;
if (const VTypeRecord*record = dynamic_cast<const VTypeRecord*> (found_type)) {
@ -140,6 +185,7 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
ivl_assert(*this, element_type);
suffix_type = element_type;
}
if (suffix_type == 0) {
@ -654,6 +700,10 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
return 0;
}
while (const VTypeDef*def = dynamic_cast<const VTypeDef*> (prefix_type)) {
prefix_type = def->peek_definition();
}
// If the prefix type is a record, then the current name is
// the name of a member.
if (const VTypeRecord*pref_record = dynamic_cast<const VTypeRecord*> (prefix_type)) {
@ -699,6 +749,10 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
if (arc->find_constant(name_, ctype, cval))
return ctype;
if (const VType*gtype = arc->probe_genvar_type(name_)) {
return gtype;
}
cerr << get_fileline() << ": error: Signal/variable " << name_
<< " not found in this context." << endl;
return 0;

View File

@ -610,7 +610,12 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
}
out << "\\" << name_ << " ";
ivl_assert(*this, index_ == 0);
if (index_) {
out << "[";
errors += index_->emit(out, ent, arc);
out << "]";
ivl_assert(*this, lsb_ == 0);
}
out << ".";
return errors;
}
@ -623,7 +628,12 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
errors += prefix_->emit_as_prefix_(out, ent, arc);
}
const GenerateStatement*gs = 0;
if (arc && (gs = arc->probe_genvar_emit(name_)))
out << "\\" << gs->get_name() << ":" << name_ << " ";
else
out << "\\" << name_ << " ";
if (index_) {
out << "[";
errors += index_->emit(out, ent, arc);

View File

@ -1,6 +1,7 @@
const char COPYRIGHT[] =
"Copyright (c) 2011 Stephen Williams (steve@icarus.com)";
"Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)\n"
"Copyright CERN 2012 / 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
@ -36,6 +37,10 @@ const char COPYRIGHT[] =
* Enable debugging of library support by dumping library
* information to the file named <path>.
*
* elaboration=<path>
* Enable debugging of elaboratin by dumping elaboration
* process information to the file named <path>.
*
* entities=<path>
* Enable debugging of elaborated entities by writing the
* elaboration results to the file named <path>.
@ -94,7 +99,10 @@ bool verbose_flag = false;
// Where to dump design entities
const char*dump_design_entities_path = 0;
const char*dump_libraries_path = 0;
const char*debug_log_path = 0;
bool debug_elaboration = false;
ofstream debug_log_file;
extern void dump_libraries(ostream&file);
extern void parser_cleanup();
@ -109,6 +117,10 @@ static void process_debug_token(const char*word)
dump_design_entities_path = strdup(word+9);
} else if (strncmp(word, "libraries=", 10) == 0) {
dump_libraries_path = strdup(word+10);
} else if (strncmp(word, "log=", 4) == 0) {
debug_log_path = strdup(word+4);
} else if (strcmp(word, "elaboration") == 0) {
debug_elaboration = true;
}
}
@ -148,6 +160,10 @@ int main(int argc, char*argv[])
break;
}
if (debug_log_path) {
debug_log_file.open(debug_log_path);
}
if ( (rc = mkdir(work_path, 0777)) < 0 ) {
if (errno != EEXIST) {
fprintf(stderr, "Icarus Verilog VHDL unable to create work directory %s, errno=%d\n", work_path, errno);

View File

@ -7,6 +7,7 @@
%{
/*
* Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / 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
@ -167,37 +168,6 @@ static Expression*aggregate_or_primary(const YYLTYPE&loc, std::list<ExpAggregate
return el1->extract_expression();
}
static ExpName*make_name_from_prefix(const YYLTYPE&loc, const vector<perm_string>*names)
{
ExpName*cur = new ExpName(names->at(0));
FILE_NAME(cur, loc);
for (size_t idx = 1 ; idx < names->size() ; idx += 1) {
ExpName*tmp = new ExpName(cur, names->at(idx));
FILE_NAME(tmp, loc);
cur = tmp;
}
return cur;
}
static ExpName*make_name_from_prefix(const YYLTYPE&loc, const vector<perm_string>*names, Expression*msb, Expression*lsb)
{
ExpName*cur = new ExpName(names->at(0));
FILE_NAME(cur, loc);
for (size_t idx = 1 ; idx < (names->size()-1) ; idx += 1) {
ExpName*tmp = new ExpName(cur, names->at(idx));
FILE_NAME(tmp, loc);
cur = tmp;
}
ExpName*result = new ExpName(cur, names->back(), msb, lsb);
FILE_NAME(result, loc);
return result;
}
static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
const VType*type)
{
@ -220,8 +190,6 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
char*text;
std::list<perm_string>* name_list;
std::vector<perm_string>* compound_name;
std::list<std::vector<perm_string>* >* compound_name_list;
bool flag;
int64_t uni_integer;
@ -331,7 +299,7 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
%type <expr> expression factor primary relation
%type <expr> expression_logical expression_logical_and expression_logical_or
%type <expr> expression_logical_xnor expression_logical_xor
%type <expr> name
%type <expr> name prefix selected_name
%type <expr> shift_expression signal_declaration_assign_opt
%type <expr> simple_expression term waveform_element
%type <expr> interface_element_expression
@ -339,6 +307,7 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
%type <expr_list> waveform waveform_elements
%type <expr_list> name_list expression_list
%type <expr_list> process_sensitivity_list process_sensitivity_list_opt
%type <expr_list> selected_names use_clause
%type <named_expr> association_element
%type <named_expr_list> association_list port_map_aspect port_map_aspect_opt
@ -353,8 +322,6 @@ static list<VTypeRecord::element_t*>* record_elements(list<perm_string>*names,
%type <text> identifier_opt identifier_colon_opt logical_name suffix
%type <name_list> logical_name_list identifier_list
%type <name_list> enumeration_literal_list enumeration_literal
%type <compound_name> prefix selected_name
%type <compound_name_list> selected_names use_clause
%type <sequ_list> sequence_of_statements if_statement_else
%type <sequ> sequential_statement if_statement signal_assignment_statement
@ -1497,8 +1464,8 @@ mode
mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ;
name
: IDENTIFIER
name /* IEEE 1076-2008 P8.1 */
: IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */
{ ExpName*tmp = new ExpName(lex_strings.make($1));
FILE_NAME(tmp, @1);
delete[]$1;
@ -1506,10 +1473,7 @@ name
}
| selected_name
{ ExpName*tmp = make_name_from_prefix(@1, $1);
delete $1;
$$ = tmp;
}
{ $$ = $1; }
/* Note that this rule can match array element selects and various
function calls. The only way we can tell the difference is from
@ -1534,8 +1498,8 @@ name
$$ = tmp;
}
| selected_name '(' range ')'
{ ExpName*tmp = make_name_from_prefix(@1, $1, $3->msb(), $3->lsb());
delete $1;
{ ExpName*tmp = dynamic_cast<ExpName*> ($1);
tmp->set_range($3->msb(), $3->lsb());
$$ = tmp;
}
;
@ -1667,20 +1631,9 @@ port_map_aspect_opt
| { $$ = 0; }
;
prefix
: IDENTIFIER
{ std::vector<perm_string>* tmp = new std::vector<perm_string>();
tmp->push_back(lex_strings.make($1));
delete[] $1;
$$ = tmp;
}
| STRING_LITERAL
{ std::vector<perm_string>* tmp = new std::vector<perm_string>();
tmp->push_back(lex_strings.make($1));
delete[] $1;
$$ = tmp;
}
| selected_name
prefix /* IEEE 1076-2008 P8.1 */
: name
{ $$ = $1; }
;
@ -1926,34 +1879,42 @@ secondary_unit
| package_body
;
selected_name
selected_name /* IEEE 1076-2008 P8.3 */
: prefix '.' suffix
{ std::vector<perm_string>* tmp = $1;
tmp->push_back(lex_strings.make($3));
{ Expression*pfx = $1;
ExpName*pfx1 = dynamic_cast<ExpName*>(pfx);
assert(pfx1);
perm_string tmp = lex_strings.make($3);
$$ = new ExpName(pfx1, tmp);
FILE_NAME($$, @3);
delete[]$3;
}
| error '.' suffix
{ errormsg(@1, "Syntax error in prefix in front of \"%s\".\n", $3);
yyerrok;
$$ = new ExpName(lex_strings.make($3));
FILE_NAME($$, @3);
delete[]$3;
$$ = tmp;
}
;
selected_names
: selected_names ',' selected_name
{
std::list<std::vector<perm_string>* >* tmp = $1;
{ std::list<Expression*>* tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
| selected_name
{
std::list<std::vector<perm_string>* >* tmp = new std::list<std::vector<perm_string>* >();
{ std::list<Expression*>* tmp = new std::list<Expression*>();
tmp->push_back($1);
$$ = tmp;
}
;
/* The *_use variant of selected_name is used by the "use"
/* The *_lib variant of selected_name is used by the "use"
clause. It is syntactically identical to other selected_name
rules, but is a convenient place to attach use_clause actions. */
selected_name_use
selected_name_lib
: IDENTIFIER '.' K_all
{ library_use(@1, active_scope, 0, $1, 0);
delete[]$1;
@ -1971,9 +1932,9 @@ selected_name_use
}
;
selected_names_use
: selected_names_use ',' selected_name_use
| selected_name_use
selected_names_lib
: selected_names_lib ',' selected_name_lib
| selected_name_lib
;
@ -2102,16 +2063,11 @@ subtype_indication
suffix
: IDENTIFIER
{
$$ = $1;
}
{ $$ = $1; }
| CHARACTER_LITERAL
{
$$ = $1;
}
{ $$ = $1; }
| K_all
{
//do not have now better idea than using char constant
{ //do not have now better idea than using char constant
$$ = strcpy(new char[strlen("all"+1)], "all");
}
;
@ -2191,30 +2147,28 @@ type_definition
use_clause
: K_use selected_names ';'
{
$$ = $2;
}
{ $$ = $2; }
| K_use error ';'
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
;
use_clause_lib
: K_use selected_names_use ';'
: K_use selected_names_lib ';'
| K_use error ';'
{ errormsg(@1, "Syntax error in use clause.\n"); yyerrok; }
;
use_clauses
: use_clauses use_clause
| use_clause
use_clauses_lib
: use_clauses_lib use_clause_lib
| use_clause_lib
;
use_clauses_opt
: use_clauses
: use_clauses_lib
|
;
variable_assignment_statement
variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */
: name VASSIGN expression ';'
{ VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3);
FILE_NAME(tmp, @1);

View File

@ -246,6 +246,8 @@ class VTypeDef : public VType {
explicit VTypeDef(perm_string name, const VType*is);
~VTypeDef();
inline perm_string peek_name() const { return name_; }
// If the type is not given a definition in the constructor,
// then this must be used to set the definition later.
void set_definition(const VType*is);