Rewrite the functor type to have fewer functor modes,

and use objects to manage the different types.
 (Stephan Boettcher)
This commit is contained in:
steve 2001-10-31 04:27:46 +00:00
parent b3e430c751
commit a75326e2e0
24 changed files with 1306 additions and 1611 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: arith.cc,v 1.17 2001/10/27 03:22:26 steve Exp $"
#ident "$Id: arith.cc,v 1.18 2001/10/31 04:27:46 steve Exp $"
#endif
# include "arith.h"
@ -25,137 +25,141 @@
# include <limits.h>
# include <stdio.h>
# include <assert.h>
# include <malloc.h>
vvp_arith_::vvp_arith_(vvp_ipoint_t b, unsigned w)
: base_(b), wid_(w)
{
}
void vvp_arith_::output_x_(bool push)
void vvp_arith_::output_x_(vvp_ipoint_t base, bool push, unsigned val)
{
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
obj->put_oval(ptr, push, val);
}
}
void vvp_arith_::output_val_(vvp_ipoint_t base, bool push, unsigned long sum)
{
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
unsigned val = sum & 1;
sum >>= 1;
obj->put_oval(ptr, push, val);
}
}
// Make sure the static sum_ scratch space is large enough for everybody
vvp_wide_arith_::vvp_wide_arith_(unsigned wid)
: vvp_arith_(wid)
{
unsigned np = (wid + pagesize - 1)/pagesize;
sum_ = (unsigned long *)malloc(np*sizeof(unsigned long));
assert(sum_);
}
void vvp_wide_arith_::output_val_(vvp_ipoint_t base, bool push)
{
unsigned page = 0;
unsigned pbit = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
if (obj->oval == 2)
continue;
unsigned val = (sum_[page] >> pbit) & 1;
obj->oval = 2;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
pbit += 1;
if (pbit == pagesize) {
pbit = 0;
page += 1;
}
obj->put_oval(ptr, push, val);
}
}
vvp_arith_div::vvp_arith_div(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
// Division
inline void vvp_arith_div::wide(vvp_ipoint_t base, bool push)
{
assert(0);
}
void vvp_arith_div::set(vvp_ipoint_t i, functor_t f, bool push)
void vvp_arith_div::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
if (wid_ <= 8*sizeof(unsigned long)) {
unsigned long a = 0, b = 0;
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
if(wid_ > 8*sizeof(unsigned long)) {
wide(base, push);
return;
}
unsigned ival = obj->ival;
if (ival & 0xaa) {
fprintf(stderr, "Division by 0 error: "
"returning X value\n");
output_x_(push);
return;
}
if (ival & 0x01)
a += 1 << idx;
if (ival & 0x04)
b += 1 << idx;
}
if (b == 0) {
output_x_(push);
unsigned long a = 0, b = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
unsigned val = obj->ival;
if (val & 0xaa) {
output_x_(base, push);
return;
}
unsigned long sum = a / b;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
unsigned oval = sum & 1;
sum >>= 1;
if (obj->oval == oval)
continue;
obj->oval = oval;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
} else {
assert(0);
if (val & 0x01)
a += 1 << idx;
if (val & 0x04)
b += 1 << idx;
}
if (b == 0) {
output_x_(base, push);
return;
}
output_val_(base, push, a/b);
}
vvp_arith_mult::vvp_arith_mult(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
{
}
// Multiplication
void vvp_arith_mult::set(vvp_ipoint_t i, functor_t f, bool push)
void vvp_arith_mult::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
if(wid_ <= 8*sizeof(unsigned long)) {
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
if(wid_ > 8*sizeof(unsigned long)) {
wide(base, push);
return;
}
unsigned long a = 0, b = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0xaa) {
output_x_(push);
unsigned val = obj->ival;
if (val & 0xaa) {
output_x_(base, push);
return;
}
if (ival & 0x01)
if (val & 0x01)
a += 1 << idx;
if (ival & 0x04)
if (val & 0x04)
b += 1 << idx;
}
unsigned long sum = a * b;
output_val_(base, push, a*b);
}
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
unsigned oval = sum & 1;
sum >>= 1;
if (obj->oval == oval)
continue;
obj->oval = oval;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
} else { /* long form only used if > machine length long */
void vvp_arith_mult::wide(vvp_ipoint_t base, bool push)
{
unsigned char *a, *b, *sum;
a = new unsigned char[wid_];
b = new unsigned char[wid_];
@ -165,12 +169,12 @@ if(wid_ <= 8*sizeof(unsigned long)) {
int mxb = -1;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0xaa) {
output_x_(push);
output_x_(base, push);
delete[]sum;
delete[]b;
delete[]a;
@ -201,41 +205,27 @@ if(wid_ <= 8*sizeof(unsigned long)) {
}
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
vvp_ipoint_t ptr = ipoint_index(base,idx);
functor_t obj = functor_index(ptr);
unsigned oval = sum[idx];
unsigned val = sum[idx];
if (obj->oval == oval)
continue;
obj->oval = oval;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
obj->put_oval(ptr, push, val);
}
delete[]sum;
delete[]b;
delete[]a;
delete[]sum;
delete[]b;
delete[]a;
}
}
vvp_arith_sum::vvp_arith_sum(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
// Addition
void vvp_arith_sum::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
sum_ = new unsigned long[(w+1) / 8*sizeof(unsigned long) + 1];
}
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
vvp_arith_sum::~vvp_arith_sum()
{
delete[]sum_;
}
void vvp_arith_sum::set(vvp_ipoint_t i, functor_t f, bool push)
{
unsigned page = 0;
unsigned pbit = 0;
unsigned long carry = 0;
@ -243,116 +233,24 @@ void vvp_arith_sum::set(vvp_ipoint_t i, functor_t f, bool push)
sum_[0] = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0xaa) {
output_x_(push);
unsigned val = obj->ival;
if (val & 0xaa) {
output_x_(base, push);
return;
}
// Accumulate the sum of the input bits.
unsigned long tmp = 0;
if (ival & 0x01)
if (val & 0x01)
tmp += 1;
if (ival & 0x04)
if (val & 0x04)
tmp += 1;
if (ival & 0x10)
if (val & 0x10)
tmp += 1;
if (ival & 0x40)
tmp += 1;
// Save carry bits
if (pbit >= pagesize - 2)
carry += (tmp + (sum_[page]>>pbit)) >> (pagesize-pbit);
// Put the next bit into the sum,
sum_[page] += tmp << pbit;
pbit += 1;
if (pbit >= pagesize) {
pbit = 0;
page += 1;
sum_[page] = carry;
carry = 0;
}
}
page = 0;
pbit = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
unsigned oval = (sum_[page] >> pbit) & 1;
pbit += 1;
if (pbit == 8 * sizeof sum_[page]) {
pbit = 0;
page += 1;
}
if (obj->oval == oval)
continue;
obj->oval = oval;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
}
vvp_arith_sub::vvp_arith_sub(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
{
sum_ = new unsigned long[(w+1) / 8*sizeof(unsigned long) + 1];
}
vvp_arith_sub::~vvp_arith_sub()
{
delete[]sum_;
}
/*
* Subtraction works by adding the 2s complement of the B, C and D
* inputs from the A input. The 2s complement is the 1s complement
* plus one, so we further reduce the operation to adding in the
* inverted value and adding a correction.
*/
void vvp_arith_sub::set(vvp_ipoint_t i, functor_t f, bool push)
{
unsigned page = 0;
unsigned pbit = 0;
unsigned long carry = 0;
/* There are 3 values subtracted from the first parameter, so
there are three 2s complements, so three ~X +1. That's why
the sum_ starts with 3. */
sum_[0] = 3;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0xaa) {
output_x_(push);
return;
}
// Accumulate the sum of the input bits. Add in the
// first value, and the ones complement of the other values.
unsigned long tmp = 0;
if (ival & 0x01)
tmp += 1;
if (! (ival & 0x04))
tmp += 1;
if (! (ival & 0x10))
tmp += 1;
if (! (ival & 0x40))
if (val & 0x40)
tmp += 1;
// Save carry bits
@ -371,55 +269,91 @@ void vvp_arith_sub::set(vvp_ipoint_t i, functor_t f, bool push)
}
}
page = 0;
pbit = 0;
output_val_(base, push);
}
/*
* Subtraction works by adding the 2s complement of the B, C and D
* inputs from the A input. The 2s complement is the 1s complement
* plus one, so we further reduce the operation to adding in the
* inverted value and adding a correction.
*/
void vvp_arith_sub::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned page = 0;
unsigned pbit = 0;
unsigned long carry = 0;
/* There are 3 values subtracted from the first parameter, so
there are three 2s complements, so three ~X +1. That's why
the sum_ starts with 3. */
sum_[0] = 3;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx);
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t obj = functor_index(ptr);
unsigned oval = (sum_[page] >> pbit) & 1;
pbit += 1;
if (pbit == 8 * sizeof sum_[page]) {
pbit = 0;
page += 1;
unsigned val = obj->ival;
if (val & 0xaa) {
output_x_(base, push);
return;
}
if (obj->oval == oval)
continue;
// Accumulate the sum of the input bits. Add in the
// first value, and the ones complement of the other values.
unsigned long tmp = 0;
if (val & 0x01)
tmp += 1;
if (! (val & 0x04))
tmp += 1;
if (! (val & 0x10))
tmp += 1;
if (! (val & 0x40))
tmp += 1;
// Save carry bits
if (pbit >= pagesize - 2)
carry += (tmp + (sum_[page]>>pbit)) >> (pagesize-pbit);
obj->oval = oval;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
// Put the next bits into the sum,
sum_[page] += tmp << pbit;
pbit += 1;
if (pbit >= pagesize) {
pbit = 0;
page += 1;
sum_[page] = carry;
carry = 0;
}
}
output_val_(base, push);
}
vvp_cmp_ge::vvp_cmp_ge(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
{
}
void vvp_cmp_ge::set(vvp_ipoint_t i, functor_t f, bool push)
void vvp_cmp_ge::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
functor_t base_obj = functor_index(base_);
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned out_val = 1;
for (unsigned idx = wid_ ; idx > 0 ; idx -= 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx-1);
vvp_ipoint_t ptr = ipoint_index(base,idx-1);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0x0a) {
unsigned val = obj->ival;
if (val & 0x0a) {
out_val = 2;
break;
}
unsigned a = (ival & 0x01)? 1 : 0;
unsigned b = (ival & 0x04)? 1 : 0;
unsigned a = (val & 0x01)? 1 : 0;
unsigned b = (val & 0x04)? 1 : 0;
if (a > b) {
out_val = 1;
@ -432,37 +366,28 @@ void vvp_cmp_ge::set(vvp_ipoint_t i, functor_t f, bool push)
}
}
if (out_val != base_obj->oval) {
base_obj->oval = out_val;
if (push)
functor_propagate(base_);
else
schedule_functor(base_, 0);
}
put_oval(base, push, out_val);
}
vvp_cmp_gt::vvp_cmp_gt(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
void vvp_cmp_gt::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
}
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
void vvp_cmp_gt::set(vvp_ipoint_t i, functor_t f, bool push)
{
functor_t base_obj = functor_index(base_);
unsigned out_val = 0;
for (unsigned idx = wid_ ; idx > 0 ; idx -= 1) {
vvp_ipoint_t ptr = ipoint_index(base_,idx-1);
vvp_ipoint_t ptr = ipoint_index(base, idx-1);
functor_t obj = functor_index(ptr);
unsigned ival = obj->ival;
if (ival & 0x0a) {
unsigned val = obj->ival;
if (val & 0x0a) {
out_val = 2;
break;
}
unsigned a = (ival & 0x01)? 1 : 0;
unsigned b = (ival & 0x04)? 1 : 0;
unsigned a = (val & 0x01)? 1 : 0;
unsigned b = (val & 0x04)? 1 : 0;
if (a > b) {
out_val = 1;
@ -475,26 +400,19 @@ void vvp_cmp_gt::set(vvp_ipoint_t i, functor_t f, bool push)
}
}
if (out_val != base_obj->oval) {
base_obj->oval = out_val;
if (push)
functor_propagate(base_);
else
schedule_functor(base_, 0);
}
put_oval(base, push, out_val);
}
vvp_shiftl::vvp_shiftl(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
{
amount_ = 0;
}
void vvp_shiftl::set(vvp_ipoint_t i, functor_t f, bool push)
void vvp_shiftl::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
amount_ = 0;
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned amount = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_, idx);
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t fp = functor_index(ptr);
unsigned val = (fp->ival >> 2) & 0x03;
@ -502,73 +420,48 @@ void vvp_shiftl::set(vvp_ipoint_t i, functor_t f, bool push)
case 0:
break;
case 1:
amount_ |= 1 << idx;
amount |= 1 << idx;
break;
default:
output_x_(push);
output_x_(base, push);
return;
}
}
if (amount_ >= wid_) {
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t optr = ipoint_index(base_, idx);
functor_t ofp = functor_index(optr);
if (ofp->oval != 0) {
ofp->oval = 0;
if (push)
functor_propagate(optr);
else
schedule_functor(optr, 0);
}
}
if (amount >= wid_) {
output_x_(base, push, 0);
return;
} else {
vvp_ipoint_t optr, iptr;
functor_t ofp, ifp;
for (unsigned idx = 0 ; idx < amount_ ; idx += 1) {
optr = ipoint_index(base_, idx);
for (unsigned idx = 0 ; idx < amount ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
if (ofp->oval != 0) {
ofp->oval = 0;
if (push)
functor_propagate(optr);
else
schedule_functor(optr, 0);
}
ofp->put_oval(optr, push, 0);
}
for (unsigned idx = amount_ ; idx < wid_ ; idx += 1) {
optr = ipoint_index(base_, idx);
for (unsigned idx = amount ; idx < wid_ ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
iptr = ipoint_index(base_, idx - amount_);
iptr = ipoint_index(base, idx - amount);
ifp = functor_index(iptr);
if (ofp->oval != (ifp->ival&3)) {
ofp->oval = ifp->ival&3;
if (push)
functor_propagate(optr);
else
schedule_functor(optr, 0);
}
ofp->put_oval(optr, push, ifp->ival & 3);
}
}
}
vvp_shiftr::vvp_shiftr(vvp_ipoint_t b, unsigned w)
: vvp_arith_(b, w)
void vvp_shiftr::set(vvp_ipoint_t i, bool push, unsigned val, unsigned)
{
amount_ = 0;
}
put(i, val);
vvp_ipoint_t base = ipoint_make(i,0);
unsigned amount = 0;
void vvp_shiftr::set(vvp_ipoint_t i, functor_t f, bool push)
{
amount_ = 0;
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(base_, idx);
vvp_ipoint_t ptr = ipoint_index(base, idx);
functor_t fp = functor_index(ptr);
unsigned val = (fp->ival >> 2) & 0x03;
@ -576,56 +469,35 @@ void vvp_shiftr::set(vvp_ipoint_t i, functor_t f, bool push)
case 0:
break;
case 1:
amount_ |= 1 << idx;
amount |= 1 << idx;
break;
default:
output_x_(push);
output_x_(base, push);
return;
}
}
if (amount_ >= wid_) {
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
vvp_ipoint_t optr = ipoint_index(base_, idx);
functor_t ofp = functor_index(optr);
if (ofp->oval != 0) {
ofp->oval = 0;
if (push)
functor_propagate(optr);
else
schedule_functor(optr, 0);
}
}
if (amount >= wid_) {
output_x_(base, push, 0);
return;
} else {
vvp_ipoint_t optr, iptr;
functor_t ofp, ifp;
for (unsigned idx = 0 ; idx < (wid_-amount_) ; idx += 1) {
optr = ipoint_index(base_, idx);
for (unsigned idx = 0 ; idx < (wid_-amount) ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
iptr = ipoint_index(base_, idx + amount_);
iptr = ipoint_index(base, idx + amount);
ifp = functor_index(iptr);
if (ofp->oval != (ifp->ival&3)) {
ofp->oval = ifp->ival&3;
if (push)
functor_propagate(optr);
else
schedule_functor(optr, 0);
}
ofp->put_oval(optr, push, ifp->ival & 3);
}
for (unsigned idx = wid_-amount_; idx < wid_ ; idx += 1) {
optr = ipoint_index(base_, idx);
for (unsigned idx = wid_-amount; idx < wid_ ; idx += 1) {
optr = ipoint_index(base, idx);
ofp = functor_index(optr);
if (ofp->oval != 0) {
ofp->oval = 0;
if (push)
functor_propagate(optr);
else
schedule_functor(optr, 0);
}
ofp->put_oval(optr, push, 0);
}
}
}
@ -633,6 +505,11 @@ void vvp_shiftr::set(vvp_ipoint_t i, functor_t f, bool push)
/*
* $Log: arith.cc,v $
* Revision 1.18 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.17 2001/10/27 03:22:26 steve
* Minor rework of summation carry propagation (Stephan Boettcher)
*

View File

@ -19,148 +19,117 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: arith.h,v 1.10 2001/10/27 03:22:26 steve Exp $"
#ident "$Id: arith.h,v 1.11 2001/10/31 04:27:46 steve Exp $"
#endif
# include "functor.h"
class vvp_arith_ : public vvp_fobj_s {
// base class for arithmetic functors
class vvp_arith_ : public functor_s {
public:
explicit vvp_arith_(vvp_ipoint_t b, unsigned wid);
explicit vvp_arith_(unsigned wid) : wid_(wid) {};
protected:
vvp_ipoint_t base_;
unsigned wid_;
protected:
void output_x_(bool push);
private: // not implemented
vvp_arith_(const vvp_arith_&);
vvp_arith_& operator= (const vvp_arith_&);
void output_x_(vvp_ipoint_t base, bool push, unsigned val = 2);
void output_val_(vvp_ipoint_t base, bool push, unsigned long sum);
};
// base class for wide arithmetic functors
class vvp_wide_arith_ : public vvp_arith_ {
public:
explicit vvp_wide_arith_(unsigned wid);
protected:
static const unsigned pagesize = 8*sizeof(unsigned long);
unsigned long *sum_;
void output_val_(vvp_ipoint_t base, bool push);
};
/*
* This class is a mode-42 object for arithmetic operators. Inputs
* that come in cause the 4-input summation to be calculated, and
* output functors that are affected cause propagations.
* This class is functor for arithmetic sum. Inputs that come
* in cause the 4-input summation to be calculated, and output
* functors that are affected cause propagations.
*/
class vvp_arith_div : public vvp_arith_ {
public:
explicit vvp_arith_div(vvp_ipoint_t b, unsigned wid);
void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_arith_div(const vvp_arith_div&);
vvp_arith_div& operator= (const vvp_arith_div&);
};
class vvp_arith_mult : public vvp_arith_ {
public:
explicit vvp_arith_mult(vvp_ipoint_t b, unsigned wid);
explicit vvp_arith_mult(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_arith_mult(const vvp_arith_mult&);
vvp_arith_mult& operator= (const vvp_arith_mult&);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
void wide(vvp_ipoint_t base, bool push);
};
class vvp_arith_sum : public vvp_arith_ {
class vvp_arith_div : public vvp_arith_ {
public:
explicit vvp_arith_sum(vvp_ipoint_t b, unsigned wid);
virtual ~vvp_arith_sum();
explicit vvp_arith_div(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
private:
unsigned long*sum_;
static const unsigned pagesize = 8*sizeof(unsigned long);
private: // not implemented
vvp_arith_sum(const vvp_arith_sum&);
vvp_arith_sum& operator= (const vvp_arith_sum&);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
void wide(vvp_ipoint_t base, bool push);
};
class vvp_arith_sub : public vvp_arith_ {
class vvp_arith_sum : public vvp_wide_arith_ {
public:
explicit vvp_arith_sub(vvp_ipoint_t b, unsigned wid);
virtual ~vvp_arith_sub();
explicit vvp_arith_sum(unsigned wid) : vvp_wide_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
private:
unsigned long*sum_;
static const unsigned pagesize = 8*sizeof(unsigned long);
class vvp_arith_sub : public vvp_wide_arith_ {
private: // not implemented
vvp_arith_sub(const vvp_arith_sub&);
vvp_arith_sub& operator= (const vvp_arith_sub&);
public:
explicit vvp_arith_sub(unsigned wid) : vvp_wide_arith_(wid) {}
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
class vvp_cmp_ge : public vvp_arith_ {
public:
explicit vvp_cmp_ge(vvp_ipoint_t b, unsigned wid);
explicit vvp_cmp_ge(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_cmp_ge(const vvp_cmp_ge&);
vvp_cmp_ge& operator= (const vvp_cmp_ge&);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
class vvp_cmp_gt : public vvp_arith_ {
public:
explicit vvp_cmp_gt(vvp_ipoint_t b, unsigned wid);
explicit vvp_cmp_gt(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_cmp_gt(const vvp_cmp_gt&);
vvp_cmp_gt& operator= (const vvp_cmp_gt&);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
class vvp_shiftl : public vvp_arith_ {
public:
explicit vvp_shiftl(vvp_ipoint_t b, unsigned wid);
explicit vvp_shiftl(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
private:
unsigned amount_;
private: // not implemented
vvp_shiftl(const vvp_shiftl&);
vvp_shiftl& operator= (const vvp_shiftl&);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
class vvp_shiftr : public vvp_arith_ {
public:
explicit vvp_shiftr(vvp_ipoint_t b, unsigned wid);
explicit vvp_shiftr(unsigned wid) : vvp_arith_(wid) {}
void set(vvp_ipoint_t i, functor_t f, bool push);
private:
unsigned amount_;
private: // not implemented
vvp_shiftr(const vvp_shiftr&);
vvp_shiftr& operator= (const vvp_shiftr&);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
/*
* $Log: arith.h,v $
* Revision 1.11 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.10 2001/10/27 03:22:26 steve
* Minor rework of summation carry propagation (Stephan Boettcher)
*

View File

@ -17,129 +17,79 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: bufif.cc,v 1.1 2001/05/31 04:12:43 steve Exp $"
#ident "$Id: bufif.cc,v 1.2 2001/10/31 04:27:46 steve Exp $"
#endif
# include "bufif.h"
# include "functor.h"
# include "schedule.h"
void vvp_bufif0_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
void vvp_bufif1_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned)
{
unsigned in0 = fp->ival & 0x03;
unsigned in1 = (fp->ival >> 2) & 0x03;
put(ptr, v);
unsigned char out0 = 0x00 | (fp->odrive0<<0) | (fp->odrive0<<4);
unsigned char out1 = 0x88 | (fp->odrive1<<0) | (fp->odrive1<<4);
unsigned char outX = 0x80 | (fp->odrive1<<0) | (fp->odrive0<<4);
unsigned char outH = 0x88 | (fp->odrive1<<4) | (0);
unsigned char outL = 0x00 | (fp->odrive1<<0) | (0);
unsigned in0 = ival & 0x03;
unsigned in1 = (ival >> 2) & 0x03;
switch (in1) {
unsigned char out0 = 0x00 | (odrive0<<0) | (odrive0<<4);
unsigned char out1 = 0x88 | (odrive1<<0) | (odrive1<<4);
unsigned char outX = 0x80 | (odrive1<<0) | (odrive0<<4);
unsigned char outH = 0x88 | (0) | (odrive1<<4);
unsigned char outL = 0x00 | (odrive1<<0) | (0);
case 0:
switch (in0) {
case 0:
fp->oval = 0;
fp->ostr = out0;
break;
case 1:
fp->oval = 1;
fp->ostr = out1;
break;
default:
fp->oval = 2;
fp->ostr = outX;
break;
}
break;
unsigned val;
unsigned str;
case 1:
fp->oval = 3;
fp->ostr = HiZ;
break;
default:
fp->oval = 2;
switch (in0) {
case 0:
fp->ostr = outL;
break;
case 1:
fp->ostr = outH;
break;
default:
fp->ostr = outX;
break;
}
break;
}
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
void vvp_bufif1_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
{
unsigned in0 = fp->ival & 0x03;
unsigned in1 = (fp->ival >> 2) & 0x03;
unsigned char out0 = 0x00 | (fp->odrive0<<0) | (fp->odrive0<<4);
unsigned char out1 = 0x88 | (fp->odrive1<<0) | (fp->odrive1<<4);
unsigned char outX = 0x80 | (fp->odrive1<<0) | (fp->odrive0<<4);
unsigned char outH = 0x88 | (fp->odrive1<<4) | (0);
unsigned char outL = 0x00 | (fp->odrive1<<0) | (0);
switch (in1) {
switch (in1 ^ pol) {
case 1:
switch (in0) {
case 0:
fp->oval = 0;
fp->ostr = out0;
val = 0;
str = out0;
break;
case 1:
fp->oval = 1;
fp->ostr = out1;
val = 1;
str = out1;
break;
default:
fp->oval = 2;
fp->ostr = outX;
val = 2;
str = outX;
break;
}
break;
case 0:
fp->oval = 3;
fp->ostr = HiZ;
val = 3;
str = HiZ;
break;
default:
fp->oval = 2;
val = 2;
switch (in0) {
case 0:
fp->ostr = outL;
str = outL;
break;
case 1:
fp->ostr = outH;
str = outH;
break;
default:
fp->ostr = outX;
str = outX;
break;
}
break;
}
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
put_ostr(ptr, push, val, str);
}
/*
* $Log: bufif.cc,v $
* Revision 1.2 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.1 2001/05/31 04:12:43 steve
* Make the bufif0 and bufif1 gates strength aware,
* and accurately propagate strengths of outputs.

View File

@ -19,29 +19,33 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: bufif.h,v 1.1 2001/05/31 04:12:43 steve Exp $"
#ident "$Id: bufif.h,v 1.2 2001/10/31 04:27:46 steve Exp $"
#endif
# include "functor.h"
class vvp_bufif0_s : public vvp_fobj_s {
class vvp_bufif1_s : public functor_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_bufif1_s() : pol(0) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
protected:
unsigned pol : 1;
};
class vvp_bufif1_s : public vvp_fobj_s {
class vvp_bufif0_s : public vvp_bufif1_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_bufif0_s() { pol = 1; }
};
/*
* $Log: bufif.h,v $
* Revision 1.2 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.1 2001/05/31 04:12:43 steve
* Make the bufif0 and bufif1 gates strength aware,
* and accurately propagate strengths of outputs.

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.109 2001/10/18 17:30:25 steve Exp $"
#ident "$Id: compile.cc,v 1.110 2001/10/31 04:27:46 steve Exp $"
#endif
# include "arith.h"
@ -522,81 +522,66 @@ static void inputs_connect(vvp_ipoint_t fdx, unsigned argc, struct symb_s*argv)
vvp_ipoint_t ifdx = ipoint_input_index(fdx, idx);
functor_t iobj = functor_index(ifdx);
if (strcmp(argv[idx].text, "C<0>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 0, St0);
if (strcmp(argv[idx].text, "C<0>") == 0)
iobj->set(ifdx, false, 0, St0);
else if (strcmp(argv[idx].text, "C<pu0>") == 0)
iobj->set(ifdx, false, 0, Pu0);
else if (strcmp(argv[idx].text, "C<su0>") == 0)
iobj->set(ifdx, false, 0, Su0);
else if (strcmp(argv[idx].text, "C<1>") == 0)
iobj->set(ifdx, false, 1, St1);
else if (strcmp(argv[idx].text, "C<pu1>") == 0)
iobj->set(ifdx, false, 1, Pu1);
else if (strcmp(argv[idx].text, "C<su1>") == 0)
iobj->set(ifdx, false, 1, Su1);
else if (strcmp(argv[idx].text, "C<x>") == 0)
iobj->set(ifdx, false, 2, StX);
else if (strcmp(argv[idx].text, "C<z>") == 0)
iobj->set(ifdx, false, 3, HiZ);
else {
postpone_functor_input(ifdx, argv[idx].text, argv[idx].idx);
continue;
}
if (strcmp(argv[idx].text, "C<pu0>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 0, Pu0);
continue;
}
if (strcmp(argv[idx].text, "C<su0>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 0, Su0);
continue;
}
if (strcmp(argv[idx].text, "C<1>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 1, St1);
continue;
}
if (strcmp(argv[idx].text, "C<pu1>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 1, Pu1);
continue;
}
if (strcmp(argv[idx].text, "C<su1>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 1, Su1);
continue;
}
if (strcmp(argv[idx].text, "C<x>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 2, StX);
continue;
}
if (strcmp(argv[idx].text, "C<z>") == 0) {
free(argv[idx].text);
functor_put_input(iobj, idx, 3, HiZ);
continue;
}
postpone_functor_input(ifdx, argv[idx].text, argv[idx].idx);
free(argv[idx].text);
}
}
/* Lookup a functor[idx] and save the ipoint in *ref. */
struct const_functor_s: public functor_s {
const_functor_s(unsigned str0, unsigned str1)
{ odrive0 = str0; odrive1 = str1; }
virtual void set(vvp_ipoint_t, bool, unsigned, unsigned);
};
void const_functor_s::set(vvp_ipoint_t, bool, unsigned, unsigned)
{
assert(! "const_functor_s::set: don't do that");
}
static vvp_ipoint_t make_const_functor(unsigned val,
unsigned str0,
unsigned str1)
{
vvp_ipoint_t fdx = functor_allocate(1);
functor_t obj = functor_index(fdx);
obj->table = ft_var;
obj->ival = val;
obj->oval = val;
obj->odrive0 = str0;
obj->odrive1 = str1;
obj->mode = 0;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
schedule_functor(fdx, 0);
functor_t obj = new const_functor_s(str0, str1);
functor_define(fdx, obj);
obj->put_oval(fdx, false, val);
return fdx;
}
/* Lookup a functor[idx] and save the ipoint in *ref. */
static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
{
if (lab == 0)
@ -639,107 +624,103 @@ static void functor_reference(vvp_ipoint_t *ref, char *lab, unsigned idx)
* functor, and map the name to the vvp_ipoint_t address for the
* functor. Also resolve the inputs to the functor.
*/
void compile_functor(char*label, char*type, unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t fdx = functor_allocate(1);
functor_t obj = functor_index(fdx);
define_functor_symbol(label, fdx);
assert(argc <= 4);
obj->ival = 0xaa;
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = 0;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
functor_t obj;
if (strcmp(type, "OR") == 0) {
obj->table = ft_OR;
obj = new table_functor_s(ft_OR);
} else if (strcmp(type, "AND") == 0) {
obj->table = ft_AND;
obj = new table_functor_s(ft_AND);
} else if (strcmp(type, "BUF") == 0) {
obj->table = ft_BUF;
obj = new table_functor_s(ft_BUF);
} else if (strcmp(type, "BUFIF0") == 0) {
obj->obj = new vvp_bufif0_s;
obj->mode = M42;
obj = new vvp_bufif0_s;
} else if (strcmp(type, "BUFIF1") == 0) {
obj->obj = new vvp_bufif1_s;
obj->mode = M42;
obj = new vvp_bufif1_s;
} else if (strcmp(type, "PMOS") == 0) {
obj->obj = new vvp_pmos_s;
obj->mode = M42;
obj = new vvp_pmos_s;
} else if (strcmp(type, "NMOS") == 0) {
obj->obj = new vvp_nmos_s;
obj->mode = M42;
obj= new vvp_nmos_s;
} else if (strcmp(type, "RPMOS") == 0) {
obj->obj = new vvp_rpmos_s;
obj->mode = M42;
obj = new vvp_rpmos_s;
} else if (strcmp(type, "RNMOS") == 0) {
obj->obj = new vvp_rnmos_s;
obj->mode = M42;
obj = new vvp_rnmos_s;
} else if (strcmp(type, "MUXZ") == 0) {
obj->table = ft_MUXZ;
obj = new table_functor_s(ft_MUXZ);
} else if (strcmp(type, "EEQ") == 0) {
obj->table = ft_EEQ;
obj = new table_functor_s(ft_EEQ);
} else if (strcmp(type, "NAND") == 0) {
obj->table = ft_NAND;
obj = new table_functor_s(ft_NAND);
} else if (strcmp(type, "NOR") == 0) {
obj->table = ft_NOR;
obj = new table_functor_s(ft_NOR);
} else if (strcmp(type, "NOT") == 0) {
obj->table = ft_NOT;
obj = new table_functor_s(ft_NOT);
} else if (strcmp(type, "XNOR") == 0) {
obj->table = ft_XNOR;
obj = new table_functor_s(ft_XNOR);
} else if (strcmp(type, "XOR") == 0) {
obj->table = ft_XOR;
obj = new table_functor_s(ft_XOR);
} else {
yyerror("invalid functor type.");
free(type);
free(argv);
free(label);
return;
}
free(type);
assert(argc <= 4);
vvp_ipoint_t fdx = functor_allocate(1);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
free(label);
/* Connect the inputs of this functor to the given symbols. If
there are C<X> inputs, set the ival appropriately. */
inputs_connect(fdx, argc, argv);
free(argv);
/* Recalculate the output based on the given ival. if the oval
turns out to *not* be x, then schedule the functor so that
the value gets propagated. */
if (obj->mode == M42) {
obj->obj->set(fdx, obj, false);
} else {
unsigned char out = obj->table[obj->ival >> 2];
obj->oval = 3 & (out >> 2 * (obj->ival&3));
if (obj->oval != 2)
schedule_functor(fdx, 0);
}
free(label);
free(type);
}
static void connect_arith_inputs(vvp_ipoint_t fdx, long wid,
vvp_arith_* arith,
unsigned argc, struct symb_s*argv)
static void make_extra_outputs(vvp_ipoint_t fdx, unsigned wid)
{
for (unsigned i=1; i < wid; i++) {
extra_outputs_functor_s *fu = new extra_outputs_functor_s;
vvp_ipoint_t ipt = ipoint_index(fdx, i);
functor_define(ipt, fu);
fu->base_ = fdx;
}
}
static void make_arith(vvp_arith_ *arith,
char*label, long wid,
unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t fdx = functor_allocate(wid);
functor_define(fdx, arith);
define_functor_symbol(label, fdx);
free(label);
make_extra_outputs(fdx, wid);
unsigned opcount = argc / wid;
struct symb_s tmp_argv[4];
@ -748,14 +729,6 @@ static void connect_arith_inputs(vvp_ipoint_t fdx, long wid,
functor_t obj = functor_index(ptr);
obj->ival = 0xaa >> 2*(4 - opcount);
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = M42;
obj->obj = arith;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
for (unsigned cdx = 0 ; cdx < opcount ; cdx += 1)
tmp_argv[cdx] = argv[idx + wid*cdx];
@ -763,9 +736,6 @@ static void connect_arith_inputs(vvp_ipoint_t fdx, long wid,
inputs_connect(ptr, opcount, tmp_argv);
}
/* This runs a calculation, so that the output is propagated. */
arith->set(fdx, functor_index(fdx), false);
free(argv);
}
@ -777,16 +747,12 @@ void compile_arith_div(char*label, long wid,
if ((long)argc != 2*wid) {
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_arith_div(wid);
vvp_arith_div*arith = new vvp_arith_div(fdx, wid);
connect_arith_inputs(fdx, wid, arith, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_arith_mult(char*label, long wid,
@ -797,16 +763,12 @@ void compile_arith_mult(char*label, long wid,
if ((long)argc != 2*wid) {
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_arith_mult(wid);
vvp_arith_mult*arith = new vvp_arith_mult(fdx, wid);
connect_arith_inputs(fdx, wid, arith, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_arith_sub(char*label, long wid, unsigned argc, struct symb_s*argv)
@ -816,7 +778,6 @@ void compile_arith_sub(char*label, long wid, unsigned argc, struct symb_s*argv)
if ((argc % wid) != 0) {
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label);
compile_errors += 1;
free(label);
return;
}
@ -824,16 +785,12 @@ void compile_arith_sub(char*label, long wid, unsigned argc, struct symb_s*argv)
if (opcount > 4) {
fprintf(stderr, "%s; .arith has too many operands.\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_arith_sub(wid);
vvp_arith_sub*arith = new vvp_arith_sub(fdx, wid);
connect_arith_inputs(fdx, wid, arith, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
@ -843,7 +800,6 @@ void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
if ((argc % wid) != 0) {
fprintf(stderr, "%s; .arith has wrong number of symbols\n", label);
compile_errors += 1;
free(label);
return;
}
@ -851,16 +807,12 @@ void compile_arith_sum(char*label, long wid, unsigned argc, struct symb_s*argv)
if (opcount > 4) {
fprintf(stderr, "%s; .arith has too many operands.\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_arith_sum(wid);
vvp_arith_sum*arith = new vvp_arith_sum(fdx, wid);
connect_arith_inputs(fdx, wid, arith, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_cmp_ge(char*label, long wid, unsigned argc, struct symb_s*argv)
@ -870,16 +822,12 @@ void compile_cmp_ge(char*label, long wid, unsigned argc, struct symb_s*argv)
if ((long)argc != 2*wid) {
fprintf(stderr, "%s; .cmp has wrong number of symbols\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_cmp_ge(wid);
vvp_cmp_ge*cmp = new vvp_cmp_ge(fdx, wid);
connect_arith_inputs(fdx, wid, cmp, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
void compile_cmp_gt(char*label, long wid, unsigned argc, struct symb_s*argv)
@ -889,21 +837,26 @@ void compile_cmp_gt(char*label, long wid, unsigned argc, struct symb_s*argv)
if ((long)argc != 2*wid) {
fprintf(stderr, "%s; .cmp has wrong number of symbols\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_cmp_gt(wid);
vvp_cmp_gt*cmp = new vvp_cmp_gt(fdx, wid);
connect_arith_inputs(fdx, wid, cmp, argc, argv);
make_arith(arith, label, wid, argc, argv);
}
static void compile_shift_inputs(vvp_arith_*dev, vvp_ipoint_t fdx,
long wid, unsigned argc, struct symb_s*argv)
static void make_shift(vvp_arith_*arith,
char*label, long wid,
unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t fdx = functor_allocate(wid);
functor_define(fdx, arith);
define_functor_symbol(label, fdx);
free(label);
make_extra_outputs(fdx, wid);
for (int idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t ptr = ipoint_index(fdx,idx);
functor_t obj = functor_index(ptr);
@ -913,15 +866,6 @@ static void compile_shift_inputs(vvp_arith_*dev, vvp_ipoint_t fdx,
else
obj->ival = 0x0a;
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = M42;
obj->obj = dev;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
struct symb_s tmp_argv[3];
unsigned tmp_argc = 1;
tmp_argv[0] = argv[idx];
@ -932,6 +876,8 @@ static void compile_shift_inputs(vvp_arith_*dev, vvp_ipoint_t fdx,
inputs_connect(ptr, tmp_argc, tmp_argv);
}
free(argv);
}
/*
@ -946,25 +892,18 @@ void compile_shiftl(char*label, long wid, unsigned argc, struct symb_s*argv)
if ((long)argc < (wid+1)) {
fprintf(stderr, "%s; .shift/l has too few symbols\n", label);
compile_errors += 1;
free(label);
return;
}
if ((long)argc > (wid*2)) {
fprintf(stderr, "%s; .shift/l has too many symbols\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_arith_ *arith = new vvp_shiftl(wid);
vvp_shiftl*dev = new vvp_shiftl(fdx, wid);
compile_shift_inputs(dev, fdx, wid, argc, argv);
free(argv);
make_shift(arith, label, wid, argc, argv);
}
void compile_shiftr(char*label, long wid, unsigned argc, struct symb_s*argv)
@ -974,65 +913,45 @@ void compile_shiftr(char*label, long wid, unsigned argc, struct symb_s*argv)
if ((long)argc < (wid+1)) {
fprintf(stderr, "%s; .shift/r has too few symbols\n", label);
compile_errors += 1;
free(label);
return;
}
if ((long)argc > (wid*2)) {
fprintf(stderr, "%s; .shift/r has too many symbols\n", label);
compile_errors += 1;
free(label);
return;
}
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
vvp_shiftr*dev = new vvp_shiftr(fdx, wid);
compile_shift_inputs(dev, fdx, wid, argc, argv);
free(argv);
vvp_arith_ *arith = new vvp_shiftr(wid);
make_shift(arith, label, wid, argc, argv);
}
void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t fdx = functor_allocate(1);
functor_t obj = functor_index(fdx);
define_functor_symbol(label, fdx);
assert(argc <= 4);
obj->ival = 0xaa;
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = M42;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
functor_t obj = 0;
if (strcmp(type,"tri") == 0) {
obj->obj = new vvp_resolv_s;
obj = new resolv_functor_s;
} else {
fprintf(stderr, "invalid resolver type: %s\n", type);
compile_errors += 1;
}
/* Connect the inputs of this functor to the given symbols. If
there are C<X> inputs, set the ival appropriately. */
inputs_connect(fdx, argc, argv);
free(argv);
if (obj) {
vvp_ipoint_t fdx = functor_allocate(1);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
inputs_connect(fdx, argc, argv);
}
/* This causes the output value to be set from the existing
inputs, and if the output is not x, a propagation event is
created. */
obj->obj->set(fdx, obj, false);
free(label);
free(type);
free(label);
free(argv);
}
void compile_udp_def(int sequ, char *label, char *name,
@ -1066,46 +985,31 @@ char **compile_udp_table(char **table, char *row)
void compile_udp_functor(char*label, char*type,
unsigned argc, struct symb_s*argv)
{
struct vvp_udp_s *u = udp_find(type);
assert (argc == u->nin);
struct vvp_udp_s *u = udp_find(type);
assert (argc == u->nin);
functor_t udp = new udp_functor_s(u);
unsigned nfun = (argc+3)/4;
vvp_ipoint_t fdx = functor_allocate(nfun);
functor_define(fdx, udp);
define_functor_symbol(label, fdx);
free(label);
if (nfun > 1) {
for (unsigned i=0; i < nfun-1; i++) {
functor_t fu = new edge_inputs_functor_s;
vvp_ipoint_t ipt = ipoint_index(fdx, i+1);
functor_define(ipt, fu);
fu->out = fdx;
}
}
int nfun = (argc+3)/4;
vvp_ipoint_t fdx = functor_allocate(nfun);
functor_t obj = functor_index(fdx);
define_functor_symbol(label, fdx);
free(label);
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 = M42;
#if defined(WITH_DEBUG)
iobj->breakpoint = 0;
#endif
if (idx)
{
iobj->out = fdx;
iobj->obj = 0;
}
else
{
iobj->obj = u;
}
}
inputs_connect(fdx, argc, argv);
free(argv);
// Propagate the initial value if the UDP has one and it isn't x.
if (u->init != 2)
schedule_functor(fdx, 0);
inputs_connect(fdx, argc, argv);
free(argv);
if (u->sequ)
udp->put_oval(fdx, false, u->init);
}
@ -1138,29 +1042,13 @@ void compile_memory_port(char *label, char *memid,
bool writable = argc >= (naddr + 2 + nbits);
unsigned nfun = naddr;
if (writable)
nfun += 2 + nbits;
assert(nfun == argc);
nfun = (nfun+3)/4;
if (nfun < nbits)
nfun = nbits;
vvp_ipoint_t ix = functor_allocate(nfun);
vvp_ipoint_t ix = memory_port_new(mem, nbits, lsb, naddr, writable);
define_functor_symbol(label, ix);
free(label);
for (unsigned i=0; i<nfun; i++) {
vvp_ipoint_t iix = ipoint_index(ix, i);
functor_t ip = functor_index(iix);
ip->ival = 0xaa;
}
inputs_connect(ix, argc, argv);
free(argv);
memory_port_new(mem, ix, nbits, lsb, naddr, writable);
}
void compile_memory_init(char *memid, unsigned i, unsigned char val)
@ -1178,16 +1066,41 @@ void compile_memory_init(char *memid, unsigned i, unsigned char val)
idx++;
}
/*
** Create an event functor
** edge: compile_event(label, type, argc, argv)
** or: compile_event(label, NULL, argc, argv)
** name: compile_event(label, name, NULL, NULL)
*/
void compile_event(char*label, char*type,
unsigned argc, struct symb_s*argv)
{
event_functor_s::edge_t edge = vvp_edge_none;
if (argc && type) {
if (strcmp(type,"posedge") == 0)
edge = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0)
edge = vvp_edge_negedge;
else if (strcmp(type,"edge") == 0)
edge = vvp_edge_anyedge;
assert(argc <= 4 || edge == vvp_edge_none);
}
if (!argc && type) {
// "type" is the name of the named event
}
free(type);
functor_t obj = new event_functor_s(edge);
vvp_ipoint_t fdx = functor_allocate(1);
functor_t obj = functor_index(fdx);
functor_define(fdx, obj);
define_functor_symbol(label, fdx);
assert(argc <= 4);
free(label);
/* Run through the arguments looking for the functors that are
connected to my input ports. For each source functor that I
@ -1197,107 +1110,22 @@ void compile_event(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. */
inputs_connect(fdx, argc, argv);
free(argv);
obj->ival = 0xaa;
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive0 = 6;
obj->mode = 1;
obj->out = 0;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
obj->event = (struct vvp_event_s*) malloc(sizeof (struct vvp_event_s));
obj->event->threads = 0;
obj->old_ival = obj->ival;
if (strcmp(type,"posedge") == 0)
obj->event->vvp_edge_tab = vvp_edge_posedge;
else if (strcmp(type,"negedge") == 0)
obj->event->vvp_edge_tab = vvp_edge_negedge;
else if (strcmp(type,"edge") == 0)
obj->event->vvp_edge_tab = vvp_edge_anyedge;
if (edge != vvp_edge_none)
inputs_connect(fdx, argc, argv);
else
obj->event->vvp_edge_tab = 0;
free(type);
free(label);
}
void compile_named_event(char*label, char*name)
{
vvp_ipoint_t fdx = functor_allocate(1);
functor_t obj = functor_index(fdx);
define_functor_symbol(label, fdx);
obj->ival = 0xaa;
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = 1;
obj->out = 0;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
obj->event = (struct vvp_event_s*) malloc(sizeof (struct vvp_event_s));
obj->event->threads = 0;
obj->event->vvp_edge_tab = 0;
obj->old_ival = obj->ival;
free(label);
free(name);
}
void compile_event_or(char*label, unsigned argc, struct symb_s*argv)
{
vvp_ipoint_t fdx = functor_allocate(1);
functor_t obj = functor_index(fdx);
define_functor_symbol(label, fdx);
obj->ival = 0xaa;
obj->oval = 2;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = 1;
obj->out = 0;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
obj->event = new struct vvp_event_s;
obj->event->threads = 0;
obj->old_ival = obj->ival;
obj->event->vvp_edge_tab = 0;
/* Link the outputs of the named events to me. */
for (unsigned idx = 0 ; idx < argc ; idx += 1) {
vvp_ipoint_t tmp = lookup_functor_symbol(argv[idx].text);
assert(tmp);
tmp = ipoint_index(tmp, argv[idx].idx);
functor_t fport = functor_index(tmp);
assert(fport);
assert(fport->out == 0);
fport->out = fdx;
free(argv[idx].text);
}
// Are we sure that we have those .event/or
// drivers exclusively?
for (unsigned i=0; i<argc; i++) {
inputs_connect(fdx, 1, argv+i);
}
free(argv);
free(label);
}
/*
* The parser uses this function to compile an link an executable
* The parser uses this function to compile and link an executable
* opcode. I do this by looking up the opcode in the opcode_table. The
* table gives the operand structure that is acceptible, so I can
* process the operands here as well.
@ -1537,25 +1365,17 @@ void compile_variable(char*label, char*name, int msb, int lsb,
bool signed_flag)
{
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
vvp_ipoint_t fdx = functor_allocate(wid);
vvp_fvector_t vec = vvp_fvector_continuous_new(wid, fdx);
vvp_ipoint_t fdx = functor_allocate(wid);
define_functor_symbol(label, fdx);
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
functor_t obj = functor_index(ipoint_index(fdx,idx));
obj->table = ft_var;
obj->ival = 0x22;
obj->oval = 0x02;
obj->odrive0 = 6;
obj->odrive1 = 6;
obj->mode = 0;
#if defined(WITH_DEBUG)
obj->breakpoint = 0;
#endif
functor_t fu = new var_functor_s;
functor_define(ipoint_index(fdx, idx), fu);
}
/* Make the vpiHandle for the reg. */
vvp_fvector_t vec = vvp_fvector_continuous_new(wid, fdx);
vpiHandle obj = vpip_make_reg(name, msb, lsb, signed_flag, vec);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
@ -1602,6 +1422,11 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
/*
* $Log: compile.cc,v $
* Revision 1.110 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.109 2001/10/18 17:30:25 steve
* Support rnpmos devices. (Philip Blundell)
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.h,v 1.34 2001/10/16 02:47:37 steve Exp $"
#ident "$Id: compile.h,v 1.35 2001/10/31 04:27:46 steve Exp $"
#endif
# include <stdio.h>
@ -138,10 +138,6 @@ extern void compile_memory_init(char *memid, unsigned idx, unsigned char val);
extern void compile_event(char*label, char*type,
unsigned argc, struct symb_s*argv);
extern void compile_named_event(char*label, char*name);
extern void compile_event_or(char*label, unsigned argc, struct symb_s*argv);
/*
* A code statement is a label, an opcode and up to 3 operands. There
* are a few lexical types that the parser recognizes of the operands,
@ -206,6 +202,11 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.35 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.34 2001/10/16 02:47:37 steve
* Add arith/div object.
*

View File

@ -17,17 +17,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: functor.cc,v 1.28 2001/10/27 03:43:56 steve Exp $"
#ident "$Id: functor.cc,v 1.29 2001/10/31 04:27:46 steve Exp $"
#endif
# include "functor.h"
# include "udp.h"
# include "schedule.h"
# include "vthread.h"
# include "vpi_priv.h"
# include "debug.h"
# include <assert.h>
# include <string.h>
# include <malloc.h>
/*
* Functors are created as the source design is read in. Each is
@ -45,21 +45,9 @@
* tables are allocated as needed.
*/
const unsigned functor_index0_size = 2 << 9;
const unsigned functor_index1_size = 2 << 11;
const unsigned functor_index2_size = 2 << 10;
struct functor_index0 {
struct functor_s table[functor_index0_size];
};
struct functor_index1 {
struct functor_index0* table[functor_index1_size];
};
static vvp_ipoint_t functor_count = 0;
static struct functor_index1*functor_table[functor_index2_size] = { 0 };
functor_t **functor_list = 0x0;
static unsigned functor_count = 0;
static unsigned functors_allocated = 0;
/*
* This function initializes the functor address space by creating the
@ -68,294 +56,156 @@ static struct functor_index1*functor_table[functor_index2_size] = { 0 };
*/
void functor_init(void)
{
functor_table[0] = new struct functor_index1;
memset(functor_table[0], 0, sizeof(struct functor_index1));
functor_table[0]->table[0] = new struct functor_index0;
memset(functor_table[0]->table[0], 0, sizeof(struct functor_index0));
functor_count = 1;
// allocate the ZERO functor.
functor_allocate(1);
}
/*
* Allocate normally is just a matter of incrementing the functor_count
* and returning a pointer to the next unallocated functor. However,
* if we overrun a chunk or an index, we need to allocate the needed
* if we overrun an allocated chunk, we need to allocate the needed
* bits first.
*/
static vvp_ipoint_t functor_allocate_(void)
{
vvp_ipoint_t idx = functor_count;
idx /= functor_index0_size;
unsigned index1 = idx % functor_index1_size;
idx /= functor_index1_size;
assert( idx < functor_index2_size);
if (functor_table[idx] == 0) {
functor_table[idx] = new struct functor_index1;
memset(functor_table[idx], 0, sizeof(struct functor_index1));
}
if (functor_table[idx]->table[index1] == 0) {
functor_table[idx]->table[index1] = new struct functor_index0;
memset(functor_table[idx]->table[index1],
0, sizeof(struct functor_index0));
}
vvp_ipoint_t res = functor_count;
functor_count += 1;
return res * 4;
}
vvp_ipoint_t functor_allocate(unsigned wid)
{
assert(wid > 0);
vvp_ipoint_t res = functor_allocate_();
vvp_ipoint_t idx = functor_count*4;
functor_count += wid;
wid -= 1;
while (wid > 0) {
functor_allocate_();
wid -= 1;
}
if (functor_count > functors_allocated*functor_chunks) {
return res;
}
// enlarge the list of chunks
unsigned fa = (functor_count + functor_chunks - 1)/functor_chunks;
functor_list = (functor_t **)
realloc(functor_list, fa*sizeof(functor_t*));
assert(functor_list);
/*
* Given a vvp_ipoint_t pointer, return a pointer to the detailed
* functor structure. This does not use the low 2 bits, which address
* a specific port of the functor.
*/
functor_t functor_index(vvp_ipoint_t point)
{
point /= 4;
// allocate the chunks of functor pointers.
while (fa > functors_allocated) {
assert(point < functor_count);
assert(point > 0);
functor_list[functors_allocated] = (functor_t *)
malloc(functor_chunks * sizeof(functor_t));
assert(functor_list[functors_allocated]);
unsigned index0 = point % functor_index0_size;
point /= functor_index0_size;
memset(functor_list[functors_allocated],
0,
functor_chunks * sizeof(functor_t));
unsigned index1 = point % functor_index1_size;
point /= functor_index1_size;
return functor_table[point]->table[index1]->table + index0;
}
void functor_put_input(functor_t fp, unsigned pp, unsigned val, unsigned str)
{
/* Change the bits of the input. */
static const unsigned char ival_mask[4] = { 0xfc, 0xf3, 0xcf, 0x3f };
unsigned char imask = ival_mask[pp];
fp->ival = (fp->ival & imask) | ((val & 3) << (2*pp));
/* Save the strength aware input value. */
fp->istr[pp] = str;
}
static void functor_set_mode0(vvp_ipoint_t ptr, functor_t fp, bool push)
{
/* Locate the new output value in the table. */
unsigned char out = fp->table[fp->ival >> 2];
out >>= 2 * (fp->ival&0x03);
out &= 0x03;
/* If the output changes, then create a propagation event. */
if (out != fp->oval) {
fp->oval = out;
switch (out) {
case 0:
fp->ostr = 0x00 | (fp->odrive0<<0) | (fp->odrive0<<4);
break;
case 1:
fp->ostr = 0x88 | (fp->odrive1<<0) | (fp->odrive1<<4);
break;
case 2:
fp->ostr = 0x80 | (fp->odrive0<<0) | (fp->odrive1<<4);
break;
case 3:
fp->ostr = 0x00;
break;
functors_allocated += 1;
}
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
return idx;
}
const unsigned char vvp_edge_posedge[16] = {
0, 1, 1, 1, // 0 -> ...
0, 0, 0, 0, // 1 -> ...
0, 1, 0, 0, // x -> ...
0, 1, 0, 0 // z -> ...
};
void functor_define(vvp_ipoint_t point, functor_t obj)
{
unsigned index1 = point/4/functor_chunks;
unsigned index2 = (point/4) % functor_chunks;
functor_list[index1][index2] = obj;
}
const unsigned char vvp_edge_negedge[16] = {
0, 0, 0, 0, // 0 -> ...
1, 0, 1, 1, // 1 -> ...
1, 0, 0, 0, // x -> ...
1, 0, 0, 0 // z -> ...
};
void table_functor_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned)
{
put(ptr, v);
const unsigned char vvp_edge_anyedge[16] = {
0, 1, 1, 1, // 0 -> ...
1, 0, 1, 1, // 1 -> ...
1, 1, 0, 1, // x -> ...
1, 1, 1, 0 // z -> ...
};
/* Locate the new output value in the table. */
unsigned char val = table[ival >> 2];
val >>= 2 * (ival&0x03);
val &= 0x03;
put_oval(ptr, push, val);
}
/*
* A mode1 functor is a probe of some sort that is looking for an edge
* An event functor is a probe of some sort that is looking for an edge
* of some specified type on any of its inputs. If it finds the right
* kind of edge, then it awakens all the threads that are waiting on
* this functor *and* it schedules an assign for any output it might
* have. The latter is to support wider event/or then a single functor
* can support.
*/
static void functor_set_mode1(vvp_ipoint_t iptr, functor_t fp)
{
vvp_event_t ep = fp->event;
void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
{
old_ival = ival;
put(ptr, val);
/* Only go through the effort if there is someone interested
in the results... */
if (threads || out) {
if (ep->threads || fp->out) {
bool edge_p = true;
unsigned char edge_p = 1;
if (ep->vvp_edge_tab) {
if (edge) {
vvp_ipoint_t idx = ipoint_port(iptr);
unsigned pp = ipoint_port(ptr);
unsigned oval = (fp->old_ival >> 2*idx) & 3;
unsigned nval = (fp->ival >> 2*idx) & 3;
unsigned oval = (old_ival >> 2*pp) & 3;
unsigned nval = (ival >> 2*pp) & 3;
unsigned val = (oval << 2) | nval;
edge_p = ep->vvp_edge_tab[val];
edge_p = ((edge>>val) & 1) != 0;
}
if (edge_p) {
vthread_t tmp = ep->threads;
ep->threads = 0;
vthread_t tmp = threads;
threads = 0;
vthread_schedule_list(tmp);
if (fp->out)
schedule_assign(fp->out, 0, 0);
if (out)
// only one output? Why not propagate?
schedule_assign(out, 0, 0);
}
}
/* the new value is the new old value. */
fp->old_ival = fp->ival;
}
/*
* Set the addressed bit of the functor, and recalculate the
* output. If the output changes any, then generate the necessary
* propagation events to pass the output on.
/*
* Variable functors receive %assign-ed values at port[0].
* Continuous assignments are connected to port[1].
*/
void functor_set(vvp_ipoint_t ptr, unsigned bit, unsigned str, bool push)
void var_functor_s::set(vvp_ipoint_t ptr, bool push, unsigned val, unsigned)
{
functor_t fp = functor_index(ptr);
unsigned pp = ipoint_port(ptr);
assert(fp);
/* Store the value and strengths in the input bits. */
functor_put_input(fp, pp, bit, str);
assert(fp->mode != 2);
switch (fp->mode) {
case 0:
functor_set_mode0(ptr, fp, push);
break;
case 1:
functor_set_mode1(ptr, fp);
break;
case M42:
if (!fp->obj) {
ptr = fp->out;
fp = functor_index(ptr);
assert(fp->mode == M42);
}
fp->obj->set(ptr, fp, push);
break;
}
#if defined(WITH_DEBUG)
if (fp->breakpoint)
breakpoint();
#endif
}
unsigned functor_get(vvp_ipoint_t ptr)
{
functor_t fp = functor_index(ptr);
assert(fp);
if ((fp->mode == M42) && fp->obj)
return fp->obj->get(ptr, fp);
return fp->oval;
}
unsigned vvp_fobj_s::get(vvp_ipoint_t, functor_t fp)
{
return fp->oval;
}
/*
* This function is used by the scheduler to implement the propagation
* event. The input is the pointer to the functor who's output is to
* be propagated. Pass the output to the inputs of all the connected
* functors.
*/
void functor_propagate(vvp_ipoint_t ptr, bool push)
{
functor_t fp = functor_index(ptr);
unsigned char oval = fp->oval;
unsigned char ostr = fp->ostr;
vvp_ipoint_t idx = fp->out;
while (idx) {
functor_t idxp = functor_index(idx);
vvp_ipoint_t next = idxp->port[ipoint_port(idx)];
functor_set(idx, oval, ostr, push);
idx = next;
if (assigned && pp==1 || !assigned && pp==0) {
put_oval(ptr, push, val);
}
}
/*
* The variable functor is special. This is the truth table for it.
*/
const unsigned char ft_var[16] = {
0xe4, /* 0 0: 11, 10, 01, 00 */
0xe4, /* 0 1: 11, 10, 01, 00 */
0xe4, /* 0 x: 11, 10, 01, 00 */
0xe4, /* 0 z: 11, 10, 01, 00 */
0x00, /* 1 0: 00, 00, 00, 00 */
0x55, /* 1 1: 01, 01, 01, 01 */
0xaa, /* 1 x: 10, 10, 10, 10 */
0xff, /* 1 z: 11, 11, 11, 11 */
0xe4,
0xe4,
0xe4,
0xe4,
0xe4,
0xe4,
0xe4,
0xe4
};
void extra_outputs_functor_s::set(vvp_ipoint_t i, bool push,
unsigned val, unsigned)
{
put(i, val);
functor_t base = functor_index(base_);
val = base->ival & 3; // yes, this is ugly
base->set(base_, push, val);
}
void extra_ports_functor_s::set(vvp_ipoint_t i, bool push,
unsigned val, unsigned str)
{
functor_t base = functor_index(base_);
base->set(i, push, val, str);
}
void extra_inputs_functor_s::set(vvp_ipoint_t i, bool push,
unsigned val, unsigned)
{
put(i, val);
functor_t base = functor_index(out);
val = base->ival & 3; // yes, this is ugly
base->set(ipoint_make(out,0), push, val);
}
/*
* $Log: functor.cc,v $
* Revision 1.29 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.28 2001/10/27 03:43:56 steve
* Propagate functor push, to make assign better.
*

View File

@ -19,11 +19,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: functor.h,v 1.34 2001/10/27 03:43:56 steve Exp $"
#ident "$Id: functor.h,v 1.35 2001/10/31 04:27:46 steve Exp $"
#endif
# include "pointers.h"
/*
* Create a propagation event. The fun parameter points to the functor
* to have its output propagated, and the delay is the delay to
* schedule the propagation.
*/
extern void schedule_functor(vvp_ipoint_t fun, unsigned delay);
/*
*
* The major mode is selected by the mode parameter.
@ -53,27 +60,6 @@
* output value is picked from the lookup table that the table pointer
* points to.
*
* MODE 1: EDGE EVENT FUNCTORS
*
* These functors take inputs like mode 0 functors, but the input is
* compared with the preveous input for that bit, and the results of
* that comparison are used to detect edges. The functor may be
* programmed to detect posedge, negedge, or any edge events. These
* functors can have %wait instructions waiting on them.
*
* MODE 2: NAMED EVENT FUNCTORS
*
* These functors do not bother to check for edges. Any event on the
* input causes an event to be detected. Like mode-1 functors, these
* can have %wait instructions waiting on them. Mode-2 functors do not
* have structural inputs, however. They take their inputs from %set
* instructions.
*
* Mode-2 events can also be used to combine other mode-1 and mode-2
* functors by setting their outputs to put to the mode-2
* functor. Since the mode-2 functor does not take input, any number
* of mode-1 and mode-2 functors may point in.
*
* MODE 42: LIFE, THE UNIVERSE AND EVERYTHING ELSE
*
* These functors are and escape for all other behaviors. This mode
@ -84,7 +70,7 @@
*
* DRIVE STRENGTHS:
*
* The normal functor (modes 0, 1 and 2) is not aware of strengths. It
* The normal functor (modes 0) is not aware of strengths. It
* generates strength simply by virtue of having strength
* specifications. The drive strength specification includes a drive0
* and drive1 strength, each with 8 possible values (that can be
@ -117,44 +103,12 @@
* value.
*/
struct functor_s {
/* This is the truth table for the device */
union {
vvp_truth_t table;
vvp_event_t event;
struct vvp_fobj_s *obj;
};
/* This is the output for the device. */
vvp_ipoint_t out;
/* These are the input ports. */
vvp_ipoint_t port[4];
/* Input with strengths, for strength aware functors. */
unsigned char istr[4];
/* Input values without strengths. */
unsigned ival : 8;
/* Output value (low bits) and drive1 and drive0 strength. */
unsigned oval : 2;
unsigned odrive0 : 3;
unsigned odrive1 : 3;
/* Strength form of the output value. */
unsigned ostr : 8;
#if defined(WITH_DEBUG)
/* True if this functor triggers a breakpoint. */
unsigned breakpoint : 1;
#endif
/* functor mode: 0 == table ; 1 == event */
unsigned mode : 2;
/* General purpose flag for M42 functor's convenience */
unsigned flag42 : 1;
union {
unsigned char old_ival; // mode 1, UDP
};
};
typedef struct functor_s *functor_t;
/*
* signal strengths
*/
enum strength_e {
HiZ = 0x00,
Su0 = 0x77, /* Su0-Su0 */
@ -166,46 +120,6 @@ enum strength_e {
StX = 0x66|0x80, /* St0 - St1 */
};
/*
* This a an `obj' structute for mode-42 functors.
* Each instance implements the get and set methods in a type specific
* way, so that this represents a completely general functor.
*
* ::set(...)
*
* This method is called when any of the 4 inputs of the functor
* receives a bit value. This method is called even if the set value
* is the same as the existing value.
*
* ::get(...)
*
* This method is called to pull the "value" of the functor. Normally,
* there is not much of a trick to this, but some types might need to
* do complex things here, like look up a memory index. Anyhow, this
* method must be idempotent, because I'm only going to tell you that
* it happens when it happens.
*/
#define M42 3
struct vvp_fobj_s {
virtual unsigned get(vvp_ipoint_t i, functor_t f);
virtual void set(vvp_ipoint_t i, functor_t f, bool push) =0;
};
/*
* If functor mode is 1, the event member is valid and the vvp_event_s
* points to the extended event information.
*/
extern const unsigned char vvp_edge_posedge[16];
extern const unsigned char vvp_edge_negedge[16];
extern const unsigned char vvp_edge_anyedge[16];
struct vvp_event_s {
vthread_t threads;
const unsigned char*vvp_edge_tab;
};
/*
* Initialize the functors address space. This function must be called
@ -225,15 +139,183 @@ extern void functor_init(void);
extern vvp_ipoint_t functor_allocate(unsigned wid);
/*
* This function is used by the compile time to initialize the value
* of an input, and by the run time to manipulate the bits of the
* input in a uniform manner.
*
* The val parameter is the 2bit representation of the input value,
* and the str is a strength aware version.
* Given an ipoint_t pointer, return a C pointer to the functor. This
* is like a pointer dereference. The point parameter must have been
* returned from a previous call to functor_allocate.
*/
extern void functor_put_input(functor_t fp, unsigned pp,
unsigned val, unsigned str);
extern functor_t **functor_list;
static const unsigned functor_chunks = 0x400;
inline static functor_t functor_index(vvp_ipoint_t point)
{
unsigned index1 = point/4/functor_chunks;
unsigned index2 = (point/4) % functor_chunks;
return functor_list[index1][index2];
}
/*
* This function defines the functor object. After allocation an ipoint,
* you must call this before functor_index() is called on it.
*/
extern void functor_define(vvp_ipoint_t point, functor_t obj);
/*
** The functor object
*/
struct functor_s {
functor_s();
/* This is the output for the device. */
vvp_ipoint_t out;
/* These are the input ports. */
vvp_ipoint_t port[4];
/* Input values without strengths. */
unsigned ival : 8;
private:
/* Output value (low bits) and drive1 and drive0 strength. */
unsigned oval : 2;
protected:
unsigned odrive0 : 3;
unsigned odrive1 : 3;
private:
/* Strength form of the output value. */
unsigned ostr : 8;
unsigned inhibit : 1;
public:
#if defined(WITH_DEBUG)
/* True if this functor triggers a breakpoint. */
unsigned breakpoint : 1;
#endif
virtual void set(vvp_ipoint_t ipt, bool push,
unsigned val, unsigned str = 0) = 0;
inline unsigned char get() { return oval; }
void put(vvp_ipoint_t ipt, unsigned val);
void put_oval(vvp_ipoint_t ptr, bool push, unsigned val);
void put_ostr(vvp_ipoint_t ptr, bool push, unsigned val, unsigned str);
bool disable(vvp_ipoint_t ptr);
bool enable(vvp_ipoint_t ptr);
void propagate(bool push);
};
inline functor_s::functor_s()
{
out = 0;
port[0] = 0;
port[1] = 0;
port[2] = 0;
port[3] = 0;
ival = 0xaa;
oval = 2;
odrive0 = 6;
odrive1 = 6;
ostr = StX;
inhibit = 0;
#if defined(WITH_DEBUG)
breakpoint = 0;
#endif
}
/*
* Set the ival for input port ptr to value val.
*/
inline void functor_s::put(vvp_ipoint_t ptr, unsigned val)
{
static const unsigned char ival_mask[4] = { 0xfc, 0xf3, 0xcf, 0x3f };
unsigned pp = ipoint_port(ptr);
unsigned char imask = ival_mask[pp];
ival = (ival & imask) | ((val & 3) << (2*pp));
}
inline void functor_s::propagate(bool push)
{
vvp_ipoint_t idx = out;
while (idx) {
functor_t idxp = functor_index(idx);
idxp->set(idx, push, oval, ostr);
idx = idxp->port[ipoint_port(idx)];
#if defined(WITH_DEBUG)
if (fp->breakpoint)
breakpoint();
#endif
}
}
inline void functor_s::put_oval(vvp_ipoint_t ptr, bool push, unsigned val)
{
switch (val) {
case 0:
ostr = 0x00 | (odrive0<<0) | (odrive0<<4);
break;
case 1:
ostr = 0x88 | (odrive1<<0) | (odrive1<<4);
break;
case 2:
ostr = 0x80 | (odrive0<<0) | (odrive1<<4);
break;
case 3:
ostr = 0x00;
break;
}
if (inhibit)
return;
if (val != oval) {
oval = val;
if (push)
propagate(true);
else
schedule_functor(ptr, 0);
}
}
inline void functor_s::put_ostr(vvp_ipoint_t ptr, 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(ptr, 0);
}
}
inline bool functor_s::disable(vvp_ipoint_t ptr)
{
bool r = inhibit;
inhibit = 1;
return r;
}
inline bool functor_s::enable(vvp_ipoint_t ptr)
{
unsigned val;
if (ostr == 0)
val = 3;
else switch (ostr & 0x88) {
case 0x00: val = 0; break;
case 0x88: val = 1; break;
default: val = 2;
}
if (val != oval) {
schedule_functor(ptr, 0);
}
bool r = inhibit;
inhibit = 0;
return r;
}
/*
* functor_set sets the addressed input to the specified value, and
@ -245,14 +327,35 @@ extern void functor_put_input(functor_t fp, unsigned pp,
* version is also passed, and typically just stored in the
* functor.
*/
extern void functor_set(vvp_ipoint_t point, unsigned val,
unsigned str, bool push);
/*
* Set the addressed bit of the functor, and recalculate the
* output. If the output changes any, then generate the necessary
* propagation events to pass the output on.
*/
inline static
void functor_set(vvp_ipoint_t ptr, unsigned val, unsigned str, bool push)
{
functor_t fp = functor_index(ptr);
fp->set(ptr, push, val, str);
#if defined(WITH_DEBUG)
if (fp->breakpoint)
breakpoint();
#endif
}
/*
* Read the value of the functor. In fact, only the *value* is read --
* the strength of that value is stripped off.
*/
extern unsigned functor_get(vvp_ipoint_t ptr);
inline static
unsigned functor_get(vvp_ipoint_t ptr)
{
functor_t fp = functor_index(ptr);
return fp->get();
}
/*
* When a propagation event happens, this function is called with the
@ -260,47 +363,64 @@ extern unsigned functor_get(vvp_ipoint_t ptr);
* the inputs it is connected to, creating new propagation event on
* the way.
*/
extern void functor_propagate(vvp_ipoint_t ptr, bool push = true);
/*
* Given an ipoint_t pointer, return a C pointer to the functor. This
* is like a pointer dereference. The point parameter must have been
* returned from a previous call to functor_allocate.
*/
extern functor_t functor_index(vvp_ipoint_t point);
/*
* This is a convenience function that returns the current output
* value of the functor.
*/
inline unsigned functor_oval(vvp_ipoint_t fptr)
static inline
void functor_propagate(vvp_ipoint_t ptr, bool push=true)
{
functor_t fp = functor_index(fptr);
return fp->oval & 3;
functor_t fp = functor_index(ptr);
fp->propagate(push);
}
/*
* Vectors of functors
*/
// The extra_outputs_functor_s class is for devices that require
// multiple inputs and outputs.
// ->set redirects the job to the base_, who knows what shall be done.
extern unsigned vvp_fvector_size(vvp_fvector_t v);
extern vvp_ipoint_t vvp_fvector_get(vvp_fvector_t v, unsigned i);
extern void vvp_fvector_set(vvp_fvector_t v, unsigned i, vvp_ipoint_t p);
extern vvp_ipoint_t *vvp_fvector_member(vvp_fvector_t v, unsigned i);
extern vvp_fvector_t vvp_fvector_new(unsigned size);
extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
struct extra_outputs_functor_s: public functor_s {
extra_outputs_functor_s(vvp_ipoint_t b = 0) : base_(b) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
/*
* M42 functor type for callback events
*/
struct vvp_cb_fobj_s: public vvp_fobj_s {
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
struct __vpiCallback *cb_handle;
unsigned permanent : 1;
unsigned base_;
};
struct vvp_cb_fobj_s *vvp_fvector_make_callback(vvp_fvector_t vec,
const unsigned char *edge = 0);
// extra_ports_functor_s redirects to base without setting the inputs.
// But base must be awayr that i may not match this. This is used by
// memory ports.
struct extra_ports_functor_s : public extra_outputs_functor_s
{
extra_ports_functor_s(vvp_ipoint_t b = 0) : extra_outputs_functor_s(b) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
// The extra_inputs_functor_s class is for devices that require
// multiple inputs but only one output
// ->set redirects the job to ->out, that knows what shall be done.
struct extra_inputs_functor_s: public functor_s {
extra_inputs_functor_s(vvp_ipoint_t b = 0) { out = b; }
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
};
// edge_inputs_functor_s provides an old_ival
// it's up to the set() method to use it (UDP).
// The default set() is inherited from extra_inputs_functor_s.
struct edge_inputs_functor_s: public extra_inputs_functor_s
{
edge_inputs_functor_s() : old_ival(2) {}
unsigned char old_ival;
};
/*
* Table driven functor. oval = table[ival];
*/
struct table_functor_s: public functor_s {
typedef const unsigned char *truth_t;
explicit table_functor_s(truth_t t) : table(t) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
truth_t table;
};
// table functor types
extern const unsigned char ft_AND[];
extern const unsigned char ft_BUF[];
@ -318,8 +438,75 @@ extern const unsigned char ft_XNOR[];
extern const unsigned char ft_XOR[];
extern const unsigned char ft_var[];
/*
* Event / edge detection functors
*/
struct event_functor_s: public edge_inputs_functor_s {
typedef unsigned short edge_t;
explicit event_functor_s(edge_t e) : edge(e), threads(0) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
edge_t edge;
vthread_t threads;
};
#define VVP_EDGE(a,b) (1<<(((a)<<2)|(b)))
const event_functor_s::edge_t vvp_edge_posedge
= VVP_EDGE(0,1)
| VVP_EDGE(0,2)
| VVP_EDGE(0,3)
| VVP_EDGE(2,1)
| VVP_EDGE(3,1)
;
const event_functor_s::edge_t vvp_edge_negedge
= VVP_EDGE(1,0)
| VVP_EDGE(1,2)
| VVP_EDGE(1,3)
| VVP_EDGE(2,0)
| VVP_EDGE(3,0)
;
const event_functor_s::edge_t vvp_edge_anyedge = 0x7bde;
const event_functor_s::edge_t vvp_edge_none = 0;
/*
* Variable functors
*/
struct var_functor_s: public functor_s {
var_functor_s() : assigned(0) {};
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
unsigned assigned : 1;
};
/*
* Callback functors.
*/
struct callback_functor_s *vvp_fvector_make_callback
(vvp_fvector_t, event_functor_s::edge_t = vvp_edge_none);
/*
* Vectors of functors
*/
extern unsigned vvp_fvector_size(vvp_fvector_t v);
extern vvp_ipoint_t vvp_fvector_get(vvp_fvector_t v, unsigned i);
extern void vvp_fvector_set(vvp_fvector_t v, unsigned i, vvp_ipoint_t p);
extern vvp_ipoint_t *vvp_fvector_member(vvp_fvector_t v, unsigned i);
extern vvp_fvector_t vvp_fvector_new(unsigned size);
extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p);
/*
* $Log: functor.h,v $
* Revision 1.35 2001/10/31 04:27:46 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.34 2001/10/27 03:43:56 steve
* Propagate functor push, to make assign better.
*

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: memory.cc,v 1.11 2001/10/14 01:36:12 steve Exp $"
#ident "$Id: memory.cc,v 1.12 2001/10/31 04:27:47 steve Exp $"
#endif
#include "memory.h"
@ -65,9 +65,9 @@ struct vvp_memory_index_s
unsigned size; // number of valid addresses
};
struct vvp_memory_port_s : public vvp_fobj_s
struct vvp_memory_port_s : public functor_s
{
void set(vvp_ipoint_t i, functor_t f, bool push);
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
vvp_memory_t mem;
vvp_ipoint_t ix;
@ -83,7 +83,6 @@ struct vvp_memory_port_s : public vvp_fobj_s
bool writable;
};
unsigned memory_size(vvp_memory_t mem)
{
return mem->size;
@ -168,22 +167,10 @@ void memory_new(vvp_memory_t mem, char *name, int msb, int lsb,
static void update_addr(vvp_memory_port_t addr);
void memory_port_new(vvp_memory_t mem, vvp_ipoint_t ix,
unsigned nbits, unsigned bitoff,
unsigned naddr, bool writable)
vvp_ipoint_t memory_port_new(vvp_memory_t mem,
unsigned nbits, unsigned bitoff,
unsigned naddr, bool writable)
{
vvp_memory_port_t a = new struct vvp_memory_port_s;
a->mem = mem;
a->ix = ix;
a->naddr = naddr;
a->writable = writable;
a->nbits = nbits;
a->bitoff = bitoff;
a->next = mem->addr_root;
mem->addr_root = a;
unsigned nfun = naddr;
if (writable)
nfun += 2 + nbits;
@ -191,21 +178,32 @@ void memory_port_new(vvp_memory_t mem, vvp_ipoint_t ix,
if (nfun < nbits)
nfun = nbits;
for (unsigned idx = 0; idx < nfun; idx ++)
vvp_memory_port_t a = new struct vvp_memory_port_s;
a->mem = mem;
a->naddr = naddr;
a->writable = writable;
a->nbits = nbits;
a->bitoff = bitoff;
a->next = mem->addr_root;
mem->addr_root = a;
a->ix = functor_allocate(nfun);
functor_define(a->ix, a);
if (nfun > 1)
{
vvp_ipoint_t ifdx = ipoint_index(ix, idx);
functor_t iobj = functor_index(ifdx);
iobj->oval = 0x02;
iobj->mode = M42;
iobj->out = 0;
iobj->obj = a;
extra_ports_functor_s *fu = new extra_ports_functor_s[nfun-1];
for (unsigned i = 0; i< nfun - 1; i++) {
fu[i].base_ = a->ix;
functor_define(ipoint_index(a->ix, i+1), fu+i);
}
}
a->cur_addr = VVP_MEMORY_NO_ADDR;
a->cur_bits = 0x0;
update_addr(a);
return a->ix;
}
void memory_init_nibble(vvp_memory_t mem, unsigned idx, unsigned char val)
@ -319,11 +317,7 @@ void update_data(vvp_memory_port_t data)
vvp_ipoint_t dx = ipoint_index(data->ix, i);
functor_t df = functor_index(dx);
unsigned char out = get_bit(data->cur_bits, i + data->bitoff);
if (out != df->oval)
{
df->oval = out;
functor_propagate(dx);
}
df->put_oval(dx, false, out);
}
}
@ -344,11 +338,7 @@ void update_data_ports(vvp_memory_t mem, vvp_memory_bits_t bits, int bit,
{
vvp_ipoint_t ix = ipoint_index(a->ix, i);
functor_t df = functor_index(ix);
if (df->oval != val)
{
df->oval = val;
functor_propagate(ix);
}
df->put_oval(ix, false, val);
}
}
a = a->next;
@ -382,17 +372,22 @@ void write_event(vvp_memory_port_t p)
}
}
void vvp_memory_port_s::set(vvp_ipoint_t i, functor_t f, bool push)
void vvp_memory_port_s::set(vvp_ipoint_t i, bool, unsigned val, unsigned)
{
// !attention! "i" may not corespont to "this"
functor_t ifu = functor_index(i);
ifu->put(i, val);
if (i < ix+naddr)
{
if (update_addr_bit(this, i))
update_data(this);
}
// An event at ix+naddr always sets the value 0, and triggeres a write.
// If the write event port is 3, then it's not connected, and the
// write port is transparent, controlled by ix+naddr+1, the write enable.
// port ix+naddr is the write clock. If it's input value is
// undefined, we do assynchronous write. Else any event on ix+naddr
// is a valid write clock edge. Connect an appropriate edge event
// functor.
if (i == ix+naddr
|| (writable && functor_get_input(ix+naddr) == 3))

View File

@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: memory.h,v 1.3 2001/06/15 03:28:31 steve Exp $"
#ident "$Id: memory.h,v 1.4 2001/10/31 04:27:47 steve Exp $"
#endif
#include "pointers.h"
@ -37,9 +37,9 @@ typedef struct vvp_memory_index_s *vvp_memory_index_t;
void memory_new(vvp_memory_t mem, char *name, int lsb, int msb,
unsigned idxs, long *idx);
void memory_port_new(vvp_memory_t mem, vvp_ipoint_t ix,
unsigned nbits, unsigned bitoff,
unsigned naddr, bool writable);
vvp_ipoint_t memory_port_new(vvp_memory_t mem,
unsigned nbits, unsigned bitoff,
unsigned naddr, bool writable);
void memory_init_nibble(vvp_memory_t mem, unsigned idx, unsigned char val);
@ -61,6 +61,11 @@ vvp_memory_t memory_create(char *label);
/*
* $Log: memory.h,v $
* Revision 1.4 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.3 2001/06/15 03:28:31 steve
* Change the VPI call process so that loaded .vpi modules
* use a function table instead of implicit binding.

View File

@ -17,89 +17,81 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: npmos.cc,v 1.4 2001/10/24 03:18:52 steve Exp $"
#ident "$Id: npmos.cc,v 1.5 2001/10/31 04:27:47 steve Exp $"
#endif
# include "npmos.h"
# include "functor.h"
# include "schedule.h"
/* from IEEE 1384-1995 Table 7-8 */
static unsigned char rmos_table[8] = { 0, 1, 1, 2, 2, 3, 5, 5 };
/* just reduce SUPPLY to STRONG */
static unsigned char mos_table[8] = { 0, 1, 2, 3, 4, 5, 6, 6 };
static inline unsigned reduce_strength(unsigned is0, unsigned char *table)
void vvp_pmos_s::set(vvp_ipoint_t ptr, bool push, unsigned v, unsigned s)
{
unsigned vals = is0 & 0x88;
unsigned s1 = table[is0 & 0x7];
unsigned s2 = table[(is0 & 0x70) >> 4];
put(ptr, v);
return vals | s1 | (s2 << 4);
}
unsigned pp = ipoint_port(ptr);
if (pp == 0) {
static void mos_set(vvp_ipoint_t ptr, functor_t fp, bool push, unsigned in1_on, unsigned char *table)
{
unsigned in0 = fp->ival & 0x03;
unsigned in1 = (fp->ival >> 2) & 0x03;
unsigned is0 = reduce_strength(fp->istr[0], table);
unsigned char outH = 0x88 | ((is0 & 7)<<4) | (0);
unsigned char outL = 0x00 | ((is0 & 7)<<0) | (0);
unsigned char outX = 0x80 | (is0 & 7) | (is0 & 0x70);
/* from IEEE 1384-1995 Table 7-8 */
static const unsigned char rmos_table[8]
= { 0, 1, 1, 2, 2, 3, 5, 5 };
/* just reduce SUPPLY to STRONG */
static const unsigned char mos_table[8]
= { 0, 1, 2, 3, 4, 5, 6, 6 };
const unsigned char *table = res ? rmos_table : mos_table;
unsigned vals = s & 0x88;
unsigned s1 = table[s & 0x7];
unsigned s2 = table[(s & 0x70) >> 4];
istr = vals | s1 | (s2 << 4);
}
if (in1 == in1_on) {
unsigned in0 = ival & 0x03;
unsigned in1 = (ival >> 2) & 0x03;
unsigned char outH = 0x88 | ((istr & 7)<<4) | (0);
unsigned char outL = 0x00 | ((istr & 7)<<0) | (0);
unsigned char outX = 0x80 | (istr & 7) | (istr & 0x70);
in1 ^= pol;
unsigned char val;
unsigned char str;
if (in0 == 3 || in1 == 0) {
// gate on; output follows input
fp->oval = in0;
fp->ostr = is0;
val = in0;
str = istr;
} else if (in1 == 2 || in1 == 3) {
// gate X or Z; output is undefined
fp->oval = 2;
val = 2;
switch (in0) {
case 0:
fp->ostr = outL;
str = outL;
break;
case 1:
fp->ostr = outH;
str = outH;
break;
default:
fp->ostr = outX;
str = outX;
break;
}
} else {
// gate off; output is high impedance
fp->oval = 3;
fp->ostr = HiZ;
val = 3;
str = HiZ;
}
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
void vvp_pmos_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
{
mos_set(ptr, fp, push, 0, mos_table);
}
void vvp_nmos_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
{
mos_set(ptr, fp, push, 1, mos_table);
}
void vvp_rpmos_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
{
mos_set(ptr, fp, push, 0, rmos_table);
}
void vvp_rnmos_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
{
mos_set(ptr, fp, push, 1, rmos_table);
put_ostr(ptr, push, val, str);
}
/*
* $Log: npmos.cc,v $
* Revision 1.5 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.4 2001/10/24 03:18:52 steve
* npmos outputs have 3bit strengths, not 2.
*

View File

@ -19,45 +19,48 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: npmos.h,v 1.2 2001/10/18 17:30:26 steve Exp $"
#ident "$Id: npmos.h,v 1.3 2001/10/31 04:27:47 steve Exp $"
#endif
# include "functor.h"
class vvp_pmos_s : public vvp_fobj_s {
class vvp_pmos_s : public functor_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_pmos_s() : istr(StX), pol(0), res(0) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
protected:
unsigned char istr;
unsigned pol : 1;
unsigned res : 1;
};
class vvp_nmos_s : public vvp_fobj_s {
class vvp_nmos_s : public vvp_pmos_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_nmos_s() { pol = 1; res = 0; }
};
class vvp_rpmos_s : public vvp_fobj_s {
class vvp_rpmos_s : public vvp_pmos_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_rpmos_s() { pol = 0; res = 1; }
};
class vvp_rnmos_s : public vvp_fobj_s {
class vvp_rnmos_s : public vvp_pmos_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
vvp_rnmos_s() { pol = 1; res = 1; }
};
/*
* $Log: npmos.h,v $
* Revision 1.3 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.2 2001/10/18 17:30:26 steve
* Support rnpmos devices. (Philip Blundell)
* Revision 1.1 2001/10/09 02:28:17 steve Add the

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: parse.y,v 1.38 2001/10/16 02:47:37 steve Exp $"
#ident "$Id: parse.y,v 1.39 2001/10/31 04:27:47 steve Exp $"
#endif
# include "parse_misc.h"
@ -208,17 +208,13 @@ statement
named event instead. */
| T_LABEL K_EVENT T_SYMBOL ',' symbols ';'
{ struct symbv_s obj = $5;
compile_event($1, $3, obj.cnt, obj.vect);
}
{ compile_event($1, $3, $5.cnt, $5.vect); }
| T_LABEL K_EVENT T_STRING ';'
{ compile_named_event($1, $3); }
{ compile_event($1, $3, 0, 0); }
| T_LABEL K_EVENT_OR symbols ';'
{ struct symbv_s obj = $3;
compile_event_or($1, obj.cnt, obj.vect);
}
{ compile_event($1, 0, $3.cnt, $3.vect); }
/* Instructions may have a label, and have zero or more
@ -509,6 +505,11 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.39 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.38 2001/10/16 02:47:37 steve
* Add arith/div object.
*

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.5 2001/08/08 01:05:06 steve Exp $"
#ident "$Id: pointers.h,v 1.6 2001/10/31 04:27:47 steve Exp $"
#endif
/*
@ -85,17 +85,11 @@ inline unsigned ipoint_port(vvp_ipoint_t func)
typedef unsigned vvp_cpoint_t;
/*
* The truth table that functors point to are addressed with this
* typedef.
*/
typedef const unsigned char*vvp_truth_t;
/*
* The functor event mode uses a pointer of this type to point to the
* extended event data.
*/
typedef struct vvp_event_s *vvp_event_t;
typedef struct event_functor_s *vvp_event_t;
typedef struct vthread_s*vthread_t;
@ -107,6 +101,11 @@ typedef struct vvp_fvector_s *vvp_fvector_t;
/*
* $Log: pointers.h,v $
* Revision 1.6 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.5 2001/08/08 01:05:06 steve
* Initial implementation of vvp_fvectors.
* (Stephan Boettcher)

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: resolv.cc,v 1.6 2001/10/14 01:45:11 steve Exp $"
#ident "$Id: resolv.cc,v 1.7 2001/10/31 04:27:47 steve Exp $"
#endif
# include "resolv.h"
@ -137,44 +137,43 @@ static unsigned blend(unsigned a, unsigned b)
* inputs are resolved with the blend function, and the final value is
* reduced to a 4-value result for propagation.
*/
void vvp_resolv_s::set(vvp_ipoint_t ptr, functor_t fp, bool push)
void resolv_functor_s::set(vvp_ipoint_t i, bool push, unsigned, unsigned str)
{
unsigned val = fp->istr[0];
unsigned pp = ipoint_port(i);
istr[pp] = str;
val = blend(val, fp->istr[1]);
val = blend(val, fp->istr[2]);
val = blend(val, fp->istr[3]);
unsigned sval = istr[0];
sval = blend(sval, istr[1]);
sval = blend(sval, istr[2]);
sval = blend(sval, istr[3]);
unsigned oval;
if (val == HiZ) {
oval = 3;
unsigned val;
if (sval == HiZ) {
val = 3;
} else switch (val & 0x88) {
} else switch (sval & 0x88) {
case 0x00:
oval = 0;
val = 0;
break;
case 0x88:
oval = 1;
val = 1;
break;
default:
oval = 2;
val = 2;
break;
}
fp->oval = oval;
/* If the output changes, then create a propagation event. */
if (val != fp->ostr) {
fp->ostr = val;
if (push)
functor_propagate(ptr);
else
schedule_functor(ptr, 0);
}
put_ostr(i, push, val, sval);
}
/*
* $Log: resolv.cc,v $
* Revision 1.7 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.6 2001/10/14 01:45:11 steve
* Propogate strength-only changes from resolver.
*

View File

@ -19,21 +19,26 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: resolv.h,v 1.2 2001/05/12 01:48:57 steve Exp $"
#ident "$Id: resolv.h,v 1.3 2001/10/31 04:27:47 steve Exp $"
#endif
# include "functor.h"
class vvp_resolv_s : public vvp_fobj_s {
class resolv_functor_s: public functor_s {
public:
virtual void set(vvp_ipoint_t i, functor_t f, bool push);
private: // not implemented
resolv_functor_s() { istr[0]=istr[1]=istr[2]=istr[3]=StX; }
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
unsigned char istr[4];
};
/*
* $Log: resolv.h,v $
* Revision 1.3 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.2 2001/05/12 01:48:57 steve
* Silly copyright typo.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: schedule.h,v 1.7 2001/07/11 02:27:21 steve Exp $"
#ident "$Id: schedule.h,v 1.8 2001/10/31 04:27:47 steve Exp $"
#endif
# include "vthread.h"
@ -32,13 +32,6 @@
*/
extern void schedule_vthread(vthread_t thr, unsigned delay);
/*
* Create a propagation event. The fun parameter points to the functor
* to have its output propagated, and the delay is the delay to
* schedule the propagation.
*/
extern void schedule_functor(vvp_ipoint_t fun, unsigned delay);
/*
* Create an assignment event. The val passed here will be assigned to
* the specified input when the delay times out.
@ -95,6 +88,11 @@ extern bool schedule_finished(void);
/*
* $Log: schedule.h,v $
* Revision 1.8 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.7 2001/07/11 02:27:21 steve
* Add support for REadOnlySync and monitors.
*

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.11 2001/09/19 04:10:40 steve Exp $"
#ident "$Id: udp.cc,v 1.12 2001/10/31 04:27:47 steve Exp $"
#endif
#include "udp.h"
@ -31,30 +31,12 @@
#include <stdlib.h>
#include <stdio.h>
void vvp_udp_s::set(vvp_ipoint_t ptr, functor_t fp, bool)
void udp_functor_s::set(vvp_ipoint_t i, bool, unsigned val, unsigned)
{
unsigned char out = propagate_(ptr);
switch (out) {
case 0:
fp->ostr = 0x00 | (fp->odrive0<<0) | (fp->odrive0<<4);
break;
case 1:
fp->ostr = 0x88 | (fp->odrive1<<0) | (fp->odrive1<<4);
break;
case 2:
fp->ostr = 0x80 | (fp->odrive0<<0) | (fp->odrive1<<4);
break;
case 3:
fp->ostr = 0x00;
break;
}
if (out != fp->oval)
{
fp->oval = out;
schedule_functor(ptr, 0);
}
// old_ival is set on the way out
put(i, val);
unsigned char out = udp->propagate(this, i);
put_oval(i, false, out);
}
@ -67,7 +49,7 @@ struct vvp_udp_s *udp_create(char *label)
assert(!udp_find(label));
struct vvp_udp_s *u = new struct vvp_udp_s;
struct vvp_udp_s *u = new vvp_udp_s;
symbol_value_t v;
v.ptr = u;
@ -106,9 +88,9 @@ enum edge_type_e
EDGE_any = 0x0f,
};
unsigned char vvp_udp_s::propagate_(vvp_ipoint_t uix)
unsigned char vvp_udp_s::propagate(functor_t fu, vvp_ipoint_t uix)
{
functor_t fu = functor_index(uix);
vvp_ipoint_t base = ipoint_make(uix, 0);
unsigned char ret = 2;
@ -119,8 +101,10 @@ unsigned char vvp_udp_s::propagate_(vvp_ipoint_t uix)
for (int i=0; i < nin; i+=4)
{
int idx = ipoint_input_index(uix, i);
functor_t pfun = functor_index(idx);
int idx = ipoint_input_index(base, i);
edge_inputs_functor_s *pfun =
dynamic_cast<edge_inputs_functor_s *>(functor_index(idx));
assert(pfun);
invec |= pfun->ival << (2*i);
@ -144,10 +128,10 @@ unsigned char vvp_udp_s::propagate_(vvp_ipoint_t uix)
if (sequ)
{
invec <<= 2;
invec |= (fu->oval&3);
if (edge_type == 0)
return fu->oval;
return fu->get();
invec <<= 2;
invec |= (fu->get() & 3);
}
udp_vec_t inx = invec & 0xaaaaaaaaU; // all 'x'/'z'
@ -179,7 +163,7 @@ unsigned char vvp_udp_s::propagate_(vvp_ipoint_t uix)
}
if (ret>2)
ret = fu->oval;
ret = fu->get();
return ret;
}
@ -201,7 +185,7 @@ void vvp_udp_s::compile_table(char **tab)
void vvp_udp_s::compile_row_(udp_table_entry_t row, char *rchr)
{
row->not_0 = 0; // all inputs that must not be 0
row->not_1x = 0; // all inputs that bust not be 1 or x
row->not_1x = 0; // all inputs that must not be 1 or x
row->edge_idx = 0; // input index of the edge
row->edge_type = 0; // permissible transitions. 0: no edge.
@ -366,6 +350,11 @@ void vvp_udp_s::compile_row_(udp_table_entry_t row, char *rchr)
/*
* $Log: udp.cc,v $
* Revision 1.12 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.11 2001/09/19 04:10:40 steve
* Change UDP output only if table matches.
*

View File

@ -20,40 +20,53 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: udp.h,v 1.9 2001/08/09 19:38:23 steve Exp $"
#ident "$Id: udp.h,v 1.10 2001/10/31 04:27:47 steve Exp $"
#endif
#include "pointers.h"
#include "functor.h"
// UDP implementation:
typedef struct udp_table_entry_s *udp_table_entry_t;
class vvp_udp_s : public vvp_fobj_s
struct vvp_udp_s
{
public:
void set(vvp_ipoint_t i, functor_t f, bool push);
public:
char *name;
udp_table_entry_t table;
unsigned short ntable;
unsigned short sequ;
unsigned short nin;
unsigned char init;
unsigned char init;
void compile_table(char **tab);
private:
unsigned char propagate(functor_t fu, vvp_ipoint_t i);
private:
void compile_row_(udp_table_entry_t, char *);
unsigned char propagate_(vvp_ipoint_t i);
};
struct vvp_udp_s *udp_create(char *label);
struct vvp_udp_s *udp_find(char *label);
// UDP instances:
class udp_functor_s : public edge_inputs_functor_s
{
public:
explicit udp_functor_s(vvp_udp_s *u) : udp(u) {}
void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
vvp_udp_s *udp;
};
/*
* $Log: udp.h,v $
* Revision 1.10 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.9 2001/08/09 19:38:23 steve
* Nets (wires) do not use their own functors.
* Modifications to propagation of values.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_callback.cc,v 1.8 2001/10/25 04:19:53 steve Exp $"
#ident "$Id: vpi_callback.cc,v 1.9 2001/10/31 04:27:47 steve Exp $"
#endif
/*
@ -51,6 +51,27 @@ const struct __vpirt callback_rt = {
0
};
/*
* Callback handles are created when the VPI function registers a
* callback. The handle is stored by the run time, and it triggered
* when the run-time thing that it is waiting for happens.
*/
struct __vpiCallback {
struct __vpiHandle base;
struct t_cb_data cb_data;
struct t_vpi_time cb_time;
struct sync_cb* cb_sync;
struct __vpiCallback*next;
};
struct sync_cb : public vvp_gen_event_s {
struct __vpiCallback*handle;
};
static struct __vpiCallback* free_callback_root = 0x0;
inline static struct __vpiCallback* new_vpi_callback()
@ -74,54 +95,66 @@ inline static void free_vpi_callback(struct __vpiCallback* obj)
}
/*
* A signal get equipped with an M42 event functor to trigger
* A signal get equipped with a callback_functor_s to trigger
* callbacks.
*/
struct vvp_cb_fobj_s *vvp_fvector_make_callback(vvp_fvector_t vec,
const unsigned char *edge)
{
struct vvp_cb_fobj_s *obj = new vvp_cb_fobj_s;
unsigned nvec = vvp_fvector_size(vec);
unsigned nfun = (nvec+3)/4;
struct callback_functor_s: public functor_s {
callback_functor_s() : permanent(0) {}
virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str);
struct __vpiCallback *cb_handle;
unsigned permanent : 1;
};
if (edge)
struct callback_functor_s *vvp_fvector_make_callback(vvp_fvector_t vec,
event_functor_s::edge_t edge)
{
// Let's make a callback functor.
struct callback_functor_s *obj = new callback_functor_s;
// We want to connect nvec inputs
unsigned nvec = vvp_fvector_size(vec);
// We require a total of nfun functors. If there's an edge to
// look for, then all inputs must go to extra event functors.
// Otherwise we just make sure we have one input left on the base
// functor to connect the extras to, if there are any.
unsigned nfun = (nvec+3)/4;
if (edge != vvp_edge_none)
nfun ++ ;
else if (nfun > 1 && 4*nfun == nvec)
nfun ++;
vvp_ipoint_t fdx = functor_allocate(nfun);
unsigned vi = 0;
for (unsigned i = 0; i<nfun; i++) {
vvp_ipoint_t ipt = ipoint_index(fdx, i);
functor_t fu = functor_index(ipt);
fu->ival = 0xaa;
fu->oval = 2;
fu->odrive0 = 6;
fu->odrive0 = 6;
fu->out = 0;
#if defined(WITH_DEBUG)
fu->breakpoint = 0;
#endif
if (i == nfun-1) {
fu->mode = M42;
fu->obj = obj;
} else {
fu->mode = 1;
fu->event = (struct vvp_event_s*)
malloc(sizeof (struct vvp_event_s));
fu->event->threads = 0;
fu->old_ival = fu->ival;
fu->event->vvp_edge_tab = edge;
fu->out = ipoint_input_index(ipoint_index(fdx, nfun-1), 3);
}
for (unsigned j=0; j<4 && vi < nvec; j++, vi++) {
vvp_ipoint_t vipt = vvp_fvector_get(vec, vi);
functor_t vfu = functor_index(vipt);
fu->port[j] = vfu->out;
vfu->out = ipoint_input_index(ipt, j);
}
functor_define(fdx, obj);
for (unsigned i=1; i<nfun; i++) {
functor_t fu = new event_functor_s(edge);
functor_define(ipoint_index(fdx, i), fu);
fu->out = fdx;
}
unsigned i;
if (edge != vvp_edge_none)
i = 4;
else if (nvec > 4)
i = 1;
else
i = 0;
for (unsigned vi = 0; vi < nvec; vi++, i++) {
vvp_ipoint_t vipt = vvp_fvector_get(vec, vi);
functor_t vfu = functor_index(vipt);
vvp_ipoint_t ipt = ipoint_input_index(fdx, i);
functor_t fu = functor_index(ipt);
unsigned pp = ipoint_port(ipt);
fu->port[pp] = vfu->out;
vfu->out = ipt;
}
obj->permanent = 0;
obj->cb_handle = 0;
return obj;
@ -157,10 +190,6 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
return obj;
}
struct sync_cb : public vvp_gen_event_s {
struct __vpiCallback*handle;
};
static void make_sync_run(vvp_gen_event_t obj, unsigned char)
{
struct sync_cb*cb = (struct sync_cb*)obj;
@ -235,7 +264,7 @@ int vpi_remove_cb(vpiHandle ref)
* A callback event happened.
*/
void vvp_cb_fobj_s::set(vvp_ipoint_t i, functor_t f, bool push)
void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
{
struct __vpiCallback *next = cb_handle;
if (!permanent)
@ -246,7 +275,7 @@ void vvp_cb_fobj_s::set(vvp_ipoint_t i, functor_t f, bool push)
if (cur->cb_data.value) {
switch (cur->cb_data.value->format) {
case vpiScalarVal:
cur->cb_data.value->value.scalar = f->ival & 3;
cur->cb_data.value->value.scalar = val;
break;
case vpiSuppressVal:
break;
@ -271,6 +300,11 @@ void vpip_trip_monitor_callbacks(void)
/*
* $Log: vpi_callback.cc,v $
* Revision 1.9 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.8 2001/10/25 04:19:53 steve
* VPI support for callback to return values.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_priv.cc,v 1.9 2001/09/15 18:27:05 steve Exp $"
#ident "$Id: vpi_priv.cc,v 1.10 2001/10/31 04:27:47 steve Exp $"
#endif
# include "vpi_priv.h"
@ -75,7 +75,7 @@ char* vpi_get_str(int property, vpiHandle ref)
if (ref->vpi_type->vpi_get_str_ == 0)
return 0;
return (ref->vpi_type->vpi_get_str_)(property, ref);
return (char*)(ref->vpi_type->vpi_get_str_)(property, ref);
}
void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
@ -154,6 +154,11 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
/*
* $Log: vpi_priv.cc,v $
* Revision 1.10 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.9 2001/09/15 18:27:05 steve
* Make configure detect malloc.h
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_priv.h,v 1.23 2001/10/15 01:49:50 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.24 2001/10/31 04:27:47 steve Exp $"
#endif
# include "vpi_user.h"
@ -110,32 +110,14 @@ struct __vpiSignal {
unsigned signed_flag : 1;
/* The represented value is here. */
vvp_fvector_t bits;
/* This is the callback event finctor object */
struct vvp_cb_fobj_s *callback;
/* This is the callback event functor */
struct callback_functor_s *callback;
};
extern vpiHandle vpip_make_reg(char*name, int msb, int lsb, bool signed_flag,
vvp_fvector_t vec);
extern vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag,
vvp_fvector_t vec);
/*
* Callback handles are created when the VPI function registers a
* callback. The handle is stored by the run time, and it triggered
* when the run-time thing that it is waiting for happens.
*/
struct sync_cb;
struct __vpiCallback {
struct __vpiHandle base;
struct t_cb_data cb_data;
struct t_vpi_time cb_time;
struct sync_cb* cb_sync;
struct __vpiCallback*next;
};
/*
* Memory is an array of bits that is accessible in N-bit chunks, with
* N being the width of a word. The memory word handle just points
@ -259,6 +241,11 @@ extern void vpip_set_time_precision(int pres);
/*
* $Log: vpi_priv.h,v $
* Revision 1.24 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.23 2001/10/15 01:49:50 steve
* Support getting scope of scope, and scope of signals.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_signal.cc,v 1.27 2001/10/18 04:52:31 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.28 2001/10/31 04:27:47 steve Exp $"
#endif
/*
@ -136,7 +136,7 @@ static void signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, wid-idx-1);
val *= 2;
switch (functor_oval(fptr)) {
switch (functor_get(fptr)) {
case 0:
break;
case 1:
@ -210,7 +210,7 @@ static void signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
for (bdx = 8 ; bdx > 0 ; bdx -= 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx-8+bdx-1);
tmp <<= 1;
switch (functor_oval(fptr)) {
switch (functor_get(fptr)) {
case 0:
break;
case 1:
@ -248,7 +248,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
vp->value.integer = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
switch (functor_oval(fptr)) {
switch (functor_get(fptr)) {
case 0:
break;
case 1:
@ -265,7 +265,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
case vpiBinStrVal:
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
buf[wid-idx-1] = "01xz"[functor_oval(fptr)];
buf[wid-idx-1] = "01xz"[functor_get(fptr)];
}
buf[wid] = 0;
vp->value.str = buf;
@ -278,7 +278,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
hval = hval | (functor_oval(fptr) << 2*(idx % 4));
hval = hval | (functor_get(fptr) << 2*(idx % 4));
if (idx%4 == 3) {
hwid -= 1;
@ -313,7 +313,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
hval = hval | (functor_oval(fptr) << 2*(idx % 3));
hval = hval | (functor_get(fptr) << 2*(idx % 3));
if (idx%3 == 2) {
hwid -= 1;
@ -357,7 +357,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
unsigned int obit = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
switch (functor_oval(fptr)) {
switch (functor_get(fptr)) {
case 0:
op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit);
@ -404,9 +404,7 @@ static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
{
vvp_ipoint_t ptr = vvp_fvector_get(rfp->bits,idx);
functor_t fu = functor_index(ptr);
fu->oval = val;
fu->ostr = str;
functor_propagate(ptr);
fu->put_ostr(ptr, true, val, str);
}
static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
@ -554,6 +552,11 @@ vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.28 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.27 2001/10/18 04:52:31 steve
* Support vpiVectorVal for signals. (Philip Blundell)
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vthread.cc,v 1.61 2001/10/25 04:19:53 steve Exp $"
#ident "$Id: vthread.cc,v 1.62 2001/10/31 04:27:47 steve Exp $"
#endif
# include "vthread.h"
@ -1577,9 +1577,8 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp)
{
assert(! thr->waiting_for_event);
thr->waiting_for_event = 1;
functor_t fp = functor_index(cp->iptr);
assert((fp->mode == 1) || (fp->mode == 2));
vvp_event_t ep = fp->event;
vvp_event_t ep = dynamic_cast<vvp_event_t>(functor_index(cp->iptr));
assert(ep);
thr->wait_next = ep->threads;
ep->threads = thr;
@ -1672,6 +1671,11 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
/*
* $Log: vthread.cc,v $
* Revision 1.62 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.61 2001/10/25 04:19:53 steve
* VPI support for callback to return values.
*