Merge branch 'x-mil11'
This commit is contained in:
commit
61fbfb562e
25
PExpr.cc
25
PExpr.cc
|
|
@ -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)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
|
|
@ -417,12 +436,12 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
|
|||
return false;
|
||||
}
|
||||
|
||||
PENew::PENew(PExpr*size_expr)
|
||||
: size_(size_expr)
|
||||
PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr)
|
||||
: size_(size_expr), init_(init_expr)
|
||||
{
|
||||
}
|
||||
|
||||
PENew::~PENew()
|
||||
PENewArray::~PENewArray()
|
||||
{
|
||||
delete size_;
|
||||
}
|
||||
|
|
|
|||
37
PExpr.h
37
PExpr.h
|
|
@ -194,6 +194,29 @@ class PExpr : public LineInfo {
|
|||
|
||||
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 {
|
||||
|
||||
public:
|
||||
|
|
@ -279,6 +302,8 @@ class PEFNumber : public PExpr {
|
|||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
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*,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
|
|
@ -479,11 +504,11 @@ class PEIdent : public PExpr {
|
|||
long&midx, long&lidx) const;
|
||||
};
|
||||
|
||||
class PENew : public PExpr {
|
||||
class PENewArray : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PENew (PExpr*s);
|
||||
~PENew();
|
||||
explicit PENewArray (PExpr*s, PExpr*i);
|
||||
~PENewArray();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
|
|
@ -496,6 +521,7 @@ class PENew : public PExpr {
|
|||
|
||||
private:
|
||||
PExpr*size_;
|
||||
PExpr*init_;
|
||||
};
|
||||
|
||||
class PENewClass : public PExpr {
|
||||
|
|
@ -570,7 +596,7 @@ class PENumber : public PExpr {
|
|||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
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;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
|
|
@ -606,6 +632,9 @@ class PEString : public PExpr {
|
|||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
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*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
|
|
|||
|
|
@ -105,8 +105,9 @@ class PAssign_ : public Statement {
|
|||
|
||||
protected:
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
|
||||
ivl_variable_type_t type) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
|
||||
|
||||
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
|
||||
|
|
|
|||
|
|
@ -1410,6 +1410,19 @@ void NetEAccess::dump(ostream&o) const
|
|||
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
|
||||
{
|
||||
if (op_ == 'm' || op_ == 'M') {
|
||||
|
|
@ -1549,7 +1562,14 @@ void NetENetenum::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
|
||||
|
|
|
|||
11
dup_expr.cc
11
dup_expr.cc
|
|
@ -32,6 +32,17 @@ NetEAccess* NetEAccess::dup_expr() const
|
|||
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
|
||||
{
|
||||
ivl_assert(*this, 0);
|
||||
|
|
|
|||
170
elab_expr.cc
170
elab_expr.cc
|
|
@ -86,15 +86,34 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
|
|||
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,
|
||||
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;
|
||||
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_STRING:
|
||||
case IVL_VT_DARRAY:
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
|
|
@ -163,6 +182,76 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
|
|||
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)
|
||||
{
|
||||
|
|
@ -1524,7 +1613,8 @@ static NetExpr* check_for_enum_methods(const LineInfo*li,
|
|||
// Process the method argument if it is available.
|
||||
NetExpr* count = 0;
|
||||
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) {
|
||||
cerr << li->get_fileline() << ": error: unable to elaborate "
|
||||
"enumeration method argument " << use_path << "."
|
||||
|
|
@ -1978,7 +2068,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
|||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_base_: "
|
||||
<< "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
|
||||
|
|
@ -2061,6 +2151,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
|||
PExpr*tmp = parms_[idx];
|
||||
if (tmp) {
|
||||
parms[pidx] = elaborate_rval_expr(des, scope,
|
||||
def->port(pidx)->net_type(),
|
||||
def->port(pidx)->data_type(),
|
||||
(unsigned)def->port(pidx)->vector_width(),
|
||||
tmp, need_const);
|
||||
|
|
@ -2153,12 +2244,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, parms_.size() == 2);
|
||||
NetExpr*tmp;
|
||||
|
||||
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL,
|
||||
32, parms_[0], false);
|
||||
tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
|
||||
IVL_VT_BOOL, 32, parms_[0], false);
|
||||
sys_expr->parm(1, tmp);
|
||||
|
||||
tmp = elaborate_rval_expr(des, scope, IVL_VT_BOOL,
|
||||
32, parms_[1], false);
|
||||
tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
|
||||
IVL_VT_BOOL, 32, parms_[1], false);
|
||||
sys_expr->parm(2, tmp);
|
||||
|
||||
return sys_expr;
|
||||
|
|
@ -2446,6 +2537,13 @@ unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
|
|||
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
|
||||
{
|
||||
NetECReal*tmp = new NetECReal(*value_);
|
||||
|
|
@ -2902,7 +3000,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (net->net_type() != ntype) {
|
||||
if (! ntype->type_compatible(net->net_type())) {
|
||||
cerr << get_fileline() << ": internal_error: "
|
||||
<< "net type doesn't match context type." << endl;
|
||||
|
||||
|
|
@ -2920,7 +3018,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
ntype->debug_dump(cerr);
|
||||
cerr << endl;
|
||||
}
|
||||
ivl_assert(*this, net->net_type() == ntype);
|
||||
ivl_assert(*this, ntype->type_compatible(net->net_type()));
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
|
|
@ -4515,7 +4613,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
|||
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_width_ = 1;
|
||||
|
|
@ -4524,23 +4622,41 @@ unsigned PENew::test_width(Design*, NetScope*, width_mode_t&)
|
|||
return 1;
|
||||
}
|
||||
|
||||
NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t ntype, unsigned flags) const
|
||||
NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t ntype, unsigned flags) const
|
||||
{
|
||||
// Elaborate the size expression.
|
||||
width_mode_t mode = LOSSLESS;
|
||||
unsigned use_wid = size_->test_width(des, scope, mode);
|
||||
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);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
return 0;
|
||||
|
|
@ -4623,7 +4739,8 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
|||
// While there are default arguments, check them.
|
||||
if (idx <= parms_.size() && 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(),
|
||||
tmp, false);
|
||||
if (parms[idx] == 0)
|
||||
|
|
@ -4734,7 +4851,7 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
|
|||
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);
|
||||
if (use_type == 0) {
|
||||
|
|
@ -4745,6 +4862,15 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, uns
|
|||
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();
|
||||
use_val .has_sign( use_type->get_signed() );
|
||||
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_;
|
||||
}
|
||||
|
||||
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*,
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
|
|
|
|||
43
elaborate.cc
43
elaborate.cc
|
|
@ -84,7 +84,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
<< " 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));
|
||||
|
||||
if (rval_expr == 0) {
|
||||
|
|
@ -2244,13 +2245,18 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||
unsigned lv_width,
|
||||
ivl_variable_type_t lv_type) const
|
||||
ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width) const
|
||||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, lv_width, rval(),
|
||||
is_constant_);
|
||||
// Don't have a good value for the lv_net_type argument to
|
||||
// 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;
|
||||
|
||||
|
|
@ -2368,7 +2374,7 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
|
|||
NetAssign_*lv = elaborate_lval(des, scope);
|
||||
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;
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, op_, rv);
|
||||
|
|
@ -2456,7 +2462,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
} else {
|
||||
/* 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;
|
||||
|
|
@ -2648,7 +2654,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
|||
// 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;
|
||||
|
||||
NetExpr*delay = 0;
|
||||
|
|
@ -3463,7 +3469,8 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
|||
NetExpr*rv = 0;
|
||||
|
||||
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)) {
|
||||
cerr << evt->get_fileline() << ": error: An event '"
|
||||
<< 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);
|
||||
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)
|
||||
return 0;
|
||||
|
||||
|
|
@ -4295,7 +4306,11 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned lwid = count_lval_width(lval);
|
||||
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)
|
||||
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
|
||||
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_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
@ -4566,7 +4582,8 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
|
|||
unsigned long wid = res->vector_width();
|
||||
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);
|
||||
proc->set_line( *this );
|
||||
|
|
|
|||
5
emit.cc
5
emit.cc
|
|
@ -546,6 +546,11 @@ void NetEAccess::expr_scan(struct expr_scan_t*tgt) const
|
|||
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
|
||||
{
|
||||
tgt->expr_binary(this);
|
||||
|
|
|
|||
19
ivl_target.h
19
ivl_target.h
|
|
@ -228,6 +228,7 @@ typedef enum ivl_expr_type_e {
|
|||
IVL_EX_NEW = 23,
|
||||
IVL_EX_NULL = 22,
|
||||
IVL_EX_NUMBER = 5,
|
||||
IVL_EX_ARRAY_PATTERN = 26,
|
||||
IVL_EX_PROPERTY = 24,
|
||||
IVL_EX_REALNUM = 16,
|
||||
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
|
||||
* 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
|
||||
* This expression takes two operands, oper1 is the expression to
|
||||
* 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);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
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);
|
||||
/* 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);
|
||||
/* IVL_EX_TERNARY */
|
||||
extern ivl_expr_t ivl_expr_oper3(ivl_expr_t net);
|
||||
/* and expression */
|
||||
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);
|
||||
/* 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);
|
||||
/* IVL_EX_CONCAT */
|
||||
extern unsigned ivl_expr_repeat(ivl_expr_t net);
|
||||
|
|
|
|||
22
net_expr.cc
22
net_expr.cc
|
|
@ -61,7 +61,10 @@ bool NetExpr::has_width() 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
|
||||
|
|
@ -69,6 +72,17 @@ const netenum_t*NetExpr::enumeration() const
|
|||
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.
|
||||
*/
|
||||
|
|
@ -322,12 +336,12 @@ const netenum_t* NetENetenum::netenum() const
|
|||
}
|
||||
|
||||
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)
|
||||
: obj_type_(t), size_(size)
|
||||
NetENew::NetENew(ivl_type_t t, NetExpr*size, NetExpr*init_val)
|
||||
: obj_type_(t), size_(size), init_val_(init_val)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,21 @@ NexusSet* NetProc::nex_input(bool)
|
|||
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*result = left_->nex_input(rem_out);
|
||||
|
|
|
|||
10
netdarray.cc
10
netdarray.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "netdarray.h"
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -34,3 +35,12 @@ ivl_variable_type_t netdarray_t::base_type(void) const
|
|||
{
|
||||
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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class netdarray_t : public netarray_t {
|
|||
std::ostream& debug_dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
bool test_compatibility(ivl_type_t that) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
12
netlist.cc
12
netlist.cc
|
|
@ -759,18 +759,14 @@ void NetNet::set_module_port_index(unsigned idx)
|
|||
|
||||
ivl_variable_type_t NetNet::data_type() const
|
||||
{
|
||||
if (net_type_==0)
|
||||
return IVL_VT_LOGIC;
|
||||
else
|
||||
return net_type_->base_type();
|
||||
ivl_assert(*this, net_type_);
|
||||
return net_type_->base_type();
|
||||
}
|
||||
|
||||
bool NetNet::get_signed() const
|
||||
{
|
||||
if (net_type_==0)
|
||||
return false;
|
||||
else
|
||||
return net_type_->get_signed();
|
||||
ivl_assert(*this, net_type_);
|
||||
return net_type_->get_signed();
|
||||
}
|
||||
|
||||
bool NetNet::get_isint() const
|
||||
|
|
|
|||
25
netlist.h
25
netlist.h
|
|
@ -627,7 +627,7 @@ class NetNet : public NetObj, public PortType {
|
|||
// now, the unpacked type is not burried into an ivl_type_s object.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
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
|
||||
// definition. They should probably be replaced with a single
|
||||
|
|
@ -1914,6 +1914,25 @@ class NetExpr : public LineInfo {
|
|||
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
|
||||
* returned from other classes that can be evaluated at compile
|
||||
|
|
@ -4011,11 +4030,12 @@ class NetENew : public NetExpr {
|
|||
// Make class object
|
||||
explicit NetENew(ivl_type_t);
|
||||
// dynamic array of objects.
|
||||
explicit NetENew(ivl_type_t, NetExpr*);
|
||||
explicit NetENew(ivl_type_t, NetExpr*size, NetExpr* init_val=0);
|
||||
~NetENew();
|
||||
|
||||
inline ivl_type_t get_type() const { return obj_type_; }
|
||||
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;
|
||||
|
||||
|
|
@ -4028,6 +4048,7 @@ class NetENew : public NetExpr {
|
|||
private:
|
||||
ivl_type_t obj_type_;
|
||||
NetExpr*size_;
|
||||
NetExpr*init_val_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
26
netmisc.cc
26
netmisc.cc
|
|
@ -751,13 +751,15 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
|||
expr_width = context_width;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << pe->get_fileline() << ": debug: test_width of "
|
||||
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
||||
<< *pe << endl;
|
||||
cerr << pe->get_fileline() << ": "
|
||||
cerr << pe->get_fileline() << ": : "
|
||||
<< "returns type=" << pe->expr_type()
|
||||
<< ", width=" << expr_width
|
||||
<< ", signed=" << pe->has_sign()
|
||||
<< ", 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
|
||||
|
|
@ -807,6 +809,26 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
|||
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,
|
||||
unsigned arg_idx, PExpr*pe, bool need_const)
|
||||
{
|
||||
|
|
|
|||
15
netmisc.h
15
netmisc.h
|
|
@ -244,6 +244,15 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
|||
bool annotatable =false,
|
||||
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
|
||||
* 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 the l-value, and the expr is the expression to elaborate. The
|
||||
* 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,
|
||||
ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width, PExpr*expr,
|
||||
bool need_const =false);
|
||||
|
|
|
|||
13
nettypes.cc
13
nettypes.cc
|
|
@ -46,6 +46,19 @@ bool ivl_type_s::get_signed() const
|
|||
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()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
26
nettypes.h
26
nettypes.h
|
|
@ -38,11 +38,23 @@ class ivl_type_s {
|
|||
virtual long packed_width(void) 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 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;
|
||||
|
||||
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_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:
|
||||
long msb_;
|
||||
long lsb_;
|
||||
|
|
|
|||
20
netvector.cc
20
netvector.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "netvector.h"
|
||||
# include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -62,3 +63,22 @@ vector<netrange_t> netvector_t::slice_dimensions() const
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ class netvector_t : public ivl_type_s {
|
|||
static netvector_t scalar_bool;
|
||||
static netvector_t scalar_logic;
|
||||
|
||||
private:
|
||||
bool test_compatibility(ivl_type_t that) const;
|
||||
|
||||
private:
|
||||
std::vector<netrange_t> packed_dims_;
|
||||
ivl_variable_type_t type_;
|
||||
|
|
|
|||
34
parse.y
34
parse.y
|
|
@ -669,15 +669,14 @@ source_text : description_list | ;
|
|||
|
||||
assignment_pattern /* IEEE1800-2005: A.6.7.1 */
|
||||
: K_LP expression_list_proper '}'
|
||||
{ PEVoid*tmp = new PEVoid;
|
||||
{ PEAssignPattern*tmp = new PEAssignPattern(*$2);
|
||||
FILE_NAME(tmp, @1);
|
||||
yyerror(@1, "sorry: Assignment patterns (array literals) not supported.");
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_LP '}'
|
||||
{ PEVoid*tmp = new PEVoid;
|
||||
{ PEAssignPattern*tmp = new PEAssignPattern;
|
||||
FILE_NAME(tmp, @1);
|
||||
yyerror(@1, "sorry: Assignment patterns (array literals) not supported.");
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -1070,13 +1069,11 @@ endnew_opt : ':' K_new | ;
|
|||
|
||||
dynamic_array_new /* IEEE1800-2005: A.2.4 */
|
||||
: K_new '[' expression ']'
|
||||
{ $$ = new PENew($3);
|
||||
{ $$ = new PENewArray($3, 0);
|
||||
FILE_NAME($$, @1);
|
||||
}
|
||||
| K_new '[' expression ']' '(' expression ')'
|
||||
{ yyerror(@1, "sorry: Dynamic array new expression with initializer not supported.");
|
||||
delete $6;
|
||||
$$ = new PENew($3);
|
||||
{ $$ = new PENewArray($3, $6);
|
||||
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
|
||||
{ vector<pform_tf_port_t>*tmp;
|
||||
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);
|
||||
|
||||
if (($2 == 0) && ($1==NetNet::PIMPLICIT)) {
|
||||
// Detect special case this is an undecorated
|
||||
// identifier and we need to get the declaration from
|
||||
// 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) {
|
||||
tmp = pform_make_task_ports(@3, use_port_type,
|
||||
port_declaration_context.data_type,
|
||||
|
|
@ -1829,11 +1830,11 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
|||
port_declaration_context.data_type = $2;
|
||||
tmp = pform_make_task_ports(@3, use_port_type, $2, ilist);
|
||||
}
|
||||
$$ = tmp;
|
||||
if ($4) {
|
||||
yyerror(@4, "sorry: Port variable dimensions not supported yet.");
|
||||
delete $4;
|
||||
if ($4 != 0) {
|
||||
pform_set_reg_idx(name, $4);
|
||||
}
|
||||
|
||||
$$ = tmp;
|
||||
if ($5) {
|
||||
assert(tmp->size()==1);
|
||||
tmp->front().defe = $5;
|
||||
|
|
@ -5072,11 +5073,12 @@ register_variable
|
|||
pform_set_reg_idx(name, $2);
|
||||
$$ = $1;
|
||||
}
|
||||
| IDENTIFIER '=' expression
|
||||
{ perm_string ident_name = lex_strings.make($1);
|
||||
pform_makewire(@1, ident_name, NetNet::REG,
|
||||
| IDENTIFIER dimensions_opt '=' expression
|
||||
{ perm_string name = lex_strings.make($1);
|
||||
pform_makewire(@1, name, NetNet::REG,
|
||||
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;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
|
|
@ -230,6 +230,19 @@ void PExpr::dump(ostream&out) const
|
|||
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
|
||||
{
|
||||
if (repeat_)
|
||||
|
|
@ -299,9 +312,11 @@ void PEFNumber::dump(ostream &out) const
|
|||
out << value();
|
||||
}
|
||||
|
||||
void PENew::dump(ostream&out) const
|
||||
void PENewArray::dump(ostream&out) const
|
||||
{
|
||||
out << "new [" << *size_ << "]";
|
||||
if (init_)
|
||||
out << "(" << *init_ << ")";
|
||||
}
|
||||
|
||||
void PENewClass::dump(ostream&out) const
|
||||
|
|
|
|||
10
t-dll-api.cc
10
t-dll-api.cc
|
|
@ -520,6 +520,9 @@ extern "C" ivl_expr_t ivl_expr_oper2(ivl_expr_t net)
|
|||
case IVL_EX_BINARY:
|
||||
return net->u_.binary_.rig_;
|
||||
|
||||
case IVL_EX_NEW:
|
||||
return net->u_.new_.init_val;
|
||||
|
||||
case IVL_EX_SELECT:
|
||||
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);
|
||||
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:
|
||||
assert(idx < net->u_.concat_.parms);
|
||||
return net->u_.concat_.parm[idx];
|
||||
|
|
@ -593,6 +600,9 @@ extern "C" unsigned ivl_expr_parms(ivl_expr_t net)
|
|||
assert(net);
|
||||
switch (net->type_) {
|
||||
|
||||
case IVL_EX_ARRAY_PATTERN:
|
||||
return net->u_.array_pattern_.parms;
|
||||
|
||||
case IVL_EX_CONCAT:
|
||||
return net->u_.concat_.parms;
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,31 @@ void dll_target::expr_access_func(const NetEAccess*net)
|
|||
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)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
|
@ -321,12 +346,20 @@ void dll_target::expr_creal(const NetECReal*net)
|
|||
void dll_target::expr_new(const NetENew*net)
|
||||
{
|
||||
ivl_expr_t size = 0;
|
||||
ivl_expr_t init_val = 0;
|
||||
|
||||
if (net->size_expr()) {
|
||||
net->size_expr()->expr_scan(this);
|
||||
size = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
if (net->init_expr()) {
|
||||
net->init_expr()->expr_scan(this);
|
||||
init_val = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
assert(expr_ == 0);
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
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_->net_type= net->get_type();
|
||||
expr_->u_.new_.size = size;
|
||||
expr_->u_.new_.init_val = init_val;
|
||||
}
|
||||
|
||||
void dll_target::expr_null(const NetENull*net)
|
||||
|
|
|
|||
7
t-dll.h
7
t-dll.h
|
|
@ -135,6 +135,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
struct ivl_expr_s*expr_;
|
||||
void expr_access_func(const NetEAccess*);
|
||||
void expr_array_pattern(const NetEArrayPattern*);
|
||||
void expr_binary(const NetEBinary*);
|
||||
void expr_concat(const NetEConcat*);
|
||||
void expr_const(const NetEConst*);
|
||||
|
|
@ -239,6 +240,11 @@ struct ivl_expr_s {
|
|||
ivl_expr_t rig_;
|
||||
} binary_;
|
||||
|
||||
struct {
|
||||
size_t parms;
|
||||
ivl_expr_t*parm;
|
||||
} array_pattern_;
|
||||
|
||||
struct {
|
||||
ivl_select_type_t sel_type_;
|
||||
ivl_expr_t expr_;
|
||||
|
|
@ -331,6 +337,7 @@ struct ivl_expr_s {
|
|||
|
||||
struct {
|
||||
ivl_expr_t size;
|
||||
ivl_expr_t init_val;
|
||||
} new_;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -452,6 +452,12 @@ void expr_scan_t::expr_access_func(const NetEAccess*)
|
|||
"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*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
|
|
|
|||
1
target.h
1
target.h
|
|
@ -152,6 +152,7 @@ struct target_t {
|
|||
struct expr_scan_t {
|
||||
virtual ~expr_scan_t();
|
||||
virtual void expr_access_func(const NetEAccess*);
|
||||
virtual void expr_array_pattern(const NetEArrayPattern*);
|
||||
virtual void expr_const(const NetEConst*);
|
||||
virtual void expr_new(const NetENew*);
|
||||
virtual void expr_null(const NetENull*);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,16 @@ static void show_array_expression(ivl_expr_t net, unsigned ind)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
case IVL_VT_DARRAY:
|
||||
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",
|
||||
ind+3, "");
|
||||
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;
|
||||
default:
|
||||
|
|
@ -408,6 +430,10 @@ void show_expression(ivl_expr_t net, unsigned ind)
|
|||
show_array_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_ARRAY_PATTERN:
|
||||
show_array_pattern_expression(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_EX_BACCESS:
|
||||
show_branch_access_expression(net, ind);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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:
|
||||
function_argument_string(port, expr);
|
||||
break;
|
||||
case IVL_VT_DARRAY:
|
||||
function_argument_darray(port, expr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
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);
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@
|
|||
|
||||
static int eval_darray_new(ivl_expr_t ex)
|
||||
{
|
||||
int errors = 0;
|
||||
unsigned size_reg = allocate_word();
|
||||
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);
|
||||
clr_word(size_reg);
|
||||
|
||||
|
|
@ -64,7 +66,91 @@ static int eval_darray_new(ivl_expr_t ex)
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -180,6 +180,10 @@ void draw_eval_string(ivl_expr_t expr)
|
|||
fallback_eval(expr);
|
||||
break;
|
||||
|
||||
case IVL_EX_UFUNC:
|
||||
draw_ufunc_string(expr);
|
||||
break;
|
||||
|
||||
default:
|
||||
fallback_eval(expr);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* variable support.
|
||||
*/
|
||||
|
|
@ -795,6 +795,81 @@ static int show_stmt_assign_sig_string(ivl_statement_t net)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
} 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 {
|
||||
/* There is no l-value mux, so this must be an
|
||||
assignment to the array as a whole. Evaluate the
|
||||
|
|
|
|||
|
|
@ -83,6 +83,11 @@ extern const char* vvp_signal_label(ivl_signal_t sig);
|
|||
extern unsigned width_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);
|
||||
|
||||
/*
|
||||
|
|
@ -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 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 pad_expr_in_place(ivl_expr_t expr, struct vector_info res,
|
||||
|
|
|
|||
|
|
@ -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_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_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_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%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/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/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -952,10 +952,26 @@ statement. The <type> is 0 for nets and 1 for registers. See the other
|
|||
%release commands above.
|
||||
|
||||
* %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
|
||||
contains the word address within the dynamic array, and <bit>,<wid>
|
||||
specifies the thread vector to be written.
|
||||
The "%set/dar" opcode sets a vector to a word of the dynamic
|
||||
array. Index register 3 contains the word address within the dynamic
|
||||
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>
|
||||
|
||||
|
|
|
|||
|
|
@ -4921,6 +4921,59 @@ bool of_SET_DAR(vthread_t thr, vvp_code_t cp)
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue