diff --git a/vvp/arith.cc b/vvp/arith.cc index eca7eafa4..2bece7e43 100644 --- a/vvp/arith.cc +++ b/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 # include # include +# include - - -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) * diff --git a/vvp/arith.h b/vvp/arith.h index df15c1a80..e26461233 100644 --- a/vvp/arith.h +++ b/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) * diff --git a/vvp/bufif.cc b/vvp/bufif.cc index 9ee67ab60..343aefdef 100644 --- a/vvp/bufif.cc +++ b/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. diff --git a/vvp/bufif.h b/vvp/bufif.h index 68e6f6b49..d14a81406 100644 --- a/vvp/bufif.h +++ b/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. diff --git a/vvp/compile.cc b/vvp/compile.cc index 069602a51..4501914ec 100644 --- a/vvp/compile.cc +++ b/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") == 0) + iobj->set(ifdx, false, 0, Pu0); + + else if (strcmp(argv[idx].text, "C") == 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") == 0) + iobj->set(ifdx, false, 1, Pu1); + + else if (strcmp(argv[idx].text, "C") == 0) + iobj->set(ifdx, false, 1, Su1); + + else if (strcmp(argv[idx].text, "C") == 0) + iobj->set(ifdx, false, 2, StX); + + else if (strcmp(argv[idx].text, "C") == 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") == 0) { - free(argv[idx].text); - functor_put_input(iobj, idx, 0, Pu0); - continue; - } - - if (strcmp(argv[idx].text, "C") == 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") == 0) { - free(argv[idx].text); - functor_put_input(iobj, idx, 1, Pu1); - continue; - } - - if (strcmp(argv[idx].text, "C") == 0) { - free(argv[idx].text); - functor_put_input(iobj, idx, 1, Su1); - continue; - } - - if (strcmp(argv[idx].text, "C") == 0) { - free(argv[idx].text); - functor_put_input(iobj, idx, 2, StX); - continue; - } - - if (strcmp(argv[idx].text, "C") == 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 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 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; iival = 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 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) * diff --git a/vvp/compile.h b/vvp/compile.h index 7cbbfdb6a..249d610ee 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -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 @@ -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. * diff --git a/vvp/functor.cc b/vvp/functor.cc index e87cf5a9f..da9da50f6 100644 --- a/vvp/functor.cc +++ b/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 # include +# include /* * 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. * diff --git a/vvp/functor.h b/vvp/functor.h index 54da6359b..537fb0172 100644 --- a/vvp/functor.h +++ b/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. * diff --git a/vvp/memory.cc b/vvp/memory.cc index 93f4c1ce6..dcd2b2960 100644 --- a/vvp/memory.cc +++ b/vvp/memory.cc @@ -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)) diff --git a/vvp/memory.h b/vvp/memory.h index 7c4e639fc..c91b9917e 100644 --- a/vvp/memory.h +++ b/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. diff --git a/vvp/npmos.cc b/vvp/npmos.cc index 83a62f60f..5f1fa7dad 100644 --- a/vvp/npmos.cc +++ b/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. * diff --git a/vvp/npmos.h b/vvp/npmos.h index 2190a6a26..362372612 100644 --- a/vvp/npmos.h +++ b/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 diff --git a/vvp/parse.y b/vvp/parse.y index 64d66ba90..e88083c17 100644 --- a/vvp/parse.y +++ b/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. * diff --git a/vvp/pointers.h b/vvp/pointers.h index 82cd4f42c..fd12ed959 100644 --- a/vvp/pointers.h +++ b/vvp/pointers.h @@ -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) diff --git a/vvp/resolv.cc b/vvp/resolv.cc index 101fe92d9..9a6c20a07 100644 --- a/vvp/resolv.cc +++ b/vvp/resolv.cc @@ -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. * diff --git a/vvp/resolv.h b/vvp/resolv.h index 4ad7286f7..4ed3b7235 100644 --- a/vvp/resolv.h +++ b/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. * diff --git a/vvp/schedule.h b/vvp/schedule.h index 083e94de6..02d167c56 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -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. * diff --git a/vvp/udp.cc b/vvp/udp.cc index e978bc837..38940b70e 100644 --- a/vvp/udp.cc +++ b/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 #include -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(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. * diff --git a/vvp/udp.h b/vvp/udp.h index e839fedda..3bea029d8 100644 --- a/vvp/udp.h +++ b/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. diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 2a0f1d5f9..ac5351def 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -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; iival = 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; iout = 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. * diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 0a244d105..90eb1ea18 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -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 * diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 021606641..5a4268806 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.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. * diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 2f2a07e91..af3688cd8 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -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) * diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 4190de4a8..1928517d2 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -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(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. *