Runtime support for functor delays. (Stephan Boettcher)
This commit is contained in:
parent
4d0b840c26
commit
4a74ae1795
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.31 2001/11/06 03:07:21 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.32 2001/11/10 18:07:11 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -65,7 +65,7 @@ vpi_vthr_vector.o vvp_vpi.o
|
|||
|
||||
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o debug.o \
|
||||
functor.o fvectors.o npmos.o resolv.o symbols.o codes.o vthread.o schedule.o \
|
||||
tables.o udp.o memory.o force.o event.o logic.o $V
|
||||
tables.o udp.o memory.o force.o event.o logic.o delay.o $V
|
||||
|
||||
vvp: $O
|
||||
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(LIBS) $(dllib)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: delay.cc,v 1.1 2001/11/10 18:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "delay.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
inline static unsigned dmin(unsigned d1, unsigned d2)
|
||||
{
|
||||
return (d1 < d2) ? d1 : d2;
|
||||
}
|
||||
|
||||
inline static unsigned dmax(unsigned d1, unsigned d2)
|
||||
{
|
||||
return (d1 > d2) ? d1 : d2;
|
||||
}
|
||||
|
||||
typedef const unsigned char tab_t;
|
||||
// 01 0x 0z 10 1x 1z x0 x1 xz z0 z1 zx
|
||||
static tab_t tab_1 [16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static tab_t tab_4 [16] = { 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 3, 2, 1, 0, 3, 2};
|
||||
static tab_t tab_6 [16] = { 1, 0, 3, 2, 1, 0, 4, 2, 1, 0, 5, 2, 1, 0, 5, 2};
|
||||
static tab_t tab_12[16] = { 1, 0, 6, 2, 1, 0, 8, 4, 9, 7,11,10, 5, 3,11,10};
|
||||
|
||||
inline unsigned vvp_delay_size(vvp_delay_t del)
|
||||
{
|
||||
return del ? del->size() : 0;
|
||||
}
|
||||
|
||||
inline vvp_delay_s::vvp_delay_s(const unsigned char *t)
|
||||
{
|
||||
memcpy((void*)tab, (void*)t, sizeof(tab));
|
||||
}
|
||||
|
||||
vvp_delay_s::vvp_delay_s(unsigned d)
|
||||
{
|
||||
memcpy((void*)tab, (void*)tab_1, sizeof(tab));
|
||||
del[0] = d;
|
||||
}
|
||||
vvp_delay_2_s::vvp_delay_2_s(unsigned r, unsigned f)
|
||||
: vvp_delay_s(tab_4)
|
||||
{
|
||||
del[0] = r;
|
||||
del[1] = f;
|
||||
del[2] = dmax(r, f);
|
||||
del[3] = dmin(r, f);
|
||||
}
|
||||
|
||||
vvp_delay_3_s::vvp_delay_3_s(unsigned r, unsigned f, unsigned z)
|
||||
: vvp_delay_s(tab_6)
|
||||
{
|
||||
del[0] = r;
|
||||
del[1] = f;
|
||||
del[2] = z;
|
||||
del[3] = dmin(r, z);
|
||||
del[4] = dmin(f, z);
|
||||
del[5] = dmin(r, f);
|
||||
}
|
||||
|
||||
vvp_delay_6_s::vvp_delay_6_s(unsigned r, unsigned f, unsigned rz,
|
||||
unsigned zr, unsigned fz, unsigned zf)
|
||||
: vvp_delay_12_s(r, f, rz, zr, fz, zf,
|
||||
dmin(r, rz),
|
||||
dmax(r, zr),
|
||||
dmin(f, fz),
|
||||
dmax(f, zf),
|
||||
dmax(rz, fz),
|
||||
dmin(zr, zf))
|
||||
{}
|
||||
|
||||
vvp_delay_12_s::vvp_delay_12_s(unsigned r, unsigned f, unsigned rz,
|
||||
unsigned zr, unsigned fz, unsigned zf,
|
||||
unsigned rx, unsigned xr, unsigned fx,
|
||||
unsigned xf, unsigned xz, unsigned zx)
|
||||
: vvp_delay_s(tab_12)
|
||||
{
|
||||
del[0] = r;
|
||||
del[1] = f;
|
||||
del[2] = rz;
|
||||
del[3] = zr;
|
||||
del[4] = fz;
|
||||
del[5] = zf;
|
||||
del[6] = rx;
|
||||
del[7] = xr;
|
||||
del[8] = fx;
|
||||
del[9] = xf;
|
||||
del[10] = xz;
|
||||
del[11] = zx;
|
||||
}
|
||||
|
||||
vvp_delay_t vvp_delay_new(unsigned n, unsigned *dels)
|
||||
{
|
||||
switch (n) {
|
||||
default:
|
||||
assert(0);
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return new vvp_delay_s(dels[0]);
|
||||
case 2:
|
||||
return new vvp_delay_2_s(dels[0], dels[1]);
|
||||
case 3:
|
||||
return new vvp_delay_3_s(dels[0], dels[1], dels[2]);
|
||||
case 6:
|
||||
return new vvp_delay_6_s(dels[0], dels[1], dels[2],
|
||||
dels[3], dels[4], dels[5]);
|
||||
case 12:
|
||||
return new vvp_delay_12_s(dels[0], dels[1], dels[2],
|
||||
dels[3], dels[4], dels[5],
|
||||
dels[6], dels[7], dels[8],
|
||||
dels[9], dels[10], dels[11]);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_delay_delete(vvp_delay_t del)
|
||||
{
|
||||
switch (vvp_delay_size(del)) {
|
||||
case 1: delete del; break;
|
||||
case 4: delete static_cast<vvp_delay_2_s *>(del); break;
|
||||
case 6: delete static_cast<vvp_delay_3_s *>(del); break;
|
||||
case 12: delete static_cast<vvp_delay_12_s *>(del); break;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_delay_t vvp_delay_add(vvp_delay_t d1, vvp_delay_t d2)
|
||||
{
|
||||
unsigned s1 = vvp_delay_size(d1);
|
||||
unsigned s2 = vvp_delay_size(d2);
|
||||
vvp_delay_t out = s1 > s2 ? d1 : d2;
|
||||
if (s1==0 || s2==0)
|
||||
return out;
|
||||
|
||||
vvp_delay_t oth = s1 > s2 ? d2 : d1;
|
||||
unsigned s = s1 > s2 ? s1 : s2;
|
||||
unsigned so = s1 > s2 ? s2 : s1;
|
||||
|
||||
if (s==so)
|
||||
for (unsigned i=0; i<s; i++)
|
||||
out->del[i] = oth->del[i];
|
||||
else switch (so) {
|
||||
case 1:
|
||||
for (unsigned i=0; i<s; i++)
|
||||
out->del[i] = oth->del[0];
|
||||
break;
|
||||
|
||||
case 4:
|
||||
switch (s) {
|
||||
case 6:
|
||||
out->del[0] = oth->del[0];
|
||||
out->del[1] = oth->del[1];
|
||||
out->del[2] = oth->del[4];
|
||||
out->del[3] = oth->del[4];
|
||||
out->del[4] = oth->del[4];
|
||||
out->del[5] = oth->del[4];
|
||||
break;
|
||||
case 12:
|
||||
out->del[ 0] = oth->del[0];
|
||||
out->del[ 1] = oth->del[1];
|
||||
out->del[ 2] = oth->del[0];
|
||||
out->del[ 3] = oth->del[0];
|
||||
out->del[ 4] = oth->del[1];
|
||||
out->del[ 5] = oth->del[1];
|
||||
out->del[ 6] = oth->del[0];
|
||||
out->del[ 7] = oth->del[0];
|
||||
out->del[ 8] = oth->del[1];
|
||||
out->del[ 9] = oth->del[1];
|
||||
out->del[10] = oth->del[2];
|
||||
out->del[11] = oth->del[3];
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
out->del[ 0] = oth->del[0];
|
||||
out->del[ 1] = oth->del[1];
|
||||
out->del[ 2] = oth->del[2];
|
||||
out->del[ 3] = oth->del[0];
|
||||
out->del[ 4] = oth->del[2];
|
||||
out->del[ 5] = oth->del[1];
|
||||
out->del[ 6] = oth->del[3];
|
||||
out->del[ 7] = oth->del[0];
|
||||
out->del[ 8] = oth->del[4];
|
||||
out->del[ 9] = oth->del[1];
|
||||
out->del[10] = oth->del[2];
|
||||
out->del[11] = oth->del[5];
|
||||
break;
|
||||
}
|
||||
|
||||
vvp_delay_delete(oth);
|
||||
return out;
|
||||
}
|
||||
|
||||
vvp_delay_t vvp_delay_set(vvp_delay_t tgt, vvp_delay_t src, unsigned mask)
|
||||
{
|
||||
unsigned stgt = vvp_delay_size(tgt);
|
||||
unsigned ssrc = vvp_delay_size(src);
|
||||
|
||||
if (stgt == 0)
|
||||
return src;
|
||||
if (ssrc == 0)
|
||||
return tgt;
|
||||
|
||||
if (stgt == ssrc) {
|
||||
for (unsigned i=0; i<stgt; i++)
|
||||
if (!(mask & (1<<i)))
|
||||
tgt->del[i] = src->del[i];
|
||||
|
||||
vvp_delay_delete(src);
|
||||
return tgt;
|
||||
}
|
||||
#if 0 // later
|
||||
if (mask) {
|
||||
static bool done_that = false;
|
||||
if (!done_that) {
|
||||
vvp_printf(VVP_PRINT_WARNING,
|
||||
"Warning:"
|
||||
" partial replacement of delay values"
|
||||
" of different size"
|
||||
" not supported\n"
|
||||
" either replace all edges,"
|
||||
" or specify the same number of values\n" );
|
||||
done_that = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vvp_delay_delete(tgt);
|
||||
return src;
|
||||
}
|
||||
|
||||
/*
|
||||
** $Log: delay.cc,v $
|
||||
** Revision 1.1 2001/11/10 18:07:11 steve
|
||||
** Runtime support for functor delays. (Stephan Boettcher)
|
||||
**
|
||||
*/
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
#ifndef __delay_H /* -*- c++ -*- */
|
||||
#define __delay_H
|
||||
/*
|
||||
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: delay.h,v 1.1 2001/11/10 18:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** vvp_delay_t del;
|
||||
**
|
||||
** del = vvp_delay_new(n, dels);
|
||||
** make a delay from n delay specs in array dels.
|
||||
** n = 0, 1, 2, 3, 6, 12.
|
||||
**
|
||||
** unsigned vvp_delay_get(del, from, to);
|
||||
** tells the delay for the edge (from->to).
|
||||
**
|
||||
** del = NULL;
|
||||
** new delay with zero delay.
|
||||
**
|
||||
** del = new vvp_delay_s(delay);
|
||||
** new delay with one spec for all edges.
|
||||
**
|
||||
** del = new vvp_delay_2_s(delay, delay);
|
||||
** new delay with two specs for rise and fall delays.
|
||||
**
|
||||
** del = new vvp_delay_3_s(delay);
|
||||
** new delay with three specs for rise, fall, and highz delays.
|
||||
**
|
||||
** del = new vvp_delay_6_s(delay, del...);
|
||||
** new delay with six specs for all 01z edge delays.
|
||||
**
|
||||
** del = new vvp_delay_12_s(delay, del...);
|
||||
** new delay with twelve specs for all edge delays.
|
||||
**
|
||||
** void vvp_delsy_delete(del);
|
||||
** delete a delay.
|
||||
**
|
||||
** del = vvp_delay_add(del1, del2);
|
||||
** add the delay spaces. del1 and del2 are deleted.
|
||||
**
|
||||
** del = vvp_delay_set(tgt, src, mask);
|
||||
** set then non-masked edges of delay tgt from src.
|
||||
** tgt and src are deleted.
|
||||
*/
|
||||
|
||||
typedef struct vvp_delay_s *vvp_delay_t;
|
||||
|
||||
struct vvp_delay_s {
|
||||
vvp_delay_s(unsigned);
|
||||
unsigned delay(unsigned char idx) { return del[tab[idx]]; }
|
||||
unsigned size() { return tab[14]+1; }
|
||||
protected:
|
||||
vvp_delay_s(const unsigned char *t);
|
||||
private:
|
||||
unsigned char tab[16];
|
||||
public:
|
||||
unsigned del[1];
|
||||
};
|
||||
|
||||
struct vvp_delay_2_s : public vvp_delay_s {
|
||||
vvp_delay_2_s(unsigned, unsigned);
|
||||
unsigned dell[4-1];
|
||||
};
|
||||
|
||||
struct vvp_delay_3_s : public vvp_delay_s {
|
||||
vvp_delay_3_s(unsigned, unsigned, unsigned);
|
||||
unsigned dell[6-1];
|
||||
};
|
||||
|
||||
struct vvp_delay_12_s : public vvp_delay_s {
|
||||
vvp_delay_12_s(unsigned, unsigned, unsigned,
|
||||
unsigned, unsigned, unsigned,
|
||||
unsigned, unsigned, unsigned,
|
||||
unsigned, unsigned, unsigned);
|
||||
unsigned dell[12-1];
|
||||
};
|
||||
|
||||
struct vvp_delay_6_s : public vvp_delay_12_s {
|
||||
vvp_delay_6_s(unsigned, unsigned, unsigned,
|
||||
unsigned, unsigned, unsigned);
|
||||
};
|
||||
|
||||
inline static
|
||||
unsigned vvp_delay_get(vvp_delay_t del, unsigned char oval, unsigned char nval)
|
||||
{
|
||||
unsigned char idx = nval | (oval << 2);
|
||||
return del->delay(idx);
|
||||
}
|
||||
|
||||
vvp_delay_t vvp_delay_new(unsigned n, unsigned *dels);
|
||||
void vvp_delay_delete(vvp_delay_t);
|
||||
vvp_delay_t vvp_delay_add(vvp_delay_t, vvp_delay_t);
|
||||
vvp_delay_t vvp_delay_set(vvp_delay_t tgt, vvp_delay_t src,
|
||||
unsigned mask = 0);
|
||||
|
||||
/*
|
||||
** $Log: delay.h,v $
|
||||
** Revision 1.1 2001/11/10 18:07:11 steve
|
||||
** Runtime support for functor delays. (Stephan Boettcher)
|
||||
**
|
||||
*/
|
||||
#endif // __delay_H
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.cc,v 1.32 2001/11/06 03:07:22 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.33 2001/11/10 18:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
|
|
@ -106,6 +106,7 @@ void functor_define(vvp_ipoint_t point, functor_t obj)
|
|||
|
||||
functor_s::functor_s()
|
||||
{
|
||||
delay = 0;
|
||||
out = 0;
|
||||
port[0] = 0;
|
||||
port[1] = 0;
|
||||
|
|
@ -167,6 +168,9 @@ edge_inputs_functor_s::~edge_inputs_functor_s()
|
|||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.33 2001/11/10 18:07:11 steve
|
||||
* Runtime support for functor delays. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.32 2001/11/06 03:07:22 steve
|
||||
* Code rearrange. (Stephan Boettcher)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.h,v 1.38 2001/11/07 03:34:42 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.39 2001/11/10 18:07:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "pointers.h"
|
||||
# include "delay.h"
|
||||
|
||||
/*
|
||||
* Create a propagation event. The fun parameter points to the functor
|
||||
|
|
@ -149,6 +150,9 @@ extern void functor_define(vvp_ipoint_t point, functor_t obj);
|
|||
struct functor_s {
|
||||
functor_s();
|
||||
virtual ~functor_s();
|
||||
|
||||
/* delay object */
|
||||
vvp_delay_t delay;
|
||||
/* This is the output for the device. */
|
||||
vvp_ipoint_t out;
|
||||
/* These are the input ports. */
|
||||
|
|
@ -215,6 +219,30 @@ inline void functor_s::propagate(bool push)
|
|||
}
|
||||
}
|
||||
|
||||
inline void functor_s::put_ostr(bool push, unsigned val, unsigned str)
|
||||
{
|
||||
if (val != oval || str != ostr) {
|
||||
|
||||
ostr = str;
|
||||
|
||||
if (inhibit)
|
||||
return;
|
||||
|
||||
oval = val;
|
||||
|
||||
unsigned del;
|
||||
if (delay)
|
||||
del = vvp_delay_get(delay, oval, val);
|
||||
else
|
||||
del = 0;
|
||||
|
||||
if (del == 0 && push)
|
||||
propagate(true);
|
||||
else
|
||||
schedule_functor(this, del);
|
||||
}
|
||||
}
|
||||
|
||||
inline void functor_s::put_oval(bool push, unsigned val)
|
||||
{
|
||||
switch (val) {
|
||||
|
|
@ -231,29 +259,8 @@ inline void functor_s::put_oval(bool push, unsigned val)
|
|||
ostr = 0x00;
|
||||
break;
|
||||
}
|
||||
if (inhibit)
|
||||
return;
|
||||
if (val != oval) {
|
||||
oval = val;
|
||||
if (push)
|
||||
propagate(true);
|
||||
else
|
||||
schedule_functor(this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline void functor_s::put_ostr(bool push, unsigned val, unsigned str)
|
||||
{
|
||||
if (val != oval || str != ostr) {
|
||||
ostr = str;
|
||||
if (inhibit)
|
||||
return;
|
||||
oval = val;
|
||||
if (push)
|
||||
propagate(true);
|
||||
else
|
||||
schedule_functor(this, 0);
|
||||
}
|
||||
put_ostr(push, val, ostr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -369,6 +376,9 @@ extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
|
|||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.39 2001/11/10 18:07:12 steve
|
||||
* Runtime support for functor delays. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.38 2001/11/07 03:34:42 steve
|
||||
* Use functor pointers where vvp_ipoint_t is unneeded.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue