Merge branch 'vector4_format'

This commit is contained in:
Stephen Williams 2008-04-20 21:46:02 -07:00
commit 5ab0c20a7d
15 changed files with 450 additions and 1183 deletions

View File

@ -1444,10 +1444,10 @@ void compile_resolver(char*label, char*type, unsigned argc, struct symb_s*argv)
obj = new resolv_functor(vvp_scalar_t(BIT4_1, 5)); obj = new resolv_functor(vvp_scalar_t(BIT4_1, 5));
} else if (strcmp(type,"triand") == 0) { } else if (strcmp(type,"triand") == 0) {
obj = new table_functor_s(ft_TRIAND); obj = new resolv_triand;
} else if (strcmp(type,"trior") == 0) { } else if (strcmp(type,"trior") == 0) {
obj = new table_functor_s(ft_TRIOR); obj = new resolv_trior;
} else { } else {
fprintf(stderr, "invalid resolver type: %s\n", type); fprintf(stderr, "invalid resolver type: %s\n", type);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -16,639 +16,9 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_tt.c,v 1.23 2006/11/28 05:57:20 steve Exp $"
#endif
# include <stdio.h> # include <stdio.h>
#if 0
static void draw_AND(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_AND[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 == 0) || (i1 == 0) ||
(i2 == 0) || (i3 == 0))
val = 0;
else if ((i0 == 1) && (i1 == 1) &&
(i2 == 1) && (i3 == 1))
val = 1;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_NAND(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_NAND[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 == 0) || (i1 == 0) ||
(i2 == 0) || (i3 == 0))
val = 1;
else if ((i0 == 1) && (i1 == 1) &&
(i2 == 1) && (i3 == 1))
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_BUF(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_BUF[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i0 == 1)
val = 1;
else if (i0 == 0)
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_BUFZ(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_BUFZ[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val = i0;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_BUFIF0(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_BUFIF0[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i2 == 0)
val = 3;
else if (i0 == 1)
val = 1;
else if (i0 == 0)
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_BUFIF1(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_BUFIF1[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i2 == 1)
val = 3;
else if (i0 == 1)
val = 1;
else if (i0 == 0)
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_PMOS(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_PMOS[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i2 == 0 || i0 == 3)
val = 3;
else if (i0 == 1)
val = 1;
else if (i0 == 0)
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_NMOS(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_NMOS[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i2 == 1 || i0 == 3)
val = 3;
else if (i0 == 1)
val = 1;
else if (i0 == 0)
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
static void draw_MUXX(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_MUXX[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i3 == 0)
val = 3;
else if (i3 == 2)
val = 2;
else if (i3 == 3)
val = 2;
else if (i2 >= 2) {
val = 2;
} else if (i2 == 0)
val = i0;
else
val = i1;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#if 0
static void draw_MUXZ(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_MUXZ[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i3 == 0)
val = 3;
else if (i3 == 2)
val = 2;
else if (i3 == 3)
val = 2;
else if (i2 >= 2) {
if (i0 == i1)
val = i0;
else
val = 2;
} else if (i2 == 0)
val = i0;
else
val = i1;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_EEQ(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_EEQ[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i3 != i2)
val = 0;
else if (i1 != i0)
val = 0;
else
val = 1;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_NOR(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_NOR[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 == 1) || (i1 == 1) ||
(i2 == 1) || (i3 == 1))
val = 0;
else if ((i0 == 0) && (i1 == 0) &&
(i2 == 0) && (i3 == 0))
val = 1;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_NOT(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_NOT[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if (i0 == 1)
val = 0;
else if (i0 == 0)
val = 1;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_OR(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_OR[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 == 1) || (i1 == 1) ||
(i2 == 1) || (i3 == 1))
val = 1;
else if ((i0 == 0) && (i1 == 0) &&
(i2 == 0) && (i3 == 0))
val = 0;
else
val = 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_XNOR(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_XNOR[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 > 1) || (i1 > 1)
|| (i2 > 1) || (i3 > 1))
val = 2;
else
val = (i0 + i1 + i2 + i3) % 2 ^ 1;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
#if 0
static void draw_XOR(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_XOR[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 > 1) || (i1 > 1)
|| (i2 > 1) || (i3 > 1))
val = 2;
else
val = (i0 + i1 + i2 + i3) % 2;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
#endif
static void draw_TRIAND(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_TRIAND[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 == 0) || (i1 == 0) ||
(i2 == 0) || (i3 == 0))
val = 0;
else if ((i0 == 2) || (i1 == 2) ||
(i2 == 2) || (i3 == 2))
val = 2;
else if ((i0 == 3) && (i1 == 3) &&
(i2 == 3) && (i3 == 3))
val = 3;
else
val = 1;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
static void draw_TRIOR(void)
{
unsigned i0, i1, i2, i3;
printf("const unsigned char ft_TRIOR[64] = {");
for (i3 = 0 ; i3 < 4 ; i3 += 1)
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
printf("\n ");
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
unsigned char byte = 0;
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
unsigned val;
if ((i0 == 1) || (i1 == 1) ||
(i2 == 1) || (i3 == 1))
val = 1;
else if ((i0 == 2) || (i1 == 2) ||
(i2 == 2) || (i3 == 2))
val = 2;
else if ((i0 == 3) && (i1 == 3) &&
(i2 == 3) && (i3 == 3))
val = 3;
else
val = 0;
byte |= val << (i0*2);
}
printf("0x%02x, ", byte);
}
}
printf("};\n");
}
/* /*
* The hex_digits table is not a functor truth table per say, but a * The hex_digits table is not a functor truth table per say, but a
@ -749,85 +119,7 @@ static void draw_oct_table()
main() main()
{ {
printf("# include \"logic.h\"\n");
draw_MUXX();
draw_TRIAND();
draw_TRIOR();
draw_hex_table(); draw_hex_table();
draw_oct_table(); draw_oct_table();
return 0; return 0;
} }
/*
* $Log: draw_tt.c,v $
* Revision 1.23 2006/11/28 05:57:20 steve
* Use new vvp_fun_XXX in place of old functor table for NAND/NOR/XNOR/EEQ.
*
* Revision 1.22 2005/09/19 21:45:09 steve
* Use lazy eval of BUF/NOT/OR/XOR gates.
*
* Revision 1.21 2005/06/12 21:56:16 steve
* Remove unused ft_MOS truth tables.
*
* Revision 1.20 2005/02/12 23:05:25 steve
* Cleanup unused truth tables.
*
* Revision 1.19 2005/02/12 22:50:52 steve
* Implement the vvp_fun_muxz functor.
*
* Revision 1.18 2005/01/29 17:52:06 steve
* move AND to buitin instead of table.
*
* Revision 1.17 2004/12/31 05:57:25 steve
* No need to draw BUF or BUFZ tables.
*
* Revision 1.16 2004/10/04 01:10:59 steve
* Clean up spurious trailing white space.
*
* Revision 1.15 2003/07/30 01:13:29 steve
* Add support for triand and trior.
*
* Revision 1.14 2002/08/29 03:04:01 steve
* Generate x out for x select on wide muxes.
*
* Revision 1.13 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
* Revision 1.12 2002/01/12 04:02:16 steve
* Support the BUFZ logic device.
*
* Revision 1.11 2001/11/06 03:07:22 steve
* Code rearrange. (Stephan Boettcher)
*
* Revision 1.10 2001/10/09 02:28:17 steve
* Add the PMOS and NMOS functor types.
*
* Revision 1.9 2001/06/19 03:01:10 steve
* Add structural EEQ gates (Stephan Boettcher)
*
* Revision 1.8 2001/04/29 23:13:34 steve
* Add bufif0 and bufif1 functors.
*
* Revision 1.7 2001/04/26 05:12:02 steve
* Implement simple MUXZ for ?: operators.
*
* Revision 1.6 2001/04/21 02:04:01 steve
* Add NAND and XNOR functors.
*
* Revision 1.5 2001/04/15 16:37:48 steve
* add XOR support.
*
* Revision 1.4 2001/04/01 21:31:46 steve
* Add the buf functor type.
*
* Revision 1.3 2001/03/25 20:45:09 steve
* Add vpiOctStrVal access to signals.
*
* Revision 1.2 2001/03/25 19:37:26 steve
* Calculate NOR and NOT tables, and also the hex_digits table.
*
* Revision 1.1 2001/03/11 22:42:11 steve
* Functor values and propagation.
*
*/

View File

@ -31,52 +31,6 @@
# include <malloc.h> # include <malloc.h>
#endif #endif
/*
* Implementation of the table functor, which provides logic with up
* to 4 inputs.
*/
table_functor_s::table_functor_s(truth_t t)
: table(t)
{
count_functors_logic += 1;
}
table_functor_s::~table_functor_s()
{
}
/*
* WARNING: This function assumes that the table generator encodes the
* values 0/1/x/z the same as the vvp_bit4_t enumeration values.
*/
void table_functor_s::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&val)
{
input_[ptr.port()] = val;
vvp_vector4_t result (val.size());
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
unsigned lookup = 0;
for (unsigned pdx = 4 ; pdx > 0 ; pdx -= 1) {
lookup <<= 2;
if (idx < input_[pdx-1].size())
lookup |= input_[pdx-1].value(idx);
}
unsigned off = lookup / 4;
unsigned shift = lookup % 4 * 2;
unsigned bit_val = table[off] >> shift;
bit_val &= 3;
result.set_bit(idx, (vvp_bit4_t)bit_val);
}
vvp_send_vec4(ptr.ptr()->out, result);
}
vvp_fun_boolean_::vvp_fun_boolean_(unsigned wid) vvp_fun_boolean_::vvp_fun_boolean_(unsigned wid)
{ {
net_ = 0; net_ = 0;
@ -604,9 +558,6 @@ void compile_functor(char*label, char*type, unsigned width,
} else if (strcmp(type, "MUXR") == 0) { } else if (strcmp(type, "MUXR") == 0) {
obj = new vvp_fun_muxr; obj = new vvp_fun_muxr;
} else if (strcmp(type, "MUXX") == 0) {
obj = new table_functor_s(ft_MUXX);
} else if (strcmp(type, "MUXZ") == 0) { } else if (strcmp(type, "MUXZ") == 0) {
obj = new vvp_fun_muxz(width); obj = new vvp_fun_muxz(width);

View File

@ -23,26 +23,6 @@
# include "schedule.h" # include "schedule.h"
# include <stddef.h> # include <stddef.h>
/*
* Table driven functor. This kind of node takes 4 inputs and
* generates a single output. The logic is bitwise, and implemented
* with a lookup table.
*/
class table_functor_s: public vvp_net_fun_t {
public:
typedef const unsigned char *truth_t;
explicit table_functor_s(truth_t t);
virtual ~table_functor_s();
void recv_vec4(vvp_net_ptr_t p, const vvp_vector4_t&bit);
private:
truth_t table;
vvp_vector4_t input_[4];
};
/* /*
* vvp_fun_boolean_ is just a common hook for holding operands. * vvp_fun_boolean_ is just a common hook for holding operands.
*/ */
@ -210,11 +190,4 @@ class vvp_fun_xor : public vvp_fun_boolean_ {
bool invert_; bool invert_;
}; };
// table functor types
extern const unsigned char ft_MUXX[];
extern const unsigned char ft_EEQ[];
extern const unsigned char ft_TRIAND[];
extern const unsigned char ft_TRIOR[];
#endif // __logic_H #endif // __logic_H

View File

@ -93,3 +93,84 @@ void resolv_functor::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
vvp_send_vec8(ptr->out, out); vvp_send_vec8(ptr->out, out);
} }
resolv_wired_logic::resolv_wired_logic()
{
}
resolv_wired_logic::~resolv_wired_logic()
{
}
void resolv_wired_logic::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
{
unsigned pdx = port.port();
vvp_net_t*ptr = port.ptr();
if (val_[pdx].eeq(bit))
return;
val_[pdx] = bit;
vvp_vector4_t out (bit);
for (unsigned idx = 0 ; idx < 4 ; idx += 1) {
if (idx == pdx)
continue;
if (val_[idx].size() == 0)
continue;
out = wired_logic_math_(out, val_[idx]);
}
vvp_send_vec4(ptr->out, out);
}
vvp_vector4_t resolv_triand::wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b)
{
assert(a.size() == b.size());
vvp_vector4_t out (a.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_bit4_t abit = a.value(idx);
vvp_bit4_t bbit = b.value(idx);
if (abit == BIT4_Z) {
out.set_bit(idx, bbit);
} else if (bbit == BIT4_Z) {
out.set_bit(idx, abit);
} else if (abit == BIT4_0 || bbit == BIT4_0) {
out.set_bit(idx, BIT4_0);
} else if (abit == BIT4_X || bbit == BIT4_X) {
out.set_bit(idx, BIT4_X);
} else {
out.set_bit(idx, BIT4_1);
}
}
return out;
}
vvp_vector4_t resolv_trior::wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b)
{
assert(a.size() == b.size());
vvp_vector4_t out (a.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_bit4_t abit = a.value(idx);
vvp_bit4_t bbit = b.value(idx);
if (abit == BIT4_Z) {
out.set_bit(idx, bbit);
} else if (bbit == BIT4_Z) {
out.set_bit(idx, abit);
} else if (abit == BIT4_1 || bbit == BIT4_1) {
out.set_bit(idx, BIT4_1);
} else if (abit == BIT4_X || bbit == BIT4_X) {
out.set_bit(idx, BIT4_X);
} else {
out.set_bit(idx, BIT4_0);
}
}
return out;
}

View File

@ -1,7 +1,7 @@
#ifndef __resolv_H #ifndef __resolv_H
#define __resolv_H #define __resolv_H
/* /*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT
#ident "$Id: resolv.h,v 1.15 2005/06/22 18:30:12 steve Exp $"
#endif
# include "config.h" # include "config.h"
# include "vvp_net.h" # include "vvp_net.h"
@ -57,32 +54,39 @@ class resolv_functor : public vvp_net_fun_t {
const char* debug_label_; const char* debug_label_;
}; };
/* class resolv_wired_logic : public vvp_net_fun_t {
* $Log: resolv.h,v $
* Revision 1.15 2005/06/22 18:30:12 steve public:
* Inline more simple stuff, and more vector4_t by const reference for performance. explicit resolv_wired_logic(void);
* ~resolv_wired_logic();
* Revision 1.14 2005/06/22 00:04:49 steve
* Reduce vvp_vector4 copies by using const references. void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
*
* Revision 1.13 2005/03/12 04:27:43 steve protected:
* Implement VPI access to signal strengths, virtual vvp_vector4_t wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b) =0;
* Fix resolution of ambiguous drive pairs,
* Fix spelling of scalar. private:
* vvp_vector4_t val_[4];
* Revision 1.12 2005/01/09 20:11:16 steve };
* Add the .part/pv node and related functionality.
* class resolv_triand : public resolv_wired_logic {
* Revision 1.11 2005/01/01 02:12:34 steve
* vvp_fun_signal propagates vvp_vector8_t vectors when appropriate. public:
* explicit resolv_triand(void) { }
* Revision 1.10 2004/12/31 06:00:06 steve ~resolv_triand() { }
* Implement .resolv functors, and stub signals recv_vec8 method.
* private:
* Revision 1.9 2004/12/11 02:31:30 steve virtual vvp_vector4_t wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b);
* Rework of internals to carry vectors through nexus instead };
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path. class resolv_trior : public resolv_wired_logic {
*
*/ public:
explicit resolv_trior(void) { }
~resolv_trior() { }
private:
virtual vvp_vector4_t wired_logic_math_(vvp_vector4_t&a, vvp_vector4_t&b);
};
#endif #endif

View File

@ -444,7 +444,20 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
rbuf = need_result_buf(width+1, RBUF_VAL); rbuf = need_result_buf(width+1, RBUF_VAL);
for (unsigned idx = 0 ; idx < width ; idx += 1) { for (unsigned idx = 0 ; idx < width ; idx += 1) {
vvp_bit4_t bit = word_val.value(idx); vvp_bit4_t bit = word_val.value(idx);
rbuf[width-idx-1] = "01xz"[bit]; switch (bit) {
case BIT4_0:
rbuf[width-idx-1] = '0';
break;
case BIT4_1:
rbuf[width-idx-1] = '1';
break;
case BIT4_Z:
rbuf[width-idx-1] = 'z';
break;
case BIT4_X:
rbuf[width-idx-1] = 'x';
break;
}
} }
rbuf[width] = 0; rbuf[width] = 0;
vp->value.str = rbuf; vp->value.str = rbuf;

View File

@ -503,14 +503,9 @@ extern const char* vpip_name_string(const char*str);
/* /*
* This function is used to make decimal string versions of various * This function is used to make decimal string versions of various
* vectors. The input format is an array of bit values (0, 1, 2, 3) * vectors. The input format is a vvp_vector4_t, and the result is
* lsb first, and the result is written into buf, without overflowing * written into buf, without overflowing nbuf.
* nbuf.
*/ */
extern unsigned vpip_bits_to_dec_str(const unsigned char *bits,
unsigned int nbits,
char *buf, unsigned int nbuf,
int signed_flag);
extern unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4, extern unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
char *buf, unsigned int nbuf, char *buf, unsigned int nbuf,
int signed_flag); int signed_flag);
@ -521,8 +516,6 @@ extern void vpip_bin_str_to_vec4(vvp_vector4_t&val,
extern void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf, extern void vpip_vec4_to_hex_str(const vvp_vector4_t&bits, char*buf,
unsigned nbuf, bool signed_flag); unsigned nbuf, bool signed_flag);
extern void vpip_bits_to_oct_str(const unsigned char*bits, unsigned nbits,
char*buf, unsigned nbuf, bool signed_flag);
extern void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, extern void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf,
unsigned nbuf, bool signed_flag); unsigned nbuf, bool signed_flag);

View File

@ -239,26 +239,13 @@ static vpiHandle signal_iterate(int code, vpiHandle ref)
static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp) static char *signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{ {
unsigned wid = (rfp->msb >= rfp->lsb)
? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1);
vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun); vvp_fun_signal_vec*vsig = dynamic_cast<vvp_fun_signal_vec*>(rfp->node->fun);
assert(vsig); assert(vsig);
/* FIXME: bits should be an array of vvp_bit4_t. */ unsigned hwid = (vsig->size()+2) / 3 + 1;
unsigned char* bits = new unsigned char[wid];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
bits[idx] = vsig->value(idx);
}
unsigned hwid = (wid+2) / 3 + 1;
char *rbuf = need_result_buf(hwid, RBUF_VAL); char *rbuf = need_result_buf(hwid, RBUF_VAL);
vpip_bits_to_dec_str(bits, wid, rbuf, hwid, rfp->signed_flag); vpip_vec4_to_dec_str(vsig->vec4_value(), rbuf, hwid, rfp->signed_flag);
delete[]bits;
return rbuf; return rbuf;
} }
@ -445,7 +432,20 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf = need_result_buf(wid+1, RBUF_VAL); rbuf = need_result_buf(wid+1, RBUF_VAL);
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
rbuf[wid-idx-1] = "01xz"[vsig->value(idx)]; switch (vsig->value(idx)) {
case BIT4_0:
rbuf[wid-idx-1] = '0';
break;
case BIT4_1:
rbuf[wid-idx-1] = '1';
break;
case BIT4_Z:
rbuf[wid-idx-1] = 'z';
break;
case BIT4_X:
rbuf[wid-idx-1] = 'x';
break;
}
} }
rbuf[wid] = 0; rbuf[wid] = 0;
vp->value.str = rbuf; vp->value.str = rbuf;
@ -470,7 +470,22 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
rbuf[hwid] = 0; rbuf[hwid] = 0;
hval = 0; hval = 0;
for (unsigned idx = 0 ; idx < wid ; idx += 1) { for (unsigned idx = 0 ; idx < wid ; idx += 1) {
hval = hval | (vsig->value(idx) << 2*(idx % 3)); unsigned tmp = 0;
switch (vsig->value(idx)) {
case BIT4_0:
tmp = 0;
break;
case BIT4_1:
tmp = 1;
break;
case BIT4_Z:
tmp = 3;
break;
case BIT4_X:
tmp = 2;
break;
}
hval = hval | (tmp << 2*(idx % 3));
if (idx%3 == 2) { if (idx%3 == 2) {
hwid -= 1; hwid -= 1;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu> * Copyright (c) 2001 Stephan Boettcher <stephan@nevis.columbia.edu>
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_vthr_vector.cc,v 1.24 2007/02/19 01:45:56 steve Exp $"
#endif
/* /*
* vpiReg handles are handled here. These objects represent vectors of * vpiReg handles are handled here. These objects represent vectors of
@ -44,7 +41,7 @@ struct __vpiVThrVec {
}; };
inline static inline static
unsigned get_bit(struct __vpiVThrVec *rfp, unsigned idx) vvp_bit4_t get_bit(struct __vpiVThrVec *rfp, unsigned idx)
{ {
return vthread_get_bit(vpip_current_vthread, rfp->bas+idx); return vthread_get_bit(vpip_current_vthread, rfp->bas+idx);
} }
@ -114,13 +111,14 @@ static char* vthr_vec_get_str(int code, vpiHandle ref)
static void vthr_vec_DecStrVal(struct __vpiVThrVec*rfp, s_vpi_value*vp) static void vthr_vec_DecStrVal(struct __vpiVThrVec*rfp, s_vpi_value*vp)
{ {
unsigned char*bits = new unsigned char[rfp->wid]; int nbuf = (rfp->wid+2)/3 + 1;
char *rbuf = need_result_buf((rfp->wid+2)/3 + 1, RBUF_VAL); char *rbuf = need_result_buf(nbuf, RBUF_VAL);
vvp_vector4_t tmp (rfp->wid);
for (unsigned idx = 0 ; idx < rfp->wid ; idx += 1) for (unsigned idx = 0 ; idx < rfp->wid ; idx += 1)
bits[idx] = get_bit(rfp, idx); tmp.set_bit(idx, get_bit(rfp, idx));
vpip_bits_to_dec_str(bits, rfp->wid, rbuf, rfp->wid+1, rfp->signed_flag); vpip_vec4_to_dec_str(tmp, rbuf, nbuf, rfp->signed_flag);
vp->value.str = rbuf; vp->value.str = rbuf;
return; return;

View File

@ -88,37 +88,6 @@ void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str)
} }
} }
void vpip_bits_to_oct_str(const unsigned char*bits, unsigned nbits,
char*buf, unsigned nbuf, bool signed_flag)
{
unsigned slen = (nbits + 2) / 3;
unsigned val = 0;
assert(slen < nbuf);
buf[slen] = 0;
for (unsigned idx = 0 ; idx < nbits ; idx += 1) {
unsigned bi = idx/4;
unsigned bs = (idx%4) * 2;
unsigned bit = (bits[bi] >> bs) & 3;
unsigned vs = (idx%3) * 2;
val |= bit << vs;
if (vs == 4) {
slen -= 1;
buf[slen] = oct_digits[val];
val = 0;
}
}
if (slen > 0) {
slen -= 1;
buf[slen] = oct_digits[val];
}
}
void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf, void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf,
bool signed_flag) bool signed_flag)
{ {

View File

@ -1,4 +1,5 @@
/* /*
* Copyright (c) 2008 Stephen Williams <steve@icarus.com>
* Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org) * Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
@ -16,9 +17,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpip_to_dec.cc,v 1.8 2006/02/21 02:39:27 steve Exp $"
#endif
# include "config.h" # include "config.h"
# include "vpi_priv.h" # include "vpi_priv.h"
@ -222,100 +220,6 @@ unsigned vpip_vec4_to_dec_str(const vvp_vector4_t&vec4,
return 0; return 0;
} }
unsigned vpip_bits_to_dec_str(const unsigned char *bits, unsigned int nbits,
char *buf, unsigned int nbuf, int signed_flag)
{
unsigned int idx, len, vlen;
unsigned int mbits=nbits; /* number of non-sign bits */
unsigned count_x = 0, count_z = 0;
/* Jump through some hoops so we don't have to malloc/free valv
* on every call, and implement an optional malloc-less version. */
static unsigned long *valv=NULL;
static unsigned int vlen_alloc=0;
unsigned long val=0;
int comp=0;
if (signed_flag) {
if (B_ISZ(bits[nbits-1])) count_z++;
else if (B_ISX(bits[nbits-1])) count_x++;
else if (B_IS1(bits[nbits-1])) comp=1;
--mbits;
}
assert(mbits<(UINT_MAX-92)/28);
vlen = ((mbits*28+92)/93+BDIGITS-1)/BDIGITS;
/* printf("vlen=%d\n",vlen); */
#define ALLOC_MARGIN 4
if (!valv || vlen > vlen_alloc) {
if (valv) free(valv);
valv = (unsigned long*)
calloc( vlen+ALLOC_MARGIN, sizeof (*valv));
if (!valv) {perror("malloc"); return 0; }
vlen_alloc=vlen+ALLOC_MARGIN;
} else {
memset(valv,0,vlen*sizeof(valv[0]));
}
for (idx = 0; idx < mbits; idx += 1) {
/* printf("%c ",bits[mbits-idx-1]); */
if (B_ISZ(bits[mbits-idx-1])) count_z++;
else if (B_ISX(bits[mbits-idx-1])) count_x++;
else if (!comp && B_IS1(bits[mbits-idx-1])) ++val;
else if ( comp && B_IS0(bits[mbits-idx-1])) ++val;
if ((mbits-idx-1)%BBITS==0) {
/* make negative 2's complement, not 1's complement */
if (comp && idx==mbits-1) ++val;
shift_in(valv,vlen,val);
val=0;
} else {
val=val+val;
}
}
if (count_x == nbits) {
len = 1;
buf[0] = 'x';
buf[1] = 0;
} else if (count_x > 0) {
len = 1;
buf[0] = 'X';
buf[1] = 0;
} else if (count_z == nbits) {
len = 1;
buf[0] = 'z';
buf[1] = 0;
} else if (count_z > 0) {
len = 1;
buf[0] = 'Z';
buf[1] = 0;
} else {
int i;
int zero_suppress=1;
if (comp) {
*buf++='-';
nbuf--;
/* printf("-"); */
}
for (i=vlen-1; i>=0; i--) {
zero_suppress = write_digits(valv[i],
&buf,&nbuf,zero_suppress);
/* printf(",%.4u",valv[i]); */
}
/* Awkward special case, since we don't want to
* zero suppress down to nothing at all. The only
* way we can still have zero_suppress on in the
* comp=1 case is if mbits==0, and therefore vlen==0.
* We represent 1'sb1 as "-1". */
if (zero_suppress) *buf++='0'+comp;
/* printf("\n"); */
*buf='\0';
}
/* hold on to the memory, since we expect to be called again. */
/* free(valv); */
return 0;
}
void vpip_dec_str_to_vec4(vvp_vector4_t&vec, void vpip_dec_str_to_vec4(vvp_vector4_t&vec,
const char*buf, bool signed_flag) const char*buf, bool signed_flag)
{ {
@ -364,23 +268,3 @@ void vpip_dec_str_to_vec4(vvp_vector4_t&vec,
delete[]str; delete[]str;
} }
/*
* $Log: vpip_to_dec.cc,v $
* Revision 1.8 2006/02/21 02:39:27 steve
* Support string values for memory words.
*
* Revision 1.7 2004/10/04 01:11:00 steve
* Clean up spurious trailing white space.
*
* Revision 1.6 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2002/05/17 04:05:38 steve
* null terminate the reversed decimal string
*
* Revision 1.4 2002/05/11 04:39:36 steve
* Set and get memory words by string value.
*
*/

View File

@ -119,6 +119,9 @@ struct vthread_s {
struct vthread_s*scope_next, *scope_prev; struct vthread_s*scope_next, *scope_prev;
}; };
// this table maps the thread special index bit addresses to
// vvp_bit4_t bit values.
static vvp_bit4_t thr_index_to_bit4[4] = { BIT4_0, BIT4_1, BIT4_X, BIT4_Z };
static inline void thr_check_addr(struct vthread_s*thr, unsigned addr) static inline void thr_check_addr(struct vthread_s*thr, unsigned addr)
{ {
@ -203,7 +206,7 @@ static vvp_vector4_t vthread_bits_to_vector(struct vthread_s*thr,
} else { } else {
vvp_vector4_t value(wid); vvp_vector4_t value(wid);
vvp_bit4_t bit_val = (vvp_bit4_t)bit; vvp_bit4_t bit_val = thr_index_to_bit4[bit];
for (unsigned idx = 0; idx < wid; idx +=1) { for (unsigned idx = 0; idx < wid; idx +=1) {
value.set_bit(idx, bit_val); value.set_bit(idx, bit_val);
} }
@ -2799,7 +2802,7 @@ bool of_MOD_WR(vthread_t thr, vvp_code_t cp)
static bool of_MOV1XZ_(vthread_t thr, vvp_code_t cp) static bool of_MOV1XZ_(vthread_t thr, vvp_code_t cp)
{ {
thr_check_addr(thr, cp->bit_idx[0]+cp->number-1); thr_check_addr(thr, cp->bit_idx[0]+cp->number-1);
vvp_vector4_t tmp (cp->number, (vvp_bit4_t)cp->bit_idx[1]); vvp_vector4_t tmp (cp->number, thr_index_to_bit4[cp->bit_idx[1]]);
thr->bits4.set_vec(cp->bit_idx[0], tmp); thr->bits4.set_vec(cp->bit_idx[0], tmp);
return true; return true;
} }
@ -3528,9 +3531,8 @@ bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
} else { } else {
/* Make a vector of the desired width. */ /* Make a vector of the desired width. */
vvp_bit4_t bit_val = (vvp_bit4_t)bit; vvp_bit4_t bit_val = thr_index_to_bit4[bit];
vvp_vector4_t value(wid, bit_val); vvp_vector4_t value(wid, bit_val);
vvp_send_vec4(ptr, value); vvp_send_vec4(ptr, value);
} }

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) {
@ -228,26 +213,34 @@ void vvp_vector4_t::copy_from_(const vvp_vector4_t&that)
size_ = that.size_; size_ = that.size_;
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD; unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
bits_ptr_ = new unsigned long[words]; abits_ptr_ = new unsigned long[2*words];
bbits_ptr_ = abits_ptr_ + words;
for (unsigned idx = 0 ; idx < words ; idx += 1) for (unsigned idx = 0 ; idx < words ; idx += 1)
bits_ptr_[idx] = that.bits_ptr_[idx]; abits_ptr_[idx] = that.abits_ptr_[idx];
for (unsigned idx = 0 ; idx < words ; idx += 1)
bbits_ptr_[idx] = that.bbits_ptr_[idx];
} else { } else {
bits_val_ = that.bits_val_; abits_val_ = that.abits_val_;
bbits_val_ = that.bbits_val_;
} }
} }
void vvp_vector4_t::allocate_words_(unsigned wid, unsigned long init) void vvp_vector4_t::allocate_words_(unsigned wid, unsigned long inita, unsigned long initb)
{ {
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
unsigned cnt = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD; unsigned cnt = (size_ + BITS_PER_WORD - 1) / BITS_PER_WORD;
bits_ptr_ = new unsigned long[cnt]; abits_ptr_ = new unsigned long[2*cnt];
bbits_ptr_ = abits_ptr_ + cnt;
for (unsigned idx = 0 ; idx < cnt ; idx += 1) for (unsigned idx = 0 ; idx < cnt ; idx += 1)
bits_ptr_[idx] = init; abits_ptr_[idx] = inita;
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
bbits_ptr_[idx] = initb;
} else { } else {
bits_val_ = init; abits_val_ = inita;
bbits_val_ = initb;
} }
} }
@ -257,20 +250,21 @@ vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that,
size_ = wid; size_ = wid;
assert((adr + wid) <= that.size_); assert((adr + wid) <= that.size_);
allocate_words_(wid, WORD_X_BITS); allocate_words_(wid, WORD_X_ABITS, WORD_X_BBITS);
if (wid > BITS_PER_WORD) { if (wid > BITS_PER_WORD) {
/* In this case, the subvector and the source vector are /* In this case, the subvector and the source vector are
long. Do the transfer reasonably efficiently. */ long. Do the transfer reasonably efficiently. */
unsigned ptr = adr / BITS_PER_WORD; unsigned ptr = adr / BITS_PER_WORD;
unsigned off = adr % BITS_PER_WORD; unsigned long off = adr % BITS_PER_WORD;
unsigned noff = BITS_PER_WORD - off; unsigned long noff = BITS_PER_WORD - off;
unsigned long lmask = (1UL << 2UL*off) - 1UL; unsigned long lmask = (1UL << off) - 1UL;
unsigned trans = 0; unsigned trans = 0;
unsigned dst = 0; unsigned dst = 0;
while (trans < wid) { while (trans < wid) {
// The low bits of the result. // The low bits of the result.
bits_ptr_[dst] = (that.bits_ptr_[ptr] & ~lmask) >> 2UL*off; abits_ptr_[dst] = (that.abits_ptr_[ptr] & ~lmask) >> off;
bbits_ptr_[dst] = (that.bbits_ptr_[ptr] & ~lmask) >> off;
trans += noff; trans += noff;
if (trans >= wid) if (trans >= wid)
@ -281,7 +275,8 @@ vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that,
// The high bits of the result. Skip this if the // The high bits of the result. Skip this if the
// source and destination are perfectly aligned. // source and destination are perfectly aligned.
if (noff != BITS_PER_WORD) { if (noff != BITS_PER_WORD) {
bits_ptr_[dst] |= (that.bits_ptr_[ptr]&lmask) << 2*noff; abits_ptr_[dst] |= (that.abits_ptr_[ptr]&lmask) << noff;
bbits_ptr_[dst] |= (that.bbits_ptr_[ptr]&lmask) << noff;
trans += off; trans += off;
} }
@ -293,6 +288,7 @@ vvp_vector4_t::vvp_vector4_t(const vvp_vector4_t&that,
set_bit(idx, that.value(adr+idx)); set_bit(idx, that.value(adr+idx));
} }
} }
} }
/* /*
@ -308,7 +304,7 @@ void vvp_vector4_t::resize(unsigned newsize)
if (newsize > BITS_PER_WORD) { if (newsize > BITS_PER_WORD) {
unsigned newcnt = (newsize + BITS_PER_WORD - 1) / BITS_PER_WORD; unsigned newcnt = (newsize + BITS_PER_WORD - 1) / BITS_PER_WORD;
unsigned long*newbits = new unsigned long[newcnt]; unsigned long*newbits = new unsigned long[2*newcnt];
if (cnt > 1) { if (cnt > 1) {
unsigned trans = cnt; unsigned trans = cnt;
@ -316,26 +312,33 @@ void vvp_vector4_t::resize(unsigned newsize)
trans = newcnt; trans = newcnt;
for (unsigned idx = 0 ; idx < trans ; idx += 1) for (unsigned idx = 0 ; idx < trans ; idx += 1)
newbits[idx] = bits_ptr_[idx]; newbits[idx] = abits_ptr_[idx];
for (unsigned idx = 0 ; idx < trans ; idx += 1)
newbits[newcnt+idx] = bbits_ptr_[idx];
delete[]bits_ptr_; delete[]abits_ptr_;
} else { } else {
newbits[0] = bits_val_; newbits[0] = abits_val_;
newbits[newcnt] = bbits_val_;
} }
for (unsigned idx = cnt ; idx < newcnt ; idx += 1) for (unsigned idx = cnt ; idx < newcnt ; idx += 1)
newbits[idx] = WORD_X_BITS; newbits[idx] = WORD_X_ABITS;
for (unsigned idx = cnt ; idx < newcnt ; idx += 1)
newbits[newcnt+idx] = WORD_X_BBITS;
size_ = newsize; size_ = newsize;
bits_ptr_ = newbits; abits_ptr_ = newbits;
bbits_ptr_ = newbits + newcnt;
} else { } else {
unsigned long newval;
if (cnt > 1) { if (cnt > 1) {
newval = bits_ptr_[0]; unsigned long newvala = abits_ptr_[0];
delete[]bits_ptr_; unsigned long newvalb = bbits_ptr_[0];
bits_val_ = newval; delete[]abits_ptr_;
abits_val_ = newvala;
bbits_val_ = newvalb;
} }
size_ = newsize; size_ = newsize;
@ -354,69 +357,49 @@ unsigned long* vvp_vector4_t::subarray(unsigned adr, unsigned wid) const
if (size_ <= BITS_PER_WORD) { if (size_ <= BITS_PER_WORD) {
/* Handle the special case that the array is small. The /* Handle the special case that the array is small. The
entire value of the vector4 is within the bits_val_ entire value of the vector4 is within the xbits_val_
so we know that the result is a single word, the so we know that the result is a single word, the
source is a single word, and we just have to loop source is a single word, and we just have to loop
through that word. */ through that word. */
unsigned long tmp = bits_val_ >> 2UL*adr; unsigned long atmp = abits_val_ >> adr;
tmp &= (1UL << 2*wid) - 1; unsigned long btmp = bbits_val_ >> adr;
if (tmp & WORD_X_BITS) atmp &= (1UL << wid) - 1;
goto x_out; btmp &= (1UL << wid) - 1;
if (btmp) goto x_out;
unsigned long mask1 = 1; val[0] = atmp;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (tmp & 1) val[0] |= mask1;
mask1 <<= 1UL;
tmp >>= 2UL;
}
return val; return val;
} else { } else {
unsigned val_ptr = 0;
unsigned val_off = 0;
/* Get the first word we are scanning. We may in fact be /* Get the first word we are scanning. We may in fact be
somewhere in the middle of that word. */ somewhere in the middle of that word. */
unsigned long tmp = bits_ptr_[adr/BITS_PER_WORD]; while (wid > 0) {
unsigned long off = adr%BITS_PER_WORD; unsigned long atmp = abits_ptr_[adr/BITS_PER_WORD];
tmp >>= 2UL * off; unsigned long btmp = bbits_ptr_[adr/BITS_PER_WORD];
unsigned long off = adr%BITS_PER_WORD;
atmp >>= off;
btmp >>= off;
// Test for X bits but not beyond the desired wid. unsigned long trans = BITS_PER_WORD - off;
if (wid < (BITS_PER_WORD-off)) if (trans > (8*sizeof(val[0]) - val_off))
tmp &= ~(-1UL << 2*wid); trans = 8*sizeof(val[0]) - val_off;
if (tmp & WORD_X_BITS) if (wid < trans)
goto x_out; trans = wid;
atmp &= (1UL << trans) - 1;
btmp &= (1UL << trans) - 1;
if (btmp) goto x_out;
// Where in the target array to write the next bit. val[val_ptr] |= atmp << val_off;
unsigned long mask1 = 1; adr += trans;
const unsigned long mask1_last = 1UL << (BIT2_PER_WORD-1); wid -= trans;
unsigned long*val_ptr = val; val_off += trans;
// Track where the source bit is in the source word. if (val_off == 8*sizeof(val[0])) {
unsigned adr_bit = adr%BITS_PER_WORD;
// Scan...
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
/* Starting a new word? */
if (adr_bit == BITS_PER_WORD) {
tmp = bits_ptr_[adr/BITS_PER_WORD];
// If this is the last word, then only test
// for X in the valid bits.
if ((wid-idx) < BITS_PER_WORD)
tmp &= ~(WORD_Z_BITS<<2*(wid-idx));
if (tmp & WORD_X_BITS)
goto x_out;
adr_bit = 0;
}
if (tmp&1)
*val_ptr |= mask1;
adr += 1;
adr_bit += 1;
tmp >>= 2UL;
if (mask1 == mask1_last) {
val_ptr += 1; val_ptr += 1;
mask1 = 1; val_off = 0;
} else {
mask1 <<= 1;
} }
} }
} }
@ -447,50 +430,59 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
for all the bits that are to come from that. Do the for all the bits that are to come from that. Do the
job by some shifting, masking and OR. */ job by some shifting, masking and OR. */
unsigned long lmask = (1UL << 2UL*adr) - 1; unsigned long lmask = (1UL << adr) - 1;
unsigned long hmask; unsigned long hmask;
unsigned long hshift = adr+that.size_; unsigned long hshift = adr+that.size_;
if (hshift >= BITS_PER_WORD) if (hshift >= BITS_PER_WORD)
hmask = -1UL; hmask = -1UL;
else else
hmask = (1UL << 2UL*(adr+that.size_)) - 1; hmask = (1UL << (adr+that.size_)) - 1;
unsigned long mask = hmask & ~lmask; unsigned long mask = hmask & ~lmask;
bits_val_ = abits_val_ =
(bits_val_ & ~mask) (abits_val_ & ~mask)
| ((that.bits_val_<<2UL*adr) & mask); | ((that.abits_val_<<adr) & mask);
bbits_val_ =
(bbits_val_ & ~mask)
| ((that.bbits_val_<<adr) & mask);
} else if (that.size_ <= BITS_PER_WORD) { } else if (that.size_ <= BITS_PER_WORD) {
/* This vector is more than a word, but that vector is /* This vector is more than a word, but that vector is
still small. Write into the destination, possibly still small. Write into the destination, possibly
spanning two destination works, depending on whether spanning two destination words, depending on whether
the source vector spans a word transition. */ the source vector spans a word transition. */
unsigned long dptr = adr / BITS_PER_WORD; unsigned long dptr = adr / BITS_PER_WORD;
unsigned long doff = adr % BITS_PER_WORD; unsigned long doff = adr % BITS_PER_WORD;
unsigned long lmask = (1UL << 2UL*doff) - 1; unsigned long lmask = (1UL << doff) - 1;
unsigned long hshift = doff+that.size_; unsigned long hshift = doff+that.size_;
unsigned long hmask; unsigned long hmask;
if (hshift >= BITS_PER_WORD) if (hshift >= BITS_PER_WORD)
hmask = -1UL; hmask = -1UL;
else else
hmask = (1UL << 2*hshift) - 1UL; hmask = (1UL << hshift) - 1UL;
unsigned long mask = hmask & ~lmask; unsigned long mask = hmask & ~lmask;
bits_ptr_[dptr] = abits_ptr_[dptr] =
(bits_ptr_[dptr] & ~mask) (abits_ptr_[dptr] & ~mask)
| ((that.bits_val_ << 2UL*doff) & mask); | ((that.abits_val_ << doff) & mask);
bbits_ptr_[dptr] =
(bbits_ptr_[dptr] & ~mask)
| ((that.bbits_val_ << doff) & mask);
if ((doff + that.size_) > BITS_PER_WORD) { if ((doff + that.size_) > BITS_PER_WORD) {
unsigned tail = doff + that.size_ - BITS_PER_WORD; unsigned tail = doff + that.size_ - BITS_PER_WORD;
mask = (1UL << 2UL*tail) - 1; mask = (1UL << tail) - 1;
dptr += 1; dptr += 1;
bits_ptr_[dptr] = abits_ptr_[dptr] =
(bits_ptr_[dptr] & ~mask) (abits_ptr_[dptr] & ~mask)
| ((that.bits_val_ >> 2UL*(that.size_-tail)) & mask); | ((that.abits_val_ >> (that.size_-tail)) & mask);
bbits_ptr_[dptr] =
(bbits_ptr_[dptr] & ~mask)
| ((that.bbits_val_ >> (that.size_-tail)) & mask);
} }
} else if (adr%BITS_PER_WORD == 0) { } else if (adr%BITS_PER_WORD == 0) {
@ -503,15 +495,21 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
unsigned sptr = 0; unsigned sptr = 0;
unsigned dptr = adr / BITS_PER_WORD; unsigned dptr = adr / BITS_PER_WORD;
while (remain >= BITS_PER_WORD) { while (remain >= BITS_PER_WORD) {
bits_ptr_[dptr++] = that.bits_ptr_[sptr++]; abits_ptr_[dptr] = that.abits_ptr_[sptr];
bbits_ptr_[dptr] = that.bbits_ptr_[sptr];
dptr += 1;
sptr += 1;
remain -= BITS_PER_WORD; remain -= BITS_PER_WORD;
} }
if (remain > 0) { if (remain > 0) {
unsigned long mask = (1UL << 2UL*remain) - 1; unsigned long mask = (1UL << remain) - 1;
bits_ptr_[dptr] = abits_ptr_[dptr] =
(bits_ptr_[dptr] & ~mask) (abits_ptr_[dptr] & ~mask)
| (that.bits_ptr_[sptr] & mask); | (that.abits_ptr_[sptr] & mask);
bbits_ptr_[dptr] =
(bbits_ptr_[dptr] & ~mask)
| (that.bbits_ptr_[sptr] & mask);
} }
} else { } else {
@ -523,17 +521,23 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
unsigned sptr = 0; unsigned sptr = 0;
unsigned dptr = adr / BITS_PER_WORD; unsigned dptr = adr / BITS_PER_WORD;
unsigned doff = adr % BITS_PER_WORD; unsigned doff = adr % BITS_PER_WORD;
unsigned long lmask = (1UL << 2UL*doff) - 1; unsigned long lmask = (1UL << doff) - 1;
unsigned ndoff = BITS_PER_WORD - doff; unsigned ndoff = BITS_PER_WORD - doff;
while (remain >= BITS_PER_WORD) { while (remain >= BITS_PER_WORD) {
bits_ptr_[dptr] = abits_ptr_[dptr] =
(bits_ptr_[dptr] & lmask) (abits_ptr_[dptr] & lmask)
| ((that.bits_ptr_[sptr] << 2UL*doff) & ~lmask); | ((that.abits_ptr_[sptr] << doff) & ~lmask);
bbits_ptr_[dptr] =
(bbits_ptr_[dptr] & lmask)
| ((that.bbits_ptr_[sptr] << doff) & ~lmask);
dptr += 1; dptr += 1;
bits_ptr_[dptr] = abits_ptr_[dptr] =
(bits_ptr_[dptr] & ~lmask) (abits_ptr_[dptr] & ~lmask)
| ((that.bits_ptr_[sptr] >> 2UL*ndoff) & lmask); | ((that.abits_ptr_[sptr] >> ndoff) & lmask);
bbits_ptr_[dptr] =
(bbits_ptr_[dptr] & ~lmask)
| ((that.bbits_ptr_[sptr] >> ndoff) & lmask);
remain -= BITS_PER_WORD; remain -= BITS_PER_WORD;
sptr += 1; sptr += 1;
@ -545,28 +549,32 @@ void vvp_vector4_t::set_vec(unsigned adr, const vvp_vector4_t&that)
if (hshift >= BITS_PER_WORD) if (hshift >= BITS_PER_WORD)
hmask = -1UL; hmask = -1UL;
else else
hmask = (1UL << 2UL*(doff+remain)) - 1; hmask = (1UL << (doff+remain)) - 1;
unsigned long mask = hmask & ~lmask; unsigned long mask = hmask & ~lmask;
bits_ptr_[dptr] = (bits_ptr_[dptr] & ~mask) abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask)
| ((that.bits_ptr_[sptr] << 2UL*doff) & mask); | ((that.abits_ptr_[sptr] << doff) & mask);
bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask)
| ((that.bbits_ptr_[sptr] << doff) & mask);
if ((doff + remain) > BITS_PER_WORD) { if ((doff + remain) > BITS_PER_WORD) {
unsigned tail = doff + remain - BITS_PER_WORD; unsigned tail = doff + remain - BITS_PER_WORD;
if (tail >= BITS_PER_WORD) if (tail >= BITS_PER_WORD)
mask = -1UL; mask = -1UL;
else else
mask = (1UL << 2UL*tail) - 1; mask = (1UL << tail) - 1;
dptr += 1; dptr += 1;
bits_ptr_[dptr] = (bits_ptr_[dptr] & ~mask) | abits_ptr_[dptr] = (abits_ptr_[dptr] & ~mask) |
((that.bits_ptr_[sptr] >> 2UL* ((that.abits_ptr_[sptr] >> (remain-tail))&mask);
(remain-tail))&mask); bbits_ptr_[dptr] = (bbits_ptr_[dptr] & ~mask) |
((that.bbits_ptr_[sptr] >> (remain-tail))&mask);
} }
} }
} }
} }
bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const
@ -575,24 +583,29 @@ bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const
return false; return false;
if (size_ < BITS_PER_WORD) { if (size_ < BITS_PER_WORD) {
unsigned long mask = (1UL << 2UL * size_) - 1; unsigned long mask = (1UL << size_) - 1;
return (bits_val_&mask) == (that.bits_val_&mask); return (abits_val_&mask) == (that.abits_val_&mask)
&& (bbits_val_&mask) == (that.bbits_val_&mask);
} }
if (size_ == BITS_PER_WORD) { if (size_ == BITS_PER_WORD) {
return bits_val_ == that.bits_val_; return (abits_val_ == that.abits_val_)
&& (bbits_val_ == that.bbits_val_);
} }
unsigned words = size_ / BITS_PER_WORD; unsigned words = size_ / BITS_PER_WORD;
for (unsigned idx = 0 ; idx < words ; idx += 1) { for (unsigned idx = 0 ; idx < words ; idx += 1) {
if (bits_ptr_[idx] != that.bits_ptr_[idx]) if (abits_ptr_[idx] != that.abits_ptr_[idx])
return false;
if (bbits_ptr_[idx] != that.bbits_ptr_[idx])
return false; return false;
} }
unsigned long mask = size_%BITS_PER_WORD; unsigned long mask = size_%BITS_PER_WORD;
if (mask > 0) { if (mask > 0) {
mask = (1UL << 2UL*mask) - 1; mask = (1UL << mask) - 1;
return (bits_ptr_[words]&mask) == (that.bits_ptr_[words]&mask); return (abits_ptr_[words]&mask) == (that.abits_ptr_[words]&mask)
&& (bbits_ptr_[words]&mask) == (that.bbits_ptr_[words]&mask);
} }
return true; return true;
@ -601,24 +614,24 @@ bool vvp_vector4_t::eeq(const vvp_vector4_t&that) const
bool vvp_vector4_t::has_xz() const bool vvp_vector4_t::has_xz() const
{ {
if (size_ < BITS_PER_WORD) { if (size_ < BITS_PER_WORD) {
unsigned long mask = WORD_X_BITS >> 2*(BITS_PER_WORD - size_); unsigned long mask = -1UL >> (BITS_PER_WORD - size_);
return 0 != (bits_val_&mask); return bbits_val_&mask;
} }
if (size_ == BITS_PER_WORD) { if (size_ == BITS_PER_WORD) {
return 0 != (bits_val_&WORD_X_BITS); return bbits_val_;
} }
unsigned words = size_ / BITS_PER_WORD; unsigned words = size_ / BITS_PER_WORD;
for (unsigned idx = 0 ; idx < words ; idx += 1) { for (unsigned idx = 0 ; idx < words ; idx += 1) {
if (bits_ptr_[idx] & WORD_X_BITS) if (bbits_ptr_[idx])
return true; return true;
} }
unsigned long mask = size_%BITS_PER_WORD; unsigned long mask = size_%BITS_PER_WORD;
if (mask > 0) { if (mask > 0) {
mask = WORD_X_BITS >> 2*(BITS_PER_WORD - mask); mask = -1UL >> (BITS_PER_WORD - mask);
return 0 != (bits_ptr_[words]&mask); return bbits_ptr_[words]&mask;
} }
return false; return false;
@ -626,15 +639,18 @@ bool vvp_vector4_t::has_xz() const
void vvp_vector4_t::change_z2x() void vvp_vector4_t::change_z2x()
{ {
assert(BIT4_Z == 3 && BIT4_X == 2); // This method relies on the fact that both BIT4_X and BIT4_Z
# define Z2X(val) do{ (val) = (val) & ~(((val)&WORD_X_BITS) >> 1UL); }while(0) // have the bbit set in the vector4 encoding, and also that
// the BIT4_X has abit set in the vector4 encoding. By simply
// or-ing the bbit into the abit, BIT4_X and BIT4_Z both
// become BIT4_X.
if (size_ <= BITS_PER_WORD) { if (size_ <= BITS_PER_WORD) {
Z2X(bits_val_); abits_val_ |= bbits_val_;
} else { } else {
unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD; unsigned words = (size_+BITS_PER_WORD-1) / BITS_PER_WORD;
for (unsigned idx = 0 ; idx < words ; idx += 1) for (unsigned idx = 0 ; idx < words ; idx += 1)
Z2X(bits_ptr_[idx]); abits_ptr_[idx] |= bbits_ptr_[idx];
} }
} }

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);
@ -136,31 +150,50 @@ class vvp_vector4_t {
private: private:
// Number of vvp_bit4_t bits that can be shoved into a word. // Number of vvp_bit4_t bits that can be shoved into a word.
enum { BITS_PER_WORD = 8*sizeof(unsigned long)/2 }; enum { BITS_PER_WORD = 8*sizeof(unsigned long) };
#if SIZEOF_UNSIGNED_LONG == 8 #if SIZEOF_UNSIGNED_LONG == 8
enum { WORD_0_BITS = 0x0000000000000000UL }; enum { WORD_0_ABITS = 0x0000000000000000UL,
enum { WORD_1_BITS = 0x5555555555555555UL }; WORD_0_BBITS = 0x0000000000000000UL };
enum { WORD_X_BITS = 0xaaaaaaaaaaaaaaaaUL }; enum { WORD_1_ABITS = 0xFFFFFFFFFFFFFFFFUL,
enum { WORD_Z_BITS = 0xffffffffffffffffUL }; WORD_1_BBITS = 0x0000000000000000UL };
enum { WORD_X_ABITS = 0xFFFFFFFFFFFFFFFFUL,
WORD_X_BBITS = 0xFFFFFFFFFFFFFFFFUL };
enum { WORD_Z_ABITS = 0x0000000000000000UL,
WORD_Z_BBITS = 0xFFFFFFFFFFFFFFFFUL };
#elif SIZEOF_UNSIGNED_LONG == 4 #elif SIZEOF_UNSIGNED_LONG == 4
enum { WORD_0_BITS = 0x00000000UL }; enum { WORD_0_ABITS = 0x00000000UL, WORD_0_BBITS = 0x00000000UL };
enum { WORD_1_BITS = 0x55555555UL }; enum { WORD_1_ABITS = 0xFFFFFFFFUL, WORD_1_BBITS = 0x00000000UL };
enum { WORD_X_BITS = 0xaaaaaaaaUL }; enum { WORD_X_ABITS = 0xFFFFFFFFUL, WORD_X_BBITS = 0xFFFFFFFFUL };
enum { WORD_Z_BITS = 0xffffffffUL }; enum { WORD_Z_ABITS = 0x00000000UL, WORD_Z_BBITS = 0xFFFFFFFFUL };
#else #else
#error "WORD_X_BITS not defined for this architecture?" #error "WORD_X_xBITS not defined for this architecture?"
#endif #endif
// Initialize and operator= use this private method to copy // Initialize and operator= use this private method to copy
// the data from that object into this object. // the data from that object into this object.
void copy_from_(const vvp_vector4_t&that); void copy_from_(const vvp_vector4_t&that);
void allocate_words_(unsigned size, unsigned long init); 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
unsigned size_; unsigned size_;
union { union {
unsigned long bits_val_; unsigned long abits_val_;
unsigned long*bits_ptr_; unsigned long*abits_ptr_;
};
union {
unsigned long bbits_val_;
unsigned long*bbits_ptr_;
}; };
}; };
@ -173,19 +206,26 @@ inline vvp_vector4_t::vvp_vector4_t(unsigned size, vvp_bit4_t val)
: size_(size) : size_(size)
{ {
/* note: this relies on the bit encoding for the vvp_bit4_t. */ /* note: this relies on the bit encoding for the vvp_bit4_t. */
const static unsigned long init_table[4] = { const static unsigned long init_atable[4] = {
WORD_0_BITS, WORD_0_ABITS,
WORD_1_BITS, WORD_1_ABITS,
WORD_X_BITS, WORD_Z_ABITS,
WORD_Z_BITS }; WORD_X_ABITS };
const static unsigned long init_btable[4] = {
WORD_0_BBITS,
WORD_1_BBITS,
WORD_Z_BBITS,
WORD_X_BBITS };
allocate_words_(size, init_table[val]); allocate_words_(size, init_atable[val], init_btable[val]);
} }
inline vvp_vector4_t::~vvp_vector4_t() inline vvp_vector4_t::~vvp_vector4_t()
{ {
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
delete[] bits_ptr_; delete[] abits_ptr_;
// bbits_ptr_ actually points half-way into a
// double-length array started at abits_ptr_
} }
} }
@ -195,7 +235,7 @@ inline vvp_vector4_t& vvp_vector4_t::operator= (const vvp_vector4_t&that)
return *this; return *this;
if (size_ > BITS_PER_WORD) if (size_ > BITS_PER_WORD)
delete[] bits_ptr_; delete[] abits_ptr_;
copy_from_(that); copy_from_(that);
@ -211,18 +251,28 @@ inline vvp_bit4_t vvp_vector4_t::value(unsigned idx) const
unsigned wdx = idx / BITS_PER_WORD; unsigned wdx = idx / BITS_PER_WORD;
unsigned long off = idx % BITS_PER_WORD; unsigned long off = idx % BITS_PER_WORD;
unsigned long bits; unsigned long abits, bbits;
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
bits = bits_ptr_[wdx]; abits = abits_ptr_[wdx];
bbits = bbits_ptr_[wdx];
} else { } else {
bits = bits_val_; abits = abits_val_;
bbits = bbits_val_;
} }
bits >>= (off * 2UL); 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
};
/* Casting is evil, but this cast matches the un-cast done /* Casting is evil, but this cast matches the un-cast done
when the vvp_bit4_t value is put into the vector. */ when the vvp_bit4_t value is put into the vector. */
return (vvp_bit4_t) (bits & 3); return bits_bit4_map[tmp];
} }
inline vvp_vector4_t vvp_vector4_t::subvalue(unsigned adr, unsigned wid) const inline vvp_vector4_t vvp_vector4_t::subvalue(unsigned adr, unsigned wid) const
@ -235,15 +285,41 @@ inline void vvp_vector4_t::set_bit(unsigned idx, vvp_bit4_t val)
assert(idx < size_); assert(idx < size_);
unsigned long off = idx % BITS_PER_WORD; unsigned long off = idx % BITS_PER_WORD;
unsigned long mask = 3UL << (2UL*off); unsigned long amask = 0, bmask = 0;
switch (val) {
case BIT4_0:
amask = 0;
bmask = 0;
break;
case BIT4_1:
amask = 1;
bmask = 0;
break;
case BIT4_X:
amask = 1;
bmask = 1;
break;
case BIT4_Z:
amask = 0;
bmask = 1;
break;
}
unsigned long mask = 1UL << off;
amask <<= off;
bmask <<= off;
if (size_ > BITS_PER_WORD) { if (size_ > BITS_PER_WORD) {
unsigned wdx = idx / BITS_PER_WORD; unsigned wdx = idx / BITS_PER_WORD;
bits_ptr_[wdx] &= ~mask; abits_ptr_[wdx] &= ~mask;
bits_ptr_[wdx] |= (unsigned long)val << (2UL*off); abits_ptr_[wdx] |= amask;
bbits_ptr_[wdx] &= ~mask;
bbits_ptr_[wdx] |= bmask;
} else { } else {
bits_val_ &= ~mask; abits_val_ &= ~mask;
bits_val_ |= (unsigned long)val << (2UL*off); abits_val_ |= amask;
bbits_val_ &= ~mask;
bbits_val_ |= bmask;
} }
} }