Rewrite the functor type to have fewer functor modes,
and use objects to manage the different types. (Stephan Boettcher)
This commit is contained in:
parent
b3e430c751
commit
a75326e2e0
597
vvp/arith.cc
597
vvp/arith.cc
|
|
@ -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)
|
||||
*
|
||||
|
|
|
|||
133
vvp/arith.h
133
vvp/arith.h
|
|
@ -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)
|
||||
*
|
||||
|
|
|
|||
112
vvp/bufif.cc
112
vvp/bufif.cc
|
|
@ -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.
|
||||
|
|
|
|||
22
vvp/bufif.h
22
vvp/bufif.h
|
|
@ -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.
|
||||
|
|
|
|||
595
vvp/compile.cc
595
vvp/compile.cc
|
|
@ -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)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
344
vvp/functor.cc
344
vvp/functor.cc
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
475
vvp/functor.h
475
vvp/functor.h
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
13
vvp/memory.h
13
vvp/memory.h
|
|
@ -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.
|
||||
|
|
|
|||
102
vvp/npmos.cc
102
vvp/npmos.cc
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
37
vvp/npmos.h
37
vvp/npmos.h
|
|
@ -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
|
||||
|
|
|
|||
17
vvp/parse.y
17
vvp/parse.y
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
15
vvp/resolv.h
15
vvp/resolv.h
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
57
vvp/udp.cc
57
vvp/udp.cc
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
37
vvp/udp.h
37
vvp/udp.h
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue