Optimize some common vvp_bit4_t operators.

By slightly altering the vvp_bit4_t encoding, a few simple
optimizations become possible. By making Z==2 and X==3, the
conversion from X/Z to X is a simple shift-or, and this can
be used to reduce the size of some of the bit4 operators.
This commit is contained in:
Stephen Williams 2008-04-20 21:36:53 -07:00
parent 6d2ef15951
commit 935c3dc02d
2 changed files with 25 additions and 26 deletions

View File

@ -44,6 +44,7 @@ vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c)
switch (sum) { switch (sum) {
case 0: case 0:
// c must already be 0.
return BIT4_0; return BIT4_0;
case 1: case 1:
c = BIT4_0; c = BIT4_0;
@ -79,11 +80,7 @@ vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b)
return BIT4_1; return BIT4_1;
if (b == BIT4_1) if (b == BIT4_1)
return BIT4_1; return BIT4_1;
if (bit4_is_xz(a)) return bit4_z2x( (vvp_bit4_t) ((int)a | (int)b) );
return BIT4_X;
if (bit4_is_xz(b))
return BIT4_X;
return BIT4_0;
} }
vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b) vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b)
@ -99,18 +96,6 @@ vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b)
return BIT4_0; return BIT4_0;
} }
vvp_bit4_t operator ~ (vvp_bit4_t a)
{
switch (a) {
case BIT4_0:
return BIT4_1;
case BIT4_1:
return BIT4_0;
default:
return BIT4_X;
}
}
ostream& operator<<(ostream&out, vvp_bit4_t bit) ostream& operator<<(ostream&out, vvp_bit4_t bit)
{ {
switch (bit) { switch (bit) {

View File

@ -57,8 +57,8 @@ class vvp_delay_t;
enum vvp_bit4_t { enum vvp_bit4_t {
BIT4_0 = 0, BIT4_0 = 0,
BIT4_1 = 1, BIT4_1 = 1,
BIT4_X = 2, BIT4_X = 3,
BIT4_Z = 3 BIT4_Z = 2
}; };
extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c); extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c);
@ -67,11 +67,25 @@ extern vvp_bit4_t add_with_carry(vvp_bit4_t a, vvp_bit4_t b, vvp_bit4_t&c);
implementation here relies on the encoding of vvp_bit4_t values. */ implementation here relies on the encoding of vvp_bit4_t values. */
inline bool bit4_is_xz(vvp_bit4_t a) { return a >= 2; } inline bool bit4_is_xz(vvp_bit4_t a) { return a >= 2; }
/* 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) ); }
/* Some common boolean operators. These implement the Verilog rules /* Some common boolean operators. These implement the Verilog rules
for 4-value bit operations. */ for 4-value bit operations. The fast implementations here rely
extern vvp_bit4_t operator ~ (vvp_bit4_t a); on the encoding of vvp_bit4_t values. */
extern vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b);
// ~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)); }
extern vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b); extern vvp_bit4_t operator | (vvp_bit4_t a, vvp_bit4_t b);
extern vvp_bit4_t operator & (vvp_bit4_t a, vvp_bit4_t b);
extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b); extern vvp_bit4_t operator ^ (vvp_bit4_t a, vvp_bit4_t b);
extern ostream& operator<< (ostream&o, vvp_bit4_t a); extern ostream& operator<< (ostream&o, vvp_bit4_t a);
@ -195,13 +209,13 @@ inline vvp_vector4_t::vvp_vector4_t(unsigned size, vvp_bit4_t val)
const static unsigned long init_atable[4] = { const static unsigned long init_atable[4] = {
WORD_0_ABITS, WORD_0_ABITS,
WORD_1_ABITS, WORD_1_ABITS,
WORD_X_ABITS, WORD_Z_ABITS,
WORD_Z_ABITS }; WORD_X_ABITS };
const static unsigned long init_btable[4] = { const static unsigned long init_btable[4] = {
WORD_0_BBITS, WORD_0_BBITS,
WORD_1_BBITS, WORD_1_BBITS,
WORD_X_BBITS, WORD_Z_BBITS,
WORD_Z_BBITS }; WORD_X_BBITS };
allocate_words_(size, init_atable[val], init_btable[val]); allocate_words_(size, init_atable[val], init_btable[val]);
} }