Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl

This commit is contained in:
Nick Gasson 2008-10-26 12:48:22 +00:00
commit f49a4e4336
12 changed files with 339 additions and 213 deletions

View File

@ -66,7 +66,7 @@ class PExpr : public LineInfo {
// The expr_type is an output argument that gives the
// calculated type for the expression.
//
// The unsigned_flag is set to true if the expression is
// The unsized_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
@ -156,6 +156,11 @@ class PEConcat : public PExpr {
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag);
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2008 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
@ -739,7 +739,8 @@ v }
}
}
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
#if 0
static void replace_with_mos(Design*des, NetMux*obj, NetLogic::TYPE type)
{
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
@ -749,7 +750,7 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
connect(obj->pin_Data(type==NetLogic::PMOS? 0 : 1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
@ -780,10 +781,11 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
delete obj;
}
#endif
/*
* This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a bufif with the sel
* Vz. In this case, replace the device with a mos with the sel
* input used to enable the output.
*/
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
@ -793,45 +795,34 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
if (obj->sel_width() != 1)
return;
#if 0
/*
* This is slower than the actual MUXZ so we are skipping this for now.
* If we had a half mux functor this could be faster and more compact
* so I'm leaving the code for future reference.
*/
/* If the first input is all constant Vz, then replace the
NetMux with an array of BUFIF1 devices, with the enable
NetMux with an array of NMOS devices, with the enable
connected to the select input. */
bool flag = true;
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF1);
if (obj->pin_Data(0).nexus()->drivers_constant() &&
obj->pin_Data(0).nexus()->driven_value() == verinum::Vz) {
replace_with_mos(des, obj, NetLogic::NMOS);
count += 1;
return;
}
/* If instead the second input is all constant Vz, replace the
NetMux with an array of BUFIF0 devices. */
flag = true;
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF0);
NetMux with an array of PMOS devices. */
if (obj->pin_Data(1).nexus()->drivers_constant() &&
obj->pin_Data(1).nexus()->driven_value() == verinum::Vz) {
replace_with_mos(des, obj, NetLogic::PMOS);
count += 1;
return;
}
#endif
/* If the select input is constant, then replace with a BUFZ */
flag = obj->pin_Sel().nexus()->drivers_constant();
bool flag = obj->pin_Sel().nexus()->drivers_constant();
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
@ -974,4 +965,3 @@ void cprop(Design*des)
cprop_dc_functor dc;
des->functor(&dc);
}

View File

@ -112,7 +112,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, int, bool) const
unsigned PEBinary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
ivl_variable_type_t expr_type_left = IVL_VT_NO_TYPE;
@ -155,7 +155,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
break;
case '*':
if (unsized_flag && type_is_vectorable(expr_type)) {
if (unsized_flag && type_is_vectorable(expr_type_)) {
unsigned use_wid = wid_left + wid_right;
if (use_wid > integer_width)
use_wid = integer_width;
@ -191,7 +191,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
else
expr_width_ = 1;
expr_type = expr_type_;
expr_type__ = expr_type_;
return expr_width_;
}
@ -502,7 +502,7 @@ NetExpr* PEBinary::elaborate_expr_base_lshift_(Design*des,
} else if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
long shift = rpc->value().as_long();
long use_wid = lp->expr_width();
use_wid = lp->expr_width();
if (expr_wid > 0)
use_wid = expr_wid;
@ -734,15 +734,17 @@ NetExpr* PEBinary::elaborate_expr_base_add_(Design*des,
}
unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&)
{
expr_type = IVL_VT_LOGIC;
expr_type_ = IVL_VT_LOGIC;
expr_type__ = expr_type_;
expr_width_ = 1;
return 1;
}
NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const
int expr_width_dummy, bool sys_task_arg) const
{
assert(left_);
assert(right_);
@ -793,10 +795,10 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
unsigned PEBShift::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
unsigned wid_left = left_->test_width(des,scope,min, 0, expr_type, unsized_flag);
unsigned wid_left = left_->test_width(des,scope,min, 0, expr_type__, unsized_flag);
// The right expression is self-determined and has no impact
// on the expression size that is generated.
@ -816,7 +818,22 @@ unsigned PEBShift::test_width(Design*des, NetScope*scope,
<< endl;
}
return wid_left;
expr_type_ = expr_type__;
expr_width_ = wid_left;
// Run a test-width on the shift amount so that its types are
// worked out for elaboration later on. We don't need the
// value now.
ivl_variable_type_t rtype = IVL_VT_NO_TYPE;
bool rflag = false;
unsigned wid_right = right_->test_width(des, scope, 0, 0, rtype, rflag);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Test width of shift amount of shift expression "
<< "returns wid=" << wid_right << ", type=" << rtype
<< ", flag=" << rflag << endl;
return expr_width_;
}
NetExpr*PEBShift::elaborate_expr(Design*des, NetScope*scope,
@ -839,7 +856,7 @@ NetExpr*PEBShift::elaborate_expr(Design*des, NetScope*scope,
unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
perm_string name = peek_tail_name(path_);
@ -848,12 +865,15 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
PExpr*expr = parms_[0];
if (expr == 0)
return 0;
unsigned wid = expr->test_width(des, scope, min, lval, expr_type, unsized_flag);
expr_width_ = expr->test_width(des, scope, min, lval, expr_type__, unsized_flag);
expr_type_ = expr_type__;
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width"
<< " of $signed/$unsigned returns test_width"
<< " of subexpression." << endl;
return wid;
return expr_width_;
}
// Run through the arguments of the system function and make
@ -880,7 +900,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
expr_type_ = IVL_VT_BOOL;
expr_width_= integer_width;
expr_type = expr_type_;
expr_type__ = expr_type_;
return expr_width_;
}
@ -892,7 +912,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
expr_type_ = IVL_VT_BOOL;
expr_width_ = 1;
expr_type = expr_type_;
expr_type__ = expr_type_;
return expr_width_;
}
@ -904,7 +924,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
expr_type_ = sfunc_info->type;
expr_width_ = sfunc_info->wid;
expr_type = expr_type_;
expr_type__ = expr_type_;
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width "
@ -917,11 +937,11 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
unsigned PECallFunction::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
if (peek_tail_name(path_)[0] == '$')
return test_width_sfunc_(des, scope, min, lval, expr_type, unsized_flag);
return test_width_sfunc_(des, scope, min, lval, expr_type__, unsized_flag);
// The width of user defined functions depends only on the
// width of the return value. The arguments are entirely
@ -939,17 +959,19 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope,
assert(dscope);
if (NetNet*res = dscope->find_signal(dscope->basename())) {
expr_type = res->data_type();
expr_type_ = res->data_type();
if (debug_elaborate)
cerr << get_fileline() << ": debug: test_width "
<< "of function returns width " << res->vector_width()
<< ", type=" << expr_type
<< ", type=" << expr_type_
<< "." << endl;
if (! type_is_vectorable(expr_type))
if (! type_is_vectorable(expr_type__))
unsized_flag = true;
return res->vector_width();
expr_width_ = res->vector_width();
expr_type__ = expr_type_;
return expr_width_;
}
ivl_assert(*this, 0);
@ -1265,6 +1287,21 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
unsigned PEConcat::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
expr_type_ = IVL_VT_LOGIC;
if (debug_elaborate)
cerr << get_fileline() << ": debug: CONCAT MISSING TEST_WIDTH!" << endl;
expr_type__ = expr_type_;
unsized_flag = false;
return 0;
}
// Keep track of the concatenation/repeat depth.
static int concat_depth = 0;
@ -1379,14 +1416,14 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
*/
unsigned PEFNumber::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
expr_type_ = IVL_VT_REAL;
expr_width_ = 1;
unsized_flag = true;
expr_type = expr_type_;
expr_type__ = expr_type_;
return 1;
}
@ -1540,7 +1577,7 @@ bool PEIdent::calculate_param_range_(Design*des, NetScope*scope,
unsigned PEIdent::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
NetNet* net = 0;
@ -1551,11 +1588,6 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
symbol_search(des, scope, path_, net, par, eve, ex1, ex2);
if (net != 0)
expr_type_ = net->data_type();
expr_type = expr_type;
// If there is a part/bit select expression, then process it
// here. This constrains the results no matter what kind the
// name is.
@ -1591,14 +1623,18 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
ivl_assert(*this, 0);
}
if (use_width != UINT_MAX)
return max(use_width, min);
if (use_width != UINT_MAX) {
expr_type_ = IVL_VT_LOGIC; // Assume bit/parts selects are logic
expr_width_ = max(use_width, min);
expr_type__ = expr_type_;
return expr_width_;
}
// The width of a signal expression is the width of the signal.
if (net != 0) {
expr_type_ = net->data_type();
expr_width_= max(net->vector_width(), (unsigned long)min);
expr_type = expr_type_;
expr_type__ = expr_type_;
return expr_width_;
}
@ -1607,7 +1643,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
// width is undefined.
if (par != 0) {
expr_type_ = par->expr_type();
expr_type = expr_type_;
expr_type__ = expr_type_;
if (ex1) {
ivl_assert(*this, ex2);
const NetEConst*ex1_const = dynamic_cast<const NetEConst*> (ex1);
@ -1624,7 +1660,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
}
// This is a parameter. If it is sized (meaning it was
// declared with range expresions) then the range
// declared with range expressions) then the range
// expressions would have been caught above. So if we
// got there there we know this is an unsized constant.
expr_width_ = par->expr_width();
@ -1632,7 +1668,12 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
return expr_width_;
}
// Not a net, and not a parameter? Give up on the type, but
// set the width that we collected.
expr_type_ = IVL_VT_NO_TYPE;
expr_width_ = min;
expr_type__ = expr_type_;
return min;
}
@ -2070,10 +2111,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
rb = verinum::V0;
}
NetEConst*re = new NetEConst(verinum(rb, 1));
NetEConst*re2 = new NetEConst(verinum(rb, 1));
delete tmp;
delete mtmp;
tmp = re;
tmp = re2;
} else {
@ -2487,7 +2528,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
unsigned PENumber::test_width(Design*, NetScope*,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
expr_type_ = IVL_VT_LOGIC;
@ -2501,13 +2542,13 @@ unsigned PENumber::test_width(Design*, NetScope*,
if (lval > 0 && lval < use_wid)
use_wid = lval;
expr_type = expr_type_;
expr_type__ = expr_type_;
expr_width_ = use_wid;
return use_wid;
}
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const
int expr_width__, bool) const
{
assert(value_);
verinum tvalue = *value_;
@ -2516,10 +2557,10 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*,
// specific size (for example this is part of the r-values of
// an assignment) so we pad to the desired width and ignore
// the self-determined size.
if (expr_width > 0) {
tvalue = pad_to_width(tvalue, expr_width);
if (tvalue.len() > (unsigned)expr_width) {
verinum tmp (tvalue, expr_width);
if (expr_width__ > 0) {
tvalue = pad_to_width(tvalue, expr_width__);
if (tvalue.len() > (unsigned)expr_width__) {
verinum tmp (tvalue, expr_width__);
tmp.has_sign(tvalue.has_sign());
tvalue = tmp;
}
@ -2532,19 +2573,20 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*,
unsigned PEString::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
expr_type = IVL_VT_BOOL;
unsigned use_wid = text_? 8*strlen(text_) : 0;
if (min > use_wid)
use_wid = min;
expr_type_ = IVL_VT_BOOL;
expr_width_ = text_? 8*strlen(text_) : 0;
if (min > expr_width_)
expr_width_ = min;
return use_wid;
expr_type__ = expr_type_;
return expr_width_;
}
NetEConst* PEString::elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const
int expr_width_dummy, bool) const
{
NetEConst*tmp = new NetEConst(value());
tmp->set_line(*this);
@ -2553,9 +2595,15 @@ NetEConst* PEString::elaborate_expr(Design*des, NetScope*,
unsigned PETernary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&flag)
{
// The condition of the ternary is self-determined, but we
// test its width to force its type to be calculated.
ivl_variable_type_t con_type = IVL_VT_NO_TYPE;
bool con_flag = false;
expr_->test_width(des, scope, 0, 0, con_type, con_flag);
ivl_variable_type_t tru_type = IVL_VT_NO_TYPE;
unsigned tru_wid = tru_->test_width(des, scope, min, lval, tru_type,flag);
@ -2583,7 +2631,7 @@ unsigned PETernary::test_width(Design*des, NetScope*scope,
expr_width_ = max(tru_wid,fal_wid);
expr_type = expr_type_;
expr_type__ = expr_type_;
return expr_width_;
}
@ -2626,7 +2674,9 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
cerr << get_fileline() << ": debug: "
<< "Self-sized ternary chooses wid="<< use_wid
<< ", type=" << expr_type()
<< ", expr=" << *this
<< endl;
ivl_assert(*this, use_wid > 0);
}
@ -2711,22 +2761,31 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
unsigned PEUnary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
ivl_variable_type_t&expr_type__,
bool&unsized_flag)
{
switch (op_) {
case '!':
case '&':
case '&': // Reduction AND
case '|': // Reduction OR
case '^': // Reduction XOR
case 'A': // Reduction NAND (~&)
case 'N': // Reduction NOR (~|)
case 'X': // Reduction NXOR (~^)
expr_type = IVL_VT_LOGIC;
return 1;
{
ivl_variable_type_t sub_type = IVL_VT_NO_TYPE;
bool flag = false;
expr_->test_width(des, scope, 0, 0, sub_type, flag);
expr_type_ = sub_type;
ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
}
expr_width_ = 1;
expr_type__ = expr_type_;
return expr_width_;
}
unsigned test_wid = expr_->test_width(des, scope, min, lval, expr_type, unsized_flag);
unsigned test_wid = expr_->test_width(des, scope, min, lval, expr_type__, unsized_flag);
switch (op_) {
// For these operators, the act of padding to the
// minimum width can have an important impact on the
@ -2740,6 +2799,8 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope,
break;
}
expr_type_ = expr_type__;
expr_width_ = test_wid;
return test_wid;
}
@ -2803,11 +2864,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
tmp->set_line(*this);
delete ip;
} else if (NetECReal*ipc = dynamic_cast<NetECReal*>(ip)) {
} else if (NetECReal*ipr = dynamic_cast<NetECReal*>(ip)) {
/* When taking the - of a real, fold this into the
constant value. */
verireal val = - ipc->value();
verireal val = - ipr->value();
tmp = new NetECReal(val);
tmp->set_line( *ip );
delete ip;

View File

@ -251,6 +251,27 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
lidx = tmpx;
}
/* Warn about an indexed part select that is out of range. */
if (midx >= (long)sig->vector_width() || lidx < 0) {
cerr << get_fileline() << ": warning: Indexed part "
"select " << sig->name();
if (sig->array_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << midx_val;
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] is out of range." << endl;
}
/* This is completely out side the signal so just skip it. */
if (lidx >= (long)sig->vector_width() || midx < 0) {
return false;
}
break;
}
@ -275,16 +296,24 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
des->errors += 1;
}
/* Detect a part select out of range. */
/* Warn about a part select that is out of range. */
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
cerr << get_fileline() << ": warning: Part select "
<< sig->name() << "[" << msb << ":"
<< lsb << "] out of range." << endl;
<< sig->name();
if (sig->array_dimensions() > 0) {
cerr << "[]";
}
cerr << "[" << msb << ":" << lsb
<< "] is out of range." << endl;
#if 0
midx_tmp = sig->vector_width() - 1;
lidx_tmp = 0;
des->errors += 1;
#endif
}
/* This is completely out side the signal so just skip it. */
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
return false;
}
midx = midx_tmp;
@ -311,7 +340,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
midx = sig->sb_to_idx(mval->as_long());
if (midx >= (long)sig->vector_width()) {
cerr << get_fileline() << ": error: Index " << sig->name()
<< "[" << mval->as_long() << "] out of range."
<< "[" << mval->as_long() << "] is out of range."
<< endl;
des->errors += 1;
midx = 0;
@ -428,7 +457,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
long midx_tmp, lidx_tmp;
if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
return 0;
ivl_assert(*this, lidx_tmp >= 0);
if (lidx_tmp < 0) {
cerr << get_fileline() << ": sorry: part selects "
"straddling the start of signal (" << path_
<< ") are not currently supported." << endl;
des->errors += 1;
return 0;
}
midx = midx_tmp;
lidx = lidx_tmp;
}
@ -437,7 +473,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
return 0;
ivl_assert(*this, lidx_tmp >= 0);
if (lidx_tmp < 0) {
cerr << get_fileline() << ": sorry: part selects "
"straddling the start of signal (" << path_
<< ") are not currently supported." << endl;
des->errors += 1;
return 0;
}
midx = midx_tmp;
lidx = lidx_tmp;
}

