Merge branch 'x-mil11'

This commit is contained in:
Stephen Williams 2013-10-21 08:55:13 -07:00
commit 61fbfb562e
38 changed files with 864 additions and 83 deletions

View File

@ -94,6 +94,25 @@ const char* PExpr::width_mode_name(width_mode_t mode)
} }
} }
PEAssignPattern::PEAssignPattern()
{
}
PEAssignPattern::PEAssignPattern(const list<PExpr*>&p)
: parms_(p.size())
{
size_t idx = 0;
for (list<PExpr*>::const_iterator cur = p.begin()
; cur != p.end() ; ++cur) {
parms_[idx] = *cur;
idx += 1;
}
}
PEAssignPattern::~PEAssignPattern()
{
}
PEBinary::PEBinary(char op, PExpr*l, PExpr*r) PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r) : op_(op), left_(l), right_(r)
{ {
@ -417,12 +436,12 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
return false; return false;
} }
PENew::PENew(PExpr*size_expr) PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr)
: size_(size_expr) : size_(size_expr), init_(init_expr)
{ {
} }
PENew::~PENew() PENewArray::~PENewArray()
{ {
delete size_; delete size_;
} }

37
PExpr.h
View File

@ -194,6 +194,29 @@ class PExpr : public LineInfo {
ostream& operator << (ostream&, const PExpr&); ostream& operator << (ostream&, const PExpr&);
class PEAssignPattern : public PExpr {
public:
explicit PEAssignPattern();
explicit PEAssignPattern(const std::list<PExpr*>&p);
~PEAssignPattern();
void dump(std::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;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
private:
NetExpr* elaborate_expr_darray_(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
private:
std::vector<PExpr*>parms_;
};
class PEConcat : public PExpr { class PEConcat : public PExpr {
public: public:
@ -279,6 +302,8 @@ class PEFNumber : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode); width_mode_t&mode);
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned expr_wid,
unsigned flags) const; unsigned flags) const;
@ -479,11 +504,11 @@ class PEIdent : public PExpr {
long&midx, long&lidx) const; long&midx, long&lidx) const;
}; };
class PENew : public PExpr { class PENewArray : public PExpr {
public: public:
explicit PENew (PExpr*s); explicit PENewArray (PExpr*s, PExpr*i);
~PENew(); ~PENewArray();
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
@ -496,6 +521,7 @@ class PENew : public PExpr {
private: private:
PExpr*size_; PExpr*size_;
PExpr*init_;
}; };
class PENewClass : public PExpr { class PENewClass : public PExpr {
@ -570,7 +596,7 @@ class PENumber : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode); width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*scope, virtual NetExpr *elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const; ivl_type_t type, unsigned flags) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned) const; unsigned expr_wid, unsigned) const;
@ -606,6 +632,9 @@ class PEString : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope, virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode); width_mode_t&mode);
virtual NetEConst*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*, virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned) const; unsigned expr_wid, unsigned) const;
verinum* eval_const(Design*, NetScope*) const; verinum* eval_const(Design*, NetScope*) const;

View File

