Merge branch 'work1'

This commit is contained in:
Stephen Williams 2010-10-21 19:31:49 -07:00
commit 3733c59e49
50 changed files with 1102 additions and 342 deletions

View File

@ -302,7 +302,7 @@ else
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
endif
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(libdir)/ivl$(suffix)/include/constants.vams $(libdir)/ivl$(suffix)/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/sv_vpi_user.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
@ -323,6 +323,9 @@ $(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
$(includedir)/_pli_types.h: _pli_types.h
$(INSTALL_DATA) $< "$(DESTDIR)$(includedir)/_pli_types.h"
$(includedir)/sv_vpi_user.h: $(srcdir)/sv_vpi_user.h
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"

View File

@ -37,7 +37,9 @@ enum PTaskFuncEnum {
PTF_INTEGER,
PTF_REAL,
PTF_REALTIME,
PTF_TIME
PTF_TIME,
PTF_ATOM2,
PTF_ATOM2_S
};
struct PTaskFuncArg {

View File

@ -151,6 +151,16 @@ extern bool gn_io_range_error_flag;
re-evaluated. */
extern bool gn_strict_ca_eval_flag;
/* If variables can be converted to uwires by a continuous assignment
(assuming no procedural assign, then return true. This will be true
for SystemVerilog */
static inline bool gn_var_can_be_uwire(void)
{
if (generation_flag == GN_VER2009)
return true;
return false;
}
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
sets of keywords. The compiler enables groups of keywords by setting
lexor_keyword_mask with the OR of the bits for the keywords to be

View File

@ -335,9 +335,17 @@ void NetArrayDq::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetCastInt::dump_node(ostream&o, unsigned ind) const
void NetCastInt2::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to int. (NetCastInt): " <<
o << setw(ind) << "" << "Cast to int2. (NetCastInt2): " <<
name() << " width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCastInt4::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Cast to int4. (NetCastInt4): " <<
name() << " width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@ -660,7 +668,8 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
if (rise_time())
o << " #(" <<*rise_time()
<<","<<*fall_time()
<< "," <<*decay_time() << ")" << endl;
<< "," <<*decay_time() << ")";
o << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}

View File

@ -414,6 +414,22 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
assert(sig);
/* If this is SystemVerilog and the variable is not yet
assigned by anything, then convert it to an unresolved
wire. */
if (gn_var_can_be_uwire()
&& (sig->type() == NetNet::REG)
&& (sig->peek_eref() == 0) ) {
sig->type(NetNet::UNRESOLVED_WIRE);
}
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->pin(0).is_linked()) {
cerr << get_fileline() << ": error: Unresolved net " << sig->name()
<< " cannot have multiple drivers." << endl;
des->errors += 1;
return 0;
}
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_fileline() << ": error: reg " << sig->name()

View File

@ -69,6 +69,15 @@ static bool get_const_argument(NetExpr*exp, verinum&res)
return true;
}
static bool get_const_argument(NetExpr*exp, long&res)
{
verinum tmp;
bool rc = get_const_argument(exp, tmp);
if (rc == false) return false;
res = tmp.as_long();
return true;
}
void Statement::elaborate_sig(Design*des, NetScope*scope) const
{
}
@ -472,18 +481,14 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
need_constant_expr = false;
long mnum = 0, lnum = 0;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) {
mnum = tmp->value().as_long();
} else {
if ( ! get_const_argument(me, mnum) ) {
cerr << me->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *me << "." << endl;
des->errors += 1;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*>(le)) {
lnum = tmp->value().as_long();
} else {
if ( ! get_const_argument(le, lnum) ) {
cerr << le->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *le << "." << endl;
@ -534,6 +539,48 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ret_sig->data_type(IVL_VT_REAL);
break;
case PTF_ATOM2:
case PTF_ATOM2_S:
ivl_assert(*this, return_type_.range != 0);
probe_expr_width(des, scope, (*return_type_.range)[0]);
probe_expr_width(des, scope, (*return_type_.range)[1]);
long use_wid;
{
need_constant_expr = true;
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1], -1);
assert(le);
need_constant_expr = false;
long mnum = 0, lnum = 0;
if ( ! get_const_argument(me, mnum) ) {
cerr << me->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *me << "." << endl;
des->errors += 1;
}
if ( ! get_const_argument(le, lnum) ) {
cerr << le->get_fileline() << ": error: "
"Unable to evaluate constant expression "
<< *le << "." << endl;
des->errors += 1;
}
use_wid = mnum - lnum + 1;
}
ret_sig = new NetNet(scope, fname, NetNet::REG, use_wid);
ret_sig->set_line(*this);
ret_sig->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
ret_sig->set_isint(true);
ret_sig->set_scalar(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_BOOL);
break;
default:
if (ports_) {
cerr << get_fileline() << ": internal error: I don't know "

View File

@ -129,13 +129,17 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
need_driver_flag = true;
/* Cast the right side when needed. */
if ((lval->data_type() == IVL_VT_REAL &&
rval->data_type() != IVL_VT_REAL)) {
if ((lval->data_type() == IVL_VT_REAL) &&
(rval->data_type() != IVL_VT_REAL)) {
rval = cast_to_real(des, scope, rval);
need_driver_flag = false;
} else if ((lval->data_type() != IVL_VT_REAL &&
rval->data_type() == IVL_VT_REAL)) {
rval = cast_to_int(des, scope, rval, lval->vector_width());
} else if ((lval->data_type() == IVL_VT_BOOL) &&
(rval->data_type() != IVL_VT_BOOL)) {
rval = cast_to_int2(des, scope, rval, lval->vector_width());
need_driver_flag = false;
} else if ((lval->data_type() != IVL_VT_REAL) &&
(rval->data_type() == IVL_VT_REAL)) {
rval = cast_to_int4(des, scope, rval, lval->vector_width());
need_driver_flag = false;
}
@ -1370,7 +1374,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// thing needs to go to each instance when arrayed.
if ((sig->data_type() == IVL_VT_REAL ) &&
!prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) {
sig = cast_to_int(des, scope, sig,
sig = cast_to_int4(des, scope, sig,
prts_vector_width/instance.size());
}
// If we have a bit/vector signal driving a real port
@ -1478,7 +1482,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
prts_vector_width = sig->vector_width();
for (unsigned pidx = 0; pidx < prts.size(); pidx += 1) {
prts[pidx]->port_type(NetNet::NOT_A_PORT);
prts[pidx] = cast_to_int(des, scope, prts[pidx],
prts[pidx] = cast_to_int4(des, scope, prts[pidx],
prts_vector_width /
instance.size());
prts[pidx]->port_type(NetNet::POUTPUT);
@ -2261,6 +2265,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
ivl_assert(*this, rv->expr_width() >= wid);
}
if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) {
if (debug_elaborate)
cerr << get_fileline() << ": debug: Cast expression to int2" << endl;
rv = cast_to_int2(rv);
}
NetAssign*cur = new NetAssign(lv, rv);
cur->set_line(*this);
@ -3558,6 +3568,14 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
rexp->set_width(lwid, true);
rexp = pad_to_width(rexp, lwid, *this);
if (ltype==IVL_VT_BOOL && rexp->expr_type()!=IVL_VT_BOOL) {
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Cast force rvalue to int2" << endl;
}
rexp = cast_to_int2(rexp);
}
dev = new NetForce(lval, rexp);
if (debug_elaborate) {

View File

@ -72,9 +72,14 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
return true;
}
bool NetCastInt::emit_node(struct target_t*tgt) const
bool NetCastInt2::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_int(this);
return tgt->lpm_cast_int2(this);
}
bool NetCastInt4::emit_node(struct target_t*tgt) const
{
return tgt->lpm_cast_int4(this);
}
bool NetCastReal::emit_node(struct target_t*tgt) const

View File

@ -737,8 +737,16 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
if (tmp[idx] == 0) flag = false;
/* Set the data type to the first one found. */
if (data_type == IVL_VT_NO_TYPE) {
data_type = tmp[idx]->data_type();
switch (data_type) {
case IVL_VT_NO_TYPE:
data_type = tmp[idx]->data_type();
break;
case IVL_VT_BOOL:
if (tmp[idx]->data_type()==IVL_VT_LOGIC)
data_type = IVL_VT_LOGIC;
break;
default:
break;
}
}
}
@ -985,7 +993,7 @@ NetNet* NetECast::synthesize(Design*des, NetScope*scope, NetExpr*root)
switch (op()) {
case 'i':
isig = cast_to_int(des, scope, isig, isig->vector_width());
isig = cast_to_int4(des, scope, isig, isig->vector_width());
break;
case 'r':
isig = cast_to_real(des, scope, isig);

View File

@ -272,7 +272,8 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_ABS = 32,
IVL_LPM_ADD = 0,
IVL_LPM_ARRAY = 30,
IVL_LPM_CAST_INT = 34,
IVL_LPM_CAST_INT = 34,
IVL_LPM_CAST_INT2 = 35,
IVL_LPM_CAST_REAL = 33,
IVL_LPM_CONCAT = 16,
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */

View File

@ -78,7 +78,7 @@ ostream& operator<< (ostream&o, NetNet::Type t)
case NetNet::WIRE:
o << "wire";
break;
case NetNet::UWIRE:
case NetNet::UNRESOLVED_WIRE:
o << "uwire";
}
return o;
@ -951,7 +951,14 @@ const NetScope* NetAnalogTop::scope() const
return scope_;
}
NetCastInt::NetCastInt(NetScope*scope__, perm_string n, unsigned width__)
NetCastInt2::NetCastInt2(NetScope*scope__, perm_string n, unsigned width__)
: NetNode(scope__, n, 2), width_(width__)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
}
NetCastInt4::NetCastInt4(NetScope*scope__, perm_string n, unsigned width__)
: NetNode(scope__, n, 2), width_(width__)
{
pin(0).set_dir(Link::OUTPUT);
@ -2359,11 +2366,13 @@ ivl_variable_type_t NetETernary::expr_type() const
ivl_assert(*this, false_val_);
ivl_variable_type_t tru = true_val_->expr_type();
ivl_variable_type_t fal = false_val_->expr_type();
ivl_variable_type_t sel = cond_->expr_type();
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
return IVL_VT_LOGIC;
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
if (sel == IVL_VT_LOGIC && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL) && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
return IVL_VT_LOGIC;
if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
return IVL_VT_REAL;
if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
@ -2455,6 +2464,9 @@ ivl_variable_type_t NetECast::expr_type() const
case 'r':
ret = IVL_VT_REAL;
break;
case '2':
ret = IVL_VT_BOOL;
break;
default:
assert(0);
}

