mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-22 05:47:31 +02:00
Add support for LPM_UFUNC user defined functions.
This commit is contained in:
+20
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams ([email protected])
|
||||
*
|
||||
* $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
|
||||
@@ -609,8 +609,26 @@ STRUCTURAL FUNCTION CALLS:
|
||||
|
||||
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:
|
||||
|
||||
|
||||
+10
-4
@@ -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.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
|
||||
|
||||
# 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
|
||||
* 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
|
||||
* 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
|
||||
@@ -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,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
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
|
||||
@@ -297,6 +300,9 @@ extern void compile_net(char*label, char*name,
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Handle case inequality in netlists.
|
||||
*
|
||||
|
||||
+6
-3
@@ -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.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
|
||||
|
||||
# include "parse_misc.h"
|
||||
@@ -171,11 +171,11 @@ statement
|
||||
bits in the symbols list change. */
|
||||
|
||||
| T_LABEL K_UFUNC T_SYMBOL ',' T_NUMBER ',' symbols
|
||||
'(' symbols ')' symbols ';'
|
||||
'(' symbols ')' symbol ';'
|
||||
{ compile_ufunc($1, $3, $5,
|
||||
$7.cnt, $7.vect,
|
||||
$9.cnt, $9.vect,
|
||||
$11.cnt, $11.vect); }
|
||||
$11); }
|
||||
|
||||
/* Resolver statements are very much like functors. They are
|
||||
compiled to functors of a different mode. */
|
||||
@@ -679,6 +679,9 @@ int compile_design(const char*path)
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Handle case inequality in netlists.
|
||||
*
|
||||
|
||||
+107
-122
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2003 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2002-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* 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
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "compile.h"
|
||||
@@ -39,34 +39,65 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
ufunc_core::ufunc_core(unsigned ow, vvp_ipoint_t ob, vvp_ipoint_t*op,
|
||||
unsigned np, vvp_ipoint_t*p,
|
||||
vvp_code_t start_address,
|
||||
struct __vpiScope*run_scope)
|
||||
: owid_(ow), obase_(ob), oports_(op), nports_(np), ports_(p)
|
||||
ufunc_core::ufunc_core(unsigned owid, vvp_net_t*ptr,
|
||||
unsigned nports, vvp_net_t**ports,
|
||||
vvp_code_t sa, struct __vpiScope*run_scope,
|
||||
char*result_label)
|
||||
{
|
||||
owid_ = owid;
|
||||
onet_ = ptr;
|
||||
nports_ = nports;
|
||||
ports_ = ports;
|
||||
port_values_ = new vvp_vector4_t[nports];
|
||||
code_ = sa;
|
||||
thread_ = 0;
|
||||
scope_ = run_scope;
|
||||
code_ = start_address;
|
||||
|
||||
ibits_ = new unsigned char[(nports_+3) / 4];
|
||||
memset(ibits_, 0xaa, (nports_+3) / 4);
|
||||
functor_ref_lookup(&result_, result_label);
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned pp = port_idx % 4;
|
||||
for (unsigned idx = 0 ; idx < nports_ ; idx += 1) {
|
||||
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];
|
||||
ibits_[idx] |= (val&3) << pp*2;
|
||||
vvp_fun_signal*sig = reinterpret_cast<vvp_fun_signal*>(result_->fun);
|
||||
|
||||
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) {
|
||||
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};
|
||||
|
||||
void ufunc_core::assign_bits_to_ports(void)
|
||||
ufunc_input_functor::ufunc_input_functor(ufunc_core*c, unsigned base)
|
||||
: core_(c), port_base_(base)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
void ufunc_input_functor::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
|
||||
{
|
||||
put_oval(val, push);
|
||||
}
|
||||
|
||||
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);
|
||||
unsigned pidx = port_base_ + port.port();
|
||||
core_->recv_vec4_from_inputs(pidx, bit);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function compiles the .ufunc statement that is discovered in
|
||||
* the source file. Create all the functors and the thread, and
|
||||
* 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,
|
||||
unsigned argc, struct symb_s*argv,
|
||||
unsigned portc, struct symb_s*portv,
|
||||
unsigned retc, struct symb_s*retv)
|
||||
struct symb_s retv)
|
||||
{
|
||||
#if 0
|
||||
/* Create an array of vvp_ipoint_t pointers, that point to the
|
||||
.var bits of the function ports. Do this for the input
|
||||
ports and the output port. */
|
||||
/* The input argument list and port list must have the same
|
||||
sizes, since internally we will be mapping the inputs list
|
||||
to the ports list. */
|
||||
assert(argc == portc);
|
||||
vvp_ipoint_t* ports = new vvp_ipoint_t [portc];
|
||||
|
||||
for (unsigned idx = 0 ; idx < portc ; idx += 1) {
|
||||
functor_ref_lookup(ports+idx, portv[idx].text, portv[idx].idx);
|
||||
}
|
||||
|
||||
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);
|
||||
struct __vpiScope*run_scope = vpip_peek_current_scope();
|
||||
assert(run_scope);
|
||||
|
||||
/* Construct some phantom code that is the thread of the
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* Create the function core object that references the output
|
||||
functors and the function ports. The input functors will
|
||||
point to this core to deliver input. */
|
||||
ufunc_core*core = new ufunc_core(wid, obase, rets,
|
||||
portc, ports,
|
||||
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);
|
||||
/* Run through the function ports (which are related to but
|
||||
not the same as the input ports) and arrange for their
|
||||
binding. */
|
||||
vvp_net_t**ports = new vvp_net_t*[portc];
|
||||
for (unsigned idx = 0 ; idx < portc ; idx += 1) {
|
||||
functor_ref_lookup(&ports[idx], portv[idx].text);
|
||||
}
|
||||
|
||||
inputs_connect(ibase, argc, argv);
|
||||
#else
|
||||
fprintf(stderr, "XXXX compile_ufunc not implemented.\n");
|
||||
#endif
|
||||
/* Create the output functor and attach it to the label. Tell
|
||||
it about the start address of the code stub, and the scope
|
||||
that will contain the execution. */
|
||||
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 $
|
||||
* 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
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
||||
+63
-39
@@ -1,7 +1,7 @@
|
||||
#ifndef __ufunc_H
|
||||
#define __ufunc_H
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2002-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* 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
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "pointers.h"
|
||||
|
||||
/*
|
||||
* The .ufunc statement creates functors to represent user defined
|
||||
* functions. The function device itself is implemented as a thread
|
||||
* with a bunch of functors for the output bits. This thread has a set
|
||||
* of outputs, represented by output_functors and a set of inputs
|
||||
* connected to input functors. The input functors detect that a
|
||||
* change has occurred, and invoke the thread to process the new
|
||||
* values. The relationships work like this:
|
||||
* functions within the netlist (as opposed to within behavioral
|
||||
* code.) The function device itself is implemented as a thread with a
|
||||
* bunch of functors to receive input and a functor to deliver the
|
||||
* output. (Functions have exactly one output.) The input functors
|
||||
* detect that a change has occurred, and invoke the thread to process
|
||||
* 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_s --+ +--> ufunc_output_functor_s
|
||||
* |
|
||||
* ufunc_input_functor_s --+
|
||||
* ufunc_input_functor --+--> ufunc_core --> ...
|
||||
* |
|
||||
* 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:
|
||||
ufunc_core(unsigned ow, vvp_ipoint_t ob, vvp_ipoint_t*op,
|
||||
unsigned np, vvp_ipoint_t*p,
|
||||
ufunc_core(unsigned ow, vvp_net_t*ptr,
|
||||
unsigned nports, vvp_net_t**ports,
|
||||
vvp_code_t start_address,
|
||||
struct __vpiScope*run_scope);
|
||||
struct __vpiScope*run_scope,
|
||||
char*result_label);
|
||||
~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_; }
|
||||
|
||||
void assign_bits_to_ports(void);
|
||||
void finish_thread(vthread_t thr);
|
||||
|
||||
private:
|
||||
// The owid_ and obase_ point to the functor vector that makes
|
||||
// up the output of the function.
|
||||
friend class ufunc_input_functor;
|
||||
void recv_vec4_from_inputs(unsigned port, vvp_vector4_t bit);
|
||||
|
||||
private:
|
||||
// output width of the function node.
|
||||
unsigned owid_;
|
||||
vvp_ipoint_t obase_;
|
||||
vvp_ipoint_t*oports_;
|
||||
// Keep an array of vvp_ipoint_t pointers that point to .var
|
||||
// functors. These are the input ports of the function.
|
||||
// Pointer to the "self" vvp_net_t that points to this functor.
|
||||
vvp_net_t*onet_;
|
||||
// Structure to track the input values from the input functors.
|
||||
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
|
||||
// function.
|
||||
vthread_t thread_;
|
||||
struct __vpiScope*scope_;
|
||||
vvp_code_t code_;
|
||||
|
||||
// Save the input bits as I receive them.
|
||||
unsigned char*ibits_;
|
||||
// Where the result will be.
|
||||
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 $
|
||||
* Revision 1.3 2003/07/03 20:03:36 steve
|
||||
* Remove the vvp_cpoint_t indirect code pointer.
|
||||
*
|
||||
* 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.
|
||||
* Revision 1.4 2005/03/18 02:56:04 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+15
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2004-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* 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
|
||||
* 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 <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);
|
||||
}
|
||||
|
||||
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 **** */
|
||||
|
||||
/*
|
||||
@@ -1168,6 +1178,9 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Implement VPI access to signal strengths,
|
||||
* Fix resolution of ambiguous drive pairs,
|
||||
|
||||
+5
-1
@@ -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.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 <assert.h>
|
||||
@@ -579,6 +579,7 @@ class vvp_fun_signal : public vvp_net_fun_t {
|
||||
unsigned size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
vvp_vector4_t vec4_value() const;
|
||||
|
||||
// Commands
|
||||
void deassign();
|
||||
@@ -603,6 +604,9 @@ class vvp_fun_signal : public vvp_net_fun_t {
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Implement VPI access to signal strengths,
|
||||
* Fix resolution of ambiguous drive pairs,
|
||||
|
||||
Reference in New Issue
Block a user