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