1 /*
2 * Copyright (c) Tony Bybell 2001-2010
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 */
9
10 #include <config.h>
11 #include "globals.h"
12 #include <stdio.h>
13
14 #ifndef _MSC_VER
15 #include <unistd.h>
16 #ifndef __MINGW32__
17 #include <sys/mman.h>
18 #endif
19 #else
20 #include <windows.h>
21 #endif
22
23 #include <fcntl.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include "symbol.h"
29 #include "vcd.h"
30 #include "lxt.h"
31 #include "bsearch.h"
32 #include "hierpack.h"
33
34 #ifdef _WAVE_HAVE_JUDY
35 #include <Judy.h>
36 #endif
37
38 /*
39 * s_selected accessors
40 */
41 #ifdef _WAVE_HAVE_JUDY
42
get_s_selected(struct symbol * s)43 char get_s_selected(struct symbol *s)
44 {
45 int rc = Judy1Test(GLOBALS->s_selected, (Word_t)s, PJE0);
46
47 return(rc);
48 }
49
set_s_selected(struct symbol * s,char value)50 char set_s_selected(struct symbol *s, char value)
51 {
52 if(value)
53 {
54 Judy1Set ((Pvoid_t)&GLOBALS->s_selected, (Word_t)s, PJE0);
55 }
56 else
57 {
58 Judy1Unset ((Pvoid_t)&GLOBALS->s_selected, (Word_t)s, PJE0);
59 }
60
61 return(value);
62 }
63
destroy_s_selected(void)64 void destroy_s_selected(void)
65 {
66 Judy1FreeArray(&GLOBALS->s_selected, PJE0);
67
68 GLOBALS->s_selected = NULL;
69 }
70
71 #else
72
get_s_selected(struct symbol * s)73 char get_s_selected(struct symbol *s)
74 {
75 return(s->s_selected);
76 }
77
set_s_selected(struct symbol * s,char value)78 char set_s_selected(struct symbol *s, char value)
79 {
80 return((s->s_selected = value));
81 }
82
destroy_s_selected(void)83 void destroy_s_selected(void)
84 {
85 /* nothing */
86 }
87
88 #endif
89
90
91 /*
92 * hash create/destroy
93 */
sym_hash_initialize(void * g)94 void sym_hash_initialize(void *g)
95 {
96 #ifdef _WAVE_HAVE_JUDY
97 ((struct Global *)g)->sym_judy = NULL;
98 #else
99 ((struct Global *)g)->sym_hash=(struct symbol **)calloc_2(SYMPRIME,sizeof(struct symbol *));
100 #endif
101 }
102
103
sym_hash_destroy(void * g)104 void sym_hash_destroy(void *g)
105 {
106 struct Global *gg = (struct Global *)g;
107
108 #ifdef _WAVE_HAVE_JUDY
109
110 JudySLFreeArray(&gg->sym_judy, PJE0);
111 gg->sym_judy = NULL;
112
113 #else
114
115 if(gg->sym_hash)
116 {
117 free_2(gg->sym_hash); gg->sym_hash = NULL;
118 }
119
120 #endif
121 }
122
123
124 /*
125 * Generic hash function for symbol names...
126 */
hash(char * s)127 int hash(char *s)
128 {
129 #ifndef _WAVE_HAVE_JUDY
130 char *p;
131 char ch;
132 unsigned int h=0, h2=0, pos=0, g;
133 for(p=s;*p;p++)
134 {
135 ch=*p;
136 h2<<=3;
137 h2-=((unsigned int)ch+(pos++)); /* this handles stranded vectors quite well.. */
138
139 h=(h<<4)+ch;
140 if((g=h&0xf0000000))
141 {
142 h=h^(g>>24);
143 h=h^g;
144 }
145 }
146
147 h^=h2; /* combine the two hashes */
148 GLOBALS->hashcache=h%SYMPRIME;
149 #else
150 (void)s;
151 #endif
152 return(GLOBALS->hashcache);
153 }
154
155
156 /*
157 * add symbol to table. no duplicate checking
158 * is necessary as aet's are "correct."
159 */
symadd(char * name,int hv)160 struct symbol *symadd(char *name, int hv)
161 {
162 struct symbol *s=(struct symbol *)calloc_2(1,sizeof(struct symbol));
163
164 #ifdef _WAVE_HAVE_JUDY
165 (void)hv;
166
167 PPvoid_t PPValue = JudySLIns(&GLOBALS->sym_judy, (uint8_t *)name, PJE0);
168 *((struct symbol **)PPValue) = s;
169
170 #else
171
172 strcpy(s->name=(char *)malloc_2(strlen(name)+1),name);
173 s->sym_next=GLOBALS->sym_hash[hv];
174 GLOBALS->sym_hash[hv]=s;
175
176 #endif
177 return(s);
178 }
179
symadd_name_exists(char * name,int hv)180 struct symbol *symadd_name_exists(char *name, int hv)
181 {
182 struct symbol *s=(struct symbol *)calloc_2(1,sizeof(struct symbol));
183
184 #ifdef _WAVE_HAVE_JUDY
185 (void)hv;
186
187 PPvoid_t PPValue = JudySLIns(&GLOBALS->sym_judy, (uint8_t *)name, PJE0);
188 *((struct symbol **)PPValue) = s;
189
190 s->name = name; /* redundant for now */
191
192 #else
193
194 s->name = name;
195 s->sym_next=GLOBALS->sym_hash[hv];
196 GLOBALS->sym_hash[hv]=s;
197
198 #endif
199
200 return(s);
201 }
202
203 /*
204 * find a slot already in the table...
205 */
symfind_2(char * s,unsigned int * rows_return)206 static struct symbol *symfind_2(char *s, unsigned int *rows_return)
207 {
208 #ifndef _WAVE_HAVE_JUDY
209 int hv;
210 struct symbol *temp;
211 #endif
212
213 if(!GLOBALS->facs_are_sorted)
214 {
215 #ifdef _WAVE_HAVE_JUDY
216 PPvoid_t PPValue = JudySLGet(GLOBALS->sym_judy, (uint8_t *)s, PJE0);
217
218 if(PPValue)
219 {
220 return(*(struct symbol **)PPValue);
221 }
222 #else
223 hv=hash(s);
224 if(!(temp=GLOBALS->sym_hash[hv])) return(NULL); /* no hash entry, add here wanted to add */
225
226 while(temp)
227 {
228 if(!strcmp(temp->name,s))
229 {
230 return(temp); /* in table already */
231 }
232 if(!temp->sym_next) break;
233 temp=temp->sym_next;
234 }
235 #endif
236 return(NULL); /* not found, add here if you want to add*/
237 }
238 else /* no sense hashing if the facs table is built */
239 {
240 struct symbol *sr;
241 DEBUG(printf("BSEARCH: %s\n",s));
242
243 sr = bsearch_facs(s, rows_return);
244 if(sr)
245 {
246 }
247 else
248 {
249 /* this is because . is > in ascii than chars like $ but . was converted to 0x1 on sort */
250 char *s2;
251 int i;
252 int mat;
253
254 #ifndef WAVE_HIERFIX
255 if(!GLOBALS->escaped_names_found_vcd_c_1)
256 {
257 return(sr);
258 }
259 #endif
260
261 if(GLOBALS->facs_have_symbols_state_machine == 0)
262 {
263 if(GLOBALS->escaped_names_found_vcd_c_1)
264 {
265 mat = 1;
266 }
267 else
268 {
269 mat = 0;
270
271 for(i=0;i<GLOBALS->numfacs;i++)
272 {
273 int was_packed = HIER_DEPACK_STATIC;
274 char *hfacname = NULL;
275
276 hfacname = hier_decompress_flagged(GLOBALS->facs[i]->name, &was_packed);
277 s2 = hfacname;
278 while(*s2)
279 {
280 if(*s2 < GLOBALS->hier_delimeter)
281 {
282 mat = 1;
283 break;
284 }
285 s2++;
286 }
287
288 /* if(was_packed) { free_2(hfacname); } ...not needed with HIER_DEPACK_STATIC */
289 if(mat) { break; }
290 }
291 }
292
293 if(mat)
294 { GLOBALS->facs_have_symbols_state_machine = 1; }
295 else
296 { GLOBALS->facs_have_symbols_state_machine = 2; } /* prevent code below from executing */
297 }
298
299 if(GLOBALS->facs_have_symbols_state_machine == 1)
300 {
301 mat = 0;
302 for(i=0;i<GLOBALS->numfacs;i++)
303 {
304 int was_packed = HIER_DEPACK_STATIC;
305 char *hfacname = NULL;
306
307 hfacname = hier_decompress_flagged(GLOBALS->facs[i]->name, &was_packed);
308 if(!strcmp(hfacname, s))
309 {
310 mat = 1;
311 }
312
313 /* if(was_packed) { free_2(hfacname); } ...not needed with HIER_DEPACK_STATIC */
314 if(mat)
315 {
316 sr = GLOBALS->facs[i];
317 break;
318 }
319 }
320 }
321
322 }
323
324 return(sr);
325 }
326 }
327
328
symfind(char * s,unsigned int * rows_return)329 struct symbol *symfind(char *s, unsigned int *rows_return)
330 {
331 struct symbol *s_pnt = symfind_2(s, rows_return);
332
333 if(!s_pnt)
334 {
335 int len = strlen(s);
336 if(len)
337 {
338 char ch = s[len-1];
339 if((ch != ']') && (ch != '}'))
340 {
341 char *s2 = wave_alloca(len + 4);
342 memcpy(s2, s, len);
343 strcpy(s2+len, "[0]"); /* bluespec vs modelsim */
344
345 s_pnt = symfind_2(s2, rows_return);
346 }
347 }
348 }
349
350 return(s_pnt);
351 }
352