Merge branch 'master' into vec4-stack

This commit is contained in:
Stephen Williams 2014-01-30 15:59:51 -08:00
commit fdc9e8590d
36 changed files with 721 additions and 196 deletions

View File

@ -540,6 +540,15 @@ bool PETernary::has_aa_term(Design*des, NetScope*scope) const
|| fal_->has_aa_term(des, scope);
}
PETypename::PETypename(data_type_t*dt)
: data_type_(dt)
{
}
PETypename::~PETypename()
{
}
PEUnary::PEUnary(char op, PExpr*ex)
: op_(op), expr_(ex)
{

17
PExpr.h
View File

@ -660,6 +660,23 @@ class PEString : public PExpr {
char*text_;
};
class PETypename : public PExpr {
public:
explicit PETypename(data_type_t*data_type);
~PETypename();
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
inline data_type_t* get_type() const { return data_type_; }
private:
data_type_t*data_type_;
};
class PEUnary : public PExpr {
public:

View File

@ -65,7 +65,7 @@ void PFunction::push_statement_front(Statement*stmt)
blk->push_statement_front(stmt);
}
void PFunction::set_return(const data_type_t*t)
void PFunction::set_return(data_type_t*t)
{
return_type_ = t;
}

View File

@ -114,7 +114,7 @@ class PFunction : public PTaskFunc {
~PFunction();
void set_statement(Statement *s);
void set_return(const data_type_t*t);
void set_return(data_type_t*t);
inline Statement* get_statement() { return statement_; }
@ -141,7 +141,7 @@ class PFunction : public PTaskFunc {
void dump(ostream&, unsigned) const;
private:
const data_type_t* return_type_;
data_type_t* return_type_;
Statement *statement_;
bool is_auto_;
};

View File

@ -1313,9 +1313,9 @@ void NetScope::dump(ostream&o) const
o << " enum sets {" << endl;
/* Dump the enumerations and enum names in this scope. */
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++ cur) {
o << " " << *cur << endl;
o << " " << cur->second << endl;
}
o << " }" << endl;

View File

@ -188,7 +188,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
* supported, can assign to packed arrays and structs, unpacked arrays
* and dynamic arrays.
*/
unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode)
unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&)
{
expr_type_ = IVL_VT_DARRAY;
expr_width_ = 1;
@ -1078,10 +1078,14 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
if (expr == 0)
return 0;
// The argument type/width is self-determined and doesn't
// affect the result type/width.
width_mode_t arg_mode = SIZED;
expr->test_width(des, scope, arg_mode);
if (! dynamic_cast<PETypename*>(expr)) {
// The argument type/width is self-determined and doesn't
// affect the result type/width. Note that if the
// argument is a type name (a special case) then
// don't bother with this step.
width_mode_t arg_mode = SIZED;
expr->test_width(des, scope, arg_mode);
}
expr_type_ = IVL_VT_BOOL;
expr_width_ = integer_width;
@ -1393,7 +1397,25 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
PExpr*expr = parms_[0];
verinum val ( (uint64_t)expr->expr_width(), integer_width);
uint64_t use_width = 0;
if (PETypename*type_expr = dynamic_cast<PETypename*>(expr)) {
ivl_type_t tmp_type = type_expr->get_type()->elaborate_type(des, scope);
ivl_assert(*this, tmp_type);
use_width = tmp_type->packed_width();
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
<< " Packed width of type argument is " << use_width << endl;
}
} else {
use_width = expr->expr_width();
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
<< " Width of expression argument is " << use_width << endl;
}
}
verinum val (use_width, integer_width);
NetEConst*sub = new NetEConst(val);
sub->set_line(*this);
@ -3299,9 +3321,14 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
<< "got " << use_path.back().index.size() << "." << endl;
}
return check_for_struct_members(this, des, use_scope,
net, use_path.back().index,
member_comp);
NetExpr*tmp = check_for_struct_members(this, des, use_scope,
net, use_path.back().index,
member_comp);
if (!tmp) return 0;
tmp = pad_to_width(tmp, expr_wid, *this);
tmp->cast_signed(signed_flag_);
return tmp;
}
if (net->class_type() != 0) {
@ -4693,11 +4720,11 @@ unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&)
*/
NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
const netclass_t*ctype,
NetExpr*obj, unsigned flags) const
NetExpr*obj, unsigned /*flags*/) const
{
// If there is an initializer function, then pass the object
// through that function first. Note tha the initializer
// function has no arguments other then the object itself.
// through that function first. Note that the initializer
// function has no arguments other than the object itself.
if (NetScope*new1_scope = ctype->method_from_name(perm_string::literal("new@"))) {
NetFuncDef*def1 = new1_scope->func_def();
ivl_assert(*this, def1);
@ -4839,7 +4866,7 @@ NetExpr* PENewCopy::elaborate_expr(Design*des, NetScope*scope, ivl_type_t obj_ty
/*
* A "null" expression represents class objects/handles. This brings
* up a ton of special cases, but we handle it here bu setting the
* up a ton of special cases, but we handle it here by setting the
* expr_type_ and expr_width_ to fixed values.
*/
unsigned PENull::test_width(Design*, NetScope*, width_mode_t&)
@ -5158,6 +5185,31 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
return tmp;
}
/*
* A typename expression is only legal in very narrow cases. This is
* just a placeholder.
*/
unsigned PETypename::test_width(Design*des, NetScope*, width_mode_t&)
{
cerr << get_fileline() << ": error: "
<< "Type names are not valid expressions here." << endl;
des->errors += 1;
expr_type_ = IVL_VT_NO_TYPE;
expr_width_ = 1;
min_width_ = 1;
signed_flag_ = false;
return expr_width_;
}
NetExpr*PETypename::elaborate_expr(Design*des, NetScope*,
ivl_type_t, unsigned) const
{
cerr << get_fileline() << ": error: Type name not a valid expression here." << endl;
des->errors += 1;
return 0;
}
unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
{
switch (op_) {

View File

@ -48,6 +48,7 @@
# include "netlist.h"
# include "netclass.h"
# include "netenum.h"
# include "parse_api.h"
# include "util.h"
# include <typeinfo>
# include <cassert>
@ -156,6 +157,10 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
}
}
/*
* Elaborate the enumeration into the given scope. If scope==0, then
* the enumeration goes into $root instead of a scope.
*/
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type)
{
@ -176,10 +181,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
msb, lsb, enum_type->names->size());
use_enum->set_line(enum_type->li);
scope->add_enumeration_set(use_enum);
ivl_assert(*enum_type, enum_type->net_type == 0);
enum_type->net_type = use_enum;
if (scope)
scope->add_enumeration_set(enum_type, use_enum);
else
des->add_enumeration_set(enum_type, use_enum);
verinum cur_value (0);
verinum one_value (1);
@ -270,7 +275,11 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
tmp_val.has_sign(enum_type->signed_flag);
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
if (scope)
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
else
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
if (! rc_flag) {
cerr << use_enum->get_fileline()
<< ": error: Duplicate enumeration name "
@ -297,6 +306,15 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_enumerations(Design*des)
{
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
; cur != pform_enum_sets.end() ; ++ cur) {
enum_type_t*curp = *cur;
elaborate_scope_enumeration(des, 0, curp);
}
}
/*
* If the pclass includes an implicit and explicit constructor, then
* merge the implicit constructor into the explicit constructor as

View File

@ -563,7 +563,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
// Special case: this is a constructor, so the return
// signal is also the first argument. For example, the
// source code for the definition may be:
// function new(...);
// function new(...);
// endfunction
// In this case, the "@" port is the synthetic "this"
// argument and we also use it as a return value at the
@ -876,7 +876,7 @@ static ivl_type_s*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 = struct_type->elaborate_type(des, scope);
ivl_type_s*use_type = struct_type->elaborate_type(des, scope);
return use_type;
}
@ -965,7 +965,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< "'." << endl;
des->errors += 1;
}
// A signal can not have the same name as a parameter.
// A signal can not have the same name as a parameter. Note
// that we treat enumeration literals similar to parameters,
// so if the name matches an enumeration literal, it will be
// caught here.
const NetExpr *ex_msb, *ex_lsb;
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
if (parm) {
@ -1207,7 +1210,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
} else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
// If this is a struct type, then build the net with the
// struct type.
netstruct_t*use_type = struct_type->elaborate_type(des, scope);
ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope);
netstruct_t*use_type = dynamic_cast<netstruct_t*>(tmp_type);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal " << wtype;
if (use_type->packed())
@ -1256,7 +1260,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// 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
// Should not be getting packed dimensions other than
// through the parray type declaration.
ivl_assert(*this, packed_dimensions.empty());

View File

@ -31,7 +31,7 @@
using namespace std;
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const
{
cerr << get_fileline() << ": internal error: "
<< "Elaborate method not implemented for " << typeid(*this).name()
@ -40,7 +40,7 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*) const
return 0;
}
ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
ivl_type_s* atom2_type_t::elaborate_type_raw(Design*des, NetScope*) const
{
switch (type_code) {
case 64:
@ -75,18 +75,28 @@ ivl_type_s* atom2_type_t::elaborate_type(Design*des, NetScope*) const
}
}
ivl_type_s* class_type_t::elaborate_type(Design*, NetScope*scope) const
ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const
{
return scope->find_class(name);
}
ivl_type_s* enum_type_t::elaborate_type(Design*des, NetScope*scope) const
/*
* elaborate_type_raw for enumerations is actually mostly performed
* during scope elaboration so that the enumeration literals are
* available at the right time. At that time, the netenum_t* object is
* stashed in the scope so that I can retrieve it here.
*/
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
ivl_assert(*this, net_type);
return net_type;
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;
}
ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
vector<netrange_t> packed;
@ -122,7 +132,7 @@ ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const
return tmp;
}
ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const
ivl_type_s* real_type_t::elaborate_type_raw(Design*, NetScope*) const
{
switch (type_code) {
case REAL:
@ -133,12 +143,12 @@ ivl_type_s* real_type_t::elaborate_type(Design*, NetScope*) const
return 0;
}
ivl_type_s* string_type_t::elaborate_type(Design*, NetScope*) const
ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
{
return &netstring_t::type_string;
}
netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
netstruct_t*res = new netstruct_t;
@ -173,7 +183,7 @@ netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const
return res;
}
ivl_type_s* uarray_type_t::elaborate_type(Design*des, NetScope*scope) const
ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
ivl_type_t btype = base_type->elaborate_type(des, scope);