View File

@ -553,7 +553,7 @@ class NetNet : public NetObj {
public:
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
UWIRE };
UNRESOLVED_WIRE };
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
@ -1016,10 +1016,24 @@ class NetArrayDq : public NetNode {
* Convert an IVL_VT_REAL input to a logical value with the
* given width. The input is pin(1) and the output is pin(0).
*/
class NetCastInt : public NetNode {
class NetCastInt4 : public NetNode {
public:
NetCastInt(NetScope*s, perm_string n, unsigned width);
NetCastInt4(NetScope*s, perm_string n, unsigned width);
unsigned width() const { return width_; }
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
unsigned width_;
};
class NetCastInt2 : public NetNode {
public:
NetCastInt2(NetScope*s, perm_string n, unsigned width);
unsigned width() const { return width_; }
@ -3763,6 +3777,7 @@ class NetETernary : public NetExpr {
* X -- Reduction NXOR (~^ or ^~)
* m -- abs(x) (i.e. "magnitude")
* i -- Cast from real to integer (vector)
* 2 -- Cast from real or logic (vector) to bool (vector)
* r -- Cast from integer (vector) to real
*/
class NetEUnary : public NetExpr {

View File

@ -116,7 +116,27 @@ NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
return tmp;
}
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
NetNet* cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid)
{
if (src->data_type() == IVL_VT_BOOL)
return src;
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
tmp->data_type(IVL_VT_BOOL);
tmp->set_line(*src);
tmp->local_flag(true);
NetCastInt2*cast = new NetCastInt2(scope, scope->local_symbol(), wid);
cast->set_line(*src);
des->add_node(cast);
connect(cast->pin(0), tmp->pin(0));
connect(cast->pin(1), src->pin(0));
return tmp;
}
NetNet* cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid)
{
if (src->data_type() != IVL_VT_REAL)
return src;
@ -126,7 +146,7 @@ NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
tmp->set_line(*src);
tmp->local_flag(true);
NetCastInt*cast = new NetCastInt(scope, scope->local_symbol(), wid);
NetCastInt4*cast = new NetCastInt4(scope, scope->local_symbol(), wid);
cast->set_line(*src);
des->add_node(cast);
@ -156,6 +176,14 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
return tmp;
}
NetExpr* cast_to_int2(NetExpr*expr)
{
NetECast*cast = new NetECast('2', expr);
cast->set_line(*expr);
cast->cast_signed(expr->has_sign());
return cast;
}
/*
* Add a signed constant to an existing expression. Generate a new
* NetEBAdd node that has the input expression and an expression made

View File

@ -74,9 +74,12 @@ extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w,
* Generate the nodes necessary to cast an expression (a net) to a
* real value.
*/
extern NetNet*cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid);
extern NetNet*cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid);
extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid);
extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
extern NetExpr*cast_to_int2(NetExpr*expr);
/*
* Take the input expression and return a variation that assures that
* the expression is 1-bit wide and logical. This reflects the needs

359
parse.y
View File

@ -106,6 +106,16 @@ static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string,
return tmp;
}
static svector<PExpr*>* make_range_from_width(uint64_t wid)
{
svector<PExpr*>*range = new svector<PExpr*>(2);
(*range)[0] = new PENumber(new verinum(wid-1, integer_width));
(*range)[1] = new PENumber(new verinum((uint64_t)0, integer_width));
return range;
}
static list<perm_string>* list_from_identifier(char*id)
{
list<perm_string>*tmp = new list<perm_string>;
@ -167,6 +177,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
bool flag;
char letter;
int int_val;
/* text items are C strings allocated by the lexor using
strdup. They can be put into lists with the texts type. */
@ -319,7 +330,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
%type <flag> from_exclude
%type <number> number
%type <flag> signed_opt udp_reg_opt edge_operator automatic_opt
%type <flag> unsigned_signed_opt signed_unsigned_opt
%type <flag> udp_reg_opt edge_operator automatic_opt
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
%type <letter> udp_input_sym udp_output_sym
%type <text> udp_input_list udp_sequ_entry udp_comb_entry
@ -393,6 +405,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
%type <specpath> specify_simple_path specify_simple_path_decl
%type <specpath> specify_edge_path specify_edge_path_decl
%type <int_val> atom2_type
%token K_TAND
%right '?' ':'
%left K_LOR
@ -494,7 +508,7 @@ attribute
block_item_decl
: attribute_list_opt K_reg
primitive_type_opt signed_opt range
primitive_type_opt unsigned_signed_opt range
register_variable_list ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
@ -507,7 +521,7 @@ block_item_decl
range. This is the rule for a scalar. */
| attribute_list_opt K_reg
primitive_type_opt signed_opt
primitive_type_opt unsigned_signed_opt
register_variable_list ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
@ -516,18 +530,24 @@ block_item_decl
if ($1) delete $1;
}
/* Integer declarations are simpler in that they do not have all the
trappings of a general variable declaration. All of that is
implicit in the "integer" of the declaration. */
/* Integer atom declarations are simpler in that they do not have
all the trappings of a general variable declaration. All of that
is implicit in the "integer" of the declaration. */
| attribute_list_opt K_integer register_variable_list ';'
{ pform_set_reg_integer($3);
if ($1) delete $1;
}
| attribute_list_opt K_integer signed_unsigned_opt register_variable_list ';'
{ pform_set_reg_integer($4);
if ($1) delete $1;
}
| attribute_list_opt K_time register_variable_list ';'
{ pform_set_reg_time($3);
}
| attribute_list_opt K_time register_variable_list ';'
{ pform_set_reg_time($3);
if ($1) delete $1;
}
| attribute_list_opt atom2_type signed_unsigned_opt register_variable_list ';'
{ pform_set_integer_2atom($2, $3, $4);
if ($1) delete $1;
}
/* real declarations are fairly simple as there is no range of
signed flag in the declaration. Create the real as a NetNet::REG
@ -1880,7 +1900,7 @@ list_of_port_declarations
port_declaration
: attribute_list_opt
K_input net_type_opt primitive_type_opt signed_opt range_opt IDENTIFIER
K_input net_type_opt primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($7);
ptmp = pform_module_port_reference(name, @2.text,
@ -1897,8 +1917,27 @@ port_declaration
delete[]$7;
$$ = ptmp;
}
| attribute_list_opt K_input atom2_type signed_unsigned_opt IDENTIFIER
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($5);
svector<PExpr*>*use_range = make_range_from_width($3);
ptmp = pform_module_port_reference(name, @2.text,
@2.first_line);
pform_module_define_port(@2, name, NetNet::PINPUT,
NetNet::UNRESOLVED_WIRE, IVL_VT_BOOL,
$4, use_range, $1);
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.port_net_type = NetNet::UNRESOLVED_WIRE;
port_declaration_context.var_type = IVL_VT_BOOL;
port_declaration_context.sign_flag = $4;
delete port_declaration_context.range;
port_declaration_context.range = use_range;
delete $1;
delete[]$5;
$$ = ptmp;
}
| attribute_list_opt
K_inout net_type_opt primitive_type_opt signed_opt range_opt IDENTIFIER
K_inout net_type_opt primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($7);
ptmp = pform_module_port_reference(name, @2.text,
@ -1916,7 +1955,7 @@ port_declaration
$$ = ptmp;
}
| attribute_list_opt
K_output net_type_opt primitive_type_opt signed_opt range_opt IDENTIFIER
K_output net_type_opt primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($7);
ptmp = pform_module_port_reference(name, @2.text,
@ -1934,7 +1973,7 @@ port_declaration
$$ = ptmp;
}
| attribute_list_opt
K_output var_type primitive_type_opt signed_opt range_opt IDENTIFIER
K_output var_type primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($7);
ptmp = pform_module_port_reference(name, @2.text,
@ -1952,7 +1991,7 @@ port_declaration
$$ = ptmp;
}
| attribute_list_opt
K_output var_type primitive_type_opt signed_opt range_opt IDENTIFIER '=' expression
K_output var_type primitive_type_opt unsigned_signed_opt range_opt IDENTIFIER '=' expression
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($7);
ptmp = pform_module_port_reference(name, @2.text,
@ -1972,6 +2011,25 @@ port_declaration
delete[]$7;
$$ = ptmp;
}
| attribute_list_opt K_output atom2_type signed_unsigned_opt IDENTIFIER
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($5);
svector<PExpr*>*use_range = make_range_from_width($3);
ptmp = pform_module_port_reference(name, @2.text,
@2.first_line);
pform_module_define_port(@2, name, NetNet::POUTPUT,
NetNet::IMPLICIT_REG, IVL_VT_BOOL,
$4, use_range, $1);
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.port_net_type = NetNet::IMPLICIT_REG;
port_declaration_context.var_type = IVL_VT_BOOL;
port_declaration_context.sign_flag = $4;
delete port_declaration_context.range;
port_declaration_context.range = use_range;
delete $1;
delete[]$5;
$$ = ptmp;
}
;
@ -1981,7 +2039,38 @@ net_type_opt
| { $$ = NetNet::IMPLICIT; }
;
signed_opt : K_signed { $$ = true; } | {$$ = false; } ;
/*
* The signed_opt rule will return "true" if K_signed is present,
* for "false" otherwise. This rule corresponds to the declaration
* defaults for reg/bit/logic.
*
* The signed_unsigned_opt rule with match K_signed or K_unsigned
* and return true or false as appropriate. The default is
* "true". This corresponds to the declaration defaults for
* byte/shortint/int/longint.
*/
unsigned_signed_opt
: K_signed { $$ = true; }
| K_unsigned { $$ = false; }
| { $$ = false; }
;
signed_unsigned_opt
: K_signed { $$ = true; }
| K_unsigned { $$ = false; }
| { $$ = true; }
;
/*
* In some places we can take any of the 4 2-value atom-type
* names. All the context needs to know if that type is its width.
*/
atom2_type
: K_byte { $$ = 8; }
| K_shortint { $$ = 16; }
| K_int { $$ = 32; }
| K_longint { $$ = 64; }
;
/* An lpvalue is the expression that can go on the left side of a
procedural assignment. This rule handles only procedural
@ -2118,7 +2207,7 @@ module_item
resort to the default type LOGIC. */
: attribute_list_opt net_type
primitive_type_opt signed_opt range_opt
primitive_type_opt unsigned_signed_opt range_opt
delay3_opt
net_variable_list ';'
@ -2139,7 +2228,7 @@ module_item
declarations. */
| attribute_list_opt net_type
primitive_type_opt signed_opt range_opt
primitive_type_opt unsigned_signed_opt range_opt
delay3_opt net_decl_assigns ';'
{ ivl_variable_type_t dtype = $3;
@ -2158,7 +2247,7 @@ module_item
gives strength to the assignment drivers. */
| attribute_list_opt net_type
primitive_type_opt signed_opt
primitive_type_opt unsigned_signed_opt
drive_strength net_decl_assigns ';'
{ ivl_variable_type_t dtype = $3;
@ -2178,7 +2267,7 @@ module_item
delete $4;
}
| port_type signed_opt range_opt delay3_opt list_of_identifiers ';'
| port_type unsigned_signed_opt range_opt delay3_opt list_of_identifiers ';'
{ pform_set_port_type(@1, $5, $3, $2, $1);
}
@ -2186,12 +2275,12 @@ module_item
input wire signed [h:l] <list>;
This creates the wire and sets the port type all at once. */
| port_type net_type signed_opt range_opt list_of_identifiers ';'
| port_type net_type unsigned_signed_opt range_opt list_of_identifiers ';'
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0,
SR_BOTH);
}
| K_output var_type signed_opt range_opt list_of_port_identifiers ';'
| K_output var_type unsigned_signed_opt range_opt list_of_port_identifiers ';'
{ list<pair<perm_string,PExpr*> >::const_iterator pp;
list<perm_string>*tmp = new list<perm_string>;
for (pp = $5->begin(); pp != $5->end(); pp++) {
@ -2211,19 +2300,19 @@ module_item
because the port declaration implies an external driver, which
cannot be attached to a reg. These rules catch that error early. */
| K_input var_type signed_opt range_opt list_of_identifiers ';'
| K_input var_type unsigned_signed_opt range_opt list_of_identifiers ';'
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINPUT,
IVL_VT_NO_TYPE, 0);
yyerror(@2, "error: reg variables cannot be inputs.");
}
| K_inout var_type signed_opt range_opt list_of_identifiers ';'
| K_inout var_type unsigned_signed_opt range_opt list_of_identifiers ';'
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::PINOUT,
IVL_VT_NO_TYPE, 0);
yyerror(@2, "error: reg variables cannot be inouts.");
}
| port_type signed_opt range_opt delay3_opt error ';'
| port_type unsigned_signed_opt range_opt delay3_opt error ';'
{ yyerror(@1, "error: Invalid variable list"
" in port declaration.");
if ($3) delete $3;
@ -2639,10 +2728,11 @@ net_decl_assigns
;
primitive_type
: K_logic { $$ = IVL_VT_LOGIC; }
| K_bool { $$ = IVL_VT_BOOL; }
| K_real { $$ = IVL_VT_REAL; }
;
: K_logic { $$ = IVL_VT_LOGIC; }
| K_bool { $$ = IVL_VT_BOOL; /* Icarus Verilog xtypes */}
| K_bit { $$ = IVL_VT_BOOL; /* IEEE1800 / IEEE1364-2009 */}
| K_real { $$ = IVL_VT_REAL; }
;
primitive_type_opt : primitive_type { $$ = $1; } | { $$ = IVL_VT_NO_TYPE; } ;
@ -2657,12 +2747,12 @@ net_type
| K_supply1 { $$ = NetNet::SUPPLY1; }
| K_wor { $$ = NetNet::WOR; }
| K_trior { $$ = NetNet::TRIOR; }
| K_wone { $$ = NetNet::UWIRE;
| K_wone { $$ = NetNet::UNRESOLVED_WIRE;
cerr << @1.text << ":" << @1.first_line << ": warning: "
"'wone' is deprecated, please use 'uwire' "
"instead." << endl;
}
| K_uwire { $$ = NetNet::UWIRE; }
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
;
var_type
@ -3195,14 +3285,18 @@ dimensions
/* This is used to express the return type of a function. */
function_range_or_type_opt
: range { $$.range = $1; $$.type = PTF_REG; }
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
| K_real { $$.range = 0; $$.type = PTF_REAL; }
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
| K_time { $$.range = 0; $$.type = PTF_TIME; }
| { $$.range = 0; $$.type = PTF_REG; }
;
: range { $$.range = $1; $$.type = PTF_REG; }
| K_signed range { $$.range = $2; $$.type = PTF_REG_S; }
| K_unsigned range { $$.range = $2; $$.type = PTF_REG; }
| K_integer { $$.range = 0; $$.type = PTF_INTEGER; }
| K_real { $$.range = 0; $$.type = PTF_REAL; }
| K_realtime { $$.range = 0; $$.type = PTF_REALTIME; }
| K_time { $$.range = 0; $$.type = PTF_TIME; }
| atom2_type { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
| atom2_type K_signed { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2_S; }
| atom2_type K_unsigned { $$.range = make_range_from_width($1); $$.type = PTF_ATOM2; }
| { $$.range = 0; $$.type = PTF_REG; }
;
/* The register_variable rule is matched only when I am parsing
variables in a "reg" definition. I therefore know that I am
@ -4039,30 +4133,27 @@ reg_opt
task_port_item
: K_input reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
: K_input reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
IVL_VT_NO_TYPE, $3,
$4, $5,
@1.text, @1.first_line);
$$ = tmp;
}
| K_output reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
$$ = tmp;
}
| K_output reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $3,
$4, $5,
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout reg_opt signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
$$ = tmp;
}
| K_inout reg_opt unsigned_signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $3,
$4, $5,
@1.text, @1.first_line);
$$ = tmp;
}
$$ = tmp;
}
/* When the port is an integer, infer a signed vector of the integer
shape. Generate a range ([31:0]) to make it work. */
@ -4206,7 +4297,7 @@ task_item_list_opt
task_port_decl
: K_input reg_opt signed_opt range_opt IDENTIFIER
: K_input reg_opt unsigned_signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
@ -4220,7 +4311,7 @@ task_port_decl
$$ = tmp;
}
| K_output reg_opt signed_opt range_opt IDENTIFIER
| K_output reg_opt unsigned_signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
@ -4233,7 +4324,7 @@ task_port_decl
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout reg_opt signed_opt range_opt IDENTIFIER
| K_inout reg_opt unsigned_signed_opt range_opt IDENTIFIER
{ port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = $3;
@ -4315,66 +4406,48 @@ task_port_decl
/* Ports can be time with a width of [63:0] (unsigned). */
| K_input K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_time IDENTIFIER
{ svector<PExpr*>*range_stub = new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum((uint64_t)63, integer_width));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, integer_width));
(*range_stub)[1] = re;
port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_input K_time IDENTIFIER
{ svector<PExpr*>*range_stub = make_range_from_width(64);
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_time IDENTIFIER
{ svector<PExpr*>*range_stub = make_range_from_width(64);
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_time IDENTIFIER
{ svector<PExpr*>*range_stub = make_range_from_width(64);
port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_LOGIC;
port_declaration_context.sign_flag = false;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, false,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be real or realtime. */
@ -4417,7 +4490,51 @@ task_port_decl
@1.text, @1.first_line);
$$ = tmp;
}
;
/* Ports can be 2-value atom types. */
| K_input atom2_type signed_unsigned_opt IDENTIFIER
{ svector<PExpr*>*range_stub = make_range_from_width($2);
port_declaration_context.port_type = NetNet::PINPUT;
port_declaration_context.var_type = IVL_VT_BOOL;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINPUT,
IVL_VT_BOOL, $3,
range_stub, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output atom2_type signed_unsigned_opt IDENTIFIER
{ svector<PExpr*>*range_stub = make_range_from_width($2);
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.var_type = IVL_VT_BOOL;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_BOOL, $3,
range_stub, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout atom2_type signed_unsigned_opt IDENTIFIER
{ svector<PExpr*>*range_stub = make_range_from_width($2);
port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.var_type = IVL_VT_BOOL;
port_declaration_context.sign_flag = $3;
delete port_declaration_context.range;
port_declaration_context.range = copy_range(range_stub);
svector<PWire*>*tmp = pform_make_task_ports(NetNet::PINOUT,
IVL_VT_BOOL, $3,
range_stub, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
;
task_port_decl_list
: task_port_decl_list ',' task_port_decl

View File

@ -2431,6 +2431,38 @@ void pform_set_reg_time(list<perm_string>*names)
delete names;
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name)
{
PWire*cur = pform_get_wire_in_scope(name);
if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_BOOL);
pform_put_wire_in_scope(name, cur);
} else {
bool rc = cur->set_wire_type(NetNet::REG);
assert(rc);
rc = cur->set_data_type(IVL_VT_BOOL);
assert(rc);
}
assert(cur);
cur->set_signed(signed_flag);
cur->set_range(new PENumber(new verinum(width-1, integer_width)),
new PENumber(new verinum((uint64_t)0, integer_width)),
SR_NET, false);
}
void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end()
; cur ++ ) {
perm_string txt = *cur;
pform_set_integer_2atom(width, signed_flag, txt);
}
delete names;
}
svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
{
svector<PWire*>*out = new svector<PWire*>(names->size());

View File

@ -275,6 +275,8 @@ extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names);
extern void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names);
/* pform_set_attrib and pform_set_type_attrib exist to support the
$attribute syntax, which can only set string values to
attributes. The functions keep the value strings that are

View File

@ -787,6 +787,12 @@ void PFunction::dump(ostream&out, unsigned ind) const
case PTF_TIME:
out << "time ";
break;
case PTF_ATOM2:
out << "int unsigned ";
break;
case PTF_ATOM2_S:
cout << "int signed ";
break;
}
if (return_type_.range) {

View File

@ -6,7 +6,7 @@
#
# NOTE: DO NOT INSTALL THIS FILE!
#
generation:2005
generation:2009
generation:specify
generation:xtypes
generation:verilog-ams

54
sv_vpi_user.h Normal file
View File

@ -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

View File

@ -964,6 +964,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
switch (net->type) {
case IVL_LPM_ABS:
case IVL_LPM_CAST_INT:
case IVL_LPM_CAST_INT2:
case IVL_LPM_CAST_REAL:
assert(idx == 0);
return net->u_.arith.a;
@ -1108,6 +1109,7 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net)
case IVL_LPM_ABS:
case IVL_LPM_ADD:
case IVL_LPM_CAST_INT:
case IVL_LPM_CAST_INT2:
case IVL_LPM_CAST_REAL:
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
@ -1259,6 +1261,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_MULT:
case IVL_LPM_POW:
case IVL_LPM_SUB:
case IVL_LPM_CAST_INT2:
return net->u_.arith.signed_flag;
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:

View File

@ -1488,16 +1488,17 @@ void dll_target::lpm_clshift(const NetCLShift*net)
scope_add_lpm(obj->scope, obj);
}
bool dll_target::lpm_cast_int(const NetCastInt*net)
bool dll_target::lpm_arith1_(ivl_lpm_type_t lpm_type, unsigned width, bool signed_flag, const NetNode*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_CAST_INT;
obj->name = net->name(); // NetCastInt names are permallocated
obj->type = lpm_type;
obj->name = net->name(); // NetCastInt2 names are permallocated
assert(net->scope());
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->width = net->width();
obj->width = width;
obj->u_.arith.signed_flag = signed_flag? 1 : 0;
const Nexus*nex;
@ -1520,37 +1521,19 @@ bool dll_target::lpm_cast_int(const NetCastInt*net)
return true;
}
bool dll_target::lpm_cast_int2(const NetCastInt2*net)
{
return lpm_arith1_(IVL_LPM_CAST_INT2, net->width(), true, net);
}
bool dll_target::lpm_cast_int4(const NetCastInt4*net)
{
return lpm_arith1_(IVL_LPM_CAST_INT, net->width(), true, net);
}
bool dll_target::lpm_cast_real(const NetCastReal*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_CAST_REAL;
obj->name = net->name(); // NetCastReal names are permallocated
assert(net->scope());
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->width = 0;
obj->u_.arith.signed_flag = net->signed_flag()? 1 : 0;
const Nexus*nex;
nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.arith.q = nex->t_cookie();
nex = net->pin(1).nexus();
assert(nex->t_cookie());
obj->u_.arith.a = nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
make_lpm_delays_(obj, net);
scope_add_lpm(obj->scope, obj);
return true;
return lpm_arith1_(IVL_LPM_CAST_REAL, 0, net->signed_flag(), net);
}
/*
@ -2389,7 +2372,7 @@ void dll_target::signal(const NetNet*net)
/* We will convert this to a TRI after we check that there
is only one driver. */
case NetNet::UWIRE:
case NetNet::UNRESOLVED_WIRE:
obj->type_ = IVL_SIT_UWIRE;
break;

