Merge branch 'work1'
This commit is contained in:
commit
3733c59e49
|
|
@ -302,7 +302,7 @@ else
|
|||
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/sv_vpi_user.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
|
||||
|
||||
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
|
||||
|
|
@ -323,6 +323,9 @@ $(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
|||
$(includedir)/_pli_types.h: _pli_types.h
|
||||
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_pli_types.h"
|
||||
|
||||
$(includedir)/sv_vpi_user.h: $(srcdir)/sv_vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"
|
||||
|
||||
|
|
|
|||
4
PTask.h
4
PTask.h
|
|
@ -37,7 +37,9 @@ enum PTaskFuncEnum {
|
|||
PTF_INTEGER,
|
||||
PTF_REAL,
|
||||
PTF_REALTIME,
|
||||
PTF_TIME
|
||||
PTF_TIME,
|
||||
PTF_ATOM2,
|
||||
PTF_ATOM2_S
|
||||
};
|
||||
|
||||
struct PTaskFuncArg {
|
||||
|
|
|
|||
10
compiler.h
10
compiler.h
|
|
@ -151,6 +151,16 @@ extern bool gn_io_range_error_flag;
|
|||
re-evaluated. */
|
||||
extern bool gn_strict_ca_eval_flag;
|
||||
|
||||
/* If variables can be converted to uwires by a continuous assignment
|
||||
(assuming no procedural assign, then return true. This will be true
|
||||
for SystemVerilog */
|
||||
static inline bool gn_var_can_be_uwire(void)
|
||||
{
|
||||
if (generation_flag == GN_VER2009)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
|
||||
sets of keywords. The compiler enables groups of keywords by setting
|
||||
lexor_keyword_mask with the OR of the bits for the keywords to be
|
||||
|
|
|
|||
|
|
@ -335,9 +335,17 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastInt::dump_node(ostream&o, unsigned ind) const
|
||||
void NetCastInt2::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
|
||||
o << setw(ind) << "" << "Cast to int2. (NetCastInt2): " <<
|
||||
name() << " width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCastInt4::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Cast to int4. (NetCastInt4): " <<
|
||||
name() << " width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
@ -660,7 +668,8 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
|||
if (rise_time())
|
||||
o << " #(" <<*rise_time()
|
||||
<<","<<*fall_time()
|
||||
<< "," <<*decay_time() << ")" << endl;
|
||||
<< "," <<*decay_time() << ")";
|
||||
o << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
|
|||
16
elab_net.cc
16
elab_net.cc
|
|
@ -414,6 +414,22 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
|
||||
assert(sig);
|
||||
|
||||
/* If this is SystemVerilog and the variable is not yet
|
||||
assigned by anything, then convert it to an unresolved
|
||||
wire. */
|
||||
if (gn_var_can_be_uwire()
|
||||
&& (sig->type() == NetNet::REG)
|
||||
&& (sig->peek_eref() == 0) ) {
|
||||
sig->type(NetNet::UNRESOLVED_WIRE);
|
||||
}
|
||||
|
||||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->pin(0).is_linked()) {
|
||||
cerr << get_fileline() << ": error: Unresolved net " << sig->name()
|
||||
<< " cannot have multiple drivers." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't allow registers as assign l-values. */
|
||||
if (sig->type() == NetNet::REG) {
|
||||
cerr << get_fileline() << ": error: reg " << sig->name()
|
||||
|
|
|
|||
59
elab_sig.cc
59
elab_sig.cc
|
|
@ -69,6 +69,15 @@ static bool get_const_argument(NetExpr*exp, verinum&res)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool get_const_argument(NetExpr*exp, long&res)
|
||||
{
|
||||
verinum tmp;
|
||||
bool rc = get_const_argument(exp, tmp);
|
||||
if (rc == false) return false;
|
||||
res = tmp.as_long();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Statement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
}
|
||||
|
|
@ -472,18 +481,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) {
|
||||
mnum = tmp->value().as_long();
|
||||
} else {
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
cerr << me->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *me << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(le)) {
|
||||
lnum = tmp->value().as_long();
|
||||
} else {
|
||||
if ( ! get_const_argument(le, lnum) ) {
|
||||
cerr << le->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *le << "." << endl;
|
||||
|
|
@ -534,6 +539,48 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
ret_sig->data_type(IVL_VT_REAL);
|
||||
break;
|
||||
|
||||
case PTF_ATOM2:
|
||||
case PTF_ATOM2_S:
|
||||
ivl_assert(*this, return_type_.range != 0);
|
||||
probe_expr_width(des, scope, (*return_type_.range)[0]);
|
||||
probe_expr_width(des, scope, (*return_type_.range)[1]);
|
||||
long use_wid;
|
||||
{
|
||||
need_constant_expr = true;
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1);
|
||||
assert(le);
|
||||
need_constant_expr = false;
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( ! get_const_argument(me, mnum) ) {
|
||||
cerr << me->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *me << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( ! get_const_argument(le, lnum) ) {
|
||||
cerr << le->get_fileline() << ": error: "
|
||||
"Unable to evaluate constant expression "
|
||||
<< *le << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
use_wid = mnum - lnum + 1;
|
||||
}
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, use_wid);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
|
||||
ret_sig->set_isint(true);
|
||||
ret_sig->set_scalar(false);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_BOOL);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ports_) {
|
||||
cerr << get_fileline() << ": internal error: I don't know "
|
||||
|
|
|
|||
32
elaborate.cc
32
elaborate.cc
|
|
@ -129,13 +129,17 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
|||
need_driver_flag = true;
|
||||
|
||||
/* Cast the right side when needed. */
|
||||
if ((lval->data_type() == IVL_VT_REAL &&
|
||||
rval->data_type() != IVL_VT_REAL)) {
|
||||
if ((lval->data_type() == IVL_VT_REAL) &&
|
||||
(rval->data_type() != IVL_VT_REAL)) {
|
||||
rval = cast_to_real(des, scope, rval);
|
||||
need_driver_flag = false;
|
||||
} else if ((lval->data_type() != IVL_VT_REAL &&
|
||||
rval->data_type() == IVL_VT_REAL)) {
|
||||
rval = cast_to_int(des, scope, rval, lval->vector_width());
|
||||
} else if ((lval->data_type() == IVL_VT_BOOL) &&
|
||||
(rval->data_type() != IVL_VT_BOOL)) {
|
||||
rval = cast_to_int2(des, scope, rval, lval->vector_width());
|
||||
need_driver_flag = false;
|
||||
} else if ((lval->data_type() != IVL_VT_REAL) &&
|
||||
(rval->data_type() == IVL_VT_REAL)) {
|
||||
rval = cast_to_int4(des, scope, rval, lval->vector_width());
|
||||
need_driver_flag = false;
|
||||
}
|
||||
|
||||
|
|
@ -1370,7 +1374,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
// thing needs to go to each instance when arrayed.
|
||||
if ((sig->data_type() == IVL_VT_REAL ) &&
|
||||
!prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) {
|
||||
sig = cast_to_int(des, scope, sig,
|
||||
sig = cast_to_int4(des, scope, sig,
|
||||
prts_vector_width/instance.size());
|
||||
}
|
||||
// If we have a bit/vector signal driving a real port
|
||||
|
|
@ -1478,7 +1482,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
prts_vector_width = sig->vector_width();
|
||||
for (unsigned pidx = 0; pidx < prts.size(); pidx += 1) {
|
||||
prts[pidx]->port_type(NetNet::NOT_A_PORT);
|
||||
prts[pidx] = cast_to_int(des, scope, prts[pidx],
|
||||
prts[pidx] = cast_to_int4(des, scope, prts[pidx],
|
||||
prts_vector_width /
|
||||
instance.size());
|
||||
prts[pidx]->port_type(NetNet::POUTPUT);
|
||||
|
|
@ -2261,6 +2265,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
ivl_assert(*this, rv->expr_width() >= wid);
|
||||
}
|
||||
|
||||
if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Cast expression to int2" << endl;
|
||||
rv = cast_to_int2(rv);
|
||||
}
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, rv);
|
||||
cur->set_line(*this);
|
||||
|
||||
|
|
@ -3558,6 +3568,14 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
|||
rexp->set_width(lwid, true);
|
||||
rexp = pad_to_width(rexp, lwid, *this);
|
||||
|
||||
if (ltype==IVL_VT_BOOL && rexp->expr_type()!=IVL_VT_BOOL) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Cast force rvalue to int2" << endl;
|
||||
}
|
||||
rexp = cast_to_int2(rexp);
|
||||
}
|
||||
|
||||
dev = new NetForce(lval, rexp);
|
||||
|
||||
if (debug_elaborate) {
|
||||
|
|
|
|||
9
emit.cc
9
emit.cc
|
|
@ -72,9 +72,14 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NetCastInt::emit_node(struct target_t*tgt) const
|
||||
bool NetCastInt2::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_int(this);
|
||||
return tgt->lpm_cast_int2(this);
|
||||
}
|
||||
|
||||
bool NetCastInt4::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_cast_int4(this);
|
||||
}
|
||||
|
||||
bool NetCastReal::emit_node(struct target_t*tgt) const
|
||||
|
|
|
|||
|
|
@ -737,8 +737,16 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
||||
if (tmp[idx] == 0) flag = false;
|
||||
/* Set the data type to the first one found. */
|
||||
if (data_type == IVL_VT_NO_TYPE) {
|
||||
data_type = tmp[idx]->data_type();
|
||||
switch (data_type) {
|
||||
case IVL_VT_NO_TYPE:
|
||||
data_type = tmp[idx]->data_type();
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
if (tmp[idx]->data_type()==IVL_VT_LOGIC)
|
||||
data_type = IVL_VT_LOGIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -985,7 +993,7 @@ NetNet* NetECast::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
|||
|
||||
switch (op()) {
|
||||
case 'i':
|
||||
isig = cast_to_int(des, scope, isig, isig->vector_width());
|
||||
isig = cast_to_int4(des, scope, isig, isig->vector_width());
|
||||
break;
|
||||
case 'r':
|
||||
isig = cast_to_real(des, scope, isig);
|
||||
|
|
|
|||
|
|
@ -272,7 +272,8 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_ABS = 32,
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CAST_INT = 34,
|
||||
IVL_LPM_CAST_INT = 34,
|
||||
IVL_LPM_CAST_INT2 = 35,
|
||||
IVL_LPM_CAST_REAL = 33,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
|
|
|
|||
18
netlist.cc
18
netlist.cc
|
|
@ -78,7 +78,7 @@ ostream& operator<< (ostream&o, NetNet::Type t)
|
|||
case NetNet::WIRE:
|
||||
o << "wire";
|
||||
break;
|
||||
case NetNet::UWIRE:
|
||||
case NetNet::UNRESOLVED_WIRE:
|
||||
o << "uwire";
|
||||
}
|
||||
return o;
|
||||
|
|
@ -951,7 +951,14 @@ const NetScope* NetAnalogTop::scope() const
|
|||
return scope_;
|
||||
}
|
||||
|
||||
NetCastInt::NetCastInt(NetScope*scope__, perm_string n, unsigned width__)
|
||||
NetCastInt2::NetCastInt2(NetScope*scope__, perm_string n, unsigned width__)
|
||||
: NetNode(scope__, n, 2), width_(width__)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
NetCastInt4::NetCastInt4(NetScope*scope__, perm_string n, unsigned width__)
|
||||
: NetNode(scope__, n, 2), width_(width__)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
|
|
@ -2359,11 +2366,13 @@ ivl_variable_type_t NetETernary::expr_type() const
|
|||
ivl_assert(*this, false_val_);
|
||||
ivl_variable_type_t tru = true_val_->expr_type();
|
||||
ivl_variable_type_t fal = false_val_->expr_type();
|
||||
ivl_variable_type_t sel = cond_->expr_type();
|
||||
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
|
||||
return IVL_VT_LOGIC;
|
||||
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
if (sel == IVL_VT_LOGIC && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL) && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
|
||||
return IVL_VT_LOGIC;
|
||||
if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
|
||||
return IVL_VT_REAL;
|
||||
if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
|
||||
|
|
@ -2455,6 +2464,9 @@ ivl_variable_type_t NetECast::expr_type() const
|
|||
case 'r':
|
||||
ret = IVL_VT_REAL;
|
||||
break;
|
||||
case '2':
|
||||
ret = IVL_VT_BOOL;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
|||
21
netlist.h
21
netlist.h
|
|
@ -553,7 +553,7 @@ class NetNet : public NetObj {
|
|||
public:
|
||||
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
||||
UWIRE };
|
||||
UNRESOLVED_WIRE };
|
||||
|
||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
||||
|
||||
|
|
@ -1016,10 +1016,24 @@ class NetArrayDq : public NetNode {
|
|||
* Convert an IVL_VT_REAL input to a logical value with the
|
||||
* given width. The input is pin(1) and the output is pin(0).
|
||||
*/
|
||||
class NetCastInt : public NetNode {
|
||||
class NetCastInt4 : public NetNode {
|
||||
|
||||
public:
|
||||
NetCastInt(NetScope*s, perm_string n, unsigned width);
|
||||
NetCastInt4(NetScope*s, perm_string n, unsigned width);
|
||||
|
||||
unsigned width() const { return width_; }
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
class NetCastInt2 : public NetNode {
|
||||
|
||||
public:
|
||||
NetCastInt2(NetScope*s, perm_string n, unsigned width);
|
||||
|
||||
unsigned width() const { return width_; }
|
||||
|
||||
|
|
@ -3763,6 +3777,7 @@ class NetETernary : public NetExpr {
|
|||
* X -- Reduction NXOR (~^ or ^~)
|
||||
* m -- abs(x) (i.e. "magnitude")
|
||||
* i -- Cast from real to integer (vector)
|
||||
* 2 -- Cast from real or logic (vector) to bool (vector)
|
||||
* r -- Cast from integer (vector) to real
|
||||
*/
|
||||
class NetEUnary : public NetExpr {
|
||||
|
|
|
|||
32
netmisc.cc
32
netmisc.cc
|
|
@ -116,7 +116,27 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
||||
NetNet* cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
||||
{
|
||||
if (src->data_type() == IVL_VT_BOOL)
|
||||
return src;
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
|
||||
tmp->data_type(IVL_VT_BOOL);
|
||||
tmp->set_line(*src);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetCastInt2*cast = new NetCastInt2(scope, scope->local_symbol(), wid);
|
||||
cast->set_line(*src);
|
||||
des->add_node(cast);
|
||||
|
||||
connect(cast->pin(0), tmp->pin(0));
|
||||
connect(cast->pin(1), src->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
||||
{
|
||||
if (src->data_type() != IVL_VT_REAL)
|
||||
return src;
|
||||
|
|
@ -126,7 +146,7 @@ NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
|||
tmp->set_line(*src);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetCastInt*cast = new NetCastInt(scope, scope->local_symbol(), wid);
|
||||
NetCastInt4*cast = new NetCastInt4(scope, scope->local_symbol(), wid);
|
||||
cast->set_line(*src);
|
||||
des->add_node(cast);
|
||||
|
||||
|
|
@ -156,6 +176,14 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* cast_to_int2(NetExpr*expr)
|
||||
{
|
||||
NetECast*cast = new NetECast('2', expr);
|
||||
cast->set_line(*expr);
|
||||
cast->cast_signed(expr->has_sign());
|
||||
return cast;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a signed constant to an existing expression. Generate a new
|
||||
* NetEBAdd node that has the input expression and an expression made
|
||||
|
|
|
|||
|
|
@ -74,9 +74,12 @@ extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w,
|
|||
* Generate the nodes necessary to cast an expression (a net) to a
|
||||
* real value.
|
||||
*/
|
||||
extern NetNet*cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid);
|
||||
extern NetNet*cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid);
|
||||
extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid);
|
||||
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
|
||||
|
||||
extern NetExpr*cast_to_int2(NetExpr*expr);
|
||||
|
||||
/*
|
||||
* Take the input expression and return a variation that assures that
|
||||
* the expression is 1-bit wide and logical. This reflects the needs
|
||||
|
|
|
|||
359
parse.y
359
parse.y
|
|
@ -106,6 +106,16 @@ static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
static svector<PExpr*>* make_range_from_width(uint64_t wid)
|
||||
{
|
||||
svector<PExpr*>*range = new svector<PExpr*>(2);
|
||||
|
||||
(*range)[0] = new PENumber(new verinum(wid-1, integer_width));
|
||||
(*range)[1] = new PENumber(new verinum((uint64_t)0, integer_width));
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
static list<perm_string>* list_from_identifier(char*id)
|
||||
{
|
||||
list<perm_string>*tmp = new list<perm_string>;
|
||||
|
|
@ -167,6 +177,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
bool flag;
|
||||
|
||||
char letter;
|
||||
int int_val;
|
||||
|
||||
/* text items are C strings allocated by the lexor using
|
||||
strdup. They can be put into lists with the texts type. */
|
||||
|
|
@ -319,7 +330,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
|
||||
%type <flag> from_exclude
|
||||
%type <number> number
|
||||
%type <flag> signed_opt udp_reg_opt edge_operator automatic_opt
|
||||
%type <flag> unsigned_signed_opt signed_unsigned_opt
|
||||
%type <flag> udp_reg_opt edge_operator automatic_opt
|
||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
%type <letter> udp_input_sym udp_output_sym
|
||||
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
|
||||
|
|
@ -393,6 +405,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
%type <specpath> specify_simple_path specify_simple_path_decl
|
||||
%type <specpath> specify_edge_path specify_edge_path_decl
|
||||
|
||||
%type <int_val> atom2_type
|
||||
|
||||
%token K_TAND
|
||||
%right '?' ':'
|
||||
%left K_LOR
|
||||
|
|
@ -494,7 +508,7 @@ attribute
|
|||
|
||||
block_item_decl
|
||||
: attribute_list_opt K_reg
|
||||
primitive_type_opt signed_opt range
|
||||
primitive_type_opt unsigned_signed_opt range
|
||||
register_variable_list ';'
|
||||
{ ivl_variable_type_t dtype = $3;
|
||||
if (dtype == IVL_VT_NO_TYPE)
|
||||
|
|
@ -507,7 +521,7 @@ block_item_decl
|
|||
range. This is the rule for a scalar. */
|
||||
|
||||
| attribute_list_opt K_reg
|
||||
primitive_type_opt signed_opt
|
||||
primitive_type_opt unsigned_signed_opt
|
||||
register_variable_list ';'
|
||||
{ ivl_variable_type_t dtype = $3;
|
||||
if (dtype == IVL_VT_NO_TYPE)
|
||||
|
|
@ -516,18 +530,24 @@ block_item_decl
|
|||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
/* Integer declarations are simpler in that they do not have all the
|
||||
trappings of a general variable declaration. All of that is
|
||||
implicit in the "integer" of the declaration. */
|
||||
/* Integer atom declarations are simpler in that they do not have
|
||||
all the trappings of a general variable declaration. All of that
|
||||
is implicit in the "integer" of the declaration. */
|
||||
|
||||
| attribute_list_opt K_integer register_variable_list ';'
|
||||
{ pform_set_reg_integer($3);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| attribute_list_opt K_integer signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_reg_integer($4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
| attribute_list_opt K_time register_variable_list ';'
|
||||
{ pform_set_reg_time($3);
|
||||
}
|
||||
| attribute_list_opt K_time register_variable_list ';'
|
||||
{ pform_set_reg_time($3);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
| attribute_list_opt atom2_type signed_unsigned_opt register_variable_list ';'
|
||||
{ pform_set_integer_2atom($2, $3, $4);
|
||||
if ($1) delete $1;
|
||||
}
|
||||
|
||||
/* real declarations are fairly simple as there is no range of
|
||||
signed flag in the declaration. Create the real as a NetNet::REG
|
||||
|
|
@ -1880,7 +1900,7 @@ list_of_port_declarations
|
|||
|
||||
port_declaration
|
||||
: attribute_list_opt
|
||||
K_input net_type_opt primitive_type_opt signed_opt range_opt IDENTIFIER
|
||||
K_input net_type_opt primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($7);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
|
|
@ -1897,8 +1917,27 @@ port_declaration
|
|||
delete[]$7;
|
||||
$$ = ptmp;
|
||||
}
|
||||
| attribute_list_opt K_input atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($5);
|
||||
svector<PExpr*>*use_range = make_range_from_width($3);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT,
|
||||
NetNet::UNRESOLVED_WIRE, IVL_VT_BOOL,
|
||||
$4, use_range, $1);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.port_net_type = NetNet::UNRESOLVED_WIRE;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $4;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = use_range;
|
||||
delete $1;
|
||||
delete[]$5;
|
||||
$$ = ptmp;
|
||||
}
|
||||
| attribute_list_opt
|
||||
K_inout net_type_opt primitive_type_opt signed_opt range_opt IDENTIFIER
|
||||
K_inout net_type_opt primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($7);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
|
|
@ -1916,7 +1955,7 @@ port_declaration
|
|||
$$ = ptmp;
|
||||
}
|
||||
| attribute_list_opt
|
||||
K_output net_type_opt primitive_type_opt signed_opt range_opt IDENTIFIER
|
||||
K_output net_type_opt primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($7);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
|
|
@ -1934,7 +1973,7 @@ port_declaration
|
|||
$$ = ptmp;
|
||||
}
|
||||
| attribute_list_opt
|
||||
K_output var_type primitive_type_opt signed_opt range_opt IDENTIFIER
|
||||
K_output var_type primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($7);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
|
|
@ -1952,7 +1991,7 @@ port_declaration
|
|||
$$ = ptmp;
|
||||
}
|
||||
| attribute_list_opt
|
||||
K_output var_type primitive_type_opt signed_opt range_opt IDENTIFIER '=' expression
|
||||
K_output var_type primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER '=' expression
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($7);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
|
|
@ -1972,6 +2011,25 @@ port_declaration
|
|||
delete[]$7;
|
||||
$$ = ptmp;
|
||||
}
|
||||
| attribute_list_opt K_output atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($5);
|
||||
svector<PExpr*>*use_range = make_range_from_width($3);
|
||||
ptmp = pform_module_port_reference(name, @2.text,
|
||||
@2.first_line);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
NetNet::IMPLICIT_REG, IVL_VT_BOOL,
|
||||
$4, use_range, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = NetNet::IMPLICIT_REG;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $4;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = use_range;
|
||||
delete $1;
|
||||
delete[]$5;
|
||||
$$ = ptmp;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
|
|
@ -1981,7 +2039,38 @@ net_type_opt
|
|||
| { $$ = NetNet::IMPLICIT; }
|
||||
;
|
||||
|
||||
signed_opt : K_signed { $$ = true; } | {$$ = false; } ;
|
||||
/*
|
||||
* The signed_opt rule will return "true" if K_signed is present,
|
||||
* for "false" otherwise. This rule corresponds to the declaration
|
||||
* defaults for reg/bit/logic.
|
||||
*
|
||||
* The signed_unsigned_opt rule with match K_signed or K_unsigned
|
||||
* and return true or false as appropriate. The default is
|
||||
* "true". This corresponds to the declaration defaults for
|
||||
* byte/shortint/int/longint.
|
||||
*/
|
||||
unsigned_signed_opt
|
||||
: K_signed { $$ = true; }
|
||||
| K_unsigned { $$ = false; }
|
||||
| { $$ = false; }
|
||||
;
|
||||
|
||||
signed_unsigned_opt
|
||||
: K_signed { $$ = true; }
|
||||
| K_unsigned { $$ = false; }
|
||||
| { $$ = true; }
|
||||
;
|
||||
|
||||
/*
|
||||
* In some places we can take any of the 4 2-value atom-type
|
||||
* names. All the context needs to know if that type is its width.
|
||||
*/
|
||||
atom2_type
|
||||
: K_byte { $$ = 8; }
|
||||
| K_shortint { $$ = 16; }
|
||||
| K_int { $$ = 32; }
|
||||
| K_longint { $$ = 64; }
|
||||
;
|
||||
|
||||
/* An lpvalue is the expression that can go on the left side of a
|
||||
procedural assignment. This rule handles only procedural
|
||||
|
|
@ -2118,7 +2207,7 @@ module_item
|
|||
resort to the default type LOGIC. */
|
||||
|
||||
: attribute_list_opt net_type
|
||||
primitive_type_opt signed_opt range_opt
|
||||
primitive_type_opt unsigned_signed_opt range_opt
|
||||
delay3_opt
|
||||
net_variable_list ';'
|
||||
|
||||
|
|
@ -2139,7 +2228,7 @@ module_item
|
|||
declarations. */
|
||||
|
||||
| attribute_list_opt net_type
|
||||
primitive_type_opt signed_opt range_opt
|
||||
primitive_type_opt unsigned_signed_opt range_opt
|
||||
delay3_opt net_decl_assigns ';'
|
||||
|
||||
{ ivl_variable_type_t dtype = $3;
|
||||
|
|
@ -2158,7 +2247,7 @@ module_item
|
|||
gives strength to the assignment drivers. */
|
||||
|
||||
| attribute_list_opt net_type
|
||||
primitive_type_opt signed_opt
|
||||
primitive_type_opt unsigned_signed_opt
|
||||
drive_strength net_decl_assigns ';'
|
||||
|
||||
{ ivl_variable_type_t dtype = $3;
|
||||
|
|
@ -2178,7 +2267,7 @@ module_item
|
|||
delete $4;
|
||||
}
|
||||
|
||||
| port_type signed_opt range_opt delay3_opt list_of_identifiers ';'
|
||||
| port_type unsigned_signed_opt range_opt delay3_opt list_of_identifiers ';'
|
||||
{ pform_set_port_type(@1, $5, $3, $2, $1);
|
||||
}
|
||||
|
||||
|
|
@ -2186,12 +2275,12 @@ module_item
|
|||
input wire signed [h:l] <list>;
|
||||
This creates the wire and sets the port type all at once. */
|
||||
|
||||
| port_type net_type signed_opt range_opt list_of_identifiers ';'
|
||||
| port_type net_type unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0,
|
||||
SR_BOTH);
|
||||
}
|
||||
|
||||
| K_output var_type signed_opt range_opt list_of_port_identifiers ';'
|
||||
| K_output var_type unsigned_signed_opt range_opt list_of_port_identifiers ';'
|
||||
{ list<pair<perm_string,PExpr*> >::const_iterator pp;
|
||||
list<perm_string>*tmp = new list<perm_string>;
|
||||
for (pp = $5->begin(); pp != $5->end(); pp++) {
|
||||
|
|
@ -2211,19 +2300,19 @@ module_item
|
|||
because the port declaration implies an external driver, which
|
||||
cannot be attached to a reg. These rules catch that error early. */
|
||||
|
||||
| K_input var_type signed_opt range_opt list_of_identifiers ';'
|
||||
| K_input var_type unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINPUT,
|
||||
IVL_VT_NO_TYPE, 0);
|
||||
yyerror(@2, "error: reg variables cannot be inputs.");
|
||||
}
|
||||
|
||||
| K_inout var_type signed_opt range_opt list_of_identifiers ';'
|
||||
| K_inout var_type unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINOUT,
|
||||
IVL_VT_NO_TYPE, 0);
|
||||
yyerror(@2, "error: reg variables cannot be inouts.");
|
||||
}
|
||||
|
||||
| port_type signed_opt range_opt delay3_opt error ';'
|
||||
| port_type unsigned_signed_opt range_opt delay3_opt error ';'
|
||||
{ yyerror(@1, "error: Invalid variable list"
|
||||
" in port declaration.");
|
||||
if ($3) delete $3;
|
||||
|
|
@ -2639,10 +2728,11 @@ net_decl_assigns
|
|||
;
|
||||
|
||||
primitive_type
|
||||
: K_logic { $$ = IVL_VT_LOGIC; }
|
||||
| K_bool { $$ = IVL_VT_BOOL; }
|
||||
| K_real { $$ = IVL_VT_REAL; }
|
||||
;
|
||||
: K_logic { $$ = IVL_VT_LOGIC; }
|
||||
| K_bool { $$ = IVL_VT_BOOL; /* Icarus Verilog xtypes */}
|
||||
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
|
||||
| K_real { $$ = IVL_VT_REAL; }
|
||||
;
|
||||
|
||||
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
|
||||
|
||||
|
|
@ -2657,12 +2747,12 @@ net_type
|
|||
| K_supply1 { $$ = NetNet::SUPPLY1; }
|
||||
| K_wor { $$ = NetNet::WOR; }
|
||||
| K_trior { $$ = NetNet::TRIOR; }
|
||||
| K_wone { $$ = NetNet::UWIRE;
|
||||
| K_wone { $$ = NetNet::UNRESOLVED_WIRE;
|
||||
cerr << @1.text << ":" << @1.first_line << ": warning: "
|
||||
"'wone' is deprecated, please use 'uwire' "
|
||||
"instead." << endl;
|
||||
}
|
||||
| K_uwire { $$ = NetNet::UWIRE; }
|
||||
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
|
||||
;
|
||||
|
||||
var_type
|
||||
|
|
@ -3195,14 +3285,18 @@ dimensions
|
|||
|
||||
/* This is used to express the return type of a function. */
|
||||
function_range_or_type_opt
|
||||
: range { $$.range = $1; $$.type = PTF_REG; }
|
||||
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
||||
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
||||
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
||||
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
||||
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
||||
| { $$.range = 0; $$.type = PTF_REG; }
|
||||
;
|
||||
: range { $$.range = $1; $$.type = PTF_REG; }
|
||||
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
||||
| K_unsigned range { $$.range = $2; $$.type = PTF_REG; }
|
||||
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
||||
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
||||
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
||||
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
||||
| atom2_type { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
|
||||
| atom2_type K_signed { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
|
||||
| atom2_type K_unsigned { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2; }
|
||||
| { $$.range = 0; $$.type = PTF_REG; }
|
||||
;
|
||||
|
||||
/* The register_variable rule is matched only when I am parsing
|
||||
variables in a "reg" definition. I therefore know that I am
|
||||
|
|
@ -4039,30 +4133,27 @@ reg_opt
|
|||
|
||||
task_port_item
|
||||
|
||||
: K_input reg_opt signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
: K_input reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_NO_TYPE, $3,
|
||||
$4, $5,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output reg_opt signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT,
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC, $3,
|
||||
$4, $5,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout reg_opt signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT,
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_LOGIC, $3,
|
||||
$4, $5,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* When the port is an integer, infer a signed vector of the integer
|
||||
shape. Generate a range ([31:0]) to make it work. */
|
||||
|
|
@ -4206,7 +4297,7 @@ task_item_list_opt
|
|||
|
||||
task_port_decl
|
||||
|
||||
: K_input reg_opt signed_opt range_opt IDENTIFIER
|
||||
: K_input reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
|
|
@ -4220,7 +4311,7 @@ task_port_decl
|
|||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_output reg_opt signed_opt range_opt IDENTIFIER
|
||||
| K_output reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
|
|
@ -4233,7 +4324,7 @@ task_port_decl
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout reg_opt signed_opt range_opt IDENTIFIER
|
||||
| K_inout reg_opt unsigned_signed_opt range_opt IDENTIFIER
|
||||
{ port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
|
|
@ -4315,66 +4406,48 @@ task_port_decl
|
|||
|
||||
/* Ports can be time with a width of [63:0] (unsigned). */
|
||||
|
||||
| K_input K_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum((uint64_t)63, integer_width));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
||||
(*range_stub)[1] = re;
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output K_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum((uint64_t)63, integer_width));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
||||
(*range_stub)[1] = re;
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout K_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum((uint64_t)63, integer_width));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
||||
(*range_stub)[1] = re;
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_input K_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output K_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout K_time IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||
port_declaration_context.sign_flag = false;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_LOGIC, false,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be real or realtime. */
|
||||
|
||||
|
|
@ -4417,7 +4490,51 @@ task_port_decl
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
/* Ports can be 2-value atom types. */
|
||||
|
||||
| K_input atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width($2);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_BOOL, $3,
|
||||
range_stub, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_output atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width($2);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_BOOL, $3,
|
||||
range_stub, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_inout atom2_type signed_unsigned_opt IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub = make_range_from_width($2);
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.var_type = IVL_VT_BOOL;
|
||||
port_declaration_context.sign_flag = $3;
|
||||
delete port_declaration_context.range;
|
||||
port_declaration_context.range = copy_range(range_stub);
|
||||
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_BOOL, $3,
|
||||
range_stub, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_port_decl_list
|
||||
: task_port_decl_list ',' task_port_decl
|
||||
|
|
|
|||
32
pform.cc
32
pform.cc
|
|
@ -2431,6 +2431,38 @@ void pform_set_reg_time(list<perm_string>*names)
|
|||
delete names;
|
||||
}
|
||||
|
||||
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_BOOL);
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::REG);
|
||||
assert(rc);
|
||||
rc = cur->set_data_type(IVL_VT_BOOL);
|
||||
assert(rc);
|
||||
}
|
||||
|
||||
assert(cur);
|
||||
|
||||
cur->set_signed(signed_flag);
|
||||
cur->set_range(new PENumber(new verinum(width-1, integer_width)),
|
||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||
SR_NET, false);
|
||||
}
|
||||
|
||||
void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_integer_2atom(width, signed_flag, txt);
|
||||
}
|
||||
delete names;
|
||||
}
|
||||
|
||||
svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
{
|
||||
svector<PWire*>*out = new svector<PWire*>(names->size());
|
||||
|
|
|
|||
2
pform.h
2
pform.h
|
|
@ -275,6 +275,8 @@ extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
|
|||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
|
||||
extern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names);
|
||||
|
||||
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||
$attribute syntax, which can only set string values to
|
||||
attributes. The functions keep the value strings that are
|
||||
|
|
|
|||
|
|
@ -787,6 +787,12 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
|||
case PTF_TIME:
|
||||
out << "time ";
|
||||
break;
|
||||
case PTF_ATOM2:
|
||||
out << "int unsigned ";
|
||||
break;
|
||||
case PTF_ATOM2_S:
|
||||
cout << "int signed ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (return_type_.range) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
# NOTE: DO NOT INSTALL THIS FILE!
|
||||
#
|
||||
generation:2005
|
||||
generation:2009
|
||||
generation:specify
|
||||
generation:xtypes
|
||||
generation:verilog-ams
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef __sv_vpi_user_H
|
||||
#define __sv_vpi_user_H
|
||||
/*
|
||||
* Copyright (c) 2010 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
||||
#if defined(__MINGW32__) || defined (__CYGWIN32__)
|
||||
# define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define DLLEXPORT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define EXTERN_C_START extern "C" {
|
||||
# define EXTERN_C_END }
|
||||
#else
|
||||
# define EXTERN_C_START
|
||||
# define EXTERN_C_END
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
# undef __attribute__
|
||||
# define __attribute__(x)
|
||||
#endif
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
/********* OBJECT TYPES ***********/
|
||||
#define vpiLongIntVar 610
|
||||
#define vpiShortIntVar 611
|
||||
#define vpiIntVar 612
|
||||
#define vpiByteVar 614
|
||||
#define vpiLogicVar vpiReg
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
|
|
@ -964,6 +964,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
switch (net->type) {
|
||||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_CAST_INT:
|
||||
case IVL_LPM_CAST_INT2:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.a;
|
||||
|
|
@ -1108,6 +1109,7 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net)
|
|||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CAST_INT:
|
||||
case IVL_LPM_CAST_INT2:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
|
|
@ -1259,6 +1261,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_POW:
|
||||
case IVL_LPM_SUB:
|
||||
case IVL_LPM_CAST_INT2:
|
||||
return net->u_.arith.signed_flag;
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
|
|
|
|||
51
t-dll.cc
51
t-dll.cc
|
|
@ -1488,16 +1488,17 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_cast_int(const NetCastInt*net)
|
||||
bool dll_target::lpm_arith1_(ivl_lpm_type_t lpm_type, unsigned width, bool signed_flag, const NetNode*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_CAST_INT;
|
||||
obj->name = net->name(); // NetCastInt names are permallocated
|
||||
obj->type = lpm_type;
|
||||
obj->name = net->name(); // NetCastInt2 names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->width = net->width();
|
||||
obj->width = width;
|
||||
obj->u_.arith.signed_flag = signed_flag? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
|
|
@ -1520,37 +1521,19 @@ bool dll_target::lpm_cast_int(const NetCastInt*net)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool dll_target::lpm_cast_int2(const NetCastInt2*net)
|
||||
{
|
||||
return lpm_arith1_(IVL_LPM_CAST_INT2, net->width(), true, net);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_cast_int4(const NetCastInt4*net)
|
||||
{
|
||||
return lpm_arith1_(IVL_LPM_CAST_INT, net->width(), true, net);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_cast_real(const NetCastReal*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_CAST_REAL;
|
||||
obj->name = net->name(); // NetCastReal names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->width = 0;
|
||||
obj->u_.arith.signed_flag = net->signed_flag()? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
make_lpm_delays_(obj, net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
return true;
|
||||
return lpm_arith1_(IVL_LPM_CAST_REAL, 0, net->signed_flag(), net);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2389,7 +2372,7 @@ void dll_target::signal(const NetNet*net)
|
|||
|
||||
/* We will convert this to a TRI after we check that there
|
||||
is only one driver. */
|
||||
case NetNet::UWIRE:
|
||||
case NetNet::UNRESOLVED_WIRE:
|
||||
obj->type_ = IVL_SIT_UWIRE;
|
||||
break;
|
||||
|
||||
|
|
|
|||
5
t-dll.h
5
t-dll.h
|
|
@ -67,7 +67,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_abs(const NetAbs*);
|
||||
void lpm_add_sub(const NetAddSub*);
|
||||
bool lpm_array_dq(const NetArrayDq*);
|
||||
bool lpm_cast_int(const NetCastInt*);
|
||||
bool lpm_cast_int2(const NetCastInt2*);
|
||||
bool lpm_cast_int4(const NetCastInt4*);
|
||||
bool lpm_cast_real(const NetCastReal*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
|
|
@ -175,6 +176,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
ivl_event_t make_lpm_trigger(const NetEvWait*ev);
|
||||
|
||||
bool lpm_arith1_(ivl_lpm_type_t lpm_type, unsigned wid, bool signed_flag, const NetNode*net);
|
||||
|
||||
static ivl_expr_t expr_from_value_(const verinum&that);
|
||||
};
|
||||
|
||||
|
|
|
|||
11
target.cc
11
target.cc
|
|
@ -114,10 +114,17 @@ bool target_t::lpm_array_dq(const NetArrayDq*)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool target_t::lpm_cast_int(const NetCastInt*)
|
||||
bool target_t::lpm_cast_int2(const NetCastInt2*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetCastInt." << endl;
|
||||
"Unhandled NetCastInt2." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::lpm_cast_int4(const NetCastInt4*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetCastInt4." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
3
target.h
3
target.h
|
|
@ -75,7 +75,8 @@ struct target_t {
|
|||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual bool lpm_array_dq(const NetArrayDq*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual bool lpm_cast_int(const NetCastInt*);
|
||||
virtual bool lpm_cast_int2(const NetCastInt2*);
|
||||
virtual bool lpm_cast_int4(const NetCastInt4*);
|
||||
virtual bool lpm_cast_real(const NetCastReal*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
|
|
|
|||
|
|
@ -468,6 +468,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
case IVL_LPM_ABS:
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_ARRAY:
|
||||
case IVL_LPM_CAST_INT2:
|
||||
case IVL_LPM_CAST_INT:
|
||||
case IVL_LPM_CAST_REAL:
|
||||
case IVL_LPM_CONCAT:
|
||||
|
|
|
|||
|
|
@ -55,6 +55,12 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
|||
clr_word(res);
|
||||
}
|
||||
|
||||
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
/* For now, treat bit2 variables as bit4 variables. */
|
||||
function_argument_logic(port, expr);
|
||||
}
|
||||
|
||||
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
|
|
@ -65,6 +71,9 @@ static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
|||
case IVL_VT_REAL:
|
||||
function_argument_real(port, expr);
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
function_argument_bool(port, expr);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
ivl_signal_basename(port), dtype);
|
||||
|
|
|
|||
|
|
@ -47,10 +47,14 @@ static int eval_bool64_logic(ivl_expr_t expr)
|
|||
{
|
||||
int res;
|
||||
struct vector_info tmp;
|
||||
const char*s_flag = "";
|
||||
|
||||
tmp = draw_eval_expr(expr, STUFF_OK_XZ);
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, tmp.base, tmp.wid);
|
||||
if (ivl_expr_signed(expr))
|
||||
s_flag = "/s";
|
||||
|
||||
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", s_flag, res, tmp.base, tmp.wid);
|
||||
clr_vector(tmp);
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -3126,6 +3126,21 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid)
|
|||
local_count += 1;
|
||||
break;
|
||||
|
||||
case '2': /* Cast logic to bool */
|
||||
assert(ivl_expr_value(sub) == IVL_VT_LOGIC);
|
||||
res = draw_eval_expr_wid(sub, wid, 0);
|
||||
|
||||
/* Handle special case that value is 0 or 1. */
|
||||
if (res.base == 0 || res.base == 1)
|
||||
break;
|
||||
if (res.base == 2 || res.base == 2) {
|
||||
res.base = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%cast2 %d, %d, %u;\n", res.base, res.base, res.wid);
|
||||
break;
|
||||
|
||||
case 'i': /* Cast a real value to an integer. */
|
||||
assert(ivl_expr_value(sub) == IVL_VT_REAL);
|
||||
word = draw_eval_real(sub);
|
||||
|
|
|
|||
|
|
@ -427,6 +427,12 @@ static void draw_reg_in_scope(ivl_signal_t sig)
|
|||
const char*local_flag = ivl_signal_local(sig)? "*" : "";
|
||||
|
||||
switch (ivl_signal_data_type(sig)) {
|
||||
case IVL_VT_BOOL:
|
||||
if (ivl_signal_signed(sig))
|
||||
datatype_flag = "/2s";
|
||||
else
|
||||
datatype_flag = "/2u";
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
datatype_flag = "/real";
|
||||
break;
|
||||
|
|
@ -470,6 +476,12 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
|||
unsigned iword;
|
||||
|
||||
switch (ivl_signal_data_type(sig)) {
|
||||
case IVL_VT_BOOL:
|
||||
if (ivl_signal_signed(sig))
|
||||
datatype_flag = "/2s";
|
||||
else
|
||||
datatype_flag = "/2u";
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
datatype_flag = "/real";
|
||||
break;
|
||||
|
|
@ -1209,6 +1221,19 @@ static void draw_lpm_abs(ivl_lpm_t net)
|
|||
net, dly, src_table[0]);
|
||||
}
|
||||
|
||||
static void draw_lpm_cast_int2(ivl_lpm_t net)
|
||||
{
|
||||
const char*src_table[1];
|
||||
const char*dly;
|
||||
|
||||
draw_lpm_data_inputs(net, 0, 1, src_table);
|
||||
|
||||
dly = draw_lpm_output_delay(net, IVL_VT_BOOL);
|
||||
|
||||
fprintf(vvp_out, "L_%p%s .cast/2 %u, %s;\n",
|
||||
net, dly, ivl_lpm_width(net), src_table[0]);
|
||||
}
|
||||
|
||||
static void draw_lpm_cast_int(ivl_lpm_t net)
|
||||
{
|
||||
const char*src_table[1];
|
||||
|
|
@ -1829,6 +1854,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_cast_int(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_CAST_INT2:
|
||||
draw_lpm_cast_int2(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_CAST_REAL:
|
||||
draw_lpm_cast_real(net);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1048,6 +1048,10 @@ static int sys_check_args(vpiHandle callh, vpiHandle argv, const PLI_BYTE8*name,
|
|||
case vpiNet:
|
||||
case vpiReg:
|
||||
case vpiIntegerVar:
|
||||
case vpiByteVar:
|
||||
case vpiShortIntVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiTimeVar:
|
||||
case vpiRealVar:
|
||||
case vpiSysFuncCall:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
#include "vpi_config.h"
|
||||
#include "vpi_user.h"
|
||||
#include "sv_vpi_user.h"
|
||||
|
||||
/*
|
||||
* Context structure for PRNG in mt19937int.c
|
||||
|
|
|
|||
|
|
@ -278,8 +278,10 @@ A variable is a bit vector that can be written by behavioral code (so
|
|||
has no structural input) and propagates its output to a functor. The
|
||||
general syntax of a variable is:
|
||||
|
||||
<label> .var "name", <msb>, <lsb>; Unsigned logic variable
|
||||
<label> .var/s "name", <msb>, <lsb>; Signed logic variable
|
||||
<label> .var "name", <msb> <lsb>; Unsigned logic variable
|
||||
<label> .var/s "name", <msb> <lsb>; Signed logic variable
|
||||
<label> .var/2u "name", <msb> <lsb>; Unsigned bool/bit variable
|
||||
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
|
||||
<label> .var/real "name", <msb>, <lsb>; real varibale
|
||||
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar variable
|
||||
|
||||
|
|
@ -356,6 +358,7 @@ net or from a bit based net to a real valued net. These statements
|
|||
are used to perform that operation:
|
||||
|
||||
<label> .cast/int <width>, <symbol>;
|
||||
<label> .cast/2 <width>, <symbol>;
|
||||
<label> .cast/real <symbol>;
|
||||
<label> .cast/real.s <symbol>;
|
||||
|
||||
|
|
|
|||
22
vvp/arith.cc
22
vvp/arith.cc
|
|
@ -121,6 +121,28 @@ void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
|||
ptr.ptr()->send_real(val, 0);
|
||||
}
|
||||
|
||||
vvp_arith_cast_vec2::vvp_arith_cast_vec2(unsigned wid)
|
||||
: wid_(wid)
|
||||
{
|
||||
}
|
||||
|
||||
vvp_arith_cast_vec2::~vvp_arith_cast_vec2()
|
||||
{
|
||||
}
|
||||
|
||||
void vvp_arith_cast_vec2::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
|
||||
}
|
||||
|
||||
void vvp_arith_cast_vec2::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t)
|
||||
{
|
||||
vvp_vector2_t tmp = bit;
|
||||
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,tmp.size()), 0);
|
||||
}
|
||||
|
||||
// Division
|
||||
|
||||
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
|
||||
|
|
|
|||
14
vvp/arith.h
14
vvp/arith.h
|
|
@ -86,6 +86,20 @@ class vvp_arith_cast_real : public vvp_net_fun_t {
|
|||
bool signed_;
|
||||
};
|
||||
|
||||
class vvp_arith_cast_vec2 : public vvp_net_fun_t {
|
||||
public:
|
||||
explicit vvp_arith_cast_vec2(unsigned wid);
|
||||
~vvp_arith_cast_vec2();
|
||||
|
||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||
vvp_context_t);
|
||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||
vvp_context_t);
|
||||
|
||||
private:
|
||||
unsigned wid_;
|
||||
};
|
||||
|
||||
class vvp_arith_div : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -52,9 +52,6 @@ extern void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle word);
|
|||
extern void vpip_array_change(struct __vpiCallback*cb, vpiHandle word);
|
||||
|
||||
/* Compile hooks */
|
||||
extern void compile_variablew(char*label, vvp_array_t array,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb, char signed_flag);
|
||||
extern void compile_varw_real(char*label, vvp_array_t array,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CASSIGN_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CAST2(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPIS(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPS(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ const static struct opcode_table_s opcode_table[] = {
|
|||
{ "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%cassign/wr",of_CASSIGN_WR,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
|
||||
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%cast2", of_CAST2, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
|
|
@ -286,6 +287,10 @@ vvp_net_t* vvp_net_lookup(const char*label)
|
|||
switch (vpi->vpi_type->type_code) {
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
case vpiByteVar:
|
||||
case vpiShortIntVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
case vpiIntegerVar: {
|
||||
__vpiSignal*sig = (__vpiSignal*)vpi;
|
||||
return sig->node;
|
||||
|
|
@ -908,6 +913,22 @@ void compile_arith_cast_int(char*label, long width,
|
|||
free(argv);
|
||||
}
|
||||
|
||||
void compile_arith_cast_vec2(char*label, long width,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_arith_cast_vec2*arith = new vvp_arith_cast_vec2((unsigned) width);
|
||||
|
||||
vvp_net_t* ptr = new vvp_net_t;
|
||||
ptr->fun = arith;
|
||||
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
assert(argc == 1);
|
||||
inputs_connect(ptr, argc, argv);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
void compile_arith_cast_real(char*label, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
# include <fstream>
|
||||
# include <vector>
|
||||
# include "parse_misc.h"
|
||||
# include "vpi_user.h"
|
||||
# include "sv_vpi_user.h"
|
||||
# include "vvp_net.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -158,6 +158,8 @@ extern void compile_arith_cast_int(char*label, long width,
|
|||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_cast_real(char*label, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_cast_vec2(char*label, long width,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_div(char*label, long width, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_arith_mod(char*label, long width, bool signed_flag,
|
||||
|
|
@ -433,26 +435,41 @@ extern void compile_thread(char*start_sym, char*flag);
|
|||
|
||||
/*
|
||||
* This function is called to create a var vector with the given name.
|
||||
*
|
||||
* The vpi_type_code argument of compile_variable() is one of the vpi
|
||||
* object codes that identify the type: vpiReg, vpiIntegerVar,
|
||||
* vpiIntVar, etc.
|
||||
*/
|
||||
extern void compile_variable(char*label, char*name,
|
||||
int msb, int lsb, char signed_flag,
|
||||
bool local_flag);
|
||||
int msb, int lsb, int vpi_type_code,
|
||||
bool signed_flag, bool local_flag);
|
||||
|
||||
extern void compile_var_real(char*label, char*name,
|
||||
int msb, int lsb);
|
||||
|
||||
extern void compile_net(char*label, char*name,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag, bool local_flag,
|
||||
/*
|
||||
* The compile_net functio is called to create a .net vector with a
|
||||
* given name.
|
||||
*
|
||||
* The vpi_type_code argument of compile_net() is one of the vpi
|
||||
* object codes for the equivelent variable types. The supported codes
|
||||
* are:
|
||||
* vpiLogic -- 4-value logic
|
||||
* vpiIntVar -- 2-value logic
|
||||
* -vpiLogic -- 8-value (i.e. strength aware) logic
|
||||
*/
|
||||
extern void compile_net(char*label, char*name, int msb, int lsb,
|
||||
int vpi_type_code, bool signed_flag, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_net_real(char*label, char*name,
|
||||
int msb, int lsb, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_netw(char*label, char*array_symbol,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb, bool signed_flag,
|
||||
bool net8_flag,
|
||||
extern void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb, int vpi_type_code, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_netw_real(char*label, char*array_symbol,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ static char* strdupnew(char const *str)
|
|||
".array/real" { return K_ARRAY_R; }
|
||||
".array/s" { return K_ARRAY_S; }
|
||||
".array/port" { return K_ARRAY_PORT; }
|
||||
".cast/2" { return K_CAST_2; }
|
||||
".cast/int" { return K_CAST_INT; }
|
||||
".cast/real" { return K_CAST_REAL; }
|
||||
".cast/real.s" { return K_CAST_REAL_S; }
|
||||
|
|
@ -148,8 +149,10 @@ static char* strdupnew(char const *str)
|
|||
".functor" { return K_FUNCTOR; }
|
||||
".import" { return K_IMPORT; }
|
||||
".island" { return K_ISLAND; }
|
||||
".modpath" { return K_MODPATH; }
|
||||
".modpath" { return K_MODPATH; }
|
||||
".net" { return K_NET; }
|
||||
".net/2s" { return K_NET_2S; }
|
||||
".net/2u" { return K_NET_2U; }
|
||||
".net8" { return K_NET8; }
|
||||
".net8/s" { return K_NET8_S; }
|
||||
".net/real" { return K_NET_R; }
|
||||
|
|
@ -188,6 +191,8 @@ static char* strdupnew(char const *str)
|
|||
".var/real" { return K_VAR_R; }
|
||||
".var/s" { return K_VAR_S; }
|
||||
".var/i" { return K_VAR_I; /* integer */ }
|
||||
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
|
||||
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
|
||||
".udp" { return K_UDP; }
|
||||
".udp/c"(omb)? { return K_UDP_C; }
|
||||
".udp/s"(equ)? { return K_UDP_S; }
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
# include "schedule.h"
|
||||
# include "delay.h"
|
||||
# include "statistics.h"
|
||||
# include <iostream>
|
||||
# include <cstring>
|
||||
# include <cassert>
|
||||
# include <cstdlib>
|
||||
|
|
|
|||
|
|
@ -217,6 +217,12 @@ cassign port (port-1) of the signal functor instead of the normal
|
|||
assign port (port-0), so the signal responds differently. See
|
||||
"VARIABLE STATEMENTS" and "NET STATEMENTS" in the README.txt file.
|
||||
|
||||
* %cast2 <dst>, <src>, <wid>
|
||||
|
||||
Convert the source vector, of type logic, to a bool vector by
|
||||
changing all the X and Z bits to 0. The source and destinations may
|
||||
overlap.
|
||||
|
||||
* %cmp/u <bit-l>, <bit-r>, <wid>
|
||||
* %cmp/s <bit-l>, <bit-r>, <wid>
|
||||
|
||||
|
|
|
|||
101
vvp/parse.y
101
vvp/parse.y
|
|
@ -72,20 +72,21 @@ static struct __vpiModPath*modpath_dst = 0;
|
|||
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
|
||||
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
|
||||
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
|
||||
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S
|
||||
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
|
||||
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
|
||||
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
|
||||
%token K_CONCAT K_DEBUG K_DELAY K_DFF
|
||||
%token K_EVENT K_EVENT_OR K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND
|
||||
%token K_MODPATH K_NET K_NET_S K_NET_R
|
||||
%token K_NET8 K_NET8_S
|
||||
%token K_MODPATH
|
||||
%token K_NET K_NET_S K_NET_R K_NET_2S K_NET_2U K_NET8 K_NET8_S
|
||||
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
|
||||
%token K_PART_V K_PART_V_S K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
|
||||
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
|
||||
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
|
||||
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
|
||||
%token K_UFUNC K_UFUNC_E K_UDP K_UDP_C K_UDP_S
|
||||
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_call_w K_vpi_call_i
|
||||
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
|
||||
%token K_vpi_call K_vpi_call_w K_vpi_call_i
|
||||
%token K_vpi_func K_vpi_func_r
|
||||
%token K_disable K_fork
|
||||
%token K_ivl_version K_ivl_delay_selection
|
||||
|
|
@ -271,20 +272,25 @@ statement
|
|||
compile_arith_abs($1, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CAST_INT T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_arith_cast_int($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
| T_LABEL K_CAST_INT T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_arith_cast_int($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CAST_REAL symbols ';'
|
||||
{ struct symbv_s obj = $3;
|
||||
compile_arith_cast_real($1, false, obj.cnt, obj.vect);
|
||||
}
|
||||
| T_LABEL K_CAST_REAL symbols ';'
|
||||
{ struct symbv_s obj = $3;
|
||||
compile_arith_cast_real($1, false, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CAST_REAL_S symbols ';'
|
||||
{ struct symbv_s obj = $3;
|
||||
compile_arith_cast_real($1, true, obj.cnt, obj.vect);
|
||||
}
|
||||
| T_LABEL K_CAST_REAL_S symbols ';'
|
||||
{ struct symbv_s obj = $3;
|
||||
compile_arith_cast_real($1, true, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
| T_LABEL K_CAST_2 T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_arith_cast_vec2($1, $3, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
/* Arithmetic statements generate functor arrays of a given width
|
||||
that take like size input vectors. */
|
||||
|
|
@ -651,13 +657,19 @@ statement
|
|||
the variable in the netlist. */
|
||||
|
||||
| T_LABEL K_VAR local_flag T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_variable($1, $4, $6, $7, 0 /* unsigned */, $3); }
|
||||
{ compile_variable($1, $4, $6, $7, vpiLogicVar, false, $3); }
|
||||
|
||||
| T_LABEL K_VAR_S local_flag T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_variable($1, $4, $6, $7, 1 /* signed */, $3); }
|
||||
{ compile_variable($1, $4, $6, $7, vpiLogicVar, true, $3); }
|
||||
|
||||
| T_LABEL K_VAR_I local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
|
||||
{ compile_variable($1, $4, $6, $7, 2 /* integer */, $3); }
|
||||
{ compile_variable($1, $4, $6, $7, vpiIntegerVar, true, $3); }
|
||||
|
||||
| T_LABEL K_VAR_2S local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
|
||||
{ compile_variable($1, $4, $6, $7, vpiIntVar, true, $3); }
|
||||
|
||||
| T_LABEL K_VAR_2U local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
|
||||
{ compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); }
|
||||
|
||||
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
|
||||
{ compile_var_real($1, $3, $5, $6); }
|
||||
|
|
@ -667,19 +679,27 @@ statement
|
|||
|
||||
| T_LABEL K_NET local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $4, $6, $7, false, false, $3, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $4, $6, $7, vpiLogicVar, false, $3, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_S local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $4, $6, $7, true, false, $3, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $4, $6, $7, vpiLogicVar, true, $3, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_2U local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $4, $6, $7, vpiIntVar, false, $3, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_2S local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $4, $6, $7, vpiIntVar, true, $3, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET8 local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $4, $6, $7, false, true, $3, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $4, $6, $7, -vpiLogicVar, false, $3, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET8_S local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
{ compile_net($1, $4, $6, $7, true, true, $3, $9.cnt, $9.vect); }
|
||||
{ compile_net($1, $4, $6, $7, -vpiLogicVar, true, $3, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_R local_flag T_STRING ',' signed_t_number signed_t_number
|
||||
',' symbols_net ';'
|
||||
|
|
@ -687,30 +707,25 @@ statement
|
|||
|
||||
/* Arrayed versions of net directives. */
|
||||
|
||||
| T_LABEL K_NET T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, false, false, $9.cnt, $9.vect); }
|
||||
| T_LABEL K_NET T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, false, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_S T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, true, false, $9.cnt, $9.vect); }
|
||||
| T_LABEL K_NET_S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, true, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, false, true, $9.cnt, $9.vect); }
|
||||
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, false, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET8_S T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, true, true, $9.cnt, $9.vect); }
|
||||
| T_LABEL K_NET8_S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, true, $9.cnt, $9.vect); }
|
||||
|
||||
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ','
|
||||
signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
|
||||
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||
symbols_net ';'
|
||||
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
|
||||
|
||||
/* Array word versions of alias directives. */
|
||||
|
||||
|
|
|
|||
|
|
@ -255,14 +255,20 @@ static const char* vpi_type_values(PLI_INT32 code)
|
|||
{
|
||||
static char buf[32];
|
||||
switch (code) {
|
||||
case vpiByteVar:
|
||||
return "vpiByteVar";
|
||||
case vpiConstant:
|
||||
return "vpiConstant";
|
||||
case vpiFunction:
|
||||
return "vpiFunction";
|
||||
case vpiIntVar:
|
||||
return "vpiIntVar";
|
||||
case vpiIntegerVar:
|
||||
return "vpiIntegerVar";
|
||||
case vpiIterator:
|
||||
return "vpiIterator";
|
||||
case vpiLongIntVar:
|
||||
return "vpiLongIntVar";
|
||||
case vpiMemory:
|
||||
return "vpiMemory";
|
||||
case vpiMemoryWord:
|
||||
|
|
@ -287,6 +293,8 @@ static const char* vpi_type_values(PLI_INT32 code)
|
|||
return "vpiRealVar";
|
||||
case vpiReg:
|
||||
return "vpiReg";
|
||||
case vpiShortIntVar:
|
||||
return "vpiShortIntVar";
|
||||
case vpiSysFuncCall:
|
||||
return "vpiSysFuncCall";
|
||||
case vpiSysTaskCall:
|
||||
|
|
@ -318,9 +326,7 @@ PLI_INT32 vpi_get(int property, vpiHandle ref)
|
|||
}
|
||||
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
|
||||
return vpiIntegerVar;
|
||||
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
||||
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
||||
return vpiNetArray;
|
||||
else
|
||||
return ref->vpi_type->type_code;
|
||||
|
|
@ -375,9 +381,7 @@ char* vpi_get_str(PLI_INT32 property, vpiHandle ref)
|
|||
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||
PLI_INT32 type;
|
||||
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
|
||||
type = vpiIntegerVar;
|
||||
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
||||
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
||||
type = vpiNetArray;
|
||||
else
|
||||
type = ref->vpi_type->type_code;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include "sv_vpi_user.h"
|
||||
# include "vvp_net.h"
|
||||
# include "config.h"
|
||||
|
||||
|
|
@ -243,7 +243,6 @@ struct __vpiSignal {
|
|||
int msb, lsb;
|
||||
/* Flags */
|
||||
unsigned signed_flag : 1;
|
||||
unsigned isint_ : 1; // original type was integer
|
||||
unsigned is_netarray : 1; // This is word of a net array
|
||||
/* The represented value is here. */
|
||||
vvp_net_t*node;
|
||||
|
|
@ -251,12 +250,14 @@ struct __vpiSignal {
|
|||
extern unsigned vpip_size(__vpiSignal *sig);
|
||||
extern struct __vpiScope* vpip_scope(__vpiSignal*sig);
|
||||
|
||||
extern vpiHandle vpip_make_int(const char*name, int msb, int lsb,
|
||||
extern vpiHandle vpip_make_int2(const char*name, int msb, int lsb,
|
||||
vvp_net_t*vec);
|
||||
extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
||||
extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb,
|
||||
vvp_net_t*vec);
|
||||
extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_net_t*net);
|
||||
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_net_t*node);
|
||||
extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_net_t*node);
|
||||
|
||||
/*
|
||||
* This is used by system calls to represent a bit/part select of
|
||||
|
|
|
|||
|
|
@ -507,11 +507,19 @@ static void format_vpiVectorVal(vvp_signal_value*sig, int base, unsigned wid,
|
|||
|
||||
struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref)
|
||||
{
|
||||
if ((ref->vpi_type->type_code != vpiNet)
|
||||
&& (ref->vpi_type->type_code != vpiReg))
|
||||
return 0;
|
||||
switch (ref->vpi_type->type_code) {
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
case vpiIntegerVar:
|
||||
case vpiByteVar:
|
||||
case vpiShortIntVar:
|
||||
case vpiIntVar:
|
||||
case vpiLongIntVar:
|
||||
return (struct __vpiSignal*)ref;
|
||||
|
||||
return (struct __vpiSignal*)ref;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -874,6 +882,17 @@ static const struct __vpirt vpip_reg_rt = {
|
|||
0
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_integer_rt = {
|
||||
vpiIntegerVar,
|
||||
signal_get,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
signal_put_value,
|
||||
signal_get_handle,
|
||||
signal_iterate,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_net_rt = {
|
||||
vpiNet,
|
||||
signal_get,
|
||||
|
|
@ -888,31 +907,97 @@ static const struct __vpirt vpip_net_rt = {
|
|||
0
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_byte_rt = {
|
||||
vpiByteVar,
|
||||
signal_get,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
signal_put_value,
|
||||
signal_get_handle,
|
||||
signal_iterate,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_shortint_rt = {
|
||||
vpiShortIntVar,
|
||||
signal_get,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
signal_put_value,
|
||||
signal_get_handle,
|
||||
signal_iterate,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_int_rt = {
|
||||
vpiIntVar,
|
||||
signal_get,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
signal_put_value,
|
||||
signal_get_handle,
|
||||
signal_iterate,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_longint_rt = {
|
||||
vpiLongIntVar,
|
||||
signal_get,
|
||||
signal_get_str,
|
||||
signal_get_value,
|
||||
signal_put_value,
|
||||
signal_get_handle,
|
||||
signal_iterate,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Construct a vpiIntegerVar object. Indicate the type using a flag
|
||||
* to minimize the code modifications. Icarus implements integers
|
||||
* as 'reg signed [31:0]'.
|
||||
*/
|
||||
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
|
||||
vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, true, vec);
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
rfp->isint_ = true;
|
||||
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
|
||||
obj->vpi_type = &vpip_integer_rt;
|
||||
return obj;
|
||||
}
|
||||
|
||||
vpiHandle vpip_make_int2(const char*name, int msb, int lsb, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
|
||||
|
||||
assert(lsb == 0);
|
||||
switch (msb) {
|
||||
case 7:
|
||||
obj->vpi_type = &vpip_byte_rt;
|
||||
break;
|
||||
case 15:
|
||||
obj->vpi_type = &vpip_shortint_rt;
|
||||
break;
|
||||
case 31:
|
||||
obj->vpi_type = &vpip_int_rt;
|
||||
break;
|
||||
case 63:
|
||||
obj->vpi_type = &vpip_longint_rt;
|
||||
break;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a vpiReg object. It's like a net, except for the type.
|
||||
* Construct a vpiReg/vpiLogicVar object. It's like a net, except for the type.
|
||||
*/
|
||||
vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
|
||||
vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_net_t*vec)
|
||||
{
|
||||
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
|
||||
vpiHandle obj = vpip_make_net4(name, msb,lsb, signed_flag, vec);
|
||||
obj->vpi_type = &vpip_reg_rt;
|
||||
return obj;
|
||||
}
|
||||
|
||||
#ifdef CHECK_WITH_VALGRIND
|
||||
static struct __vpiSignal **signal_pool = 0;
|
||||
static unsigned signal_pool_count = 0;
|
||||
|
|
@ -988,7 +1073,7 @@ void signal_pool_delete()
|
|||
* The name is the PLI name for the object. If it is an array it is
|
||||
* <name>[<index>].
|
||||
*/
|
||||
vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||
vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
|
||||
bool signed_flag, vvp_net_t*node)
|
||||
{
|
||||
struct __vpiSignal*obj = allocate_vpiSignal();
|
||||
|
|
@ -997,7 +1082,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
|||
obj->msb = msb;
|
||||
obj->lsb = lsb;
|
||||
obj->signed_flag = signed_flag? 1 : 0;
|
||||
obj->isint_ = 0;
|
||||
obj->is_netarray = 0;
|
||||
obj->node = node;
|
||||
|
||||
|
|
|
|||
|
|
@ -1385,6 +1385,34 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool of_CAST2(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned dst = cp->bit_idx[0];
|
||||
unsigned src = cp->bit_idx[1];
|
||||
unsigned wid = cp->number;
|
||||
|
||||
thr_check_addr(thr, dst+wid-1);
|
||||
thr_check_addr(thr, src+wid-1);
|
||||
|
||||
vvp_vector4_t res;
|
||||
switch (src) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 3:
|
||||
res = vvp_vector4_t(wid, BIT4_0);
|
||||
break;
|
||||
case 1:
|
||||
res = vvp_vector4_t(wid, BIT4_1);
|
||||
break;
|
||||
default:
|
||||
res = vector2_to_vector4(vvp_vector2_t(vthread_bits_to_vector(thr, src, wid)), wid);
|
||||
break;
|
||||
}
|
||||
|
||||
thr->bits4.set_vec(dst, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_CMPS(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_bit4_t eq = BIT4_1;
|
||||
|
|
|
|||
|
|
@ -1949,7 +1949,24 @@ vvp_vector2_t::vvp_vector2_t(vvp_vector2_t::fill_t fill, unsigned wid)
|
|||
vec_[idx] = fill? -1 : 0;
|
||||
}
|
||||
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned base, unsigned wid)
|
||||
{
|
||||
wid_ = wid;
|
||||
const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
|
||||
|
||||
vec_ = new unsigned long[words];
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
int bit = that.value(base+idx);
|
||||
if (bit == 0)
|
||||
continue;
|
||||
unsigned word = idx / BITS_PER_WORD;
|
||||
unsigned long mask = 1UL << (idx % BITS_PER_WORD);
|
||||
vec_[word] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_vector2_t::copy_from_that_(const vvp_vector4_t&that)
|
||||
{
|
||||
wid_ = that.size();
|
||||
const unsigned words = (that.size() + BITS_PER_WORD-1) / BITS_PER_WORD;
|
||||
|
|
@ -1970,15 +1987,12 @@ vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
|
|||
|
||||
switch (that.value(idx)) {
|
||||
case BIT4_0:
|
||||
case BIT4_X:
|
||||
case BIT4_Z:
|
||||
break;
|
||||
case BIT4_1:
|
||||
vec_[addr] |= 1UL << shift;
|
||||
break;
|
||||
default:
|
||||
delete[]vec_;
|
||||
vec_ = 0;
|
||||
wid_ = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1999,11 +2013,6 @@ void vvp_vector2_t::copy_from_that_(const vvp_vector2_t&that)
|
|||
vec_[idx] = that.vec_[idx];
|
||||
}
|
||||
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
|
||||
{
|
||||
copy_from_that_(that);
|
||||
}
|
||||
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned newsize)
|
||||
{
|
||||
wid_ = newsize;
|
||||
|
|
@ -2036,6 +2045,14 @@ vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector2_t&that)
|
|||
return *this;
|
||||
}
|
||||
|
||||
vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector4_t&that)
|
||||
{
|
||||
delete[]vec_;
|
||||
vec_ = 0;
|
||||
copy_from_that_(that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
vvp_vector2_t& vvp_vector2_t::operator <<= (unsigned int shift)
|
||||
{
|
||||
if (wid_ == 0)
|
||||
|
|
@ -2200,11 +2217,6 @@ vvp_vector2_t& vvp_vector2_t::operator -= (const vvp_vector2_t&that)
|
|||
return *this;
|
||||
}
|
||||
|
||||
vvp_vector2_t::~vvp_vector2_t()
|
||||
{
|
||||
delete[] vec_;
|
||||
}
|
||||
|
||||
void vvp_vector2_t::trim()
|
||||
{
|
||||
while (value(wid_-1) == 0 && wid_ > 1) wid_ -= 1;
|
||||
|
|
@ -2248,6 +2260,14 @@ void vvp_vector2_t::set_bit(unsigned idx, int bit)
|
|||
vec_[addr] &= ~(1UL << mask);
|
||||
}
|
||||
|
||||
void vvp_vector2_t::set_vec(unsigned adr, const vvp_vector2_t&that)
|
||||
{
|
||||
assert((adr + that.wid_) <= wid_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < that.wid_ ; idx += 1)
|
||||
set_bit(adr+idx, that.value(idx));
|
||||
}
|
||||
|
||||
bool vvp_vector2_t::is_NaN() const
|
||||
{
|
||||
return wid_ == 0;
|
||||
|
|
@ -2659,6 +2679,24 @@ vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
|
|||
}
|
||||
}
|
||||
|
||||
vvp_vector8_t::vvp_vector8_t(const vvp_vector2_t&that,
|
||||
unsigned str0, unsigned str1)
|
||||
: size_(that.size())
|
||||
{
|
||||
if (size_ == 0)
|
||||
return;
|
||||
|
||||
if (size_ <= sizeof val_) {
|
||||
ptr_ = 0;
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
val_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
|
||||
} else {
|
||||
ptr_ = new unsigned char[size_];
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
ptr_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
|
||||
}
|
||||
}
|
||||
|
||||
const vvp_vector8_t vvp_vector8_t::nil;
|
||||
|
||||
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ using namespace std;
|
|||
/* Data types */
|
||||
class vvp_scalar_t;
|
||||
|
||||
class vvp_vector2_t;
|
||||
class vvp_vector4_t;
|
||||
class vvp_vector8_t;
|
||||
|
||||
/* Basic netlist types. */
|
||||
class vvp_net_t;
|
||||
class vvp_net_fun_t;
|
||||
|
|
@ -607,9 +611,10 @@ class vvp_vector2_t {
|
|||
vvp_vector2_t();
|
||||
vvp_vector2_t(const vvp_vector2_t&);
|
||||
vvp_vector2_t(const vvp_vector2_t&, unsigned newsize);
|
||||
vvp_vector2_t(const vvp_vector2_t&, unsigned base, unsigned wid);
|
||||
// Make a vvp_vector2_t from a vvp_vector4_t. If there are X
|
||||
// or Z bits, then the result becomes a NaN value.
|
||||
explicit vvp_vector2_t(const vvp_vector4_t&that);
|
||||
vvp_vector2_t(const vvp_vector4_t&that);
|
||||
// Make from a native long and a specified width.
|
||||
vvp_vector2_t(unsigned long val, unsigned wid);
|
||||
// Make with the width, and filled with 1 or 0 bits.
|
||||
|
|
@ -623,11 +628,19 @@ class vvp_vector2_t {
|
|||
vvp_vector2_t&operator >>= (unsigned shift);
|
||||
vvp_vector2_t&operator = (const vvp_vector2_t&);
|
||||
|
||||
// Assign a vec4 to a vec2, using Verilog rules for converting
|
||||
// XZ values to 0.
|
||||
vvp_vector2_t&operator = (const vvp_vector4_t&);
|
||||
|
||||
bool is_NaN() const;
|
||||
bool is_zero() const;
|
||||
unsigned size() const;
|
||||
int value(unsigned idx) const;
|
||||
vvp_bit4_t value4(unsigned idx) const;
|
||||
// Get the vector2 subvector starting at the address
|
||||
vvp_vector2_t subvalue(unsigned idx, unsigned size) const;
|
||||
void set_bit(unsigned idx, int bit);
|
||||
void set_vec(unsigned idx, const vvp_vector2_t&that);
|
||||
// Make the size just big enough to hold the first 1 bit.
|
||||
void trim();
|
||||
// Trim off extra 1 bit since this is representing a negative value.
|
||||
|
|
@ -641,6 +654,7 @@ class vvp_vector2_t {
|
|||
|
||||
private:
|
||||
void copy_from_that_(const vvp_vector2_t&that);
|
||||
void copy_from_that_(const vvp_vector4_t&that);
|
||||
};
|
||||
|
||||
extern bool operator > (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||
|
|
@ -667,12 +681,40 @@ extern double crstring_to_double(const char*str);
|
|||
|
||||
extern ostream& operator<< (ostream&, const vvp_vector2_t&);
|
||||
|
||||
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
|
||||
{
|
||||
copy_from_that_(that);
|
||||
}
|
||||
|
||||
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
|
||||
{
|
||||
copy_from_that_(that);
|
||||
}
|
||||
|
||||
inline vvp_vector2_t::~vvp_vector2_t()
|
||||
{
|
||||
delete[] vec_;
|
||||
}
|
||||
|
||||
/* Inline some of the vector2_t methods. */
|
||||
inline unsigned vvp_vector2_t::size() const
|
||||
{
|
||||
return wid_;
|
||||
}
|
||||
|
||||
inline vvp_bit4_t vvp_vector2_t::value4(unsigned idx) const
|
||||
{
|
||||
if (value(idx))
|
||||
return BIT4_1;
|
||||
else
|
||||
return BIT4_0;
|
||||
}
|
||||
|
||||
inline vvp_vector2_t vvp_vector2_t::subvalue(unsigned base, unsigned wid) const
|
||||
{
|
||||
return vvp_vector2_t(*this, base, wid);
|
||||
}
|
||||
|
||||
/*
|
||||
* This class represents a scalar value with strength. These are
|
||||
* heavier then the simple vvp_bit4_t, but more information is
|
||||
|
|
@ -810,6 +852,9 @@ class vvp_vector8_t {
|
|||
explicit vvp_vector8_t(const vvp_vector4_t&that,
|
||||
unsigned str0,
|
||||
unsigned str1);
|
||||
explicit vvp_vector8_t(const vvp_vector2_t&that,
|
||||
unsigned str0,
|
||||
unsigned str1);
|
||||
|
||||
~vvp_vector8_t();
|
||||
|
||||
|
|
@ -1220,7 +1265,9 @@ class vvp_net_fil_t : public vvp_vpi_callback {
|
|||
// the val through the force mask. The force value is the
|
||||
// currently forced value, and the buf is a value that this
|
||||
// method will use to hold a filtered value, if needed. This
|
||||
// method returns a pointer to val or buf.
|
||||
// method returns the replacement value into the "rep"
|
||||
// argument and returns a code indicating whether any changes
|
||||
// were made.
|
||||
template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep, unsigned addr);
|
||||
// This template method is similar to the above, but works for
|
||||
// native types that are not so expensive to edit in place.
|
||||
|
|
|
|||
97
vvp/words.cc
97
vvp/words.cc
|
|
@ -85,7 +85,8 @@ void compile_varw_real(char*label, vvp_array_t array,
|
|||
*/
|
||||
static void __compile_var(char*label, char*name,
|
||||
vvp_array_t array, unsigned long array_addr,
|
||||
int msb, int lsb, char signed_flag, bool local_flag)
|
||||
int msb, int lsb, int vpi_type_code,
|
||||
bool signed_flag, bool local_flag)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
|
||||
|
|
@ -95,6 +96,9 @@ static void __compile_var(char*label, char*name,
|
|||
vvp_fun_signal4_aa*tmp = new vvp_fun_signal4_aa(wid);
|
||||
net->fil = tmp;
|
||||
net->fun = tmp;
|
||||
} else if (vpi_type_code == vpiIntVar) {
|
||||
net->fil = new vvp_wire_vec4(wid, BIT4_0);
|
||||
net->fun = new vvp_fun_signal4_sa(wid);
|
||||
} else {
|
||||
net->fil = new vvp_wire_vec4(wid, BIT4_X);
|
||||
net->fun = new vvp_fun_signal4_sa(wid);
|
||||
|
|
@ -106,9 +110,21 @@ static void __compile_var(char*label, char*name,
|
|||
vpiHandle obj = 0;
|
||||
if (! local_flag && !array) {
|
||||
/* Make the vpiHandle for the reg. */
|
||||
obj = (signed_flag > 1) ?
|
||||
vpip_make_int(name, msb, lsb, net) :
|
||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, net);
|
||||
switch (vpi_type_code) {
|
||||
case vpiLogicVar:
|
||||
obj = vpip_make_var4(name, msb, lsb, signed_flag, net);
|
||||
break;
|
||||
case vpiIntegerVar:
|
||||
obj = vpip_make_int4(name, msb, lsb, net);
|
||||
break;
|
||||
case vpiIntVar: // This handles all the atom2 int types
|
||||
obj = vpip_make_int2(name, msb, lsb, net);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "internal error: %s: vpi_type_code=%d\n", name, vpi_type_code);
|
||||
break;
|
||||
}
|
||||
assert(obj);
|
||||
compile_vpi_symbol(label, obj);
|
||||
}
|
||||
// If the signal has a name, then it goes into the current
|
||||
|
|
@ -133,24 +149,10 @@ static void __compile_var(char*label, char*name,
|
|||
}
|
||||
|
||||
void compile_variable(char*label, char*name,
|
||||
int msb, int lsb, char signed_flag, bool local_flag)
|
||||
int msb, int lsb, int vpi_type_code,
|
||||
bool signed_flag, bool local_flag)
|
||||
{
|
||||
__compile_var(label, name, 0, 0, msb, lsb, signed_flag, local_flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* In this case, the variable it intended to be attached to the array
|
||||
* as a word. The array_addr is the *canonical* address of the word in
|
||||
* the array.
|
||||
*
|
||||
* This function is actually used by the compile_array function,
|
||||
* instead of directly by the parser.
|
||||
*/
|
||||
void compile_variablew(char*label, vvp_array_t array,
|
||||
unsigned long array_addr,
|
||||
int msb, int lsb, char signed_flag)
|
||||
{
|
||||
__compile_var(label, 0, array, array_addr, msb, lsb, signed_flag, false);
|
||||
__compile_var(label, name, 0, 0, msb, lsb, vpi_type_code, signed_flag, local_flag);
|
||||
}
|
||||
|
||||
vvp_net_t* create_constant_node(const char*val_str)
|
||||
|
|
@ -210,12 +212,12 @@ class __compile_net_resolv : public base_net_resolv {
|
|||
struct __vpiScope*scope,
|
||||
char*my_label, char*name,
|
||||
int msb, int lsb, unsigned array_addr,
|
||||
bool signed_flag, bool net8_flag, bool local_flag)
|
||||
int vpi_type_code, bool signed_flag, bool local_flag)
|
||||
: base_net_resolv(ref_label, array, scope, my_label, name, array_addr, local_flag)
|
||||
{ msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
vpi_type_code_ = vpi_type_code;
|
||||
signed_flag_ = signed_flag;
|
||||
net8_flag_ = net8_flag;
|
||||
}
|
||||
|
||||
~__compile_net_resolv() { }
|
||||
|
|
@ -224,7 +226,8 @@ class __compile_net_resolv : public base_net_resolv {
|
|||
|
||||
private:
|
||||
int msb_, lsb_;
|
||||
bool signed_flag_, net8_flag_;
|
||||
int vpi_type_code_;
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -239,11 +242,11 @@ class __compile_net_resolv : public base_net_resolv {
|
|||
* references into the net.
|
||||
*/
|
||||
|
||||
static void __compile_net2(vvp_net_t*node, vvp_array_t array,
|
||||
static void do_compile_net(vvp_net_t*node, vvp_array_t array,
|
||||
struct __vpiScope*scope,
|
||||
char*my_label, char*name,
|
||||
int msb, int lsb, unsigned array_addr,
|
||||
bool signed_flag, bool net8_flag, bool local_flag)
|
||||
int vpi_type_code, bool signed_flag, bool local_flag)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
assert(node);
|
||||
|
|
@ -251,17 +254,25 @@ static void __compile_net2(vvp_net_t*node, vvp_array_t array,
|
|||
vvp_wire_base*vsig = dynamic_cast<vvp_wire_base*>(node->fil);
|
||||
|
||||
if (vsig == 0) {
|
||||
vsig = net8_flag
|
||||
? dynamic_cast<vvp_wire_base*>(new vvp_wire_vec8(wid))
|
||||
: dynamic_cast<vvp_wire_base*>(new vvp_wire_vec4(wid,BIT4_Z));
|
||||
|
||||
switch (vpi_type_code) {
|
||||
case vpiIntVar:
|
||||
vsig = new vvp_wire_vec4(wid,BIT4_0);
|
||||
break;
|
||||
case vpiLogicVar:
|
||||
vsig = new vvp_wire_vec4(wid,BIT4_Z);
|
||||
break;
|
||||
case -vpiLogicVar:
|
||||
vsig = new vvp_wire_vec8(wid);
|
||||
break;
|
||||
}
|
||||
assert(vsig);
|
||||
node->fil = vsig;
|
||||
}
|
||||
|
||||
vpiHandle obj = 0;
|
||||
if (! local_flag) {
|
||||
/* Make the vpiHandle for the reg. */
|
||||
obj = vpip_make_net(name, msb, lsb, signed_flag, node);
|
||||
obj = vpip_make_net4(name, msb, lsb, signed_flag, node);
|
||||
/* This attaches the label to the vpiHandle */
|
||||
compile_vpi_symbol(my_label, obj);
|
||||
}
|
||||
|
|
@ -287,7 +298,7 @@ static void __compile_net2(vvp_net_t*node, vvp_array_t array,
|
|||
static void __compile_net(char*label,
|
||||
char*name, char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag, bool local_flag,
|
||||
int vpi_type_code, bool signed_flag, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
||||
|
|
@ -314,7 +325,7 @@ static void __compile_net(char*label,
|
|||
= new __compile_net_resolv(argv[0].text,
|
||||
array, scope, label, name,
|
||||
msb, lsb, array_addr,
|
||||
signed_flag, net8_flag, local_flag);
|
||||
vpi_type_code, signed_flag, local_flag);
|
||||
resolv_submit(res);
|
||||
free(argv);
|
||||
return;
|
||||
|
|
@ -322,8 +333,8 @@ static void __compile_net(char*label,
|
|||
assert(node);
|
||||
|
||||
struct __vpiScope*scope = vpip_peek_current_scope();
|
||||
__compile_net2(node, array, scope, label, name, msb, lsb, array_addr,
|
||||
signed_flag, net8_flag, local_flag);
|
||||
do_compile_net(node, array, scope, label, name, msb, lsb, array_addr,
|
||||
vpi_type_code, signed_flag, local_flag);
|
||||
|
||||
free(argv[0].text);
|
||||
free(argv);
|
||||
|
|
@ -338,30 +349,28 @@ bool __compile_net_resolv::resolve(bool msg_flag)
|
|||
return false;
|
||||
}
|
||||
|
||||
__compile_net2(node, array_, scope_, my_label_, name_, msb_, lsb_, array_addr_, signed_flag_, net8_flag_, local_flag_);
|
||||
do_compile_net(node, array_, scope_, my_label_, name_, msb_, lsb_, array_addr_, vpi_type_code_, signed_flag_, local_flag_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void compile_net(char*label, char*name, int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag, bool local_flag,
|
||||
int vpi_type_code, bool signed_flag, bool local_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
__compile_net(label, name, 0, 0,
|
||||
msb, lsb, signed_flag, net8_flag, local_flag,
|
||||
__compile_net(label, name, 0, 0, msb, lsb,
|
||||
vpi_type_code, signed_flag, local_flag,
|
||||
argc, argv);
|
||||
}
|
||||
|
||||
void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
||||
int msb, int lsb,
|
||||
bool signed_flag, bool net8_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
int msb, int lsb, int vpi_type_code, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
__compile_net(label, 0, array_label, array_addr,
|
||||
msb, lsb, signed_flag, net8_flag, false,
|
||||
msb, lsb, vpi_type_code, signed_flag, false,
|
||||
argc, argv);
|
||||
}
|
||||
|
||||
|
||||
class __compile_real_net_resolv : public base_net_resolv {
|
||||
|
||||
public:
|
||||
|
|
|
|||
Loading…
Reference in New Issue