Fix the debugger to finish correctly.
[iverilog.git] / vvp / vpip_to_dec.cc
blob027a462022d8ab703823c38b7fc3912eaade2b0e
1 /*
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)
8 * any later version.
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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: vpip_to_dec.cc,v 1.8 2006/02/21 02:39:27 steve Exp $"
21 #endif
23 # include "config.h"
24 # include "vpi_priv.h"
25 # include <stdio.h>
26 # include <string.h>
27 # include <limits.h> /* for CHAR_BIT */
28 # include <stdlib.h>
29 # include <ctype.h>
30 #ifdef HAVE_MALLOC_H
31 # include <malloc.h>
32 #endif
33 # include <assert.h>
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
42 #define BDIGITS 9
43 #define BASE 1000000000
44 #define BBITS 32
45 #define BMASK 0xffffffff
46 #else
47 #if SIZEOF_UNSIGNED_LONG * CHAR_BIT >= 32
48 #define BDIGITS 4
49 #define BASE 10000
50 #define BBITS 16
51 #define BMASK 0xffff
52 #else
53 #error apparent non-conforming word length
54 #endif
55 #endif
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)
74 unsigned int i;
75 /* printf("shift in %u\n",val); */
76 for (i=0; i<vlen; i++) {
77 val=(valv[i]<<BBITS)+val;
78 valv[i]=val%BASE;
79 val=val/BASE;
81 if (val!=0)
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];
94 int i;
95 for (i=BDIGITS-1; i>=0; --i) {
96 segment[i] = '0' + v%10;
97 v=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,
110 int signed_flag)
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;
120 unsigned long val=0;
121 int comp=0;
122 if (signed_flag) {
123 switch (vec4.value(vec4.size()-1)) {
124 case BIT4_X:
125 count_x += 1;
126 break;
127 case BIT4_Z:
128 count_z += 1;
129 break;
130 case BIT4_1:
131 comp=1;
132 break;
133 case BIT4_0:
134 break;
136 mbits -= 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;
149 } else {
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)) {
156 case BIT4_Z:
157 count_z += 1;
158 break;
159 case BIT4_X:
160 count_x += 1;
161 break;
162 case BIT4_1:
163 if (! comp)
164 val += 1;
165 break;
166 case BIT4_0:
167 if (comp)
168 val += 1;
169 break;
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);
176 val=0;
177 } else {
178 val=val+val;
182 if (count_x == vec4.size()) {
183 len = 1;
184 buf[0] = 'x';
185 buf[1] = 0;
186 } else if (count_x > 0) {
187 len = 1;
188 buf[0] = 'X';
189 buf[1] = 0;
190 } else if (count_z == vec4.size()) {
191 len = 1;
192 buf[0] = 'z';
193 buf[1] = 0;
194 } else if (count_z > 0) {
195 len = 1;
196 buf[0] = 'Z';
197 buf[1] = 0;
198 } else {
199 int i;
200 int zero_suppress=1;
201 if (comp) {
202 *buf++='-';
203 nbuf--;
204 /* printf("-"); */
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;
217 /* printf("\n"); */
218 *buf='\0';
220 /* hold on to the memory, since we expect to be called again. */
221 /* free(valv); */
222 return 0;
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;
236 unsigned long val=0;
237 int comp=0;
238 if (signed_flag) {
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;
242 --mbits;
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;
255 } else {
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);
269 val=0;
270 } else {
271 val=val+val;
275 if (count_x == nbits) {
276 len = 1;
277 buf[0] = 'x';
278 buf[1] = 0;
279 } else if (count_x > 0) {
280 len = 1;
281 buf[0] = 'X';
282 buf[1] = 0;
283 } else if (count_z == nbits) {
284 len = 1;
285 buf[0] = 'z';
286 buf[1] = 0;
287 } else if (count_z > 0) {
288 len = 1;
289 buf[0] = 'Z';
290 buf[1] = 0;
291 } else {
292 int i;
293 int zero_suppress=1;
294 if (comp) {
295 *buf++='-';
296 nbuf--;
297 /* printf("-"); */
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;
310 /* printf("\n"); */
311 *buf='\0';
313 /* hold on to the memory, since we expect to be called again. */
314 /* free(valv); */
315 return 0;
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];
331 else
332 str[idx] = '0';
335 str[slen] = 0;
337 for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
338 vvp_bit4_t val4 = BIT4_0;
340 switch (str[0]) {
341 case '1':
342 case '3':
343 case '5':
344 case '7':
345 case '9':
346 val4 = BIT4_1;
347 break;
350 vec.set_bit(idx, val4);
352 /* Divide the str string by 2 in decimal. */
353 char*cp = str;
354 while (*cp) {
355 unsigned val = cp[0] - '0';
356 if ((val&1) && (cp > str))
357 cp[-1] += 5;
359 cp[0] = '0' + val/2;
360 cp += 1;
365 delete[]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.