View File

@ -67,7 +67,8 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_abs(const NetAbs*);
void lpm_add_sub(const NetAddSub*);
bool lpm_array_dq(const NetArrayDq*);
bool lpm_cast_int(const NetCastInt*);
bool lpm_cast_int2(const NetCastInt2*);
bool lpm_cast_int4(const NetCastInt4*);
bool lpm_cast_real(const NetCastReal*);
void lpm_clshift(const NetCLShift*);
void lpm_compare(const NetCompare*);
@ -175,6 +176,8 @@ struct dll_target : public target_t, public expr_scan_t {
ivl_event_t make_lpm_trigger(const NetEvWait*ev);
bool lpm_arith1_(ivl_lpm_type_t lpm_type, unsigned wid, bool signed_flag, const NetNode*net);
static ivl_expr_t expr_from_value_(const verinum&that);
};

View File

@ -114,10 +114,17 @@ bool target_t::lpm_array_dq(const NetArrayDq*)
return false;
}
bool target_t::lpm_cast_int(const NetCastInt*)
bool target_t::lpm_cast_int2(const NetCastInt2*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetCastInt." << endl;
"Unhandled NetCastInt2." << endl;
return false;
}
bool target_t::lpm_cast_int4(const NetCastInt4*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetCastInt4." << endl;
return false;
}

