Implement .resolv functors, and stub signals recv_vec8 method.
This commit is contained in:
parent
d1e2538aba
commit
34a14b983b
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: README.txt,v 1.50 2004/12/29 23:45:13 steve Exp $
|
||||
* $Id: README.txt,v 1.51 2004/12/31 06:00:06 steve Exp $
|
||||
*/
|
||||
|
||||
VVP SIMULATION ENGINE
|
||||
|
|
@ -437,6 +437,9 @@ resolution function.
|
|||
<label> .resolv tri0, <symbols_list>;
|
||||
<label> .resolv tri1, <symbols_list>;
|
||||
|
||||
The output from the resolver is vvp_vector8_t value. That is, the
|
||||
result is a vector with strength included.
|
||||
|
||||
|
||||
PART SELECT STATEMENTS:
|
||||
|
||||
|
|
|
|||
196
vvp/resolv.cc
196
vvp/resolv.cc
|
|
@ -17,178 +17,15 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: resolv.cc,v 1.18 2004/12/11 02:31:30 steve Exp $"
|
||||
#ident "$Id: resolv.cc,v 1.19 2004/12/31 06:00:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "resolv.h"
|
||||
# include "schedule.h"
|
||||
# include "statistics.h"
|
||||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* A signal value is unambiguous if the top 4 bits and the bottom 4
|
||||
* bits are identical. This means that the VSSSvsss bits of the 8bit
|
||||
* value have V==v and SSS==sss.
|
||||
*/
|
||||
# define UNAMBIG(v) (((v) & 0x0f) == (((v) >> 4) & 0x0f))
|
||||
|
||||
# define STREN1(v) ( ((v)&0x80)? ((v)&0xf0) : (0x70 - ((v)&0xf0)) )
|
||||
# define STREN0(v) ( ((v)&0x08)? ((v)&0x0f) : (0x07 - ((v)&0x0f)) )
|
||||
|
||||
# include <iostream>
|
||||
static unsigned blend(unsigned a, unsigned b)
|
||||
{
|
||||
if (a == HiZ)
|
||||
return b;
|
||||
|
||||
if (b == HiZ)
|
||||
return a;
|
||||
|
||||
unsigned res = a;
|
||||
|
||||
if (UNAMBIG(a) && UNAMBIG(b)) {
|
||||
|
||||
/* If both signals are unambiguous, simply choose
|
||||
the stronger. If they have the same strength
|
||||
but different values, then this becomes
|
||||
ambiguous. */
|
||||
|
||||
if (a == b) {
|
||||
|
||||
/* values are equal. do nothing. */
|
||||
|
||||
} else if ((b&0x07) > (res&0x07)) {
|
||||
|
||||
/* New value is stronger. Take it. */
|
||||
res = b;
|
||||
|
||||
} else if ((b&0x77) == (res&0x77)) {
|
||||
|
||||
/* Strengths are the same. Make value ambiguous. */
|
||||
res = (res&0x70) | (b&0x07) | 0x80;
|
||||
|
||||
} else {
|
||||
|
||||
/* Must be res is the stronger one. */
|
||||
}
|
||||
|
||||
} else if (UNAMBIG(res)) {
|
||||
unsigned tmp = 0;
|
||||
|
||||
if ((res&0x70) > (b&0x70))
|
||||
tmp |= res&0xf0;
|
||||
else
|
||||
tmp |= b&0xf0;
|
||||
|
||||
if ((res&0x07) > (b&0x07))
|
||||
tmp |= res&0x0f;
|
||||
else
|
||||
tmp |= b&0x0f;
|
||||
|
||||
res = tmp;
|
||||
|
||||
} else if (UNAMBIG(b)) {
|
||||
|
||||
/* If one of the signals is unambiguous, then it
|
||||
will sweep up the weaker parts of the ambiguous
|
||||
signal. The result may be ambiguous, or maybe not. */
|
||||
|
||||
unsigned tmp = 0;
|
||||
|
||||
if ((b&0x70) > (res&0x70))
|
||||
tmp |= b&0xf0;
|
||||
else
|
||||
tmp |= res&0xf0;
|
||||
|
||||
if ((b&0x07) > (res&0x07))
|
||||
tmp |= b&0x0f;
|
||||
else
|
||||
tmp |= res&0x0f;
|
||||
|
||||
res = tmp;
|
||||
|
||||
} else {
|
||||
|
||||
/* If both signals are ambiguous, then the result
|
||||
has an even wider ambiguity. */
|
||||
|
||||
unsigned tmp = 0;
|
||||
|
||||
if (STREN1(b) > STREN1(res))
|
||||
tmp |= b&0xf0;
|
||||
else
|
||||
tmp |= res&0xf0;
|
||||
|
||||
if (STREN0(b) < STREN0(res))
|
||||
tmp |= b&0x0f;
|
||||
else
|
||||
tmp |= res&0x0f;
|
||||
|
||||
res = tmp;
|
||||
}
|
||||
|
||||
|
||||
/* Canonicalize the HiZ value. */
|
||||
if ((res&0x77) == 0)
|
||||
res = HiZ;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
resolv_functor_s::resolv_functor_s(unsigned char pull)
|
||||
{
|
||||
count_functors_resolv += 1;
|
||||
istr[0]=istr[1]=istr[2]=istr[3]=StX;
|
||||
hiz_ = pull;
|
||||
}
|
||||
|
||||
resolv_functor_s::~resolv_functor_s()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the strength values of the inputs, two at a time. Pairs of
|
||||
* inputs are resolved with the blend function, and the final value is
|
||||
* reduced to a 4-value result for propagation.
|
||||
*/
|
||||
void resolv_functor_s::set(vvp_ipoint_t i, bool push, unsigned, unsigned str)
|
||||
{
|
||||
unsigned pp = ipoint_port(i);
|
||||
istr[pp] = str;
|
||||
|
||||
unsigned sval = hiz_;
|
||||
sval = blend(sval, istr[0]);
|
||||
sval = blend(sval, istr[1]);
|
||||
sval = blend(sval, istr[2]);
|
||||
sval = blend(sval, istr[3]);
|
||||
|
||||
unsigned val;
|
||||
if (sval == HiZ) {
|
||||
val = 3;
|
||||
|
||||
} else switch (sval & 0x88) {
|
||||
case 0x00:
|
||||
val = 0;
|
||||
break;
|
||||
case 0x88:
|
||||
val = 1;
|
||||
break;
|
||||
default:
|
||||
val = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the output changes, then create a propagation event. */
|
||||
|
||||
// Do not propagate (push). Why? Because if, for example, a
|
||||
// clock buffer is modeled as parallel inverters, the output
|
||||
// must not show 'bx transitions when the inverters all propagate
|
||||
// at the same time.
|
||||
|
||||
put_ostr(val, sval, false);
|
||||
}
|
||||
#else
|
||||
|
||||
resolv_functor::resolv_functor(vvp_scaler_t hiz_value)
|
||||
: hiz_(hiz_value)
|
||||
|
|
@ -199,15 +36,38 @@ resolv_functor::~resolv_functor()
|
|||
{
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec8(vvp_vector8_t vit)
|
||||
void resolv_functor::recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit)
|
||||
{
|
||||
assert(0); // XXXX not implemented yet!
|
||||
recv_vec8(port, vvp_vector8_t(bit, 6 /* STRONG */));
|
||||
}
|
||||
|
||||
void resolv_functor::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
|
||||
{
|
||||
unsigned pdx = port.port();
|
||||
vvp_net_t*ptr = port.ptr();
|
||||
|
||||
val_[pdx] = bit;
|
||||
|
||||
vvp_vector8_t out (bit);
|
||||
|
||||
for (unsigned idx = 0 ; idx < 4 ; idx += 1) {
|
||||
if (val_[idx].size() == 0)
|
||||
continue;
|
||||
if (idx == pdx)
|
||||
continue;
|
||||
|
||||
out = resolve(out, val_[idx]);
|
||||
}
|
||||
|
||||
vvp_send_vec8(ptr->out, out);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: resolv.cc,v $
|
||||
* Revision 1.19 2004/12/31 06:00:06 steve
|
||||
* Implement .resolv functors, and stub signals recv_vec8 method.
|
||||
*
|
||||
* Revision 1.18 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
10
vvp/resolv.h
10
vvp/resolv.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: resolv.h,v 1.9 2004/12/11 02:31:30 steve Exp $"
|
||||
#ident "$Id: resolv.h,v 1.10 2004/12/31 06:00:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -41,15 +41,19 @@ class resolv_functor : public vvp_net_fun_t {
|
|||
explicit resolv_functor(vvp_scaler_t hiz_value);
|
||||
~resolv_functor();
|
||||
|
||||
void recv_vec8(vvp_vector8_t bit);
|
||||
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
|
||||
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
|
||||
|
||||
private:
|
||||
vvp_vector8_t driven_;
|
||||
vvp_vector8_t val_[4];
|
||||
vvp_scaler_t hiz_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: resolv.h,v $
|
||||
* Revision 1.10 2004/12/31 06:00:06 steve
|
||||
* Implement .resolv functors, and stub signals recv_vec8 method.
|
||||
*
|
||||
* Revision 1.9 2004/12/11 02:31:30 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
|
|
|
|||
123
vvp/vvp_net.cc
123
vvp/vvp_net.cc
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.cc,v 1.2 2004/12/15 17:16:08 steve Exp $"
|
||||
#ident "$Id: vvp_net.cc,v 1.3 2004/12/31 06:00:06 steve Exp $"
|
||||
|
||||
# include "vvp_net.h"
|
||||
# include <stdio.h>
|
||||
|
|
@ -62,6 +62,18 @@ void vvp_send_vec4(vvp_net_ptr_t ptr, vvp_vector4_t val)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_send_vec8(vvp_net_ptr_t ptr, vvp_vector8_t val)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
vvp_net_ptr_t next = cur->port[ptr.port()];
|
||||
|
||||
if (cur->fun)
|
||||
cur->fun->recv_vec8(ptr, val);
|
||||
|
||||
ptr = next;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_send_real(vvp_net_ptr_t ptr, double val)
|
||||
{
|
||||
while (struct vvp_net_t*cur = ptr.ptr()) {
|
||||
|
|
@ -190,6 +202,17 @@ void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
|
|||
}
|
||||
}
|
||||
|
||||
vvp_vector8_t::vvp_vector8_t(const vvp_vector8_t&that)
|
||||
{
|
||||
size_ = that.size_;
|
||||
|
||||
bits_ = new vvp_scaler_t[size_];
|
||||
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
|
||||
}
|
||||
|
||||
vvp_vector8_t::vvp_vector8_t(unsigned size)
|
||||
: size_(size)
|
||||
{
|
||||
|
|
@ -201,12 +224,63 @@ vvp_vector8_t::vvp_vector8_t(unsigned size)
|
|||
bits_ = new vvp_scaler_t[size_];
|
||||
}
|
||||
|
||||
vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that, unsigned str)
|
||||
: size_(that.size())
|
||||
{
|
||||
if (size_ == 0) {
|
||||
bits_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
bits_ = new vvp_scaler_t[size_];
|
||||
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
bits_[idx] = vvp_scaler_t (that.value(idx), str);
|
||||
|
||||
}
|
||||
|
||||
vvp_vector8_t::~vvp_vector8_t()
|
||||
{
|
||||
if (size_ > 0)
|
||||
delete[]bits_;
|
||||
}
|
||||
|
||||
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
|
||||
{
|
||||
if (size_ != that.size_) {
|
||||
if (size_ > 0)
|
||||
delete[]bits_;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
if (that.size_ == 0) {
|
||||
assert(size_ == 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (size_ == 0) {
|
||||
size_ = that.size_;
|
||||
bits_ = new vvp_scaler_t[size_];
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
vvp_scaler_t vvp_vector8_t::value(unsigned idx) const
|
||||
{
|
||||
assert(idx < size_);
|
||||
return bits_[idx];
|
||||
}
|
||||
|
||||
void vvp_vector8_t::set_bit(unsigned idx, vvp_scaler_t val)
|
||||
{
|
||||
assert(idx < size_);
|
||||
bits_[idx] = val;
|
||||
}
|
||||
|
||||
vvp_net_fun_t::vvp_net_fun_t()
|
||||
{
|
||||
}
|
||||
|
|
@ -286,6 +360,13 @@ void vvp_fun_signal::recv_vec4(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
|||
}
|
||||
}
|
||||
|
||||
void vvp_fun_signal::recv_vec8(vvp_net_ptr_t ptr, vvp_vector8_t bit)
|
||||
{
|
||||
fprintf(stderr, "internal error: vvp_fun_signal "
|
||||
"reducing vector8 input.\n");
|
||||
recv_vec4(ptr, reduce4(bit));
|
||||
}
|
||||
|
||||
void vvp_fun_signal::deassign()
|
||||
{
|
||||
continuous_assign_active_ = false;
|
||||
|
|
@ -407,6 +488,21 @@ vvp_scaler_t::vvp_scaler_t()
|
|||
value_ = 0;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_scaler_t::value() const
|
||||
{
|
||||
if (value_ == 0) {
|
||||
return BIT4_Z;
|
||||
|
||||
} else switch (value_ & 0x88) {
|
||||
case 0x00:
|
||||
return BIT4_0;
|
||||
case 0x88:
|
||||
return BIT4_1;
|
||||
default:
|
||||
return BIT4_X;
|
||||
}
|
||||
}
|
||||
|
||||
vvp_scaler_t resolve(vvp_scaler_t a, vvp_scaler_t b)
|
||||
{
|
||||
// If the value is 0, that is the same as HiZ. In that case,
|
||||
|
|
@ -507,8 +603,33 @@ vvp_scaler_t resolve(vvp_scaler_t a, vvp_scaler_t b)
|
|||
return res;
|
||||
}
|
||||
|
||||
vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b)
|
||||
{
|
||||
assert(a.size() == b.size());
|
||||
|
||||
vvp_vector8_t out (a.size());
|
||||
|
||||
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
|
||||
out.set_bit(idx, resolve(a.value(idx), b.value(idx)));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
vvp_vector4_t reduce4(const vvp_vector8_t&that)
|
||||
{
|
||||
vvp_vector4_t out (that.size());
|
||||
for (unsigned idx = 0 ; idx < out.size() ; idx += 1)
|
||||
out.set_bit(idx, that.value(idx).value());
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vvp_net.cc,v $
|
||||
* Revision 1.3 2004/12/31 06:00:06 steve
|
||||
* Implement .resolv functors, and stub signals recv_vec8 method.
|
||||
*
|
||||
* Revision 1.2 2004/12/15 17:16:08 steve
|
||||
* Add basic force/release capabilities.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.h,v 1.3 2004/12/29 23:45:13 steve Exp $"
|
||||
#ident "$Id: vvp_net.h,v 1.4 2004/12/31 06:00:06 steve Exp $"
|
||||
|
||||
# include <assert.h>
|
||||
|
||||
|
|
@ -123,11 +123,17 @@ extern vvp_scaler_t resolve(vvp_scaler_t a, vvp_scaler_t b);
|
|||
* values. The 8 in the name is the number of possible distinct values
|
||||
* a well defined bit may have. When you add in ambiguous values, the
|
||||
* number of distinct values span the vvp_scaler_t.
|
||||
*
|
||||
* a vvp_vector8_t object can be created from a vvp_vector4_t and a
|
||||
* strength value. The vvp_vector8_t bits have the values of the input
|
||||
* vector, all with the strength specified.
|
||||
*/
|
||||
class vvp_vector8_t {
|
||||
|
||||
public:
|
||||
explicit vvp_vector8_t(unsigned size =0);
|
||||
// Make a vvp_vector8_t from a vector4 and a specified strength.
|
||||
explicit vvp_vector8_t(const vvp_vector4_t&that, unsigned str);
|
||||
|
||||
~vvp_vector8_t();
|
||||
|
||||
|
|
@ -143,6 +149,9 @@ class vvp_vector8_t {
|
|||
vvp_scaler_t*bits_;
|
||||
};
|
||||
|
||||
extern vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b);
|
||||
extern vvp_vector4_t reduce4(const vvp_vector8_t&that);
|
||||
|
||||
/*
|
||||
* This class implements a pointer that points to an item within a
|
||||
* target. The ptr() method returns a pointer to the vvp_net_t, and
|
||||
|
|
@ -253,7 +262,7 @@ struct vvp_net_t {
|
|||
};
|
||||
|
||||
extern void vvp_send_vec4(vvp_net_ptr_t ptr, vvp_vector4_t val);
|
||||
extern void vvp_send_vec8(vvp_net_ptr_t ptr, vvp_vector4_t val);
|
||||
extern void vvp_send_vec8(vvp_net_ptr_t ptr, vvp_vector8_t val);
|
||||
extern void vvp_send_real(vvp_net_ptr_t ptr, double val);
|
||||
extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
|
||||
|
||||
|
|
@ -412,6 +421,7 @@ class vvp_fun_signal : public vvp_net_fun_t {
|
|||
explicit vvp_fun_signal(unsigned wid);
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, vvp_vector4_t bit);
|
||||
void recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit);
|
||||
void recv_long(vvp_net_ptr_t port, long bit);
|
||||
|
||||
// Get information about the vector value.
|
||||
|
|
@ -438,6 +448,9 @@ class vvp_fun_signal : public vvp_net_fun_t {
|
|||
|
||||
/*
|
||||
* $Log: vvp_net.h,v $
|
||||
* Revision 1.4 2004/12/31 06:00:06 steve
|
||||
* Implement .resolv functors, and stub signals recv_vec8 method.
|
||||
*
|
||||
* Revision 1.3 2004/12/29 23:45:13 steve
|
||||
* Add the part concatenation node (.concat).
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue