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