Add support for system functions in continuous assignments.
This commit is contained in:
parent
71faebd6df
commit
80f30be9d0
12
PExpr.h
12
PExpr.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.82 2006/06/02 04:48:49 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.83 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -556,10 +556,20 @@ class PECallFunction : public PExpr {
|
|||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
|
||||
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.83 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.82 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.165 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.166 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
# include <iostream>
|
||||
# include <iomanip>
|
||||
# include "netlist.h"
|
||||
|
||||
# include "compiler.h"
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
{
|
||||
|
|
@ -462,6 +462,13 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSysFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name << "(...)" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name() << "(";
|
||||
|
|
@ -1173,6 +1180,9 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.166 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.165 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
|
|
|||
122
elab_net.cc
122
elab_net.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.186 2006/06/02 04:48:50 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.187 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1209,39 +1209,11 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
|||
unsigned errors = 0;
|
||||
unsigned func_pins = 0;
|
||||
|
||||
/* Handle the special case that the function call is to
|
||||
$signed. This takes a single expression argument, and
|
||||
forces it to be a signed result. Otherwise, it is as if the
|
||||
$signed did not exist. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
return elaborate_net_sfunc_(des, scope,
|
||||
width, rise, fall, decay,
|
||||
drive0, drive1);
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(true);
|
||||
return sub;
|
||||
}
|
||||
/* handle $unsigned like $signed */
|
||||
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $unsigned() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(false);
|
||||
return sub;
|
||||
}
|
||||
|
||||
/* Look up the function definition. */
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
|
|
@ -1319,6 +1291,87 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
/* Handle the special case that the function call is to
|
||||
$signed. This takes a single expression argument, and
|
||||
forces it to be a signed result. Otherwise, it is as if the
|
||||
$signed did not exist. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(true);
|
||||
return sub;
|
||||
}
|
||||
|
||||
/* handle $unsigned like $signed */
|
||||
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $unsigned() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(false);
|
||||
return sub;
|
||||
}
|
||||
|
||||
const struct sfunc_return_type*def = lookup_sys_func(path_.peek_name(0));
|
||||
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: System function "
|
||||
<< path_.peek_name(0) << " not defined." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
|
||||
def, 1+parms_.count());
|
||||
des->add_node(net);
|
||||
net->set_line(*this);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, def->wid);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(def->type);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->elaborate_net(des, scope, 0,
|
||||
0, 0, 0,
|
||||
Link::STRONG, Link::STRONG);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
<< "port " << idx << " of call to " << path_ <<
|
||||
"." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(net->pin(1+idx), tmp->pin(0));
|
||||
}
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The concatenation operator, as a net, is a wide signal that is
|
||||
|
|
@ -2779,6 +2832,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.187 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.186 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
|
|
|
|||
9
emit.cc
9
emit.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.86 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.87 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -146,6 +146,10 @@ bool NetUReduce::emit_node(struct target_t*tgt) const
|
|||
return tgt->ureduce(this);
|
||||
}
|
||||
|
||||
bool NetSysFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_sysfunction(this);
|
||||
}
|
||||
|
||||
bool NetUserFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
|
|
@ -525,6 +529,9 @@ int emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.87 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.86 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
29
ivl_target.h
29
ivl_target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.167 2006/04/16 00:15:43 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.168 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -244,6 +244,7 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_RE_XNOR= 24,
|
||||
IVL_LPM_RE_XOR = 25,
|
||||
IVL_LPM_REPEAT = 26,
|
||||
IVL_LPM_SFUNC = 29,
|
||||
IVL_LPM_SHIFTL = 6,
|
||||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SIGN_EXT=27,
|
||||
|
|
@ -991,6 +992,19 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* the shift distance. The vector input is the same width as the
|
||||
* output, but the distance has its own width.
|
||||
*
|
||||
* - System function call (IVL_LPM_SFUNC)
|
||||
* This device represents a netlist call to a system function. The
|
||||
* inputs to the device are passed to a system function, and the
|
||||
* result is sent via the output. The ivl_lpm_q function returns the
|
||||
* output nexus.
|
||||
*
|
||||
* The ivl_lpm_size function returns the number of arguments, and the
|
||||
* ivl_lpm_data(net,N) returns the nexa for the argument.
|
||||
*
|
||||
* The ivl_lpm_string(net) function returns the name of the system
|
||||
* function (i.e. "$display") that was found in the source code. The
|
||||
* compiler does little checking of that name.
|
||||
*
|
||||
* - User Function Call (IVL_LPM_UFUNC)
|
||||
* This device is special as it represents a call to a user defined
|
||||
* function (behavioral code) within a netlist. The inputs to the
|
||||
|
|
@ -1039,14 +1053,6 @@ extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
|||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
#if 0
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
#endif
|
||||
#if 0
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
#endif
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
|
|
@ -1056,6 +1062,8 @@ extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
|||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net);
|
||||
/* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_SFUNC */
|
||||
extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
||||
|
|
@ -1706,6 +1714,9 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.168 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.167 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
|
|
|
|||
40
net_func.cc
40
net_func.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_func.cc,v 1.7 2005/03/18 02:56:03 steve Exp $"
|
||||
#ident "$Id: net_func.cc,v 1.8 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -112,8 +112,46 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
|
||||
const struct sfunc_return_type*def,
|
||||
unsigned ports)
|
||||
: NetNode(s, n, ports)
|
||||
{
|
||||
def_ = def;
|
||||
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Q"), 0);
|
||||
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
}
|
||||
}
|
||||
|
||||
NetSysFunc::~NetSysFunc()
|
||||
{
|
||||
}
|
||||
|
||||
const char*NetSysFunc::func_name() const
|
||||
{
|
||||
return def_->name;
|
||||
}
|
||||
|
||||
unsigned NetSysFunc::vector_width() const
|
||||
{
|
||||
return def_->wid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_func.cc,v $
|
||||
* Revision 1.8 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.7 2005/03/18 02:56:03 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
|
|
|
|||
27
netlist.h
27
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.357 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.358 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -1020,6 +1020,28 @@ class NetUserFunc : public NetNode {
|
|||
NetScope*def_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The number of ports includes the return value, so will always be at
|
||||
* least 1.
|
||||
*/
|
||||
class NetSysFunc : public NetNode {
|
||||
|
||||
public:
|
||||
NetSysFunc(NetScope*s, perm_string n,
|
||||
const struct sfunc_return_type*def,
|
||||
unsigned ports);
|
||||
~NetSysFunc();
|
||||
|
||||
unsigned vector_width() const;
|
||||
const char* func_name() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
const struct sfunc_return_type*def_;
|
||||
};
|
||||
|
||||
/* =========
|
||||
* There are cases where expressions need to be represented. The
|
||||
* NetExpr class is the root of a hierarchy that serves that purpose.
|
||||
|
|
@ -3464,6 +3486,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.358 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.357 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
|
|
|||
69
t-dll-api.cc
69
t-dll-api.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.133 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.134 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -852,6 +852,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx == 0);
|
||||
return net->u_.repeat.a;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
// Skip the return port.
|
||||
assert(idx < (net->u_.sfunc.ports-1));
|
||||
return net->u_.sfunc.pins[idx+1];
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
// Skip the return port.
|
||||
assert(idx < (net->u_.ufunc.ports-1));
|
||||
|
|
@ -1005,6 +1010,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx == 0);
|
||||
return net->u_.shift.q;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
assert(idx == 0);
|
||||
return net->u_.sfunc.pins[0];
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
assert(idx == 0);
|
||||
return net->u_.ufunc.pins[0];
|
||||
|
|
@ -1096,6 +1105,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
return net->u_.shift.signed_flag;
|
||||
case IVL_LPM_SIGN_EXT: // Sign extend is always signed.
|
||||
return 1;
|
||||
case IVL_LPM_SFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_CONCAT: // Concatenations are always unsigned
|
||||
|
|
@ -1117,6 +1128,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
|||
switch (net->type) {
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.size;
|
||||
case IVL_LPM_SFUNC:
|
||||
return net->u_.sfunc.ports - 1;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.ports - 1;
|
||||
case IVL_LPM_REPEAT:
|
||||
|
|
@ -1127,6 +1140,12 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_lpm_string(ivl_lpm_t net)
|
||||
{
|
||||
assert(net->type == IVL_LPM_SFUNC);
|
||||
return net->u_.sfunc.fun_name;
|
||||
}
|
||||
|
||||
extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net)
|
||||
{
|
||||
return net->type;
|
||||
|
|
@ -1135,50 +1154,7 @@ extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net)
|
|||
extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.width;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.width;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
return net->u_.arith.width;
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
return net->u_.reduce.width;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.width;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.width;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.width;
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
return net->u_.part.width;
|
||||
case IVL_LPM_PART_BI:
|
||||
return net->u_.part.width;
|
||||
case IVL_LPM_REPEAT:
|
||||
return net->u_.repeat.width;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
return net->width;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
||||
|
|
@ -2033,6 +2009,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.134 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.133 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
79
t-dll.cc
79
t-dll.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.156 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.157 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -904,7 +904,7 @@ bool dll_target::sign_extend(const NetSignExtend*net)
|
|||
{
|
||||
struct ivl_lpm_s*obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_SIGN_EXT;
|
||||
obj->u_.reduce.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -959,7 +959,7 @@ bool dll_target::ureduce(const NetUReduce*net)
|
|||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.reduce.width = net->width();
|
||||
obj->width = net->width();
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
|
|
@ -988,7 +988,7 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
|||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.arith.signed_flag = 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1014,6 +1014,46 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::net_sysfunction(const NetSysFunc*net)
|
||||
{
|
||||
unsigned idx;
|
||||
const Nexus*nex;
|
||||
|
||||
struct ivl_lpm_s*obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_SFUNC;
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.sfunc.ports = net->pin_count();
|
||||
|
||||
assert(net->pin_count() >= 1);
|
||||
obj->width = net->vector_width();
|
||||
|
||||
obj->u_.sfunc.fun_name = net->func_name();
|
||||
|
||||
obj->u_.sfunc.pins = new ivl_nexus_t[net->pin_count()];
|
||||
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.sfunc.pins[0] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.sfunc.pins[0], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
for (idx = 1 ; idx < net->pin_count() ; idx += 1) {
|
||||
nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.sfunc.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.sfunc.pins[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* An IVL_LPM_UFUNC represents a node in a combinational expression
|
||||
* that calls a user defined function. I create an LPM object that has
|
||||
|
|
@ -1039,7 +1079,7 @@ bool dll_target::net_function(const NetUserFunc*net)
|
|||
obj->u_.ufunc.ports = net->pin_count();
|
||||
|
||||
assert(net->pin_count() >= 1);
|
||||
obj->u_.ufunc.width = net->port_width(0);
|
||||
obj->width = net->port_width(0);
|
||||
|
||||
/* Now collect all the pins and connect them to the nexa of
|
||||
the net. The output pins have strong drive, and the
|
||||
|
|
@ -1177,9 +1217,9 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
/* Choose the width of the adder. If the carry bit is
|
||||
connected, then widen the adder by one and plan on leaving
|
||||
the fake inputs unconnected. */
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->width = net->width();
|
||||
if (net->pin_Cout().is_linked()) {
|
||||
obj->u_.arith.width += 1;
|
||||
obj->width += 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1235,7 +1275,7 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
else
|
||||
obj->u_.shift.signed_flag = 0;
|
||||
|
||||
obj->u_.shift.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.shift.select = net->width_dist();
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1276,7 +1316,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
|||
|
||||
bool swap_operands = false;
|
||||
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1377,7 +1417,7 @@ void dll_target::lpm_divide(const NetDivide*net)
|
|||
|
||||
unsigned wid = net->width_r();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->width = wid;
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1415,7 +1455,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
|
||||
unsigned wid = net->width_r();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->width = wid;
|
||||
obj->u_.arith.signed_flag = 0;
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1449,7 +1489,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
|||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
obj->width = net->width();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
|
|
@ -1548,7 +1588,7 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
|||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.ff.swid = net->awidth();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
|
@ -1619,7 +1659,7 @@ void dll_target::lpm_mult(const NetMult*net)
|
|||
|
||||
unsigned wid = net->width_r();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->width = wid;
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
|
|
@ -1657,7 +1697,7 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.mux.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.mux.size = net->size();
|
||||
obj->u_.mux.swid = net->sel_width();
|
||||
|
||||
|
|
@ -1701,7 +1741,7 @@ bool dll_target::concat(const NetConcat*net)
|
|||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.concat.width = net->width();
|
||||
obj->width = net->width();
|
||||
|
||||
obj->u_.concat.inputs = net->pin_count() - 1;
|
||||
obj->u_.concat.pins = new ivl_nexus_t[obj->u_.concat.inputs+1];
|
||||
|
|
@ -1743,7 +1783,7 @@ bool dll_target::part_select(const NetPartSelect*net)
|
|||
obj->u_.part.signed_flag = 0;
|
||||
|
||||
/* Choose the width of the part select. */
|
||||
obj->u_.part.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.part.base = net->base();
|
||||
obj->u_.part.s = 0;
|
||||
|
||||
|
|
@ -1834,7 +1874,7 @@ bool dll_target::replicate(const NetReplicate*net)
|
|||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.repeat.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.repeat.count = net->repeat();
|
||||
|
||||
ivl_drive_t dr = IVL_DR_STRONG;
|
||||
|
|
@ -2167,6 +2207,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.157 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.156 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
|
|
|||
23
t-dll.h
23
t-dll.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.131 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -86,6 +86,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
bool part_select(const NetPartSelect*);
|
||||
bool replicate(const NetReplicate*);
|
||||
void net_assign(const NetAssign_*);
|
||||
bool net_sysfunction(const NetSysFunc*);
|
||||
bool net_function(const NetUserFunc*);
|
||||
bool net_const(const NetConst*);
|
||||
bool net_literal(const NetLiteral*);
|
||||
|
|
@ -282,10 +283,11 @@ struct ivl_lpm_s {
|
|||
ivl_lpm_type_t type;
|
||||
ivl_scope_t scope;
|
||||
perm_string name;
|
||||
// Value returned by ivl_lpm_width;
|
||||
unsigned width;
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned width;
|
||||
unsigned swid; // ram only
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
|
|
@ -311,7 +313,6 @@ struct ivl_lpm_s {
|
|||
} ff;
|
||||
|
||||
struct ivl_lpm_mux_s {
|
||||
unsigned width;
|
||||
unsigned size;
|
||||
unsigned swid;
|
||||
ivl_nexus_t*d;
|
||||
|
|
@ -319,26 +320,22 @@ struct ivl_lpm_s {
|
|||
} mux;
|
||||
|
||||
struct ivl_lpm_shift_s {
|
||||
unsigned width;
|
||||
unsigned select;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, d, s;
|
||||
} shift;
|
||||
|
||||
struct ivl_lpm_arith_s {
|
||||
unsigned width;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_concat_s {
|
||||
unsigned width;
|
||||
unsigned inputs;
|
||||
ivl_nexus_t*pins;
|
||||
} concat;
|
||||
|
||||
struct ivl_part_s {
|
||||
unsigned width;
|
||||
unsigned base;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, a, s;
|
||||
|
|
@ -346,20 +343,23 @@ struct ivl_lpm_s {
|
|||
|
||||
// IVL_LPM_RE_* and IVL_LPM_SIGN_EXT use this.
|
||||
struct ivl_lpm_reduce_s {
|
||||
unsigned width;
|
||||
ivl_nexus_t q, a;
|
||||
} reduce;
|
||||
|
||||
struct ivl_lpm_repeat_s {
|
||||
unsigned width;
|
||||
unsigned count;
|
||||
ivl_nexus_t q, a;
|
||||
} repeat;
|
||||
|
||||
struct ivl_lpm_sfunc_s {
|
||||
const char* fun_name;
|
||||
unsigned ports;
|
||||
ivl_nexus_t*pins;
|
||||
} sfunc;
|
||||
|
||||
struct ivl_lpm_ufunc_s {
|
||||
ivl_scope_t def;
|
||||
unsigned ports;
|
||||
unsigned width;
|
||||
ivl_nexus_t*pins;
|
||||
} ufunc;
|
||||
} u_;
|
||||
|
|
@ -671,6 +671,9 @@ struct ivl_statement_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.131 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
|
|
|||
12
target.cc
12
target.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.77 2005/07/11 16:56:51 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.78 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -174,6 +174,13 @@ bool target_t::net_const(const NetConst*)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_sysfunction(const NetSysFunc*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetSysFunc node." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_function(const NetUserFunc*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -431,6 +438,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.78 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.77 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
6
target.h
6
target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.74 2005/07/11 16:56:51 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.75 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -94,6 +94,7 @@ struct target_t {
|
|||
virtual void udp(const NetUDP*);
|
||||
virtual void net_case_cmp(const NetCaseCmp*);
|
||||
virtual bool net_const(const NetConst*);
|
||||
virtual bool net_sysfunction(const NetSysFunc*);
|
||||
virtual bool net_function(const NetUserFunc*);
|
||||
virtual bool net_literal(const NetLiteral*);
|
||||
virtual void net_probe(const NetEvProbe*);
|
||||
|
|
@ -170,6 +171,9 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.75 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.74 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stub.c,v 1.138 2006/04/30 05:16:53 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.139 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -83,11 +83,29 @@ unsigned width_of_nexus(ivl_nexus_t nex)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char*vt_type_string(ivl_expr_t net)
|
||||
ivl_variable_type_t type_of_nexus(ivl_nexus_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(net); idx += 1) {
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(net, idx);
|
||||
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
|
||||
|
||||
if (sig != 0) {
|
||||
return ivl_signal_data_type(sig);
|
||||
}
|
||||
}
|
||||
|
||||
/* ERROR: A nexus should have at least one signal to carry
|
||||
properties like the data type. */
|
||||
return IVL_VT_NO_TYPE;
|
||||
}
|
||||
|
||||
const char*data_type_string(ivl_variable_type_t vtype)
|
||||
{
|
||||
const char*vt = "??";
|
||||
|
||||
switch (ivl_expr_value(net)) {
|
||||
switch (vtype) {
|
||||
case IVL_VT_NO_TYPE:
|
||||
vt = "NO_TYPE";
|
||||
break;
|
||||
|
|
@ -108,6 +126,11 @@ const char*vt_type_string(ivl_expr_t net)
|
|||
return vt;
|
||||
}
|
||||
|
||||
const char*vt_type_string(ivl_expr_t net)
|
||||
{
|
||||
return data_type_string(ivl_expr_value(net));
|
||||
}
|
||||
|
||||
void show_binary_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
|
|
@ -894,6 +917,34 @@ static void show_lpm_sub(ivl_lpm_t net)
|
|||
show_lpm_arithmetic_pins(net);
|
||||
}
|
||||
|
||||
static void show_lpm_sfunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned ports = ivl_lpm_size(net);
|
||||
ivl_variable_type_t data_type = type_of_nexus(ivl_lpm_q(net,0));
|
||||
ivl_nexus_t nex;
|
||||
unsigned idx;
|
||||
|
||||
fprintf(out, " LPM_SFUNC %s: <call=%s, width=%u, type=%s, ports=%u>\n",
|
||||
ivl_lpm_basename(net), ivl_lpm_string(net),
|
||||
width, data_type_string(data_type), ports);
|
||||
|
||||
nex = ivl_lpm_q(net, 0);
|
||||
if (width != width_of_nexus(nex)) {
|
||||
fprintf(out, " ERROR: Q output nexus width=%u "
|
||||
" does not match part width\n", width_of_nexus(nex));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
|
||||
for (idx = 0 ; idx < ports ; idx += 1) {
|
||||
nex = ivl_lpm_data(net, idx);
|
||||
fprintf(out, " D%u: %s <width=%u, type=%s>\n", idx,
|
||||
ivl_nexus_name(nex), width_of_nexus(nex),
|
||||
data_type_string(type_of_nexus(nex)));
|
||||
}
|
||||
}
|
||||
|
||||
static void show_lpm_ufunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
|
@ -1014,6 +1065,10 @@ static void show_lpm(ivl_lpm_t net)
|
|||
show_lpm_repeat(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
show_lpm_sfunc(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
show_lpm_ufunc(net);
|
||||
break;
|
||||
|
|
@ -1591,6 +1646,9 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.139 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.138 2006/04/30 05:16:53 steve
|
||||
* Dump *all* the reduction operator gates.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_scope.c,v 1.144 2006/04/22 04:27:36 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.145 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
|
|
@ -611,6 +611,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SFUNC:
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
|
|
@ -1801,6 +1802,43 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
|
|||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_type_string_of_nex(ivl_nexus_t nex)
|
||||
{
|
||||
switch (data_type_of_nexus(nex)) {
|
||||
case IVL_VT_REAL:
|
||||
fprintf(vvp_out, "r");
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
fprintf(vvp_out, "v%d", width_of_nexus(nex));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_lpm_sfunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
fprintf(vvp_out, "L_%p .sfunc \"%s\"", net, ivl_lpm_string(net));
|
||||
|
||||
/* Print the function type descriptor string. */
|
||||
fprintf(vvp_out, ", \"");
|
||||
|
||||
draw_type_string_of_nex(ivl_lpm_q(net,0));
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1)
|
||||
draw_type_string_of_nex(ivl_lpm_data(net,idx));
|
||||
|
||||
fprintf(vvp_out, "\"");
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
|
||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx)));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_lpm_ufunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
|
@ -2078,6 +2116,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
|||
draw_lpm_sign_ext(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
draw_lpm_sfunc(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
draw_lpm_ufunc(net);
|
||||
return;
|
||||
|
|
@ -2209,6 +2251,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
|||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.145 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.144 2006/04/22 04:27:36 steve
|
||||
* Get tail counts right in nested concatenations.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.69 2005/06/12 01:42:20 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.70 2006/06/18 04:15:50 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -82,7 +82,7 @@ vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
|
|||
vpip_to_dec.o vpip_format.o vvp_vpi.o
|
||||
|
||||
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o concat.o \
|
||||
dff.o extend.o npmos.o part.o reduce.o resolv.o stop.o symbols.o \
|
||||
dff.o extend.o npmos.o part.o reduce.o resolv.o sfunc.o stop.o symbols.o \
|
||||
ufunc.o codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \
|
||||
event.o logic.o delay.o words.o $V
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.cc,v 1.219 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.220 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
|
|
@ -1417,7 +1417,7 @@ void compile_vpi_call(char*label, char*name, unsigned argc, vpiHandle*argv)
|
|||
|
||||
/* Create a vpiHandle that bundles the call information, and
|
||||
store that handle in the instruction. */
|
||||
code->handle = vpip_build_vpi_call(name, 0, 0, argc, argv);
|
||||
code->handle = vpip_build_vpi_call(name, 0, 0, 0, argc, argv);
|
||||
if (code->handle == 0)
|
||||
compile_errors += 1;
|
||||
|
||||
|
|
@ -1438,7 +1438,7 @@ void compile_vpi_func_call(char*label, char*name,
|
|||
|
||||
/* Create a vpiHandle that bundles the call information, and
|
||||
store that handle in the instruction. */
|
||||
code->handle = vpip_build_vpi_call(name, vbit, vwid, argc, argv);
|
||||
code->handle = vpip_build_vpi_call(name, vbit, vwid, 0, argc, argv);
|
||||
if (code->handle == 0)
|
||||
compile_errors += 1;
|
||||
|
||||
|
|
@ -1495,6 +1495,9 @@ void compile_param_string(char*label, char*name, char*value)
|
|||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.220 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.219 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.h,v 1.80 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.81 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -169,6 +169,8 @@ extern void compile_reduce_xnor(char*label, struct symb_s arg);
|
|||
|
||||
extern void compile_extend_signed(char*label, long width, struct symb_s arg);
|
||||
|
||||
extern void compile_sfunc(char*label, char*name, char*format_string,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_repeat(char*label, long width, long repeat,
|
||||
struct symb_s arg);
|
||||
|
||||
|
|
@ -343,6 +345,9 @@ extern void compile_alias_real(char*label, char*name,
|
|||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.81 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.80 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.60 2006/05/17 04:15:25 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.61 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -130,6 +130,7 @@
|
|||
".repeat" { return K_REPEAT; }
|
||||
".resolv" { return K_RESOLV; }
|
||||
".scope" { return K_SCOPE; }
|
||||
".sfunc" { return K_SFUNC; }
|
||||
".shift/l" { return K_SHIFTL; }
|
||||
".shift/r" { return K_SHIFTR; }
|
||||
".thread" { return K_THREAD; }
|
||||
|
|
@ -208,6 +209,9 @@ int yywrap()
|
|||
|
||||
/*
|
||||
* $Log: lexor.lex,v $
|
||||
* Revision 1.61 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.60 2006/05/17 04:15:25 steve
|
||||
* Lexor os never interactive.
|
||||
*
|
||||
|
|
|
|||
11
vvp/parse.y
11
vvp/parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.82 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.83 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
|
|
@ -67,7 +67,7 @@ extern FILE*yyin;
|
|||
%token K_PARAM_STR K_PARAM_L K_PART K_PART_PV
|
||||
%token K_PART_V 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_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
|
||||
%token K_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
%token K_MEM K_MEM_P K_MEM_I
|
||||
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
|
||||
|
|
@ -329,6 +329,10 @@ statement
|
|||
| T_LABEL K_EXTEND_S T_NUMBER ',' symbol ';'
|
||||
{ compile_extend_signed($1, $3, $5); }
|
||||
|
||||
/* System function call */
|
||||
| T_LABEL K_SFUNC T_STRING ',' T_STRING ',' symbols ';'
|
||||
{ compile_sfunc($1, $3, $5, $7.cnt, $7.vect); }
|
||||
|
||||
/* Shift nodes. */
|
||||
|
||||
| T_LABEL K_SHIFTL T_NUMBER ',' symbols ';'
|
||||
|
|
@ -739,6 +743,9 @@ int compile_design(const char*path)
|
|||
|
||||
/*
|
||||
* $Log: parse.y,v $
|
||||
* Revision 1.83 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.82 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2006 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
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sfunc.cc,v 1.1 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
# include "sfunc.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <iostream>
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
sfunc_core::sfunc_core(vvp_net_t*net, vpiHandle sys,
|
||||
unsigned argc, vpiHandle*argv)
|
||||
: vvp_wide_fun_core(net, argc)
|
||||
{
|
||||
sys_ = sys;
|
||||
argc_ = argc;
|
||||
argv_ = argv;
|
||||
}
|
||||
|
||||
sfunc_core::~sfunc_core()
|
||||
{
|
||||
}
|
||||
|
||||
void sfunc_core::recv_vec4_from_inputs(unsigned port)
|
||||
{
|
||||
vpiHandle vpi = argv_[port];
|
||||
assert(vpi_get(vpiConstType,vpi) == vpiBinaryConst);
|
||||
|
||||
struct __vpiBinaryConst*obj
|
||||
= (struct __vpiBinaryConst*)vpi;
|
||||
|
||||
obj->bits = value(port);
|
||||
|
||||
invoke_function_();
|
||||
}
|
||||
|
||||
void sfunc_core::recv_real_from_inputs(unsigned port)
|
||||
{
|
||||
vpiHandle vpi = argv_[port];
|
||||
assert(vpi_get(vpiConstType,vpi) == vpiRealConst);
|
||||
|
||||
struct __vpiRealConst*obj
|
||||
= (struct __vpiRealConst*)vpi;
|
||||
|
||||
obj->value = value_r(port);
|
||||
|
||||
invoke_function_();
|
||||
}
|
||||
|
||||
void sfunc_core::invoke_function_()
|
||||
{
|
||||
vpip_execute_vpi_call(0, sys_);
|
||||
}
|
||||
|
||||
static int make_vpi_argv(unsigned argc, vpiHandle*vpi_argv,
|
||||
const char*arg_string)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
const char*cp = arg_string;
|
||||
int return_type = 0;
|
||||
|
||||
switch (*cp) {
|
||||
case 'r': // real result
|
||||
cp += 1;
|
||||
return_type = -vpiRealConst;
|
||||
break;
|
||||
|
||||
case 'v': // vector4_t
|
||||
cp += 1;
|
||||
return_type = strtoul(cp, 0, 10);
|
||||
cp += strspn(cp, "0123456789");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
while (*cp) {
|
||||
assert(idx < argc);
|
||||
|
||||
switch (*cp) {
|
||||
case 'r': // real
|
||||
cp += 1;
|
||||
vpi_argv[idx] = vpip_make_real_const(0.0);
|
||||
break;
|
||||
|
||||
case 'v': { // vector4_t (v<n>)
|
||||
cp += 1;
|
||||
unsigned wid = strtoul(cp, 0, 10);
|
||||
cp += strspn(cp, "0123456789");
|
||||
vpi_argv[idx] = vpip_make_binary_const(wid, "x");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
assert(idx == argc);
|
||||
return return_type;
|
||||
}
|
||||
|
||||
|
||||
void compile_sfunc(char*label, char*name, char*format_string,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vpiHandle*vpi_argv = new vpiHandle[argc];
|
||||
int width_code = make_vpi_argv(argc, vpi_argv, format_string);
|
||||
free(format_string);
|
||||
|
||||
vvp_net_t*ptr = new vvp_net_t;
|
||||
|
||||
vpiHandle sys = vpip_build_vpi_call(name, 0, width_code, ptr,
|
||||
argc, vpi_argv);
|
||||
assert(sys);
|
||||
|
||||
/* Create and connect the functor to the label. */
|
||||
sfunc_core*score = new sfunc_core(ptr, sys, argc, vpi_argv);
|
||||
ptr->fun = score;
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
/* Link the inputs to the functor. */
|
||||
wide_inputs_connect(score, argc, argv);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: sfunc.cc,v $
|
||||
* Revision 1.1 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
*/
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef __sfunc_H
|
||||
#define __sfunc_H
|
||||
/*
|
||||
* Copyright (c) 2006 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
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sfunc.h,v 1.1 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "pointers.h"
|
||||
|
||||
class sfunc_core : public vvp_wide_fun_core {
|
||||
|
||||
public:
|
||||
sfunc_core(vvp_net_t*ptr, vpiHandle sys, unsigned argc, vpiHandle*argv);
|
||||
~sfunc_core();
|
||||
|
||||
private:
|
||||
void recv_vec4_from_inputs(unsigned port);
|
||||
void recv_real_from_inputs(unsigned port);
|
||||
|
||||
void invoke_function_();
|
||||
|
||||
private:
|
||||
vpiHandle sys_;
|
||||
unsigned argc_;
|
||||
vpiHandle*argv_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: sfunc.h,v $
|
||||
* Revision 1.1 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stop.cc,v 1.15 2005/11/25 18:35:38 steve Exp $"
|
||||
#ident "$Id: stop.cc,v 1.16 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -174,7 +174,7 @@ static void cmd_call(unsigned argc, char*argv[])
|
|||
vpi task and execute that call. Free the call structure
|
||||
when we finish. */
|
||||
if (errors == 0) {
|
||||
vpiHandle call_handle = vpip_build_vpi_call(argv[0], 0, 0,
|
||||
vpiHandle call_handle = vpip_build_vpi_call(argv[0], 0, 0, 0,
|
||||
vpi_argc, vpi_argv);
|
||||
if (call_handle == 0)
|
||||
goto out;
|
||||
|
|
@ -505,6 +505,9 @@ void stop_handler(int rc)
|
|||
|
||||
/*
|
||||
* $Log: stop.cc,v $
|
||||
* Revision 1.16 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.15 2005/11/25 18:35:38 steve
|
||||
* stop/continue messages go through MCD for logging.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_const.cc,v 1.35 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: vpi_const.cc,v 1.36 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
|
|
@ -529,8 +529,69 @@ vpiHandle vpip_make_dec_const(int value)
|
|||
}
|
||||
|
||||
|
||||
static int real_get(int code, vpiHandle ref)
|
||||
{
|
||||
|
||||
switch (code) {
|
||||
case vpiConstType:
|
||||
return vpiRealConst;
|
||||
|
||||
case vpiSigned:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiDecConst\n", code);
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void real_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
struct __vpiRealConst*rfp = (struct __vpiRealConst*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiConstant);
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
vp->format = vpiRealVal;
|
||||
case vpiRealVal:
|
||||
vp->value.real = rfp->value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_real_rt = {
|
||||
vpiConstant,
|
||||
real_get,
|
||||
0,
|
||||
real_value,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_real_const(struct __vpiRealConst*obj, double value)
|
||||
{
|
||||
obj->base.vpi_type = &vpip_real_rt;
|
||||
obj->value = value;
|
||||
return &(obj->base);
|
||||
}
|
||||
|
||||
vpiHandle vpip_make_real_const(double value)
|
||||
{
|
||||
struct __vpiRealConst*obj;
|
||||
obj =(struct __vpiRealConst*) malloc(sizeof (struct __vpiRealConst));
|
||||
return vpip_make_real_const(obj, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_const.cc,v $
|
||||
* Revision 1.36 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.35 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_priv.h,v 1.70 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.71 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
|
@ -257,6 +257,9 @@ struct __vpiUserSystf {
|
|||
s_vpi_systf_data info;
|
||||
};
|
||||
|
||||
extern struct __vpiUserSystf* vpip_find_systf(const char*name);
|
||||
|
||||
|
||||
struct __vpiSysTaskCall {
|
||||
struct __vpiHandle base;
|
||||
struct __vpiScope* scope;
|
||||
|
|
@ -268,6 +271,7 @@ struct __vpiSysTaskCall {
|
|||
/* These represent where in the vthread to put the return value. */
|
||||
unsigned vbit;
|
||||
signed vwid;
|
||||
class vvp_net_t*fnet;
|
||||
};
|
||||
|
||||
extern struct __vpiSysTaskCall*vpip_cur_task;
|
||||
|
|
@ -309,6 +313,13 @@ struct __vpiDecConst {
|
|||
vpiHandle vpip_make_dec_const(int value);
|
||||
vpiHandle vpip_make_dec_const(struct __vpiDecConst*obj, int value);
|
||||
|
||||
struct __vpiRealConst {
|
||||
struct __vpiHandle base;
|
||||
double value;
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_real_const(double value);
|
||||
|
||||
/*
|
||||
* This one looks like a constant, but really is a vector in the current
|
||||
* thread.
|
||||
|
|
@ -350,6 +361,7 @@ extern unsigned vpip_module_path_cnt;
|
|||
*/
|
||||
extern vpiHandle vpip_build_vpi_call(const char*name,
|
||||
unsigned vbit, int vwid,
|
||||
class vvp_net_t*fnet,
|
||||
unsigned argc,
|
||||
vpiHandle*argv);
|
||||
|
||||
|
|
@ -432,6 +444,9 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
|
|||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.71 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.70 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
|
|
|||
135
vvp/vpi_tasks.cc
135
vvp/vpi_tasks.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_tasks.cc,v 1.31 2005/09/20 18:34:02 steve Exp $"
|
||||
#ident "$Id: vpi_tasks.cc,v 1.32 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -266,6 +266,92 @@ static vpiHandle sysfunc_put_real_value(vpiHandle ref, p_vpi_value vp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle sysfunc_put_4net_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiSysFuncCall);
|
||||
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
|
||||
unsigned vwid = (unsigned) rfp->vwid;
|
||||
vvp_vector4_t val (vwid);
|
||||
|
||||
switch (vp->format) {
|
||||
|
||||
case vpiIntVal: {
|
||||
long tmp = vp->value.integer;
|
||||
for (unsigned idx = 0 ; idx < vwid ; idx += 1) {
|
||||
val.set_bit(idx, (tmp&1)? BIT4_1 : BIT4_0);
|
||||
tmp >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case vpiVectorVal:
|
||||
|
||||
for (unsigned wdx = 0 ; wdx < vwid ; wdx += 32) {
|
||||
unsigned word = wdx / 32;
|
||||
unsigned long aval = vp->value.vector[word].aval;
|
||||
unsigned long bval = vp->value.vector[word].bval;
|
||||
|
||||
for (unsigned idx = 0 ; (wdx+idx) < vwid ; idx += 1) {
|
||||
int bit = (aval&1) | ((bval<<1)&2);
|
||||
vvp_bit4_t bit4;
|
||||
|
||||
switch (bit) {
|
||||
case 0:
|
||||
bit4 = BIT4_0;
|
||||
break;
|
||||
case 1:
|
||||
bit4 = BIT4_1;
|
||||
break;
|
||||
case 2:
|
||||
bit4 = BIT4_Z;
|
||||
break;
|
||||
case 3:
|
||||
bit4 = BIT4_X;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
val.set_bit(wdx+idx, bit4);
|
||||
|
||||
aval >>= 1;
|
||||
bval >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XXXX format=%d, vwid=%u\n", vp->format, rfp->vwid);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_vec4(rfp->fnet->out, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiSysFuncCall);
|
||||
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
double val;
|
||||
|
||||
switch (vp->format) {
|
||||
|
||||
case vpiRealVal:
|
||||
val = vp->value.real;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_real(rfp->fnet->out, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_rt = {
|
||||
vpiSysFuncCall,
|
||||
|
|
@ -287,6 +373,26 @@ static const struct __vpirt vpip_sysfunc_real_rt = {
|
|||
systask_iter
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_4net_rt = {
|
||||
vpiSysFuncCall,
|
||||
0,
|
||||
systask_get_str,
|
||||
0,
|
||||
sysfunc_put_4net_value,
|
||||
systask_handle,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_rnet_rt = {
|
||||
vpiSysFuncCall,
|
||||
0,
|
||||
systask_get_str,
|
||||
0,
|
||||
sysfunc_put_rnet_value,
|
||||
systask_handle,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
/* **** Manipulate the internal datastructures. **** */
|
||||
|
||||
static struct __vpiUserSystf**def_table = 0;
|
||||
|
|
@ -315,7 +421,7 @@ static struct __vpiUserSystf* allocate_def(void)
|
|||
}
|
||||
|
||||
|
||||
static struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < def_count ; idx += 1)
|
||||
if (strcmp(def_table[idx]->info.tfname, name) == 0)
|
||||
|
|
@ -337,6 +443,7 @@ static struct __vpiUserSystf* vpip_find_systf(const char*name)
|
|||
* vbit is also a non-zero value, the address in thread space of the result.
|
||||
*/
|
||||
vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
class vvp_net_t*fnet,
|
||||
unsigned argc, vpiHandle*argv)
|
||||
{
|
||||
struct __vpiUserSystf*defn = vpip_find_systf(name);
|
||||
|
|
@ -348,7 +455,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
|||
|
||||
switch (defn->info.type) {
|
||||
case vpiSysTask:
|
||||
if (vwid != 0) {
|
||||
if (vwid != 0 || fnet != 0) {
|
||||
fprintf(stderr, "%s: This is a system Task, "
|
||||
"you cannot call it as a Function\n", name);
|
||||
return 0;
|
||||
|
|
@ -357,7 +464,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
|||
break;
|
||||
|
||||
case vpiSysFunc:
|
||||
if (vwid == 0) {
|
||||
if (vwid == 0 && fnet == 0) {
|
||||
fprintf(stderr, "%s: This is a system Function, "
|
||||
"you cannot call it as a Task\n", name);
|
||||
return 0;
|
||||
|
|
@ -376,18 +483,20 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
|||
break;
|
||||
|
||||
case vpiSysFunc:
|
||||
if (vwid > 0) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_rt;
|
||||
if (fnet && vwid == -vpiRealConst) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_rnet_rt;
|
||||
|
||||
} else switch (vwid) {
|
||||
} else if (fnet && vwid > 0) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_4net_rt;
|
||||
|
||||
case -vpiRealConst:
|
||||
} else if (vwid == -vpiRealConst) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_real_rt;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
} else if (vwid > 0) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_rt;
|
||||
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -398,6 +507,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
|||
obj->args = argv;
|
||||
obj->vbit = vbit;
|
||||
obj->vwid = vwid;
|
||||
obj->fnet = fnet;
|
||||
obj->userdata = 0;
|
||||
|
||||
/* If there is a compiletf function, call it here. */
|
||||
|
|
@ -487,6 +597,9 @@ void* vpi_get_userdata(vpiHandle ref)
|
|||
|
||||
/*
|
||||
* $Log: vpi_tasks.cc,v $
|
||||
* Revision 1.32 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.31 2005/09/20 18:34:02 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.cc,v 1.52 2006/03/15 19:15:34 steve Exp $"
|
||||
#ident "$Id: vvp_net.cc,v 1.53 2006/06/18 04:15:50 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
|
|
@ -1709,12 +1709,14 @@ vvp_wide_fun_core::vvp_wide_fun_core(vvp_net_t*net, unsigned nports)
|
|||
{
|
||||
ptr_ = net;
|
||||
nports_ = nports;
|
||||
port_values_ = new vvp_vector4_t [nports_];
|
||||
port_values_ = 0;
|
||||
port_rvalues_ = 0;
|
||||
}
|
||||
|
||||
vvp_wide_fun_core::~vvp_wide_fun_core()
|
||||
{
|
||||
delete[]port_values_;
|
||||
if (port_values_) delete[]port_values_;
|
||||
if (port_rvalues_) delete[]port_rvalues_;
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::propagate_vec4(const vvp_vector4_t&bit,
|
||||
|
|
@ -1735,17 +1737,39 @@ unsigned vvp_wide_fun_core::port_count() const
|
|||
vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx)
|
||||
{
|
||||
assert(idx < nports_);
|
||||
assert(port_values_);
|
||||
return port_values_[idx];
|
||||
}
|
||||
|
||||
double vvp_wide_fun_core::value_r(unsigned idx)
|
||||
{
|
||||
assert(idx < nports_);
|
||||
return port_rvalues_? port_rvalues_[idx] : 0.0;
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::recv_real_from_inputs(unsigned p)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::dispatch_vec4_from_input_(unsigned port,
|
||||
vvp_vector4_t bit)
|
||||
{
|
||||
assert(port < nports_);
|
||||
if (port_values_ == 0) port_values_ = new vvp_vector4_t [nports_];
|
||||
port_values_[port] = bit;
|
||||
recv_vec4_from_inputs(port);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::dispatch_real_from_input_(unsigned port,
|
||||
double bit)
|
||||
{
|
||||
assert(port < nports_);
|
||||
if (port_rvalues_ == 0) port_rvalues_ = new double[nports_];
|
||||
port_rvalues_[port] = bit;
|
||||
recv_real_from_inputs(port);
|
||||
}
|
||||
|
||||
vvp_wide_fun_t::vvp_wide_fun_t(vvp_wide_fun_core*c, unsigned base)
|
||||
: core_(c), port_base_(base)
|
||||
{
|
||||
|
|
@ -1761,6 +1785,12 @@ void vvp_wide_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
|||
core_->dispatch_vec4_from_input_(pidx, bit);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit)
|
||||
{
|
||||
unsigned pidx = port_base_ + port.port();
|
||||
core_->dispatch_real_from_input_(pidx, bit);
|
||||
}
|
||||
|
||||
|
||||
/* **** vvp_scalar_t methods **** */
|
||||
|
||||
|
|
@ -2163,6 +2193,9 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
|
|||
|
||||
/*
|
||||
* $Log: vvp_net.cc,v $
|
||||
* Revision 1.53 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.52 2006/03/15 19:15:34 steve
|
||||
* const/non-const clash.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.h,v 1.50 2006/03/08 05:29:42 steve Exp $"
|
||||
#ident "$Id: vvp_net.h,v 1.51 2006/06/18 04:15:50 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include <stddef.h>
|
||||
|
|
@ -918,15 +918,19 @@ class vvp_wide_fun_core : public vvp_net_fun_t {
|
|||
protected:
|
||||
void propagate_vec4(const vvp_vector4_t&bit, vvp_time64_t delay =0);
|
||||
unsigned port_count() const;
|
||||
|
||||
vvp_vector4_t& value(unsigned);
|
||||
double value_r(unsigned);
|
||||
|
||||
private:
|
||||
// the derived class implements this to receive an indication
|
||||
// that one of the port input values changed.
|
||||
virtual void recv_vec4_from_inputs(unsigned port) =0;
|
||||
virtual void recv_real_from_inputs(unsigned port);
|
||||
|
||||
friend class vvp_wide_fun_t;
|
||||
void dispatch_vec4_from_input_(unsigned port, vvp_vector4_t bit);
|
||||
void dispatch_real_from_input_(unsigned port, double bit);
|
||||
|
||||
private:
|
||||
// Back-point to the vvp_net_t that points to me.
|
||||
|
|
@ -934,7 +938,7 @@ class vvp_wide_fun_core : public vvp_net_fun_t {
|
|||
// Structure to track the input values from the input functors.
|
||||
unsigned nports_;
|
||||
vvp_vector4_t*port_values_;
|
||||
|
||||
double*port_rvalues_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -950,6 +954,7 @@ class vvp_wide_fun_t : public vvp_net_fun_t {
|
|||
~vvp_wide_fun_t();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
|
||||
private:
|
||||
vvp_wide_fun_core*core_;
|
||||
|
|
@ -1008,6 +1013,9 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
|||
|
||||
/*
|
||||
* $Log: vvp_net.h,v $
|
||||
* Revision 1.51 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.50 2006/03/08 05:29:42 steve
|
||||
* Add support for logic parameters.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue