1 /*
2  * This file is part of the Alliance CAD System
3  * Copyright (C) Laboratoire LIP6 - D�partement ASIM
4  * Universite Pierre et Marie Curie
5  *
6  * Home page          : http://www-asim.lip6.fr/alliance/
7  * E-mail             : mailto:alliance-users@asim.lip6.fr
8  *
9  * This library is free software; you  can redistribute it and/or modify it
10  * under the terms  of the GNU Library General Public  License as published
11  * by the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * Alliance VLSI  CAD System  is distributed  in the hope  that it  will be
15  * useful, but WITHOUT  ANY WARRANTY; without even the  implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy  of the GNU General Public License along
20  * with the GNU C Library; see the  file COPYING. If not, write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * Purpose : verilog driver, mainly used to enable simulating with Cadence Verilog.
26  * Version : 002
27  * Date    : Jul 1995
28  * Author  : Aldo Mozzi <aldo.mozzi@libero.it>
29  * Modified by Mourad Aberbour in Sept. 1997
30  */
31 
32 #ident "$Id: drive_vlog.c,v 1.3 2012/05/14 14:20:26 alliance Exp $"
33 
34 #include <mut.h>
35 #include <mlo.h>
36 #include <stdlib.h>
37 #include <ctype.h>
38 #include <time.h>
39 #include <string.h>
40 
41 extern char *mvl_vhdlname(); /*see ../mbkvhdl/mbkvhdl/mvl_drive.h*/
42 
43 static char name_buffer[255];
44 static char vec_name_buffer[255];
45 
46 /******************************************************************
47 * function vlg_name: gets a name and returns a legal verilog name *
48 * in name_buffer. Characteres not allowed in a valid verilog name *
49 * are replaced by "_"<ascii code in hex>"_".                      *
50 * If the name is indexed the indexing syntax is translated:       *
51 *     <name><space><number> --> <name>[<number>]                  *
52 ******************************************************************/
vlg_name(name)53 char *vlg_name (name)
54 char *name;
55 {
56 	char *scan_new;
57 	int i, indexed;
58 	static char hextable[] = "0123456789ABCDEF";
59 #ifdef mark_in_out
60 printf ("entering vlg_name %s\n", name);
61 #endif
62 	scan_new = name_buffer;
63 	i = 0;
64 	indexed = 0;
65 	while (*name)
66 	{
67 		if (i != 0 && *name == ' ')
68 		{
69 			*scan_new++ = '[';
70 			indexed = 1;
71 			name++;
72 		}
73 		else
74 		{
75             if (isalpha(*name) || *name == '_' || (((i != 0) && (isdigit(*name))) || *name == '$'))
76 			{
77 				*scan_new = *name++;
78 		/* modif mourad : le 03/12/97
79 			Le driver verilog pour les netlists alliance doit garder les noms de models et des coneecteurs
80 			en minuscule pour une compatibilite avec les cellules ScLib et PadLib exportees vers Cadence.
81 			Les noms de signaux et d'instances peuvent rester tel quel.
82 
83 				if (islower(*scan_new)) *scan_new = toupper(*scan_new);
84 		----*/
85 				if (isupper(*scan_new)) *scan_new = tolower(*scan_new);
86 				scan_new++;
87 			}
88 			else
89 			{
90 				*scan_new++ = '_';
91 				*scan_new++ = hextable[(*name >> 4) & 0x0f];
92 				*scan_new++ = hextable[*name++ & 0x0f];
93 				*scan_new++ = '_';
94 			}
95 		}
96 		++i;
97 	}
98 	if (indexed != 0) *scan_new++ = ']';
99 	*scan_new = '\0';
100 
101 #ifdef mark_in_out
102 printf ("exiting vlg_name %s\n", name_buffer);
103 #endif
104 
105 	return (name_buffer);
106 }
107 
108 
109 /***************************************************************************
110 * function vlg_busname: gets a pointer to a list of connectors and returns *
111 * the next connector name in *name (that points to vec_buffer), the left   *
112 * and right indices of the vector (-1 if signal is a scalar) and the       *
113 * pointer to the next vector as the return value. Performs vectorization   *
114 * of locon names, that are always scalar.                                  *
115 ***************************************************************************/
vlg_busname(pt_list,left,right,name)116 locon_list *vlg_busname(pt_list,left,right,name)
117 locon_list *pt_list;
118 int *left, *right;
119 char **name;
120 {
121 	char *blank_space;
122 	locon_list *ptcon;
123 	char END = 0;
124 
125 #ifdef mark_in_out
126 printf("entering vlg_busname %s\n", pt_list->NAME);
127 #endif
128 
129 	ptcon = pt_list;
130 /* Extract the name and number of an element */
131 	*left = *right = -1;
132 	strcpy(vec_name_buffer, ptcon->NAME);
133 	blank_space = strchr(vec_name_buffer, ' ');
134 	if (blank_space != NULL)
135 	{
136 		*right = atoi(blank_space);
137 		*left = *right;
138 		*blank_space = '\0';
139 
140 		while(END != 1)
141 		{
142 			if(ptcon->NEXT != NULL)
143 			{
144 				blank_space = strchr(ptcon->NEXT->NAME, ' ');
145 				if(blank_space != NULL)
146 				{
147 					*blank_space = '\0';
148 					if(!strcmp(vec_name_buffer, ptcon->NEXT->NAME))
149 					{
150 						*right = atoi(blank_space + 1);
151 						ptcon = ptcon->NEXT;
152 					}
153 					else END = 1;
154 					*blank_space = ' ';
155 				}
156 				else END = 1;
157 			}
158 			else END = 1;
159 		}
160 	}
161 	*name = vec_name_buffer;
162 
163 #ifdef mark_in_out
164 printf("exiting vlg_busname %s\n", *name);
165 #endif
166 
167 	return(ptcon->NEXT);
168 }
169 
170 
171 /*******************************************************************************
172 * function vlogsavelofig                                                       *
173 *******************************************************************************/
174 
vlogsavelofig(ptfig)175 void vlogsavelofig(ptfig)
176 lofig_list *ptfig;
177 {
178 	loins_list *ptins = NULL;
179 	locon_list *ptcon = NULL;
180 	locon_list *ptscan = NULL;
181 	losig_list *ptsig = NULL;
182 	FILE *ptfile;
183 	time_t clock;
184 	int flag, left, right, i, first;
185 	char *name;
186 	char *sig_name;
187 	char direc_flag;
188 	chain_list *sig_list = NULL;
189 
190 #ifdef mark_in_out
191 printf("entering vlogsavelofig\n");
192 #endif
193 
194 	if ((ptfile = mbkfopen(ptfig->NAME, OUT_LO, WRITE_TEXT)) == NULL)
195 	{
196 		(void)fprintf(stderr, "*** mbk error ***\n");
197 		(void)fprintf(stderr, "cannot open file %s.%s\n", ptfig->NAME, OUT_LO);
198 		EXIT(1);
199 	}
200 
201 	time (&clock);
202 	(void) fprintf (ptfile,"// Verilog structural description generated from `%s`\n", ptfig->NAME);
203 	(void) fprintf (ptfile,"// Date : %s\n\n", ctime(&clock));
204 
205 /*********************
206 * Module declaration *
207 *********************/
208 	(void) fprintf (ptfile,"// Module Declaration.\n\n");
209 	(void) fprintf (ptfile,"module %s (\n", vlg_name(ptfig->NAME));
210 
211 	if (ptfig->LOCON != NULL) {
212 	ptfig->LOCON = (struct locon *) reverse ((chain_list *)ptfig->LOCON);
213 	/*list inputs without indices first*/
214 	ptcon = ptfig->LOCON;
215 	flag = 0;
216 	while (ptcon != NULL)
217 	{
218 		if (ptcon->DIRECTION == 'I')
219 		{
220 			ptcon = vlg_busname(ptcon,&left,&right,&name);
221 			/*
222 			printf("list input %s\n", name);
223 			*/
224 			if (flag == 4)
225 			{
226 				(void)fprintf(ptfile, ",\n");
227 				flag = 0;
228 			}
229 			if (flag != 0)
230 				(void)fprintf(ptfile, ", ");
231 			(void)fprintf(ptfile, "%s", vlg_name(name));
232 			++flag;
233 			}
234 			else ptcon = ptcon->NEXT;
235 		}
236 		/*then list I/Os*/
237 		ptcon = ptfig->LOCON;
238 		while (ptcon != NULL)
239 		{
240 			direc_flag = ptcon->DIRECTION;
241 			if ((direc_flag != 'I') && (direc_flag != 'O') && (direc_flag != 'B'))
242 			{
243 				ptcon = vlg_busname(ptcon,&left,&right,&name);
244 				/*
245 				printf("list input-output %s %c\n", name, direc_flag);
246 				*/
247 				if (flag == 4)
248 				{
249 					(void)fprintf(ptfile, ",\n");
250 					flag = 0;
251 				}
252 				if (flag != 0)
253 					(void)fprintf(ptfile, ", ");
254 				(void)fprintf(ptfile, "%s", vlg_name(name));
255 				++flag;
256 			}
257 			else ptcon = ptcon->NEXT;
258 		}
259 		/*then list outputs*/
260 		ptcon = ptfig->LOCON;
261 		while (ptcon != NULL)
262 		{
263 			direc_flag = ptcon->DIRECTION;
264 			if ((direc_flag == 'O') || (direc_flag == 'B'))
265 			{
266 				ptcon = vlg_busname(ptcon,&left,&right,&name);
267 				/*
268 				printf("list output %s\n", name);
269 				*/
270 				if (flag == 4)
271 				{
272 					(void)fprintf(ptfile, ",\n");
273 					flag = 0;
274 				}
275 				if (flag != 0)
276 					(void)fprintf(ptfile, ", ");
277 				(void)fprintf(ptfile, "%s", vlg_name(name));
278 				++flag;
279 			}
280 			else ptcon = ptcon->NEXT;
281 		}
282 		(void) fprintf(ptfile, ");\n\n\n");
283 
284 		(void) fprintf (ptfile,"// Declaration of external signals.\n\n");
285 		/*now list inputs and outputs with indices; bidirs are both listed as
286 		inputs and outputs*/
287 		ptcon = ptfig->LOCON;
288 		while (ptcon != NULL)
289 		{
290 			direc_flag = ptcon->DIRECTION;
291 			ptcon = vlg_busname(ptcon, &left, &right, &name);
292 			if ((direc_flag != 'O') && (direc_flag != 'B'))
293 			{
294 				if (left != -1)
295 					(void)fprintf(ptfile, "input [%d:%d] %s;\n", left, right, vlg_name(name));
296 				else
297 					(void)fprintf(ptfile, "input %s;\n", vlg_name(name));
298 			}
299 			if (direc_flag != 'I')
300 			{
301 				if (left != -1)
302 					(void)fprintf(ptfile, "output [%d:%d] %s;\n", left, right, vlg_name(name));
303 				else
304 					(void)fprintf(ptfile, "output %s;\n", vlg_name(name));
305 			}
306 		}
307 	}
308 	(void) fprintf(ptfile, "\n\n");
309 
310 	ptfig->LOCON = (struct locon *) reverse ((chain_list *)ptfig->LOCON);
311 
312 /***********************************************************
313 * End of module declarations, now declare internal signals *
314 ***********************************************************/
315 
316 	(void) fprintf(ptfile, "// Declaration of internal signals.\n\n");
317 	ptsig = ptfig->LOSIG;
318 	while(ptsig != NULL)
319 	{
320 		if (ptsig->TYPE == 'I')
321 		{
322 			(void) fprintf (ptfile, "wire %s;\n", vlg_name(getsigname(ptsig)));
323 		}
324 		ptsig = ptsig->NEXT;
325 	}
326 
327 /*********************************************************
328 * End of signal declarations, now comes the real netlist *
329 *********************************************************/
330 
331 	(void) fprintf(ptfile, "\n\n// Declaration of instances.\n\n");
332 	ptfig->LOINS = (struct loins *) reverse ((chain_list *)ptfig->LOINS);
333 	for (ptins = ptfig->LOINS; ptins; ptins = ptins->NEXT)
334 	{
335 		/* name the module name and the instance name */
336 		(void) fprintf (ptfile, "%s ", vlg_name(ptins->FIGNAME));
337 		(void) fprintf (ptfile, "i_%s (\n  ", vlg_name(ptins->INSNAME));
338 		ptcon = ptins->LOCON;
339 		while(ptcon != NULL)
340 		{
341 			vlg_busname(ptcon, &left, &right, &name);
342 			(void) fprintf (ptfile, ".%s(",vlg_name(name));
343 			if(left != -1)
344 			{
345 				/* The connected signals are bused */
346 				for(i = abs(left - right); i >= 0; i--)
347 				{
348 					ptsig = ptcon->SIG;
349 					if (ptsig->TYPE == 'I')
350 					{
351 						/* The signal is internal */
352 						sig_name = namealloc(mvl_vhdlname(getsigname(ptsig)));
353 						sig_list = addchain(sig_list,(char *)sig_name);
354 					}
355 					else
356 					{
357 						/* The signal is external */
358 						for (ptscan = ptfig->LOCON ; ptscan ; ptscan = ptscan->NEXT)
359 						{
360 							if (ptscan->SIG == ptsig)
361 							break;
362 						}
363 						if (ptscan == NULL)
364 						{
365 							(void) printf("\n*** mbk error *** no external connector  \n");
366 							(void) printf("     driving verilog file %s\n", ptfig->NAME);
367 						}
368 						else
369 						{
370 							sig_name = namealloc(vlg_name(ptscan->NAME));
371 							sig_list = addchain(sig_list,(char *)sig_name);
372 						}
373 					}
374 					if(i > 0)
375 						ptcon = ptcon->NEXT;
376 				}
377 				first = 1;
378 				while(sig_list != NULL)
379 				{
380 					if(first!=1)
381 					{
382 						(void)fprintf(ptfile,"& %s",(char *)(sig_list->DATA));
383 					}
384 					else
385 					{
386 						(void)fprintf(ptfile,"%s",(char *)(sig_list->DATA));
387 						first = 0;
388 					}
389 					sig_list = sig_list->NEXT;
390 				}
391 			}
392 			else
393 			{
394 				/* The connected signals is simple */
395 				ptsig = ptcon->SIG;
396 				if (ptsig->TYPE == 'I')
397 				{
398 					(void) fprintf(ptfile, "%s", vlg_name (getsigname(ptsig)));
399 				}
400 				else
401 				{
402 					for (ptscan = ptfig->LOCON ; ptscan ; ptscan = ptscan->NEXT)
403 					{
404 						if (ptscan->SIG == ptsig) break;
405 					}
406 					if (ptscan == NULL)
407 					{
408 						(void) printf("\n*** mbk error *** no external connector  \n");
409 						(void) printf("     driving verilog file %s\n", ptfig->NAME);
410 					}
411 					else
412 					{
413 						(void) fprintf(ptfile, "%s", vlg_name(ptscan->NAME));
414 					}
415 				}
416 			}
417 			if (ptcon->NEXT != NULL)
418 				(void) fprintf (ptfile, "),");
419 			ptcon = ptcon->NEXT;
420 		}
421 		(void) fprintf(ptfile, "));\n");
422 	}
423 	ptfig->LOINS = (struct loins *) reverse ((chain_list *)ptfig->LOINS);
424 	(void) fprintf(ptfile, "endmodule\n");
425 	(void) fclose  (ptfile);
426 }
427