View File

@ -75,7 +75,8 @@ struct target_t {
virtual void lpm_add_sub(const NetAddSub*);
virtual bool lpm_array_dq(const NetArrayDq*);
virtual void lpm_clshift(const NetCLShift*);
virtual bool lpm_cast_int(const NetCastInt*);
virtual bool lpm_cast_int2(const NetCastInt2*);
virtual bool lpm_cast_int4(const NetCastInt4*);
virtual bool lpm_cast_real(const NetCastReal*);
virtual void lpm_compare(const NetCompare*);
virtual void lpm_divide(const NetDivide*);

View File

@ -468,6 +468,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_ABS:
case IVL_LPM_ADD:
case IVL_LPM_ARRAY:
case IVL_LPM_CAST_INT2:
case IVL_LPM_CAST_INT:
case IVL_LPM_CAST_REAL:
case IVL_LPM_CONCAT:

View File

@ -55,6 +55,12 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
clr_word(res);
}
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
{
/* For now, treat bit2 variables as bit4 variables. */
function_argument_logic(port, expr);
}
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
@ -65,6 +71,9 @@ static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
case IVL_VT_REAL:
function_argument_real(port, expr);
break;
case IVL_VT_BOOL:
function_argument_bool(port, expr);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
ivl_signal_basename(port), dtype);

View File

@ -47,10 +47,14 @@ static int eval_bool64_logic(ivl_expr_t expr)
{
int res;
struct vector_info tmp;
const char*s_flag = "";
tmp = draw_eval_expr(expr, STUFF_OK_XZ);
res = allocate_word();
fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, tmp.base, tmp.wid);
if (ivl_expr_signed(expr))
s_flag = "/s";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", s_flag, res, tmp.base, tmp.wid);
clr_vector(tmp);
return res;

View File

@ -3126,6 +3126,21 @@ static struct vector_info draw_unary_expr(ivl_expr_t expr, unsigned wid)
local_count += 1;
break;
case '2': /* Cast logic to bool */
assert(ivl_expr_value(sub) == IVL_VT_LOGIC);
res = draw_eval_expr_wid(sub, wid, 0);
/* Handle special case that value is 0 or 1. */
if (res.base == 0 || res.base == 1)
break;
if (res.base == 2 || res.base == 2) {
res.base = 0;
break;
}
fprintf(vvp_out, " %%cast2 %d, %d, %u;\n", res.base, res.base, res.wid);
break;
case 'i': /* Cast a real value to an integer. */
assert(ivl_expr_value(sub) == IVL_VT_REAL);
word = draw_eval_real(sub);

View File