@ -105,8 +105,9 @@ class PAssign_ : public Statement {
protected: protected:
NetAssign_* elaborate_lval(Design*, NetScope*scope) const; NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width, NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
ivl_variable_type_t type) const; ivl_variable_type_t lv_type,
unsigned lv_width) const;
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const; NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
NetExpr* elaborate_rval_obj_(Design*, NetScope*, NetExpr* elaborate_rval_obj_(Design*, NetScope*,

View File

@ -1410,6 +1410,19 @@ void NetEAccess::dump(ostream&o) const
o << ")"; o << ")";
} }
void NetEArrayPattern::dump(ostream&fd) const
{
fd << "'{";
if (items_.size() >= 1) {
if (items_[0]) fd << *items_[0];
}
for (size_t idx = 1 ; idx < items_.size() ; idx += 1) {
fd << ", ";
if (items_[idx]) fd << *items_[idx];
}
fd << "}";
}
void NetEBinary::dump(ostream&o) const void NetEBinary::dump(ostream&o) const
{ {
if (op_ == 'm' || op_ == 'M') { if (op_ == 'm' || op_ == 'M') {
@ -1549,7 +1562,14 @@ void NetENetenum::dump(ostream&o) const
void NetENew::dump(ostream&o) const void NetENew::dump(ostream&o) const
{ {
o << "new <type>"; o << "new <type> [";
if (size_) size_->dump(o);
o << "]";
if (init_val_) {
o << "(";
init_val_->dump(o);
o << ")";
}
} }
void NetENull::dump(ostream&o) const void NetENull::dump(ostream&o) const

View File

@ -32,6 +32,17 @@ NetEAccess* NetEAccess::dup_expr() const
return tmp; return tmp;
} }
NetEArrayPattern*NetEArrayPattern::dup_expr() const
{
vector<NetExpr*>tmp (items_.size());
for (size_t idx = 0 ; idx < tmp.size() ; idx += 1)
tmp[idx] = items_[idx]->dup_expr();
NetEArrayPattern*res = new NetEArrayPattern(net_type(), tmp);
res->set_line(*this);
return res;
}
NetEBinary* NetEBinary::dup_expr() const NetEBinary* NetEBinary::dup_expr() const
{ {
ivl_assert(*this, 0); ivl_assert(*this, 0);

View File

@ -86,15 +86,34 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
return 0; return 0;
} }
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
ivl_variable_type_t lv_type, unsigned lv_width, ivl_variable_type_t lv_type, unsigned lv_width,
PExpr*expr, bool need_const) PExpr*expr, bool need_const)
{ {
if (debug_elaborate) {
cerr << expr->get_fileline() << ": elaborate_rval_expr: "
<< "expr=" << *expr;
if (lv_net_type)
cerr << ", lv_net_type=" << *lv_net_type;
else
cerr << ", lv_net_type=<nil>";
cerr << ", lv_type=" << lv_type
<< ", lv_width=" << lv_width
<< endl;
}
int context_wid = -1; int context_wid = -1;
switch (lv_type) { switch (lv_type) {
case IVL_VT_DARRAY:
// For these types, use a different elab_and_eval that
// uses the lv_net_type. We should eventually transition
// all the types to this new form.
if (lv_net_type)
return elab_and_eval(des, scope, expr, lv_net_type, need_const);
break;
case IVL_VT_REAL: case IVL_VT_REAL:
case IVL_VT_STRING: case IVL_VT_STRING:
case IVL_VT_DARRAY:
break; break;
case IVL_VT_BOOL: case IVL_VT_BOOL:
case IVL_VT_LOGIC: case IVL_VT_LOGIC:
@ -163,6 +182,76 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
return 0; return 0;
} }
/*
* For now, assuse that assignment patterns are for dynamic
* objects. This is not really true as this expression type, fully
* 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)
{
expr_type_ = IVL_VT_DARRAY;
expr_width_ = 1;
min_width_ = 1;
signed_flag_= false;
return 1;
}
NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned flags) const
{
// Special case: If this is an empty pattern (i.e. '{}) and
// the expected type is a DARRAY, then convert this to a null
// handle. Internally, Icarus Verilog uses this to represent
// nil dynamic arrays.
if (parms_.size() == 0 && ntype->base_type()==IVL_VT_DARRAY) {
NetENull*tmp = new NetENull;
tmp->set_line(*this);
return tmp;
}
if (ntype->base_type()==IVL_VT_DARRAY)
return elaborate_expr_darray_(des, scope, ntype, flags);
cerr << get_fileline() << ": sorry: I don't know how to elaborate "
<< "assignment_pattern expressions yet." << endl;
cerr << get_fileline() << ": : Expression is: " << *this
<< endl;
des->errors += 1;
return 0;
}
NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned flags) const
{
const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype);
ivl_assert(*this, array_type);
// This is an array pattern, so run through the elements of
// the expression and elaborate each as if they are
// element_type expressions.
ivl_type_t elem_type = array_type->element_type();
vector<NetExpr*> elem_exprs (parms_.size());
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags);
elem_exprs[idx] = tmp;
}
NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs);
res->set_line(*this);
return res;
}
NetExpr* PEAssignPattern::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
{
cerr << get_fileline() << ": sorry: I do not know how to"
<< " elaborate assignment patterns using old method." << endl;
cerr << get_fileline() << ": : Expression is: " << *this
<< endl;
des->errors += 1;
ivl_assert(*this, 0);
return 0;
}
unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode) unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
{ {
@ -1524,7 +1613,8 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
// Process the method argument if it is available. // Process the method argument if it is available.
NetExpr* count = 0; NetExpr* count = 0;
if (args != 0 && parg) { if (args != 0 && parg) {
count = elaborate_rval_expr(des, scope, IVL_VT_BOOL, 32, parg); count = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
IVL_VT_BOOL, 32, parg);
if (count == 0) { if (count == 0) {
cerr << li->get_fileline() << ": error: unable to elaborate " cerr << li->get_fileline() << ": error: unable to elaborate "
"enumeration method argument " << use_path << "." "enumeration method argument " << use_path << "."
@ -1978,7 +2068,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::elaborate_base_: " cerr << get_fileline() << ": PECallFunction::elaborate_base_: "
<< "Expecting " << parms_count << "Expecting " << parms_count
<< " for function " << scope_path(dscope) << "." << endl; << " argument for function " << scope_path(dscope) << "." << endl;
} }
/* Elaborate the input expressions for the function. This is /* Elaborate the input expressions for the function. This is
@ -2061,6 +2151,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
PExpr*tmp = parms_[idx]; PExpr*tmp = parms_[idx];
if (tmp) { if (tmp) {
parms[pidx] = elaborate_rval_expr(des, scope, parms[pidx] = elaborate_rval_expr(des, scope,
def->port(pidx)->net_type(),
def->port(pidx)->data_type(), def->port(pidx)->data_type(),
(unsigned)def->port(pidx)->vector_width(), (unsigned)def->port(pidx)->vector_width(),
tmp, need_const); tmp, need_const);
@ -2153,12 +2244,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
ivl_assert(*this, parms_.size() == 2); ivl_assert(*this, parms_.size() == 2);
NetExpr*tmp; NetExpr*tmp;
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL, tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
32, parms_[0], false); IVL_VT_BOOL, 32, parms_[0], false);
sys_expr->parm(1, tmp); sys_expr->parm(1, tmp);
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL, tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
32, parms_[1], false); IVL_VT_BOOL, 32, parms_[1], false);
sys_expr->parm(2, tmp); sys_expr->parm(2, tmp);
return sys_expr; return sys_expr;
@ -2446,6 +2537,13 @@ unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
return expr_width_; return expr_width_;
} }
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, ivl_type_t type, unsigned) const
{
NetECReal*tmp = new NetECReal(*value_);
tmp->set_line(*this);
return tmp;
}
NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
{ {
NetECReal*tmp = new NetECReal(*value_); NetECReal*tmp = new NetECReal(*value_);
@ -2902,7 +3000,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return 0; return 0;
} }
if (net->net_type() != ntype) { if (! ntype->type_compatible(net->net_type())) {
cerr << get_fileline() << ": internal_error: " cerr << get_fileline() << ": internal_error: "
<< "net type doesn't match context type." << endl; << "net type doesn't match context type." << endl;
@ -2920,7 +3018,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
ntype->debug_dump(cerr); ntype->debug_dump(cerr);
cerr << endl; cerr << endl;
} }
ivl_assert(*this, net->net_type() == ntype); ivl_assert(*this, ntype->type_compatible(net->net_type()));
NetESignal*tmp = new NetESignal(net); NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this); tmp->set_line(*this);
@ -4515,7 +4613,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
return node; return node;
} }
unsigned PENew::test_width(Design*, NetScope*, width_mode_t&) unsigned PENewArray::test_width(Design*, NetScope*, width_mode_t&)
{ {
expr_type_ = IVL_VT_DARRAY; expr_type_ = IVL_VT_DARRAY;
expr_width_ = 1; expr_width_ = 1;
@ -4524,23 +4622,41 @@ unsigned PENew::test_width(Design*, NetScope*, width_mode_t&)
return 1; return 1;
} }
NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t ntype, unsigned flags) const ivl_type_t ntype, unsigned flags) const
{ {
// Elaborate the size expression. // Elaborate the size expression.
width_mode_t mode = LOSSLESS; width_mode_t mode = LOSSLESS;
unsigned use_wid = size_->test_width(des, scope, mode); unsigned use_wid = size_->test_width(des, scope, mode);
NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags); NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags);
NetExpr*init_val = 0;
NetENew*tmp = new NetENew(ntype, size); if (dynamic_cast<PEAssignPattern*> (init_)) {
// Special case: the initial value expression is an
// array_pattern. Elaborate the expresion like the
// r-value to an assignment to array.
init_val = init_->elaborate_expr(des, scope, ntype, flags);
} else if (init_) {
// Regular case: The initial value is an
// expression. Elaborate the expression as an element
// type. The run-time will assign this value to each element.
const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype);
ivl_type_t elem_type = array_type->element_type();
init_val = init_->elaborate_expr(des, scope, elem_type, flags);
}
NetENew*tmp = new NetENew(ntype, size, init_val);
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
} }
/* /*
* This method should never actually be called. * This method should never actually be called.
*/ */
NetExpr* PENew::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const NetExpr* PENewArray::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
{ {
ivl_assert(*this, 0); ivl_assert(*this, 0);
return 0; return 0;
@ -4623,7 +4739,8 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
// While there are default arguments, check them. // While there are default arguments, check them.
if (idx <= parms_.size() && parms_[idx-1]) { if (idx <= parms_.size() && parms_[idx-1]) {
PExpr*tmp = parms_[idx-1]; PExpr*tmp = parms_[idx-1];
parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->data_type(), parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->net_type(),
def->port(idx)->data_type(),
def->port(idx)->vector_width(), def->port(idx)->vector_width(),
tmp, false); tmp, false);
if (parms[idx] == 0) if (parms[idx] == 0)
@ -4734,7 +4851,7 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
return expr_width_; return expr_width_;
} }
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const
{ {
const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype); const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype);
if (use_type == 0) { if (use_type == 0) {
@ -4745,6 +4862,15 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, uns
return 0; return 0;
} }
// Special case: If the context type is REAL, then cast the
// vector value to a real and rethrn a NetECReal.
if (ntype->base_type() == IVL_VT_REAL) {
verireal val (value_->as_long());
NetECReal*tmp = new NetECReal(val);
tmp->set_line(*this);
return tmp;
}
verinum use_val = value(); verinum use_val = value();
use_val .has_sign( use_type->get_signed() ); use_val .has_sign( use_type->get_signed() );
use_val = cast_to_width(use_val, use_type->packed_width()); use_val = cast_to_width(use_val, use_type->packed_width());
@ -4780,6 +4906,16 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
return expr_width_; return expr_width_;
} }
NetEConst* PEString::elaborate_expr(Design*, NetScope*, ivl_type_t type, unsigned)const
{
verinum val(value());
NetEConst*tmp = new NetEConst(val);
tmp->cast_signed(signed_flag_);
tmp->set_line(*this);
return tmp;
}
NetEConst* PEString::elaborate_expr(Design*, NetScope*, NetEConst* PEString::elaborate_expr(Design*, NetScope*,
unsigned expr_wid, unsigned) const unsigned expr_wid, unsigned) const
{ {

View File

@ -84,7 +84,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
<< " width=" << lval->vector_width() << endl; << " width=" << lval->vector_width() << endl;
} }
NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->data_type(), NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(),
lval->data_type(),
lval->vector_width(), pin(1)); lval->vector_width(), pin(1));
if (rval_expr == 0) { if (rval_expr == 0) {
@ -2244,13 +2245,18 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
} }
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
unsigned lv_width, ivl_type_t lv_net_type,
ivl_variable_type_t lv_type) const ivl_variable_type_t lv_type,
unsigned lv_width) const
{ {
ivl_assert(*this, rval_); ivl_assert(*this, rval_);
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(), // Don't have a good value for the lv_net_type argument to
is_constant_); // elaborate_rval_expr, so punt and pass nil. In the future we
// should look into fixing calls to this method to pass a
// net_type instead of the separate lv_width/lv_type values.
NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width,
rval(), is_constant_);
if (!is_constant_ || !rv) return rv; if (!is_constant_ || !rv) return rv;
@ -2368,7 +2374,7 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
NetAssign_*lv = elaborate_lval(des, scope); NetAssign_*lv = elaborate_lval(des, scope);
if (lv == 0) return 0; if (lv == 0) return 0;
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv));
if (rv == 0) return 0; if (rv == 0) return 0;
NetAssign*cur = new NetAssign(lv, op_, rv); NetAssign*cur = new NetAssign(lv, op_, rv);
@ -2456,7 +2462,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
} else { } else {
/* Elaborate the r-value expression, then try to evaluate it. */ /* Elaborate the r-value expression, then try to evaluate it. */
rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); rv = elaborate_rval_(des, scope, lv_net_type, lv->expr_type(), count_lval_width(lv));
} }
if (rv == 0) return 0; if (rv == 0) return 0;
@ -2648,7 +2654,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
// because it would necessarily trigger other errors. // because it would necessarily trigger other errors.
} }
NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv));
if (rv == 0) return 0; if (rv == 0) return 0;
NetExpr*delay = 0; NetExpr*delay = 0;
@ -3463,7 +3469,8 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
NetExpr*rv = 0; NetExpr*rv = 0;
if (parms_idx<parms_.size() && parms_[parms_idx]) { if (parms_idx<parms_.size() && parms_[parms_idx]) {
rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_ [parms_idx]); rv = elaborate_rval_expr(des, scope, port->net_type(),
lv_type, wid, parms_ [parms_idx]);
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) { if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
cerr << evt->get_fileline() << ": error: An event '" cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' can not be a user " << evt->event()->name() << "' can not be a user "
@ -3617,7 +3624,11 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
unsigned lwid = count_lval_width(lval); unsigned lwid = count_lval_width(lval);
ivl_variable_type_t ltype = lval->expr_type(); ivl_variable_type_t ltype = lval->expr_type();
NetExpr*rexp = elaborate_rval_expr(des, scope, ltype, lwid, expr_); // Need to figure out a better thing to do about the
// lv_net_type argument to elaborate_rval_expr here. This
// would entail getting the NetAssign_ to give us an
// ivl_type_t as needed.
NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_);
if (rexp == 0) if (rexp == 0)
return 0; return 0;
@ -4295,7 +4306,11 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
unsigned lwid = count_lval_width(lval); unsigned lwid = count_lval_width(lval);
ivl_variable_type_t ltype = lval->expr_type(); ivl_variable_type_t ltype = lval->expr_type();
NetExpr*rexp = elaborate_rval_expr(des, scope, ltype, lwid, expr_); // Like a variety of other assigns, we need to figure out a
// better way to get a reasonable lv_net_type value, and that
// probably will involve NetAssign_ having a method for
// synthesizing one as needed.
NetExpr*rexp = elaborate_rval_expr(des, scope, 0, ltype, lwid, expr_);
if (rexp == 0) if (rexp == 0)
return 0; return 0;
@ -4351,7 +4366,8 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
/* Make the r-value of the initial assignment, and size it /* Make the r-value of the initial assignment, and size it
properly. Then use it to build the assignment statement. */ properly. Then use it to build the assignment statement. */
etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(), etmp = elaborate_rval_expr(des, scope, sig->net_type(),
lv->expr_type(), lv->lwidth(),
expr1_); expr1_);
if (debug_elaborate) { if (debug_elaborate) {
@ -4566,7 +4582,8 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
unsigned long wid = res->vector_width(); unsigned long wid = res->vector_width();
NetAssign_*lv = new NetAssign_(res); NetAssign_*lv = new NetAssign_(res);
NetExpr*val = elaborate_rval_expr(des, scope, lv_type, wid, expr_); NetExpr*val = elaborate_rval_expr(des, scope, res->net_type(),
lv_type, wid, expr_);
NetBlock*proc = new NetBlock(NetBlock::SEQU, 0); NetBlock*proc = new NetBlock(NetBlock::SEQU, 0);
proc->set_line( *this ); proc->set_line( *this );

View File

@ -546,6 +546,11 @@ void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_access_func(this); tgt->expr_access_func(this);
} }
void NetEArrayPattern::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_array_pattern(this);
}
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
{ {
tgt->expr_binary(this); tgt->expr_binary(this);

View File

@ -228,6 +228,7 @@ typedef enum ivl_expr_type_e {
IVL_EX_NEW = 23, IVL_EX_NEW = 23,
IVL_EX_NULL = 22, IVL_EX_NULL = 22,
IVL_EX_NUMBER = 5, IVL_EX_NUMBER = 5,
IVL_EX_ARRAY_PATTERN = 26,
IVL_EX_PROPERTY = 24, IVL_EX_PROPERTY = 24,
IVL_EX_REALNUM = 16, IVL_EX_REALNUM = 16,
IVL_EX_SCOPE = 6, IVL_EX_SCOPE = 6,
@ -827,6 +828,16 @@ extern unsigned ivl_event_lineno(ivl_event_t net);
* table. That number can be passed to ivl_type_prop_*() functions to * table. That number can be passed to ivl_type_prop_*() functions to
* get details about the property. * get details about the property.
* *
* - IVL_EX_NEW
* This expression takes one or two operands. The first operand,
* returned by ivl_expr_oper1() is the number of elements to create
* for the dynamic array. The second operand, if present, is returned
* by the ivl_expr_oper2() function. If this returns a non-nil
* expression, it is the initial value to be written to the elements
* of the array. If the expression is an IVL_EX_ARRAY_PATTERN, then
* this is the very special case of a list of values to be written to
* array elements.
*
* - IVL_EX_SELECT * - IVL_EX_SELECT
* This expression takes two operands, oper1 is the expression to * This expression takes two operands, oper1 is the expression to
* select from, and oper2 is the selection base. The ivl_expr_width * select from, and oper2 is the selection base. The ivl_expr_width
@ -895,17 +906,17 @@ extern const char* ivl_expr_name(ivl_expr_t net);
extern ivl_nature_t ivl_expr_nature(ivl_expr_t net); extern ivl_nature_t ivl_expr_nature(ivl_expr_t net);
/* IVL_EX_BINARY IVL_EX_UNARY */ /* IVL_EX_BINARY IVL_EX_UNARY */
extern char ivl_expr_opcode(ivl_expr_t net); extern char ivl_expr_opcode(ivl_expr_t net);
/* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_TERNARY */ /* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_NEW IVL_EX_TERNARY */
extern ivl_expr_t ivl_expr_oper1(ivl_expr_t net); extern ivl_expr_t ivl_expr_oper1(ivl_expr_t net);
/* IVL_EX_BINARY IVL_EX_TERNARY */ /* IVL_EX_BINARY IVL_EX_NEW IVL_EX_TERNARY */
extern ivl_expr_t ivl_expr_oper2(ivl_expr_t net); extern ivl_expr_t ivl_expr_oper2(ivl_expr_t net);
/* IVL_EX_TERNARY */ /* IVL_EX_TERNARY */
extern ivl_expr_t ivl_expr_oper3(ivl_expr_t net); extern ivl_expr_t ivl_expr_oper3(ivl_expr_t net);
/* and expression */ /* and expression */
extern ivl_parameter_t ivl_expr_parameter(ivl_expr_t net); extern ivl_parameter_t ivl_expr_parameter(ivl_expr_t net);
/* IVL_EX_CONCAT IVL_EX_UFUNC */ /* IVL_EX_ARRAY_PATTERN IVL_EX_CONCAT IVL_EX_UFUNC */
extern ivl_expr_t ivl_expr_parm(ivl_expr_t net, unsigned idx); extern ivl_expr_t ivl_expr_parm(ivl_expr_t net, unsigned idx);
/* IVL_EX_CONCAT IVL_EX_SFUNC IVL_EX_UFUNC */ /* IVL_EX_ARRAY_PATTERN IVL_EX_CONCAT IVL_EX_SFUNC IVL_EX_UFUNC */
extern unsigned ivl_expr_parms(ivl_expr_t net); extern unsigned ivl_expr_parms(ivl_expr_t net);
/* IVL_EX_CONCAT */ /* IVL_EX_CONCAT */
extern unsigned ivl_expr_repeat(ivl_expr_t net); extern unsigned ivl_expr_repeat(ivl_expr_t net);

View File

@ -61,7 +61,10 @@ bool NetExpr::has_width() const
*/ */
ivl_variable_type_t NetExpr::expr_type() const ivl_variable_type_t NetExpr::expr_type() const
{ {
return IVL_VT_LOGIC; if (net_type_)
return net_type_->base_type();
else
return IVL_VT_LOGIC;
} }
const netenum_t*NetExpr::enumeration() const const netenum_t*NetExpr::enumeration() const
@ -69,6 +72,17 @@ const netenum_t*NetExpr::enumeration() const
return 0; return 0;
} }
NetEArrayPattern::NetEArrayPattern(ivl_type_t lv_type, vector<NetExpr*>&items)
: NetExpr(lv_type), items_(items)
{
}
NetEArrayPattern::~NetEArrayPattern()
{
for (size_t idx = 0 ; idx < items_.size() ; idx += 1)
delete items_[idx];
}
/* /*
* Create an add/sub node from the two operands. * Create an add/sub node from the two operands.
*/ */
@ -322,12 +336,12 @@ const netenum_t* NetENetenum::netenum() const
} }
NetENew::NetENew(ivl_type_t t) NetENew::NetENew(ivl_type_t t)
: obj_type_(t), size_(0) : obj_type_(t), size_(0), init_val_(0)
{ {
} }
NetENew::NetENew(ivl_type_t t, NetExpr*size) NetENew::NetENew(ivl_type_t t, NetExpr*size, NetExpr*init_val)
: obj_type_(t), size_(size) : obj_type_(t), size_(size), init_val_(init_val)
{ {
} }

View File

@ -43,6 +43,21 @@ NexusSet* NetProc::nex_input(bool)
return 0; return 0;
} }
NexusSet* NetEArrayPattern::nex_input(bool rem_out)
{
NexusSet*result = new NexusSet;
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
if (items_[idx]==0) continue;
NexusSet*tmp = items_[idx]->nex_input(rem_out);
if (tmp == 0) continue;
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetEBinary::nex_input(bool rem_out) NexusSet* NetEBinary::nex_input(bool rem_out)
{ {
NexusSet*result = left_->nex_input(rem_out); NexusSet*result = left_->nex_input(rem_out);

View File

@ -18,6 +18,7 @@
*/ */
# include "netdarray.h" # include "netdarray.h"
# include <iostream>
using namespace std; using namespace std;
@ -34,3 +35,12 @@ ivl_variable_type_t netdarray_t::base_type(void) const
{ {
return IVL_VT_DARRAY; return IVL_VT_DARRAY;
} }
bool netdarray_t::test_compatibility(ivl_type_t that) const
{
const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that);
if (that_da == 0)
return false;
return element_type()->type_compatible(that_da->element_type());
}

View File

@ -45,6 +45,7 @@ class netdarray_t : public netarray_t {
std::ostream& debug_dump(std::ostream&) const; std::ostream& debug_dump(std::ostream&) const;
private: private:
bool test_compatibility(ivl_type_t that) const;
}; };
#endif #endif

View File

@ -759,18 +759,14 @@ void NetNet::set_module_port_index(unsigned idx)
ivl_variable_type_t NetNet::data_type() const ivl_variable_type_t NetNet::data_type() const
{ {
if (net_type_==0) ivl_assert(*this, net_type_);
return IVL_VT_LOGIC; return net_type_->base_type();
else
return net_type_->base_type();
} }
bool NetNet::get_signed() const bool NetNet::get_signed() const
{ {
if (net_type_==0) ivl_assert(*this, net_type_);
return false; return net_type_->get_signed();
else
return net_type_->get_signed();
} }
bool NetNet::get_isint() const bool NetNet::get_isint() const

View File

@ -627,7 +627,7 @@ class NetNet : public NetObj, public PortType {
// now, the unpacked type is not burried into an ivl_type_s object. // now, the unpacked type is not burried into an ivl_type_s object.
explicit NetNet(NetScope*s, perm_string n, Type t, explicit NetNet(NetScope*s, perm_string n, Type t,
const std::list<netrange_t>&unpacked, const std::list<netrange_t>&unpacked,
ivl_type_t type =0); ivl_type_t type);
// This form builds a NetNet from its record/enum/darray // This form builds a NetNet from its record/enum/darray
// definition. They should probably be replaced with a single // definition. They should probably be replaced with a single
@ -1914,6 +1914,25 @@ class NetExpr : public LineInfo {
NetExpr& operator=(const NetExpr&); NetExpr& operator=(const NetExpr&);
}; };
class NetEArrayPattern : public NetExpr {
public:
NetEArrayPattern(ivl_type_t lv_type, std::vector<NetExpr*>&items);
~NetEArrayPattern();
inline size_t item_size() const { return items_.size(); }
const NetExpr* item(size_t idx) const { return items_[idx]; }
void expr_scan(struct expr_scan_t*) const;
void dump(ostream&) const;
NetEArrayPattern* dup_expr() const;
NexusSet* nex_input(bool rem_out =true);
private:
std::vector<NetExpr*> items_;
};
/* /*
* The expression constant is slightly special, and is sometimes * The expression constant is slightly special, and is sometimes
* returned from other classes that can be evaluated at compile * returned from other classes that can be evaluated at compile
@ -4011,11 +4030,12 @@ class NetENew : public NetExpr {
// Make class object // Make class object
explicit NetENew(ivl_type_t); explicit NetENew(ivl_type_t);
// dynamic array of objects. // dynamic array of objects.
explicit NetENew(ivl_type_t, NetExpr*); explicit NetENew(ivl_type_t, NetExpr*size, NetExpr* init_val=0);
~NetENew(); ~NetENew();
inline ivl_type_t get_type() const { return obj_type_; } inline ivl_type_t get_type() const { return obj_type_; }
inline const NetExpr*size_expr() const { return size_; } inline const NetExpr*size_expr() const { return size_; }
inline const NetExpr*init_expr() const { return init_val_; }
virtual ivl_variable_type_t expr_type() const; virtual ivl_variable_type_t expr_type() const;
@ -4028,6 +4048,7 @@ class NetENew : public NetExpr {
private: private:
ivl_type_t obj_type_; ivl_type_t obj_type_;
NetExpr*size_; NetExpr*size_;
NetExpr*init_val_;
}; };
/* /*

View File

@ -751,13 +751,15 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
expr_width = context_width; expr_width = context_width;
if (debug_elaborate) { if (debug_elaborate) {
cerr << pe->get_fileline() << ": debug: test_width of " cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
<< *pe << endl; << *pe << endl;
cerr << pe->get_fileline() << ": " cerr << pe->get_fileline() << ": : "
<< "returns type=" << pe->expr_type() << "returns type=" << pe->expr_type()
<< ", width=" << expr_width << ", width=" << expr_width
<< ", signed=" << pe->has_sign() << ", signed=" << pe->has_sign()
<< ", mode=" << PExpr::width_mode_name(mode) << endl; << ", mode=" << PExpr::width_mode_name(mode) << endl;
cerr << pe->get_fileline() << ": : "
<< "cast_type=" << cast_type << endl;
} }
// If we can get the same result using a smaller expression // If we can get the same result using a smaller expression
@ -807,6 +809,26 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
return tmp; return tmp;
} }
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
ivl_type_t lv_net_type, bool need_const)
{
if (debug_elaborate) {
cerr << pe->get_fileline() << ": elab_and_eval: "
<< "pe=" << *pe
<< ", lv_net_type=" << *lv_net_type << endl;
}
// Elaborate the expression using the more general
// elaborate_expr method.
unsigned flags = PExpr::NO_FLAGS;
if (need_const)
flags |= PExpr::NEED_CONST;
NetExpr*tmp = pe->elaborate_expr(des, scope, lv_net_type, flags);
return tmp;
}
NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name, NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
unsigned arg_idx, PExpr*pe, bool need_const) unsigned arg_idx, PExpr*pe, bool need_const)
{ {

View File

@ -244,6 +244,15 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
bool annotatable =false, bool annotatable =false,
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE); ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
/*
* This form of elab_and_eval uses the ivl_type_t to carry type
* information instead of the piecemeal form. We should transition to
* this form as we reasonably can.
*/
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
PExpr*expr, ivl_type_t lv_net_type,
bool need_const);
/* /*
* This function is a variant of elab_and_eval that elaborates and * This function is a variant of elab_and_eval that elaborates and
* evaluates the arguments of a system task. * evaluates the arguments of a system task.
@ -256,8 +265,14 @@ extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
* of an assignment, The lv_type and lv_width are the type and width * of an assignment, The lv_type and lv_width are the type and width
* of the l-value, and the expr is the expression to elaborate. The * of the l-value, and the expr is the expression to elaborate. The
* result is the NetExpr elaborated and evaluated. (See elab_expr.cc) * result is the NetExpr elaborated and evaluated. (See elab_expr.cc)
*
* I would rather that all calls to elaborate_rval_expr use the
* lv_net_type argument to express the l-value type, but, for now,
* that it not possible. Those cases will be indicated by the
* lv_net_type being set to nil.
*/ */
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_type_t lv_net_type,
ivl_variable_type_t lv_type, ivl_variable_type_t lv_type,
unsigned lv_width, PExpr*expr, unsigned lv_width, PExpr*expr,
bool need_const =false); bool need_const =false);

