Redo and simplify UDP behavior.

This commit is contained in:
steve 2001-04-26 03:10:55 +00:00
parent 8b5f62a5e5
commit 62c9f39297
5 changed files with 89 additions and 137 deletions

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: README.txt,v 1.17 2001/04/25 04:35:05 steve Exp $
* $Id: README.txt,v 1.18 2001/04/26 03:10:55 steve Exp $
*/
VVP SIMULATION ENGINE
@ -125,13 +125,23 @@ the output becomes 1'bx.
The output state can be specified as "0", "1", or "x". Sequential
UDPs may also have "-": no change.
An input or current output state can be "1", "0", "x", or "?" (don't
care). For Sequential UDPs, at most one input state specification may
be replaced by an edge specification. Valid edges are:
An input or current output state can be
"1": 1
"0": 0
"x": x
"b": 1, 0
"h": 1, x
"l": 0, x
"?": 1, 0, x
For Sequential UDPs, at most one input state specification may be
replaced by an edge specification. Valid edges are:
"*": (??) "_": (?0) "+": (?1) "%": (?x)
"r": (01) "R": (x1) "f": (10) "F": (x0)
"p": (0?) "n": (1?) "P": (0x) "N": (1x)
"p": (0?) "r": (01) "P": (0x)
"n": (1?) "f": (10) "N": (1x)
"B": (x?) "F": (x0) "R": (x1)
A combinatorial UDP is defined like this:

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.cc,v 1.40 2001/04/24 03:48:53 steve Exp $"
#ident "$Id: compile.cc,v 1.41 2001/04/26 03:10:55 steve Exp $"
#endif
# include "compile.h"
@ -319,7 +319,7 @@ void compile_udp_functor(char*label, char*type,
struct vvp_udp_s *u = udp_find(type);
assert (argc == u->nin);
int nfun = argc<=4 ? 1 : (argc-2) / 3 + 1;
int nfun = (argc+3)/4;
vvp_ipoint_t fdx = functor_allocate(nfun);
functor_t obj = functor_index(fdx);
@ -330,6 +330,26 @@ void compile_udp_functor(char*label, char*type,
sym_set_value(sym_functors, label, val);
}
for (unsigned idx = 0; idx < argc; idx += 4)
{
vvp_ipoint_t ifdx = ipoint_input_index(fdx, idx);
functor_t iobj = functor_index(ifdx);
iobj->ival = 0xaa;
iobj->old_ival = obj->ival;
iobj->oval = u->init;
iobj->mode = 3;
if (idx)
{
iobj->out = fdx;
iobj->udp = 0;
}
else
{
iobj->udp = u;
}
}
/* Run through the arguments looking for the functors that are
connected to my input ports. For each source functor that I
find, connect the output of that functor to the indexed
@ -339,14 +359,10 @@ void compile_udp_functor(char*label, char*type,
If the source functor is not declared yet, then don't do
the link yet. Save the reference to be resolved later. */
udp_init_links(fdx, u);
udp_idx_t ux(fdx, u);
for (unsigned idx = 0; idx < argc; idx += 1)
{
vvp_ipoint_t ifdx = ux.ipoint();
functor_t iobj = ux.functor();
ux.next();
vvp_ipoint_t ifdx = ipoint_input_index(fdx, idx);
functor_t iobj = functor_index(ifdx);
symbol_value_t val = sym_get_value(sym_functors, argv[idx].text);
vvp_ipoint_t tmp = val.num;
@ -366,12 +382,6 @@ void compile_udp_functor(char*label, char*type,
}
}
obj->ival = 0xaa;
obj->old_ival = obj->ival;
obj->oval = u->init;
obj->mode = 3;
obj->udp = u;
free(argv);
free(label);
}
@ -944,6 +954,9 @@ void compile_dump(FILE*fd)
/*
* $Log: compile.cc,v $
* Revision 1.41 2001/04/26 03:10:55 steve
* Redo and simplify UDP behavior.
*
* Revision 1.40 2001/04/24 03:48:53 steve
* Fix underflow when UDP has 1 input.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: pointers.h,v 1.3 2001/03/26 04:00:39 steve Exp $"
#ident "$Id: pointers.h,v 1.4 2001/04/26 03:10:55 steve Exp $"
#endif
/*
@ -66,6 +66,14 @@ inline vvp_ipoint_t ipoint_index(vvp_ipoint_t base, unsigned idx)
return base + (idx<<2);
}
/*
* Return the ipoint of an input into a multi-functor input vector.
*/
inline vvp_ipoint_t ipoint_input_index(vvp_ipoint_t base, unsigned idx)
{
return (base & ~3) + idx;
}
/*
* This function returns the port index of a functor given a complete
* vvp_ipoint_t pointer.
@ -94,6 +102,9 @@ typedef struct vthread_s*vthread_t;
/*
* $Log: pointers.h,v $
* Revision 1.4 2001/04/26 03:10:55 steve
* Redo and simplify UDP behavior.
*
* Revision 1.3 2001/03/26 04:00:39 steve
* Add the .event statement and the %wait instruction.
*

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: udp.cc,v 1.1 2001/04/24 02:23:59 steve Exp $"
#ident "$Id: udp.cc,v 1.2 2001/04/26 03:10:55 steve Exp $"
#endif
#include "udp.h"
@ -56,27 +56,6 @@ struct vvp_udp_s *udp_find(char *label)
return (struct vvp_udp_s *)v.ptr;
}
void udp_init_links(vvp_ipoint_t fdx, struct vvp_udp_s *u)
{
udp_idx_t ux(fdx, u);
do
{
vvp_ipoint_t pa = ux.parent();
if (pa)
{
functor_t fu = ux.functor();
functor_t fp = functor_index(pa);
fp->port[ipoint_port(pa)] = 0x0;
fu->out = pa;
fu->udp = 0x0;
fu->mode = 3;
fu->ival = 0xaa;
fu->old_ival = fu->ival;
}
} while (ux.next_node());
}
unsigned char udp_propagate(vvp_ipoint_t uix)
{
functor_t fu = functor_index(uix);
@ -84,8 +63,6 @@ unsigned char udp_propagate(vvp_ipoint_t uix)
assert(u);
assert(u->table);
udp_idx_t ux(uix, u);
unsigned char ret = 2;
for (char **rptr = u->table; *rptr ; rptr++)
@ -94,24 +71,34 @@ unsigned char udp_propagate(vvp_ipoint_t uix)
if (u->sequ)
{
if (row[0]=='?' || row[0]==(fu->oval&3)["01xx"])
char old_out = (fu->oval&3)["01xx"];
if ( row[0]=='?'
|| row[0]==old_out
|| (row[0]=='b' && old_out!='x')
|| (row[0]=='l' && old_out!='1')
|| (row[0]=='h' && old_out!='0') )
row++;
else
continue;
}
ux.reset();
int i;
do
for (i=0; i < u->nin; i++, row++)
{
assert (*row);
int port = ipoint_port(ux.ipoint());
functor_t pfun = ux.functor();
int idx = ipoint_input_index(uix, i);
int port = ipoint_port(idx);
functor_t pfun = functor_index(idx);
char new_bit = ((pfun->ival >> (2*port))&3)["01xx"];
if (*row != new_bit && *row != '?')
if ( *row != new_bit
&& *row != '?'
&& (*row != 'b' || new_bit == 'x')
&& (*row != 'l' || new_bit == '1')
&& (*row != 'h' || new_bit == '0') )
{
char old_bit = ((pfun->old_ival >> (2*port))&3)["01xx"];
if (new_bit == old_bit)
@ -133,6 +120,10 @@ unsigned char udp_propagate(vvp_ipoint_t uix)
if (new_bit == 'x')
continue;
break;
case 'B':
if (old_bit == 'x')
continue;
break;
case 'r':
if (old_bit=='0' && new_bit=='1')
continue;
@ -168,9 +159,9 @@ unsigned char udp_propagate(vvp_ipoint_t uix)
}
break;
}
} while (row++, ux.next());
}
if (ux.done())
if (i == u->nin)
{
assert(*row);
if (*row == '-')
@ -192,18 +183,20 @@ unsigned char udp_propagate(vvp_ipoint_t uix)
}
}
ux.reset();
do
for (int i=0; i < u->nin; i+=4)
{
functor_t fu = ux.functor();
functor_t fu = functor_index(ipoint_input_index(uix, i));
fu->old_ival = fu->ival;
} while (ux.next_node());
}
return ret;
}
/*
* $Log: udp.cc,v $
* Revision 1.2 2001/04/26 03:10:55 steve
* Redo and simplify UDP behavior.
*
* Revision 1.1 2001/04/24 02:23:59 steve
* Support for UDP devices in VVP (Stephen Boettcher)
*

View File

@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: udp.h,v 1.2 2001/04/24 03:48:53 steve Exp $"
#ident "$Id: udp.h,v 1.3 2001/04/26 03:10:55 steve Exp $"
#endif
#include "pointers.h"
@ -36,90 +36,15 @@ struct vvp_udp_s
char **table;
};
void udp_init_links(vvp_ipoint_t fdx, struct vvp_udp_s *u);
struct vvp_udp_s *udp_create(char *label);
struct vvp_udp_s *udp_find(char *label);
unsigned char udp_propagate(vvp_ipoint_t);
// The iterator through the input port list/tree/whatever
class udp_idx_t
{
public:
udp_idx_t(vvp_ipoint_t, struct vvp_udp_s *);
vvp_ipoint_t ipoint();
functor_t functor();
bool next();
vvp_ipoint_t next_node();
bool done();
vvp_ipoint_t parent();
void reset();
private:
vvp_ipoint_t root;
unsigned nin;
unsigned cur_i;
};
inline void udp_idx_t::reset()
{
cur_i = 0;
}
inline udp_idx_t::udp_idx_t(vvp_ipoint_t idx, struct vvp_udp_s *u)
: root(idx), nin(u->nin)
{
reset();
}
inline bool udp_idx_t::done()
{
return cur_i >= nin;
}
inline bool udp_idx_t::next()
{
cur_i++;
return !done();
}
inline vvp_ipoint_t udp_idx_t::ipoint()
{
// The last node in the chain can hold 4 inputs.
int idx = (cur_i==nin-1 && cur_i ? cur_i-1 : cur_i) / 3;
int port = cur_i - 3*idx;
return ipoint_make(ipoint_index(root, idx), port);
}
inline functor_t udp_idx_t::functor()
{
return functor_index(ipoint());
}
// junp to the next node, and return the ipoint.
inline vvp_ipoint_t udp_idx_t::next_node()
{
// We omit the last-node case, since is is a don't care here.
int idx = cur_i / 3 + 1;
cur_i = idx*3+1;
return cur_i < nin
? ipoint_make(ipoint_index(root, idx),0)
: 0;
}
inline vvp_ipoint_t udp_idx_t::parent()
{
if (nin<=4)
return 0x0;
int idx = (cur_i==nin-1 ? cur_i-1 : cur_i) / 3;
if (!idx)
return 0x0;
return ipoint_make(ipoint_index(root, idx-1), 3);
}
/*
* $Log: udp.h,v $
* Revision 1.3 2001/04/26 03:10:55 steve
* Redo and simplify UDP behavior.
*
* Revision 1.2 2001/04/24 03:48:53 steve
* Fix underflow when UDP has 1 input.
*