Add support for LPM_UFUNC user defined functions.

This commit is contained in:
steve 2005-03-18 02:56:03 +00:00
parent 0f914bf35a
commit 53da6e9a33
16 changed files with 375 additions and 302 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.155 2005/03/13 01:26:48 steve Exp $" #ident "$Id: elab_net.cc,v 1.156 2005/03/18 02:56:03 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1227,7 +1227,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) { for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) {
const NetNet* port_reg = def->port(idx); const NetNet* port_reg = def->port(idx);
NetNet*tmp = parms_[idx]->elaborate_net(des, scope, NetNet*tmp = parms_[idx]->elaborate_net(des, scope,
port_reg->pin_count(), port_reg->vector_width(),
0, 0, 0, 0, 0, 0,
Link::STRONG, Link::STRONG,
Link::STRONG); Link::STRONG);
@ -1256,21 +1256,19 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
of the function net. */ of the function net. */
NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, NetNet::WIRE,
def->return_sig()->pin_count()); def->return_sig()->vector_width());
osig->local_flag(true); osig->local_flag(true);
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) connect(net->pin(0), osig->pin(0));
connect(net->port_pin(0, idx), osig->pin(idx));
/* Connect the parameter pins to the parameter expressions. */ /* Connect the parameter pins to the parameter expressions. */
for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) { for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) {
const NetNet* port = def->port(idx); const NetNet* port = def->port(idx);
NetNet*cur = eparms[idx]; NetNet*cur = eparms[idx];
NetNet*tmp = pad_to_width(des, cur, port->pin_count()); NetNet*tmp = pad_to_width(des, cur, port->vector_width());
for (unsigned pin = 0 ; pin < port->pin_count() ; pin += 1) connect(net->pin(idx+1), tmp->pin(0));
connect(net->port_pin(idx+1, pin), tmp->pin(pin));
} }
return osig; return osig;
@ -2492,6 +2490,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $Log: elab_net.cc,v $
* Revision 1.156 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.155 2005/03/13 01:26:48 steve * Revision 1.155 2005/03/13 01:26:48 steve
* UPdate elabrate continuous assighn of string to net. * UPdate elabrate continuous assighn of string to net.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.146 2005/03/09 04:53:40 steve Exp $" #ident "$Id: ivl_target.h,v 1.147 2005/03/18 02:56:03 steve Exp $"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -866,6 +866,25 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1) * ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1)
* the shift distance. The vector input is the same width as the * the shift distance. The vector input is the same width as the
* output, but the distance has its own width. * output, but the distance has its own width.
*
* - 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
* function are connected to the net, as is the output.
*
* The function definition is associated with a scope, and the
* ivl_lpm_define fuction returns the scope that is that definition.
* See the ivl_scope_* fuctions for how to get at the actual
* definition.
*
* As with many LPM nodes, the ivl_lpm_q function returns the nexus
* for the signal function return value. The width of this nexus must
* exactly match the width of the device from ivl_lpm_width.
*
* The ivl_lpm_data function retrives the nexa for all the input
* ports. The ivl_lpm_size function returns the number of inputs for
* the device, and the ivl_lpm_data() function index argument selects
* the port to retrieve. Each port is sized independently.
*/ */
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
@ -891,14 +910,19 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */ /* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT /* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB */ IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */ /* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
#if 0
/* IVL_LPM_UFUNC */ /* IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx); extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
#endif
#if 0
/* IVL_LPM_UFUNC */ /* IVL_LPM_UFUNC */
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx); 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_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
IVL_LPM_SUB IVL_LPM_UFUNC */ IVL_LPM_SUB IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
@ -906,7 +930,7 @@ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
extern unsigned ivl_lpm_selects(ivl_lpm_t net); extern unsigned ivl_lpm_selects(ivl_lpm_t net);
/* IVL_LPM_MUX IVL_LPM_RAM */ /* IVL_LPM_MUX IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT */ /* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */
extern unsigned ivl_lpm_size(ivl_lpm_t net); extern unsigned ivl_lpm_size(ivl_lpm_t net);
/* IVL_LPM_RAM */ /* IVL_LPM_RAM */
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
@ -1556,6 +1580,9 @@ _END_DECL
/* /*
* $Log: ivl_target.h,v $ * $Log: ivl_target.h,v $
* Revision 1.147 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.146 2005/03/09 04:53:40 steve * Revision 1.146 2005/03/09 04:53:40 steve
* Generate code for new form of memory ports. * Generate code for new form of memory ports.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_func.cc,v 1.6 2004/05/31 23:34:37 steve Exp $" #ident "$Id: net_func.cc,v 1.7 2005/03/18 02:56:03 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -26,42 +26,25 @@
# include "PExpr.h" # include "PExpr.h"
# include <iostream> # include <iostream>
static unsigned count_def_pins(const NetFuncDef*def) /*
{ * To make a NetUserFunc device, make as many pins as there are ports
assert(def->return_sig()); * in the function. Get the port count from the function definition,
* which accounts for all the inputs, plus one for the phantom output
unsigned sum = def->return_sig()->pin_count(); * that is the result.
for (unsigned idx = 0 ; idx < def->port_count() ; idx += 1) */
sum += def->port(idx)->pin_count();
return sum;
}
NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d) NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
: NetNode(s, n, count_def_pins(d->func_def())), : NetNode(s, n, d->func_def()->port_count()+1),
def_(d) def_(d)
{ {
NetFuncDef*def = def_->func_def(); pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(def_->basename(), 0);
unsigned port_wid = port_width(0); for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
for (unsigned idx = 0 ; idx < port_wid ; idx += 1) {
pin(idx).set_dir(Link::OUTPUT);
pin(idx).set_name(def_->basename(), idx);
}
unsigned pin_base = port_wid; pin(idx).set_dir(Link::INPUT);
for (unsigned idx = 1 ; idx < port_count() ; idx += 1) { pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
const NetNet*port_sig = def->port(idx-1); pin(idx).drive1(Link::HIGHZ);
unsigned bits = port_width(idx);
for (unsigned bit = 0; bit < bits; bit += 1) {
pin(pin_base+bit).set_dir(Link::INPUT);
pin(pin_base+bit).set_name(port_sig->name(), bit);
pin(pin_base+bit).drive0(Link::HIGHZ);
pin(pin_base+bit).drive1(Link::HIGHZ);
}
pin_base += bits;
} }
} }
@ -69,11 +52,6 @@ NetUserFunc::~NetUserFunc()
{ {
} }
unsigned NetUserFunc::port_count() const
{
return def_->func_def()->port_count() + 1;
}
unsigned NetUserFunc::port_width(unsigned port) const unsigned NetUserFunc::port_width(unsigned port) const
{ {
NetFuncDef*def = def_->func_def(); NetFuncDef*def = def_->func_def();
@ -82,44 +60,16 @@ unsigned NetUserFunc::port_width(unsigned port) const
if (port == 0) { if (port == 0) {
const NetNet*sig = def->return_sig(); const NetNet*sig = def->return_sig();
assert(sig); assert(sig);
return sig->pin_count(); return sig->vector_width();
} }
port -= 1; port -= 1;
assert(port < def->port_count()); assert(port < def->port_count());
const NetNet*port_sig = def->port(port); const NetNet*port_sig = def->port(port);
return port_sig->pin_count(); return port_sig->vector_width();
} }
Link& NetUserFunc::port_pin(unsigned port, unsigned idx)
{
NetFuncDef*def = def_->func_def();
unsigned pin_base = 0;
const NetNet*port_sig;
if (port == 0)
return pin(idx);
port_sig = def->return_sig();
pin_base += port_sig->pin_count();
port -= 1;
assert(port < def->port_count());
for (unsigned port_idx = 0 ; port_idx < port ; port_idx += 1) {
port_sig = def->port(port_idx);
pin_base += port_sig->pin_count();
}
port_sig = def->port(port);
assert(idx < port_sig->pin_count());
assert((pin_base+idx) < pin_count());
return pin(pin_base+idx);
}
const NetScope* NetUserFunc::def() const const NetScope* NetUserFunc::def() const
{ {
return def_; return def_;
@ -164,6 +114,9 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
/* /*
* $Log: net_func.cc,v $ * $Log: net_func.cc,v $
* Revision 1.7 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.6 2004/05/31 23:34:37 steve * Revision 1.6 2004/05/31 23:34:37 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * function return values to allow for better

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.337 2005/03/12 06:43:36 steve Exp $" #ident "$Id: netlist.h,v 1.338 2005/03/18 02:56:03 steve Exp $"
#endif #endif
/* /*
@ -960,7 +960,8 @@ class NetReplicate : public NetNode {
/* /*
* This node represents the call of a user defined function in a * This node represents the call of a user defined function in a
* structural context. * structural context. The pin count is the same as the port count,
* with pin0 the return value.
*/ */
class NetUserFunc : public NetNode { class NetUserFunc : public NetNode {
@ -968,9 +969,7 @@ class NetUserFunc : public NetNode {
NetUserFunc(NetScope*s, perm_string n, NetScope*def); NetUserFunc(NetScope*s, perm_string n, NetScope*def);
~NetUserFunc(); ~NetUserFunc();
unsigned port_count() const;
unsigned port_width(unsigned port) const; unsigned port_width(unsigned port) const;
Link& port_pin(unsigned port, unsigned idx);
const NetScope* def() const; const NetScope* def() const;
@ -3417,6 +3416,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.338 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.337 2005/03/12 06:43:36 steve * Revision 1.337 2005/03/12 06:43:36 steve
* Update support for LPM_MOD. * Update support for LPM_MOD.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.120 2005/03/09 05:52:04 steve Exp $" #ident "$Id: t-dll-api.cc,v 1.121 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -798,6 +798,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(idx == 0); assert(idx == 0);
return net->u_.repeat.a; return net->u_.repeat.a;
case IVL_LPM_UFUNC:
// Skip the return port.
assert(idx < (net->u_.ufunc.ports-1));
return net->u_.ufunc.pins[idx+1];
default: default:
assert(0); assert(0);
return 0; return 0;
@ -828,8 +833,10 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
} }
} }
#if 0
extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx) extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
{ {
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_data2." << endl;
assert(net); assert(net);
switch (net->type) { switch (net->type) {
@ -848,7 +855,8 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
return 0; return 0;
} }
} }
#endif
#if 0
extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx) extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
{ {
assert(net); assert(net);
@ -862,6 +870,7 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
return 0; return 0;
} }
} }
#endif
/* /*
* This function returns the hierarchical name for the LPM device. The * This function returns the hierarchical name for the LPM device. The
@ -942,8 +951,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
return net->u_.shift.q; return net->u_.shift.q;
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
assert(idx < net->u_.ufunc.port_wid[0]); assert(idx == 0);
return net->u_.ufunc.pins[idx]; return net->u_.ufunc.pins[0];
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
return net->u_.concat.pins[0]; return net->u_.concat.pins[0];
@ -1101,7 +1110,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
return net->u_.shift.width; return net->u_.shift.width;
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
return net->u_.ufunc.port_wid[0]; return net->u_.ufunc.width;
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
return net->u_.concat.width; return net->u_.concat.width;
case IVL_LPM_PART_VP: case IVL_LPM_PART_VP:
@ -1991,6 +2000,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/* /*
* $Log: t-dll-api.cc,v $ * $Log: t-dll-api.cc,v $
* Revision 1.121 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.120 2005/03/09 05:52:04 steve * Revision 1.120 2005/03/09 05:52:04 steve
* Handle case inequality in netlists. * Handle case inequality in netlists.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.144 2005/03/12 06:43:36 steve Exp $" #ident "$Id: t-dll.cc,v 1.145 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1012,28 +1012,25 @@ bool dll_target::net_function(const NetUserFunc*net)
/* Save information about the ports in the ivl_lpm_s /* Save information about the ports in the ivl_lpm_s
structure. Note that port 0 is the return value. */ structure. Note that port 0 is the return value. */
obj->u_.ufunc.ports = net->port_count(); obj->u_.ufunc.ports = net->pin_count();
obj->u_.ufunc.port_wid = new unsigned[net->port_count()];
for (unsigned idx = 0 ; idx < obj->u_.ufunc.ports ; idx += 1) assert(net->pin_count() >= 1);
obj->u_.ufunc.port_wid[idx] = net->port_width(idx); obj->u_.ufunc.width = net->port_width(0);
/* Now collect all the pins and connect them to the nexa of /* Now collect all the pins and connect them to the nexa of
the net. The output pins have strong drive, and the the net. The output pins have strong drive, and the
remaining input pins are HiZ. */ remaining input pins are HiZ. */
unsigned pin_count = net->pin_count(); obj->u_.ufunc.pins = new ivl_nexus_t[net->pin_count()];
obj->u_.ufunc.pins = new ivl_nexus_t[pin_count];
for (unsigned idx = 0 ; idx < pin_count ; idx += 1) { for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus(); const Nexus*nex = net->pin(idx).nexus();
assert(nex->t_cookie()); assert(nex->t_cookie());
ivl_nexus_t nn = (ivl_nexus_t)nex->t_cookie(); ivl_nexus_t nn = (ivl_nexus_t)nex->t_cookie();
assert(nn); assert(nn);
obj->u_.ufunc.pins[idx] = nn; obj->u_.ufunc.pins[idx] = nn;
ivl_drive_t drive = idx < obj->u_.ufunc.port_wid[0] ivl_drive_t drive = idx == 0 ? IVL_DR_STRONG : IVL_DR_HiZ;
? IVL_DR_STRONG
: IVL_DR_HiZ;
nexus_lpm_add(obj->u_.ufunc.pins[idx], obj, idx, drive, drive); nexus_lpm_add(obj->u_.ufunc.pins[idx], obj, idx, drive, drive);
} }
@ -2136,6 +2133,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.145 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.144 2005/03/12 06:43:36 steve * Revision 1.144 2005/03/12 06:43:36 steve
* Update support for LPM_MOD. * Update support for LPM_MOD.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.122 2005/02/19 02:43:39 steve Exp $" #ident "$Id: t-dll.h,v 1.123 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "target.h" # include "target.h"
@ -362,7 +362,7 @@ struct ivl_lpm_s {
struct ivl_lpm_ufunc_s { struct ivl_lpm_ufunc_s {
ivl_scope_t def; ivl_scope_t def;
unsigned ports; unsigned ports;
unsigned *port_wid; unsigned width;
ivl_nexus_t*pins; ivl_nexus_t*pins;
} ufunc; } ufunc;
} u_; } u_;
@ -685,6 +685,9 @@ struct ivl_variable_s {
/* /*
* $Log: t-dll.h,v $ * $Log: t-dll.h,v $
* Revision 1.123 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.122 2005/02/19 02:43:39 steve * Revision 1.122 2005/02/19 02:43:39 steve
* Support shifts and divide. * Support shifts and divide.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.116 2005/03/12 06:43:36 steve Exp $" #ident "$Id: stub.c,v 1.117 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -604,6 +604,33 @@ static void show_lpm_sub(ivl_lpm_t net)
show_lpm_arithmetic_pins(net); show_lpm_arithmetic_pins(net);
} }
static void show_lpm_ufunc(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned ports = ivl_lpm_size(net);
ivl_scope_t def = ivl_lpm_define(net);
ivl_nexus_t nex;
unsigned idx;
fprintf(out, " LPM_UFUNC %s: <call=%s, width=%u, ports=%u>\n",
ivl_lpm_basename(net), ivl_scope_name(def), width, 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>\n", idx,
ivl_nexus_name(nex), width_of_nexus(nex));
}
}
static void show_lpm(ivl_lpm_t net) static void show_lpm(ivl_lpm_t net)
{ {
unsigned idx; unsigned idx;
@ -736,6 +763,10 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_repeat(net); show_lpm_repeat(net);
break; break;
case IVL_LPM_UFUNC:
show_lpm_ufunc(net);
break;
default: default:
fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n", fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n",
ivl_lpm_type(net), ivl_lpm_type(net),
@ -1185,6 +1216,9 @@ int target_design(ivl_design_t des)
/* /*
* $Log: stub.c,v $ * $Log: stub.c,v $
* Revision 1.117 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.116 2005/03/12 06:43:36 steve * Revision 1.116 2005/03/12 06:43:36 steve
* Update support for LPM_MOD. * Update support for LPM_MOD.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.121 2005/03/09 05:52:04 steve Exp $" #ident "$Id: vvp_scope.c,v 1.122 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -1714,8 +1714,7 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
static void draw_lpm_ufunc(ivl_lpm_t net) static void draw_lpm_ufunc(ivl_lpm_t net)
{ {
unsigned idx, bit; unsigned idx;
char comma;
ivl_scope_t def = ivl_lpm_define(net); ivl_scope_t def = ivl_lpm_define(net);
fprintf(vvp_out, "L_%p .ufunc TD_%s, %u", net, fprintf(vvp_out, "L_%p .ufunc TD_%s, %u", net,
@ -1723,15 +1722,10 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
ivl_lpm_width(net)); ivl_lpm_width(net));
/* Print all the net signals that connect to the input of the /* Print all the net signals that connect to the input of the
function. Print them one per line, for convenience. */ function. */
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) { for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
comma = ' '; fprintf(vvp_out, ", ");
fprintf(vvp_out, ",\n"); draw_input_from_net(ivl_lpm_data(net, idx));
for (bit = 0 ; bit < ivl_lpm_data2_width(net, idx) ; bit += 1) {
fprintf(vvp_out, "%c ", comma);
draw_input_from_net(ivl_lpm_data2(net, idx, bit));
comma = ',';
}
} }
@ -1741,32 +1735,23 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
receive the input values given in the previous list. */ receive the input values given in the previous list. */
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) { for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
ivl_signal_t psig = ivl_scope_port(def, idx+1); ivl_signal_t psig = ivl_scope_port(def, idx+1);
comma = ' ';
if (idx == 0) if (idx == 0)
fprintf(vvp_out, "\n("); fprintf(vvp_out, " (");
else else
fprintf(vvp_out, ",\n"); fprintf(vvp_out, ", ");
for (bit = 0 ; bit < ivl_signal_pins(psig) ; bit += 1) { fprintf(vvp_out, "V_%s", vvp_signal_label(psig));
fprintf(vvp_out, "%c V_%s[%u]", comma,
vvp_signal_label(psig), bit);
comma = ',';
}
} }
fprintf(vvp_out, ")\n"); fprintf(vvp_out, ")");
/* Finally, print the reference to the signal from which the
result is collected. */
{ ivl_signal_t psig = ivl_scope_port(def, 0); { ivl_signal_t psig = ivl_scope_port(def, 0);
assert(ivl_lpm_width(net) == ivl_signal_pins(psig)); assert(ivl_lpm_width(net) == ivl_signal_width(psig));
comma = ' '; fprintf(vvp_out, " V_%s", vvp_signal_label(psig));
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
fprintf(vvp_out, "%c V_%s[%u]", comma,
vvp_signal_label(psig),
idx);
comma = ',';
}
} }
fprintf(vvp_out, ";\n"); fprintf(vvp_out, ";\n");
@ -2022,6 +2007,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/* /*
* $Log: vvp_scope.c,v $ * $Log: vvp_scope.c,v $
* Revision 1.122 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.121 2005/03/09 05:52:04 steve * Revision 1.121 2005/03/09 05:52:04 steve
* Handle case inequality in netlists. * Handle case inequality in netlists.
* *

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com) * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* *
* $Id: README.txt,v 1.60 2005/03/09 05:52:04 steve Exp $ * $Id: README.txt,v 1.61 2005/03/18 02:56:04 steve Exp $
*/ */
VVP SIMULATION ENGINE VVP SIMULATION ENGINE
@ -609,8 +609,26 @@ STRUCTURAL FUNCTION CALLS:
The .ufunc statement defines a call to a user defined function. The .ufunc statement defines a call to a user defined function.
<label> .ufunc ; <label> .ufunc <flabel>, <wid>, <isymbols> ( <psymbols> ) <rsymbol> ;
The <flabel> is the code label for the first instruction of the
function implementation. This is code that the simulator will branch
to.
The <wid> is the width of the output vector in bits.
The <isymbols> is a list of net symbols for each of the inputs to the
function. These are points in the net, and the ufunc device watches
these nets for input changes.
The <psymbols> list is exactly the same size as the <isymbols>
list. The <psymbols> are variables that represent the input ports for
the function. The ufunc performs an assignment to these variables
before calling the function.
Finally, the <rsymbol> is the variable within the function where the
result will be found when the function code ends. This value is picked
up and propagated to the output of the functor.
THREAD STATEMENTS: THREAD STATEMENTS:

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: compile.h,v 1.65 2005/03/09 05:52:04 steve Exp $" #ident "$Id: compile.h,v 1.66 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include <stdio.h> # include <stdio.h>
@ -161,11 +161,14 @@ extern void compile_param_string(char*label, char*name,
/* /*
* This function schedules a lookup of an indexed label. The ref * This function schedules a lookup of an indexed label. The ref
* points to the vvp_ipoint_t that receives the result. The result may * points to the vvp_net_t that receives the result. The result may
* be assigned later, if the symbol is defined later in the source * be assigned later, if the symbol is defined later in the source
* file, so the memory that ref points to must persist. * file, so the memory that ref points to must persist.
*
* The text for the label will be deleted by this function, or the
* cleanup that completes the binding.
*/ */
extern void functor_ref_lookup(vvp_ipoint_t *ref, char*lab, unsigned idx); extern void functor_ref_lookup(vvp_net_t**ref, char*lab);
/* /*
* This function schedules a lookup of the labeled instruction. The * This function schedules a lookup of the labeled instruction. The
@ -212,7 +215,7 @@ extern void compile_memory_init(char *memid, unsigned idx, long val);
extern void compile_ufunc(char*label, char*code, unsigned wid, extern void compile_ufunc(char*label, char*code, unsigned wid,
unsigned argc, struct symb_s*argv, unsigned argc, struct symb_s*argv,
unsigned portc, struct symb_s*portv, unsigned portc, struct symb_s*portv,
unsigned retc, struct symb_s*retv); struct symb_s retv);
/* /*
* The compile_event function takes the parts of the event statement * The compile_event function takes the parts of the event statement
@ -297,6 +300,9 @@ extern void compile_net(char*label, char*name,
/* /*
* $Log: compile.h,v $ * $Log: compile.h,v $
* Revision 1.66 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.65 2005/03/09 05:52:04 steve * Revision 1.65 2005/03/09 05:52:04 steve
* Handle case inequality in netlists. * Handle case inequality in netlists.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.69 2005/03/09 05:52:04 steve Exp $" #ident "$Id: parse.y,v 1.70 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "parse_misc.h" # include "parse_misc.h"
@ -171,11 +171,11 @@ statement
bits in the symbols list change. */ bits in the symbols list change. */
| T_LABEL K_UFUNC T_SYMBOL ',' T_NUMBER ',' symbols | T_LABEL K_UFUNC T_SYMBOL ',' T_NUMBER ',' symbols
'(' symbols ')' symbols ';' '(' symbols ')' symbol ';'
{ compile_ufunc($1, $3, $5, { compile_ufunc($1, $3, $5,
$7.cnt, $7.vect, $7.cnt, $7.vect,
$9.cnt, $9.vect, $9.cnt, $9.vect,
$11.cnt, $11.vect); } $11); }
/* Resolver statements are very much like functors. They are /* Resolver statements are very much like functors. They are
compiled to functors of a different mode. */ compiled to functors of a different mode. */
@ -679,6 +679,9 @@ int compile_design(const char*path)
/* /*
* $Log: parse.y,v $ * $Log: parse.y,v $
* Revision 1.70 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.69 2005/03/09 05:52:04 steve * Revision 1.69 2005/03/09 05:52:04 steve
* Handle case inequality in netlists. * Handle case inequality in netlists.
* *

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002-2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2005 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ufunc.cc,v 1.5 2004/12/11 02:31:30 steve Exp $" #ident "$Id: ufunc.cc,v 1.6 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "compile.h" # include "compile.h"
@ -39,34 +39,65 @@
#include <windows.h> #include <windows.h>
#endif #endif
ufunc_core::ufunc_core(unsigned ow, vvp_ipoint_t ob, vvp_ipoint_t*op, ufunc_core::ufunc_core(unsigned owid, vvp_net_t*ptr,
unsigned np, vvp_ipoint_t*p, unsigned nports, vvp_net_t**ports,
vvp_code_t start_address, vvp_code_t sa, struct __vpiScope*run_scope,
struct __vpiScope*run_scope) char*result_label)
: owid_(ow), obase_(ob), oports_(op), nports_(np), ports_(p)
{ {
owid_ = owid;
onet_ = ptr;
nports_ = nports;
ports_ = ports;
port_values_ = new vvp_vector4_t[nports];
code_ = sa;
thread_ = 0; thread_ = 0;
scope_ = run_scope; scope_ = run_scope;
code_ = start_address;
ibits_ = new unsigned char[(nports_+3) / 4]; functor_ref_lookup(&result_, result_label);
memset(ibits_, 0xaa, (nports_+3) / 4);
} }
ufunc_core::~ufunc_core() ufunc_core::~ufunc_core()
{ {
delete[] ports_; delete[]port_values_;
} }
void ufunc_core::set_bit(unsigned port_idx, unsigned val) /*
* This method is called by the %fork_ufunc function to prepare the
* input variables of the function for execution. The method copies
* the input values collected by the core to the variables.
*/
void ufunc_core::assign_bits_to_ports(void)
{ {
unsigned idx = port_idx / 4; for (unsigned idx = 0 ; idx < nports_ ; idx += 1) {
unsigned pp = port_idx % 4; vvp_net_t*net = ports_[idx];
vvp_net_ptr_t pp (net, 0);
net->fun->recv_vec4(pp, port_values_[idx]);
}
}
static const unsigned char mask[4] = {0xfc, 0xf3, 0xcf, 0x3f}; /*
* This method is called by the %join_ufunc instruction to copy the
* result from the return code variable and deliver it to the output
* of the functor, back into the netlist.
*/
void ufunc_core::finish_thread(vthread_t thr)
{
thread_ = 0;
ibits_[idx] &= mask[pp]; vvp_fun_signal*sig = reinterpret_cast<vvp_fun_signal*>(result_->fun);
ibits_[idx] |= (val&3) << pp*2;
vvp_send_vec4(onet_->out, sig->vec4_value());
}
/*
* The recv_vec4 methods of the input functors call this to assign the
* input value to the port of the functor. I save the input value and
* arrange for the function to be called.
*/
void ufunc_core::recv_vec4_from_inputs(unsigned port, vvp_vector4_t bit)
{
assert(port < nports_);
port_values_[port] = bit;
if (thread_ == 0) { if (thread_ == 0) {
thread_ = vthread_new(code_, scope_); thread_ = vthread_new(code_, scope_);
@ -74,100 +105,43 @@ void ufunc_core::set_bit(unsigned port_idx, unsigned val)
} }
} }
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ}; ufunc_input_functor::ufunc_input_functor(ufunc_core*c, unsigned base)
: core_(c), port_base_(base)
void ufunc_core::assign_bits_to_ports(void)
{ {
for (unsigned idx = 0 ; idx < nports_ ; idx += 1) {
unsigned bit_val = ibits_[idx/4] >> (idx%4)*2;
bit_val &= 3;
functor_set(ports_[idx], bit_val, strong_values[bit_val], true);
}
} }
void ufunc_core::finish_thread(vthread_t thr) ufunc_input_functor::~ufunc_input_functor()
{ {
assert(thread_ == thr);
thread_ = 0;
for (unsigned idx = 0 ; idx < owid_ ; idx += 1) {
unsigned val = functor_get(oports_[idx]);
vvp_ipoint_t ptr = ipoint_index(obase_, idx);
functor_set(ptr, val, strong_values[val], false);
}
} }
/* void ufunc_input_functor::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
* There is an instance of ufunc_output_functor_s for each output bit
* of the function. This is the functor that passes the output bits to
* the rest of the design. The functor simply puts its input to its
* output.
*/
struct ufunc_output_functor_s : public functor_s {
void set(vvp_ipoint_t, bool push, unsigned val, unsigned str = 0);
};
void ufunc_output_functor_s::set(vvp_ipoint_t, bool push, unsigned
val, unsigned str)
{ {
put_oval(val, push); unsigned pidx = port_base_ + port.port();
} core_->recv_vec4_from_inputs(pidx, bit);
struct ufunc_input_functor_s : public functor_s {
void set(vvp_ipoint_t, bool push, unsigned val, unsigned str = 0);
unsigned core_base_;
ufunc_core*core_;
};
void ufunc_input_functor_s::set(vvp_ipoint_t ptr, bool,
unsigned val, unsigned str)
{
unsigned pp = ipoint_port(ptr);
core_->set_bit(core_base_+pp, val);
} }
/* /*
* This function compiles the .ufunc statement that is discovered in * This function compiles the .ufunc statement that is discovered in
* the source file. Create all the functors and the thread, and * the source file. Create all the functors and the thread, and
* connect them all up. * connect them all up.
*
* The argv list is a list of the inputs to the function.
*
* The portv list is a list of variables that the function reads as
* inputs. The core assigns values to these nets as part of the startup.
*/ */
void compile_ufunc(char*label, char*code, unsigned wid, void compile_ufunc(char*label, char*code, unsigned wid,
unsigned argc, struct symb_s*argv, unsigned argc, struct symb_s*argv,
unsigned portc, struct symb_s*portv, unsigned portc, struct symb_s*portv,
unsigned retc, struct symb_s*retv) struct symb_s retv)
{ {
#if 0 /* The input argument list and port list must have the same
/* Create an array of vvp_ipoint_t pointers, that point to the sizes, since internally we will be mapping the inputs list
.var bits of the function ports. Do this for the input to the ports list. */
ports and the output port. */
assert(argc == portc); assert(argc == portc);
vvp_ipoint_t* ports = new vvp_ipoint_t [portc];
for (unsigned idx = 0 ; idx < portc ; idx += 1) { struct __vpiScope*run_scope = vpip_peek_current_scope();
functor_ref_lookup(ports+idx, portv[idx].text, portv[idx].idx); assert(run_scope);
}
assert(retc == wid);
vvp_ipoint_t* rets = new vvp_ipoint_t [retc];
for (unsigned idx = 0 ; idx < retc ; idx += 1) {
functor_ref_lookup(rets+idx, retv[idx].text, retv[idx].idx);
}
/* Create enough output functors for the output bits of the
function. */
vvp_ipoint_t obase = functor_allocate(wid);
struct ufunc_output_functor_s*fpa
= new struct ufunc_output_functor_s[wid];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(obase,idx);
functor_define(ptr, fpa+idx);
}
define_functor_symbol(label, obase);
/* Construct some phantom code that is the thread of the /* Construct some phantom code that is the thread of the
function call. The first instruction, at the start_address function call. The first instruction, at the start_address
@ -202,43 +176,54 @@ void compile_ufunc(char*label, char*code, unsigned wid,
codep->opcode = &of_END; codep->opcode = &of_END;
} }
/* Run through the function ports (which are related to but
/* Create the function core object that references the output not the same as the input ports) and arrange for their
functors and the function ports. The input functors will binding. */
point to this core to deliver input. */ vvp_net_t**ports = new vvp_net_t*[portc];
ufunc_core*core = new ufunc_core(wid, obase, rets, for (unsigned idx = 0 ; idx < portc ; idx += 1) {
portc, ports, functor_ref_lookup(&ports[idx], portv[idx].text);
start_code,
vpip_peek_current_scope());
start_code->ufunc_core_ptr = core;
ujoin_code->ufunc_core_ptr = core;
/* create enough input functors to connect to all the input
bits of the function. These are used to detect changes and
trigger the function thread. */
unsigned icnt = (argc + 3) / 4;
vvp_ipoint_t ibase = functor_allocate(icnt);
struct ufunc_input_functor_s*ifp
= new struct ufunc_input_functor_s[icnt];
for (unsigned idx = 0 ; idx < icnt ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(ibase,idx);
struct ufunc_input_functor_s*cur = ifp+idx;
cur->core_base_ = idx*4;
cur->core_ = core;
functor_define(ptr, ifp+idx);
} }
inputs_connect(ibase, argc, argv); /* Create the output functor and attach it to the label. Tell
#else it about the start address of the code stub, and the scope
fprintf(stderr, "XXXX compile_ufunc not implemented.\n"); that will contain the execution. */
#endif vvp_net_t*ptr = new vvp_net_t;
ufunc_core*fcore = new ufunc_core(wid, ptr, portc, ports,
start_code, run_scope,
retv.text);
ptr->fun = fcore;
define_functor_symbol(label, ptr);
free(label);
start_code->ufunc_core_ptr = fcore;
ujoin_code->ufunc_core_ptr = fcore;
/* Create input functors to receive values from the
network. These functors pass the data to the core. */
unsigned input_functors = (argc+3) / 4;
for (unsigned idx = 0 ; idx < input_functors ; idx += 1) {
unsigned base = idx*4;
unsigned trans = 4;
if (base+trans > argc)
trans = argc - base;
ufunc_input_functor*cur = new ufunc_input_functor(fcore, base);
ptr = new vvp_net_t;
ptr->fun = cur;
inputs_connect(ptr, trans, argv+base);
}
free(argv);
free(portv);
} }
/* /*
* $Log: ufunc.cc,v $ * $Log: ufunc.cc,v $
* Revision 1.6 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.5 2004/12/11 02:31:30 steve * Revision 1.5 2004/12/11 02:31:30 steve
* Rework of internals to carry vectors through nexus instead * Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes * of single bits. Make the ivl, tgt-vvp and vvp initial changes

View File

@ -1,7 +1,7 @@
#ifndef __ufunc_H #ifndef __ufunc_H
#define __ufunc_H #define __ufunc_H
/* /*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2005 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -19,73 +19,97 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: ufunc.h,v 1.3 2003/07/03 20:03:36 steve Exp $" #ident "$Id: ufunc.h,v 1.4 2005/03/18 02:56:04 steve Exp $"
#endif #endif
# include "pointers.h" # include "pointers.h"
/* /*
* The .ufunc statement creates functors to represent user defined * The .ufunc statement creates functors to represent user defined
* functions. The function device itself is implemented as a thread * functions within the netlist (as opposed to within behavioral
* with a bunch of functors for the output bits. This thread has a set * code.) The function device itself is implemented as a thread with a
* of outputs, represented by output_functors and a set of inputs * bunch of functors to receive input and a functor to deliver the
* connected to input functors. The input functors detect that a * output. (Functions have exactly one output.) The input functors
* change has occurred, and invoke the thread to process the new * detect that a change has occurred, and invoke the thread to process
* values. The relationships work like this: * the new values. The thread then uses the output functor to deliver
* the result. The relationships look like this:
* *
* ufunc_input_functor_s --+--> ufunc_core --+--> ufunc_output_functor_s * ufunc_input_functor --+--> ufunc_core --> ...
* | |
* ufunc_input_functor_s --+ +--> ufunc_output_functor_s
* | * |
* ufunc_input_functor_s --+ * ufunc_input_functor --+
* |
* ufunc_input_functor --+
*
* There are enough input functors to take all the function inputs, 4
* per functor. These inputs deliver the changed input value to the
* ufunc_core, which carries the infastructure for the thread. The
* ufunc_core is also a functor whose output is connected to the rest
* of the netlist. This is where the result is delivered back to the
* netlist.
*/ */
class ufunc_core { class ufunc_core : public vvp_net_fun_t {
public: public:
ufunc_core(unsigned ow, vvp_ipoint_t ob, vvp_ipoint_t*op, ufunc_core(unsigned ow, vvp_net_t*ptr,
unsigned np, vvp_ipoint_t*p, unsigned nports, vvp_net_t**ports,
vvp_code_t start_address, vvp_code_t start_address,
struct __vpiScope*run_scope); struct __vpiScope*run_scope,
char*result_label);
~ufunc_core(); ~ufunc_core();
void set_bit(unsigned port_idx, unsigned val);
void assign_bits_to_ports();
void finish_thread(vthread_t thr);
struct __vpiScope*scope() { return scope_; } struct __vpiScope*scope() { return scope_; }
void assign_bits_to_ports(void);
void finish_thread(vthread_t thr);
private: private:
// The owid_ and obase_ point to the functor vector that makes friend class ufunc_input_functor;
// up the output of the function. void recv_vec4_from_inputs(unsigned port, vvp_vector4_t bit);
private:
// output width of the function node.
unsigned owid_; unsigned owid_;
vvp_ipoint_t obase_; // Pointer to the "self" vvp_net_t that points to this functor.
vvp_ipoint_t*oports_; vvp_net_t*onet_;
// Keep an array of vvp_ipoint_t pointers that point to .var // Structure to track the input values from the input functors.
// functors. These are the input ports of the function.
unsigned nports_; unsigned nports_;
vvp_ipoint_t*ports_; vvp_net_t**ports_;
vvp_vector4_t*port_values_;
// This is a thread to execute the behavioral portion of the // This is a thread to execute the behavioral portion of the
// function. // function.
vthread_t thread_; vthread_t thread_;
struct __vpiScope*scope_; struct __vpiScope*scope_;
vvp_code_t code_; vvp_code_t code_;
// Save the input bits as I receive them. // Where the result will be.
unsigned char*ibits_; vvp_net_t*result_;
};
/*
* The job of the input functor is only to monitor inputs to the
* function and pass them to the ufunc_core object. Each functor takes
* up to 4 inputs, with the base the port number for the first
* function input that this functor represents.
*/
class ufunc_input_functor : public vvp_net_fun_t {
public:
ufunc_input_functor(ufunc_core*c, unsigned base);
~ufunc_input_functor();
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
private:
ufunc_core*core_;
unsigned port_base_;
}; };
/* /*
* $Log: ufunc.h,v $ * $Log: ufunc.h,v $
* Revision 1.3 2003/07/03 20:03:36 steve * Revision 1.4 2005/03/18 02:56:04 steve
* Remove the vvp_cpoint_t indirect code pointer. * Add support for LPM_UFUNC user defined functions.
*
* Revision 1.2 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.1 2002/03/18 00:19:34 steve
* Add the .ufunc statement.
* *
*/ */
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004 Stephen Williams (steve@icarus.com) * Copyright (c) 2004-2005 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ident "$Id: vvp_net.cc,v 1.18 2005/03/12 04:27:43 steve Exp $" #ident "$Id: vvp_net.cc,v 1.19 2005/03/18 02:56:04 steve Exp $"
# include "vvp_net.h" # include "vvp_net.h"
# include <stdio.h> # include <stdio.h>
@ -771,6 +771,16 @@ vvp_scalar_t vvp_fun_signal::scalar_value(unsigned idx) const
return vvp_scalar_t(bits4_.value(idx), 6, 6); return vvp_scalar_t(bits4_.value(idx), 6, 6);
} }
vvp_vector4_t vvp_fun_signal::vec4_value() const
{
if (force_active_)
return force_;
else if (type_is_vector8_())
return reduce4(bits8_);
else
return bits4_;
}
/* **** vvp_scalar_t methods **** */ /* **** vvp_scalar_t methods **** */
/* /*
@ -1168,6 +1178,9 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
/* /*
* $Log: vvp_net.cc,v $ * $Log: vvp_net.cc,v $
* Revision 1.19 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.18 2005/03/12 04:27:43 steve * Revision 1.18 2005/03/12 04:27:43 steve
* Implement VPI access to signal strengths, * Implement VPI access to signal strengths,
* Fix resolution of ambiguous drive pairs, * Fix resolution of ambiguous drive pairs,

View File

@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ident "$Id: vvp_net.h,v 1.18 2005/03/12 04:27:43 steve Exp $" #ident "$Id: vvp_net.h,v 1.19 2005/03/18 02:56:04 steve Exp $"
# include <stdio.h> # include <stdio.h>
# include <assert.h> # include <assert.h>
@ -579,6 +579,7 @@ class vvp_fun_signal : public vvp_net_fun_t {
unsigned size() const; unsigned size() const;
vvp_bit4_t value(unsigned idx) const; vvp_bit4_t value(unsigned idx) const;
vvp_scalar_t scalar_value(unsigned idx) const; vvp_scalar_t scalar_value(unsigned idx) const;
vvp_vector4_t vec4_value() const;
// Commands // Commands
void deassign(); void deassign();
@ -603,6 +604,9 @@ class vvp_fun_signal : public vvp_net_fun_t {
/* /*
* $Log: vvp_net.h,v $ * $Log: vvp_net.h,v $
* Revision 1.19 2005/03/18 02:56:04 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.18 2005/03/12 04:27:43 steve * Revision 1.18 2005/03/12 04:27:43 steve
* Implement VPI access to signal strengths, * Implement VPI access to signal strengths,
* Fix resolution of ambiguous drive pairs, * Fix resolution of ambiguous drive pairs,