2004-12-11 03:31:25 +01:00
|
|
|
#ifndef __vvp_net_H
|
|
|
|
|
#define __vvp_net_H
|
|
|
|
|
/*
|
2008-01-13 03:22:46 +01:00
|
|
|
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
|
2004-12-11 03:31:25 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
2005-04-03 07:45:51 +02:00
|
|
|
# include "config.h"
|
2005-06-14 02:42:06 +02:00
|
|
|
# include <stddef.h>
|
2008-06-07 01:36:43 +02:00
|
|
|
# include <new>
|
2004-12-11 03:31:25 +01:00
|
|
|
# include <assert.h>
|
|
|
|
|
|
2005-04-13 08:34:20 +02:00
|
|
|
#ifdef HAVE_IOSFWD
|
|
|
|
|
# include <iosfwd>
|
|
|
|
|
#else
|
|
|
|
|
class ostream;
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-07-15 01:34:18 +02:00
|
|
|
using namespace std;
|
2005-04-13 08:34:20 +02:00
|
|
|
|
2005-02-12 07:13:22 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* Data types */
|
2005-03-12 05:27:42 +01:00
|
|
|
class vvp_scalar_t;
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
/* Basic netlist types. */
|
|
|
|
|
class vvp_net_t;
|
|
|
|
|
class vvp_net_fun_t;
|
|
|
|
|
|
|
|
|
|
/* Core net function types. */
|
|
|
|
|
class vvp_fun_concat;
|
|
|
|
|
class vvp_fun_drive;
|
|
|
|
|
class vvp_fun_part;
|
|
|
|
|
|
2005-04-03 07:45:51 +02:00
|
|
|
class vvp_delay_t;
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/*
|
2005-03-12 05:27:42 +01:00
|
|
|
* This is the set of Verilog 4-value bit values. Scalars have this
|
2004-12-11 03:31:25 +01:00
|
|
|
* value along with strength, vectors are a collection of these
|
|
|
|
|
* values. The enumeration has fixed numeric values that can be
|
|
|
|
|
* expressed in 2 real bits, so that some of the internal classes can
|
|
|
|
|
* pack them tightly.
|
|
|
|
|
*/
|
|
|
|
|
enum vvp_bit4_t {
|
|
|
|
|
BIT4_0 = 0,
|
|
|
|
|
BIT4_1 = 1,
|
2008-04-21 06:36:53 +02:00
|
|
|
BIT4_X = 3,
|
|
|
|
|
BIT4_Z = 2
|
2004-12-11 03:31:25 +01:00
|
|
|
};
|
|
|
|
|
|
2008-04-23 20:16:24 +02:00
|
|
|
/* Return an ASCII character that represents the vvp_bit4_t value. */
|
|
|
|
|
inline char vvp_bit4_to_ascii(vvp_bit4_t a) { return "01zx"[a]; }
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c);
|
2005-08-27 04:34:42 +02:00
|
|
|
|
|
|
|
|
/* Return TRUE if the bit is BIT4_X or BIT4_Z. The fast
|
|
|
|
|
implementation here relies on the encoding of vvp_bit4_t values. */
|
|
|
|
|
inline bool bit4_is_xz(vvp_bit4_t a) { return a >= 2; }
|
|
|
|
|
|
2008-04-21 06:36:53 +02:00
|
|
|
/* This function converts BIT4_Z to BIT4_X, but passes other values
|
|
|
|
|
unchanged. This fast implementation relies of the encoding of the
|
|
|
|
|
vvp_bit4_t values. In particular, the BIT4_X==3 and BIT4_Z==2 */
|
|
|
|
|
inline vvp_bit4_t bit4_z2x(vvp_bit4_t a)
|
|
|
|
|
{ return (vvp_bit4_t) ( (int)a | ((int)a >> 1) ); }
|
|
|
|
|
|
2005-01-30 06:06:49 +01:00
|
|
|
/* Some common boolean operators. These implement the Verilog rules
|
2008-04-21 06:36:53 +02:00
|
|
|
for 4-value bit operations. The fast implementations here rely
|
|
|
|
|
on the encoding of vvp_bit4_t values. */
|
|
|
|
|
|
|
|
|
|
// ~BIT4_0 --> BIT4_1
|
|
|
|
|
// ~BIT4_1 --> BIT4_0
|
|
|
|
|
// ~BIT4_X --> BIT4_X
|
|
|
|
|
// ~BIT4_Z --> BIT4_X
|
|
|
|
|
inline vvp_bit4_t operator ~ (vvp_bit4_t a)
|
|
|
|
|
{ return bit4_z2x((vvp_bit4_t) (((int)a) ^ 1)); }
|
|
|
|
|
|
2008-05-26 20:09:33 +02:00
|
|
|
inline vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
|
|
|
|
|
{
|
|
|
|
|
if (a==BIT4_1 || b==BIT4_1)
|
|
|
|
|
return BIT4_1;
|
|
|
|
|
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b)
|
|
|
|
|
{
|
|
|
|
|
if (a==BIT4_0 || b==BIT4_0)
|
|
|
|
|
return BIT4_0;
|
|
|
|
|
return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-03 05:55:13 +01:00
|
|
|
extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b);
|
2005-04-13 08:34:20 +02:00
|
|
|
extern ostream& operator<< (ostream&o, vvp_bit4_t a);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2007-03-02 07:13:22 +01:00
|
|
|
/* Return >0, ==0 or <0 if the from-to transition represents a
|
|
|
|
|
posedge, no edge, or negedge. */
|
|
|
|
|
extern int edge(vvp_bit4_t from, vvp_bit4_t to);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/*
|
2005-07-15 01:34:18 +02:00
|
|
|
* This class represents scalar values collected into vectors. The
|
2004-12-11 03:31:25 +01:00
|
|
|
* vector values can be accessed individually, or treated as a
|
|
|
|
|
* unit. in any case, the elements of the vector are addressed from
|
|
|
|
|
* zero(LSB) to size-1(MSB).
|
|
|
|
|
*
|
|
|
|
|
* No strength values are stored here, if strengths are needed, use a
|
2005-03-12 05:27:42 +01:00
|
|
|
* collection of vvp_scalar_t objects instead.
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
|
|
|
|
class vvp_vector4_t {
|
|
|
|
|
|
2008-04-24 01:50:22 +02:00
|
|
|
friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
public:
|
2005-08-27 04:34:42 +02:00
|
|
|
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
|
|
|
|
|
|
|
|
|
// Construct a vector4 from the subvalue of another vector4.
|
|
|
|
|
explicit vvp_vector4_t(const vvp_vector4_t&that,
|
|
|
|
|
unsigned adr, unsigned wid);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-04-25 06:42:17 +02:00
|
|
|
vvp_vector4_t(const vvp_vector4_t&that);
|
|
|
|
|
vvp_vector4_t& operator= (const vvp_vector4_t&that);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
~vvp_vector4_t();
|
|
|
|
|
|
|
|
|
|
unsigned size() const { return size_; }
|
2005-08-27 04:34:42 +02:00
|
|
|
void resize(unsigned new_size);
|
|
|
|
|
|
|
|
|
|
// Get the bit at the specified address
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_bit4_t value(unsigned idx) const;
|
2005-08-27 04:34:42 +02:00
|
|
|
// Get the vector4 subvector starting at the address
|
|
|
|
|
vvp_vector4_t subvalue(unsigned idx, unsigned size) const;
|
|
|
|
|
// Get the 2-value bits for the subvector. This returns a new
|
|
|
|
|
// array of longs, or a nil pointer if an XZ bit was detected
|
|
|
|
|
// in the array.
|
|
|
|
|
unsigned long*subarray(unsigned idx, unsigned size) const;
|
2008-04-23 22:50:05 +02:00
|
|
|
void setarray(unsigned idx, unsigned size, const unsigned long*val);
|
2005-08-27 04:34:42 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
void set_bit(unsigned idx, vvp_bit4_t val);
|
2005-08-27 04:34:42 +02:00
|
|
|
void set_vec(unsigned idx, const vvp_vector4_t&that);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-01-13 03:22:46 +01:00
|
|
|
// Get the bits from another vector, but keep my size.
|
|
|
|
|
void copy_bits(const vvp_vector4_t&that);
|
|
|
|
|
|
2005-04-25 06:42:17 +02:00
|
|
|
// Test that the vectors are exactly equal
|
|
|
|
|
bool eeq(const vvp_vector4_t&that) const;
|
|
|
|
|
|
2007-12-05 04:15:15 +01:00
|
|
|
// Return true if there is an X or Z anywhere in the vector.
|
|
|
|
|
bool has_xz() const;
|
|
|
|
|
|
2005-06-22 00:48:23 +02:00
|
|
|
// Change all Z bits to X bits.
|
|
|
|
|
void change_z2x();
|
|
|
|
|
|
2005-01-29 18:52:06 +01:00
|
|
|
// Display the value into the buf as a string.
|
|
|
|
|
char*as_string(char*buf, size_t buf_len);
|
|
|
|
|
|
2008-05-24 02:52:43 +02:00
|
|
|
void invert();
|
|
|
|
|
vvp_vector4_t& operator &= (const vvp_vector4_t&that);
|
|
|
|
|
vvp_vector4_t& operator |= (const vvp_vector4_t&that);
|
2007-12-05 04:15:15 +01:00
|
|
|
vvp_vector4_t& operator += (int64_t);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
private:
|
2005-06-20 03:28:14 +02:00
|
|
|
// Number of vvp_bit4_t bits that can be shoved into a word.
|
2008-04-21 01:30:27 +02:00
|
|
|
enum { BITS_PER_WORD = 8*sizeof(unsigned long) };
|
2005-06-22 00:48:23 +02:00
|
|
|
#if SIZEOF_UNSIGNED_LONG == 8
|
2008-04-21 01:30:27 +02:00
|
|
|
enum { WORD_0_ABITS = 0x0000000000000000UL,
|
|
|
|
|
WORD_0_BBITS = 0x0000000000000000UL };
|
|
|
|
|
enum { WORD_1_ABITS = 0xFFFFFFFFFFFFFFFFUL,
|
|
|
|
|
WORD_1_BBITS = 0x0000000000000000UL };
|
|
|
|
|
enum { WORD_X_ABITS = 0xFFFFFFFFFFFFFFFFUL,
|
|
|
|
|
WORD_X_BBITS = 0xFFFFFFFFFFFFFFFFUL };
|
|
|
|
|
enum { WORD_Z_ABITS = 0x0000000000000000UL,
|
|
|
|
|
WORD_Z_BBITS = 0xFFFFFFFFFFFFFFFFUL };
|
2005-06-22 00:48:23 +02:00
|
|
|
#elif SIZEOF_UNSIGNED_LONG == 4
|
2008-04-21 01:30:27 +02:00
|
|
|
enum { WORD_0_ABITS = 0x00000000UL, WORD_0_BBITS = 0x00000000UL };
|
|
|
|
|
enum { WORD_1_ABITS = 0xFFFFFFFFUL, WORD_1_BBITS = 0x00000000UL };
|
|
|
|
|
enum { WORD_X_ABITS = 0xFFFFFFFFUL, WORD_X_BBITS = 0xFFFFFFFFUL };
|
|
|
|
|
enum { WORD_Z_ABITS = 0x00000000UL, WORD_Z_BBITS = 0xFFFFFFFFUL };
|
2005-06-22 00:48:23 +02:00
|
|
|
#else
|
2008-04-21 01:30:27 +02:00
|
|
|
#error "WORD_X_xBITS not defined for this architecture?"
|
2005-06-22 00:48:23 +02:00
|
|
|
#endif
|
2005-06-20 03:28:14 +02:00
|
|
|
|
|
|
|
|
// Initialize and operator= use this private method to copy
|
|
|
|
|
// the data from that object into this object.
|
|
|
|
|
void copy_from_(const vvp_vector4_t&that);
|
2005-06-19 20:42:00 +02:00
|
|
|
|
2008-04-21 01:30:27 +02:00
|
|
|
void allocate_words_(unsigned size, unsigned long inita, unsigned long initb);
|
|
|
|
|
|
|
|
|
|
// Values in the vvp_vector4_t are stored split accross two
|
|
|
|
|
// arrays. For each bit in the vector, there is an abit and a
|
|
|
|
|
// bbit. the encoding of a vvp_vector4_t is:
|
|
|
|
|
//
|
|
|
|
|
// abit bbit
|
|
|
|
|
// ---- ----
|
|
|
|
|
// BIT4_0 0 0 (Note that for BIT4_0 and BIT4_1, the bbit
|
|
|
|
|
// BIT4_1 1 0 value is 0. This makes detecting XZ fast.)
|
|
|
|
|
// BIT4_X 1 1
|
|
|
|
|
// BIT4_Z 0 1
|
2005-08-27 04:34:42 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
unsigned size_;
|
|
|
|
|
union {
|
2008-04-21 01:30:27 +02:00
|
|
|
unsigned long abits_val_;
|
|
|
|
|
unsigned long*abits_ptr_;
|
|
|
|
|
};
|
|
|
|
|
union {
|
|
|
|
|
unsigned long bbits_val_;
|
|
|
|
|
unsigned long*bbits_ptr_;
|
2004-12-11 03:31:25 +01:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2005-06-20 03:28:14 +02:00
|
|
|
inline vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that)
|
|
|
|
|
{
|
|
|
|
|
copy_from_(that);
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-27 04:34:42 +02:00
|
|
|
inline vvp_vector4_t::vvp_vector4_t(unsigned size, vvp_bit4_t val)
|
|
|
|
|
: size_(size)
|
|
|
|
|
{
|
|
|
|
|
/* note: this relies on the bit encoding for the vvp_bit4_t. */
|
2008-04-21 01:30:27 +02:00
|
|
|
const static unsigned long init_atable[4] = {
|
|
|
|
|
WORD_0_ABITS,
|
|
|
|
|
WORD_1_ABITS,
|
2008-04-21 06:36:53 +02:00
|
|
|
WORD_Z_ABITS,
|
|
|
|
|
WORD_X_ABITS };
|
2008-04-21 01:30:27 +02:00
|
|
|
const static unsigned long init_btable[4] = {
|
|
|
|
|
WORD_0_BBITS,
|
|
|
|
|
WORD_1_BBITS,
|
2008-04-21 06:36:53 +02:00
|
|
|
WORD_Z_BBITS,
|
|
|
|
|
WORD_X_BBITS };
|
2008-04-21 01:30:27 +02:00
|
|
|
|
|
|
|
|
allocate_words_(size, init_atable[val], init_btable[val]);
|
2005-08-27 04:34:42 +02:00
|
|
|
}
|
|
|
|
|
|
2005-06-19 20:42:00 +02:00
|
|
|
inline vvp_vector4_t::~vvp_vector4_t()
|
|
|
|
|
{
|
|
|
|
|
if (size_ > BITS_PER_WORD) {
|
2008-04-21 01:30:27 +02:00
|
|
|
delete[] abits_ptr_;
|
|
|
|
|
// bbits_ptr_ actually points half-way into a
|
|
|
|
|
// double-length array started at abits_ptr_
|
2005-06-19 20:42:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-20 03:28:14 +02:00
|
|
|
inline vvp_vector4_t& vvp_vector4_t::operator= (const vvp_vector4_t&that)
|
|
|
|
|
{
|
|
|
|
|
if (this == &that)
|
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
|
|
if (size_ > BITS_PER_WORD)
|
2008-04-21 01:30:27 +02:00
|
|
|
delete[] abits_ptr_;
|
2005-06-20 03:28:14 +02:00
|
|
|
|
|
|
|
|
copy_from_(that);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-19 20:42:00 +02:00
|
|
|
|
|
|
|
|
inline vvp_bit4_t vvp_vector4_t::value(unsigned idx) const
|
|
|
|
|
{
|
|
|
|
|
if (idx >= size_)
|
|
|
|
|
return BIT4_X;
|
|
|
|
|
|
|
|
|
|
unsigned wdx = idx / BITS_PER_WORD;
|
2005-06-26 03:57:22 +02:00
|
|
|
unsigned long off = idx % BITS_PER_WORD;
|
2005-06-19 20:42:00 +02:00
|
|
|
|
2008-04-21 01:30:27 +02:00
|
|
|
unsigned long abits, bbits;
|
2005-06-19 20:42:00 +02:00
|
|
|
if (size_ > BITS_PER_WORD) {
|
2008-04-21 01:30:27 +02:00
|
|
|
abits = abits_ptr_[wdx];
|
|
|
|
|
bbits = bbits_ptr_[wdx];
|
2005-06-19 20:42:00 +02:00
|
|
|
} else {
|
2008-04-21 01:30:27 +02:00
|
|
|
abits = abits_val_;
|
|
|
|
|
bbits = bbits_val_;
|
2005-06-19 20:42:00 +02:00
|
|
|
}
|
|
|
|
|
|
2008-04-21 01:30:27 +02:00
|
|
|
abits >>= off;
|
|
|
|
|
bbits >>= off;
|
|
|
|
|
int tmp = ((bbits&1) << 1) + (abits&1);
|
|
|
|
|
static const vvp_bit4_t bits_bit4_map[4] = {
|
|
|
|
|
BIT4_0, // bbit==0, abit==0
|
|
|
|
|
BIT4_1, // bbit==0, abit==1
|
|
|
|
|
BIT4_Z, // bbit==1, abit==0
|
|
|
|
|
BIT4_X // bbit==1, abit==1
|
|
|
|
|
};
|
2005-06-19 20:42:00 +02:00
|
|
|
|
|
|
|
|
/* Casting is evil, but this cast matches the un-cast done
|
|
|
|
|
when the vvp_bit4_t value is put into the vector. */
|
2008-04-21 01:30:27 +02:00
|
|
|
return bits_bit4_map[tmp];
|
2005-06-19 20:42:00 +02:00
|
|
|
}
|
|
|
|
|
|
2005-08-27 04:34:42 +02:00
|
|
|
inline vvp_vector4_t vvp_vector4_t::subvalue(unsigned adr, unsigned wid) const
|
|
|
|
|
{
|
|
|
|
|
return vvp_vector4_t(*this, adr, wid);
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-20 03:28:14 +02:00
|
|
|
inline void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
|
|
|
|
|
{
|
|
|
|
|
assert(idx < size_);
|
|
|
|
|
|
2005-06-26 03:57:22 +02:00
|
|
|
unsigned long off = idx % BITS_PER_WORD;
|
2008-04-21 01:30:27 +02:00
|
|
|
unsigned long mask = 1UL << off;
|
2005-06-20 03:28:14 +02:00
|
|
|
|
|
|
|
|
if (size_ > BITS_PER_WORD) {
|
2005-06-26 03:57:22 +02:00
|
|
|
unsigned wdx = idx / BITS_PER_WORD;
|
2008-05-26 20:09:33 +02:00
|
|
|
switch (val) {
|
|
|
|
|
case BIT4_0:
|
|
|
|
|
abits_ptr_[wdx] &= ~mask;
|
|
|
|
|
bbits_ptr_[wdx] &= ~mask;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_1:
|
|
|
|
|
abits_ptr_[wdx] |= mask;
|
|
|
|
|
bbits_ptr_[wdx] &= ~mask;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_X:
|
|
|
|
|
abits_ptr_[wdx] |= mask;
|
|
|
|
|
bbits_ptr_[wdx] |= mask;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_Z:
|
|
|
|
|
abits_ptr_[wdx] &= ~mask;
|
|
|
|
|
bbits_ptr_[wdx] |= mask;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-06-20 03:28:14 +02:00
|
|
|
} else {
|
2008-05-26 20:09:33 +02:00
|
|
|
switch (val) {
|
|
|
|
|
case BIT4_0:
|
|
|
|
|
abits_val_ &= ~mask;
|
|
|
|
|
bbits_val_ &= ~mask;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_1:
|
|
|
|
|
abits_val_ |= mask;
|
|
|
|
|
bbits_val_ &= ~mask;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_X:
|
|
|
|
|
abits_val_ |= mask;
|
|
|
|
|
bbits_val_ |= mask;
|
|
|
|
|
break;
|
|
|
|
|
case BIT4_Z:
|
|
|
|
|
abits_val_ &= ~mask;
|
|
|
|
|
bbits_val_ |= mask;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-06-20 03:28:14 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-24 02:52:43 +02:00
|
|
|
inline vvp_vector4_t operator ~ (const vvp_vector4_t&that)
|
|
|
|
|
{
|
|
|
|
|
vvp_vector4_t res = that;
|
|
|
|
|
res.invert();
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-07 05:14:50 +02:00
|
|
|
extern ostream& operator << (ostream&, const vvp_vector4_t&);
|
2005-02-07 23:42:42 +01:00
|
|
|
|
2005-01-22 18:36:15 +01:00
|
|
|
extern vvp_bit4_t compare_gtge(const vvp_vector4_t&a,
|
|
|
|
|
const vvp_vector4_t&b,
|
|
|
|
|
vvp_bit4_t val_if_equal);
|
|
|
|
|
extern vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
|
|
|
|
|
const vvp_vector4_t&b,
|
|
|
|
|
vvp_bit4_t val_if_equal);
|
2005-11-25 18:55:26 +01:00
|
|
|
template <class T> extern T coerce_to_width(const T&that, unsigned width);
|
2005-01-16 05:19:08 +01:00
|
|
|
|
2008-02-09 02:32:57 +01:00
|
|
|
extern vvp_vector4_t double_to_vector4(double val, unsigned wid);
|
|
|
|
|
|
2005-01-28 06:34:25 +01:00
|
|
|
/*
|
|
|
|
|
* These functions extract the value of the vector as a native type,
|
|
|
|
|
* if possible, and return true to indicate success. If the vector has
|
2007-06-12 04:36:58 +02:00
|
|
|
* any X or Z bits, the resulting value will have 0 bits in their
|
|
|
|
|
* place (this follows the rules of Verilog conversions from vector4
|
|
|
|
|
* to real and integers) and the return value becomes false to
|
|
|
|
|
* indicate an error.
|
2005-01-28 06:34:25 +01:00
|
|
|
*/
|
|
|
|
|
extern bool vector4_to_value(const vvp_vector4_t&a, unsigned long&val);
|
2006-12-09 20:06:53 +01:00
|
|
|
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
2005-01-28 06:34:25 +01:00
|
|
|
|
2005-02-04 06:13:02 +01:00
|
|
|
/* vvp_vector2_t
|
|
|
|
|
*/
|
|
|
|
|
class vvp_vector2_t {
|
|
|
|
|
|
|
|
|
|
friend vvp_vector2_t operator + (const vvp_vector2_t&,
|
|
|
|
|
const vvp_vector2_t&);
|
|
|
|
|
friend vvp_vector2_t operator * (const vvp_vector2_t&,
|
|
|
|
|
const vvp_vector2_t&);
|
2005-11-10 14:27:16 +01:00
|
|
|
friend bool operator > (const vvp_vector2_t&, const vvp_vector2_t&);
|
2007-11-01 17:52:20 +01:00
|
|
|
friend bool operator >= (const vvp_vector2_t&, const vvp_vector2_t&);
|
2005-11-10 14:27:16 +01:00
|
|
|
friend bool operator < (const vvp_vector2_t&, const vvp_vector2_t&);
|
|
|
|
|
friend bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
|
2007-11-01 17:52:20 +01:00
|
|
|
friend bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
|
2005-02-04 06:13:02 +01:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_vector2_t();
|
|
|
|
|
vvp_vector2_t(const vvp_vector2_t&);
|
2005-11-10 14:27:16 +01:00
|
|
|
vvp_vector2_t(const vvp_vector2_t&, unsigned newsize);
|
|
|
|
|
// Make a vvp_vector2_t from a vvp_vector4_t. If there are X
|
|
|
|
|
// or Z bits, then the result becomes a NaN value.
|
2005-02-04 06:13:02 +01:00
|
|
|
explicit vvp_vector2_t(const vvp_vector4_t&that);
|
2005-11-10 14:27:16 +01:00
|
|
|
// Make from a native long and a specified width.
|
2005-02-04 06:13:02 +01:00
|
|
|
vvp_vector2_t(unsigned long val, unsigned wid);
|
2005-11-26 18:16:05 +01:00
|
|
|
// Make with the width, and filled with 1 or 0 bits.
|
|
|
|
|
enum fill_t {FILL0, FILL1};
|
|
|
|
|
vvp_vector2_t(fill_t fill, unsigned wid);
|
2005-02-04 06:13:02 +01:00
|
|
|
~vvp_vector2_t();
|
|
|
|
|
|
2005-11-10 14:27:16 +01:00
|
|
|
vvp_vector2_t&operator += (const vvp_vector2_t&that);
|
|
|
|
|
vvp_vector2_t&operator -= (const vvp_vector2_t&that);
|
|
|
|
|
vvp_vector2_t&operator <<= (unsigned shift);
|
|
|
|
|
vvp_vector2_t&operator >>= (unsigned shift);
|
|
|
|
|
vvp_vector2_t&operator = (const vvp_vector2_t&);
|
2005-02-04 06:13:02 +01:00
|
|
|
|
|
|
|
|
bool is_NaN() const;
|
2008-04-10 03:56:42 +02:00
|
|
|
bool is_zero() const;
|
2005-02-04 06:13:02 +01:00
|
|
|
unsigned size() const;
|
|
|
|
|
int value(unsigned idx) const;
|
2005-11-26 18:16:05 +01:00
|
|
|
void set_bit(unsigned idx, int bit);
|
2008-02-05 04:43:50 +01:00
|
|
|
// Make the size just big enough to hold the first 1 bit.
|
|
|
|
|
void trim();
|
2005-02-04 06:13:02 +01:00
|
|
|
|
|
|
|
|
private:
|
2005-11-10 14:27:16 +01:00
|
|
|
enum { BITS_PER_WORD = 8 * sizeof(unsigned long) };
|
2005-02-04 06:13:02 +01:00
|
|
|
unsigned long*vec_;
|
|
|
|
|
unsigned wid_;
|
2005-11-10 14:27:16 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void copy_from_that_(const vvp_vector2_t&that);
|
2005-02-04 06:13:02 +01:00
|
|
|
};
|
|
|
|
|
|
2005-11-10 14:27:16 +01:00
|
|
|
extern bool operator > (const vvp_vector2_t&, const vvp_vector2_t&);
|
2007-11-01 17:52:20 +01:00
|
|
|
extern bool operator >= (const vvp_vector2_t&, const vvp_vector2_t&);
|
|
|
|
|
extern bool operator < (const vvp_vector2_t&, const vvp_vector2_t&);
|
2005-11-10 14:27:16 +01:00
|
|
|
extern bool operator <= (const vvp_vector2_t&, const vvp_vector2_t&);
|
2007-11-01 17:52:20 +01:00
|
|
|
extern bool operator == (const vvp_vector2_t&, const vvp_vector2_t&);
|
2005-02-04 06:13:02 +01:00
|
|
|
extern vvp_vector2_t operator + (const vvp_vector2_t&, const vvp_vector2_t&);
|
|
|
|
|
extern vvp_vector2_t operator * (const vvp_vector2_t&, const vvp_vector2_t&);
|
2005-11-10 14:27:16 +01:00
|
|
|
extern vvp_vector2_t operator / (const vvp_vector2_t&, const vvp_vector2_t&);
|
|
|
|
|
extern vvp_vector2_t operator % (const vvp_vector2_t&, const vvp_vector2_t&);
|
2008-02-06 04:09:30 +01:00
|
|
|
|
|
|
|
|
vvp_vector2_t pow(const vvp_vector2_t&, vvp_vector2_t&);
|
2005-02-04 06:13:02 +01:00
|
|
|
extern vvp_vector4_t vector2_to_vector4(const vvp_vector2_t&, unsigned wid);
|
2006-03-08 06:29:42 +01:00
|
|
|
/* A c4string is of the form C4<...> where ... are bits. */
|
|
|
|
|
extern vvp_vector4_t c4string_to_vector4(const char*str);
|
|
|
|
|
|
2005-11-10 14:27:16 +01:00
|
|
|
extern ostream& operator<< (ostream&, const vvp_vector2_t&);
|
2005-02-04 06:13:02 +01:00
|
|
|
|
2008-05-23 03:19:40 +02:00
|
|
|
/* Inline some of the vector2_t methods. */
|
|
|
|
|
inline unsigned vvp_vector2_t::size() const
|
|
|
|
|
{
|
|
|
|
|
return wid_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/*
|
2008-01-29 21:19:59 +01:00
|
|
|
* This class represents a scalar value with strength. These are
|
2004-12-11 03:31:25 +01:00
|
|
|
* heavier then the simple vvp_bit4_t, but more information is
|
|
|
|
|
* carried by that weight.
|
|
|
|
|
*
|
|
|
|
|
* The strength values are as defined here:
|
|
|
|
|
* HiZ - 0
|
|
|
|
|
* Small - 1
|
|
|
|
|
* Medium - 2
|
|
|
|
|
* Weak - 3
|
|
|
|
|
* Large - 4
|
|
|
|
|
* Pull - 5
|
|
|
|
|
* Strong - 6
|
|
|
|
|
* Supply - 7
|
2005-03-12 05:27:42 +01:00
|
|
|
*
|
|
|
|
|
* There are two strengths for a value: strength0 and strength1. If
|
|
|
|
|
* the value is Z, then strength0 is the strength of the 0-value, and
|
|
|
|
|
* strength of the 1-value. If the value is 0 or 1, then the strengths
|
|
|
|
|
* are the range for that value.
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
2005-03-12 05:27:42 +01:00
|
|
|
class vvp_scalar_t {
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-03-12 05:27:42 +01:00
|
|
|
friend vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// Make a HiZ value.
|
2005-03-12 05:27:42 +01:00
|
|
|
explicit vvp_scalar_t();
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
// Make an unambiguous value.
|
2005-03-12 05:27:42 +01:00
|
|
|
explicit vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
// Get the vvp_bit4_t version of the value
|
|
|
|
|
vvp_bit4_t value() const;
|
2005-03-12 05:27:42 +01:00
|
|
|
unsigned strength0() const;
|
|
|
|
|
unsigned strength1() const;
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-06-15 02:47:15 +02:00
|
|
|
bool eeq(vvp_scalar_t that) const { return value_ == that.value_; }
|
2005-02-13 06:26:30 +01:00
|
|
|
bool is_hiz() const { return value_ == 0; }
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
private:
|
|
|
|
|
unsigned char value_;
|
|
|
|
|
};
|
|
|
|
|
|
2005-06-22 00:48:23 +02:00
|
|
|
inline vvp_scalar_t::vvp_scalar_t()
|
|
|
|
|
{
|
|
|
|
|
value_ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
inline vvp_scalar_t::vvp_scalar_t(vvp_bit4_t val, unsigned str0, unsigned str1)
|
2005-06-22 00:48:23 +02:00
|
|
|
{
|
2008-06-12 21:08:02 +02:00
|
|
|
assert(str0 <= 7);
|
|
|
|
|
assert(str1 <= 7);
|
2005-06-22 00:48:23 +02:00
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
if (str0 == 0 && str1 == 0) {
|
2005-06-22 00:48:23 +02:00
|
|
|
value_ = 0x00;
|
|
|
|
|
} else switch (val) {
|
|
|
|
|
case BIT4_0:
|
2008-06-12 21:08:02 +02:00
|
|
|
value_ = str0 | (str0<<4);
|
2005-06-22 00:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case BIT4_1:
|
2008-06-12 21:08:02 +02:00
|
|
|
value_ = str1 | (str1<<4) | 0x88;
|
2005-06-22 00:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case BIT4_X:
|
2008-06-12 21:08:02 +02:00
|
|
|
value_ = str0 | (str1<<4) | 0x80;
|
2005-06-22 00:48:23 +02:00
|
|
|
break;
|
|
|
|
|
case BIT4_Z:
|
|
|
|
|
value_ = 0x00;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
inline vvp_bit4_t vvp_scalar_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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-03-12 05:27:42 +01:00
|
|
|
extern vvp_scalar_t resolve(vvp_scalar_t a, vvp_scalar_t b);
|
2005-04-13 08:34:20 +02:00
|
|
|
extern ostream& operator<< (ostream&, vvp_scalar_t);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This class is a way to carry vectors of strength modeled
|
|
|
|
|
* 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
|
2005-03-12 05:27:42 +01:00
|
|
|
* number of distinct values span the vvp_scalar_t.
|
2004-12-31 07:00:06 +01:00
|
|
|
*
|
2008-01-29 21:19:59 +01:00
|
|
|
* A vvp_vector8_t object can be created from a vvp_vector4_t and a
|
2004-12-31 07:00:06 +01:00
|
|
|
* strength value. The vvp_vector8_t bits have the values of the input
|
2005-06-12 02:44:49 +02:00
|
|
|
* vector, all with the strength specified. If no strength is
|
|
|
|
|
* specified, then the conversion from bit4 to a scalar will use the
|
|
|
|
|
* Verilog convention default of strong (6).
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
|
|
|
|
class vvp_vector8_t {
|
|
|
|
|
|
2008-06-03 17:52:42 +02:00
|
|
|
friend vvp_vector8_t part_expand(const vvp_vector8_t&, unsigned, unsigned);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
public:
|
|
|
|
|
explicit vvp_vector8_t(unsigned size =0);
|
2008-06-12 21:08:02 +02:00
|
|
|
// Make a vvp_vector8_t from a vector4 and a specified
|
|
|
|
|
// strength.
|
2005-02-07 23:42:42 +01:00
|
|
|
explicit vvp_vector8_t(const vvp_vector4_t&that,
|
|
|
|
|
unsigned str0,
|
|
|
|
|
unsigned str1);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
~vvp_vector8_t();
|
|
|
|
|
|
|
|
|
|
unsigned size() const { return size_; }
|
2005-03-12 05:27:42 +01:00
|
|
|
vvp_scalar_t value(unsigned idx) const;
|
2008-06-03 20:16:25 +02:00
|
|
|
vvp_vector8_t subvalue(unsigned adr, unsigned width) const;
|
2005-03-12 05:27:42 +01:00
|
|
|
void set_bit(unsigned idx, vvp_scalar_t val);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-06-15 02:47:15 +02:00
|
|
|
// Test that the vectors are exactly equal
|
|
|
|
|
bool eeq(const vvp_vector8_t&that) const;
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
vvp_vector8_t(const vvp_vector8_t&that);
|
|
|
|
|
vvp_vector8_t& operator= (const vvp_vector8_t&that);
|
|
|
|
|
|
|
|
|
|
private:
|
2008-06-07 01:36:43 +02:00
|
|
|
// This is the number of vvp_scalar_t objects we can keep in
|
|
|
|
|
// the val_ buffer. If the vector8 is bigger then this, then
|
|
|
|
|
// resort to allocations to get a larger buffer.
|
|
|
|
|
enum { PTR_THRESH = 8 };
|
2004-12-11 03:31:25 +01:00
|
|
|
unsigned size_;
|
2008-06-07 01:36:43 +02:00
|
|
|
union {
|
|
|
|
|
vvp_scalar_t*ptr_;
|
|
|
|
|
char val_[PTR_THRESH * sizeof(vvp_scalar_t)];
|
|
|
|
|
};
|
2004-12-11 03:31:25 +01:00
|
|
|
};
|
|
|
|
|
|
2005-06-12 17:13:37 +02:00
|
|
|
/* Resolve uses the default Verilog resolver algorithm to resolve
|
|
|
|
|
two drive vectors to a single output. */
|
2008-06-12 21:08:02 +02:00
|
|
|
inline 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;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-12 17:13:37 +02:00
|
|
|
/* This function implements the strength reduction implied by
|
|
|
|
|
Verilog standard resistive devices. */
|
|
|
|
|
extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a);
|
|
|
|
|
/* The reduce4 function converts a vector8 to a vector4, losing
|
|
|
|
|
strength information in the process. */
|
2004-12-31 07:00:06 +01:00
|
|
|
extern vvp_vector4_t reduce4(const vvp_vector8_t&that);
|
2008-06-03 17:52:42 +02:00
|
|
|
extern vvp_vector8_t part_expand(const vvp_vector8_t&a, unsigned wid, unsigned off);
|
2005-06-12 17:13:37 +02:00
|
|
|
/* Print a vector8 value to a stream. */
|
2005-04-13 08:34:20 +02:00
|
|
|
extern ostream& operator<< (ostream&, const vvp_vector8_t&);
|
2004-12-31 07:00:06 +01:00
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
inline vvp_vector8_t::vvp_vector8_t(unsigned size)
|
|
|
|
|
: size_(size)
|
|
|
|
|
{
|
2008-06-07 01:36:43 +02:00
|
|
|
if (size_ <= PTR_THRESH) {
|
|
|
|
|
new (val_) vvp_scalar_t[PTR_THRESH];
|
|
|
|
|
} else {
|
|
|
|
|
ptr_ = new vvp_scalar_t[size_];
|
2008-06-12 21:08:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-22 20:30:12 +02:00
|
|
|
inline vvp_vector8_t::~vvp_vector8_t()
|
|
|
|
|
{
|
2008-06-07 01:36:43 +02:00
|
|
|
if (size_ > PTR_THRESH)
|
|
|
|
|
delete[]ptr_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline vvp_scalar_t vvp_vector8_t::value(unsigned idx) const
|
|
|
|
|
{
|
|
|
|
|
assert(idx < size_);
|
|
|
|
|
if (size_ <= PTR_THRESH)
|
|
|
|
|
return reinterpret_cast<const vvp_scalar_t*>(val_) [idx];
|
|
|
|
|
else
|
|
|
|
|
return ptr_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void vvp_vector8_t::set_bit(unsigned idx, vvp_scalar_t val)
|
|
|
|
|
{
|
|
|
|
|
assert(idx < size_);
|
|
|
|
|
if (size_ <= PTR_THRESH)
|
|
|
|
|
reinterpret_cast<vvp_scalar_t*>(val_) [idx] = val;
|
|
|
|
|
else
|
|
|
|
|
ptr_[idx] = val;
|
2005-06-22 20:30:12 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
// Exactly-equal for vvp_vector8_t is common and should be as tight
|
|
|
|
|
// as possible.
|
|
|
|
|
inline bool vvp_vector8_t::eeq(const vvp_vector8_t&that) const
|
|
|
|
|
{
|
|
|
|
|
if (size_ != that.size_)
|
|
|
|
|
return false;
|
|
|
|
|
if (size_ == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
2008-06-07 01:36:43 +02:00
|
|
|
if (size_ <= PTR_THRESH)
|
|
|
|
|
return 0 == memcmp(val_, that.val_, sizeof(val_));
|
|
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
|
2008-06-07 01:36:43 +02:00
|
|
|
if (! ptr_[idx] .eeq( that.ptr_[idx] ))
|
2008-06-12 21:08:02 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
* the port() method returns a 0-3 value that selects the input within
|
|
|
|
|
* the vvp_net_t. Use this pointer to point only to the inputs of
|
|
|
|
|
* vvp_net_t objects. To point to vvp_net_t objects as a whole, use
|
|
|
|
|
* vvp_net_t* pointers.
|
2008-06-01 06:45:55 +02:00
|
|
|
*
|
2004-12-11 03:31:25 +01:00
|
|
|
* Alert! Ugly details. Protective clothing recommended!
|
|
|
|
|
* The vvp_net_ptr_t encodes the bits of a C pointer, and two bits of
|
2008-01-29 21:19:59 +01:00
|
|
|
* port identifier into an unsigned long. This works only if vvp_net_t*
|
|
|
|
|
* values are always aligned on 4-byte boundaries.
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
2008-06-01 06:45:55 +02:00
|
|
|
template <class T> class vvp_sub_pointer_t {
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
public:
|
|
|
|
|
vvp_sub_pointer_t() : bits_(0) { }
|
|
|
|
|
|
|
|
|
|
vvp_sub_pointer_t(T*ptr, unsigned port)
|
|
|
|
|
{
|
|
|
|
|
bits_ = reinterpret_cast<unsigned long> (ptr);
|
|
|
|
|
assert( (bits_ & 3) == 0 );
|
|
|
|
|
assert( (port & ~3) == 0 );
|
|
|
|
|
bits_ |= port;
|
|
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
~vvp_sub_pointer_t() { }
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
T* ptr()
|
|
|
|
|
{ return reinterpret_cast<T*> (bits_ & ~3UL); }
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
const T* ptr() const
|
|
|
|
|
{ return reinterpret_cast<const T*> (bits_ & ~3UL); }
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
unsigned port() const { return bits_ & 3; }
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
bool nil() const { return bits_ == 0; }
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
bool operator == (vvp_sub_pointer_t that) const { return bits_ == that.bits_; }
|
|
|
|
|
bool operator != (vvp_sub_pointer_t that) const { return bits_ != that.bits_; }
|
2006-08-04 06:37:37 +02:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
private:
|
|
|
|
|
unsigned long bits_;
|
|
|
|
|
};
|
2006-08-04 06:37:37 +02:00
|
|
|
|
2008-06-01 06:45:55 +02:00
|
|
|
typedef vvp_sub_pointer_t<vvp_net_t> vvp_net_ptr_t;
|
2008-06-03 17:52:42 +02:00
|
|
|
template <class T> ostream& operator << (ostream&out, vvp_sub_pointer_t<T> val)
|
|
|
|
|
{ out << val.ptr() << "[" << val.port() << "]"; return out; }
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is the basic unit of netlist connectivity. It is a fan-in of
|
|
|
|
|
* up to 4 inputs, and output pointer, and a pointer to the node's
|
|
|
|
|
* functionality.
|
|
|
|
|
*
|
|
|
|
|
* A net output that is non-nil points to the input of one of its
|
|
|
|
|
* destination nets. If there are multiple destinations, then the
|
|
|
|
|
* referenced input port points to the next input. For example:
|
|
|
|
|
*
|
|
|
|
|
* +--+--+--+--+---+
|
|
|
|
|
* | | | | | . | Output from this vvp_net_t points to...
|
|
|
|
|
* +--+--+--+--+-|-+
|
|
|
|
|
* |
|
|
|
|
|
* /
|
|
|
|
|
* /
|
|
|
|
|
* /
|
|
|
|
|
* |
|
|
|
|
|
* v
|
|
|
|
|
* +--+--+--+--+---+
|
|
|
|
|
* | | | | | . | ... the fourth input of this vvp_net_t, and...
|
|
|
|
|
* +--+--+--+--+-|-+
|
|
|
|
|
* | |
|
|
|
|
|
* / .
|
|
|
|
|
* / .
|
|
|
|
|
* | .
|
|
|
|
|
* v
|
|
|
|
|
* +--+--+--+--+---+
|
|
|
|
|
* | | | | | . | ... the third input of this vvp_net_t.
|
|
|
|
|
* +--+--+--+--+-|-+
|
|
|
|
|
*
|
|
|
|
|
* Thus, the fan-in of a vvp_net_t node is limited to 4 inputs, but
|
|
|
|
|
* the fan-out is unlimited.
|
|
|
|
|
*
|
|
|
|
|
* The vvp_send_*() functions take as input a vvp_net_ptr_t and follow
|
|
|
|
|
* all the fan-out chain, delivering the specified value.
|
|
|
|
|
*/
|
|
|
|
|
struct vvp_net_t {
|
|
|
|
|
vvp_net_ptr_t port[4];
|
|
|
|
|
vvp_net_ptr_t out;
|
|
|
|
|
vvp_net_fun_t*fun;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Instances of this class represent the functionality of a
|
|
|
|
|
* node. vvp_net_t objects hold pointers to the vvp_net_fun_t
|
|
|
|
|
* associated with it. Objects of this type take inputs that arrive at
|
|
|
|
|
* a port and perform some sort of action in response.
|
|
|
|
|
*
|
|
|
|
|
* Whenever a bit is delivered to a vvp_net_t object, the associated
|
|
|
|
|
* vvp_net_fun_t::recv_*() method is invoked with the port pointer and
|
|
|
|
|
* the bit value. The port pointer is used to figure out which exact
|
|
|
|
|
* input receives the bit.
|
|
|
|
|
*
|
|
|
|
|
* In this context, a "bit" is the thing that arrives at a single
|
|
|
|
|
* input. The bit may be a single data bit, a bit vector, various
|
|
|
|
|
* sorts of numbers or aggregate objects.
|
2005-04-09 07:30:38 +02:00
|
|
|
*
|
|
|
|
|
* recv_vec4 is the most common way for a datum to arrive at a
|
|
|
|
|
* port. The value is a vvp_vector4_t.
|
|
|
|
|
*
|
|
|
|
|
* Most nodes do not care about the specific strengths of bits, so the
|
|
|
|
|
* default behavior for recv_vec8 is to reduce the operand to a
|
|
|
|
|
* vvp_vector4_t and pass it on to the recv_vec4 method.
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
|
|
|
|
class vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_net_fun_t();
|
|
|
|
|
virtual ~vvp_net_fun_t();
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2008-06-12 21:08:02 +02:00
|
|
|
virtual void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
2004-12-11 03:31:25 +01:00
|
|
|
virtual void recv_real(vvp_net_ptr_t port, double bit);
|
|
|
|
|
virtual void recv_long(vvp_net_ptr_t port, long bit);
|
|
|
|
|
|
2005-01-09 21:11:15 +01:00
|
|
|
// Part select variants of above
|
2005-06-22 20:30:12 +02:00
|
|
|
virtual void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
2005-01-09 21:11:15 +01:00
|
|
|
unsigned base, unsigned wid, unsigned vwid);
|
2008-03-12 00:04:00 +01:00
|
|
|
virtual void recv_long_pv(vvp_net_ptr_t port, long bit,
|
|
|
|
|
unsigned base, unsigned wid);
|
2005-01-09 21:11:15 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
private: // not implemented
|
|
|
|
|
vvp_net_fun_t(const vvp_net_fun_t&);
|
|
|
|
|
vvp_net_fun_t& operator= (const vvp_net_fun_t&);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* **** Some core net functions **** */
|
|
|
|
|
|
|
|
|
|
/* vvp_fun_concat
|
|
|
|
|
* This node function creates vectors (vvp_vector4_t) from the
|
2005-01-09 21:11:15 +01:00
|
|
|
* concatenation of the inputs. The inputs (4) may be vector or
|
|
|
|
|
* vector8 objects, but they are reduced to vector4 values and
|
|
|
|
|
* strength information lost.
|
2004-12-30 00:45:13 +01:00
|
|
|
*
|
|
|
|
|
* The expected widths of the input vectors must be given up front so
|
|
|
|
|
* that the positions in the output vector (and also the size of the
|
|
|
|
|
* output vector) can be worked out. The input vectors must match the
|
|
|
|
|
* expected width.
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
|
|
|
|
class vvp_fun_concat : public vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
2004-12-30 00:45:13 +01:00
|
|
|
vvp_fun_concat(unsigned w0, unsigned w1,
|
|
|
|
|
unsigned w2, unsigned w3);
|
|
|
|
|
~vvp_fun_concat();
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2004-12-30 00:45:13 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned wid_[4];
|
|
|
|
|
vvp_vector4_t val_;
|
2004-12-11 03:31:25 +01:00
|
|
|
};
|
|
|
|
|
|
2005-02-07 23:42:42 +01:00
|
|
|
/* vvp_fun_repeat
|
|
|
|
|
* This node function create vectors by repeating the input. The width
|
|
|
|
|
* is the width of the output vector, and the repeat is the number of
|
|
|
|
|
* times to repeat the input. The width of the input vector is
|
|
|
|
|
* implicit from these values.
|
|
|
|
|
*/
|
|
|
|
|
class vvp_fun_repeat : public vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_fun_repeat(unsigned width, unsigned repeat);
|
|
|
|
|
~vvp_fun_repeat();
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2005-02-07 23:42:42 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned wid_;
|
|
|
|
|
unsigned rep_;
|
|
|
|
|
};
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* vvp_fun_drive
|
|
|
|
|
* This node function takes an input vvp_vector4_t as input, and
|
|
|
|
|
* repeats that value as a vvp_vector8_t with all the bits given the
|
2008-01-29 21:19:59 +01:00
|
|
|
* strength of the drive. This is the way vvp_scalar8_t objects are
|
|
|
|
|
* created. Input 0 is the value to be driven (vvp_vector4_t) and
|
2004-12-11 03:31:25 +01:00
|
|
|
* inputs 1 and two are the strength0 and strength1 values to use. The
|
|
|
|
|
* strengths may be taken as constant values, or adjusted as longs
|
|
|
|
|
* from the network.
|
|
|
|
|
*
|
|
|
|
|
* This functor only propagates vvp_vector8_t values.
|
|
|
|
|
*/
|
|
|
|
|
class vvp_fun_drive : public vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_fun_drive(vvp_bit4_t init, unsigned str0 =6, unsigned str1 =6);
|
2005-04-13 08:34:20 +02:00
|
|
|
~vvp_fun_drive();
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2005-04-13 08:34:20 +02:00
|
|
|
//void recv_long(vvp_net_ptr_t port, long bit);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-04-13 08:34:20 +02:00
|
|
|
private:
|
|
|
|
|
unsigned char drive0_;
|
|
|
|
|
unsigned char drive1_;
|
2004-12-11 03:31:25 +01:00
|
|
|
};
|
|
|
|
|
|
2005-05-24 03:43:27 +02:00
|
|
|
/*
|
|
|
|
|
* EXTEND functors expand an input vector to the desired output
|
|
|
|
|
* width. The extend_signed functor sign extends the input. If the
|
|
|
|
|
* input is already wider then the desired output, then it is passed
|
|
|
|
|
* unmodified.
|
|
|
|
|
*/
|
|
|
|
|
class vvp_fun_extend_signed : public vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit vvp_fun_extend_signed(unsigned wid);
|
|
|
|
|
~vvp_fun_extend_signed();
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2005-05-24 03:43:27 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
unsigned width_;
|
|
|
|
|
};
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
/* vvp_fun_signal
|
|
|
|
|
* This node is the place holder in a vvp network for signals,
|
2005-01-01 03:12:34 +01:00
|
|
|
* including nets of various sort. The output from a signal follows
|
|
|
|
|
* the type of its port-0 input. If vvp_vector4_t values come in
|
|
|
|
|
* through port-0, then vvp_vector4_t values are propagated. If
|
|
|
|
|
* vvp_vector8_t values come in through port-0, then vvp_vector8_t
|
2008-01-29 21:19:59 +01:00
|
|
|
* values are propagated. Thus, this node is slightly polymorphic.
|
2004-12-11 03:31:25 +01:00
|
|
|
*
|
|
|
|
|
* If the signal is a net (i.e. a wire or tri) then this node will
|
|
|
|
|
* have an input that is the data source. The data source will connect
|
2008-01-29 21:19:59 +01:00
|
|
|
* through port-0.
|
2004-12-11 03:31:25 +01:00
|
|
|
*
|
|
|
|
|
* If the signal is a reg, then there will be no netlist input, the
|
|
|
|
|
* values will be written by behavioral statements. The %set and
|
2008-01-29 21:19:59 +01:00
|
|
|
* %assign statements will write through port-0.
|
2004-12-11 03:31:25 +01:00
|
|
|
*
|
|
|
|
|
* In any case, behavioral code is able to read the value that this
|
2004-12-15 18:16:08 +01:00
|
|
|
* node last propagated, by using the value() method. That is important
|
2004-12-11 03:31:25 +01:00
|
|
|
* functionality of this node.
|
|
|
|
|
*
|
|
|
|
|
* Continuous assignments are made through port-1. When a value is
|
|
|
|
|
* written here, continuous assign mode is activated, and input
|
|
|
|
|
* through port-0 is ignored until continuous assign mode is turned
|
|
|
|
|
* off again. Writing into this port can be done in behavioral code
|
|
|
|
|
* using the %cassign/v instruction, or can be done by the network by
|
|
|
|
|
* hooking the output of a vvp_net_t to this port.
|
2004-12-15 18:16:08 +01:00
|
|
|
*
|
|
|
|
|
* Force assignments are made through port-2. When a value is written
|
|
|
|
|
* here, force mode is activated. In force mode, port-0 data (or
|
|
|
|
|
* port-1 data if in continuous assign mode) is tracked but not
|
|
|
|
|
* propagated. The force value is propagated and is what is readable
|
|
|
|
|
* through the value method.
|
|
|
|
|
*
|
|
|
|
|
* Port-3 is a command port, intended for use by procedural
|
|
|
|
|
* instructions. The client must write long values to this port to
|
|
|
|
|
* invoke the command of interest. The command values are:
|
|
|
|
|
*
|
|
|
|
|
* 1 -- deassign
|
|
|
|
|
* The deassign command takes the node out of continuous
|
|
|
|
|
* assignment mode. The output value is unchanged, and force
|
|
|
|
|
* mode, if active, remains in effect.
|
|
|
|
|
*
|
|
|
|
|
* 2 -- release/net
|
|
|
|
|
* The release/net command takes the node out of force mode,
|
|
|
|
|
* and propagates the tracked port-0 value to the signal
|
|
|
|
|
* output. This acts like a release of a net signal.
|
|
|
|
|
*
|
|
|
|
|
* 3 -- release/reg
|
|
|
|
|
* The release/reg command is similar to the release/net
|
|
|
|
|
* command, but the port-0 value is not propagated. Changes
|
2008-01-29 21:19:59 +01:00
|
|
|
* to port-0 (or port-1 if continuous assign is active) will
|
2004-12-15 18:16:08 +01:00
|
|
|
* propagate starting at the next input change.
|
2004-12-11 03:31:25 +01:00
|
|
|
*/
|
2005-07-06 06:29:25 +02:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
/*
|
|
|
|
|
* Things derived from vvp_vpi_callback may also be array'ed, so it
|
|
|
|
|
* includes some members that arrays use.
|
|
|
|
|
*/
|
2005-07-06 06:29:25 +02:00
|
|
|
class vvp_vpi_callback {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_vpi_callback();
|
|
|
|
|
virtual ~vvp_vpi_callback();
|
|
|
|
|
|
2008-05-21 03:30:56 +02:00
|
|
|
virtual void run_vpi_callbacks();
|
2005-07-06 06:29:25 +02:00
|
|
|
void add_vpi_callback(struct __vpiCallback*);
|
|
|
|
|
|
|
|
|
|
virtual void get_value(struct t_vpi_value*value) =0;
|
|
|
|
|
|
2008-05-21 03:30:56 +02:00
|
|
|
private:
|
|
|
|
|
struct __vpiCallback*vpi_callbacks_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class vvp_vpi_callback_wordable : public vvp_vpi_callback {
|
|
|
|
|
public:
|
|
|
|
|
vvp_vpi_callback_wordable();
|
|
|
|
|
~vvp_vpi_callback_wordable();
|
|
|
|
|
|
|
|
|
|
void run_vpi_callbacks();
|
2007-01-16 06:44:14 +01:00
|
|
|
void attach_as_word(class __vpiArray* arr, unsigned long addr);
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
private:
|
2007-01-16 06:44:14 +01:00
|
|
|
class __vpiArray* array_;
|
|
|
|
|
unsigned long array_word_;
|
2005-07-06 06:29:25 +02:00
|
|
|
};
|
|
|
|
|
|
2008-05-21 03:30:56 +02:00
|
|
|
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback_wordable {
|
2005-07-06 06:29:25 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_fun_signal_base();
|
|
|
|
|
void recv_long(vvp_net_ptr_t port, long bit);
|
2008-03-12 00:04:00 +01:00
|
|
|
void recv_long_pv(vvp_net_ptr_t port, long bit,
|
|
|
|
|
unsigned base, unsigned wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
/* The %force/link instruction needs a place to write the
|
|
|
|
|
source node of the force, so that subsequent %force and
|
|
|
|
|
%release instructions can undo the link as needed. */
|
|
|
|
|
struct vvp_net_t*force_link;
|
2007-02-05 02:08:10 +01:00
|
|
|
struct vvp_net_t*cassign_link;
|
2005-07-06 06:29:25 +02:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
// This is true until at least one propagation happens.
|
|
|
|
|
bool needs_init_;
|
|
|
|
|
bool continuous_assign_active_;
|
2005-11-26 18:16:05 +01:00
|
|
|
vvp_vector2_t force_mask_;
|
2008-04-10 03:56:42 +02:00
|
|
|
vvp_vector2_t assign_mask_;
|
2005-07-06 06:29:25 +02:00
|
|
|
|
|
|
|
|
void deassign();
|
2008-04-10 03:56:42 +02:00
|
|
|
void deassign_pv(unsigned base, unsigned wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
virtual void release(vvp_net_ptr_t ptr, bool net) =0;
|
2008-03-12 00:04:00 +01:00
|
|
|
virtual void release_pv(vvp_net_ptr_t ptr, bool net,
|
|
|
|
|
unsigned base, unsigned wid) =0;
|
2005-07-06 06:29:25 +02:00
|
|
|
};
|
|
|
|
|
|
2005-11-25 18:55:26 +01:00
|
|
|
/*
|
2008-01-29 21:19:59 +01:00
|
|
|
* This abstract class is a little more specific than the signal_base
|
|
|
|
|
* class, in that it adds vector access methods.
|
2005-11-25 18:55:26 +01:00
|
|
|
*/
|
|
|
|
|
class vvp_fun_signal_vec : public vvp_fun_signal_base {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// For vector signal types, this returns the vector count.
|
|
|
|
|
virtual unsigned size() const =0;
|
|
|
|
|
virtual vvp_bit4_t value(unsigned idx) const =0;
|
|
|
|
|
virtual vvp_scalar_t scalar_value(unsigned idx) const =0;
|
|
|
|
|
virtual vvp_vector4_t vec4_value() const =0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class vvp_fun_signal : public vvp_fun_signal_vec {
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
public:
|
2007-08-29 01:56:01 +02:00
|
|
|
explicit vvp_fun_signal(unsigned wid, vvp_bit4_t init=BIT4_X);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2008-06-12 21:08:02 +02:00
|
|
|
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-02-14 02:50:23 +01:00
|
|
|
// Part select variants of above
|
2005-06-22 20:30:12 +02:00
|
|
|
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
2005-02-14 02:50:23 +01:00
|
|
|
unsigned base, unsigned wid, unsigned vwid);
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
// Get information about the vector value.
|
|
|
|
|
unsigned size() const;
|
|
|
|
|
vvp_bit4_t value(unsigned idx) const;
|
2005-03-12 05:27:42 +01:00
|
|
|
vvp_scalar_t scalar_value(unsigned idx) const;
|
2005-03-18 03:56:03 +01:00
|
|
|
vvp_vector4_t vec4_value() const;
|
2004-12-11 03:31:25 +01:00
|
|
|
|
|
|
|
|
// Commands
|
2004-12-15 18:16:08 +01:00
|
|
|
void release(vvp_net_ptr_t port, bool net);
|
2008-03-12 00:04:00 +01:00
|
|
|
void release_pv(vvp_net_ptr_t port, bool net,
|
|
|
|
|
unsigned base, unsigned wid);
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
void get_value(struct t_vpi_value*value);
|
2005-06-02 18:02:11 +02:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
private:
|
2005-11-26 18:16:05 +01:00
|
|
|
void calculate_output_(vvp_net_ptr_t ptr);
|
|
|
|
|
|
2005-01-01 03:12:34 +01:00
|
|
|
vvp_vector4_t bits4_;
|
2005-07-06 06:29:25 +02:00
|
|
|
vvp_vector4_t force_;
|
|
|
|
|
};
|
2005-04-25 06:42:17 +02:00
|
|
|
|
2005-11-25 18:55:26 +01:00
|
|
|
class vvp_fun_signal8 : public vvp_fun_signal_vec {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit vvp_fun_signal8(unsigned wid);
|
|
|
|
|
|
|
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2008-06-12 21:08:02 +02:00
|
|
|
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
2005-11-25 18:55:26 +01:00
|
|
|
|
|
|
|
|
// Part select variants of above
|
2008-04-10 03:56:42 +02:00
|
|
|
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|
|
|
|
unsigned base, unsigned wid, unsigned vwid);
|
2008-06-12 21:08:02 +02:00
|
|
|
void recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
2008-04-10 03:56:42 +02:00
|
|
|
unsigned base, unsigned wid, unsigned vwid);
|
2005-11-25 18:55:26 +01:00
|
|
|
|
|
|
|
|
// Get information about the vector value.
|
|
|
|
|
unsigned size() const;
|
|
|
|
|
vvp_bit4_t value(unsigned idx) const;
|
|
|
|
|
vvp_scalar_t scalar_value(unsigned idx) const;
|
|
|
|
|
vvp_vector4_t vec4_value() const;
|
|
|
|
|
|
|
|
|
|
// Commands
|
|
|
|
|
void release(vvp_net_ptr_t port, bool net);
|
2008-03-12 00:04:00 +01:00
|
|
|
void release_pv(vvp_net_ptr_t port, bool net,
|
|
|
|
|
unsigned base, unsigned wid);
|
2005-11-25 18:55:26 +01:00
|
|
|
|
|
|
|
|
void get_value(struct t_vpi_value*value);
|
|
|
|
|
|
|
|
|
|
private:
|
2005-11-26 18:16:05 +01:00
|
|
|
void calculate_output_(vvp_net_ptr_t ptr);
|
|
|
|
|
|
2005-11-25 18:55:26 +01:00
|
|
|
vvp_vector8_t bits8_;
|
|
|
|
|
vvp_vector8_t force_;
|
|
|
|
|
};
|
|
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
class vvp_fun_signal_real : public vvp_fun_signal_base {
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2005-07-06 06:29:25 +02:00
|
|
|
public:
|
|
|
|
|
explicit vvp_fun_signal_real();
|
|
|
|
|
|
|
|
|
|
//void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
|
|
|
|
void recv_real(vvp_net_ptr_t port, double bit);
|
|
|
|
|
|
|
|
|
|
// Get information about the vector value.
|
|
|
|
|
double real_value() const;
|
|
|
|
|
|
|
|
|
|
// Commands
|
|
|
|
|
void release(vvp_net_ptr_t port, bool net);
|
2008-03-12 00:04:00 +01:00
|
|
|
void release_pv(vvp_net_ptr_t port, bool net,
|
|
|
|
|
unsigned base, unsigned wid);
|
2005-07-06 06:29:25 +02:00
|
|
|
|
|
|
|
|
void get_value(struct t_vpi_value*value);
|
2004-12-15 18:16:08 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
private:
|
2005-07-06 06:29:25 +02:00
|
|
|
double bits_;
|
|
|
|
|
double force_;
|
2004-12-11 03:31:25 +01:00
|
|
|
};
|
|
|
|
|
|
2005-04-01 08:02:45 +02:00
|
|
|
/*
|
|
|
|
|
* Wide Functors:
|
2007-03-22 17:08:14 +01:00
|
|
|
* Wide functors represent special devices that may have more than 4
|
2005-04-01 08:02:45 +02:00
|
|
|
* input ports. These devices need a set of N/4 actual functors to
|
|
|
|
|
* catch the inputs, and use another to deliver the output.
|
|
|
|
|
*
|
|
|
|
|
* vvp_wide_fun_t --+--> vvp_wide_fun_core --> ...
|
|
|
|
|
* |
|
|
|
|
|
* vvp_wide_fun_t --+
|
|
|
|
|
* |
|
|
|
|
|
* vvp_wide_fun_t --+
|
|
|
|
|
*
|
|
|
|
|
* There are enough input functors to take all the functor inputs, 4
|
|
|
|
|
* per functor. These inputs deliver the changed input value to the
|
2008-01-29 21:19:59 +01:00
|
|
|
* wide_fun_core, which carries the infrastructure for the thread. The
|
2005-04-01 08:02:45 +02:00
|
|
|
* wide_fun_core is also a functor whose output is connected to the rest
|
|
|
|
|
* of the netlist. This is where the result is delivered back to the
|
|
|
|
|
* netlist.
|
|
|
|
|
*
|
|
|
|
|
* The vvp_wide_fun_core keeps a store of the inputs from all the
|
|
|
|
|
* input functors, and makes them available to the derived class that
|
|
|
|
|
* does the processing.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class vvp_wide_fun_core : public vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_wide_fun_core(vvp_net_t*net, unsigned nports);
|
|
|
|
|
virtual ~vvp_wide_fun_core();
|
|
|
|
|
|
|
|
|
|
protected:
|
2005-04-03 07:45:51 +02:00
|
|
|
void propagate_vec4(const vvp_vector4_t&bit, vvp_time64_t delay =0);
|
2008-01-29 03:57:55 +01:00
|
|
|
void propagate_real(double bit, vvp_time64_t delay =0);
|
2005-04-01 08:02:45 +02:00
|
|
|
unsigned port_count() const;
|
2006-06-18 06:15:50 +02:00
|
|
|
|
2005-04-01 08:02:45 +02:00
|
|
|
vvp_vector4_t& value(unsigned);
|
2006-06-18 06:15:50 +02:00
|
|
|
double value_r(unsigned);
|
2005-04-01 08:02:45 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// the derived class implements this to receive an indication
|
|
|
|
|
// that one of the port input values changed.
|
|
|
|
|
virtual void recv_vec4_from_inputs(unsigned port) =0;
|
2006-06-18 06:15:50 +02:00
|
|
|
virtual void recv_real_from_inputs(unsigned port);
|
2005-04-01 08:02:45 +02:00
|
|
|
|
|
|
|
|
friend class vvp_wide_fun_t;
|
|
|
|
|
void dispatch_vec4_from_input_(unsigned port, vvp_vector4_t bit);
|
2006-06-18 06:15:50 +02:00
|
|
|
void dispatch_real_from_input_(unsigned port, double bit);
|
2005-04-01 08:02:45 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Back-point to the vvp_net_t that points to me.
|
|
|
|
|
vvp_net_t*ptr_;
|
|
|
|
|
// Structure to track the input values from the input functors.
|
|
|
|
|
unsigned nports_;
|
|
|
|
|
vvp_vector4_t*port_values_;
|
2006-06-18 06:15:50 +02:00
|
|
|
double*port_rvalues_;
|
2005-04-01 08:02:45 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The job of the input functor is only to monitor inputs to the
|
|
|
|
|
* function and pass them to the ufunc_core object. Each functor takes
|
|
|
|
|
* up to 4 inputs, with the base the port number for the first
|
|
|
|
|
* function input that this functor represents.
|
|
|
|
|
*/
|
|
|
|
|
class vvp_wide_fun_t : public vvp_net_fun_t {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
vvp_wide_fun_t(vvp_wide_fun_core*c, unsigned base);
|
|
|
|
|
~vvp_wide_fun_t();
|
|
|
|
|
|
2005-06-22 02:04:48 +02:00
|
|
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
2006-06-18 06:15:50 +02:00
|
|
|
void recv_real(vvp_net_ptr_t port, double bit);
|
2005-04-01 08:02:45 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
vvp_wide_fun_core*core_;
|
|
|
|
|
unsigned port_base_;
|
|
|
|
|
};
|
|
|
|
|
|
2005-06-20 03:28:14 +02:00
|
|
|
|
|
|
|
|
inline void vvp_send_vec4(vvp_net_ptr_t ptr, const vvp_vector4_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_vec4(ptr, val);
|
|
|
|
|
|
|
|
|
|
ptr = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-06-24 04:16:42 +02:00
|
|
|
|
2008-06-12 21:08:02 +02:00
|
|
|
extern void vvp_send_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&val);
|
2005-06-20 03:28:14 +02:00
|
|
|
extern void vvp_send_real(vvp_net_ptr_t ptr, double val);
|
|
|
|
|
extern void vvp_send_long(vvp_net_ptr_t ptr, long val);
|
2008-03-12 00:04:00 +01:00
|
|
|
extern void vvp_send_long_pv(vvp_net_ptr_t ptr, long val,
|
|
|
|
|
unsigned base, unsigned width);
|
2005-06-20 03:28:14 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Part-vector versions of above functions. This function uses the
|
|
|
|
|
* corresponding recv_vec4_pv method in the vvp_net_fun_t functor to
|
|
|
|
|
* deliver parts of a vector.
|
|
|
|
|
*
|
|
|
|
|
* The ptr is the destination input port to write to.
|
|
|
|
|
*
|
|
|
|
|
* <val> is the vector to be written. The width of this vector must
|
|
|
|
|
* exactly match the <wid> vector.
|
|
|
|
|
*
|
|
|
|
|
* The <base> is where in the receiver the bit vector is to be
|
2005-09-19 23:45:35 +02:00
|
|
|
* written. This address is given in canonical units; 0 is the LSB, 1
|
2005-06-20 03:28:14 +02:00
|
|
|
* is the next bit, and so on.
|
|
|
|
|
*
|
|
|
|
|
* The <vwid> is the width of the destination vector that this part is
|
|
|
|
|
* part of. This is used by intermediate nodes, i.e. resolvers, to
|
|
|
|
|
* know how wide to pad with Z, if it needs to transform the part to a
|
|
|
|
|
* mirror of the destination vector.
|
|
|
|
|
*/
|
2005-06-24 04:16:42 +02:00
|
|
|
inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
|
|
|
|
unsigned base, unsigned wid, unsigned vwid)
|
|
|
|
|
{
|
|
|
|
|
while (struct vvp_net_t*cur = ptr.ptr()) {
|
|
|
|
|
vvp_net_ptr_t next = cur->port[ptr.port()];
|
|
|
|
|
|
|
|
|
|
if (cur->fun)
|
|
|
|
|
cur->fun->recv_vec4_pv(ptr, val, base, wid, vwid);
|
|
|
|
|
|
|
|
|
|
ptr = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
#endif
|