Use Larrys bits-to-decimal-string code.

This commit is contained in:
steve 2002-02-03 01:01:51 +00:00
parent 78bb3d6f09
commit ec82af0c74
5 changed files with 239 additions and 108 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.34 2002/01/02 02:39:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.35 2002/02/03 01:01:51 steve Exp $"
#
#
SHELL = /bin/sh
@ -63,7 +63,7 @@ check: all
V = vpi_modules.o vpi_callback.o vpi_const.o vpi_iter.o vpi_mcd.o \
vpi_priv.o vpi_scope.o vpi_signal.o vpi_tasks.o vpi_time.o vpi_memory.o \
vpi_vthr_vector.o vvp_vpi.o
vpi_vthr_vector.o vpip_to_dec.o vvp_vpi.o
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o debug.o \
functor.o fvectors.o npmos.o resolv.o symbols.o codes.o vthread.o schedule.o \

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_const.cc,v 1.10 2002/01/31 04:28:17 steve Exp $"
#ident "$Id: vpi_const.cc,v 1.11 2002/02/03 01:01:51 steve Exp $"
#endif
# include "vpi_priv.h"
@ -219,48 +219,13 @@ static void binary_value(vpiHandle ref, p_vpi_value vp)
vp->format = vpiBinStrVal;
break;
case vpiDecStrVal: {
unsigned long val = 0;
unsigned count_x = 0, count_z = 0;
case vpiDecStrVal:
vpip_bits_to_dec_str(rfp->bits, rfp->nbits,
buf, sizeof buf, 0);
vp->value.str = buf;
for (unsigned idx = 0 ; idx < rfp->nbits ; idx += 1) {
unsigned nibble = idx/4;
unsigned shift = 2 * (idx%4);
unsigned bit_val = (rfp->bits[nibble] >> shift) & 3;
switch (bit_val) {
case 0:
break;
case 1:
val |= 1 << idx;
break;
case 2:
count_x += 1;
break;
case 3:
count_z += 1;
break;
}
}
if (count_z == rfp->nbits) {
sprintf(buf, "z");
} else if (count_x == rfp->nbits) {
sprintf(buf, "x");
} else if ((count_z > 0) && (count_x == 0)) {
sprintf(buf, "Z");
} else if (count_x > 0) {
sprintf(buf, "X");
} else {
sprintf(buf, "%lu", val);
}
break;
}
vp->value.str = buf;
vp->format = vpiDecStrVal;
break;
case vpiIntVal: {
unsigned val = 0;
@ -438,6 +403,9 @@ vpiHandle vpip_make_dec_const(int value)
/*
* $Log: vpi_const.cc,v $
* Revision 1.11 2002/02/03 01:01:51 steve
* Use Larrys bits-to-decimal-string code.
*
* Revision 1.10 2002/01/31 04:28:17 steve
* Full support for $readmem ranges (Tom Verbeure)
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_priv.h,v 1.27 2002/01/31 04:28:17 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.28 2002/02/03 01:01:51 steve Exp $"
#endif
# include "vpi_user.h"
@ -255,8 +255,22 @@ extern void vpip_set_time_precision(int pres);
extern vpiHandle ipoint_get_scope(vvp_ipoint_t ipt);
extern void functor_set_scope(vpiHandle scope);
/*
* 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)
* lsb first, and the result is written into buf, without overflowing
* nbuf.
*/
extern unsigned vpip_bits_to_dec_str(const unsigned char *bits,
unsigned int nbits,
char *buf, unsigned int nbuf,
int signed_flag);
/*
* $Log: vpi_priv.h,v $
* Revision 1.28 2002/02/03 01:01:51 steve
* Use Larrys bits-to-decimal-string code.
*
* Revision 1.27 2002/01/31 04:28:17 steve
* Full support for $readmem ranges (Tom Verbeure)
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vpi_signal.cc,v 1.32 2002/01/09 03:29:12 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.33 2002/02/03 01:01:51 steve Exp $"
#endif
/*
@ -146,76 +146,21 @@ static void signal_vpiDecStrVal(struct __vpiSignal*rfp, s_vpi_value*vp)
? (rfp->msb - rfp->lsb + 1)
: (rfp->lsb - rfp->msb + 1);
unsigned long val = 0;
unsigned count_x = 0, count_z = 0;
unsigned char*bits = new unsigned char[wid];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, wid-idx-1);
val *= 2;
switch (functor_get(fptr)) {
case 0:
break;
case 1:
val += 1;
break;
case 2:
count_x += 1;
break;
case 3:
count_z += 1;
break;
}
}
if (count_x == wid) {
need_result_buf(2);
result_buf[0] = 'x';
result_buf[1] = 0;
return;
}
if (count_x > 0) {
need_result_buf(2);
result_buf[0] = 'X';
result_buf[1] = 0;
return;
}
if (count_z == wid) {
need_result_buf(2);
result_buf[0] = 'z';
result_buf[1] = 0;
return;
}
if (count_z > 0) {
need_result_buf(2);
result_buf[0] = 'Z';
result_buf[1] = 0;
return;
vvp_ipoint_t fptr = vvp_fvector_get(rfp->bits, idx);
bits[idx] = functor_get(fptr);
}
need_result_buf((wid+2) / 3 + 1);
if (rfp->signed_flag) {
long tmp;
assert(sizeof(tmp) == sizeof(val));
if (val & (1<<(wid-1)) && wid < 8*sizeof(tmp)) {
tmp = -1;
tmp <<= wid;
tmp |= val;
} else {
tmp = val;
}
sprintf(result_buf, "%ld", tmp);
assert(strlen(result_buf) < result_buf_size);
vpip_bits_to_dec_str(bits, wid, result_buf, result_buf_size,
rfp->signed_flag);
} else {
sprintf(result_buf, "%lu", val);
assert(strlen(result_buf) < result_buf_size);
}
delete[]bits;
}
static void signal_vpiStringVal(struct __vpiSignal*rfp, s_vpi_value*vp)
{
char*cp;
@ -587,6 +532,9 @@ vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.33 2002/02/03 01:01:51 steve
* Use Larrys bits-to-decimal-string code.
*
* Revision 1.32 2002/01/09 03:29:12 steve
* String prints of non-round vectors (PR378)
*

201
vvp/vpip_to_dec.cc Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org)
*
* 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
*/
# include "config.h"
# include <stdio.h>
# include <string.h>
# include <limits.h> /* for CHAR_BIT */
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <assert.h>
/* If you are allergic to malloc, you can set a stack memory allocation
* here. Otherwise, malloc() is used for the temporary array, so the
* conversion length is unlimited. */
/* #define MAX_DIGITS 20 */
#ifndef SIZEOF_UNSIGNED_LONG
#define SIZEOF_UNSIGNED_LONG 4
#endif
#if SIZEOF_UNSIGNED_LONG * CHAR_BIT >= 64
#define BDIGITS 9
#define BASE 1000000000
#define BBITS 32
#define BMASK 0xffffffff
#else
#if SIZEOF_UNSIGNED_LONG * CHAR_BIT >= 32
#define BDIGITS 4
#define BASE 10000
#define BBITS 16
#define BMASK 0xffff
#else
#error apparent non-conforming word length
#endif
#endif
#define B_IS0(x) ((x) == 0)
#define B_IS1(x) ((x) == 1)
#define B_ISX(x) ((x) == 2)
#define B_ISZ(x) ((x) == 3)
/* The program works by building a base BASE representation of the number
* in the valv array. BBITS bits of the number can be put in at a time.
* Previous values of each valv element are always less than BASE, the
* input val is less than or equal to 2^BBITS, so (valv[i]<<BBITS)+val
* is guaranteed less than or equal to BASE<<BBITS, which is configured
* less than ULONG_MAX. When this number divided by BASE, to get the amount
* propagated as a "carry" to the next array element, the result is again
* less than or equal to 2^BBITS. BBITS and BASE are configured above
* to depend on the "unsigned long" length of the host, for efficiency.
*/
static inline void shift_in(unsigned long *valv, unsigned int vlen, unsigned long val)
{
unsigned int i;
/* printf("shift in %u\n",val); */
for (i=0; i<vlen; i++) {
val=(valv[i]<<BBITS)+val;
valv[i]=val%BASE;
val=val/BASE;
}
if (val!=0)
fprintf(stderr,"internal error: carry out %lu in " __FILE__ "\n",val);
}
/* Since BASE is a power of ten, conversion of each element of the
* valv array to decimal is easy. sprintf(buf,"%d",v) could be made
* to work, I suppose, but for speed and control I prefer to write
* the steps out longhand.
*/
static inline int write_digits(unsigned long v, char **buf,
unsigned int *nbuf, int zero_suppress)
{
char segment[BDIGITS];
int i;
for (i=BDIGITS-1; i>=0; --i) {
segment[i] = '0' + v%10;
v=v/10;
}
for (i=0; i<BDIGITS; ++i) {
if (!(zero_suppress&=(segment[i]=='0'))) {
*(*buf)++=segment[i]; --(*nbuf);
}
}
return zero_suppress;
}
/* bits[0] is the lsb
* bits[nbits-1] is the msb or sign bit
*/
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 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;
}