View File

@ -1295,7 +1295,25 @@ v NOTE that this also handles the case that the
if ((instance.count() == 1)
&& (prts_vector_width != sig->vector_width())) {
const char *tmp3 = rmod->ports[idx]->name.str();
bool as_signed = false;
if (tmp3 == 0) tmp3 = "???";
switch (prts[0]->port_type()) {
case NetNet::POUTPUT:
as_signed = prts[0]->get_signed();
break;
case NetNet::PINPUT:
as_signed = sig->get_signed();
break;
case NetNet::PINOUT:
/* This may not be correct! */
as_signed = prts[0]->get_signed() && sig->get_signed();
break;
default:
ivl_assert(*this, 0);
}
cerr << get_fileline() << ": warning: Port " << (idx+1)
<< " (" << tmp3 << ") of "
<< type_ << " expects " << prts_vector_width <<
@ -1316,21 +1334,21 @@ v NOTE that this also handles the case that the
}
// Keep the if, but delete the "} else" when fixed.
} else if (prts_vector_width > sig->vector_width()) {
cerr << get_fileline() << ": : Padding "
<< (prts_vector_width-sig->vector_width())
cerr << get_fileline() << ": : Padding ";
if (as_signed) cerr << "(signed) ";
cerr << (prts_vector_width-sig->vector_width())
<< " high bits of the port."
<< endl;
} else {
cerr << get_fileline() << ": : Padding "
<< (sig->vector_width()-prts_vector_width)
cerr << get_fileline() << ": : Padding ";
if (as_signed) cerr << "(signed) ";
cerr << (sig->vector_width()-prts_vector_width)
<< " high bits of the expression."
<< endl;
}
sig = resize_net_to_port_(des, scope, sig, prts_vector_width,
prts[0]->port_type(),
prts[0]->get_signed() &&
sig->get_signed());
prts[0]->port_type(), as_signed);
}
// Connect the sig expression that is the context of the
@ -2220,6 +2238,16 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: Elaborate condition statement"
<< " with conditional: " << *expr_ << endl;
// Run a test-width on the condition so that its types are
// worked out for elaboration later on.
ivl_variable_type_t rtype = IVL_VT_NO_TYPE;
bool rflag = false;
unsigned expr_wid = expr_->test_width(des, scope, 0, 0, rtype, rflag);
if (debug_elaborate)
cerr << get_fileline() << ": debug: Test width of condition expression"
<< " returns wid=" << expr_wid << ", type=" << rtype
<< ", flag=" << rflag << endl;
// Elaborate and try to evaluate the conditional expression.
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
@ -2232,7 +2260,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
// If the condition of the conditional statement is constant,
// then look at the value and elaborate either the if statement
// or the else statement. I don't need both. If there is no
// else_ statement, the use an empty block as a noop.
// else_ statement, then use an empty block as a noop.
if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) {
verinum val = ce->value();
if (debug_elaborate) {
@ -2432,9 +2460,9 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
NetUTask*cur;
/* Handle tasks with no parameters specially. There is no need
to make a sequential block to hold the generated code. */
if (nparms() == 0) {
/* Handle non-automatic tasks with no parameters specially. There is
no need to make a sequential block to hold the generated code. */
if ((nparms() == 0) && !task->is_auto()) {
cur = new NetUTask(task);
cur->set_line(*this);
return cur;
@ -2825,7 +2853,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
assert(expr_[idx]->expr());
/* If the expression is an identifier that matches a
named event, then handle this case all at once at
named event, then handle this case all at once and
skip the rest of the expression handling. */
if (PEIdent*id = dynamic_cast<PEIdent*>(expr_[idx]->expr())) {

View File

@ -254,7 +254,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
//
// Note 2: The operand expressions may be signed even if the
// sig that comes out of synthesis is unsigned. The $signed()
// function markes the expression but doesn't change the
// function marks the expression but doesn't change the
// underlying signals.
bool signed_compare = left_->has_sign() && right_->has_sign();
if (debug_elaborate) {
@ -945,7 +945,7 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
* for us:
*
* - Expression elaboration already converted the offset expression into
* cannonical form, so we don't have to worry about that here.
* canonical form, so we don't have to worry about that here.
*/
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
{

View File

@ -2309,9 +2309,9 @@ generate_case_items
;
generate_case_item
: expression ':' { pform_generate_case_item(@1, $1); } generate_block
: expression ':' { pform_generate_case_item(@1, $1); } generate_block_opt
{ pform_endgenerate(); }
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block_opt
{ pform_endgenerate(); }
;

View File

@ -257,13 +257,13 @@ void dll_target::expr_const(const NetEConst*net)
void dll_target::expr_param(const NetEConstParam*net)
{
ivl_scope_t scope = find_scope(des_, net->scope());
ivl_parameter_t par = scope_find_param(scope, net->name());
ivl_scope_t scop = find_scope(des_, net->scope());
ivl_parameter_t par = scope_find_param(scop, net->name());
if (par == 0) {
cerr << net->get_fileline() << ": internal error: "
<< "Parameter " << net->name() << " missing from "
<< ivl_scope_name(scope) << endl;
<< ivl_scope_name(scop) << endl;
}
assert(par);
assert(par->value);

View File

@ -85,7 +85,7 @@ bool dll_target::process(const NetProcTop*net)
void dll_target::task_def(const NetScope*net)
{
ivl_scope_t scope = lookup_scope_(net);
ivl_scope_t scop = lookup_scope_(net);
const NetTaskDef*def = net->task_def();
assert(stmt_cur_ == 0);
@ -94,14 +94,14 @@ void dll_target::task_def(const NetScope*net)
def->proc()->emit_proc(this);
assert(stmt_cur_);
scope->def = stmt_cur_;
scop->def = stmt_cur_;
stmt_cur_ = 0;
}
bool dll_target::func_def(const NetScope*net)
{
ivl_scope_t scope = lookup_scope_(net);
ivl_scope_t scop = lookup_scope_(net);
const NetFuncDef*def = net->func_def();
assert(stmt_cur_ == 0);
@ -110,14 +110,14 @@ bool dll_target::func_def(const NetScope*net)
def->proc()->emit_proc(this);
assert(stmt_cur_);
scope->def = stmt_cur_;
scop->def = stmt_cur_;
stmt_cur_ = 0;
scope->ports = def->port_count() + 1;
if (scope->ports > 0) {
scope->port = new ivl_signal_t[scope->ports];
for (unsigned idx = 1 ; idx < scope->ports ; idx += 1)
scope->port[idx] = find_signal(des_, def->port(idx-1));
scop->ports = def->port_count() + 1;
if (scop->ports > 0) {
scop->port = new ivl_signal_t[scop->ports];
for (unsigned idx = 1 ; idx < scop->ports ; idx += 1)
scop->port[idx] = find_signal(des_, def->port(idx-1));
}
/* FIXME: the ivl_target API expects port-0 to be the output
@ -126,7 +126,7 @@ bool dll_target::func_def(const NetScope*net)
this, but that will break code generators that use this
result. */
if (const NetNet*ret_sig = def->return_sig()) {
scope->port[0] = find_signal(des_, ret_sig);
scop->port[0] = find_signal(des_, ret_sig);
return true;
}

160
t-dll.cc
View File

@ -469,15 +469,15 @@ ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
* ivl_parameter_t objects. This involves saving the name and scanning
* the expression value.
*/
void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net)
void dll_target::make_scope_parameters(ivl_scope_t scop, const NetScope*net)
{
scope->nparam_ = net->parameters.size() + net->localparams.size();
if (scope->nparam_ == 0) {
scope->param_ = 0;
scop->nparam_ = net->parameters.size() + net->localparams.size();
if (scop->nparam_ == 0) {
scop->param_ = 0;
return;
}
scope->param_ = new struct ivl_parameter_s [scope->nparam_];
scop->param_ = new struct ivl_parameter_s [scop->nparam_];
unsigned idx = 0;
typedef map<perm_string,NetScope::param_expr_t>::const_iterator pit_t;
@ -485,10 +485,10 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net)
for (pit_t cur_pit = net->parameters.begin()
; cur_pit != net->parameters.end() ; cur_pit ++) {
assert(idx < scope->nparam_);
ivl_parameter_t cur_par = scope->param_ + idx;
assert(idx < scop->nparam_);
ivl_parameter_t cur_par = scop->param_ + idx;
cur_par->basename = (*cur_pit).first;
cur_par->scope = scope;
cur_par->scope = scop;
cur_par->file = (*cur_pit).second.get_file();
cur_par->lineno = (*cur_pit).second.get_lineno();
@ -499,10 +499,10 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net)
for (pit_t cur_pit = net->localparams.begin()
; cur_pit != net->localparams.end() ; cur_pit ++) {
assert(idx < scope->nparam_);
ivl_parameter_t cur_par = scope->param_ + idx;
assert(idx < scop->nparam_);
ivl_parameter_t cur_par = scop->param_ + idx;
cur_par->basename = (*cur_pit).first;
cur_par->scope = scope;
cur_par->scope = scop;
cur_par->file = (*cur_pit).second.get_file();
cur_par->lineno = (*cur_pit).second.get_lineno();
@ -530,9 +530,9 @@ void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp)
assert(0);
}
} else if (const NetECReal*e = dynamic_cast<const NetECReal*>(etmp)) {
} else if (const NetECReal*er = dynamic_cast<const NetECReal*>(etmp)) {
expr_creal(e);
expr_creal(er);
assert(expr_);
assert(expr_->type_ == IVL_EX_REALNUM);
expr_->u_.real_.parameter = cur_par;
@ -550,7 +550,7 @@ void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp)
expr_ = 0;
}
void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
void dll_target::add_root(ivl_design_s &des__, const NetScope *s)
{
ivl_scope_t root_ = new struct ivl_scope_s;
perm_string name = s->basename();
@ -577,12 +577,12 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
root_->attr = fill_in_attributes(s);
root_->is_auto = 0;
des_.nroots_++;
if (des_.roots_)
des_.roots_ = (ivl_scope_t *)realloc(des_.roots_, des_.nroots_ * sizeof(ivl_scope_t));
des__.nroots_++;
if (des__.roots_)
des__.roots_ = (ivl_scope_t *)realloc(des__.roots_, des__.nroots_ * sizeof(ivl_scope_t));
else
des_.roots_ = (ivl_scope_t *)malloc(des_.nroots_ * sizeof(ivl_scope_t));
des_.roots_[des_.nroots_ - 1] = root_;
des__.roots_ = (ivl_scope_t *)malloc(des__.nroots_ * sizeof(ivl_scope_t));
des__.roots_[des__.nroots_ - 1] = root_;
}
bool dll_target::start_design(const Design*des)
@ -615,9 +615,9 @@ bool dll_target::start_design(const Design*des)
des_.roots_ = NULL;
root_scopes = des->find_root_scopes();
for (list<NetScope*>::const_iterator scope = root_scopes.begin();
scope != root_scopes.end(); scope++)
add_root(des_, *scope);
for (list<NetScope*>::const_iterator scop = root_scopes.begin();
scop != root_scopes.end(); scop++)
add_root(des_, *scop);
des_.consts = (ivl_net_const_t*)
malloc(sizeof(ivl_net_const_t));
@ -848,17 +848,17 @@ bool dll_target::bufz(const NetBUFZ*net)
/* Attach the logic device to the scope that contains it. */
assert(net->scope());
ivl_scope_t scope = find_scope(des_, net->scope());
assert(scope);
ivl_scope_t scop = find_scope(des_, net->scope());
assert(scop);
obj->scope_ = scope;
obj->scope_ = scop;
obj->name_ = net->name();
logic_attributes(obj, net);
make_logic_delays_(obj, net);
scope_add_logic(scope, obj);
scope_add_logic(scop, obj);
return true;
}
@ -867,10 +867,10 @@ void dll_target::event(const NetEvent*net)
{
struct ivl_event_s *obj = new struct ivl_event_s;
ivl_scope_t scope = find_scope(des_, net->scope());
ivl_scope_t scop = find_scope(des_, net->scope());
obj->name = net->name();
obj->scope = scope;
scope_add_event(scope, obj);
obj->scope = scop;
scope_add_event(scop, obj);
obj->nany = 0;
obj->nneg = 0;
@ -1029,17 +1029,17 @@ void dll_target::logic(const NetLogic*net)
}
assert(net->scope());
ivl_scope_t scope = find_scope(des_, net->scope());
assert(scope);
ivl_scope_t scop = find_scope(des_, net->scope());
assert(scop);
obj->scope_= scope;
obj->scope_= scop;
obj->name_ = net->name();
logic_attributes(obj, net);
make_logic_delays_(obj, net);
scope_add_logic(scope, obj);
scope_add_logic(scop, obj);
}
bool dll_target::tran(const NetTran*net)
@ -1377,10 +1377,10 @@ void dll_target::udp(const NetUDP*net)
}
assert(net->scope());
ivl_scope_t scope = find_scope(des_, net->scope());
assert(scope);
ivl_scope_t scop = find_scope(des_, net->scope());
assert(scop);
obj->scope_= scope;
obj->scope_= scop;
obj->name_ = net->name();
make_logic_delays_(obj, net);
@ -1388,7 +1388,7 @@ void dll_target::udp(const NetUDP*net)
obj->nattr = 0;
obj->attr = 0;
scope_add_logic(scope, obj);
scope_add_logic(scop, obj);
}
void dll_target::lpm_abs(const NetAbs*net)
@ -2293,81 +2293,81 @@ void dll_target::net_probe(const NetEvProbe*net)
void dll_target::scope(const NetScope*net)
{
ivl_scope_t scope;
ivl_scope_t scop;
if (net->parent() == 0) {
unsigned i;
scope = NULL;
for (i = 0; i < des_.nroots_ && scope == NULL; i++) {
scop = NULL;
for (i = 0; i < des_.nroots_ && scop == NULL; i++) {
if (strcmp(des_.roots_[i]->name_, net->basename()) == 0)
scope = des_.roots_[i];
scop = des_.roots_[i];
}
assert(scope);
assert(scop);
} else {
perm_string sname = make_scope_name(net->fullname());
scope = new struct ivl_scope_s;
scope->name_ = sname;
FILE_NAME(scope, net);
scope->child_ = 0;
scope->sibling_ = 0;
scope->parent = find_scope(des_, net->parent());
assert(scope->parent);
scope->nsigs_ = 0;
scope->sigs_ = 0;
scope->nlog_ = 0;
scope->log_ = 0;
scope->nevent_ = 0;
scope->event_ = 0;
scope->nlpm_ = 0;
scope->lpm_ = 0;
scope->def = 0;
make_scope_parameters(scope, net);
scope->time_precision = net->time_precision();
scope->time_units = net->time_unit();
scope->nattr = net->attr_cnt();
scope->attr = fill_in_attributes(net);
scope->is_auto = net->is_auto();
scop = new struct ivl_scope_s;
scop->name_ = sname;
FILE_NAME(scop, net);
scop->child_ = 0;
scop->sibling_ = 0;
scop->parent = find_scope(des_, net->parent());
assert(scop->parent);
scop->nsigs_ = 0;
scop->sigs_ = 0;
scop->nlog_ = 0;
scop->log_ = 0;
scop->nevent_ = 0;
scop->event_ = 0;
scop->nlpm_ = 0;
scop->lpm_ = 0;
scop->def = 0;
make_scope_parameters(scop, net);
scop->time_precision = net->time_precision();
scop->time_units = net->time_unit();
scop->nattr = net->attr_cnt();
scop->attr = fill_in_attributes(net);
scop->is_auto = net->is_auto();
switch (net->type()) {
case NetScope::MODULE:
scope->type_ = IVL_SCT_MODULE;
scope->tname_ = net->module_name();
scop->type_ = IVL_SCT_MODULE;
scop->tname_ = net->module_name();
break;
case NetScope::TASK: {
const NetTaskDef*def = net->task_def();
if (def == 0) {
cerr << "?:?" << ": internal error: "
<< "task " << scope->name_
<< "task " << scop->name_
<< " has no definition." << endl;
}
assert(def);
scope->type_ = IVL_SCT_TASK;
scope->tname_ = def->scope()->basename();
scop->type_ = IVL_SCT_TASK;
scop->tname_ = def->scope()->basename();
break;
}
case NetScope::FUNC:
scope->type_ = IVL_SCT_FUNCTION;
scope->tname_ = net->func_def()->scope()->basename();
scop->type_ = IVL_SCT_FUNCTION;
scop->tname_ = net->func_def()->scope()->basename();
break;
case NetScope::BEGIN_END:
scope->type_ = IVL_SCT_BEGIN;
scope->tname_ = scope->name_;
scop->type_ = IVL_SCT_BEGIN;
scop->tname_ = scop->name_;
break;
case NetScope::FORK_JOIN:
scope->type_ = IVL_SCT_FORK;
scope->tname_ = scope->name_;
scop->type_ = IVL_SCT_FORK;
scop->tname_ = scop->name_;
break;
case NetScope::GENBLOCK:
scope->type_ = IVL_SCT_GENERATE;
scope->tname_ = scope->name_;
scop->type_ = IVL_SCT_GENERATE;
scop->tname_ = scop->name_;
break;
}
assert(scope->parent != 0);
assert(scop->parent != 0);
scope->sibling_= scope->parent->child_;
scope->parent->child_ = scope;
scop->sibling_= scop->parent->child_;
scop->parent->child_ = scop;
}
}

View File

@ -407,8 +407,8 @@ bits.
5: (reserved)
6: (reserved)
* %ix/getv <functor-label>, <bit>
* %ix/getv/s <functor-label>, <bit>
* %ix/getv <idx>, <functor-label>
* %ix/getv/s <idx>, <functor-label>
These instructions are like the %ix/get instructions, except that they
read directly from a functor label instead of from thread bits. They

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2008 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
@ -49,7 +49,7 @@ void resolv_functor::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
for (unsigned idx = 0 ; idx < base ; idx += 1)
res.set_bit(idx, BIT4_Z);
for (unsigned idx = 0 ; idx < wid ; idx += 1)
for (unsigned idx = 0 ; idx < wid && idx+base < vwid; idx += 1)
res.set_bit(idx+base, bit.value(idx));
for (unsigned idx = base+wid ; idx < vwid ; idx += 1)
@ -106,7 +106,7 @@ void resolv_functor::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
for (unsigned idx = 0 ; idx < base ; idx += 1)
res.set_bit(idx, vvp_scalar_t());
for (unsigned idx = 0 ; idx < wid ; idx += 1)
for (unsigned idx = 0 ; idx < wid && idx+base < vwid; idx += 1)
res.set_bit(idx+base, bit.value(idx));
for (unsigned idx = base+wid ; idx < vwid ; idx += 1)