View File

@ -129,8 +129,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
<< ", expr=" << *rval_expr << endl;
}
assert(lval && rval);
assert(rval->pin_count() == 1);
ivl_assert(*this, lval && rval);
ivl_assert(*this, rval->pin_count() == 1);
// Detect the case that the rvalue-expression is a simple
// expression. In this case, we will need to create a driver
@ -139,23 +139,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
if (dynamic_cast<NetESignal*>(rval_expr))
need_driver_flag = true;
#if 0
// MTW, 01-Mar-2013. The expression elaboration rework should have
// ensured that this can no longer occur. Leaving this here for the
// moment, but it should be safe to remove it.
/* If the r-value insists on being smaller than the l-value
(perhaps it is explicitly sized) the pad it out to be the
right width so that something is connected to all the bits
of the l-value. */
if (lval->vector_width() > rval->vector_width()) {
if (rval->get_signed())
rval = pad_to_width_signed(des, rval, lval->vector_width(),
*this);
else
rval = pad_to_width(des, rval, lval->vector_width(), *this);
// expression elaboration should have caused the rval width to
// match the l-value by now.
if (rval->vector_width() < lval->vector_width()) {
cerr << get_fileline() << ": internal error: "
<< "lval-rval width mismatch: "
<< "rval->vector_width()==" << rval->vector_width()
<< ", lval->vector_width()==" << lval->vector_width() << endl;
}
#endif
ivl_assert(*this, rval->vector_width() >= lval->vector_width());
/* If the r-value insists on being larger than the l-value,
@ -3060,7 +3051,7 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const
NetNet*var_this = scope->find_signal(perm_string::literal("@"));
// If super.new is an implicit constructor, then there are no
// arguments (other then "this" to worry about, so make a
// arguments (other than "this" to worry about, so make a
// NetEUFunc and there we go.
if (NetScope*new_scope = class_super->method_from_name(perm_string::literal("new@"))) {
NetESignal*eres = new NetESignal(var_this);
@ -5663,6 +5654,9 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find.
Design*des = new Design;
// Elaborate enum sets in $root scope.
elaborate_rootscope_enumerations(des);
// Elaborate the packages. Package elaboration is simpler
// because there are fewer sub-scopes involved.
i = 0;

View File

@ -420,9 +420,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
tgt->class_type(this, cur->second);
}
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin()
for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++cur)
tgt->enumeration(this, *cur);
tgt->enumeration(this, cur->second);
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur )

View File

@ -288,6 +288,13 @@ NetEConst* NetEBBits::eval_arguments_(const NetExpr*l, const NetExpr*r) const
break;
}
case 'X': {
for (unsigned idx = 0 ; idx < wid ; idx += 1)
res.set(idx, ~(lval.get(idx) ^ rval.get(idx)));
break;
}
case '^': {
for (unsigned idx = 0 ; idx < wid ; idx += 1)
res.set(idx, lval.get(idx) ^ rval.get(idx));
@ -1923,6 +1930,173 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
return res;
}
NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/,
const NetExpr* /*arg1*/) const
{
return 0;
}
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const
{
return 0;
}
/* Get the total number of dimensions for the given expression. */
NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
{
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
long res = 0;
if (esig != 0) {
const NetNet *sig = esig->sig();
res = sig->packed_dimensions() + sig->unpacked_dimensions();
/* Icarus does not think a string has a packed size so to
* make these routines work correct add one if this is a
* string data type. */
if (sig->data_type() == IVL_VT_STRING) {
assert(sig->packed_dimensions() == 0);
res += 1;
}
}
/* Return the result as an integer sized constant. */
return new NetEConst(verinum(verinum(res), integer_width));
}
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const
{
return 0;
}
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const
{
return 0;
}
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const
{
return 0;
}
/* Get the number of unpacked dimensions for the given expression. */
NetEConst* NetESFunc::evaluate_unpacked_dimensions_(const NetExpr*arg) const
{
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
long res = 0;
if (esig != 0) {
const NetNet *sig = esig->sig();
res = sig->unpacked_dimensions();
}
/* Return the result as an integer sized constant. */
return new NetEConst(verinum(verinum(res), integer_width));
}
/* This code assumes that the dimension value will fit in a long.
* Return true if no constant dimension value is available. */
static bool check_dimension(const NetExpr*dim_expr, long &dim)
{
const NetEConst*dimi = dynamic_cast<const NetEConst*>(dim_expr);
const NetECReal*dimr = dynamic_cast<const NetECReal*>(dim_expr);
if (dimi == 0 && dimr == 0) return true;
if (dimi) dim = dimi->value().as_long();
if (dimr) dim = dimr->value().as_long();
return false;
}
/* Get the left and right values for the argument at the given dimension
* if it exists. Return true if no values are available. Set defer to true
* if this should be handled in the run time. */
static bool get_array_info(const NetExpr*arg, long dim,
long &left, long &right, bool&defer)
{
/* The argument must be a signal that has enough dimensions. */
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
if (esig == 0) return true;
const NetNet *sig = esig->sig();
/* A string or dynamic array must be handled by the run time. */
switch (sig->data_type()) {
case IVL_VT_DARRAY:
case IVL_VT_STRING:
defer = true;
return true;
break;
default:
break;
}
long pdims = sig->packed_dimensions();
long updims = sig->unpacked_dimensions();
if (dim > (pdims + updims)) return true;
/* Get the appropriate unpacked or packed dimension information. */
if (dim > updims) {
const vector<netrange_t>&dim_vals = sig->packed_dims();
const netrange_t&range = dim_vals[dim-updims-1];
left = range.get_msb();
right = range.get_lsb();
} else {
const vector<netrange_t>&dim_vals = sig->unpacked_dims();
const netrange_t&range = dim_vals[dim-1];
left = range.get_msb();
right = range.get_lsb();
}
return false;
}
/* Calculate the array property functions. */
NetEConst* NetESFunc::evaluate_array_funcs_(ID id,
const NetExpr*arg0,
const NetExpr*arg1) const
{
long dim = 0;
/* Check to see if the dimension argument is constant. */
if (check_dimension(arg1, dim)) return 0;
/* If dimension is less than 1 return undefined. */
if (dim < 1) {
return new NetEConst(verinum(verinum::Vx, integer_width));
}
/* Get the left/right information for this dimension if it exists. */
long left = 0;
long right = 0;
bool defer = false;
if (get_array_info(arg0, dim, left, right, defer)) {
/* If this is a string or dynamic array defer this function
* call since the left/right information is dynamic and is
* not available yet. */
if (defer) return 0;
return new NetEConst(verinum(verinum::Vx, integer_width));
}
/* Calculate the appropriate array function result. */
long res;
switch (id) {
case HIGH:
res = (right > left) ? right : left;
break;
case INCR:
res = (right > left) ? -1 : 1;
break;
case LEFT:
res = left;
break;
case LOW:
res = (right > left) ? left : right;
break;
case RIGHT:
res = right;
break;
case SIZE:
res = (right > left) ? right - left : left - right;
res += 1;
break;
default:
res = 0;
assert(0);
}
/* Return the result as an integer sized constant. */
return new NetEConst(verinum(verinum(res), integer_width));
}
/* Make a constant one value that can be used by the one argument
* array properties calls. */
const NetEConst* NetESFunc::const_one_ = new NetEConst(verinum(1U, 32U));
NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const
{
switch (id) {
@ -1930,21 +2104,51 @@ NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const
return evaluate_abs_(arg);
case CLOG2:
return evaluate_clog2_(arg);
case CTONES:
return evaluate_countones_(arg);
case DIMS:
return evaluate_dimensions_(arg);
/* The array functions are handled together. */
case HIGH:
case INCR:
case LEFT:
case LOW:
case RIGHT:
case SIZE:
return evaluate_array_funcs_(id, arg, const_one_);
case ISUNKN:
return evaluate_isunknown_(arg);
case ITOR:
return evaluate_itor_(arg);
case ONEHT:
return evaluate_onehot_(arg);
case ONEHT0:
return evaluate_onehot0_(arg);
case RTOI:
return evaluate_rtoi_(arg);
case UPDIMS:
return evaluate_unpacked_dimensions_(arg);
default:
return evaluate_math_one_arg_(id, arg);
}
}
NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
const NetExpr*arg1) const
const NetExpr*arg1) const
{
switch (id) {
case MIN:
case CTBITS:
return evaluate_countbits_(arg0, arg1);
/* The array functions are handled together. */
case HIGH:
case INCR:
case LEFT:
case LOW:
case RIGHT:
case SIZE:
return evaluate_array_funcs_(id, arg0, arg1);
case MAX:
case MIN:
return evaluate_min_max_(id, arg0, arg1);
default:
return evaluate_math_two_arg_(id, arg0, arg1);
@ -1990,6 +2194,31 @@ NetESFunc::ID NetESFunc::built_in_id_() const
built_in_func["$tanh" ] = TANH;
}
/* These are available in 1800-2005 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2005_SV)) {
built_in_func["$dimensions" ] = DIMS;
built_in_func["$high" ] = HIGH;
built_in_func["$increment" ] = INCR;
built_in_func["$isunknown" ] = ISUNKN;
built_in_func["$left" ] = LEFT;
built_in_func["$low" ] = LOW;
built_in_func["$onehot" ] = ONEHT;
built_in_func["$onehot0" ] = ONEHT0;
built_in_func["$right" ] = RIGHT;
built_in_func["$size" ] = SIZE;
built_in_func["$unpacked_dimensions" ] = UPDIMS;
}
/* These are available in 1800-2009 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2009)) {
built_in_func["$countones" ] = CTONES;
}
/* These are available in 1800-2012 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2012)) {
built_in_func["$countbits" ] = CTBITS;
}
/* These are available in Verilog-A as Icarus extensions or if the
* Icarus misc flag was given. */
if (funcs_need_init && (gn_verilog_ams_flag || gn_icarus_misc_flag)) {
@ -2045,6 +2274,7 @@ NetExpr* NetESFunc::eval_tree()
<< " arguments." << endl;
return 0;
}
// HERE: Need to add support for a multi argument $countbits().
cerr << get_fileline() << ": sorry: functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;

View File

@ -341,7 +341,7 @@ TU [munpf]
}
}
/* If this identifer names a previously declared package, then
/* If this identifier names a previously declared package, then
return this as a PACKAGE_IDENTIFIER instead. */
if (rc == IDENTIFIER && gn_system_verilog()) {
if (PPackage*pkg = pform_test_package_identifier(yylval.text)) {

View File

@ -260,7 +260,7 @@ void NetEConcat::set(unsigned idx, NetExpr*e)
expr_width( expr_width() + repeat_ * e->expr_width() );
}
NetEConstEnum::NetEConstEnum(NetScope*s, perm_string n, const netenum_t*eset, const verinum&v)
NetEConstEnum::NetEConstEnum(Definitions*s, perm_string n, const netenum_t*eset, const verinum&v)
: NetEConst(v), scope_(s), enum_set_(eset), name_(n)
{
assert(has_width());

View File

@ -138,7 +138,7 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
if (flag) {
if (debug_eval_tree) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "Evalutated to ";
<< "Evaluated to ";
if (res) cerr << *res;
else cerr << "<nil>";
cerr << endl;

View File

@ -30,6 +30,72 @@
class PExpr;
Definitions::Definitions()
{
}
Definitions::~Definitions()
{
}
void Definitions::add_enumeration_set(const enum_type_t*key, netenum_t*enum_set)
{
netenum_t*&tmp = enum_sets_[key];
assert(tmp == 0);
tmp = enum_set;
}
bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
{
netenum_t::iterator enum_val = enum_set->find_name(name);
assert(enum_val != enum_set->end_name());
NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second);
pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
cur = enum_names_.insert(make_pair(name,val));
// Return TRUE if the name is added (i.e. is NOT a duplicate.)
return cur.second;
}
netenum_t* Definitions::enumeration_for_key(const enum_type_t*key) const
{
map<const enum_type_t*,netenum_t*>::const_iterator cur;
cur = enum_sets_.find(key);
if (cur != enum_sets_.end())
return cur->second;
else
return 0;
}
/*
* This locates the enumeration TYPE for the given enumeration literal.
*/
const netenum_t*Definitions::enumeration_for_name(perm_string name)
{
NetEConstEnum*tmp = enum_names_[name];
assert(tmp != 0);
return tmp->enumeration();
}
/*
* This locates the VALUE for the given enumeration literal.
*/
const NetExpr* Definitions::enumeration_expr(perm_string key)
{
map<perm_string,NetEConstEnum*>::const_iterator eidx;
eidx = enum_names_.find(key);
if (eidx != enum_names_.end()) {
return eidx->second;
} else {
return 0;
}
}
/*
* The NetScope class keeps a scope tree organized. Each node of the
* scope tree points to its parent, its right sibling and its leftmost
@ -265,14 +331,13 @@ const NetExpr* NetScope::get_parameter(Design*des,
return idx->second.val;
}
map<perm_string,NetEConstEnum*>::const_iterator eidx;
msb = 0;
lsb = 0;
const NetExpr*tmp = enumeration_expr(key);
if (tmp) return tmp;
eidx = enum_names_.find(key);
if (eidx != enum_names_.end()) {
msb = 0;
lsb = 0;
return eidx->second;
}
tmp = des->enumeration_expr(key);
if (tmp) return tmp;
return 0;
}
@ -551,33 +616,6 @@ NetNet* NetScope::find_signal(perm_string key)
return 0;
}
void NetScope::add_enumeration_set(netenum_t*enum_set)
{
enum_sets_.push_back(enum_set);
}
bool NetScope::add_enumeration_name(netenum_t*enum_set, perm_string name)
{
netenum_t::iterator enum_val = enum_set->find_name(name);
assert(enum_val != enum_set->end_name());
NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second);
pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
cur = enum_names_.insert(make_pair(name,val));
// Return TRUE if the name is added (i.e. is NOT a duplicate.)
return cur.second;
}
const netenum_t*NetScope::enumeration_for_name(perm_string name)
{
NetEConstEnum*tmp = enum_names_[name];
assert(tmp != 0);
return tmp->enumeration();
}
void NetScope::add_class(netclass_t*net_class)
{
classes_[net_class->get_name()] = net_class;

View File

@ -755,7 +755,7 @@ const netclass_t* NetNet::class_type(void) const
/*
* "depth" is the number of index expressions that the user is using
* to index this identifer. So consider if Net was declared like so:
* to index this identifier. So consider if Net was declared like so:
*
* reg [5:0][3:0] foo;
*

153
netlist.h
View File

@ -76,6 +76,7 @@ class NetEvTrig;
class NetEvWait;
class PExpr;
class PFunction;
struct enum_type_t;
class netclass_t;
class netdarray_t;
class netparray_t;
@ -819,12 +820,53 @@ class NetBaseDef {
NetProc*proc_;
};
/*
* Some definitions (and methods to manipulate them) are common to a
* couple of types. Keep them here.
*/
class Definitions {
public:
Definitions();
~Definitions();
// Add the enumeration to the set of enumerations in this
// scope. Include a key that the elaboration can use to look
// up this enumeration based on the pform type.
void add_enumeration_set(const enum_type_t*key, netenum_t*enum_set);
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
// Look up the enumeration literal in this scope. if the name
// is present, then return the enumeration type that declares it.
const netenum_t* enumeration_for_name(perm_string name);
// Look up the enumeration set that was added with the given
// key. This is used by enum_type_t::elaborate_type to locate
// a previously elaborated enumeration.
netenum_t* enumeration_for_key(const enum_type_t*key) const;
// Look up an enumeration literal in this scope. If the
// literal is present, return the expression that defines its
// value.
const NetExpr* enumeration_expr(perm_string key);
protected:
// Enumerations. The enum_sets_ is a list of all the
// enumerations present in this scope. The enum_names_ is a
// map of all the enumeration names back to the sets that
// contain them.
std::map<const enum_type_t*,netenum_t*> enum_sets_;
std::map<perm_string,NetEConstEnum*> enum_names_;
};
/*
* This object type is used to contain a logical scope within a
* design. The scope doesn't represent any executable hardware, but is
* just a handle that netlist processors can use to grab at the design.
*/
class NetScope : public Attrib {
class NetScope : public Definitions, public Attrib {
public:
enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
@ -897,11 +939,6 @@ class NetScope : public Attrib {
void rem_signal(NetNet*);
NetNet* find_signal(perm_string name);
void add_enumeration_set(netenum_t*enum_set);
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
const netenum_t* enumeration_for_name(perm_string name);
void add_class(netclass_t*class_type);
netclass_t* find_class(perm_string name);
@ -1153,13 +1190,6 @@ class NetScope : public Attrib {
const PFunction*func_pform_;
unsigned elab_stage_;
// Enumerations. The enum_sets_ is a list of all the
// enumerations present in this scope. The enum_names_ is a
// map of all the enumeration names back to the sets that
// contain them.
std::list<netenum_t*> enum_sets_;
std::map<perm_string,NetEConstEnum*> enum_names_;
std::map<perm_string,netclass_t*> classes_;
NetScope*up_;
@ -1973,12 +2003,11 @@ class NetEConst : public NetExpr {
class NetEConstEnum : public NetEConst {
public:
explicit NetEConstEnum(NetScope*scope, perm_string name,
explicit NetEConstEnum(Definitions*scope, perm_string name,
const netenum_t*enum_set, const verinum&val);
~NetEConstEnum();
perm_string name() const;
const NetScope*scope() const;
const netenum_t*enumeration() const;
virtual void expr_scan(struct expr_scan_t*) const;
@ -1987,7 +2016,7 @@ class NetEConstEnum : public NetEConst {
virtual NetEConstEnum* dup_expr() const;
private:
NetScope*scope_;
Definitions*scope_;
const netenum_t*enum_set_;
perm_string name_;
};
@ -4176,37 +4205,53 @@ class NetESFunc : public NetExpr {
*/
enum ID { NOT_BUILT_IN = 0x0,
/* Available in all version of Verilog/SystemVerilog. */
ITOR = 0x00020001, /* $itor takes one argument. */
RTOI = 0x00020002, /* $rtoi takes one argument. */
ITOR = 0x00020001, /* $itor takes one argument. */
RTOI = 0x00020002, /* $rtoi takes one argument. */
/* Available in Verilog 2005 and later. */
ACOS = 0x00020003, /* $acos takes one argument. */
ACOSH = 0x00020004, /* $acosh takes one argument. */
ASIN = 0x00020005, /* $asin takes one argument. */
ASINH = 0x00020006, /* $asinh takes one argument. */
ATAN = 0x00020007, /* $atan takes one argument. */
ATANH = 0x00020008, /* $atanh takes one argument. */
ATAN2 = 0x00040009, /* $atan2 takes two argument. */
CEIL = 0x0002000a, /* $ceil takes one argument. */
CLOG2 = 0x0002000b, /* $clog2 takes one argument. */
COS = 0x0002000c, /* $cos takes one argument. */
COSH = 0x0002000d, /* $cosh takes one argument. */
EXP = 0x0002000e, /* $exp takes one argument. */
FLOOR = 0x0002000f, /* $floor takes one argument. */
HYPOT = 0x00040010, /* $hypot takes two argument. */
LN = 0x00020011, /* $ln takes one argument. */
LOG10 = 0x00020012, /* $log10 takes one argument. */
POW = 0x00040013, /* $pow takes two argument. */
SIN = 0x00020014, /* $sin takes one argument. */
SINH = 0x00020015, /* $sinh takes one argument. */
SQRT = 0x00020016, /* $sqrt takes one argument. */
TAN = 0x00020017, /* $tan takes one argument. */
TANH = 0x00020018, /* $tanh takes one argument. */
ACOS = 0x00020003, /* $acos takes one argument. */
ACOSH = 0x00020004, /* $acosh takes one argument. */
ASIN = 0x00020005, /* $asin takes one argument. */
ASINH = 0x00020006, /* $asinh takes one argument. */
ATAN = 0x00020007, /* $atan takes one argument. */
ATANH = 0x00020008, /* $atanh takes one argument. */
ATAN2 = 0x00040009, /* $atan2 takes two argument. */
CEIL = 0x0002000a, /* $ceil takes one argument. */
CLOG2 = 0x0002000b, /* $clog2 takes one argument. */
COS = 0x0002000c, /* $cos takes one argument. */
COSH = 0x0002000d, /* $cosh takes one argument. */
EXP = 0x0002000e, /* $exp takes one argument. */
FLOOR = 0x0002000f, /* $floor takes one argument. */
HYPOT = 0x00040010, /* $hypot takes two argument. */
LN = 0x00020011, /* $ln takes one argument. */
LOG10 = 0x00020012, /* $log10 takes one argument. */
POW = 0x00040013, /* $pow takes two argument. */
SIN = 0x00020014, /* $sin takes one argument. */
SINH = 0x00020015, /* $sinh takes one argument. */
SQRT = 0x00020016, /* $sqrt takes one argument. */
TAN = 0x00020017, /* $tan takes one argument. */
TANH = 0x00020018, /* $tanh takes one argument. */
/* Added in SystemVerilog 2005 and later. */
DIMS = 0x00020019, /* $dimensions takes one argument. */
HIGH = 0x0006001a, /* $high takes one or two arguments. */
INCR = 0x0006001b, /* $increment takes one or two arguments. */
LEFT = 0x0006001c, /* $left takes one or two arguments. */
LOW = 0x0006001d, /* $low takes one or two arguments. */
RIGHT = 0x0006001e, /* $right takes one or two arguments. */
SIZE = 0x0006001f, /* $size takes one or two arguments. */
UPDIMS = 0x00020020, /* $unpacked_dimensions takes one argument. */
ISUNKN = 0x00020021, /* $isunknown takes one argument. */
ONEHT = 0x00020022, /* $onehot takes one argument. */
ONEHT0 = 0x00020023, /* $onehot0 takes one argument. */
/* Added in SystemVerilog 2009 and later. */
CTONES = 0x00020024, /* $countones takes one argument. */
/* Added in SystemVerilog 2012 and later. */
CTBITS = 0xfffe0025, /* $countbits takes one or more arguments. */
/* Added as Icarus extensions to Verilog-A. */
ABS = 0x00020019, /* $abs takes one argument. */
MAX = 0x0004001a, /* $max takes two argument. */
MIN = 0x0004001b, /* $min takes two argument. */
ABS = 0x00020026, /* $abs takes one argument. */
MAX = 0x00040027, /* $max takes two argument. */
MIN = 0x00040028, /* $min takes two argument. */
/* A dummy value to properly close the enum. */
DUMMY = 0xffffffff };
DUMMY = 0xffffffff };
bool takes_nargs_(ID func, unsigned nargs) {
if (nargs > 15) nargs = 15;
@ -4237,6 +4282,24 @@ class NetESFunc : public NetExpr {
NetExpr* evaluate_min_max_(ID id, const NetExpr*arg0,
const NetExpr*arg1) const;
/* Constant SystemVerilog functions. */
NetEConst* evaluate_countones_(const NetExpr*arg) const;
NetEConst* evaluate_dimensions_(const NetExpr*arg) const;
NetEConst* evaluate_isunknown_(const NetExpr*arg) const;
NetEConst* evaluate_onehot_(const NetExpr*arg) const;
NetEConst* evaluate_onehot0_(const NetExpr*arg) const;
NetEConst* evaluate_unpacked_dimensions_(const NetExpr*arg) const;
/* This value is used as a default when the array functions are
* called with a single argument. */
static const NetEConst*const_one_;
NetEConst* evaluate_array_funcs_(ID id,
const NetExpr*arg0,
const NetExpr*arg1) const;
NetEConst* evaluate_countbits_(const NetExpr*arg0,
const NetExpr*arg1) const;
public:
bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; };
@ -4465,7 +4528,7 @@ struct elaborator_work_item_t {
* This class contains an entire design. It includes processes and a
* netlist, and can be passed around from function to function.
*/
class Design {
class Design : public Definitions {
public:
Design();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 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
@ -48,7 +48,7 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
} else {
verinum zero ((int64_t)val);
zero = pad_to_width(zero, sig->vector_width());
zero = cast_to_width(zero, sig->vector_width());
zero.has_sign(sig->get_signed());
NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero);
zero_obj->set_line(*sig);
@ -1360,7 +1360,7 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
/*
* 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.
* expression over a canonical equivalent 1-dimensional array.
*/
NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net,
const list<index_component_t>&indices)

View File

@ -63,7 +63,7 @@ bool ivl_type_s::type_compatible(ivl_type_t that) const
return test_compatibility(that);
}
bool ivl_type_s::test_compatibility(const ivl_type_s*that) const
bool ivl_type_s::test_compatibility(const ivl_type_s* /*that*/) const
{
return false;
}

15
parse.y
View File

@ -1081,7 +1081,7 @@ description /* IEEE1800-2005: A.1.2 */
| nature_declaration
| package_declaration
| discipline_declaration
| timeunits_declaration
| package_item
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
{ perm_string tmp3 = lex_strings.make($3);
pform_set_type_attrib(tmp3, $5, $7);
@ -2362,6 +2362,11 @@ struct_union_member /* IEEE 1800-2012 A.2.2.1 */
tmp->names .reset($3);
$$ = tmp;
}
| error ';'
{ yyerror(@2, "Error in struct/union member.");
yyerrok;
$$ = 0;
}
;
case_item
@ -3092,6 +3097,14 @@ expr_primary
delete[]$1;
}
/* There are a few special cases (notably $bits argument) where the
expression may be a type name. Let the elaborator sort this out. */
| TYPE_IDENTIFIER
{ PETypename*tmp = new PETypename($1);
FILE_NAME(tmp,@1);
$$ = tmp;
}
/* The hierarchy_identifier rule matches simple identifiers as well as
indexed arrays and part selects */

View File

@ -24,10 +24,14 @@
# include <string>
# include <ostream>
# include <map>
# include <set>
class Design;
class Module;
class PPackage;
class PUdp;
class data_type_t;
struct enum_type_t;
/*
* These are maps of the modules and primitives parsed from the
@ -36,10 +40,14 @@ class PUdp;
*/
extern std::map<perm_string,Module*> pform_modules;
extern std::map<perm_string,PUdp*> pform_primitives;
extern std::map<perm_string,data_type_t*> pform_typedefs;
extern std::set<enum_type_t*> pform_enum_sets;
extern std::map<perm_string,PPackage*> pform_packages;
extern void pform_dump(std::ostream&out, const PPackage*pac);
extern void elaborate_rootscope_enumerations(Design*des);
/*
* This code actually invokes the parser to make modules. The first
* parameter is the name of the file that is to be parsed. The

View File

@ -46,12 +46,16 @@
/*
* The pform_modules is a map of the modules that have been defined in
* the top level. This should not contain nested modules/programs.
* pform_primitives is similar, but for UDP primitives.
*/
map<perm_string,Module*> pform_modules;
/*
*/
map<perm_string,PUdp*> pform_primitives;
/*
* typedefs in the $root scope go here.
*/
map<perm_string,data_type_t*>pform_typedefs;
set<enum_type_t*>pform_enum_sets;
std::string vlltype::get_fileline() const
{
@ -484,7 +488,12 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net)
static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
{
lexical_scope->enum_sets.insert(enum_set);
if (lexical_scope) {
ivl_assert(*enum_set, lexical_scope);
lexical_scope->enum_sets.insert(enum_set);
} else {
pform_enum_sets.insert(enum_set);
}
}
PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
@ -505,7 +514,13 @@ PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetN
void pform_set_typedef(perm_string name, data_type_t*data_type)
{
data_type_t*&ref = lexical_scope->typedefs[name];
// If we are in a lexical scope (i.e. a package or module)
// then put the typedef into that scope. Otherwise, put it
// into the $root scope.
data_type_t*&ref = lexical_scope
? lexical_scope->typedefs[name]
: pform_typedefs[name];
ivl_assert(*data_type, ref == 0);
ref = data_type;
@ -514,15 +529,25 @@ void pform_set_typedef(perm_string name, data_type_t*data_type)
}
}
static data_type_t* test_type_identifier_in_root(perm_string name)
{
map<perm_string,data_type_t*>::iterator cur = pform_typedefs.find(name);
if (cur != pform_typedefs.end())
return cur->second;
else
return 0;
}
data_type_t* pform_test_type_identifier(const char*txt)
{
// If there is no lexical_scope yet, then there is NO WAY the
// identifier can be a type_identifier.
if (lexical_scope == 0)
return 0;
perm_string name = lex_strings.make(txt);
// If there is no lexical_scope yet, then look only in the
// $root scope for typedefs.
if (lexical_scope == 0) {
return test_type_identifier_in_root(name);
}
LexicalScope*cur_scope = lexical_scope;
do {
map<perm_string,data_type_t*>::iterator cur;
@ -530,7 +555,7 @@ data_type_t* pform_test_type_identifier(const char*txt)
// First look to see if this identifier is imported from
// a package. If it is, see if it is a type in that
// package. If it is, then great. If imported as
// something other then a type, then give up now becase
// something other than a type, then give up now because
// the name has at least shadowed any other possible
// meaning for this name.
map<perm_string,PPackage*>::iterator cur_pkg;
@ -552,6 +577,10 @@ data_type_t* pform_test_type_identifier(const char*txt)
cur_scope = cur_scope->parent_scope();
} while (cur_scope);
// See if there is a typedef in the $root scope.
if (data_type_t*tmp = test_type_identifier_in_root(name))
return tmp;
return 0;
}

View File

@ -170,7 +170,10 @@ void uarray_type_t::pform_dump(ostream&out, unsigned indent) const
void struct_type_t::pform_dump(ostream&out, unsigned indent) const
{
out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked")
<< " with " << members->size() << " members" << endl;
<< " with " << (members.get()==0? 0 : members->size()) << " members" << endl;
if (members.get()==0)
return;
for (list<struct_member_t*>::iterator cur = members->begin()
; cur != members->end() ; ++ cur) {
struct_member_t*curp = *cur;
@ -382,6 +385,11 @@ void PETernary::dump(ostream&out) const
out << "(" << *expr_ << ")?(" << *tru_ << "):(" << *fal_ << ")";
}
void PETypename::dump(ostream&fd) const
{
fd << "<type>";
}
void PEUnary::dump(ostream&out) const
{
switch (op_) {

View File

@ -26,8 +26,12 @@ ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const
if (! packed_flag)
return IVL_VT_NO_TYPE;
if (members.get() == 0)
return IVL_VT_NO_TYPE;
ivl_variable_type_t base_type = IVL_VT_BOOL;
ivl_assert(*this, members.get());
for (list<struct_member_t*>::iterator cur = members->begin()
; cur != members->end() ; ++ cur) {

View File

@ -24,6 +24,15 @@ data_type_t::~data_type_t()
{
}
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
{
if (cache_type_elaborate_)
return cache_type_elaborate_;
cache_type_elaborate_ = elaborate_type_raw(des, scope);
return cache_type_elaborate_;
}
string_type_t::~string_type_t()
{
}

View File

@ -88,14 +88,21 @@ struct pform_tf_port_t {
*/
class data_type_t : public LineInfo {
public:
inline explicit data_type_t() : cache_type_elaborate_(0) { }
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;
ivl_type_s* elaborate_type(Design*des, NetScope*scope);
private:
// Elaborate the type to an ivl_type_s type.
virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
ivl_type_s*cache_type_elaborate_;
};
struct void_type_t : public data_type_t {
@ -109,20 +116,14 @@ struct void_type_t : public data_type_t {
* until it is elaborated in a scope.
*/
struct enum_type_t : public data_type_t {
inline enum_type_t(void) : net_type(0) { }
// Return the elaborated version of the type.
virtual ivl_type_s*elaborate_type(Design*des, NetScope*scope) const;
virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const;
ivl_variable_type_t base_type;
bool signed_flag;
std::auto_ptr< list<pform_range_t> > range;
std::auto_ptr< list<named_pexpr_t> > names;
LineInfo li;
// This is the elaborated type. The enumeration type is
// elaborated early so that names can be placed in the scope,
// but that means the result needs to be saved for the actual
// elaborate_type method to use.
netenum_t*net_type;
};
struct struct_member_t : public LineInfo {
@ -134,7 +135,7 @@ 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;
virtual void pform_dump(std::ostream&out, unsigned indent) const;
virtual netstruct_t* elaborate_type(Design*des, NetScope*scope) const;
virtual netstruct_t* elaborate_type_raw(Design*des, NetScope*scope) const;
bool packed_flag;
bool union_flag;
@ -147,7 +148,7 @@ struct atom2_type_t : public data_type_t {
int type_code;
bool signed_flag;
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
};
/*
@ -174,7 +175,7 @@ struct vector_type_t : public data_type_t {
std::list<pform_range_t>*pd)
: base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { }
virtual ivl_variable_type_t figure_packed_base_type(void)const;
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
ivl_variable_type_t base_type;
bool signed_flag;
@ -216,7 +217,7 @@ struct uarray_type_t : public array_base_t {
public:
virtual void pform_dump(std::ostream&out, unsigned indent) const;
virtual ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
};
struct real_type_t : public data_type_t {
@ -224,14 +225,14 @@ struct real_type_t : public data_type_t {
inline explicit real_type_t(type_t tc) : type_code(tc) { }
type_t type_code;
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
};
struct string_type_t : public data_type_t {
inline explicit string_type_t() { }
~string_type_t();
ivl_type_s* elaborate_type(Design*des, NetScope*scope) const;
ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const;
};
struct class_type_t : public data_type_t {
@ -271,7 +272,7 @@ struct class_type_t : public data_type_t {
// without waiting for any constructor.
std::vector<Statement*> initialize_static;
ivl_type_s* elaborate_type(Design*, NetScope*) const;
ivl_type_s* elaborate_type_raw(Design*, NetScope*) const;
};
/*

View File

@ -232,7 +232,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
unsigned mux_size = max_guard_value + 1;
// If the sel_width can select more then just the explicit
// If the sel_width can select more than just the explicit
// guard values, and there is a default statement, then adjust
// the mux size to allow for the implicit selections.
if (statement_default && ((1U<<sel_width) > mux_size)) {

View File

@ -55,7 +55,7 @@ int blif_errors = 0;
static void emit_blif(const char*blif_path, ivl_design_t des, ivl_scope_t model);
static int process_scan_fun(ivl_process_t net, void*raw)
static int process_scan_fun(ivl_process_t net, void* /*raw*/)
{
fprintf(stderr, "%s:%u: sorry: BLIF: Processes not supported yet.\n",
ivl_process_file(net), ivl_process_lineno(net));

View File

@ -45,7 +45,7 @@ int load_footprints(void)
}
/*
* The fpparse funciton calls back the callback_fp_element function
* The fpparse function calls back the callback_fp_element function
* for each Element that it parses. The check_footprint function
* stores in the cur_footprint variable the name of the footprint that
* we are trying to find in the file. The callback uses that name to

View File

@ -267,8 +267,9 @@ static expr_sign_t expr_get_sign_type(ivl_expr_t expr, unsigned wid,
break;
}
/* Check for a self-determined context. */
if ((rtn == NO_SIGN) && (wid != expr_wid) &&
/* Check for a self-determined context. A zero width expression
* is special and is not considered a self determined context. */
if ((rtn == NO_SIGN) && (wid != expr_wid) && expr_wid &&
! (is_full_prec && ((expr_wid < wid) || (type == IVL_EX_SIGNAL)))) {
if (ivl_expr_signed(expr)) rtn = NEED_SIGNED;
else rtn = NEED_UNSIGNED;

View File

@ -917,8 +917,8 @@ static unsigned has_func_disable(ivl_scope_t scope, ivl_statement_t stmt)
rtn = scope == ivl_stmt_call(stmt);
break;
default:
fprintf(stderr, "%s:%u: vlog95 error: Unknown statment type (%d) "
"in functin disable check.\n",
fprintf(stderr, "%s:%u: vlog95 error: Unknown statement type (%d) "
"in function disable check.\n",
ivl_stmt_file(stmt),
ivl_stmt_lineno(stmt),
(int)ivl_statement_type(stmt));
@ -1187,7 +1187,7 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
name_return);
free(name_return);
} else emit_stmt(scope, body);
/* A non-block statment may need a named block for a return. */
/* A non-block statement may need a named block for a return. */
} else if (has_func_disable(scope, body)) {
char *name_return = get_func_return_name(scope);
fprintf(vlog_out, "%*cbegin: %s\n", indent, ' ',

View File

@ -214,16 +214,27 @@ static void emit_stmt_lval_darray(ivl_scope_t scope, ivl_lval_t lval,
* Class or class properties are not supported in vlog95, but this assignment
* can be translated correctly.
*/
static void emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval,
ivl_signal_t sig)
static ivl_type_t emit_stmt_lval_class(ivl_scope_t scope, ivl_lval_t lval)
{
ivl_lval_t nest = ivl_lval_nest(lval);
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_type_t type;
int idx = ivl_lval_property_idx(lval);
emit_scope_call_path(scope, ivl_signal_scope(sig));
emit_id(ivl_signal_basename(sig));
if (idx >= 0) {
ivl_type_t sig_type = ivl_signal_net_type(sig);
fprintf(vlog_out, ".%s", ivl_type_prop_name(sig_type, idx));
if (nest) {
type = emit_stmt_lval_class(scope, nest);
assert(type);
} else {
assert(sig);
emit_scope_call_path(scope, ivl_signal_scope(sig));
emit_id(ivl_signal_basename(sig));
type = ivl_signal_net_type(sig);
}
if (idx >= 0) {
fprintf(vlog_out, ".%s", ivl_type_prop_name(type, idx));
return ivl_type_prop_type(type, idx);
} else return 0;
}
static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
@ -234,14 +245,20 @@ static void emit_stmt_lval_piece(ivl_scope_t scope, ivl_lval_t lval)
unsigned width = ivl_lval_width(lval);
int msb, lsb;
assert(width > 0);
assert(sig);
/* A class supports a nested L-value so it may not have a signal
* at this level. */
if (! sig) {
(void) emit_stmt_lval_class(scope, lval);
return;
}
switch (ivl_signal_data_type(sig)) {
case IVL_VT_DARRAY:
emit_stmt_lval_darray(scope, lval, sig);
return;
case IVL_VT_CLASS:
emit_stmt_lval_class(scope, lval, sig);
(void) emit_stmt_lval_class(scope, lval);
return;
default:
break;

View File

@ -566,7 +566,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
out << ")";
} else {
// If this function has an elaborated defintion, and if
// If this function has an elaborated definition, and if
// that definition is in a package, then include the
// package name as a scope qualifier. This assures that
// the SV elaborator finds the correct VHDL elaborated

View File

@ -52,7 +52,7 @@ class class_type : public __vpiHandle {
void set_property(size_t idx, const std::string&name, const std::string&type);
// This method is called after all the properties are
// defined. This calculates information about the defintion.
// defined. This calculates information about the definition.
void finish_setup(void);
public:

View File

@ -1024,7 +1024,7 @@ includes an implicit pop, but sometimes it is necessary to pop
explicitly.
The <skip> is the number of top positions on the stack to keep,
beforing starting to pop. This allows for popping positions other then
beforing starting to pop. This allows for popping positions other than
the top of the stack.
* %pow <bit-l>, <bit-r>, <wid>