2 * Copyright (c) 2002 Larry Doolittle (larry@doolittle.boa.org)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: vpip_to_dec.cc,v 1.8 2006/02/21 02:39:27 steve Exp $"
24 # include "vpi_priv.h"
27 # include <limits.h> /* for CHAR_BIT */
35 /* If you are allergic to malloc, you can set a stack memory allocation
36 * here. Otherwise, malloc() is used for the temporary array, so the
37 * conversion length is unlimited. */
38 /* #define MAX_DIGITS 20 */
41 #if SIZEOF_UNSIGNED_LONG * CHAR_BIT >= 64
43 #define BASE 1000000000
45 #define BMASK 0xffffffff
47 #if SIZEOF_UNSIGNED_LONG * CHAR_BIT >= 32
53 #error apparent non-conforming word length
57 #define B_IS0(x) ((x) == 0)
58 #define B_IS1(x) ((x) == 1)
59 #define B_ISX(x) ((x) == 2)
60 #define B_ISZ(x) ((x) == 3)
62 /* The program works by building a base BASE representation of the number
63 * in the valv array. BBITS bits of the number can be put in at a time.
64 * Previous values of each valv element are always less than BASE, the
65 * input val is less than or equal to 2^BBITS, so (valv[i]<<BBITS)+val
66 * is guaranteed less than or equal to BASE<<BBITS, which is configured
67 * less than ULONG_MAX. When this number divided by BASE, to get the amount
68 * propagated as a "carry" to the next array element, the result is again
69 * less than or equal to 2^BBITS. BBITS and BASE are configured above
70 * to depend on the "unsigned long" length of the host, for efficiency.
72 static inline void shift_in(unsigned long *valv
, unsigned int vlen
, unsigned long val
)
75 /* printf("shift in %u\n",val); */
76 for (i
=0; i
<vlen
; i
++) {
77 val
=(valv
[i
]<<BBITS
)+val
;
82 fprintf(stderr
,"internal error: carry out %lu in " __FILE__
"\n",val
);
85 /* Since BASE is a power of ten, conversion of each element of the
86 * valv array to decimal is easy. sprintf(buf,"%d",v) could be made
87 * to work, I suppose, but for speed and control I prefer to write
88 * the steps out longhand.
90 static inline int write_digits(unsigned long v
, char **buf
,
91 unsigned int *nbuf
, int zero_suppress
)
93 char segment
[BDIGITS
];
95 for (i
=BDIGITS
-1; i
>=0; --i
) {
96 segment
[i
] = '0' + v
%10;
99 for (i
=0; i
<BDIGITS
; ++i
) {
100 if (!(zero_suppress
&=(segment
[i
]=='0'))) {
101 *(*buf
)++=segment
[i
]; --(*nbuf
);
104 return zero_suppress
;
108 unsigned vpip_vec4_to_dec_str(const vvp_vector4_t
&vec4
,
109 char *buf
, unsigned int nbuf
,
112 unsigned int idx
, len
, vlen
;
113 unsigned int mbits
=vec4
.size(); /* number of non-sign bits */
114 unsigned count_x
= 0, count_z
= 0;
115 /* Jump through some hoops so we don't have to malloc/free valv
116 * on every call, and implement an optional malloc-less version. */
117 static unsigned long *valv
=NULL
;
118 static unsigned int vlen_alloc
=0;
123 switch (vec4
.value(vec4
.size()-1)) {
138 assert(mbits
<(UINT_MAX
-92)/28);
139 vlen
= ((mbits
*28+92)/93+BDIGITS
-1)/BDIGITS
;
140 /* printf("vlen=%d\n",vlen); */
142 #define ALLOC_MARGIN 4
143 if (!valv
|| vlen
> vlen_alloc
) {
144 if (valv
) free(valv
);
145 valv
= (unsigned long*)
146 calloc( vlen
+ALLOC_MARGIN
, sizeof (*valv
));
147 if (!valv
) {perror("malloc"); return 0; }
148 vlen_alloc
=vlen
+ALLOC_MARGIN
;
150 memset(valv
,0,vlen
*sizeof(valv
[0]));
153 for (idx
= 0; idx
< mbits
; idx
+= 1) {
154 /* printf("%c ",bits[mbits-idx-1]); */
155 switch (vec4
.value(mbits
-idx
-1)) {
172 if ((mbits
-idx
-1)%BBITS
==0) {
173 /* make negative 2's complement, not 1's complement */
174 if (comp
&& idx
==mbits
-1) ++val
;
175 shift_in(valv
,vlen
,val
);
182 if (count_x
== vec4
.size()) {
186 } else if (count_x
> 0) {
190 } else if (count_z
== vec4
.size()) {
194 } else if (count_z
> 0) {
206 for (i
=vlen
-1; i
>=0; i
--) {
207 zero_suppress
= write_digits(valv
[i
],
208 &buf
,&nbuf
,zero_suppress
);
209 /* printf(",%.4u",valv[i]); */
211 /* Awkward special case, since we don't want to
212 * zero suppress down to nothing at all. The only
213 * way we can still have zero_suppress on in the
214 * comp=1 case is if mbits==0, and therefore vlen==0.
215 * We represent 1'sb1 as "-1". */
216 if (zero_suppress
) *buf
++='0'+comp
;
220 /* hold on to the memory, since we expect to be called again. */
225 unsigned vpip_bits_to_dec_str(const unsigned char *bits
, unsigned int nbits
,
226 char *buf
, unsigned int nbuf
, int signed_flag
)
228 unsigned int idx
, len
, vlen
;
229 unsigned int mbits
=nbits
; /* number of non-sign bits */
230 unsigned count_x
= 0, count_z
= 0;
231 /* Jump through some hoops so we don't have to malloc/free valv
232 * on every call, and implement an optional malloc-less version. */
233 static unsigned long *valv
=NULL
;
234 static unsigned int vlen_alloc
=0;
239 if (B_ISZ(bits
[nbits
-1])) count_z
++;
240 else if (B_ISX(bits
[nbits
-1])) count_x
++;
241 else if (B_IS1(bits
[nbits
-1])) comp
=1;
244 assert(mbits
<(UINT_MAX
-92)/28);
245 vlen
= ((mbits
*28+92)/93+BDIGITS
-1)/BDIGITS
;
246 /* printf("vlen=%d\n",vlen); */
248 #define ALLOC_MARGIN 4
249 if (!valv
|| vlen
> vlen_alloc
) {
250 if (valv
) free(valv
);
251 valv
= (unsigned long*)
252 calloc( vlen
+ALLOC_MARGIN
, sizeof (*valv
));
253 if (!valv
) {perror("malloc"); return 0; }
254 vlen_alloc
=vlen
+ALLOC_MARGIN
;
256 memset(valv
,0,vlen
*sizeof(valv
[0]));
259 for (idx
= 0; idx
< mbits
; idx
+= 1) {
260 /* printf("%c ",bits[mbits-idx-1]); */
261 if (B_ISZ(bits
[mbits
-idx
-1])) count_z
++;
262 else if (B_ISX(bits
[mbits
-idx
-1])) count_x
++;
263 else if (!comp
&& B_IS1(bits
[mbits
-idx
-1])) ++val
;
264 else if ( comp
&& B_IS0(bits
[mbits
-idx
-1])) ++val
;
265 if ((mbits
-idx
-1)%BBITS
==0) {
266 /* make negative 2's complement, not 1's complement */
267 if (comp
&& idx
==mbits
-1) ++val
;
268 shift_in(valv
,vlen
,val
);
275 if (count_x
== nbits
) {
279 } else if (count_x
> 0) {
283 } else if (count_z
== nbits
) {
287 } else if (count_z
> 0) {
299 for (i
=vlen
-1; i
>=0; i
--) {
300 zero_suppress
= write_digits(valv
[i
],
301 &buf
,&nbuf
,zero_suppress
);
302 /* printf(",%.4u",valv[i]); */
304 /* Awkward special case, since we don't want to
305 * zero suppress down to nothing at all. The only
306 * way we can still have zero_suppress on in the
307 * comp=1 case is if mbits==0, and therefore vlen==0.
308 * We represent 1'sb1 as "-1". */
309 if (zero_suppress
) *buf
++='0'+comp
;
313 /* hold on to the memory, since we expect to be called again. */
319 void vpip_dec_str_to_vec4(vvp_vector4_t
&vec
,
320 const char*buf
, bool signed_flag
)
322 /* The str string is the decimal value with the least
323 significant digit first. This loop creates that string by
324 reversing the order of the buf string. For example, if the
325 input is "1234", str gets "4321". */
326 unsigned slen
= strlen(buf
);
327 char*str
= new char[slen
+ 1];
328 for (unsigned idx
= 0 ; idx
< slen
; idx
+= 1) {
329 if (isdigit(buf
[slen
-idx
-1]))
330 str
[idx
] = buf
[slen
-idx
-1];
337 for (unsigned idx
= 0 ; idx
< vec
.size() ; idx
+= 1) {
338 vvp_bit4_t val4
= BIT4_0
;
350 vec
.set_bit(idx
, val4
);
352 /* Divide the str string by 2 in decimal. */
355 unsigned val
= cp
[0] - '0';
356 if ((val
&1) && (cp
> str
))
370 * $Log: vpip_to_dec.cc,v $
371 * Revision 1.8 2006/02/21 02:39:27 steve
372 * Support string values for memory words.
374 * Revision 1.7 2004/10/04 01:11:00 steve
375 * Clean up spurious trailing white space.
377 * Revision 1.6 2002/08/12 01:35:09 steve
378 * conditional ident string using autoconfig.
380 * Revision 1.5 2002/05/17 04:05:38 steve
381 * null terminate the reversed decimal string
383 * Revision 1.4 2002/05/11 04:39:36 steve
384 * Set and get memory words by string value.