Implement atom2 types with vvp_vector2_t.
This reflects the SystemVerilog intent, and also washes away the 'bx and 'bz values properly.
This commit is contained in:
parent
4643872fc6
commit
67000e46a8
|
|
@ -702,6 +702,11 @@ void vvp_wire_real::get_signal_value(struct t_vpi_value*vp)
|
|||
real_signal_value(vp, real_value());
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::get_value(struct t_vpi_value*val)
|
||||
{
|
||||
get_signal_value(val);
|
||||
}
|
||||
|
||||
void vvp_wire_vec4::get_value(struct t_vpi_value*val)
|
||||
{
|
||||
get_signal_value(val);
|
||||
|
|
|
|||
|
|
@ -1940,7 +1940,24 @@ vvp_vector2_t::vvp_vector2_t(vvp_vector2_t::fill_t fill, unsigned wid)
|
|||
vec_[idx] = fill? -1 : 0;
|
||||
}
|
||||
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned base, unsigned wid)
|
||||
{
|
||||
wid_ = wid;
|
||||
const unsigned words = (wid_ + BITS_PER_WORD-1) / BITS_PER_WORD;
|
||||
|
||||
vec_ = new unsigned long[words];
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
int bit = that.value(base+idx);
|
||||
if (bit == 0)
|
||||
continue;
|
||||
unsigned word = idx / BITS_PER_WORD;
|
||||
unsigned long mask = 1UL << (idx % BITS_PER_WORD);
|
||||
vec_[word] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_vector2_t::copy_from_that_(const vvp_vector4_t&that)
|
||||
{
|
||||
wid_ = that.size();
|
||||
const unsigned words = (that.size() + BITS_PER_WORD-1) / BITS_PER_WORD;
|
||||
|
|
@ -1961,15 +1978,12 @@ vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
|
|||
|
||||
switch (that.value(idx)) {
|
||||
case BIT4_0:
|
||||
case BIT4_X:
|
||||
case BIT4_Z:
|
||||
break;
|
||||
case BIT4_1:
|
||||
vec_[addr] |= 1UL << shift;
|
||||
break;
|
||||
default:
|
||||
delete[]vec_;
|
||||
vec_ = 0;
|
||||
wid_ = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1990,11 +2004,6 @@ void vvp_vector2_t::copy_from_that_(const vvp_vector2_t&that)
|
|||
vec_[idx] = that.vec_[idx];
|
||||
}
|
||||
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
|
||||
{
|
||||
copy_from_that_(that);
|
||||
}
|
||||
|
||||
vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that, unsigned newsize)
|
||||
{
|
||||
wid_ = newsize;
|
||||
|
|
@ -2027,6 +2036,14 @@ vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector2_t&that)
|
|||
return *this;
|
||||
}
|
||||
|
||||
vvp_vector2_t& vvp_vector2_t::operator= (const vvp_vector4_t&that)
|
||||
{
|
||||
delete[]vec_;
|
||||
vec_ = 0;
|
||||
copy_from_that_(that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
vvp_vector2_t& vvp_vector2_t::operator <<= (unsigned int shift)
|
||||
{
|
||||
if (wid_ == 0)
|
||||
|
|
@ -2191,11 +2208,6 @@ vvp_vector2_t& vvp_vector2_t::operator -= (const vvp_vector2_t&that)
|
|||
return *this;
|
||||
}
|
||||
|
||||
vvp_vector2_t::~vvp_vector2_t()
|
||||
{
|
||||
delete[] vec_;
|
||||
}
|
||||
|
||||
void vvp_vector2_t::trim()
|
||||
{
|
||||
while (value(wid_-1) == 0 && wid_ > 1) wid_ -= 1;
|
||||
|
|
@ -2239,6 +2251,14 @@ void vvp_vector2_t::set_bit(unsigned idx, int bit)
|
|||
vec_[addr] &= ~(1UL << mask);
|
||||
}
|
||||
|
||||
void vvp_vector2_t::set_vec(unsigned adr, const vvp_vector2_t&that)
|
||||
{
|
||||
assert((adr + that.wid_) <= wid_);
|
||||
|
||||
for (unsigned idx = 0 ; idx < that.wid_ ; idx += 1)
|
||||
set_bit(adr+idx, that.value(idx));
|
||||
}
|
||||
|
||||
bool vvp_vector2_t::is_NaN() const
|
||||
{
|
||||
return wid_ == 0;
|
||||
|
|
@ -2650,6 +2670,24 @@ vvp_vector8_t::vvp_vector8_t(const vvp_vector4_t&that,
|
|||
}
|
||||
}
|
||||
|
||||
vvp_vector8_t::vvp_vector8_t(const vvp_vector2_t&that,
|
||||
unsigned str0, unsigned str1)
|
||||
: size_(that.size())
|
||||
{
|
||||
if (size_ == 0)
|
||||
return;
|
||||
|
||||
if (size_ <= sizeof val_) {
|
||||
ptr_ = 0;
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
val_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
|
||||
} else {
|
||||
ptr_ = new unsigned char[size_];
|
||||
for (unsigned idx = 0 ; idx < size_ ; idx += 1)
|
||||
ptr_[idx] = vvp_scalar_t(that.value(idx)? BIT4_1:BIT4_0, str0, str1).raw();
|
||||
}
|
||||
}
|
||||
|
||||
const vvp_vector8_t vvp_vector8_t::nil;
|
||||
|
||||
vvp_vector8_t& vvp_vector8_t::operator= (const vvp_vector8_t&that)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ using namespace std;
|
|||
/* Data types */
|
||||
class vvp_scalar_t;
|
||||
|
||||
class vvp_vector2_t;
|
||||
class vvp_vector4_t;
|
||||
class vvp_vector8_t;
|
||||
|
||||
/* Basic netlist types. */
|
||||
class vvp_net_t;
|
||||
class vvp_net_fun_t;
|
||||
|
|
@ -606,9 +610,10 @@ class vvp_vector2_t {
|
|||
vvp_vector2_t();
|
||||
vvp_vector2_t(const vvp_vector2_t&);
|
||||
vvp_vector2_t(const vvp_vector2_t&, unsigned newsize);
|
||||
vvp_vector2_t(const vvp_vector2_t&, unsigned base, unsigned wid);
|
||||
// Make a vvp_vector2_t from a vvp_vector4_t. If there are X
|
||||
// or Z bits, then the result becomes a NaN value.
|
||||
explicit vvp_vector2_t(const vvp_vector4_t&that);
|
||||
vvp_vector2_t(const vvp_vector4_t&that);
|
||||
// Make from a native long and a specified width.
|
||||
vvp_vector2_t(unsigned long val, unsigned wid);
|
||||
// Make with the width, and filled with 1 or 0 bits.
|
||||
|
|
@ -622,11 +627,19 @@ class vvp_vector2_t {
|
|||
vvp_vector2_t&operator >>= (unsigned shift);
|
||||
vvp_vector2_t&operator = (const vvp_vector2_t&);
|
||||
|
||||
// Assign a vec4 to a vec2, using Verilog rules for converting
|
||||
// XZ values to 0.
|
||||
vvp_vector2_t&operator = (const vvp_vector4_t&);
|
||||
|
||||
bool is_NaN() const;
|
||||
bool is_zero() const;
|
||||
unsigned size() const;
|
||||
int value(unsigned idx) const;
|
||||
vvp_bit4_t value4(unsigned idx) const;
|
||||
// Get the vector2 subvector starting at the address
|
||||
vvp_vector2_t subvalue(unsigned idx, unsigned size) const;
|
||||
void set_bit(unsigned idx, int bit);
|
||||
void set_vec(unsigned idx, const vvp_vector2_t&that);
|
||||
// Make the size just big enough to hold the first 1 bit.
|
||||
void trim();
|
||||
// Trim off extra 1 bit since this is representing a negative value.
|
||||
|
|
@ -640,6 +653,7 @@ class vvp_vector2_t {
|
|||
|
||||
private:
|
||||
void copy_from_that_(const vvp_vector2_t&that);
|
||||
void copy_from_that_(const vvp_vector4_t&that);
|
||||
};
|
||||
|
||||
extern bool operator > (const vvp_vector2_t&, const vvp_vector2_t&);
|
||||
|
|
@ -666,12 +680,40 @@ extern double crstring_to_double(const char*str);
|
|||
|
||||
extern ostream& operator<< (ostream&, const vvp_vector2_t&);
|
||||
|
||||
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector2_t&that)
|
||||
{
|
||||
copy_from_that_(that);
|
||||
}
|
||||
|
||||
inline vvp_vector2_t::vvp_vector2_t(const vvp_vector4_t&that)
|
||||
{
|
||||
copy_from_that_(that);
|
||||
}
|
||||
|
||||
inline vvp_vector2_t::~vvp_vector2_t()
|
||||
{
|
||||
delete[] vec_;
|
||||
}
|
||||
|
||||
/* Inline some of the vector2_t methods. */
|
||||
inline unsigned vvp_vector2_t::size() const
|
||||
{
|
||||
return wid_;
|
||||
}
|
||||
|
||||
inline vvp_bit4_t vvp_vector2_t::value4(unsigned idx) const
|
||||
{
|
||||
if (value(idx))
|
||||
return BIT4_1;
|
||||
else
|
||||
return BIT4_0;
|
||||
}
|
||||
|
||||
inline vvp_vector2_t vvp_vector2_t::subvalue(unsigned base, unsigned wid) const
|
||||
{
|
||||
return vvp_vector2_t(*this, base, wid);
|
||||
}
|
||||
|
||||
/*
|
||||
* This class represents a scalar value with strength. These are
|
||||
* heavier then the simple vvp_bit4_t, but more information is
|
||||
|
|
@ -809,6 +851,9 @@ class vvp_vector8_t {
|
|||
explicit vvp_vector8_t(const vvp_vector4_t&that,
|
||||
unsigned str0,
|
||||
unsigned str1);
|
||||
explicit vvp_vector8_t(const vvp_vector2_t&that,
|
||||
unsigned str0,
|
||||
unsigned str1);
|
||||
|
||||
~vvp_vector8_t();
|
||||
|
||||
|
|
@ -1219,7 +1264,9 @@ class vvp_net_fil_t : public vvp_vpi_callback {
|
|||
// the val through the force mask. The force value is the
|
||||
// currently forced value, and the buf is a value that this
|
||||
// method will use to hold a filtered value, if needed. This
|
||||
// method returns a pointer to val or buf.
|
||||
// method returns the replacement value into the "rep"
|
||||
// argument and returns a code indicating whether any changes
|
||||
// were made.
|
||||
template <class T> prop_t filter_mask_(const T&val, const T&force, T&rep, unsigned addr);
|
||||
// This template method is similar to the above, but works for
|
||||
// native types that are not so expensive to edit in place.
|
||||
|
|
|
|||
|
|
@ -600,6 +600,168 @@ vvp_wire_base::~vvp_wire_base()
|
|||
{
|
||||
}
|
||||
|
||||
vvp_wire_vec2::vvp_wire_vec2(unsigned wid)
|
||||
: bits2_(0, wid)
|
||||
{
|
||||
needs_init_ = true;
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_vec2::filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid)
|
||||
{
|
||||
// Special case! the input bit is 0 wid. Interpret this as a
|
||||
// vector of 0 to match the width of the bits2_ vector.
|
||||
// FIXME! This is a hack to work around some buggy gate
|
||||
// implementations! This should be removed!
|
||||
if (base==0 && vwid==0) {
|
||||
vvp_vector2_t tmp (0, bits2_.size());
|
||||
if (bits2_ == tmp && !needs_init_) return STOP;
|
||||
bits2_ = tmp;
|
||||
needs_init_ = false;
|
||||
return filter_mask_(vector2_to_vector4(bits2_, bits2_.size()),
|
||||
vector2_to_vector4(force2_, bits2_.size()), rep, 0);
|
||||
}
|
||||
|
||||
if (vwid != bits2_.size()) {
|
||||
cerr << "Internal error: Input vector expected width="
|
||||
<< bits2_.size() << ", got "
|
||||
<< "bit=" << bit << ", base=" << base << ", vwid=" << vwid
|
||||
<< endl;
|
||||
}
|
||||
assert(bits2_.size() == vwid);
|
||||
|
||||
vvp_vector2_t bit2 = bit;
|
||||
|
||||
// Keep track of the value being driven from this net, even if
|
||||
// it is not ultimately what survives the force filter.
|
||||
if (base==0 && bit2.size()==vwid) {
|
||||
if (bits2_ == bit2 && !needs_init_) return STOP;
|
||||
bits2_ = bit2;
|
||||
} else {
|
||||
bits2_.set_vec(base, bit2);
|
||||
}
|
||||
|
||||
needs_init_ = false;
|
||||
return filter_mask_(vector2_to_vector4(bits2_, bits2_.size()),
|
||||
vector2_to_vector4(force2_, bits2_.size()), rep, 0);
|
||||
}
|
||||
|
||||
vvp_net_fil_t::prop_t vvp_wire_vec2::filter_vec8(const vvp_vector8_t&bit, vvp_vector8_t&rep, unsigned base, unsigned vwid)
|
||||
{
|
||||
assert(bits2_.size() == bit.size());
|
||||
bits2_ = reduce4(bit);
|
||||
return filter_mask_(bit, vvp_vector8_t(force2_,6,6), rep, 0);
|
||||
}
|
||||
|
||||
unsigned vvp_wire_vec2::filter_size() const
|
||||
{
|
||||
return bits2_.size();
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
force_mask(mask);
|
||||
|
||||
if (force2_.size() == 0) {
|
||||
force2_ = val;
|
||||
} else {
|
||||
for (unsigned idx = 0; idx < mask.size() ; idx += 1) {
|
||||
if (mask.value(idx) == 0)
|
||||
continue;
|
||||
|
||||
force2_.set_bit(idx, val.value(idx));
|
||||
}
|
||||
}
|
||||
run_vpi_callbacks();
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::force_fil_real(double val, vvp_vector2_t mask)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::release(vvp_net_ptr_t ptr, bool net_flag)
|
||||
{
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL1, bits2_.size());
|
||||
if (net_flag) {
|
||||
// Wires revert to their unforced value after release.
|
||||
release_mask(mask);
|
||||
needs_init_ = ! (force2_ == bits2_);
|
||||
ptr.ptr()->send_vec4(vector2_to_vector4(bits2_, bits2_.size()), 0);
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
// Variables keep the current value.
|
||||
vvp_vector4_t res (bits2_.size());
|
||||
for (unsigned idx=0; idx<bits2_.size(); idx += 1)
|
||||
res.set_bit(idx,value(idx));
|
||||
release_mask(mask);
|
||||
ptr.ptr()->fun->recv_vec4(ptr, res, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag)
|
||||
{
|
||||
assert(bits2_.size() >= base + wid);
|
||||
|
||||
vvp_vector2_t mask (vvp_vector2_t::FILL0, bits2_.size());
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
mask.set_bit(base+idx, 1);
|
||||
|
||||
if (net_flag) {
|
||||
// Wires revert to their unforced value after release.
|
||||
release_mask(mask);
|
||||
needs_init_ = ! (force2_.subvalue(base,wid) == bits2_.subvalue(base,wid));
|
||||
ptr.ptr()->send_vec4_pv(vector2_to_vector4(bits2_.subvalue(base,wid),wid),
|
||||
base, wid, bits2_.size(), 0);
|
||||
run_vpi_callbacks();
|
||||
} else {
|
||||
// Variables keep the current value.
|
||||
vvp_vector4_t res (wid);
|
||||
for (unsigned idx=0; idx<wid; idx += 1)
|
||||
res.set_bit(idx,value(base+idx));
|
||||
release_mask(mask);
|
||||
ptr.ptr()->fun->recv_vec4_pv(ptr, res, base, wid, bits2_.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vvp_wire_vec2::value_size() const
|
||||
{
|
||||
return bits2_.size();
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec2::filtered_value_(unsigned idx) const
|
||||
{
|
||||
if (test_force_mask(idx))
|
||||
return force2_.value4(idx);
|
||||
else
|
||||
return bits2_.value4(idx);
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_wire_vec2::value(unsigned idx) const
|
||||
{
|
||||
return filtered_value_(idx);
|
||||
}
|
||||
|
||||
vvp_scalar_t vvp_wire_vec2::scalar_value(unsigned idx) const
|
||||
{
|
||||
return vvp_scalar_t(value(idx),6,6);
|
||||
}
|
||||
|
||||
void vvp_wire_vec2::vec4_value(vvp_vector4_t&val) const
|
||||
{
|
||||
val = vector2_to_vector4(bits2_, bits2_.size());
|
||||
if (test_force_mask_is_zero())
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < bits2_.size() ; idx += 1)
|
||||
val.set_bit(idx, filtered_value_(idx));
|
||||
}
|
||||
|
||||
vvp_wire_vec4::vvp_wire_vec4(unsigned wid, vvp_bit4_t init)
|
||||
: bits4_(wid, init)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -274,6 +274,45 @@ class vvp_wire_base : public vvp_net_fil_t, public vvp_signal_value {
|
|||
~vvp_wire_base();
|
||||
};
|
||||
|
||||
class vvp_wire_vec2 : public vvp_wire_base {
|
||||
|
||||
public:
|
||||
vvp_wire_vec2(unsigned wid);
|
||||
|
||||
// The main filter behavior for this class. These methods take
|
||||
// the value that the node is driven to, and applies the force
|
||||
// filters. In wires, this also saves the driven value, so
|
||||
// that when a force is released, we can revert to the driven value.
|
||||
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
prop_t filter_vec8(const vvp_vector8_t&val, vvp_vector8_t&rep,
|
||||
unsigned base, unsigned vwid);
|
||||
|
||||
// Abstract methods from vvp_vpi_callback
|
||||
void get_value(struct t_vpi_value*value);
|
||||
// Abstract methods from vvp_net_fit_t
|
||||
unsigned filter_size() const;
|
||||
void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask);
|
||||
void force_fil_vec8(const vvp_vector8_t&val, vvp_vector2_t mask);
|
||||
void force_fil_real(double val, vvp_vector2_t mask);
|
||||
void release(vvp_net_ptr_t ptr, bool net_flag);
|
||||
void release_pv(vvp_net_ptr_t ptr, unsigned base, unsigned wid, bool net_flag);
|
||||
|
||||
// Implementation of vvp_signal_value methods
|
||||
unsigned value_size() const;
|
||||
vvp_bit4_t value(unsigned idx) const;
|
||||
vvp_scalar_t scalar_value(unsigned idx) const;
|
||||
void vec4_value(vvp_vector4_t&) const;
|
||||
|
||||
private:
|
||||
vvp_bit4_t filtered_value_(unsigned idx) const;
|
||||
|
||||
private:
|
||||
bool needs_init_;
|
||||
vvp_vector2_t bits2_; // The tracked driven value
|
||||
vvp_vector2_t force2_; // the value being forced
|
||||
};
|
||||
|
||||
class vvp_wire_vec4 : public vvp_wire_base {
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -251,15 +251,15 @@ static void do_compile_net(vvp_net_t*node, vvp_array_t array,
|
|||
|
||||
if (vsig == 0) {
|
||||
switch (vpi_type_code) {
|
||||
case vpiIntVar:
|
||||
vsig = new vvp_wire_vec2(wid);
|
||||
break;
|
||||
case vpiLogicVar:
|
||||
vsig = new vvp_wire_vec4(wid,BIT4_Z);
|
||||
break;
|
||||
case -vpiLogicVar:
|
||||
vsig = new vvp_wire_vec8(wid);
|
||||
break;
|
||||
case vpiIntVar:
|
||||
vsig = new vvp_wire_vec4(wid,BIT4_Z);
|
||||
break;
|
||||
}
|
||||
assert(vsig);
|
||||
node->fil = vsig;
|
||||
|
|
|
|||
Loading…
Reference in New Issue