1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: vhdlnetlisp.c
6  * NETLISP Code Generator for the VHDL front-end compiler
7  * Written by: Andrew R. Kostiuk, Queen's University
8  * Modified by: Steven M. Rubin, Static Free Software
9  *
10  * Copyright (c) 2000 Static Free Software.
11  *
12  * Electric(tm) is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Electric(tm) is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Electric(tm); see the file COPYING.  If not, write to
24  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25  * Boston, Mass 02111-1307, USA.
26  *
27  * Static Free Software
28  * 4119 Alpine Road
29  * Portola Valley, California 94028
30  * info@staticfreesoft.com
31  */
32 
33 #include "config.h"
34 #if VHDLTOOL
35 
36 #include "global.h"
37 #include "vhdl.h"
38 #include "usr.h"
39 
40 extern INTBIG		vhdl_externentities, vhdl_warnflag, vhdl_target;
41 extern DBUNITS		*vhdl_units;
42 extern SYMBOLLIST	*vhdl_gsymbols;
43 static IDENTTABLE	*vhdl_ident_ground, *vhdl_ident_power;
44 static DBINTERFACE	*vhdl_top_interface;
45 
46 /* prototypes for local routines */
47 static void vhdl_gennet_interface(DBINTERFACE*, CHAR*);
48 static void vhdl_gennet_aport(void*, DBNAME*);
49 
50 /*
51 Module:  vhdl_gennet
52 ------------------------------------------------------------------------
53 Description:
54 	Generate ALS target output for the created database.  Assume
55 	database is semantically correct.
56 ------------------------------------------------------------------------
57 Calling Sequence:  vhdl_gennet();
58 ------------------------------------------------------------------------
59 */
vhdl_gennet(INTBIG target)60 void vhdl_gennet(INTBIG target)
61 {
62 	DBINTERFACE *interfacef;
63 	UNRESLIST *ulist;
64 	Q_UNUSED( target );
65 
66 	vhdl_freeunresolvedlist(&vhdl_unresolved_list);
67 	vhdl_ident_ground = vhdl_findidentkey(x_("ground"));
68 	vhdl_ident_power = vhdl_findidentkey(x_("power"));
69 
70 	/* print file header */
71 	vhdl_printoneline(x_(";*************************************************"));
72 	vhdl_printoneline(x_(";  RNL Netlisp file"));
73 	vhdl_printoneline(x_(";"));
74 	if ((us_useroptions&NODATEORVERSION) == 0)
75 		vhdl_printoneline(x_(";  File Creation:    %s"), timetostring(getcurrenttime()));
76 	vhdl_printoneline(x_(";-------------------------------------------------"));
77 	vhdl_print(x_("(load \"library.net\")"));
78 
79 	/* determine top level cell which must be renamed main */
80 	vhdl_top_interface = vhdl_findtopinterface(vhdl_units);
81 	if (vhdl_top_interface == NULL)
82 	{
83 		ttyputmsg(x_("ERROR - Cannot find top level interface."));
84 	} else
85 	{
86 		/* clear written flag on all interfaces */
87 		for (interfacef = vhdl_units->interfaces; interfacef != NULL;
88 			interfacef = interfacef->next)
89 		{
90 			interfacef->flags &= ~ENTITY_WRITTEN;
91 		}
92 		vhdl_gennet_interface(vhdl_top_interface, x_("main"));
93 	}
94 
95 	/* print closing line of output file */
96 	vhdl_printoneline(x_(";********* End of netlist file *******************"));
97 
98 	/* print unresolved reference list is not empty */
99 	if (vhdl_unresolved_list)
100 	{
101 		ttyputmsg(_("*****  UNRESOLVED REFERENCES *****"));
102 		for (ulist = vhdl_unresolved_list; ulist != NULL; ulist = ulist->next)
103 			if (ulist->numref > 0)
104 				ttyputmsg(_("%s, %ld time(s)"), ulist->interfacef->string, ulist->numref);
105 	}
106 }
107 
108 /*
109 Module:  vhdl_gennet_interface
110 ------------------------------------------------------------------------
111 Description:
112 	Recursively generate the netlisp description for the specified model
113 	by first generating the lowest interface instantiation and working
114 	back to the top (i.e. bottom up).
115 ------------------------------------------------------------------------
116 Calling Sequence:  vhdl_gennet_interface(interfacef, name);
117 
118 Name		Type			Description
119 ----		----			-----------
120 interfacef	*DBINTERFACE	Pointer to interface.
121 name		*char			Pointer to string name of interface.
122 ------------------------------------------------------------------------
123 */
vhdl_gennet_interface(DBINTERFACE * interfacef,CHAR * name)124 void vhdl_gennet_interface(DBINTERFACE *interfacef, CHAR *name)
125 {
126 	DBINSTANCE *inst;
127 	SYMBOLTREE *symbol;
128 	DBPORTLIST *port;
129 	DBAPORTLIST *aport;
130 	INTBIG generic, power_flag, ground_flag, i;
131 	IDENTTABLE *ident;
132 	DBINDEXRANGE *irange;
133 	DBDISCRETERANGE *drange;
134 	DBNAMELIST *cat;
135 	DBSIGNALS *signal;
136 	CHAR temp[30];
137 	REGISTER void *infstr;
138 
139 	/* go through interface's architectural body and call generate interfaces*/
140 	/* for any interface called by an instance which has not been already */
141 	/* generated */
142 
143 	/* check written flag */
144 	if (interfacef->flags & ENTITY_WRITTEN) return;
145 
146 	/* set written flag */
147 	interfacef->flags |= ENTITY_WRITTEN;
148 
149 	/* check all instants of corresponding architectural body */
150 	/* and write if non-primitive instances */
151 	if (interfacef->bodies && interfacef->bodies->statements)
152 	{
153 		for (inst = interfacef->bodies->statements->instances; inst != NULL; inst = inst->next)
154 		{
155 			symbol = vhdl_searchsymbol(inst->compo->name, vhdl_gsymbols);
156 			if (symbol == NULL)
157 			{
158 				if (vhdl_externentities)
159 				{
160 					if (vhdl_warnflag)
161 					{
162 						ttyputmsg(_("WARNING - interface %s not found, assumed external."),
163 							inst->compo->name->string);
164 					}
165 					vhdl_unresolved(inst->compo->name, &vhdl_unresolved_list);
166 				} else
167 				{
168 					ttyputmsg(_("ERROR - interface %s not found."), inst->compo->name->string);
169 				}
170 				continue;
171 			} else if (symbol->pointer == NULL)
172 			{
173 				/* Should have gate entity */
174 				/* should be automatically added at end of .net file */
175 				/* EMPTY */
176 			} else
177 			{
178 				vhdl_gennet_interface((DBINTERFACE *)symbol->pointer, inst->compo->name->string);
179 			}
180 		}
181 	}
182 
183 	/* write this interface */
184 	generic = 0;
185 	power_flag = ground_flag = FALSE;
186 	infstr = initinfstr();
187 	if (interfacef == vhdl_top_interface) addstringtoinfstr(infstr, x_("(node ")); else
188 	{
189 		addstringtoinfstr(infstr, x_("(macro "));
190 		addstringtoinfstr(infstr, name);
191 		addstringtoinfstr(infstr, x_("("));
192 	}
193 
194 	/* write port list of interface */
195 	for (port = interfacef->ports; port != NULL; port = port->next)
196 	{
197 		if (port->type == NULL || port->type->type == DBTYPE_SINGLE)
198 		{
199 			addstringtoinfstr(infstr, x_(" "));
200 			addstringtoinfstr(infstr, port->name->string);
201 		} else
202 		{
203 			irange = (DBINDEXRANGE *)port->type->pointer;
204 			drange = irange->drange;
205 			if (drange->start > drange->end)
206 			{
207 				for (i = drange->start; i >= drange->end; i--)
208 				{
209 					addstringtoinfstr(infstr, x_(" "));
210 					addstringtoinfstr(infstr, port->name->string);
211 					if (vhdl_target == TARGET_RSIM) (void)esnprintf(temp, 30, x_("_%ld"), i); else
212 						(void)esnprintf(temp, 30, x_("[%ld]"), i);
213 					addstringtoinfstr(infstr, temp);
214 				}
215 			} else
216 			{
217 				for (i = drange->start; i <= drange->end; i++)
218 				{
219 					addstringtoinfstr(infstr, x_(" "));
220 					addstringtoinfstr(infstr, port->name->string);
221 					if (vhdl_target == TARGET_RSIM) (void)esnprintf(temp, 30, x_("_%ld"), i); else
222 						(void)esnprintf(temp, 30, x_("[%ld]"), i);
223 					addstringtoinfstr(infstr, temp);
224 				}
225 			}
226 		}
227 	}
228 	addstringtoinfstr(infstr, x_(")"));
229 	vhdl_print(returninfstr(infstr));
230 
231 	/* Write out local node definitions */
232 	infstr = initinfstr();
233 	if (interfacef == vhdl_top_interface) addstringtoinfstr(infstr, x_("(node open_s"));
234 		else addstringtoinfstr(infstr, x_("(local open_s"));
235 	if (interfacef->bodies && interfacef->bodies->declare)
236 	{
237 		for (signal = interfacef->bodies->declare->bodysignals; signal; signal = signal->next)
238 		{
239 			if (signal->type == NULL || signal->type->type == DBTYPE_SINGLE)
240 			{
241 				addstringtoinfstr(infstr, x_(" "));
242 				addstringtoinfstr(infstr, signal->name->string);
243 			} else
244 			{
245 				irange = (DBINDEXRANGE *)signal->type->pointer;
246 				drange = irange->drange;
247 				if (drange->start > drange->end)
248 				{
249 					for (i = drange->start; i >= drange->end; i--)
250 					{
251 						addstringtoinfstr(infstr, x_(" "));
252 						addstringtoinfstr(infstr, signal->name->string);
253 						if (vhdl_target == TARGET_RSIM) (void)esnprintf(temp, 30, x_("_%ld"), i); else
254 							(void)esnprintf(temp, 30, x_("[%ld]"), i);
255 						addstringtoinfstr(infstr, temp);
256 					}
257 				} else
258 				{
259 					for (i = drange->start; i <= drange->end; i++)
260 					{
261 						addstringtoinfstr(infstr, x_(" "));
262 						addstringtoinfstr(infstr, signal->name->string);
263 						if (vhdl_target == TARGET_RSIM) (void)esnprintf(temp, 30, x_("_%ld"), i); else
264 							(void)esnprintf(temp, 30, x_("[%ld]"), i);
265 						addstringtoinfstr(infstr, temp);
266 					}
267 				}
268 			}
269 		}
270 	}
271 	addstringtoinfstr(infstr, x_(")"));
272 	vhdl_print(returninfstr(infstr));
273 
274 	/* write all instances */
275 	if (interfacef->bodies && interfacef->bodies->statements)
276 	{
277 		for (inst = interfacef->bodies->statements->instances; inst != NULL; inst = inst->next)
278 		{
279 			infstr = initinfstr();
280 			addstringtoinfstr(infstr, x_("("));
281 			addstringtoinfstr(infstr, inst->compo->name->string);
282 			addstringtoinfstr(infstr, x_(" "));
283 
284 			/* print instance port list */
285 			for (aport = inst->ports; aport != NULL; aport = aport->next)
286 			{
287 				if (aport->name)
288 				{
289 					if (aport->name->type == DBNAME_CONCATENATED)
290 					{
291 						/* concatenated name */
292 						for (cat = (DBNAMELIST *)aport->name->pointer; cat; cat = cat->next)
293 						{
294 							ident = cat->name->name;
295 							if (ident == vhdl_ident_power) power_flag = TRUE; else
296 								if (ident == vhdl_ident_ground) ground_flag = TRUE;
297 							vhdl_gennet_aport(infstr, cat->name);
298 						}
299 					} else
300 					{
301 						ident = aport->name->name;
302 						if (ident == vhdl_ident_power) power_flag = TRUE; else
303 							if (ident == vhdl_ident_ground) ground_flag = TRUE;
304 						vhdl_gennet_aport(infstr, aport->name);
305 					}
306 				} else
307 				{
308 					/* "Open" port connection */
309 					/* check if formal port is of array type */
310 					if (aport->port->type && aport->port->type->type == DBTYPE_ARRAY)
311 					{
312 						irange = (DBINDEXRANGE *)aport->port->type->pointer;
313 						drange = irange->drange;
314 						if (drange->start > drange->end)
315 						{
316 							for (i = drange->start; i >= drange->end; i--)
317 							{
318 								addstringtoinfstr(infstr, x_(" open_s."));
319 								(void)esnprintf(temp, 30, x_("%ld"), generic++);
320 								addstringtoinfstr(infstr, temp);
321 							}
322 						} else
323 						{
324 							for (i = drange->start; i <= drange->end; i++)
325 							{
326 								addstringtoinfstr(infstr, x_(" open_s."));
327 								(void)esnprintf(temp, 30, x_("%ld"), generic++);
328 								addstringtoinfstr(infstr, temp);
329 							}
330 						}
331 					} else
332 					{
333 						addstringtoinfstr(infstr, x_(" open_s."));
334 						(void)esnprintf(temp, 30, x_("%ld"), generic++);
335 						addstringtoinfstr(infstr, temp);
336 					}
337 				}
338 			}
339 			addstringtoinfstr(infstr, x_(")"));
340 			vhdl_print(returninfstr(infstr));
341 		}
342 	}
343 
344 	/* check for power and ground flags */
345 	if (power_flag)
346 	{
347 		vhdl_print(x_("(connect power vdd)"));
348 	} else if (ground_flag)
349 	{
350 		vhdl_print(x_("(connect ground gnd)"));
351 	}
352 	if (interfacef != vhdl_top_interface) vhdl_print(x_(")"));
353 }
354 
355 /*
356 Module:  vhdl_gennet_aport
357 ------------------------------------------------------------------------
358 Description:
359 	Add the actual port for a single name to the infinite string.
360 ------------------------------------------------------------------------
361 Calling Sequence:  vhdl_gennet_aport(name);
362 
363 Name		Type		Description
364 ----		----		-----------
365 name		*DBNAME		Pointer to single name.
366 ------------------------------------------------------------------------
367 */
vhdl_gennet_aport(void * infstr,DBNAME * name)368 void vhdl_gennet_aport(void *infstr, DBNAME *name)
369 {
370 	DBINDEXRANGE *irange;
371 	DBDISCRETERANGE *drange;
372 	INTBIG i;
373 	CHAR temp[30];
374 
375 	if (name->type == DBNAME_INDEXED)
376 	{
377 		addstringtoinfstr(infstr, x_(" "));
378 		addstringtoinfstr(infstr, name->name->string);
379 		if (vhdl_target == TARGET_RSIM)
380 			(void)esnprintf(temp, 30, x_("_%ld"), ((DBEXPRLIST *)(name->pointer))->value); else
381 				(void)esnprintf(temp, 30, x_("[%ld]"), ((DBEXPRLIST *)(name->pointer))->value);
382 		addstringtoinfstr(infstr, temp);
383 	} else
384 	{
385 		if (name->dbtype && name->dbtype->type == DBTYPE_ARRAY)
386 		{
387 			irange = (DBINDEXRANGE *)name->dbtype->pointer;
388 			drange = irange->drange;
389 			if (drange->start > drange->end)
390 			{
391 				for (i = drange->start; i >= drange->end; i--)
392 				{
393 					addstringtoinfstr(infstr, x_(" "));
394 					addstringtoinfstr(infstr, name->name->string);
395 					if (vhdl_target == TARGET_RSIM) (void)esnprintf(temp, 30, x_("_%ld"), i); else
396 						(void)esnprintf(temp, 30, x_("[%ld]"), i);
397 					addstringtoinfstr(infstr, temp);
398 				}
399 			} else
400 			{
401 				for (i = drange->start; i <= drange->end; i++)
402 				{
403 					addstringtoinfstr(infstr, x_(" "));
404 					addstringtoinfstr(infstr, name->name->string);
405 					if (vhdl_target == TARGET_RSIM) (void)esnprintf(temp, 30, x_("_%ld"), i); else
406 						(void)esnprintf(temp, 30, x_("[%ld]"), i);
407 					addstringtoinfstr(infstr, temp);
408 				}
409 			}
410 		} else
411 		{
412 			addstringtoinfstr(infstr, x_(" "));
413 			addstringtoinfstr(infstr, name->name->string);
414 		}
415 	}
416 }
417 
418 #endif  /* VHDLTOOL - at top */
419