@ -427,6 +427,12 @@ static void draw_reg_in_scope(ivl_signal_t sig)
const char*local_flag = ivl_signal_local(sig)? "*" : "";
switch (ivl_signal_data_type(sig)) {
case IVL_VT_BOOL:
if (ivl_signal_signed(sig))
datatype_flag = "/2s";
else
datatype_flag = "/2u";
break;
case IVL_VT_REAL:
datatype_flag = "/real";
break;
@ -470,6 +476,12 @@ static void draw_net_in_scope(ivl_signal_t sig)
unsigned iword;
switch (ivl_signal_data_type(sig)) {
case IVL_VT_BOOL:
if (ivl_signal_signed(sig))
datatype_flag = "/2s";
else
datatype_flag = "/2u";
break;
case IVL_VT_REAL:
datatype_flag = "/real";
break;
@ -1209,6 +1221,19 @@ static void draw_lpm_abs(ivl_lpm_t net)
net, dly, src_table[0]);
}
static void draw_lpm_cast_int2(ivl_lpm_t net)
{
const char*src_table[1];
const char*dly;
draw_lpm_data_inputs(net, 0, 1, src_table);
dly = draw_lpm_output_delay(net, IVL_VT_BOOL);
fprintf(vvp_out, "L_%p%s .cast/2 %u, %s;\n",
net, dly, ivl_lpm_width(net), src_table[0]);
}
static void draw_lpm_cast_int(ivl_lpm_t net)
{
const char*src_table[1];
@ -1829,6 +1854,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_cast_int(net);
return;
case IVL_LPM_CAST_INT2:
draw_lpm_cast_int2(net);
return;
case IVL_LPM_CAST_REAL:
draw_lpm_cast_real(net);
return;

View File

@ -1048,6 +1048,10 @@ static int sys_check_args(vpiHandle callh, vpiHandle argv, const PLI_BYTE8*name,
case vpiNet:
case vpiReg:
case vpiIntegerVar:
case vpiByteVar:
case vpiShortIntVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiTimeVar:
case vpiRealVar:
case vpiSysFuncCall:

View File

@ -20,7 +20,7 @@
*/
#include "vpi_config.h"
#include "vpi_user.h"
#include "sv_vpi_user.h"
/*
* Context structure for PRNG in mt19937int.c

View File

@ -278,8 +278,10 @@ A variable is a bit vector that can be written by behavioral code (so
has no structural input) and propagates its output to a functor. The
general syntax of a variable is:
<label> .var "name", <msb>, <lsb>; Unsigned logic variable
<label> .var/s "name", <msb>, <lsb>; Signed logic variable
<label> .var "name", <msb> <lsb>; Unsigned logic variable
<label> .var/s "name", <msb> <lsb>; Signed logic variable
<label> .var/2u "name", <msb> <lsb>; Unsigned bool/bit variable
<label> .var/2s "name", <msb> <lsb>; Signed bool/bit variable
<label> .var/real "name", <msb>, <lsb>; real varibale
<label> .var/i "name", <msb>, <lsb>; vpiIntegerVar variable
@ -356,6 +358,7 @@ net or from a bit based net to a real valued net. These statements
are used to perform that operation:
<label> .cast/int <width>, <symbol>;
<label> .cast/2 <width>, <symbol>;
<label> .cast/real <symbol>;
<label> .cast/real.s <symbol>;

View File

@ -121,6 +121,28 @@ void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
ptr.ptr()->send_real(val, 0);
}
vvp_arith_cast_vec2::vvp_arith_cast_vec2(unsigned wid)
: wid_(wid)
{
}
vvp_arith_cast_vec2::~vvp_arith_cast_vec2()
{
}
void vvp_arith_cast_vec2::recv_real(vvp_net_ptr_t ptr, double bit,
vvp_context_t)
{
ptr.ptr()->send_vec4(vvp_vector4_t(wid_, bit), 0);
}
void vvp_arith_cast_vec2::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
vvp_vector2_t tmp = bit;
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,tmp.size()), 0);
}
// Division
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)

View File

@ -86,6 +86,20 @@ class vvp_arith_cast_real : public vvp_net_fun_t {
bool signed_;
};
class vvp_arith_cast_vec2 : public vvp_net_fun_t {
public:
explicit vvp_arith_cast_vec2(unsigned wid);
~vvp_arith_cast_vec2();
void recv_real(vvp_net_ptr_t ptr, double bit,
vvp_context_t);
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t);
private:
unsigned wid_;
};
class vvp_arith_div : public vvp_arith_ {
public:

View File

@ -52,9 +52,6 @@ extern void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle word);
extern void vpip_array_change(struct __vpiCallback*cb, vpiHandle word);
/* Compile hooks */
extern void compile_variablew(char*label, vvp_array_t array,
unsigned long array_addr,
int msb, int lsb, char signed_flag);
extern void compile_varw_real(char*label, vvp_array_t array,
unsigned long array_addr,
int msb, int lsb);

View File

@ -64,6 +64,7 @@ extern bool of_CASSIGN_LINK(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_V(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_WR(vthread_t thr, vvp_code_t code);
extern bool of_CASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_CAST2(vthread_t thr, vvp_code_t code);
extern bool of_CMPIS(vthread_t thr, vvp_code_t code);
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
extern bool of_CMPS(vthread_t thr, vvp_code_t code);

View File

@ -108,6 +108,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cassign/v",of_CASSIGN_V,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cassign/wr",of_CASSIGN_WR,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
{ "%cassign/x0",of_CASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%cast2", of_CAST2, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/s", of_CMPS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmp/wr", of_CMPWR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
@ -286,6 +287,10 @@ vvp_net_t* vvp_net_lookup(const char*label)
switch (vpi->vpi_type->type_code) {
case vpiNet:
case vpiReg:
case vpiByteVar:
case vpiShortIntVar:
case vpiIntVar:
case vpiLongIntVar:
case vpiIntegerVar: {
__vpiSignal*sig = (__vpiSignal*)vpi;
return sig->node;
@ -908,6 +913,22 @@ void compile_arith_cast_int(char*label, long width,
free(argv);
}
void compile_arith_cast_vec2(char*label, long width,
unsigned argc, struct symb_s*argv)
{
vvp_arith_cast_vec2*arith = new vvp_arith_cast_vec2((unsigned) width);
vvp_net_t* ptr = new vvp_net_t;
ptr->fun = arith;
define_functor_symbol(label, ptr);
free(label);
assert(argc == 1);
inputs_connect(ptr, argc, argv);
free(argv);
}
void compile_arith_cast_real(char*label, bool signed_flag,
unsigned argc, struct symb_s*argv)
{

View File

@ -23,7 +23,7 @@
# include <fstream>
# include <vector>
# include "parse_misc.h"
# include "vpi_user.h"
# include "sv_vpi_user.h"
# include "vvp_net.h"
using namespace std;
@ -158,6 +158,8 @@ extern void compile_arith_cast_int(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_arith_cast_real(char*label, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_arith_cast_vec2(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_arith_div(char*label, long width, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_arith_mod(char*label, long width, bool signed_flag,
@ -433,26 +435,41 @@ extern void compile_thread(char*start_sym, char*flag);
/*
* This function is called to create a var vector with the given name.
*
* The vpi_type_code argument of compile_variable() is one of the vpi
* object codes that identify the type: vpiReg, vpiIntegerVar,
* vpiIntVar, etc.
*/
extern void compile_variable(char*label, char*name,
int msb, int lsb, char signed_flag,
bool local_flag);
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag);
extern void compile_var_real(char*label, char*name,
int msb, int lsb);
extern void compile_net(char*label, char*name,
int msb, int lsb, bool signed_flag,
bool net8_flag, bool local_flag,
/*
* The compile_net functio is called to create a .net vector with a
* given name.
*
* The vpi_type_code argument of compile_net() is one of the vpi
* object codes for the equivelent variable types. The supported codes
* are:
* vpiLogic -- 4-value logic
* vpiIntVar -- 2-value logic
* -vpiLogic -- 8-value (i.e. strength aware) logic
*/
extern void compile_net(char*label, char*name, int msb, int lsb,
int vpi_type_code, bool signed_flag, bool local_flag,
unsigned argc, struct symb_s*argv);
extern void compile_net_real(char*label, char*name,
int msb, int lsb, bool local_flag,
unsigned argc, struct symb_s*argv);
extern void compile_netw(char*label, char*array_symbol,
unsigned long array_addr,
int msb, int lsb, bool signed_flag,
bool net8_flag,
extern void compile_netw(char*label, char*array_label, unsigned long array_addr,
int msb, int lsb, int vpi_type_code, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_netw_real(char*label, char*array_symbol,
unsigned long array_addr,
int msb, int lsb,

View File

@ -123,6 +123,7 @@ static char* strdupnew(char const *str)
".array/real" { return K_ARRAY_R; }
".array/s" { return K_ARRAY_S; }
".array/port" { return K_ARRAY_PORT; }
".cast/2" { return K_CAST_2; }
".cast/int" { return K_CAST_INT; }
".cast/real" { return K_CAST_REAL; }
".cast/real.s" { return K_CAST_REAL_S; }
@ -148,8 +149,10 @@ static char* strdupnew(char const *str)
".functor" { return K_FUNCTOR; }
".import" { return K_IMPORT; }
".island" { return K_ISLAND; }
".modpath" { return K_MODPATH; }
".modpath" { return K_MODPATH; }
".net" { return K_NET; }
".net/2s" { return K_NET_2S; }
".net/2u" { return K_NET_2U; }
".net8" { return K_NET8; }
".net8/s" { return K_NET8_S; }
".net/real" { return K_NET_R; }
@ -188,6 +191,8 @@ static char* strdupnew(char const *str)
".var/real" { return K_VAR_R; }
".var/s" { return K_VAR_S; }
".var/i" { return K_VAR_I; /* integer */ }
".var/2s" { return K_VAR_2S; /* byte/shortint/int/longint signed */ }
".var/2u" { return K_VAR_2U; /* byte/shortint/int/longint unsigned */ }
".udp" { return K_UDP; }
".udp/c"(omb)? { return K_UDP_C; }
".udp/s"(equ)? { return K_UDP_S; }

View File

@ -24,6 +24,7 @@
# include "schedule.h"
# include "delay.h"
# include "statistics.h"
# include <iostream>
# include <cstring>
# include <cassert>
# include <cstdlib>

View File

@ -217,6 +217,12 @@ cassign port (port-1) of the signal functor instead of the normal
assign port (port-0), so the signal responds differently. See
"VARIABLE STATEMENTS" and "NET STATEMENTS" in the README.txt file.
* %cast2 <dst>, <src>, <wid>
Convert the source vector, of type logic, to a bool vector by
changing all the X and Z bits to 0. The source and destinations may
overlap.
* %cmp/u <bit-l>, <bit-r>, <wid>
* %cmp/s <bit-l>, <bit-r>, <wid>

View File

@ -72,20 +72,21 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
%token K_CONCAT K_DEBUG K_DELAY K_DFF
%token K_EVENT K_EVENT_OR K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND
%token K_MODPATH K_NET K_NET_S K_NET_R
%token K_NET8 K_NET8_S
%token K_MODPATH
%token K_NET K_NET_S K_NET_R K_NET_2S K_NET_2U K_NET8 K_NET8_S
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
%token K_PART_V K_PART_V_S K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
%token K_UFUNC K_UFUNC_E K_UDP K_UDP_C K_UDP_S
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_call_w K_vpi_call_i
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_VAR_2S K_VAR_2U
%token K_vpi_call K_vpi_call_w K_vpi_call_i
%token K_vpi_func K_vpi_func_r
%token K_disable K_fork
%token K_ivl_version K_ivl_delay_selection
@ -271,20 +272,25 @@ statement
compile_arith_abs($1, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_INT T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_cast_int($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_INT T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_cast_int($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_REAL symbols ';'
{ struct symbv_s obj = $3;
compile_arith_cast_real($1, false, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_REAL symbols ';'
{ struct symbv_s obj = $3;
compile_arith_cast_real($1, false, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_REAL_S symbols ';'
{ struct symbv_s obj = $3;
compile_arith_cast_real($1, true, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_REAL_S symbols ';'
{ struct symbv_s obj = $3;
compile_arith_cast_real($1, true, obj.cnt, obj.vect);
}
| T_LABEL K_CAST_2 T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_arith_cast_vec2($1, $3, obj.cnt, obj.vect);
}
/* Arithmetic statements generate functor arrays of a given width
that take like size input vectors. */
@ -651,13 +657,19 @@ statement
the variable in the netlist. */
| T_LABEL K_VAR local_flag T_STRING ',' signed_t_number signed_t_number ';'
{ compile_variable($1, $4, $6, $7, 0 /* unsigned */, $3); }
{ compile_variable($1, $4, $6, $7, vpiLogicVar, false, $3); }
| T_LABEL K_VAR_S local_flag T_STRING ',' signed_t_number signed_t_number ';'
{ compile_variable($1, $4, $6, $7, 1 /* signed */, $3); }
{ compile_variable($1, $4, $6, $7, vpiLogicVar, true, $3); }
| T_LABEL K_VAR_I local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
{ compile_variable($1, $4, $6, $7, 2 /* integer */, $3); }
{ compile_variable($1, $4, $6, $7, vpiIntegerVar, true, $3); }
| T_LABEL K_VAR_2S local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
{ compile_variable($1, $4, $6, $7, vpiIntVar, true, $3); }
| T_LABEL K_VAR_2U local_flag T_STRING ',' T_NUMBER T_NUMBER ';'
{ compile_variable($1, $4, $6, $7, vpiIntVar, false, $3); }
| T_LABEL K_VAR_R T_STRING ',' signed_t_number signed_t_number ';'
{ compile_var_real($1, $3, $5, $6); }
@ -667,19 +679,27 @@ statement
| T_LABEL K_NET local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
{ compile_net($1, $4, $6, $7, false, false, $3, $9.cnt, $9.vect); }
{ compile_net($1, $4, $6, $7, vpiLogicVar, false, $3, $9.cnt, $9.vect); }
| T_LABEL K_NET_S local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
{ compile_net($1, $4, $6, $7, true, false, $3, $9.cnt, $9.vect); }
{ compile_net($1, $4, $6, $7, vpiLogicVar, true, $3, $9.cnt, $9.vect); }
| T_LABEL K_NET_2U local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
{ compile_net($1, $4, $6, $7, vpiIntVar, false, $3, $9.cnt, $9.vect); }
| T_LABEL K_NET_2S local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
{ compile_net($1, $4, $6, $7, vpiIntVar, true, $3, $9.cnt, $9.vect); }
| T_LABEL K_NET8 local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
{ compile_net($1, $4, $6, $7, false, true, $3, $9.cnt, $9.vect); }
{ compile_net($1, $4, $6, $7, -vpiLogicVar, false, $3, $9.cnt, $9.vect); }
| T_LABEL K_NET8_S local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
{ compile_net($1, $4, $6, $7, true, true, $3, $9.cnt, $9.vect); }
{ compile_net($1, $4, $6, $7, -vpiLogicVar, true, $3, $9.cnt, $9.vect); }
| T_LABEL K_NET_R local_flag T_STRING ',' signed_t_number signed_t_number
',' symbols_net ';'
@ -687,30 +707,25 @@ statement
/* Arrayed versions of net directives. */
| T_LABEL K_NET T_SYMBOL T_NUMBER ','
signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, false, false, $9.cnt, $9.vect); }
| T_LABEL K_NET T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, false, $9.cnt, $9.vect); }
| T_LABEL K_NET_S T_SYMBOL T_NUMBER ','
signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, true, false, $9.cnt, $9.vect); }
| T_LABEL K_NET_S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, true, $9.cnt, $9.vect); }
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ','
signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, false, true, $9.cnt, $9.vect); }
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, false, $9.cnt, $9.vect); }
| T_LABEL K_NET8_S T_SYMBOL T_NUMBER ','
signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, true, true, $9.cnt, $9.vect); }
| T_LABEL K_NET8_S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, true, $9.cnt, $9.vect); }
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ','
signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
| T_LABEL K_NET_R T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw_real($1, $3, $4, $6, $7, $9.cnt, $9.vect); }
/* Array word versions of alias directives. */

View File

@ -255,14 +255,20 @@ static const char* vpi_type_values(PLI_INT32 code)
{
static char buf[32];
switch (code) {
case vpiByteVar:
return "vpiByteVar";
case vpiConstant:
return "vpiConstant";
case vpiFunction:
return "vpiFunction";
case vpiIntVar:
return "vpiIntVar";
case vpiIntegerVar:
return "vpiIntegerVar";
case vpiIterator:
return "vpiIterator";
case vpiLongIntVar:
return "vpiLongIntVar";
case vpiMemory:
return "vpiMemory";
case vpiMemoryWord:
@ -287,6 +293,8 @@ static const char* vpi_type_values(PLI_INT32 code)
return "vpiRealVar";
case vpiReg:
return "vpiReg";
case vpiShortIntVar:
return "vpiShortIntVar";
case vpiSysFuncCall:
return "vpiSysFuncCall";
case vpiSysTaskCall:
@ -318,9 +326,7 @@ PLI_INT32 vpi_get(int property, vpiHandle ref)
}
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
return vpiIntegerVar;
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
return vpiNetArray;
else
return ref->vpi_type->type_code;
@ -375,9 +381,7 @@ char* vpi_get_str(PLI_INT32 property, vpiHandle ref)
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
PLI_INT32 type;
if (ref->vpi_type->type_code == vpiReg && rfp->isint_)
type = vpiIntegerVar;
else if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
if (ref->vpi_type->type_code == vpiMemory && is_net_array(ref))
type = vpiNetArray;
else
type = ref->vpi_type->type_code;

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "vpi_user.h"
# include "sv_vpi_user.h"
# include "vvp_net.h"
# include "config.h"
@ -243,7 +243,6 @@ struct __vpiSignal {
int msb, lsb;
/* Flags */
unsigned signed_flag : 1;
unsigned isint_ : 1; // original type was integer
unsigned is_netarray : 1; // This is word of a net array
/* The represented value is here. */
vvp_net_t*node;
@ -251,12 +250,14 @@ struct __vpiSignal {
extern unsigned vpip_size(__vpiSignal *sig);
extern struct __vpiScope* vpip_scope(__vpiSignal*sig);
extern vpiHandle vpip_make_int(const char*name, int msb, int lsb,
extern vpiHandle vpip_make_int2(const char*name, int msb, int lsb,
vvp_net_t*vec);
extern vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb,
vvp_net_t*vec);
extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*net);
extern vpiHandle vpip_make_net(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node);
/*
* This is used by system calls to represent a bit/part select of

View File

@ -507,11 +507,19 @@ static void format_vpiVectorVal(vvp_signal_value*sig, int base, unsigned wid,
struct __vpiSignal* vpip_signal_from_handle(vpiHandle ref)
{
if ((ref->vpi_type->type_code != vpiNet)
&& (ref->vpi_type->type_code != vpiReg))
return 0;
switch (ref->vpi_type->type_code) {
case vpiNet:
case vpiReg:
case vpiIntegerVar:
case vpiByteVar:
case vpiShortIntVar:
case vpiIntVar:
case vpiLongIntVar:
return (struct __vpiSignal*)ref;
return (struct __vpiSignal*)ref;
default:
return 0;
}
}
/*
@ -874,6 +882,17 @@ static const struct __vpirt vpip_reg_rt = {
0
};
static const struct __vpirt vpip_integer_rt = {
vpiIntegerVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_net_rt = {
vpiNet,
signal_get,
@ -888,31 +907,97 @@ static const struct __vpirt vpip_net_rt = {
0
};
static const struct __vpirt vpip_byte_rt = {
vpiByteVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_shortint_rt = {
vpiShortIntVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_int_rt = {
vpiIntVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
static const struct __vpirt vpip_longint_rt = {
vpiLongIntVar,
signal_get,
signal_get_str,
signal_get_value,
signal_put_value,
signal_get_handle,
signal_iterate,
0
};
/*
* Construct a vpiIntegerVar object. Indicate the type using a flag
* to minimize the code modifications. Icarus implements integers
* as 'reg signed [31:0]'.
*/
vpiHandle vpip_make_int(const char*name, int msb, int lsb, vvp_net_t*vec)
vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net(name, msb,lsb, true, vec);
struct __vpiSignal*rfp = (struct __vpiSignal*)obj;
obj->vpi_type = &vpip_reg_rt;
rfp->isint_ = true;
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
obj->vpi_type = &vpip_integer_rt;
return obj;
}
vpiHandle vpip_make_int2(const char*name, int msb, int lsb, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net4(name, msb,lsb, true, vec);
assert(lsb == 0);
switch (msb) {
case 7:
obj->vpi_type = &vpip_byte_rt;
break;
case 15:
obj->vpi_type = &vpip_shortint_rt;
break;
case 31:
obj->vpi_type = &vpip_int_rt;
break;
case 63:
obj->vpi_type = &vpip_longint_rt;
break;
}
return obj;
}
/*
* Construct a vpiReg object. It's like a net, except for the type.
* Construct a vpiReg/vpiLogicVar object. It's like a net, except for the type.
*/
vpiHandle vpip_make_reg(const char*name, int msb, int lsb,
vpiHandle vpip_make_var4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*vec)
{
vpiHandle obj = vpip_make_net(name, msb,lsb, signed_flag, vec);
vpiHandle obj = vpip_make_net4(name, msb,lsb, signed_flag, vec);
obj->vpi_type = &vpip_reg_rt;
return obj;
}
#ifdef CHECK_WITH_VALGRIND
static struct __vpiSignal **signal_pool = 0;
static unsigned signal_pool_count = 0;
@ -988,7 +1073,7 @@ void signal_pool_delete()
* The name is the PLI name for the object. If it is an array it is
* <name>[<index>].
*/
vpiHandle vpip_make_net(const char*name, int msb, int lsb,
vpiHandle vpip_make_net4(const char*name, int msb, int lsb,
bool signed_flag, vvp_net_t*node)
{
struct __vpiSignal*obj = allocate_vpiSignal();
@ -997,7 +1082,6 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
obj->msb = msb;
obj->lsb = lsb;
obj->signed_flag = signed_flag? 1 : 0;
obj->isint_ = 0;
obj->is_netarray = 0;
obj->node = node;

View File

@ -1385,6 +1385,34 @@ bool of_CASSIGN_X0(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_CAST2(vthread_t thr, vvp_code_t cp)
{
unsigned dst = cp->bit_idx[0];
unsigned src = cp->bit_idx[1];
unsigned wid = cp->number;
thr_check_addr(thr, dst+wid-1);
thr_check_addr(thr, src+wid-1);
vvp_vector4_t res;
switch (src) {
case 0:
case 2:
case 3:
res = vvp_vector4_t(wid, BIT4_0);
break;
case 1:
res = vvp_vector4_t(wid, BIT4_1);
break;
default:
res = vector2_to_vector4(vvp_vector2_t(vthread_bits_to_vector(thr, src, wid)), wid);
break;
}
thr->bits4.set_vec(dst, res);
return true;
}
bool of_CMPS(vthread_t thr, vvp_code_t cp)
{
vvp_bit4_t eq = BIT4_1;

View File

@ -1949,7 +1949,24 @@ vvp_vector2_t::vvp_vector2_t(vvp_vector2_t::fill_t fill, unsigned wid)
vec_[idx] = fill? -1 : 0;
}
vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned base, unsigned wid)
{
wid_ = wid;
const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
vec_ = new unsigned long[words];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
int bit = that.value(base+idx);
if (bit == 0)
continue;
unsigned word = idx / BITS_PER_WORD;
unsigned long mask = 1UL << (idx % BITS_PER_WORD);
vec_[word] |= mask;
}
}
void vvp_vector2_t::copy_from_that_(const vvp_vector4_t&that)
{
wid_ = that.size();
const unsigned words = (that.size() + BITS_PER_WORD-1) / BITS_PER_WORD;
@ -1970,15 +1987,12 @@ vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
switch (that.value(idx)) {
case BIT4_0:
case BIT4_X:
case BIT4_Z:
break;
case BIT4_1:
vec_[addr] |= 1UL << shift;
break;
default:
delete[]vec_;
vec_ = 0;
wid_ = 0;
return;
}
}
}
@ -1999,11 +2013,6 @@ void vvp_vector2_t::copy_from_that_(const vvp_vector2_t&that)
vec_[idx] = that.vec_[idx];
}
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
{
copy_from_that_(that);
}
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned newsize)
{
wid_ = newsize;
@ -2036,6 +2045,14 @@ vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector2_t&that)
return *this;
}
vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector4_t&that)
{
delete[]vec_;
vec_ = 0;
copy_from_that_(that);
return *this;
}
vvp_vector2_t& vvp_vector2_t::operator <<= (unsigned int shift)
{
if (wid_ == 0)
@ -2200,11 +2217,6 @@ vvp_vector2_t& vvp_vector2_t::operator -= (const vvp_vector2_t&that)
return *this;
}
vvp_vector2_t::~vvp_vector2_t()
{
delete[] vec_;
}
void vvp_vector2_t::trim()
{
while (value(wid_-1) == 0 && wid_ > 1) wid_ -= 1;
@ -2248,6 +2260,14 @@ void vvp_vector2_t::set_bit(unsigned idx, int bit)
vec_[addr] &= ~(1UL << mask);
}
void vvp_vector2_t::set_vec(unsigned adr, const vvp_vector2_t&that)
{
assert((adr + that.wid_) <= wid_);
for (unsigned idx = 0 ; idx < that.wid_ ; idx += 1)
set_bit(adr+idx, that.value(idx));
}
bool vvp_vector2_t::is_NaN() const
{
return wid_ == 0;
@ -2659,6 +2679,24 @@ vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
}
}
vvp_vector8_t::vvp_vector8_t(const vvp_vector2_t&that,
unsigned str0, unsigned str1)
: size_(that.size())
{
if (size_ == 0)
return;
if (size_ <= sizeof val_) {
ptr_ = 0;
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
val_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
} else {
ptr_ = new unsigned char[size_];
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
ptr_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
}
}
const vvp_vector8_t vvp_vector8_t::nil;
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)

View File

@ -42,6 +42,10 @@ using namespace std;
/* Data types */
class vvp_scalar_t;
class vvp_vector2_t;
class vvp_vector4_t;
class vvp_vector8_t;
/* Basic netlist types. */
class vvp_net_t;
class vvp_net_fun_t;
@ -607,9 +611,10 @@ class vvp_vector2_t {
vvp_vector2_t();
vvp_vector2_t(const vvp_vector2_t&);
vvp_vector2_t(const vvp_vector2_t&, unsigned newsize);
vvp_vector2_t(const vvp_vector2_t&, unsigned base, unsigned wid);
// Make a vvp_vector2_t from a vvp_vector4_t. If there are X
// or Z bits, then the result becomes a NaN value.
explicit vvp_vector2_t(const vvp_vector4_t&that);
vvp_vector2_t(const vvp_vector4_t&that);
// Make from a native long and a specified width.
vvp_vector2_t(unsigned long val, unsigned wid);
// Make with the width, and filled with 1 or 0 bits.
@ -623,11 +628,19 @@ class vvp_vector2_t {
vvp_vector2_t&operator >>= (unsigned shift);
vvp_vector2_t&operator = (const vvp_vector2_t&);
// Assign a vec4 to a vec2, using Verilog rules for converting
// XZ values to 0.
vvp_vector2_t&operator = (const vvp_vector4_t&);
bool is_NaN() const;
bool is_zero() const;
unsigned size() const;
int value(unsigned idx) const;
vvp_bit4_t value4(unsigned idx) const;
// Get the vector2 subvector starting at the address
vvp_vector2_t subvalue(unsigned idx, unsigned size) const;
void set_bit(unsigned idx, int bit);
void set_vec(unsigned idx, const vvp_vector2_t&that);
// Make the size just big enough to hold the first 1 bit.
void trim();
// Trim off extra 1 bit since this is representing a negative value.
@ -641,6 +654,7 @@ class vvp_vector2_t {
private:
void copy_from_that_(const vvp_vector2_t&that);
void copy_from_that_(const vvp_vector4_t&that);
};
extern bool operator > (const vvp_vector2_t&, const vvp_vector2_t&);
@ -667,12 +681,40 @@ extern double crstring_to_double(const char*str);
extern ostream& operator<< (ostream&, const vvp_vector2_t&);
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
{
copy_from_that_(that);
}
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
{
copy_from_that_(that);
}
inline vvp_vector2_t::~vvp_vector2_t()
{
delete[] vec_;
}
/* Inline some of the vector2_t methods. */
inline unsigned vvp_vector2_t::size() const
{
return wid_;
}
inline vvp_bit4_t vvp_vector2_t::value4(unsigned idx) const
{
if (value(idx))
return BIT4_1;
else
return BIT4_0;
}
inline vvp_vector2_t vvp_vector2_t::subvalue(unsigned base, unsigned wid) const
{
return vvp_vector2_t(*this, base, wid);
}
/*
* This class represents a scalar value with strength. These are
* heavier then the simple vvp_bit4_t, but more information is
@ -810,6 +852,9 @@ class vvp_vector8_t {
explicit vvp_vector8_t(const vvp_vector4_t&that,
unsigned str0,
unsigned str1);
explicit vvp_vector8_t(const vvp_vector2_t&that,
unsigned str0,
unsigned str1);
~vvp_vector8_t();
@ -1220,7 +1265,9 @@ class vvp_net_fil_t : public vvp_vpi_callback {
// the val through the force mask. The force value is the
// currently forced value, and the buf is a value that this
// method will use to hold a filtered value, if needed. This
// method returns a pointer to val or buf.
// method returns the replacement value into the "rep"
// argument and returns a code indicating whether any changes
// were made.
template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep, unsigned addr);
// This template method is similar to the above, but works for
// native types that are not so expensive to edit in place.

View File

@ -85,7 +85,8 @@ void compile_varw_real(char*label, vvp_array_t array,
*/
static void __compile_var(char*label, char*name,
vvp_array_t array, unsigned long array_addr,
int msb, int lsb, char signed_flag, bool local_flag)
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
@ -95,6 +96,9 @@ static void __compile_var(char*label, char*name,
vvp_fun_signal4_aa*tmp = new vvp_fun_signal4_aa(wid);
net->fil = tmp;
net->fun = tmp;
} else if (vpi_type_code == vpiIntVar) {
net->fil = new vvp_wire_vec4(wid, BIT4_0);
net->fun = new vvp_fun_signal4_sa(wid);
} else {
net->fil = new vvp_wire_vec4(wid, BIT4_X);
net->fun = new vvp_fun_signal4_sa(wid);
@ -106,9 +110,21 @@ static void __compile_var(char*label, char*name,
vpiHandle obj = 0;
if (! local_flag && !array) {
/* Make the vpiHandle for the reg. */
obj = (signed_flag > 1) ?
vpip_make_int(name, msb, lsb, net) :
vpip_make_reg(name, msb, lsb, signed_flag!=0, net);
switch (vpi_type_code) {
case vpiLogicVar:
obj = vpip_make_var4(name, msb, lsb, signed_flag, net);
break;
case vpiIntegerVar:
obj = vpip_make_int4(name, msb, lsb, net);
break;
case vpiIntVar: // This handles all the atom2 int types
obj = vpip_make_int2(name, msb, lsb, net);
break;
default:
fprintf(stderr, "internal error: %s: vpi_type_code=%d\n", name, vpi_type_code);
break;
}
assert(obj);
compile_vpi_symbol(label, obj);
}
// If the signal has a name, then it goes into the current
@ -133,24 +149,10 @@ static void __compile_var(char*label, char*name,
}
void compile_variable(char*label, char*name,
int msb, int lsb, char signed_flag, bool local_flag)
int msb, int lsb, int vpi_type_code,
bool signed_flag, bool local_flag)
{
__compile_var(label, name, 0, 0, msb, lsb, signed_flag, local_flag);
}
/*
* In this case, the variable it intended to be attached to the array
* as a word. The array_addr is the *canonical* address of the word in
* the array.
*
* This function is actually used by the compile_array function,
* instead of directly by the parser.
*/
void compile_variablew(char*label, vvp_array_t array,
unsigned long array_addr,
int msb, int lsb, char signed_flag)
{
__compile_var(label, 0, array, array_addr, msb, lsb, signed_flag, false);
__compile_var(label, name, 0, 0, msb, lsb, vpi_type_code, signed_flag, local_flag);
}
vvp_net_t* create_constant_node(const char*val_str)
@ -210,12 +212,12 @@ class __compile_net_resolv : public base_net_resolv {
struct __vpiScope*scope,
char*my_label, char*name,
int msb, int lsb, unsigned array_addr,
bool signed_flag, bool net8_flag, bool local_flag)
int vpi_type_code, bool signed_flag, bool local_flag)
: base_net_resolv(ref_label, array, scope, my_label, name, array_addr, local_flag)
{ msb_ = msb;
lsb_ = lsb;
vpi_type_code_ = vpi_type_code;
signed_flag_ = signed_flag;
net8_flag_ = net8_flag;
}
~__compile_net_resolv() { }
@ -224,7 +226,8 @@ class __compile_net_resolv : public base_net_resolv {
private:
int msb_, lsb_;
bool signed_flag_, net8_flag_;
int vpi_type_code_;
bool signed_flag_;
};
/*
@ -239,11 +242,11 @@ class __compile_net_resolv : public base_net_resolv {
* references into the net.
*/
static void __compile_net2(vvp_net_t*node, vvp_array_t array,
static void do_compile_net(vvp_net_t*node, vvp_array_t array,
struct __vpiScope*scope,
char*my_label, char*name,
int msb, int lsb, unsigned array_addr,
bool signed_flag, bool net8_flag, bool local_flag)
int vpi_type_code, bool signed_flag, bool local_flag)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
assert(node);
@ -251,17 +254,25 @@ static void __compile_net2(vvp_net_t*node, vvp_array_t array,
vvp_wire_base*vsig = dynamic_cast<vvp_wire_base*>(node->fil);
if (vsig == 0) {
vsig = net8_flag
? dynamic_cast<vvp_wire_base*>(new vvp_wire_vec8(wid))
: dynamic_cast<vvp_wire_base*>(new vvp_wire_vec4(wid,BIT4_Z));
switch (vpi_type_code) {
case vpiIntVar:
vsig = new vvp_wire_vec4(wid,BIT4_0);
break;
case vpiLogicVar:
vsig = new vvp_wire_vec4(wid,BIT4_Z);
break;
case -vpiLogicVar:
vsig = new vvp_wire_vec8(wid);
break;
}
assert(vsig);
node->fil = vsig;
}
vpiHandle obj = 0;
if (! local_flag) {
/* Make the vpiHandle for the reg. */
obj = vpip_make_net(name, msb, lsb, signed_flag, node);
obj = vpip_make_net4(name, msb, lsb, signed_flag, node);
/* This attaches the label to the vpiHandle */
compile_vpi_symbol(my_label, obj);
}
@ -287,7 +298,7 @@ static void __compile_net2(vvp_net_t*node, vvp_array_t array,
static void __compile_net(char*label,
char*name, char*array_label, unsigned long array_addr,
int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
int vpi_type_code, bool signed_flag, bool local_flag,
unsigned argc, struct symb_s*argv)
{
vvp_array_t array = array_label? array_find(array_label) : 0;
@ -314,7 +325,7 @@ static void __compile_net(char*label,
= new __compile_net_resolv(argv[0].text,
array, scope, label, name,
msb, lsb, array_addr,
signed_flag, net8_flag, local_flag);
vpi_type_code, signed_flag, local_flag);
resolv_submit(res);
free(argv);
return;
@ -322,8 +333,8 @@ static void __compile_net(char*label,
assert(node);
struct __vpiScope*scope = vpip_peek_current_scope();
__compile_net2(node, array, scope, label, name, msb, lsb, array_addr,
signed_flag, net8_flag, local_flag);
do_compile_net(node, array, scope, label, name, msb, lsb, array_addr,
vpi_type_code, signed_flag, local_flag);
free(argv[0].text);
free(argv);
@ -338,30 +349,28 @@ bool __compile_net_resolv::resolve(bool msg_flag)
return false;
}
__compile_net2(node, array_, scope_, my_label_, name_, msb_, lsb_, array_addr_, signed_flag_, net8_flag_, local_flag_);
do_compile_net(node, array_, scope_, my_label_, name_, msb_, lsb_, array_addr_, vpi_type_code_, signed_flag_, local_flag_);
return true;
}
void compile_net(char*label, char*name, int msb, int lsb,
bool signed_flag, bool net8_flag, bool local_flag,
int vpi_type_code, bool signed_flag, bool local_flag,
unsigned argc, struct symb_s*argv)
{
__compile_net(label, name, 0, 0,
msb, lsb, signed_flag, net8_flag, local_flag,
__compile_net(label, name, 0, 0, msb, lsb,
vpi_type_code, signed_flag, local_flag,
argc, argv);
}
void compile_netw(char*label, char*array_label, unsigned long array_addr,
int msb, int lsb,
bool signed_flag, bool net8_flag,
unsigned argc, struct symb_s*argv)
int msb, int lsb, int vpi_type_code, bool signed_flag,
unsigned argc, struct symb_s*argv)
{
__compile_net(label, 0, array_label, array_addr,
msb, lsb, signed_flag, net8_flag, false,
msb, lsb, vpi_type_code, signed_flag, false,
argc, argv);
}
class __compile_real_net_resolv : public base_net_resolv {
public: