Support sequential UDP devices.

This commit is contained in:
steve 2005-06-09 04:12:30 +00:00
parent 2f7ec71a78
commit 77792dcc2f
3 changed files with 663 additions and 64 deletions

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.204 2005/06/02 16:02:11 steve Exp $"
#ident "$Id: compile.cc,v 1.205 2005/06/09 04:12:30 steve Exp $"
#endif
# include "arith.h"
@ -1119,8 +1119,13 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
void compile_udp_def(int sequ, char *label, char *name,
unsigned nin, unsigned init, char **table)
{
vvp_udp_s *u = new vvp_udp_s(label, name, nin, sequ? true : false);
u->compile_table(table);
if (sequ) {
vvp_udp_seq_s *u = new vvp_udp_seq_s(label, name, nin);
u->compile_table(table);
} else {
vvp_udp_comb_s *u = new vvp_udp_comb_s(label, name, nin);
u->compile_table(table);
}
free(label);
}
@ -1548,6 +1553,9 @@ void compile_param_string(char*label, char*name, char*str, char*value)
/*
* $Log: compile.cc,v $
* Revision 1.205 2005/06/09 04:12:30 steve
* Support sequential UDP devices.
*
* Revision 1.204 2005/06/02 16:02:11 steve
* Add support for notif0/1 gates.
* Make delay nodes support inertial delay.

View File

@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: udp.cc,v 1.29 2005/04/04 05:13:59 steve Exp $"
#ident "$Id: udp.cc,v 1.30 2005/06/09 04:12:30 steve Exp $"
#endif
#include "udp.h"
@ -34,7 +34,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
static symbol_table_t udp_table;
@ -44,38 +44,44 @@ struct vvp_udp_s *udp_find(const char *label)
return (struct vvp_udp_s *)v.ptr;
}
vvp_udp_s::vvp_udp_s(char*label, char*name, unsigned ports, bool sequ)
vvp_udp_s::vvp_udp_s(char*label, unsigned ports)
: ports_(ports)
{
assert(!sequ); // XXXX sequential UDPs not supported yet.
if (!udp_table)
udp_table = new_symbol_table();
assert(!udp_find(label));
assert( !udp_find(label) );
symbol_value_t v;
v.ptr = this;
sym_set_value(udp_table, label, v);
}
vvp_udp_s::~vvp_udp_s()
{
}
unsigned vvp_udp_s::port_count() const
{
return ports_;
}
vvp_udp_comb_s::vvp_udp_comb_s(char*label, char*name, unsigned ports)
: vvp_udp_s(label, ports)
{
name_ = name;
ports_ = ports;
levels0_ = 0;
levels1_ = 0;
nlevels0_ = 0;
nlevels1_ = 0;
}
vvp_udp_s::~vvp_udp_s()
vvp_udp_comb_s::~vvp_udp_comb_s()
{
if (levels0_) delete[] levels0_;
if (levels1_) delete[] levels1_;
}
unsigned vvp_udp_s::port_count() const
{
return ports_;
}
/*
* The cur table that is passed in must have for every valid bit
* position exactly one of the three mask bits set. This represents an
@ -94,8 +100,14 @@ unsigned vvp_udp_s::port_count() const
* the three bit positions is set in the cur input table, the bit
* position will generate a match.
*/
vvp_bit4_t vvp_udp_s::test_levels(const udp_levels_table&cur)
vvp_bit4_t vvp_udp_comb_s::test_levels(const udp_levels_table&cur)
{
/* To test for a row match, test that the mask0, mask1 and
maskx vectors all have bits set where the matching
cur.mask0/1/x vectors have bits set. It is possible that a
levels0_[idx] vector has more bits set then the cur mask,
but this is OK and these bits are to be ignored. */
for (unsigned idx = 0 ; idx < nlevels0_ ; idx += 1) {
if (cur.mask0 != (cur.mask0 & levels0_[idx].mask0))
continue;
@ -121,15 +133,57 @@ vvp_bit4_t vvp_udp_s::test_levels(const udp_levels_table&cur)
return BIT4_X;
}
void vvp_udp_s::compile_table(char**tab)
vvp_bit4_t vvp_udp_comb_s::calculate_output(const udp_levels_table&cur,
const udp_levels_table&,
vvp_bit4_t)
{
return test_levels(cur);
}
static void or_based_on_char(udp_levels_table&cur, char flag,
unsigned long mask_bit)
{
switch (flag) {
case '0':
cur.mask0 |= mask_bit;
break;
case '1':
cur.mask1 |= mask_bit;
break;
case 'x':
cur.maskx |= mask_bit;
break;
case 'b':
cur.mask0 |= mask_bit;
cur.mask1 |= mask_bit;
break;
case 'l':
cur.mask0 |= mask_bit;
cur.maskx |= mask_bit;
break;
case 'h':
cur.maskx |= mask_bit;
cur.mask1 |= mask_bit;
break;
case '?':
cur.mask0 |= mask_bit;
cur.maskx |= mask_bit;
cur.mask1 |= mask_bit;
break;
default:
assert(0);
}
}
void vvp_udp_comb_s::compile_table(char**tab)
{
unsigned nrows0 = 0, nrows1 = 0;
/* First run through the table to figure out the number of
rows I need for each kind of table. */
for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
assert(strlen(tab[idx]) == ports_ + 1);
switch (tab[idx][ports_]) {
assert(strlen(tab[idx]) == port_count() + 1);
switch (tab[idx][port_count()]) {
case '0':
nrows0 += 1;
break;
@ -156,42 +210,13 @@ void vvp_udp_s::compile_table(char**tab)
cur.mask0 = 0;
cur.mask1 = 0;
cur.maskx = 0;
assert(ports_ <= sizeof(cur.mask0));
for (unsigned pp = 0 ; pp < ports_ ; pp += 1) {
assert(port_count() <= sizeof(cur.mask0));
for (unsigned pp = 0 ; pp < port_count() ; pp += 1) {
unsigned long mask_bit = 1UL << pp;
switch (tab[idx][pp]) {
case '0':
cur.mask0 |= mask_bit;
break;
case '1':
cur.mask1 |= mask_bit;
break;
case 'x':
cur.maskx |= mask_bit;
break;
case 'b':
cur.mask0 |= mask_bit;
cur.mask1 |= mask_bit;
break;
case 'l':
cur.mask0 |= mask_bit;
cur.maskx |= mask_bit;
break;
case 'h':
cur.maskx |= mask_bit;
cur.mask1 |= mask_bit;
break;
case '?':
cur.mask0 |= mask_bit;
cur.maskx |= mask_bit;
cur.mask1 |= mask_bit;
break;
default:
assert(0);
}
or_based_on_char(cur, tab[idx][pp], mask_bit);
}
switch (tab[idx][ports_]) {
switch (tab[idx][port_count()]) {
case '0':
levels0_[nrows0++] = cur;
break;
@ -207,6 +232,441 @@ void vvp_udp_s::compile_table(char**tab)
assert(nrows1 == nlevels1_);
}
vvp_udp_seq_s::vvp_udp_seq_s(char*label, char*name, unsigned ports)
: vvp_udp_s(label, ports)
{
levels0_ = 0;
levels1_ = 0;
levelsx_ = 0;
levelsL_ = 0;
nlevels0_ = 0;
nlevels1_ = 0;
nlevelsx_ = 0;
nlevelsL_ = 0;
edges0_ = 0;
edges1_ = 0;
edgesL_ = 0;
nedges0_ = 0;
nedges1_ = 0;
nedgesL_ = 0;
}
vvp_udp_seq_s::~vvp_udp_seq_s()
{
if (levels0_) delete[]levels0_;
if (levels1_) delete[]levels1_;
if (levelsx_) delete[]levelsx_;
if (levelsL_) delete[]levelsL_;
if (edges0_) delete[]edges0_;
if (edges1_) delete[]edges1_;
if (edgesL_) delete[]edgesL_;
}
void edge_based_on_char(struct udp_edges_table&cur, char chr, unsigned pos)
{
unsigned long mask_bit = 1 << pos;
switch (chr) {
case '0':
cur.mask0 |= mask_bit;
break;
case '1':
cur.mask1 |= mask_bit;
break;
case 'x':
cur.maskx |= mask_bit;
break;
case 'b':
cur.mask0 |= mask_bit;
cur.mask1 |= mask_bit;
break;
case 'l':
cur.mask0 |= mask_bit;
cur.maskx |= mask_bit;
break;
case 'h':
cur.maskx |= mask_bit;
cur.mask1 |= mask_bit;
break;
case '?':
cur.mask0 |= mask_bit;
cur.maskx |= mask_bit;
cur.mask1 |= mask_bit;
break;
case 'f': // (10) edge
cur.mask0 |= mask_bit;
cur.edge_position = pos;
cur.edge_mask0 = 0;
cur.edge_maskx = 0;
cur.edge_mask1 = 1;
break;
case 'q': // (bx) edge
cur.maskx |= mask_bit;
cur.edge_position = pos;
cur.edge_mask0 = 1;
cur.edge_maskx = 0;
cur.edge_mask1 = 1;
break;
case 'r': // (01) edge
cur.mask1 |= mask_bit;
cur.edge_position = pos;
cur.edge_mask0 = 1;
cur.edge_maskx = 0;
cur.edge_mask1 = 0;
break;
default:
assert(0);
}
}
void vvp_udp_seq_s::compile_table(char**tab)
{
for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
const char*row = tab[idx];
assert(strlen(row) == port_count() + 2);
if (strspn(row, "01xblh?") >= port_count()+1) {
switch (row[port_count()+1]) {
case '0':
nlevels0_ += 1;
break;
case '1':
nlevels1_ += 1;
break;
case 'x':
nlevelsx_ += 1;
break;
case '-':
nlevelsL_ += 1;
break;
default:
assert(0);
break;
}
} else {
switch (row[port_count()+1]) {
case '0':
nedges0_ += 1;
break;
case '1':
nedges1_ += 1;
break;
case 'x':
break;
case '-':
nedgesL_ += 1;
break;
default:
assert(0);
break;
}
}
}
levels0_ = new udp_levels_table[nlevels0_];
levels1_ = new udp_levels_table[nlevels1_];
levelsx_ = new udp_levels_table[nlevelsx_];
levelsL_ = new udp_levels_table[nlevelsL_];
edges0_ = new udp_edges_table[nedges0_];
edges1_ = new udp_edges_table[nedges1_];
edgesL_ = new udp_edges_table[nedgesL_];
unsigned idx_lev0 = 0;
unsigned idx_lev1 = 0;
unsigned idx_levx = 0;
unsigned idx_levL = 0;
unsigned idx_edg0 = 0;
unsigned idx_edg1 = 0;
unsigned idx_edgL = 0;
for (unsigned idx = 0 ; tab[idx] ; idx += 1) {
const char*row = tab[idx];
if (strspn(row, "01xblh?") >= port_count()+1) {
struct udp_levels_table cur;
cur.mask0 = 0;
cur.mask1 = 0;
cur.maskx = 0;
for (unsigned pp = 0 ; pp < port_count() ; pp += 1) {
unsigned long mask_bit = 1UL << pp;
or_based_on_char(cur, row[pp+1], mask_bit);
}
or_based_on_char(cur, row[0], 1UL << port_count());
switch (row[port_count()+1]) {
case '0':
levels0_[idx_lev0++] = cur;
break;
case '1':
levels1_[idx_lev1++] = cur;
break;
case 'x':
levelsx_[idx_levx++] = cur;
break;
case '-':
levelsL_[idx_levL++] = cur;
break;
default:
assert(0);
break;
}
} else {
struct udp_edges_table cur;
cur.mask0 = 0;
cur.mask1 = 0;
cur.maskx = 0;
cur.edge_position = 0;
cur.edge_mask0 = 0;
cur.edge_mask1 = 0;
cur.edge_maskx = 0;
for (unsigned pp = 0 ; pp < port_count() ; pp += 1) {
edge_based_on_char(cur, row[pp+1], pp);
}
edge_based_on_char(cur, row[0], port_count());
switch (row[port_count()+1]) {
case '0':
edges0_[idx_edg0++] = cur;
break;
case '1':
edges1_[idx_edg1++] = cur;
break;
case 'x':
break;
case '-':
edgesL_[idx_edgL++] = cur;
break;
default:
assert(0);
break;
}
}
}
}
vvp_bit4_t vvp_udp_seq_s::calculate_output(const udp_levels_table&cur,
const udp_levels_table&prev,
vvp_bit4_t cur_out)
{
udp_levels_table cur_tmp = cur;
unsigned long mask_out = 1UL << port_count();
switch (cur_out) {
case BIT4_0:
cur_tmp.mask0 |= mask_out;
break;
case BIT4_1:
cur_tmp.mask1 |= mask_out;
break;
default:
cur_tmp.maskx |= mask_out;
break;
}
vvp_bit4_t lev = test_levels_(cur_tmp);
if (lev == BIT4_Z) {
lev = test_edges_(cur_tmp, prev);
}
return lev;
}
/*
* This function tests the levels of the input with the additional
* check match for the current output. It uses this to calculate a
* next output, or Z if there was no match. (This is different from
* the combinational version of this function, which returns X for the
* cases that don't match.) This method assumes that the caller has
* set the mask bit in bit postion [port_count()] to reflect the
* current output.
*/
vvp_bit4_t vvp_udp_seq_s::test_levels_(const udp_levels_table&cur)
{
for (unsigned idx = 0 ; idx < nlevels0_ ; idx += 1) {
if (cur.mask0 != (cur.mask0 & levels0_[idx].mask0))
continue;
if (cur.mask1 != (cur.mask1 & levels0_[idx].mask1))
continue;
if (cur.maskx != (cur.maskx & levels0_[idx].maskx))
continue;
return BIT4_0;
}
for (unsigned idx = 0 ; idx < nlevels1_ ; idx += 1) {
if (cur.mask0 != (cur.mask0 & levels1_[idx].mask0))
continue;
if (cur.mask1 != (cur.mask1 & levels1_[idx].mask1))
continue;
if (cur.maskx != (cur.maskx & levels1_[idx].maskx))
continue;
return BIT4_1;
}
/* We need to test against an explicit X-output table, since
we need to distinguish from an X output and no match. */
for (unsigned idx = 0 ; idx < nlevelsx_ ; idx += 1) {
if (cur.mask0 != (cur.mask0 & levelsx_[idx].mask0))
continue;
if (cur.mask1 != (cur.mask1 & levelsx_[idx].mask1))
continue;
if (cur.maskx != (cur.maskx & levelsx_[idx].maskx))
continue;
return BIT4_X;
}
/* Test the table that requests the next output be the same as
the current output. This gets the current output from the
levels table that was passed in. */
for (unsigned idx = 0 ; idx < nlevelsL_ ; idx += 1) {
if (cur.mask0 != (cur.mask0 & levelsL_[idx].mask0))
continue;
if (cur.mask1 != (cur.mask1 & levelsL_[idx].mask1))
continue;
if (cur.maskx != (cur.maskx & levelsL_[idx].maskx))
continue;
if (cur.mask0 & (1 << port_count()))
return BIT4_0;
if (cur.mask1 & (1 << port_count()))
return BIT4_1;
if (cur.maskx & (1 << port_count()))
return BIT4_X;
assert(0);
return BIT4_X;
}
/* No explicit levels entry match. Return a Z to signal that
further testing is needed. */
return BIT4_Z;
}
vvp_bit4_t vvp_udp_seq_s::test_edges_(const udp_levels_table&cur,
const udp_levels_table&prev)
{
/* The edge_mask is true for all bits that are different in
the cur and prev tables. */
unsigned long edge0_mask = cur.mask0 ^ prev.mask0;
unsigned long edgex_mask = cur.maskx ^ prev.maskx;
unsigned long edge1_mask = cur.mask1 ^ prev.mask1;
unsigned long edge_mask = edge0_mask|edgex_mask|edge1_mask;
edge_mask &= ~ (-1UL << port_count());
/* If there are no differences, then there are no edges. Give
up now. */
if (edge_mask == 0)
return BIT4_X;
unsigned edge_position = 0;
while ((edge_mask&1) == 0) {
edge_mask >>= 1;
edge_position += 1;
}
/* We expect that there is exactly one edge in here. */
assert(edge_mask == 1);
edge_mask = 1UL << edge_position;
unsigned edge_mask0 = (prev.mask0&edge_mask)? 1 : 0;
unsigned edge_maskx = (prev.maskx&edge_mask)? 1 : 0;
unsigned edge_mask1 = (prev.mask1&edge_mask)? 1 : 0;
/* Now the edge_position and edge_mask* variables have the
values we use to test the applicability of the edge_table
entries. */
for (unsigned idx = 0 ; idx < nedges0_ ; idx += 1) {
struct udp_edges_table*row = edges0_ + idx;
if (row->edge_position != edge_position)
continue;
if (edge_mask0 && !row->edge_mask0)
continue;
if (edge_maskx && !row->edge_maskx)
continue;
if (edge_mask1 && !row->edge_mask1)
continue;
if (cur.mask0 != (cur.mask0 & row->mask0))
continue;
if (cur.maskx != (cur.maskx & row->maskx))
continue;
if (cur.mask1 != (cur.mask1 & row->mask1))
continue;
return BIT4_0;
}
for (unsigned idx = 0 ; idx < nedges1_ ; idx += 1) {
struct udp_edges_table*row = edges1_ + idx;
if (row->edge_position != edge_position)
continue;
if (edge_mask0 && !row->edge_mask0)
continue;
if (edge_maskx && !row->edge_maskx)
continue;
if (edge_mask1 && !row->edge_mask1)
continue;
if (cur.mask0 != (cur.mask0 & row->mask0))
continue;
if (cur.maskx != (cur.maskx & row->maskx))
continue;
if (cur.mask1 != (cur.mask1 & row->mask1))
continue;
return BIT4_1;
}
for (unsigned idx = 0 ; idx < nedgesL_ ; idx += 1) {
struct udp_edges_table*row = edgesL_ + idx;
if (row->edge_position != edge_position)
continue;
if (edge_mask0 && !row->edge_mask0)
continue;
if (edge_maskx && !row->edge_maskx)
continue;
if (edge_mask1 && !row->edge_mask1)
continue;
if (cur.mask0 != (cur.mask0 & row->mask0))
continue;
if (cur.maskx != (cur.maskx & row->maskx))
continue;
if (cur.mask1 != (cur.mask1 & row->mask1))
continue;
if (cur.mask0 & (1 << port_count()))
return BIT4_0;
if (cur.mask1 & (1 << port_count()))
return BIT4_1;
if (cur.maskx & (1 << port_count()))
return BIT4_X;
assert(0);
return BIT4_X;
}
return BIT4_X;
}
vvp_udp_fun_core::vvp_udp_fun_core(vvp_net_t*net,
vvp_udp_s*def,
vvp_delay_t*del)
@ -232,6 +692,8 @@ void vvp_udp_fun_core::recv_vec4_from_inputs(unsigned port)
unsigned long mask = 1UL << port;
udp_levels_table prev = current_;
switch (value(port).value(0)) {
case BIT4_0:
@ -251,7 +713,7 @@ void vvp_udp_fun_core::recv_vec4_from_inputs(unsigned port)
break;
}
vvp_bit4_t out_bit = def_->test_levels(current_);
vvp_bit4_t out_bit = def_->calculate_output(current_, prev, cur_out_);
vvp_vector4_t out (1);
out.set_bit(0, out_bit);
@ -289,6 +751,9 @@ void compile_udp_functor(char*label, char*type,
/*
* $Log: udp.cc,v $
* Revision 1.30 2005/06/09 04:12:30 steve
* Support sequential UDP devices.
*
* Revision 1.29 2005/04/04 05:13:59 steve
* Support row level wildcards.
*

146
vvp/udp.h
View File

@ -22,14 +22,35 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: udp.h,v 1.16 2005/04/03 05:45:51 steve Exp $"
#ident "$Id: udp.h,v 1.17 2005/06/09 04:12:30 steve Exp $"
#endif
# include <vvp_net.h>
# include <delay.h>
struct udp_levels_table;
struct vvp_udp_s {
public:
explicit vvp_udp_s(char*label, unsigned ports);
virtual ~vvp_udp_s();
// Return the number of input ports for the defined UDP. This
// does *not* include the current output value for a
// sequential UDP.
unsigned port_count() const;
virtual vvp_bit4_t calculate_output(const udp_levels_table&cur,
const udp_levels_table&prev,
vvp_bit4_t cur_out) =0;
private:
unsigned ports_;
};
/*
* The vvp_udp_s instance represents a *definition* of a
* The vvp_udp_async_s instance represents a *definition* of a
* primitive. netlist instances refer to these definitions.
*
* The ports argument of the constructor is the number of input ports
@ -50,7 +71,31 @@
* will be set in the three masks for each bit position.
*
* This table structure implies that the number of inputs to the level
* sensitive device is limited to the number of bits in an unsigned long.
* sensitive device is limited to the number of bits in an unsigned
* long.
*
* The array of strings passed to the compile_table method of a
* combinational UDP are strings of port_count()+1 characters. The
* expected inputs are in the order of the UDP inputs, and the output
* is the last character. For example, an AND gate has these strings
* passed to the compile_table function:
*
* 000 (Both inputs are 0)
* 010 (Second input is a 1)
* 100
* 111 (All inputs are 1, so generate a 1 output)
*
* The characters allowed in the input positions are:
*
* 0 -- Expect a 0
* 1 -- Expect a 1
* x -- Expect an x or z
* b -- 0 or 1
* l -- 0 or x
* h -- x or 1
* ? -- 0, x or 1
*
* Only 0, 1 and x characters are allowed in the output position.
*/
struct udp_levels_table {
@ -59,23 +104,23 @@ struct udp_levels_table {
unsigned long maskx;
};
class vvp_udp_s {
class vvp_udp_comb_s : public vvp_udp_s {
public:
vvp_udp_s(char*label, char*name, unsigned ports, bool sequ);
~vvp_udp_s();
vvp_udp_comb_s(char*label, char*name, unsigned ports);
~vvp_udp_comb_s();
void compile_table(char**tab);
// Return the number of input ports for the defined UDP.
unsigned port_count() const;
// Test the cur table with the compiled rows, and return the
// bit value that matches.
vvp_bit4_t test_levels(const udp_levels_table&cur);
vvp_bit4_t calculate_output(const udp_levels_table&cur,
const udp_levels_table&prev,
vvp_bit4_t cur_out);
private:
char*name_;
unsigned ports_;
// Level sensitive rows of the device.
struct udp_levels_table*levels0_;
@ -83,6 +128,84 @@ class vvp_udp_s {
unsigned nlevels0_, nlevels1_;
};
/*
* udp sequential devices are a little more complex in that they have
* an additional output type: no-change. They also have, in addition
* to a table of levels, a table of edges that are similar to levels
* but one of the positions has an edge value.
*
* The port_count() for the device is the number of inputs. Sequential
* devices have and additional phantom port that is the current output
* value. This implies that the maximim port count for sequential
* devices is 1 less then for combinational.
*
* The input table that is passed to the compile_table method is very
* similar to that for the combinational UDP. The differences are that
* there is one extra entry in the beginning of each input row that is
* the current output, and there are more characters accepted at each
* bit position.
*
* The current output bit may contain the same characters as a
* combinational UDP input position. No edges.
*
* The next output position takes the possible values 0, x, 1 and -.
*
* The input bit positions take the combinational input characters,
* plus edge specification characters. Only one input of a row may
* have an edge input.
*
* The edges_table is similar to the levels, table, with the mask?
* bits having the same meaning as with the levels tables. The edge_*
* members specify the edge for a single bit position. In this case,
* the edge_mask* members give the mask of source bits for that
* position, and the edge_position the bit that has shifted. In the
* edge case, the mask* members give the final position and the
* edge_mask* bits the initial position of the bit.
*/
struct udp_edges_table {
unsigned long edge_position : 8;
unsigned long edge_mask0 : 1;
unsigned long edge_mask1 : 1;
unsigned long edge_maskx : 1;
unsigned long mask0;
unsigned long mask1;
unsigned long maskx;
};
class vvp_udp_seq_s : public vvp_udp_s {
public:
vvp_udp_seq_s(char*label, char*name, unsigned ports);
~vvp_udp_seq_s();
void compile_table(char**tab);
vvp_bit4_t calculate_output(const udp_levels_table&cur,
const udp_levels_table&prev,
vvp_bit4_t cur_out);
private:
vvp_bit4_t test_levels_(const udp_levels_table&cur);
// Level sensitive rows of the device.
struct udp_levels_table*levels0_;
struct udp_levels_table*levels1_;
struct udp_levels_table*levelsx_;
struct udp_levels_table*levelsL_;
unsigned nlevels0_, nlevels1_, nlevelsx_, nlevelsL_;
vvp_bit4_t test_edges_(const udp_levels_table&cur,
const udp_levels_table&prev);
// Edge sensitive rows of the device
struct udp_edges_table*edges0_;
struct udp_edges_table*edges1_;
struct udp_edges_table*edgesL_;
unsigned nedges0_, nedges1_, nedgesL_;
};
/*
* Ths looks up a UDP definition from its LABEL.
*/
@ -114,6 +237,9 @@ class vvp_udp_fun_core : public vvp_wide_fun_core {
/*
* $Log: udp.h,v $
* Revision 1.17 2005/06/09 04:12:30 steve
* Support sequential UDP devices.
*
* Revision 1.16 2005/04/03 05:45:51 steve
* Rework the vvp_delay_t class.
*