View File

@ -46,6 +46,19 @@ bool ivl_type_s::get_signed() const
return false; return false;
} }
bool ivl_type_s::type_compatible(ivl_type_t that) const
{
if (this == that)
return true;
return test_compatibility(that);
}
bool ivl_type_s::test_compatibility(const ivl_type_s*that) const
{
return false;
}
netarray_t::~netarray_t() netarray_t::~netarray_t()
{ {
} }

View File

@ -38,11 +38,23 @@ class ivl_type_s {
virtual long packed_width(void) const; virtual long packed_width(void) const;
virtual std::vector<netrange_t> slice_dimensions() const; virtual std::vector<netrange_t> slice_dimensions() const;
// Some types have a base variable type. // Some types have a base variable type. This is the bit type
// for packed data types, or IVL_VT_DARRAY or IVL_VT_CLASS for
// those specific types.
virtual ivl_variable_type_t base_type() const; virtual ivl_variable_type_t base_type() const;
virtual bool get_signed() const; virtual bool get_signed() const;
// Return true if "that" type is compatible with this
// type. Compatibile means the types are essentially the same.
bool type_compatible(ivl_type_t that) const;
virtual std::ostream& debug_dump(std::ostream&) const; virtual std::ostream& debug_dump(std::ostream&) const;
private:
// The "type_compatibile" method uses this virtual method to
// invoke type-specific tests of compatibility. This should
// only be called by the type_compatible method above.
virtual bool test_compatibility(ivl_type_t that) const;
}; };
/* /*
@ -98,6 +110,18 @@ class netrange_t {
inline long get_msb() const { assert(defined()); return msb_; } inline long get_msb() const { assert(defined()); return msb_; }
inline long get_lsb() const { assert(defined()); return lsb_; } inline long get_lsb() const { assert(defined()); return lsb_; }
inline bool operator == (const netrange_t&that) const
{ if (msb_ != that.msb_) return false;
if (lsb_ != that.lsb_) return false;
return true;
}
inline bool operator != (const netrange_t&that) const
{ if (msb_ != that.msb_) return true;
if (lsb_ != that.lsb_) return true;
return false;
}
private: private:
long msb_; long msb_;
long lsb_; long lsb_;

View File

@ -18,6 +18,7 @@
*/ */
# include "netvector.h" # include "netvector.h"
# include <iostream>
using namespace std; using namespace std;
@ -62,3 +63,22 @@ vector<netrange_t> netvector_t::slice_dimensions() const
{ {
return packed_dims_; return packed_dims_;
} }
bool netvector_t::test_compatibility(ivl_type_t that) const
{
const netvector_t*that_st = dynamic_cast<const netvector_t*>(that);
if (that_st == 0)
return false;
if (type_ != that_st->type_)
return false;
if (packed_dims_.size() != that_st->packed_dims_.size())
return false;
for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1) {
if (packed_dims_[idx] != that_st->packed_dims_[idx])
return false;
}
return true;
}

View File

@ -78,6 +78,9 @@ class netvector_t : public ivl_type_s {
static netvector_t scalar_bool; static netvector_t scalar_bool;
static netvector_t scalar_logic; static netvector_t scalar_logic;
private:
bool test_compatibility(ivl_type_t that) const;
private: private:
std::vector<netrange_t> packed_dims_; std::vector<netrange_t> packed_dims_;
ivl_variable_type_t type_; ivl_variable_type_t type_;

34
parse.y
View File

@ -669,15 +669,14 @@ source_text : description_list | ;
assignment_pattern /* IEEE1800-2005: A.6.7.1 */ assignment_pattern /* IEEE1800-2005: A.6.7.1 */
: K_LP expression_list_proper '}' : K_LP expression_list_proper '}'
{ PEVoid*tmp = new PEVoid; { PEAssignPattern*tmp = new PEAssignPattern(*$2);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
yyerror(@1, "sorry: Assignment patterns (array literals) not supported."); delete $2;
$$ = tmp; $$ = tmp;
} }
| K_LP '}' | K_LP '}'
{ PEVoid*tmp = new PEVoid; { PEAssignPattern*tmp = new PEAssignPattern;
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
yyerror(@1, "sorry: Assignment patterns (array literals) not supported.");
$$ = tmp; $$ = tmp;
} }
; ;
@ -1070,13 +1069,11 @@ endnew_opt : ':' K_new | ;
dynamic_array_new /* IEEE1800-2005: A.2.4 */ dynamic_array_new /* IEEE1800-2005: A.2.4 */
: K_new '[' expression ']' : K_new '[' expression ']'
{ $$ = new PENew($3); { $$ = new PENewArray($3, 0);
FILE_NAME($$, @1); FILE_NAME($$, @1);
} }
| K_new '[' expression ']' '(' expression ')' | K_new '[' expression ']' '(' expression ')'
{ yyerror(@1, "sorry: Dynamic array new expression with initializer not supported."); { $$ = new PENewArray($3, $6);
delete $6;
$$ = new PENew($3);
FILE_NAME($$, @1); FILE_NAME($$, @1);
} }
; ;
@ -1795,12 +1792,16 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction_opt data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt : port_direction_opt data_type_or_implicit IDENTIFIER range_opt tf_port_item_expr_opt
{ vector<pform_tf_port_t>*tmp; { vector<pform_tf_port_t>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1; NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
perm_string name = lex_strings.make($3);
list<perm_string>* ilist = list_from_identifier($3); list<perm_string>* ilist = list_from_identifier($3);
if (($2 == 0) && ($1==NetNet::PIMPLICIT)) { if (($2 == 0) && ($1==NetNet::PIMPLICIT)) {
// Detect special case this is an undecorated // Detect special case this is an undecorated
// identifier and we need to get the declaration from // identifier and we need to get the declaration from
// left context. // left context.
if ($4 != 0) {
yyerror(@4, "internal error: How can there be an unpacked range here?\n");
}
if (port_declaration_context.var_type == IVL_VT_NO_TYPE) { if (port_declaration_context.var_type == IVL_VT_NO_TYPE) {
tmp = pform_make_task_ports(@3, use_port_type, tmp = pform_make_task_ports(@3, use_port_type,
port_declaration_context.data_type, port_declaration_context.data_type,
@ -1829,11 +1830,11 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
port_declaration_context.data_type = $2; port_declaration_context.data_type = $2;
tmp = pform_make_task_ports(@3, use_port_type, $2, ilist); tmp = pform_make_task_ports(@3, use_port_type, $2, ilist);
} }
$$ = tmp; if ($4 != 0) {
if ($4) { pform_set_reg_idx(name, $4);
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
delete $4;
} }
$$ = tmp;
if ($5) { if ($5) {
assert(tmp->size()==1); assert(tmp->size()==1);
tmp->front().defe = $5; tmp->front().defe = $5;
@ -5072,11 +5073,12 @@ register_variable
pform_set_reg_idx(name, $2); pform_set_reg_idx(name, $2);
$$ = $1; $$ = $1;
} }
| IDENTIFIER '=' expression | IDENTIFIER dimensions_opt '=' expression
{ perm_string ident_name = lex_strings.make($1); { perm_string name = lex_strings.make($1);
pform_makewire(@1, ident_name, NetNet::REG, pform_makewire(@1, name, NetNet::REG,
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0); NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
pform_make_reginit(@1, ident_name, $3); pform_set_reg_idx(name, $2);
pform_make_reginit(@1, name, $4);
$$ = $1; $$ = $1;
} }
; ;

View File

@ -230,6 +230,19 @@ void PExpr::dump(ostream&out) const
out << typeid(*this).name(); out << typeid(*this).name();
} }
void PEAssignPattern::dump(ostream&out) const
{
out << "'{";
if (parms_.size() > 0) {
parms_[0]->dump(out);
for (size_t idx = 1 ; idx < parms_.size() ; idx += 1) {
out << ", ";
parms_[idx]->dump(out);
}
}
out << "}";
}
void PEConcat::dump(ostream&out) const void PEConcat::dump(ostream&out) const
{ {
if (repeat_) if (repeat_)
@ -299,9 +312,11 @@ void PEFNumber::dump(ostream &out) const
out << value(); out << value();
} }
void PENew::dump(ostream&out) const void PENewArray::dump(ostream&out) const
{ {
out << "new [" << *size_ << "]"; out << "new [" << *size_ << "]";
if (init_)
out << "(" << *init_ << ")";
} }
void PENewClass::dump(ostream&out) const void PENewClass::dump(ostream&out) const

View File

@ -520,6 +520,9 @@ extern "C" ivl_expr_t ivl_expr_oper2(ivl_expr_t net)
case IVL_EX_BINARY: case IVL_EX_BINARY:
return net->u_.binary_.rig_; return net->u_.binary_.rig_;
case IVL_EX_NEW:
return net->u_.new_.init_val;
case IVL_EX_SELECT: case IVL_EX_SELECT:
return net->u_.select_.base_; return net->u_.select_.base_;
@ -570,6 +573,10 @@ extern "C" ivl_expr_t ivl_expr_parm(ivl_expr_t net, unsigned idx)
assert(net); assert(net);
switch (net->type_) { switch (net->type_) {
case IVL_EX_ARRAY_PATTERN:
assert(idx < net->u_.array_pattern_.parms);
return net->u_.array_pattern_.parm[idx];
case IVL_EX_CONCAT: case IVL_EX_CONCAT:
assert(idx < net->u_.concat_.parms); assert(idx < net->u_.concat_.parms);
return net->u_.concat_.parm[idx]; return net->u_.concat_.parm[idx];
@ -593,6 +600,9 @@ extern "C" unsigned ivl_expr_parms(ivl_expr_t net)
assert(net); assert(net);
switch (net->type_) { switch (net->type_) {
case IVL_EX_ARRAY_PATTERN:
return net->u_.array_pattern_.parms;
case IVL_EX_CONCAT: case IVL_EX_CONCAT:
return net->u_.concat_.parms; return net->u_.concat_.parms;

View File

@ -175,6 +175,31 @@ void dll_target::expr_access_func(const NetEAccess*net)
expr_->u_.branch_.nature = net->get_nature(); expr_->u_.branch_.nature = net->get_nature();
} }
void dll_target::expr_array_pattern(const NetEArrayPattern*net)
{
assert(expr_ == 0);
ivl_expr_t expr_tmp = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_tmp->type_ = IVL_EX_ARRAY_PATTERN;
expr_tmp->value_= net->expr_type();
expr_tmp->net_type = net->net_type();
expr_tmp->width_ = 1;
expr_tmp->signed_ = 0;
expr_tmp->sized_ = 0;
FILE_NAME(expr_tmp, net);
expr_tmp->u_.array_pattern_.parms = net->item_size();
expr_tmp->u_.array_pattern_.parm = new ivl_expr_t [net->item_size()];
for (size_t idx = 0 ; idx < net->item_size() ; idx += 1) {
const NetExpr*tmp = net->item(idx);
tmp->expr_scan(this);
expr_tmp->u_.array_pattern_.parm[idx] = expr_;
expr_ = 0;
}
expr_ = expr_tmp;
}
void dll_target::expr_binary(const NetEBinary*net) void dll_target::expr_binary(const NetEBinary*net)
{ {
assert(expr_ == 0); assert(expr_ == 0);
@ -321,12 +346,20 @@ void dll_target::expr_creal(const NetECReal*net)
void dll_target::expr_new(const NetENew*net) void dll_target::expr_new(const NetENew*net)
{ {
ivl_expr_t size = 0; ivl_expr_t size = 0;
ivl_expr_t init_val = 0;
if (net->size_expr()) { if (net->size_expr()) {
net->size_expr()->expr_scan(this); net->size_expr()->expr_scan(this);
size = expr_; size = expr_;
expr_ = 0; expr_ = 0;
} }
if (net->init_expr()) {
net->init_expr()->expr_scan(this);
init_val = expr_;
expr_ = 0;
}
assert(expr_ == 0); assert(expr_ == 0);
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->width_ = net->expr_width(); expr_->width_ = net->expr_width();
@ -337,6 +370,7 @@ void dll_target::expr_new(const NetENew*net)
expr_->value_ = net->expr_type(); // May be IVL_VT_DARRAY or _CLASS expr_->value_ = net->expr_type(); // May be IVL_VT_DARRAY or _CLASS
expr_->net_type= net->get_type(); expr_->net_type= net->get_type();
expr_->u_.new_.size = size; expr_->u_.new_.size = size;
expr_->u_.new_.init_val = init_val;
} }
void dll_target::expr_null(const NetENull*net) void dll_target::expr_null(const NetENull*net)

View File

@ -135,6 +135,7 @@ struct dll_target : public target_t, public expr_scan_t {
struct ivl_expr_s*expr_; struct ivl_expr_s*expr_;
void expr_access_func(const NetEAccess*); void expr_access_func(const NetEAccess*);
void expr_array_pattern(const NetEArrayPattern*);
void expr_binary(const NetEBinary*); void expr_binary(const NetEBinary*);
void expr_concat(const NetEConcat*); void expr_concat(const NetEConcat*);
void expr_const(const NetEConst*); void expr_const(const NetEConst*);
@ -239,6 +240,11 @@ struct ivl_expr_s {
ivl_expr_t rig_; ivl_expr_t rig_;
} binary_; } binary_;
struct {
size_t parms;
ivl_expr_t*parm;
} array_pattern_;
struct { struct {
ivl_select_type_t sel_type_; ivl_select_type_t sel_type_;
ivl_expr_t expr_; ivl_expr_t expr_;
@ -331,6 +337,7 @@ struct ivl_expr_s {
struct { struct {
ivl_expr_t size; ivl_expr_t size;
ivl_expr_t init_val;
} new_; } new_;
struct { struct {

View File

@ -452,6 +452,12 @@ void expr_scan_t::expr_access_func(const NetEAccess*)
"unhandled expr_access_func." << endl; "unhandled expr_access_func." << endl;
} }
void expr_scan_t::expr_array_pattern(const NetEArrayPattern*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_array_pattern." << endl;
}
void expr_scan_t::expr_const(const NetEConst*) void expr_scan_t::expr_const(const NetEConst*)
{ {
cerr << "expr_scan_t (" << typeid(*this).name() << "): " cerr << "expr_scan_t (" << typeid(*this).name() << "): "

View File

@ -152,6 +152,7 @@ struct target_t {
struct expr_scan_t { struct expr_scan_t {
virtual ~expr_scan_t(); virtual ~expr_scan_t();
virtual void expr_access_func(const NetEAccess*); virtual void expr_access_func(const NetEAccess*);
virtual void expr_array_pattern(const NetEArrayPattern*);
virtual void expr_const(const NetEConst*); virtual void expr_const(const NetEConst*);
virtual void expr_new(const NetENew*); virtual void expr_new(const NetENew*);
virtual void expr_null(const NetENull*); virtual void expr_null(const NetENull*);

View File

@ -40,6 +40,16 @@ static void show_array_expression(ivl_expr_t net, unsigned ind)
ivl_signal_dimensions(sig), width, vt); ivl_signal_dimensions(sig), width, vt);
} }
static void show_array_pattern_expression(ivl_expr_t net, unsigned ind)
{
size_t idx;
fprintf(out, "%*sArrayPattern (%s): %u expressions\n",
ind, "", vt_type_string(net), ivl_expr_parms(net));
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1) {
show_expression(ivl_expr_parm(net,idx), ind+4);
}
}
static void show_branch_access_expression(ivl_expr_t net, unsigned ind) static void show_branch_access_expression(ivl_expr_t net, unsigned ind)
{ {
ivl_branch_t bra = ivl_expr_branch(net); ivl_branch_t bra = ivl_expr_branch(net);
@ -176,6 +186,12 @@ static void show_new_expression(ivl_expr_t net, unsigned ind)
show_expression(ivl_expr_oper1(net), ind+3); show_expression(ivl_expr_oper1(net), ind+3);
stub_errors += 1; stub_errors += 1;
} }
if (ivl_expr_oper2(net)){
fprintf(out, "%*sERROR: class_new with array element initializer!\n",
ind+3, "");
show_expression(ivl_expr_oper2(net), ind+3);
stub_errors += 1;
}
break; break;
case IVL_VT_DARRAY: case IVL_VT_DARRAY:
fprintf(out, "%*snew [] <type>\n", ind, ""); fprintf(out, "%*snew [] <type>\n", ind, "");
@ -185,6 +201,12 @@ static void show_new_expression(ivl_expr_t net, unsigned ind)
fprintf(out, "%*sERROR: darray_new missing size expression\n", fprintf(out, "%*sERROR: darray_new missing size expression\n",
ind+3, ""); ind+3, "");
stub_errors += 1; stub_errors += 1;
}
/* The IVL_EX_NEW expression may include an element
initializer. This may be an array pattern or simple
expression. */
if (ivl_expr_oper2(net)) {
show_expression(ivl_expr_oper2(net), ind+3);
} }
break; break;
default: default:
@ -408,6 +430,10 @@ void show_expression(ivl_expr_t net, unsigned ind)
show_array_expression(net, ind); show_array_expression(net, ind);
break; break;
case IVL_EX_ARRAY_PATTERN:
show_array_pattern_expression(net, ind);
break;
case IVL_EX_BACCESS: case IVL_EX_BACCESS:
show_branch_access_expression(net, ind); show_branch_access_expression(net, ind);
break; break;

View File

@ -65,6 +65,12 @@ static void function_argument_class(ivl_signal_t port, ivl_expr_t expr)
fprintf(vvp_out, " %%store/obj v%p_0;\n", port); fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
} }
static void function_argument_darray(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_object(expr);
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
}
static void function_argument_string(ivl_signal_t port, ivl_expr_t expr) static void function_argument_string(ivl_signal_t port, ivl_expr_t expr)
{ {
draw_eval_string(expr); draw_eval_string(expr);
@ -90,6 +96,9 @@ static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
case IVL_VT_STRING: case IVL_VT_STRING:
function_argument_string(port, expr); function_argument_string(port, expr);
break; break;
case IVL_VT_DARRAY:
function_argument_darray(port, expr);
break;
default: default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n", fprintf(stderr, "XXXX function argument %s type=%d?!\n",
ivl_signal_basename(port), dtype); ivl_signal_basename(port), dtype);
@ -205,7 +214,23 @@ void draw_ufunc_real(ivl_expr_t expr)
fprintf(vvp_out, " %%load/real v%p_0;\n", retval); fprintf(vvp_out, " %%load/real v%p_0;\n", retval);
draw_ufunc_epilogue(expr); draw_ufunc_epilogue(expr);
}
void draw_ufunc_string(ivl_expr_t expr)
{
ivl_scope_t def = ivl_expr_def(expr);
ivl_signal_t retval = ivl_scope_port(def, 0);
/* Take in arguments to function and call the function code. */
draw_ufunc_preamble(expr);
/* Return value signal cannot be an array. */
assert(ivl_signal_dimensions(retval) == 0);
/* Load the result into a word. */
fprintf(vvp_out, " %%load/str v%p_0;\n", retval);
draw_ufunc_epilogue(expr);
} }
void draw_ufunc_object(ivl_expr_t expr) void draw_ufunc_object(ivl_expr_t expr)

View File

@ -23,8 +23,10 @@
static int eval_darray_new(ivl_expr_t ex) static int eval_darray_new(ivl_expr_t ex)
{ {
int errors = 0;
unsigned size_reg = allocate_word(); unsigned size_reg = allocate_word();
ivl_expr_t size_expr = ivl_expr_oper1(ex); ivl_expr_t size_expr = ivl_expr_oper1(ex);
ivl_expr_t init_expr = ivl_expr_oper2(ex);
draw_eval_expr_into_integer(size_expr, size_reg); draw_eval_expr_into_integer(size_expr, size_reg);
clr_word(size_reg); clr_word(size_reg);
@ -64,7 +66,91 @@ static int eval_darray_new(ivl_expr_t ex)
break; break;
} }
return 0; if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) {
int idx;
struct vector_info rvec;
unsigned wid;
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
wid = width_of_packed_type(element_type);
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
rvec = draw_eval_expr_wid(ivl_expr_parm(init_expr,idx),
wid, STUFF_OK_XZ);
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
fprintf(vvp_out, " %%set/dar/obj 3, %u, %u;\n",
rvec.base, rvec.wid);
if (rvec.base >= 4) clr_vector(rvec);
}
break;
case IVL_VT_REAL:
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
draw_eval_real(ivl_expr_parm(init_expr,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
fprintf(vvp_out, " %%set/dar/obj/real 3;\n");
fprintf(vvp_out, " %%pop/real 1;\n");
}
break;
case IVL_VT_STRING:
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
draw_eval_string(ivl_expr_parm(init_expr,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
fprintf(vvp_out, " %%set/dar/obj/str 3;\n");
fprintf(vvp_out, " %%pop/str 1;\n");
}
break;
default:
fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n");
errors += 1;
break;
}
} else if (init_expr && number_is_immediate(size_expr,32,0)) {
/* In this case, there is an init expression, the
expression is NOT an array_pattern, and the size
expression used to calculate the size of the array is
a constant. Generate an unrolled set of assignments. */
long idx;
long cnt = get_number_immediate(size_expr);
struct vector_info rvec;
unsigned wid;
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
wid = width_of_packed_type(element_type);
rvec = draw_eval_expr_wid(init_expr, wid, STUFF_OK_XZ);
for (idx = 0 ; idx < cnt ; idx += 1) {
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
fprintf(vvp_out, " %%set/dar/obj 3, %u, %u;\n",
rvec.base, rvec.wid);
}
if (rvec.base >= 4) clr_vector(rvec);
break;
case IVL_VT_REAL:
draw_eval_real(init_expr);
for (idx = 0 ; idx < cnt ; idx += 1) {
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
fprintf(vvp_out, " %%set/dar/obj/real 3;\n");
}
fprintf(vvp_out, " %%pop/real 1;\n");
break;
case IVL_VT_STRING:
draw_eval_string(init_expr);
for (idx = 0 ; idx < cnt ; idx += 1) {
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
fprintf(vvp_out, " %%set/dar/obj/str 3;\n");
}
fprintf(vvp_out, " %%pop/str 1;\n");
break;
default:
fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n");
errors += 1;
break;
}
} else if (init_expr) {
fprintf(vvp_out, "; ERROR: Sorry, I don't know how to work with this size expr.\n");
errors += 1;
}
return errors;
} }
static int eval_class_new(ivl_expr_t ex) static int eval_class_new(ivl_expr_t ex)

View File

@ -180,6 +180,10 @@ void draw_eval_string(ivl_expr_t expr)
fallback_eval(expr); fallback_eval(expr);
break; break;
case IVL_EX_UFUNC:
draw_ufunc_string(expr);
break;
default: default:
fallback_eval(expr); fallback_eval(expr);
break; break;

View File

@ -687,7 +687,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
} }
/* /*
* This function assigns a value to a real .variable. This is destined * This function assigns a value to a real variable. This is destined
* for /dev/null when typed ivl_signal_t takes over all the real * for /dev/null when typed ivl_signal_t takes over all the real
* variable support. * variable support.
*/ */
@ -795,6 +795,81 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
return 0; return 0;
} }
unsigned width_of_packed_type(ivl_type_t net)
{
unsigned idx;
unsigned width = 1;
for (idx = 0 ; idx < ivl_type_packed_dimensions(net) ; idx += 1) {
int lsb = ivl_type_packed_lsb(net,idx);
int msb = ivl_type_packed_msb(net,idx);
if (lsb <= msb)
width *= msb - lsb + 1;
else
width *= lsb - msb + 1;
}
return width;
}
/*
* This function handles the special case that we assign an array
* pattern to a dynamic array. Handle this by assigning each
* element. The array pattern will have a fixed size.
*/
static int show_stmt_assign_darray_pattern(ivl_statement_t net)
{
int errors = 0;
ivl_lval_t lval = ivl_stmt_lval(net, 0);
ivl_expr_t rval = ivl_stmt_rval(net);
ivl_signal_t var= ivl_lval_sig(lval);
ivl_type_t var_type= ivl_signal_net_type(var);
assert(ivl_type_base(var_type) == IVL_VT_DARRAY);
ivl_type_t element_type = ivl_type_element(var_type);
unsigned idx;
struct vector_info rvec;
unsigned element_width = 1;
if (ivl_type_base(element_type) == IVL_VT_BOOL)
element_width = width_of_packed_type(element_type);
else if (ivl_type_base(element_type) == IVL_VT_LOGIC)
element_width = width_of_packed_type(element_type);
assert(ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN);
for (idx = 0 ; idx < ivl_expr_parms(rval) ; idx += 1) {
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
rvec = draw_eval_expr_wid(ivl_expr_parm(rval,idx),
element_width, STUFF_OK_XZ);
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
fprintf(vvp_out, " %%set/dar v%p_0, %u, %u;\n",
var, rvec.base, rvec.wid);
if (rvec.base >= 4) clr_vector(rvec);
break;
case IVL_VT_REAL:
draw_eval_real(ivl_expr_parm(rval,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var);
break;
case IVL_VT_STRING:
draw_eval_string(ivl_expr_parm(rval,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var);
break;
default:
fprintf(vvp_out, "; ERROR: show_stmt_assign_darray_pattern: type_base=%d not implemented\n", ivl_type_base(element_type));
errors += 1;
break;
}
}
return errors;
}
static int show_stmt_assign_sig_darray(ivl_statement_t net) static int show_stmt_assign_sig_darray(ivl_statement_t net)
{ {
int errors = 0; int errors = 0;
@ -845,6 +920,12 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
if (rvec.base >= 4) clr_vector(rvec); if (rvec.base >= 4) clr_vector(rvec);
} else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) {
/* There is no l-value mux, but the r-value is an array
pattern. This is a special case of an assignment to
elements of the l-value. */
errors += show_stmt_assign_darray_pattern(net);
} else { } else {
/* There is no l-value mux, so this must be an /* There is no l-value mux, so this must be an
assignment to the array as a whole. Evaluate the assignment to the array as a whole. Evaluate the

View File

@ -83,6 +83,11 @@ extern const char* vvp_signal_label(ivl_signal_t sig);
extern unsigned width_of_nexus(ivl_nexus_t nex); extern unsigned width_of_nexus(ivl_nexus_t nex);
extern ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex); extern ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex);
/*
* Calculate the width (in bits) of a packed type.
*/
extern unsigned width_of_packed_type(ivl_type_t net);
extern int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr); extern int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr);
/* /*
@ -101,6 +106,7 @@ extern void draw_lpm_mux(ivl_lpm_t net);
extern struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid); extern struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid);
extern void draw_ufunc_real(ivl_expr_t expr); extern void draw_ufunc_real(ivl_expr_t expr);
extern void draw_ufunc_string(ivl_expr_t expr);
extern void draw_ufunc_object(ivl_expr_t expr); extern void draw_ufunc_object(ivl_expr_t expr);
extern void pad_expr_in_place(ivl_expr_t expr, struct vector_info res, extern void pad_expr_in_place(ivl_expr_t expr, struct vector_info res,

View File

@ -181,6 +181,9 @@ extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code);
extern bool of_SCOPY(vthread_t thr, vvp_code_t code); extern bool of_SCOPY(vthread_t thr, vvp_code_t code);
extern bool of_SET_AV(vthread_t thr, vvp_code_t code); extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
extern bool of_SET_DAR(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR(vthread_t thr, vvp_code_t code);
extern bool of_SET_DAR_OBJ(vthread_t thr, vvp_code_t code);
extern bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t code);
extern bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code); extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
extern bool of_SET_X0(vthread_t thr, vvp_code_t code); extern bool of_SET_X0(vthread_t thr, vvp_code_t code);
extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code); extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);

View File

@ -229,6 +229,9 @@ static const struct opcode_table_s opcode_table[] = {
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, { "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} },
{ "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/dar/obj", of_SET_DAR_OBJ, 3,{OA_NUMBER,OA_BIT1,OA_BIT2} },
{ "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} },
{ "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} },
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },

View File

@ -952,10 +952,26 @@ statement. The <type> is 0 for nets and 1 for registers. See the other
%release commands above. %release commands above.
* %set/dar <var-label>, <bit>, <wid> * %set/dar <var-label>, <bit>, <wid>
* %set/dar/obj <index>, <bit>, <wid>
This sets a vector to a word of the dynamic array. Index register 3 The "%set/dar" opcode sets a vector to a word of the dynamic
contains the word address within the dynamic array, and <bit>,<wid> array. Index register 3 contains the word address within the dynamic
specifies the thread vector to be written. array, and <bit>,<wid> specifies the thread vector to be written.
The "%set/dar/obj" opcode is similar, except that it sets elements of
a dynamic array that is in the top of the object stack. Instead of
using a fixed index register, use the register addressed by <index>.
* %set/dar/obj/real <index>
* %set/dar/obj/str <index>
The "%set/dar/obj/real" opcode sets the top value from the real-value
stack to the index. This does NOT pop the real value off the
stack. The intent is that this value may be written to a bunch of
values.
The "%set/dar/obj/str" opcode does the same but for string values and
uses the string stack.
* %set/v <var-label>, <bit>, <wid> * %set/v <var-label>, <bit>, <wid>

View File

@ -4921,6 +4921,59 @@ bool of_SET_DAR(vthread_t thr, vvp_code_t cp)
return true; return true;
} }
/*
* %set/dar/obj <index>, <bit>, <wid>
*/
bool of_SET_DAR_OBJ(vthread_t thr, vvp_code_t cp)
{
unsigned adr = thr->words[cp->number].w_int;
unsigned bit = cp->bit_idx[0];
unsigned wid = cp->bit_idx[1];
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
vvp_object_t&top = thr->peek_object();
vvp_darray*darray = top.peek<vvp_darray>();
assert(darray);
darray->set_word(adr, value);
return true;
}
/*
* %set/dar/obj/real <index>
*/
bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t cp)
{
unsigned adr = thr->words[cp->number].w_int;
double value = thr->peek_real(0);
vvp_object_t&top = thr->peek_object();
vvp_darray*darray = top.peek<vvp_darray>();
assert(darray);
darray->set_word(adr, value);
return true;
}
/*
* %set/dar/obj/str <index>
*/
bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t cp)
{
unsigned adr = thr->words[cp->number].w_int;
string value = thr->peek_str(0);
vvp_object_t&top = thr->peek_object();
vvp_darray*darray = top.peek<vvp_darray>();
assert(darray);
darray->set_word(adr, value);
return true;
}
/* /*
* This implements the "%set/v <label>, <bit>, <wid>" instruction. * This implements the "%set/v <label>, <bit>, <wid>" instruction.
* *