Add support for system functions in continuous assignments.

This commit is contained in:
steve 2006-06-18 04:15:50 +00:00
parent 71faebd6df
commit 80f30be9d0
27 changed files with 918 additions and 156 deletions

12
PExpr.h
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

160
vvp/sfunc.cc Normal file
View File

@ -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.
*
*/

51
vvp/sfunc.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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