Merge branch 'work1'
This commit is contained in:
commit
3733c59e49
|
|
@ -302,7 +302,7 @@ else
|
||||||
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
|
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
|
||||||
endif
|
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
|
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
|
||||||
|
|
||||||
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
|
$(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
|
$(includedir)/_pli_types.h: _pli_types.h
|
||||||
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_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
|
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/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_INTEGER,
|
||||||
PTF_REAL,
|
PTF_REAL,
|
||||||
PTF_REALTIME,
|
PTF_REALTIME,
|
||||||
PTF_TIME
|
PTF_TIME,
|
||||||
|
PTF_ATOM2,
|
||||||
|
PTF_ATOM2_S
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PTaskFuncArg {
|
struct PTaskFuncArg {
|
||||||
|
|
|
||||||
10
compiler.h
10
compiler.h
|
|
@ -151,6 +151,16 @@ extern bool gn_io_range_error_flag;
|
||||||
re-evaluated. */
|
re-evaluated. */
|
||||||
extern bool gn_strict_ca_eval_flag;
|
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
|
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
|
||||||
sets of keywords. The compiler enables groups of keywords by setting
|
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
|
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);
|
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;
|
name() << " width=" << width() << endl;
|
||||||
dump_node_pins(o, ind+4);
|
dump_node_pins(o, ind+4);
|
||||||
dump_obj_attr(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())
|
if (rise_time())
|
||||||
o << " #(" <<*rise_time()
|
o << " #(" <<*rise_time()
|
||||||
<<","<<*fall_time()
|
<<","<<*fall_time()
|
||||||
<< "," <<*decay_time() << ")" << endl;
|
<< "," <<*decay_time() << ")";
|
||||||
|
o << endl;
|
||||||
dump_node_pins(o, ind+4);
|
dump_node_pins(o, ind+4);
|
||||||
dump_obj_attr(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);
|
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. */
|
/* Don't allow registers as assign l-values. */
|
||||||
if (sig->type() == NetNet::REG) {
|
if (sig->type() == NetNet::REG) {
|
||||||
cerr << get_fileline() << ": error: reg " << sig->name()
|
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;
|
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
|
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;
|
need_constant_expr = false;
|
||||||
|
|
||||||
long mnum = 0, lnum = 0;
|
long mnum = 0, lnum = 0;
|
||||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) {
|
if ( ! get_const_argument(me, mnum) ) {
|
||||||
mnum = tmp->value().as_long();
|
|
||||||
} else {
|
|
||||||
cerr << me->get_fileline() << ": error: "
|
cerr << me->get_fileline() << ": error: "
|
||||||
"Unable to evaluate constant expression "
|
"Unable to evaluate constant expression "
|
||||||
<< *me << "." << endl;
|
<< *me << "." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(le)) {
|
if ( ! get_const_argument(le, lnum) ) {
|
||||||
lnum = tmp->value().as_long();
|
|
||||||
} else {
|
|
||||||
cerr << le->get_fileline() << ": error: "
|
cerr << le->get_fileline() << ": error: "
|
||||||
"Unable to evaluate constant expression "
|
"Unable to evaluate constant expression "
|
||||||
<< *le << "." << endl;
|
<< *le << "." << endl;
|
||||||
|
|
@ -534,6 +539,48 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->data_type(IVL_VT_REAL);
|
ret_sig->data_type(IVL_VT_REAL);
|
||||||
break;
|
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:
|
default:
|
||||||
if (ports_) {
|
if (ports_) {
|
||||||
cerr << get_fileline() << ": internal error: I don't know "
|
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;
|
need_driver_flag = true;
|
||||||
|
|
||||||
/* Cast the right side when needed. */
|
/* Cast the right side when needed. */
|
||||||
if ((lval->data_type() == IVL_VT_REAL &&
|
if ((lval->data_type() == IVL_VT_REAL) &&
|
||||||
rval->data_type() != IVL_VT_REAL)) {
|
(rval->data_type() != IVL_VT_REAL)) {
|
||||||
rval = cast_to_real(des, scope, rval);
|
rval = cast_to_real(des, scope, rval);
|
||||||
need_driver_flag = false;
|
need_driver_flag = false;
|
||||||
} else if ((lval->data_type() != IVL_VT_REAL &&
|
} else if ((lval->data_type() == IVL_VT_BOOL) &&
|
||||||
rval->data_type() == IVL_VT_REAL)) {
|
(rval->data_type() != IVL_VT_BOOL)) {
|
||||||
rval = cast_to_int(des, scope, rval, lval->vector_width());
|
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;
|
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.
|
// thing needs to go to each instance when arrayed.
|
||||||
if ((sig->data_type() == IVL_VT_REAL ) &&
|
if ((sig->data_type() == IVL_VT_REAL ) &&
|
||||||
!prts.empty() && (prts[0]->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());
|
prts_vector_width/instance.size());
|
||||||
}
|
}
|
||||||
// If we have a bit/vector signal driving a real port
|
// 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();
|
prts_vector_width = sig->vector_width();
|
||||||
for (unsigned pidx = 0; pidx < prts.size(); pidx += 1) {
|
for (unsigned pidx = 0; pidx < prts.size(); pidx += 1) {
|
||||||
prts[pidx]->port_type(NetNet::NOT_A_PORT);
|
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 /
|
prts_vector_width /
|
||||||
instance.size());
|
instance.size());
|
||||||
prts[pidx]->port_type(NetNet::POUTPUT);
|
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);
|
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);
|
NetAssign*cur = new NetAssign(lv, rv);
|
||||||
cur->set_line(*this);
|
cur->set_line(*this);
|
||||||
|
|
||||||
|
|
@ -3558,6 +3568,14 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||||
rexp->set_width(lwid, true);
|
rexp->set_width(lwid, true);
|
||||||
rexp = pad_to_width(rexp, lwid, *this);
|
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);
|
dev = new NetForce(lval, rexp);
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
|
|
|
||||||
9
emit.cc
9
emit.cc
|
|
@ -72,9 +72,14 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||||
return true;
|
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
|
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);
|
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
||||||
if (tmp[idx] == 0) flag = false;
|
if (tmp[idx] == 0) flag = false;
|
||||||
/* Set the data type to the first one found. */
|
/* Set the data type to the first one found. */
|
||||||
if (data_type == IVL_VT_NO_TYPE) {
|
switch (data_type) {
|
||||||
data_type = tmp[idx]->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()) {
|
switch (op()) {
|
||||||
case 'i':
|
case 'i':
|
||||||
isig = cast_to_int(des, scope, isig, isig->vector_width());
|
isig = cast_to_int4(des, scope, isig, isig->vector_width());
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
isig = cast_to_real(des, scope, isig);
|
isig = cast_to_real(des, scope, isig);
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,8 @@ typedef enum ivl_lpm_type_e {
|
||||||
IVL_LPM_ABS = 32,
|
IVL_LPM_ABS = 32,
|
||||||
IVL_LPM_ADD = 0,
|
IVL_LPM_ADD = 0,
|
||||||
IVL_LPM_ARRAY = 30,
|
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_CAST_REAL = 33,
|
||||||
IVL_LPM_CONCAT = 16,
|
IVL_LPM_CONCAT = 16,
|
||||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
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:
|
case NetNet::WIRE:
|
||||||
o << "wire";
|
o << "wire";
|
||||||
break;
|
break;
|
||||||
case NetNet::UWIRE:
|
case NetNet::UNRESOLVED_WIRE:
|
||||||
o << "uwire";
|
o << "uwire";
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
|
|
@ -951,7 +951,14 @@ const NetScope* NetAnalogTop::scope() const
|
||||||
return scope_;
|
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__)
|
: NetNode(scope__, n, 2), width_(width__)
|
||||||
{
|
{
|
||||||
pin(0).set_dir(Link::OUTPUT);
|
pin(0).set_dir(Link::OUTPUT);
|
||||||
|
|
@ -2359,11 +2366,13 @@ ivl_variable_type_t NetETernary::expr_type() const
|
||||||
ivl_assert(*this, false_val_);
|
ivl_assert(*this, false_val_);
|
||||||
ivl_variable_type_t tru = true_val_->expr_type();
|
ivl_variable_type_t tru = true_val_->expr_type();
|
||||||
ivl_variable_type_t fal = false_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)
|
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
|
||||||
return IVL_VT_LOGIC;
|
return IVL_VT_LOGIC;
|
||||||
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
|
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
|
||||||
return 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))
|
if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
|
||||||
return IVL_VT_REAL;
|
return IVL_VT_REAL;
|
||||||
if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
|
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':
|
case 'r':
|
||||||
ret = IVL_VT_REAL;
|
ret = IVL_VT_REAL;
|
||||||
break;
|
break;
|
||||||
|
case '2':
|
||||||
|
ret = IVL_VT_BOOL;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
netlist.h
21
netlist.h
|
|
@ -553,7 +553,7 @@ class NetNet : public NetObj {
|
||||||
public:
|
public:
|
||||||
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||||
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
||||||
UWIRE };
|
UNRESOLVED_WIRE };
|
||||||
|
|
||||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
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
|
* 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).
|
* given width. The input is pin(1) and the output is pin(0).
|
||||||
*/
|
*/
|
||||||
class NetCastInt : public NetNode {
|
class NetCastInt4 : public NetNode {
|
||||||
|
|
||||||
public:
|
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_; }
|
unsigned width() const { return width_; }
|
||||||
|
|
||||||
|
|
@ -3763,6 +3777,7 @@ class NetETernary : public NetExpr {
|
||||||
* X -- Reduction NXOR (~^ or ^~)
|
* X -- Reduction NXOR (~^ or ^~)
|
||||||
* m -- abs(x) (i.e. "magnitude")
|
* m -- abs(x) (i.e. "magnitude")
|
||||||
* i -- Cast from real to integer (vector)
|
* i -- Cast from real to integer (vector)
|
||||||
|
* 2 -- Cast from real or logic (vector) to bool (vector)
|
||||||
* r -- Cast from integer (vector) to real
|
* r -- Cast from integer (vector) to real
|
||||||
*/
|
*/
|
||||||
class NetEUnary : public NetExpr {
|
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;
|
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)
|
if (src->data_type() != IVL_VT_REAL)
|
||||||
return src;
|
return src;
|
||||||
|
|
@ -126,7 +146,7 @@ NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
|
||||||
tmp->set_line(*src);
|
tmp->set_line(*src);
|
||||||
tmp->local_flag(true);
|
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);
|
cast->set_line(*src);
|
||||||
des->add_node(cast);
|
des->add_node(cast);
|
||||||
|
|
||||||
|
|
@ -156,6 +176,14 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
|
||||||
return tmp;
|
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
|
* Add a signed constant to an existing expression. Generate a new
|
||||||
* NetEBAdd node that has the input expression and an expression made
|
* 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
|
* Generate the nodes necessary to cast an expression (a net) to a
|
||||||
* real value.
|
* 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 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
|
* Take the input expression and return a variation that assures that
|
||||||
* the expression is 1-bit wide and logical. This reflects the needs
|
* 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;
|
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)
|
static list<perm_string>* list_from_identifier(char*id)
|
||||||
{
|
{
|
||||||
list<perm_string>*tmp = new list<perm_string>;
|
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;
|
bool flag;
|
||||||
|
|
||||||
char letter;
|
char letter;
|
||||||
|
int int_val;
|
||||||
|
|
||||||
/* text items are C strings allocated by the lexor using
|
/* text items are C strings allocated by the lexor using
|
||||||
strdup. They can be put into lists with the texts type. */
|
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 <flag> from_exclude
|
||||||
%type <number> number
|
%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 <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
|
%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_simple_path specify_simple_path_decl
|
||||||
%type <specpath> specify_edge_path specify_edge_path_decl
|
%type <specpath> specify_edge_path specify_edge_path_decl
|
||||||
|
|
||||||
|
%type <int_val> atom2_type
|
||||||
|
|
||||||
%token K_TAND
|
%token K_TAND
|
||||||
%right '?' ':'
|
%right '?' ':'
|
||||||
%left K_LOR
|
%left K_LOR
|
||||||
|
|
@ -494,7 +508,7 @@ attribute
|
||||||
|
|
||||||
block_item_decl
|
block_item_decl
|
||||||
: attribute_list_opt K_reg
|
: attribute_list_opt K_reg
|
||||||
primitive_type_opt signed_opt range
|
primitive_type_opt unsigned_signed_opt range
|
||||||
register_variable_list ';'
|
register_variable_list ';'
|
||||||
{ ivl_variable_type_t dtype = $3;
|
{ ivl_variable_type_t dtype = $3;
|
||||||
if (dtype == IVL_VT_NO_TYPE)
|
if (dtype == IVL_VT_NO_TYPE)
|
||||||
|
|
@ -507,7 +521,7 @@ block_item_decl
|
||||||
range. This is the rule for a scalar. */
|
range. This is the rule for a scalar. */
|
||||||
|
|
||||||
| attribute_list_opt K_reg
|
| attribute_list_opt K_reg
|
||||||
primitive_type_opt signed_opt
|
primitive_type_opt unsigned_signed_opt
|
||||||
register_variable_list ';'
|
register_variable_list ';'
|
||||||
{ ivl_variable_type_t dtype = $3;
|
{ ivl_variable_type_t dtype = $3;
|
||||||
if (dtype == IVL_VT_NO_TYPE)
|
if (dtype == IVL_VT_NO_TYPE)
|
||||||
|
|
@ -516,18 +530,24 @@ block_item_decl
|
||||||
if ($1) delete $1;
|
if ($1) delete $1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Integer declarations are simpler in that they do not have all the
|
/* Integer atom declarations are simpler in that they do not have
|
||||||
trappings of a general variable declaration. All of that is
|
all the trappings of a general variable declaration. All of that
|
||||||
implicit in the "integer" of the declaration. */
|
is implicit in the "integer" of the declaration. */
|
||||||
|
|
||||||
| attribute_list_opt K_integer register_variable_list ';'
|
| attribute_list_opt K_integer signed_unsigned_opt register_variable_list ';'
|
||||||
{ pform_set_reg_integer($3);
|
{ pform_set_reg_integer($4);
|
||||||
if ($1) delete $1;
|
if ($1) delete $1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| attribute_list_opt K_time register_variable_list ';'
|
| attribute_list_opt K_time register_variable_list ';'
|
||||||
{ pform_set_reg_time($3);
|
{ 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
|
/* real declarations are fairly simple as there is no range of
|
||||||
signed flag in the declaration. Create the real as a NetNet::REG
|
signed flag in the declaration. Create the real as a NetNet::REG
|
||||||
|
|
@ -1880,7 +1900,7 @@ list_of_port_declarations
|
||||||
|
|
||||||
port_declaration
|
port_declaration
|
||||||
: attribute_list_opt
|
: 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;
|
{ Module::port_t*ptmp;
|
||||||
perm_string name = lex_strings.make($7);
|
perm_string name = lex_strings.make($7);
|
||||||
ptmp = pform_module_port_reference(name, @2.text,
|
ptmp = pform_module_port_reference(name, @2.text,
|
||||||
|
|
@ -1897,8 +1917,27 @@ port_declaration
|
||||||
delete[]$7;
|
delete[]$7;
|
||||||
$$ = ptmp;
|
$$ = 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
|
| 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;
|
{ Module::port_t*ptmp;
|
||||||
perm_string name = lex_strings.make($7);
|
perm_string name = lex_strings.make($7);
|
||||||
ptmp = pform_module_port_reference(name, @2.text,
|
ptmp = pform_module_port_reference(name, @2.text,
|
||||||
|
|
@ -1916,7 +1955,7 @@ port_declaration
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
}
|
}
|
||||||
| attribute_list_opt
|
| 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;
|
{ Module::port_t*ptmp;
|
||||||
perm_string name = lex_strings.make($7);
|
perm_string name = lex_strings.make($7);
|
||||||
ptmp = pform_module_port_reference(name, @2.text,
|
ptmp = pform_module_port_reference(name, @2.text,
|
||||||
|
|
@ -1934,7 +1973,7 @@ port_declaration
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
}
|
}
|
||||||
| attribute_list_opt
|
| 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;
|
{ Module::port_t*ptmp;
|
||||||
perm_string name = lex_strings.make($7);
|
perm_string name = lex_strings.make($7);
|
||||||
ptmp = pform_module_port_reference(name, @2.text,
|
ptmp = pform_module_port_reference(name, @2.text,
|
||||||
|
|
@ -1952,7 +1991,7 @@ port_declaration
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
}
|
}
|
||||||
| attribute_list_opt
|
| 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;
|
{ Module::port_t*ptmp;
|
||||||
perm_string name = lex_strings.make($7);
|
perm_string name = lex_strings.make($7);
|
||||||
ptmp = pform_module_port_reference(name, @2.text,
|
ptmp = pform_module_port_reference(name, @2.text,
|
||||||
|
|
@ -1972,6 +2011,25 @@ port_declaration
|
||||||
delete[]$7;
|
delete[]$7;
|
||||||
$$ = ptmp;
|
$$ = 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; }
|
| { $$ = 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
|
/* An lpvalue is the expression that can go on the left side of a
|
||||||
procedural assignment. This rule handles only procedural
|
procedural assignment. This rule handles only procedural
|
||||||
|
|
@ -2118,7 +2207,7 @@ module_item
|
||||||
resort to the default type LOGIC. */
|
resort to the default type LOGIC. */
|
||||||
|
|
||||||
: attribute_list_opt net_type
|
: attribute_list_opt net_type
|
||||||
primitive_type_opt signed_opt range_opt
|
primitive_type_opt unsigned_signed_opt range_opt
|
||||||
delay3_opt
|
delay3_opt
|
||||||
net_variable_list ';'
|
net_variable_list ';'
|
||||||
|
|
||||||
|
|
@ -2139,7 +2228,7 @@ module_item
|
||||||
declarations. */
|
declarations. */
|
||||||
|
|
||||||
| attribute_list_opt net_type
|
| 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 ';'
|
delay3_opt net_decl_assigns ';'
|
||||||
|
|
||||||
{ ivl_variable_type_t dtype = $3;
|
{ ivl_variable_type_t dtype = $3;
|
||||||
|
|
@ -2158,7 +2247,7 @@ module_item
|
||||||
gives strength to the assignment drivers. */
|
gives strength to the assignment drivers. */
|
||||||
|
|
||||||
| attribute_list_opt net_type
|
| attribute_list_opt net_type
|
||||||
primitive_type_opt signed_opt
|
primitive_type_opt unsigned_signed_opt
|
||||||
drive_strength net_decl_assigns ';'
|
drive_strength net_decl_assigns ';'
|
||||||
|
|
||||||
{ ivl_variable_type_t dtype = $3;
|
{ ivl_variable_type_t dtype = $3;
|
||||||
|
|
@ -2178,7 +2267,7 @@ module_item
|
||||||
delete $4;
|
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);
|
{ pform_set_port_type(@1, $5, $3, $2, $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2186,12 +2275,12 @@ module_item
|
||||||
input wire signed [h:l] <list>;
|
input wire signed [h:l] <list>;
|
||||||
This creates the wire and sets the port type all at once. */
|
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,
|
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0,
|
||||||
SR_BOTH);
|
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<pair<perm_string,PExpr*> >::const_iterator pp;
|
||||||
list<perm_string>*tmp = new list<perm_string>;
|
list<perm_string>*tmp = new list<perm_string>;
|
||||||
for (pp = $5->begin(); pp != $5->end(); pp++) {
|
for (pp = $5->begin(); pp != $5->end(); pp++) {
|
||||||
|
|
@ -2211,19 +2300,19 @@ module_item
|
||||||
because the port declaration implies an external driver, which
|
because the port declaration implies an external driver, which
|
||||||
cannot be attached to a reg. These rules catch that error early. */
|
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,
|
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINPUT,
|
||||||
IVL_VT_NO_TYPE, 0);
|
IVL_VT_NO_TYPE, 0);
|
||||||
yyerror(@2, "error: reg variables cannot be inputs.");
|
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,
|
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINOUT,
|
||||||
IVL_VT_NO_TYPE, 0);
|
IVL_VT_NO_TYPE, 0);
|
||||||
yyerror(@2, "error: reg variables cannot be inouts.");
|
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"
|
{ yyerror(@1, "error: Invalid variable list"
|
||||||
" in port declaration.");
|
" in port declaration.");
|
||||||
if ($3) delete $3;
|
if ($3) delete $3;
|
||||||
|
|
@ -2639,10 +2728,11 @@ net_decl_assigns
|
||||||
;
|
;
|
||||||
|
|
||||||
primitive_type
|
primitive_type
|
||||||
: K_logic { $$ = IVL_VT_LOGIC; }
|
: K_logic { $$ = IVL_VT_LOGIC; }
|
||||||
| K_bool { $$ = IVL_VT_BOOL; }
|
| K_bool { $$ = IVL_VT_BOOL; /* Icarus Verilog xtypes */}
|
||||||
| K_real { $$ = IVL_VT_REAL; }
|
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
|
||||||
;
|
| K_real { $$ = IVL_VT_REAL; }
|
||||||
|
;
|
||||||
|
|
||||||
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
|
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
|
||||||
|
|
||||||
|
|
@ -2657,12 +2747,12 @@ net_type
|
||||||
| K_supply1 { $$ = NetNet::SUPPLY1; }
|
| K_supply1 { $$ = NetNet::SUPPLY1; }
|
||||||
| K_wor { $$ = NetNet::WOR; }
|
| K_wor { $$ = NetNet::WOR; }
|
||||||
| K_trior { $$ = NetNet::TRIOR; }
|
| K_trior { $$ = NetNet::TRIOR; }
|
||||||
| K_wone { $$ = NetNet::UWIRE;
|
| K_wone { $$ = NetNet::UNRESOLVED_WIRE;
|
||||||
cerr << @1.text << ":" << @1.first_line << ": warning: "
|
cerr << @1.text << ":" << @1.first_line << ": warning: "
|
||||||
"'wone' is deprecated, please use 'uwire' "
|
"'wone' is deprecated, please use 'uwire' "
|
||||||
"instead." << endl;
|
"instead." << endl;
|
||||||
}
|
}
|
||||||
| K_uwire { $$ = NetNet::UWIRE; }
|
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
var_type
|
var_type
|
||||||
|
|
@ -3195,14 +3285,18 @@ dimensions
|
||||||
|
|
||||||
/* This is used to express the return type of a function. */
|
/* This is used to express the return type of a function. */
|
||||||
function_range_or_type_opt
|
function_range_or_type_opt
|
||||||
: range { $$.range = $1; $$.type = PTF_REG; }
|
: range { $$.range = $1; $$.type = PTF_REG; }
|
||||||
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
|
||||||
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
| K_unsigned range { $$.range = $2; $$.type = PTF_REG; }
|
||||||
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
|
||||||
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
| K_real { $$.range = 0; $$.type = PTF_REAL; }
|
||||||
| K_time { $$.range = 0; $$.type = PTF_TIME; }
|
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
|
||||||
| { $$.range = 0; $$.type = PTF_REG; }
|
| 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
|
/* The register_variable rule is matched only when I am parsing
|
||||||
variables in a "reg" definition. I therefore know that I am
|
variables in a "reg" definition. I therefore know that I am
|
||||||
|
|
@ -4039,30 +4133,27 @@ reg_opt
|
||||||
|
|
||||||
task_port_item
|
task_port_item
|
||||||
|
|
||||||
: K_input reg_opt signed_opt range_opt list_of_identifiers ';'
|
: K_input reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||||
{ svector<PWire*>*tmp
|
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||||
= pform_make_task_ports(NetNet::PINPUT,
|
|
||||||
IVL_VT_NO_TYPE, $3,
|
IVL_VT_NO_TYPE, $3,
|
||||||
$4, $5,
|
$4, $5,
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_output reg_opt signed_opt range_opt list_of_identifiers ';'
|
| K_output reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||||
{ svector<PWire*>*tmp
|
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||||
= pform_make_task_ports(NetNet::POUTPUT,
|
|
||||||
IVL_VT_LOGIC, $3,
|
IVL_VT_LOGIC, $3,
|
||||||
$4, $5,
|
$4, $5,
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_inout reg_opt signed_opt range_opt list_of_identifiers ';'
|
| K_inout reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
|
||||||
{ svector<PWire*>*tmp
|
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||||
= pform_make_task_ports(NetNet::PINOUT,
|
|
||||||
IVL_VT_LOGIC, $3,
|
IVL_VT_LOGIC, $3,
|
||||||
$4, $5,
|
$4, $5,
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the port is an integer, infer a signed vector of the integer
|
/* When the port is an integer, infer a signed vector of the integer
|
||||||
shape. Generate a range ([31:0]) to make it work. */
|
shape. Generate a range ([31:0]) to make it work. */
|
||||||
|
|
@ -4206,7 +4297,7 @@ task_item_list_opt
|
||||||
|
|
||||||
task_port_decl
|
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.port_type = NetNet::PINPUT;
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
port_declaration_context.sign_flag = $3;
|
port_declaration_context.sign_flag = $3;
|
||||||
|
|
@ -4220,7 +4311,7 @@ task_port_decl
|
||||||
$$ = tmp;
|
$$ = 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.port_type = NetNet::POUTPUT;
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
port_declaration_context.sign_flag = $3;
|
port_declaration_context.sign_flag = $3;
|
||||||
|
|
@ -4233,7 +4324,7 @@ task_port_decl
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = 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.port_type = NetNet::PINOUT;
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
port_declaration_context.sign_flag = $3;
|
port_declaration_context.sign_flag = $3;
|
||||||
|
|
@ -4315,66 +4406,48 @@ task_port_decl
|
||||||
|
|
||||||
/* Ports can be time with a width of [63:0] (unsigned). */
|
/* Ports can be time with a width of [63:0] (unsigned). */
|
||||||
|
|
||||||
| K_input K_time IDENTIFIER
|
| K_input K_time IDENTIFIER
|
||||||
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
|
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||||
PExpr*re;
|
port_declaration_context.port_type = NetNet::PINPUT;
|
||||||
re = new PENumber(new verinum((uint64_t)63, integer_width));
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
(*range_stub)[0] = re;
|
port_declaration_context.sign_flag = false;
|
||||||
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
delete port_declaration_context.range;
|
||||||
(*range_stub)[1] = re;
|
port_declaration_context.range = copy_range(range_stub);
|
||||||
port_declaration_context.port_type = NetNet::PINPUT;
|
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
IVL_VT_LOGIC, false,
|
||||||
port_declaration_context.sign_flag = false;
|
range_stub,
|
||||||
delete port_declaration_context.range;
|
list_from_identifier($3),
|
||||||
port_declaration_context.range = copy_range(range_stub);
|
@1.text, @1.first_line);
|
||||||
svector<PWire*>*tmp
|
$$ = tmp;
|
||||||
= pform_make_task_ports(NetNet::PINPUT,
|
}
|
||||||
IVL_VT_LOGIC, false,
|
| K_output K_time IDENTIFIER
|
||||||
range_stub,
|
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||||
list_from_identifier($3),
|
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||||
@1.text, @1.first_line);
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
$$ = tmp;
|
port_declaration_context.sign_flag = false;
|
||||||
}
|
delete port_declaration_context.range;
|
||||||
| K_output K_time IDENTIFIER
|
port_declaration_context.range = copy_range(range_stub);
|
||||||
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
|
svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
|
||||||
PExpr*re;
|
IVL_VT_LOGIC, false,
|
||||||
re = new PENumber(new verinum((uint64_t)63, integer_width));
|
range_stub,
|
||||||
(*range_stub)[0] = re;
|
list_from_identifier($3),
|
||||||
re = new PENumber(new verinum((uint64_t)0, integer_width));
|
@1.text, @1.first_line);
|
||||||
(*range_stub)[1] = re;
|
$$ = tmp;
|
||||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
}
|
||||||
port_declaration_context.var_type = IVL_VT_LOGIC;
|
| K_inout K_time IDENTIFIER
|
||||||
port_declaration_context.sign_flag = false;
|
{ svector<PExpr*>*range_stub = make_range_from_width(64);
|
||||||
delete port_declaration_context.range;
|
port_declaration_context.port_type = NetNet::PINOUT;
|
||||||
port_declaration_context.range = copy_range(range_stub);
|
port_declaration_context.var_type = IVL_VT_LOGIC;
|
||||||
svector<PWire*>*tmp
|
port_declaration_context.sign_flag = false;
|
||||||
= pform_make_task_ports(NetNet::POUTPUT,
|
delete port_declaration_context.range;
|
||||||
IVL_VT_LOGIC, false,
|
port_declaration_context.range = copy_range(range_stub);
|
||||||
range_stub,
|
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
|
||||||
list_from_identifier($3),
|
IVL_VT_LOGIC, false,
|
||||||
@1.text, @1.first_line);
|
range_stub,
|
||||||
$$ = tmp;
|
list_from_identifier($3),
|
||||||
}
|
@1.text, @1.first_line);
|
||||||
| K_inout K_time IDENTIFIER
|
$$ = tmp;
|
||||||
{ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ports can be real or realtime. */
|
/* Ports can be real or realtime. */
|
||||||
|
|
||||||
|
|
@ -4417,7 +4490,51 @@ task_port_decl
|
||||||
@1.text, @1.first_line);
|
@1.text, @1.first_line);
|
||||||
$$ = tmp;
|
$$ = 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_list ',' task_port_decl
|
: 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;
|
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*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||||
{
|
{
|
||||||
svector<PWire*>*out = new svector<PWire*>(names->size());
|
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_integer(list<perm_string>*names);
|
||||||
extern void pform_set_reg_time(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
|
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||||
$attribute syntax, which can only set string values to
|
$attribute syntax, which can only set string values to
|
||||||
attributes. The functions keep the value strings that are
|
attributes. The functions keep the value strings that are
|
||||||
|
|
|
||||||
|
|
@ -787,6 +787,12 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
||||||
case PTF_TIME:
|
case PTF_TIME:
|
||||||
out << "time ";
|
out << "time ";
|
||||||
break;
|
break;
|
||||||
|
case PTF_ATOM2:
|
||||||
|
out << "int unsigned ";
|
||||||
|
break;
|
||||||
|
case PTF_ATOM2_S:
|
||||||
|
cout << "int signed ";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type_.range) {
|
if (return_type_.range) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#
|
#
|
||||||
# NOTE: DO NOT INSTALL THIS FILE!
|
# NOTE: DO NOT INSTALL THIS FILE!
|
||||||
#
|
#
|
||||||
generation:2005
|
generation:2009
|
||||||
generation:specify
|
generation:specify
|
||||||
generation:xtypes
|
generation:xtypes
|
||||||
generation:verilog-ams
|
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) {
|
switch (net->type) {
|
||||||
case IVL_LPM_ABS:
|
case IVL_LPM_ABS:
|
||||||
case IVL_LPM_CAST_INT:
|
case IVL_LPM_CAST_INT:
|
||||||
|
case IVL_LPM_CAST_INT2:
|
||||||
case IVL_LPM_CAST_REAL:
|
case IVL_LPM_CAST_REAL:
|
||||||
assert(idx == 0);
|
assert(idx == 0);
|
||||||
return net->u_.arith.a;
|
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_ABS:
|
||||||
case IVL_LPM_ADD:
|
case IVL_LPM_ADD:
|
||||||
case IVL_LPM_CAST_INT:
|
case IVL_LPM_CAST_INT:
|
||||||
|
case IVL_LPM_CAST_INT2:
|
||||||
case IVL_LPM_CAST_REAL:
|
case IVL_LPM_CAST_REAL:
|
||||||
case IVL_LPM_CMP_GE:
|
case IVL_LPM_CMP_GE:
|
||||||
case IVL_LPM_CMP_GT:
|
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_MULT:
|
||||||
case IVL_LPM_POW:
|
case IVL_LPM_POW:
|
||||||
case IVL_LPM_SUB:
|
case IVL_LPM_SUB:
|
||||||
|
case IVL_LPM_CAST_INT2:
|
||||||
return net->u_.arith.signed_flag;
|
return net->u_.arith.signed_flag;
|
||||||
case IVL_LPM_RE_AND:
|
case IVL_LPM_RE_AND:
|
||||||
case IVL_LPM_RE_OR:
|
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);
|
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;
|
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||||
obj->type = IVL_LPM_CAST_INT;
|
obj->type = lpm_type;
|
||||||
obj->name = net->name(); // NetCastInt names are permallocated
|
obj->name = net->name(); // NetCastInt2 names are permallocated
|
||||||
assert(net->scope());
|
assert(net->scope());
|
||||||
obj->scope = find_scope(des_, net->scope());
|
obj->scope = find_scope(des_, net->scope());
|
||||||
assert(obj->scope);
|
assert(obj->scope);
|
||||||
|
|
||||||
obj->width = net->width();
|
obj->width = width;
|
||||||
|
obj->u_.arith.signed_flag = signed_flag? 1 : 0;
|
||||||
|
|
||||||
const Nexus*nex;
|
const Nexus*nex;
|
||||||
|
|
||||||
|
|
@ -1520,37 +1521,19 @@ bool dll_target::lpm_cast_int(const NetCastInt*net)
|
||||||
return true;
|
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)
|
bool dll_target::lpm_cast_real(const NetCastReal*net)
|
||||||
{
|
{
|
||||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
return lpm_arith1_(IVL_LPM_CAST_REAL, 0, net->signed_flag(), net);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2389,7 +2372,7 @@ void dll_target::signal(const NetNet*net)
|
||||||
|
|
||||||
/* We will convert this to a TRI after we check that there
|
/* We will convert this to a TRI after we check that there
|
||||||
is only one driver. */
|
is only one driver. */
|
||||||
case NetNet::UWIRE:
|
case NetNet::UNRESOLVED_WIRE:
|
||||||
obj->type_ = IVL_SIT_UWIRE;
|
obj->type_ = IVL_SIT_UWIRE;
|
||||||
break;
|
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_abs(const NetAbs*);
|
||||||
void lpm_add_sub(const NetAddSub*);
|
void lpm_add_sub(const NetAddSub*);
|
||||||
bool lpm_array_dq(const NetArrayDq*);
|
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*);
|
bool lpm_cast_real(const NetCastReal*);
|
||||||
void lpm_clshift(const NetCLShift*);
|
void lpm_clshift(const NetCLShift*);
|
||||||
void lpm_compare(const NetCompare*);
|
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);
|
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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool target_t::lpm_cast_int(const NetCastInt*)
|
bool target_t::lpm_cast_int2(const NetCastInt2*)
|
||||||
{
|
{
|
||||||
cerr << "target (" << typeid(*this).name() << "): "
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
3
target.h
3
target.h
|
|
@ -75,7 +75,8 @@ struct target_t {
|
||||||
virtual void lpm_add_sub(const NetAddSub*);
|
virtual void lpm_add_sub(const NetAddSub*);
|
||||||
virtual bool lpm_array_dq(const NetArrayDq*);
|
virtual bool lpm_array_dq(const NetArrayDq*);
|
||||||
virtual void lpm_clshift(const NetCLShift*);
|
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 bool lpm_cast_real(const NetCastReal*);
|
||||||
virtual void lpm_compare(const NetCompare*);
|
virtual void lpm_compare(const NetCompare*);
|
||||||
virtual void lpm_divide(const NetDivide*);
|
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_ABS:
|
||||||
case IVL_LPM_ADD:
|
case IVL_LPM_ADD:
|
||||||
case IVL_LPM_ARRAY:
|
case IVL_LPM_ARRAY:
|
||||||
|
case IVL_LPM_CAST_INT2:
|
||||||
case IVL_LPM_CAST_INT:
|
case IVL_LPM_CAST_INT:
|
||||||
case IVL_LPM_CAST_REAL:
|
case IVL_LPM_CAST_REAL:
|
||||||
case IVL_LPM_CONCAT:
|
case IVL_LPM_CONCAT:
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,12 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
|
||||||
clr_word(res);
|
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)
|
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
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:
|
case IVL_VT_REAL:
|
||||||
function_argument_real(port, expr);
|
function_argument_real(port, expr);
|
||||||
break;
|
break;
|
||||||
|
case IVL_VT_BOOL:
|
||||||
|
function_argument_bool(port, expr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||||
ivl_signal_basename(port), dtype);
|
ivl_signal_basename(port), dtype);
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,14 @@ static int eval_bool64_logic(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct vector_info tmp;
|
struct vector_info tmp;
|
||||||
|
const char*s_flag = "";
|
||||||
|
|
||||||
tmp = draw_eval_expr(expr, STUFF_OK_XZ);
|
tmp = draw_eval_expr(expr, STUFF_OK_XZ);
|
||||||
res = allocate_word();
|
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);
|
clr_vector(tmp);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -3126,6 +3126,21 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid)
|
||||||
local_count += 1;
|
local_count += 1;
|
||||||
break;
|
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. */
|
case 'i': /* Cast a real value to an integer. */
|
||||||
assert(ivl_expr_value(sub) == IVL_VT_REAL);
|
assert(ivl_expr_value(sub) == IVL_VT_REAL);
|
||||||
word = draw_eval_real(sub);
|
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)? "*" : "";
|
const char*local_flag = ivl_signal_local(sig)? "*" : "";
|
||||||
|
|
||||||
switch (ivl_signal_data_type(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:
|
case IVL_VT_REAL:
|
||||||
datatype_flag = "/real";
|
datatype_flag = "/real";
|
||||||
break;
|
break;
|
||||||
|
|
@ -470,6 +476,12 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
||||||
unsigned iword;
|
unsigned iword;
|
||||||
|
|
||||||
switch (ivl_signal_data_type(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:
|
case IVL_VT_REAL:
|
||||||
datatype_flag = "/real";
|
datatype_flag = "/real";
|
||||||
break;
|
break;
|
||||||
|
|
@ -1209,6 +1221,19 @@ static void draw_lpm_abs(ivl_lpm_t net)
|
||||||
net, dly, src_table[0]);
|
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)
|
static void draw_lpm_cast_int(ivl_lpm_t net)
|
||||||
{
|
{
|
||||||
const char*src_table[1];
|
const char*src_table[1];
|
||||||
|
|
@ -1829,6 +1854,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
||||||
draw_lpm_cast_int(net);
|
draw_lpm_cast_int(net);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case IVL_LPM_CAST_INT2:
|
||||||
|
draw_lpm_cast_int2(net);
|
||||||
|
return;
|
||||||
|
|
||||||
case IVL_LPM_CAST_REAL:
|
case IVL_LPM_CAST_REAL:
|
||||||
draw_lpm_cast_real(net);
|
draw_lpm_cast_real(net);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1048,6 +1048,10 @@ static int sys_check_args(vpiHandle callh, vpiHandle argv, const PLI_BYTE8*name,
|
||||||
case vpiNet:
|
case vpiNet:
|
||||||
case vpiReg:
|
case vpiReg:
|
||||||
case vpiIntegerVar:
|
case vpiIntegerVar:
|
||||||
|
case vpiByteVar:
|
||||||
|
case vpiShortIntVar:
|
||||||
|
case vpiIntVar:
|
||||||
|
case vpiLongIntVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiRealVar:
|
case vpiRealVar:
|
||||||
case vpiSysFuncCall:
|
case vpiSysFuncCall:
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vpi_config.h"
|
#include "vpi_config.h"
|
||||||
#include "vpi_user.h"
|
#include "sv_vpi_user.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Context structure for PRNG in mt19937int.c
|
* 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
|
has no structural input) and propagates its output to a functor. The
|
||||||
general syntax of a variable is:
|
general syntax of a variable is:
|
||||||
|
|
||||||
<label> .var "name", <msb>, <lsb>; Unsigned logic variable
|
<label> .var "name", <msb> <lsb>; Unsigned logic variable
|
||||||
<label> .var/s "name", <msb>, <lsb>; Signed 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/real "name", <msb>, <lsb>; real varibale
|
||||||
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar variable
|
<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:
|
are used to perform that operation:
|
||||||
|
|
||||||
<label> .cast/int <width>, <symbol>;
|
<label> .cast/int <width>, <symbol>;
|
||||||
|
<label> .cast/2 <width>, <symbol>;
|
||||||
<label> .cast/real <symbol>;
|
<label> .cast/real <symbol>;
|
||||||
<label> .cast/real.s <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);
|
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
|
// Division
|
||||||
|
|
||||||
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
|
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_;
|
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_ {
|
class vvp_arith_div : public vvp_arith_ {
|
||||||
|
|
||||||
public:
|
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);
|
extern void vpip_array_change(struct __vpiCallback*cb, vpiHandle word);
|
||||||
|
|
||||||
/* Compile hooks */
|
/* 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,
|
extern void compile_varw_real(char*label, vvp_array_t array,
|
||||||
unsigned long array_addr,
|
unsigned long array_addr,
|
||||||
int msb, int lsb);
|
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_V(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CASSIGN_WR(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_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_CMPIS(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_CMPIU(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);
|
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/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/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} },
|
{ "%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/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||||
{ "%cmp/u", of_CMPU, 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} },
|
{ "%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) {
|
switch (vpi->vpi_type->type_code) {
|
||||||
case vpiNet:
|
case vpiNet:
|
||||||
case vpiReg:
|
case vpiReg:
|
||||||
|
case vpiByteVar:
|
||||||
|
case vpiShortIntVar:
|
||||||
|
case vpiIntVar:
|
||||||
|
case vpiLongIntVar:
|
||||||
case vpiIntegerVar: {
|
case vpiIntegerVar: {
|
||||||
__vpiSignal*sig = (__vpiSignal*)vpi;
|
__vpiSignal*sig = (__vpiSignal*)vpi;
|
||||||
return sig->node;
|
return sig->node;
|
||||||
|
|
@ -908,6 +913,22 @@ void compile_arith_cast_int(char*label, long width,
|
||||||
free(argv);
|
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,
|
void compile_arith_cast_real(char*label, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv)
|
unsigned argc, struct symb_s*argv)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
# include <fstream>
|
# include <fstream>
|
||||||
# include <vector>
|
# include <vector>
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
# include "vpi_user.h"
|
# include "sv_vpi_user.h"
|
||||||
# include "vvp_net.h"
|
# include "vvp_net.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
@ -158,6 +158,8 @@ extern void compile_arith_cast_int(char*label, long width,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
extern void compile_arith_cast_real(char*label, bool signed_flag,
|
extern void compile_arith_cast_real(char*label, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv);
|
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,
|
extern void compile_arith_div(char*label, long width, bool signed_flag,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
extern void compile_arith_mod(char*label, long width, bool signed_flag,
|
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.
|
* 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,
|
extern void compile_variable(char*label, char*name,
|
||||||
int msb, int lsb, char signed_flag,
|
int msb, int lsb, int vpi_type_code,
|
||||||
bool local_flag);
|
bool signed_flag, bool local_flag);
|
||||||
|
|
||||||
extern void compile_var_real(char*label, char*name,
|
extern void compile_var_real(char*label, char*name,
|
||||||
int msb, int lsb);
|
int msb, int lsb);
|
||||||
|
|
||||||
extern void compile_net(char*label, char*name,
|
/*
|
||||||
int msb, int lsb, bool signed_flag,
|
* The compile_net functio is called to create a .net vector with a
|
||||||
bool net8_flag, bool local_flag,
|
* 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);
|
unsigned argc, struct symb_s*argv);
|
||||||
|
|
||||||
extern void compile_net_real(char*label, char*name,
|
extern void compile_net_real(char*label, char*name,
|
||||||
int msb, int lsb, bool local_flag,
|
int msb, int lsb, bool local_flag,
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
|
|
||||||
extern void compile_netw(char*label, char*array_symbol,
|
extern void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
||||||
unsigned long array_addr,
|
int msb, int lsb, int vpi_type_code, bool signed_flag,
|
||||||
int msb, int lsb, bool signed_flag,
|
|
||||||
bool net8_flag,
|
|
||||||
unsigned argc, struct symb_s*argv);
|
unsigned argc, struct symb_s*argv);
|
||||||
|
|
||||||
extern void compile_netw_real(char*label, char*array_symbol,
|
extern void compile_netw_real(char*label, char*array_symbol,
|
||||||
unsigned long array_addr,
|
unsigned long array_addr,
|
||||||
int msb, int lsb,
|
int msb, int lsb,
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ static char* strdupnew(char const *str)
|
||||||
".array/real" { return K_ARRAY_R; }
|
".array/real" { return K_ARRAY_R; }
|
||||||
".array/s" { return K_ARRAY_S; }
|
".array/s" { return K_ARRAY_S; }
|
||||||
".array/port" { return K_ARRAY_PORT; }
|
".array/port" { return K_ARRAY_PORT; }
|
||||||
|
".cast/2" { return K_CAST_2; }
|
||||||
".cast/int" { return K_CAST_INT; }
|
".cast/int" { return K_CAST_INT; }
|
||||||
".cast/real" { return K_CAST_REAL; }
|
".cast/real" { return K_CAST_REAL; }
|
||||||
".cast/real.s" { return K_CAST_REAL_S; }
|
".cast/real.s" { return K_CAST_REAL_S; }
|
||||||
|
|
@ -148,8 +149,10 @@ static char* strdupnew(char const *str)
|
||||||
".functor" { return K_FUNCTOR; }
|
".functor" { return K_FUNCTOR; }
|
||||||
".import" { return K_IMPORT; }
|
".import" { return K_IMPORT; }
|
||||||
".island" { return K_ISLAND; }
|
".island" { return K_ISLAND; }
|
||||||
".modpath" { return K_MODPATH; }
|
".modpath" { return K_MODPATH; }
|
||||||
".net" { return K_NET; }
|
".net" { return K_NET; }
|
||||||
|
".net/2s" { return K_NET_2S; }
|
||||||
|
".net/2u" { return K_NET_2U; }
|
||||||
".net8" { return K_NET8; }
|
".net8" { return K_NET8; }
|
||||||
".net8/s" { return K_NET8_S; }
|
".net8/s" { return K_NET8_S; }
|
||||||
".net/real" { return K_NET_R; }
|
".net/real" { return K_NET_R; }
|
||||||
|
|
@ -188,6 +191,8 @@ static char* strdupnew(char const *str)
|
||||||
".var/real" { return K_VAR_R; }
|
".var/real" { return K_VAR_R; }
|
||||||
".var/s" { return K_VAR_S; }
|
".var/s" { return K_VAR_S; }
|
||||||
".var/i" { return K_VAR_I; /* integer */ }
|
".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" { return K_UDP; }
|
||||||
".udp/c"(omb)? { return K_UDP_C; }
|
".udp/c"(omb)? { return K_UDP_C; }
|
||||||
".udp/s"(equ)? { return K_UDP_S; }
|
".udp/s"(equ)? { return K_UDP_S; }
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
# include "delay.h"
|
# include "delay.h"
|
||||||
# include "statistics.h"
|
# include "statistics.h"
|
||||||
|
# include <iostream>
|
||||||
# include <cstring>
|
# include <cstring>
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
# include <cstdlib>
|
# 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
|
assign port (port-0), so the signal responds differently. See
|
||||||
"VARIABLE STATEMENTS" and "NET STATEMENTS" in the README.txt file.
|
"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/u <bit-l>, <bit-r>, <wid>
|
||||||
* %cmp/s <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_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_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_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_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_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_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_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_MODPATH
|
||||||
%token K_NET8 K_NET8_S
|
%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_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_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_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_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_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_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_vpi_func K_vpi_func_r
|
||||||
%token K_disable K_fork
|
%token K_disable K_fork
|
||||||
%token K_ivl_version K_ivl_delay_selection
|
%token K_ivl_version K_ivl_delay_selection
|
||||||
|
|
@ -271,20 +272,25 @@ statement
|
||||||
compile_arith_abs($1, obj.cnt, obj.vect);
|
compile_arith_abs($1, obj.cnt, obj.vect);
|
||||||
}
|
}
|
||||||
|
|
||||||
| T_LABEL K_CAST_INT T_NUMBER ',' symbols ';'
|
| T_LABEL K_CAST_INT T_NUMBER ',' symbols ';'
|
||||||
{ struct symbv_s obj = $5;
|
{ struct symbv_s obj = $5;
|
||||||
compile_arith_cast_int($1, $3, obj.cnt, obj.vect);
|
compile_arith_cast_int($1, $3, obj.cnt, obj.vect);
|
||||||
}
|
}
|
||||||
|
|
||||||
| T_LABEL K_CAST_REAL symbols ';'
|
| T_LABEL K_CAST_REAL symbols ';'
|
||||||
{ struct symbv_s obj = $3;
|
{ struct symbv_s obj = $3;
|
||||||
compile_arith_cast_real($1, false, obj.cnt, obj.vect);
|
compile_arith_cast_real($1, false, obj.cnt, obj.vect);
|
||||||
}
|
}
|
||||||
|
|
||||||
| T_LABEL K_CAST_REAL_S symbols ';'
|
| T_LABEL K_CAST_REAL_S symbols ';'
|
||||||
{ struct symbv_s obj = $3;
|
{ struct symbv_s obj = $3;
|
||||||
compile_arith_cast_real($1, true, obj.cnt, obj.vect);
|
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
|
/* Arithmetic statements generate functor arrays of a given width
|
||||||
that take like size input vectors. */
|
that take like size input vectors. */
|
||||||
|
|
@ -651,13 +657,19 @@ statement
|
||||||
the variable in the netlist. */
|
the variable in the netlist. */
|
||||||
|
|
||||||
| T_LABEL K_VAR local_flag T_STRING ',' signed_t_number signed_t_number ';'
|
| 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 ';'
|
| 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 ';'
|
| 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 ';'
|
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
|
||||||
{ compile_var_real($1, $3, $5, $6); }
|
{ 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
|
| T_LABEL K_NET local_flag T_STRING ',' signed_t_number signed_t_number
|
||||||
',' symbols_net ';'
|
',' 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
|
| T_LABEL K_NET_S local_flag T_STRING ',' signed_t_number signed_t_number
|
||||||
',' symbols_net ';'
|
',' 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
|
| T_LABEL K_NET8 local_flag T_STRING ',' signed_t_number signed_t_number
|
||||||
',' symbols_net ';'
|
',' 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
|
| T_LABEL K_NET8_S local_flag T_STRING ',' signed_t_number signed_t_number
|
||||||
',' symbols_net ';'
|
',' 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
|
| T_LABEL K_NET_R local_flag T_STRING ',' signed_t_number signed_t_number
|
||||||
',' symbols_net ';'
|
',' symbols_net ';'
|
||||||
|
|
@ -687,30 +707,25 @@ statement
|
||||||
|
|
||||||
/* Arrayed versions of net directives. */
|
/* Arrayed versions of net directives. */
|
||||||
|
|
||||||
| T_LABEL K_NET T_SYMBOL T_NUMBER ','
|
| T_LABEL K_NET T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||||
signed_t_number signed_t_number ','
|
symbols_net ';'
|
||||||
symbols_net ';'
|
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, false, $9.cnt, $9.vect); }
|
||||||
{ compile_netw($1, $3, $4, $6, $7, false, false, $9.cnt, $9.vect); }
|
|
||||||
|
|
||||||
| T_LABEL K_NET_S T_SYMBOL T_NUMBER ','
|
| T_LABEL K_NET_S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||||
signed_t_number signed_t_number ','
|
symbols_net ';'
|
||||||
symbols_net ';'
|
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, true, $9.cnt, $9.vect); }
|
||||||
{ compile_netw($1, $3, $4, $6, $7, true, false, $9.cnt, $9.vect); }
|
|
||||||
|
|
||||||
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ','
|
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||||
signed_t_number signed_t_number ','
|
symbols_net ';'
|
||||||
symbols_net ';'
|
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, false, $9.cnt, $9.vect); }
|
||||||
{ compile_netw($1, $3, $4, $6, $7, false, true, $9.cnt, $9.vect); }
|
|
||||||
|
|
||||||
| T_LABEL K_NET8_S T_SYMBOL T_NUMBER ','
|
| T_LABEL K_NET8_S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||||
signed_t_number signed_t_number ','
|
symbols_net ';'
|
||||||
symbols_net ';'
|
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, true, $9.cnt, $9.vect); }
|
||||||
{ compile_netw($1, $3, $4, $6, $7, true, true, $9.cnt, $9.vect); }
|
|
||||||
|
|
||||||
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ','
|
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
|
||||||
signed_t_number signed_t_number ','
|
symbols_net ';'
|
||||||
symbols_net ';'
|
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
|
||||||
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
|
|
||||||
|
|
||||||
/* Array word versions of alias directives. */
|
/* Array word versions of alias directives. */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,14 +255,20 @@ static const char* vpi_type_values(PLI_INT32 code)
|
||||||
{
|
{
|
||||||
static char buf[32];
|
static char buf[32];
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
case vpiByteVar:
|
||||||
|
return "vpiByteVar";
|
||||||
case vpiConstant:
|
case vpiConstant:
|
||||||
return "vpiConstant";
|
return "vpiConstant";
|
||||||
case vpiFunction:
|
case vpiFunction:
|
||||||
return "vpiFunction";
|
return "vpiFunction";
|
||||||
|
case vpiIntVar:
|
||||||
|
return "vpiIntVar";
|
||||||
case vpiIntegerVar:
|
case vpiIntegerVar:
|
||||||
return "vpiIntegerVar";
|
return "vpiIntegerVar";
|
||||||
case vpiIterator:
|
case vpiIterator:
|
||||||
return "vpiIterator";
|
return "vpiIterator";
|
||||||
|
case vpiLongIntVar:
|
||||||
|
return "vpiLongIntVar";
|
||||||
case vpiMemory:
|
case vpiMemory:
|
||||||
return "vpiMemory";
|
return "vpiMemory";
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
|
|
@ -287,6 +293,8 @@ static const char* vpi_type_values(PLI_INT32 code)
|
||||||
return "vpiRealVar";
|
return "vpiRealVar";
|
||||||
case vpiReg:
|
case vpiReg:
|
||||||
return "vpiReg";
|
return "vpiReg";
|
||||||
|
case vpiShortIntVar:
|
||||||
|
return "vpiShortIntVar";
|
||||||
case vpiSysFuncCall:
|
case vpiSysFuncCall:
|
||||||
return "vpiSysFuncCall";
|
return "vpiSysFuncCall";
|
||||||
case vpiSysTaskCall:
|
case vpiSysTaskCall:
|
||||||
|
|
@ -318,9 +326,7 @@ PLI_INT32 vpi_get(int property, vpiHandle ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||||
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
|
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
||||||
return vpiIntegerVar;
|
|
||||||
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
|
||||||
return vpiNetArray;
|
return vpiNetArray;
|
||||||
else
|
else
|
||||||
return ref->vpi_type->type_code;
|
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;
|
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||||
PLI_INT32 type;
|
PLI_INT32 type;
|
||||||
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
|
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
||||||
type = vpiIntegerVar;
|
|
||||||
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
|
|
||||||
type = vpiNetArray;
|
type = vpiNetArray;
|
||||||
else
|
else
|
||||||
type = ref->vpi_type->type_code;
|
type = ref->vpi_type->type_code;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* 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 "vvp_net.h"
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
|
|
@ -243,7 +243,6 @@ struct __vpiSignal {
|
||||||
int msb, lsb;
|
int msb, lsb;
|
||||||
/* Flags */
|
/* Flags */
|
||||||
unsigned signed_flag : 1;
|
unsigned signed_flag : 1;
|
||||||
unsigned isint_ : 1; // original type was integer
|
|
||||||
unsigned is_netarray : 1; // This is word of a net array
|
unsigned is_netarray : 1; // This is word of a net array
|
||||||
/* The represented value is here. */
|
/* The represented value is here. */
|
||||||
vvp_net_t*node;
|
vvp_net_t*node;
|
||||||
|
|
@ -251,12 +250,14 @@ struct __vpiSignal {
|
||||||
extern unsigned vpip_size(__vpiSignal *sig);
|
extern unsigned vpip_size(__vpiSignal *sig);
|
||||||
extern struct __vpiScope* vpip_scope(__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);
|
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);
|
bool signed_flag, vvp_net_t*net);
|
||||||
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
|
||||||
bool signed_flag, vvp_net_t*node);
|
bool signed_flag, vvp_net_t*node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used by system calls to represent a bit/part select of
|
* 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)
|
struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref)
|
||||||
{
|
{
|
||||||
if ((ref->vpi_type->type_code != vpiNet)
|
switch (ref->vpi_type->type_code) {
|
||||||
&& (ref->vpi_type->type_code != vpiReg))
|
case vpiNet:
|
||||||
return 0;
|
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
|
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 = {
|
static const struct __vpirt vpip_net_rt = {
|
||||||
vpiNet,
|
vpiNet,
|
||||||
signal_get,
|
signal_get,
|
||||||
|
|
@ -888,31 +907,97 @@ static const struct __vpirt vpip_net_rt = {
|
||||||
0
|
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
|
* Construct a vpiIntegerVar object. Indicate the type using a flag
|
||||||
* to minimize the code modifications. Icarus implements integers
|
* to minimize the code modifications. Icarus implements integers
|
||||||
* as 'reg signed [31:0]'.
|
* 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);
|
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
|
||||||
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
|
obj->vpi_type = &vpip_integer_rt;
|
||||||
obj->vpi_type = &vpip_reg_rt;
|
return obj;
|
||||||
rfp->isint_ = true;
|
}
|
||||||
|
|
||||||
|
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;
|
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)
|
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;
|
obj->vpi_type = &vpip_reg_rt;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
static struct __vpiSignal **signal_pool = 0;
|
static struct __vpiSignal **signal_pool = 0;
|
||||||
static unsigned signal_pool_count = 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
|
* The name is the PLI name for the object. If it is an array it is
|
||||||
* <name>[<index>].
|
* <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)
|
bool signed_flag, vvp_net_t*node)
|
||||||
{
|
{
|
||||||
struct __vpiSignal*obj = allocate_vpiSignal();
|
struct __vpiSignal*obj = allocate_vpiSignal();
|
||||||
|
|
@ -997,7 +1082,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||||
obj->msb = msb;
|
obj->msb = msb;
|
||||||
obj->lsb = lsb;
|
obj->lsb = lsb;
|
||||||
obj->signed_flag = signed_flag? 1 : 0;
|
obj->signed_flag = signed_flag? 1 : 0;
|
||||||
obj->isint_ = 0;
|
|
||||||
obj->is_netarray = 0;
|
obj->is_netarray = 0;
|
||||||
obj->node = node;
|
obj->node = node;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1385,6 +1385,34 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
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)
|
bool of_CMPS(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
vvp_bit4_t eq = BIT4_1;
|
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;
|
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();
|
wid_ = that.size();
|
||||||
const unsigned words = (that.size() + BITS_PER_WORD-1) / BITS_PER_WORD;
|
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)) {
|
switch (that.value(idx)) {
|
||||||
case BIT4_0:
|
case BIT4_0:
|
||||||
|
case BIT4_X:
|
||||||
|
case BIT4_Z:
|
||||||
break;
|
break;
|
||||||
case BIT4_1:
|
case BIT4_1:
|
||||||
vec_[addr] |= 1UL << shift;
|
vec_[addr] |= 1UL << shift;
|
||||||
break;
|
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];
|
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)
|
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned newsize)
|
||||||
{
|
{
|
||||||
wid_ = newsize;
|
wid_ = newsize;
|
||||||
|
|
@ -2036,6 +2045,14 @@ vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector2_t&that)
|
||||||
return *this;
|
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)
|
vvp_vector2_t& vvp_vector2_t::operator <<= (unsigned int shift)
|
||||||
{
|
{
|
||||||
if (wid_ == 0)
|
if (wid_ == 0)
|
||||||
|
|
@ -2200,11 +2217,6 @@ vvp_vector2_t& vvp_vector2_t::operator -= (const vvp_vector2_t&that)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_vector2_t::~vvp_vector2_t()
|
|
||||||
{
|
|
||||||
delete[] vec_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vvp_vector2_t::trim()
|
void vvp_vector2_t::trim()
|
||||||
{
|
{
|
||||||
while (value(wid_-1) == 0 && wid_ > 1) wid_ -= 1;
|
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);
|
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
|
bool vvp_vector2_t::is_NaN() const
|
||||||
{
|
{
|
||||||
return wid_ == 0;
|
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;
|
const vvp_vector8_t vvp_vector8_t::nil;
|
||||||
|
|
||||||
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
|
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,10 @@ using namespace std;
|
||||||
/* Data types */
|
/* Data types */
|
||||||
class vvp_scalar_t;
|
class vvp_scalar_t;
|
||||||
|
|
||||||
|
class vvp_vector2_t;
|
||||||
|
class vvp_vector4_t;
|
||||||
|
class vvp_vector8_t;
|
||||||
|
|
||||||
/* Basic netlist types. */
|
/* Basic netlist types. */
|
||||||
class vvp_net_t;
|
class vvp_net_t;
|
||||||
class vvp_net_fun_t;
|
class vvp_net_fun_t;
|
||||||
|
|
@ -607,9 +611,10 @@ class vvp_vector2_t {
|
||||||
vvp_vector2_t();
|
vvp_vector2_t();
|
||||||
vvp_vector2_t(const 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 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
|
// Make a vvp_vector2_t from a vvp_vector4_t. If there are X
|
||||||
// or Z bits, then the result becomes a NaN value.
|
// 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.
|
// Make from a native long and a specified width.
|
||||||
vvp_vector2_t(unsigned long val, unsigned wid);
|
vvp_vector2_t(unsigned long val, unsigned wid);
|
||||||
// Make with the width, and filled with 1 or 0 bits.
|
// 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 >>= (unsigned shift);
|
||||||
vvp_vector2_t&operator = (const vvp_vector2_t&);
|
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_NaN() const;
|
||||||
bool is_zero() const;
|
bool is_zero() const;
|
||||||
unsigned size() const;
|
unsigned size() const;
|
||||||
int value(unsigned idx) 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_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.
|
// Make the size just big enough to hold the first 1 bit.
|
||||||
void trim();
|
void trim();
|
||||||
// Trim off extra 1 bit since this is representing a negative value.
|
// Trim off extra 1 bit since this is representing a negative value.
|
||||||
|
|
@ -641,6 +654,7 @@ class vvp_vector2_t {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void copy_from_that_(const vvp_vector2_t&that);
|
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&);
|
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&);
|
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 some of the vector2_t methods. */
|
||||||
inline unsigned vvp_vector2_t::size() const
|
inline unsigned vvp_vector2_t::size() const
|
||||||
{
|
{
|
||||||
return wid_;
|
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
|
* This class represents a scalar value with strength. These are
|
||||||
* heavier then the simple vvp_bit4_t, but more information is
|
* 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,
|
explicit vvp_vector8_t(const vvp_vector4_t&that,
|
||||||
unsigned str0,
|
unsigned str0,
|
||||||
unsigned str1);
|
unsigned str1);
|
||||||
|
explicit vvp_vector8_t(const vvp_vector2_t&that,
|
||||||
|
unsigned str0,
|
||||||
|
unsigned str1);
|
||||||
|
|
||||||
~vvp_vector8_t();
|
~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
|
// the val through the force mask. The force value is the
|
||||||
// currently forced value, and the buf is a value that this
|
// currently forced value, and the buf is a value that this
|
||||||
// method will use to hold a filtered value, if needed. 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);
|
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
|
// This template method is similar to the above, but works for
|
||||||
// native types that are not so expensive to edit in place.
|
// 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,
|
static void __compile_var(char*label, char*name,
|
||||||
vvp_array_t array, unsigned long array_addr,
|
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;
|
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);
|
vvp_fun_signal4_aa*tmp = new vvp_fun_signal4_aa(wid);
|
||||||
net->fil = tmp;
|
net->fil = tmp;
|
||||||
net->fun = 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 {
|
} else {
|
||||||
net->fil = new vvp_wire_vec4(wid, BIT4_X);
|
net->fil = new vvp_wire_vec4(wid, BIT4_X);
|
||||||
net->fun = new vvp_fun_signal4_sa(wid);
|
net->fun = new vvp_fun_signal4_sa(wid);
|
||||||
|
|
@ -106,9 +110,21 @@ static void __compile_var(char*label, char*name,
|
||||||
vpiHandle obj = 0;
|
vpiHandle obj = 0;
|
||||||
if (! local_flag && !array) {
|
if (! local_flag && !array) {
|
||||||
/* Make the vpiHandle for the reg. */
|
/* Make the vpiHandle for the reg. */
|
||||||
obj = (signed_flag > 1) ?
|
switch (vpi_type_code) {
|
||||||
vpip_make_int(name, msb, lsb, net) :
|
case vpiLogicVar:
|
||||||
vpip_make_reg(name, msb, lsb, signed_flag!=0, net);
|
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);
|
compile_vpi_symbol(label, obj);
|
||||||
}
|
}
|
||||||
// If the signal has a name, then it goes into the current
|
// 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,
|
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);
|
__compile_var(label, name, 0, 0, msb, lsb, vpi_type_code, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vvp_net_t* create_constant_node(const char*val_str)
|
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,
|
struct __vpiScope*scope,
|
||||||
char*my_label, char*name,
|
char*my_label, char*name,
|
||||||
int msb, int lsb, unsigned array_addr,
|
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)
|
: base_net_resolv(ref_label, array, scope, my_label, name, array_addr, local_flag)
|
||||||
{ msb_ = msb;
|
{ msb_ = msb;
|
||||||
lsb_ = lsb;
|
lsb_ = lsb;
|
||||||
|
vpi_type_code_ = vpi_type_code;
|
||||||
signed_flag_ = signed_flag;
|
signed_flag_ = signed_flag;
|
||||||
net8_flag_ = net8_flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~__compile_net_resolv() { }
|
~__compile_net_resolv() { }
|
||||||
|
|
@ -224,7 +226,8 @@ class __compile_net_resolv : public base_net_resolv {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int msb_, lsb_;
|
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.
|
* 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,
|
struct __vpiScope*scope,
|
||||||
char*my_label, char*name,
|
char*my_label, char*name,
|
||||||
int msb, int lsb, unsigned array_addr,
|
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;
|
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||||
assert(node);
|
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);
|
vvp_wire_base*vsig = dynamic_cast<vvp_wire_base*>(node->fil);
|
||||||
|
|
||||||
if (vsig == 0) {
|
if (vsig == 0) {
|
||||||
vsig = net8_flag
|
switch (vpi_type_code) {
|
||||||
? dynamic_cast<vvp_wire_base*>(new vvp_wire_vec8(wid))
|
case vpiIntVar:
|
||||||
: dynamic_cast<vvp_wire_base*>(new vvp_wire_vec4(wid,BIT4_Z));
|
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;
|
node->fil = vsig;
|
||||||
}
|
}
|
||||||
|
|
||||||
vpiHandle obj = 0;
|
vpiHandle obj = 0;
|
||||||
if (! local_flag) {
|
if (! local_flag) {
|
||||||
/* Make the vpiHandle for the reg. */
|
/* 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 */
|
/* This attaches the label to the vpiHandle */
|
||||||
compile_vpi_symbol(my_label, obj);
|
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,
|
static void __compile_net(char*label,
|
||||||
char*name, char*array_label, unsigned long array_addr,
|
char*name, char*array_label, unsigned long array_addr,
|
||||||
int msb, int lsb,
|
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)
|
unsigned argc, struct symb_s*argv)
|
||||||
{
|
{
|
||||||
vvp_array_t array = array_label? array_find(array_label) : 0;
|
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,
|
= new __compile_net_resolv(argv[0].text,
|
||||||
array, scope, label, name,
|
array, scope, label, name,
|
||||||
msb, lsb, array_addr,
|
msb, lsb, array_addr,
|
||||||
signed_flag, net8_flag, local_flag);
|
vpi_type_code, signed_flag, local_flag);
|
||||||
resolv_submit(res);
|
resolv_submit(res);
|
||||||
free(argv);
|
free(argv);
|
||||||
return;
|
return;
|
||||||
|
|
@ -322,8 +333,8 @@ static void __compile_net(char*label,
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
struct __vpiScope*scope = vpip_peek_current_scope();
|
struct __vpiScope*scope = vpip_peek_current_scope();
|
||||||
__compile_net2(node, array, scope, label, name, msb, lsb, array_addr,
|
do_compile_net(node, array, scope, label, name, msb, lsb, array_addr,
|
||||||
signed_flag, net8_flag, local_flag);
|
vpi_type_code, signed_flag, local_flag);
|
||||||
|
|
||||||
free(argv[0].text);
|
free(argv[0].text);
|
||||||
free(argv);
|
free(argv);
|
||||||
|
|
@ -338,30 +349,28 @@ bool __compile_net_resolv::resolve(bool msg_flag)
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_net(char*label, char*name, int msb, int lsb,
|
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)
|
unsigned argc, struct symb_s*argv)
|
||||||
{
|
{
|
||||||
__compile_net(label, name, 0, 0,
|
__compile_net(label, name, 0, 0, msb, lsb,
|
||||||
msb, lsb, signed_flag, net8_flag, local_flag,
|
vpi_type_code, signed_flag, local_flag,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
void compile_netw(char*label, char*array_label, unsigned long array_addr,
|
||||||
int msb, int lsb,
|
int msb, int lsb, int vpi_type_code, bool signed_flag,
|
||||||
bool signed_flag, bool net8_flag,
|
unsigned argc, struct symb_s*argv)
|
||||||
unsigned argc, struct symb_s*argv)
|
|
||||||
{
|
{
|
||||||
__compile_net(label, 0, array_label, array_addr,
|
__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);
|
argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class __compile_real_net_resolv : public base_net_resolv {
|
class __compile_real_net_resolv : public base_net_resolv {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue