FreeCalypso > hg > ueda-linux
comparison ueda/sverp/elaborate.c @ 0:cd92449fdb51
initial import of ueda and ifctf-part-lib from ifctfvax CVS
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 20 Jul 2015 00:24:37 +0000 |
parents | |
children | 7b4f78fcca08 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cd92449fdb51 |
---|---|
1 /* | |
2 * Here we elaborate the hierarchy and create our flat netlist. | |
3 */ | |
4 | |
5 #include <stdio.h> | |
6 #include <strings.h> | |
7 #include "struct.h" | |
8 #include "lexer.h" /* for MAXDIGITS */ | |
9 | |
10 extern char *malloc(); | |
11 | |
12 struct output_net *output_net_head; | |
13 struct output_element *output_element_head; | |
14 int total_good_nets, total_singular_nets, total_null_nets; | |
15 int total_output_elements; | |
16 | |
17 static struct output_net **output_net_tail = &output_net_head; | |
18 static struct output_element **output_element_tail = &output_element_head; | |
19 | |
20 static struct output_net ** | |
21 alloc_mod_net_array(mod) | |
22 struct module_def *mod; | |
23 { | |
24 int total_wires; | |
25 unsigned alloc_size; | |
26 register struct output_net **array; | |
27 | |
28 total_wires = mod->nwires_ports + mod->nwires_internal; | |
29 alloc_size = sizeof(struct output_net *) * total_wires; | |
30 array = (struct output_net **) malloc(alloc_size); | |
31 if (!array) { | |
32 perror("malloc"); | |
33 exit(1); | |
34 } | |
35 return(array); | |
36 } | |
37 | |
38 static struct output_net ** | |
39 alloc_connect_net_array(mod) | |
40 struct module_def *mod; | |
41 { | |
42 register unsigned alloc_size; | |
43 register struct output_net **array; | |
44 | |
45 alloc_size = sizeof(struct output_net *) * mod->nwires_ports; | |
46 array = (struct output_net **) malloc(alloc_size); | |
47 if (!array) { | |
48 perror("malloc"); | |
49 exit(1); | |
50 } | |
51 bzero(array, alloc_size); | |
52 return(array); | |
53 } | |
54 | |
55 static struct output_net * | |
56 create_real_net(hier_prefix, base_name, is_bus, bus_pos) | |
57 char *hier_prefix, *base_name; | |
58 { | |
59 int len; | |
60 register char *buf; | |
61 register struct output_net *net; | |
62 | |
63 len = sizeof(struct output_net) + strlen(hier_prefix) + | |
64 strlen(base_name) + 1; | |
65 if (is_bus) | |
66 len += MAXDIGITS + 2; | |
67 buf = malloc(len); | |
68 if (!buf) { | |
69 perror("malloc"); | |
70 exit(1); | |
71 } | |
72 net = (struct output_net *) buf; | |
73 bzero(net, sizeof(struct output_net)); | |
74 buf += sizeof(struct output_net); | |
75 if (is_bus) | |
76 sprintf(buf, "%s%s[%d]", hier_prefix, base_name, bus_pos); | |
77 else | |
78 sprintf(buf, "%s%s", hier_prefix, base_name); | |
79 net->name = buf; | |
80 *output_net_tail = net; | |
81 output_net_tail = &net->next; | |
82 return(net); | |
83 } | |
84 | |
85 static void | |
86 create_module_nets(mod, hier_prefix, fillp) | |
87 struct module_def *mod; | |
88 char *hier_prefix; | |
89 register struct output_net **fillp; | |
90 { | |
91 register struct module_net_def *nd; | |
92 register int i, incr; | |
93 | |
94 for (nd = mod->nets; nd; nd = nd->next) { | |
95 if (nd->is_port) | |
96 continue; | |
97 if (!nd->is_bus) { | |
98 *fillp++ = create_real_net(hier_prefix, nd->name, 0); | |
99 continue; | |
100 } | |
101 if (nd->bus_msb < nd->bus_lsb) | |
102 incr = 1; | |
103 else | |
104 incr = -1; | |
105 for (i = nd->bus_msb; i != nd->bus_lsb + incr; i += incr) | |
106 *fillp++ = create_real_net(hier_prefix, nd->name, 1, i); | |
107 } | |
108 } | |
109 | |
110 elaborate_module(mod, inst_name, hier_prefix, in_conn_array) | |
111 register struct module_def *mod; | |
112 char *inst_name, *hier_prefix; | |
113 struct output_net **in_conn_array; | |
114 { | |
115 register struct output_net **mod_net_array; | |
116 register struct module_def_subinst *sub; | |
117 | |
118 if (mod->nwires_internal) { | |
119 mod_net_array = alloc_mod_net_array(mod); | |
120 if (mod->nwires_ports) | |
121 bcopy(in_conn_array, mod_net_array, | |
122 sizeof(struct output_net *) * mod->nwires_ports); | |
123 create_module_nets(mod, hier_prefix, | |
124 mod_net_array + mod->nwires_ports); | |
125 } else | |
126 mod_net_array = in_conn_array; | |
127 | |
128 for (sub = mod->subinst; sub; sub = sub->next) | |
129 elaborate_subinst(mod, inst_name, hier_prefix, mod_net_array, | |
130 sub); | |
131 | |
132 if (mod->nwires_internal) | |
133 free(mod_net_array); | |
134 } | |
135 | |
136 static void | |
137 report_connect_conflict(new_inst, ce, offset) | |
138 char *new_inst; | |
139 struct connect_entry *ce; | |
140 int offset; | |
141 { | |
142 register struct module_net_def *port = ce->down_portdef; | |
143 int bus_pos; | |
144 | |
145 if (port->is_bus) { | |
146 offset += ce->down_offset; | |
147 if (port->bus_msb > port->bus_lsb) | |
148 bus_pos = port->bus_msb - offset; | |
149 else | |
150 bus_pos = port->bus_msb + offset; | |
151 fprintf(stderr, | |
152 "elaborating %s: multiple connections to port %s[%d]\n", | |
153 new_inst, port->name, bus_pos); | |
154 } else | |
155 fprintf(stderr, | |
156 "elaborating %s: multiple connections to port %s\n", | |
157 new_inst, port->name); | |
158 exit(1); | |
159 } | |
160 | |
161 static void | |
162 check_connect_conflict(new_inst, ce, conn_array) | |
163 char *new_inst; | |
164 register struct connect_entry *ce; | |
165 register struct output_net **conn_array; | |
166 { | |
167 register int start, i; | |
168 | |
169 start = ce->down_portdef->array_index + ce->down_offset; | |
170 for (i = 0; i < ce->down_width; i++) | |
171 if (conn_array[start + i]) | |
172 report_connect_conflict(new_inst, ce, i); | |
173 } | |
174 | |
175 static struct output_net * | |
176 create_nc_net(mup, old_inst, ce) | |
177 struct module_def *mup; | |
178 char *old_inst; | |
179 struct connect_entry *ce; | |
180 { | |
181 register struct output_net *net; | |
182 | |
183 net = (struct output_net *) malloc(sizeof(struct output_net)); | |
184 if (!net) { | |
185 perror("malloc"); | |
186 exit(1); | |
187 } | |
188 bzero(net, sizeof(struct output_net)); | |
189 net->nc_module_name = mup->name; | |
190 net->nc_module_lineno = ce->src_lineno; | |
191 net->nc_module_inst = old_inst; | |
192 return(net); | |
193 } | |
194 | |
195 static struct output_net * | |
196 process_subinst_connect(mup, sub, old_inst, new_inst, mod_net_array, conn_array) | |
197 struct module_def *mup; | |
198 struct module_def_subinst *sub; | |
199 char *old_inst, *new_inst; | |
200 struct output_net **mod_net_array; | |
201 register struct output_net **conn_array; | |
202 { | |
203 struct output_net *nc_head = 0, **nc_tail = &nc_head; | |
204 register struct connect_entry *ce; | |
205 int start; | |
206 register int i; | |
207 register struct output_net *nc_net; | |
208 | |
209 for (ce = sub->connections; ce; ce = ce->next) { | |
210 check_connect_conflict(new_inst, ce, conn_array); | |
211 if (ce->up_netdef) { | |
212 bcopy(mod_net_array + ce->up_netdef->array_index + | |
213 ce->up_offset, | |
214 conn_array + ce->down_portdef->array_index + | |
215 ce->down_offset, | |
216 sizeof(struct output_net *) * ce->up_width); | |
217 continue; | |
218 } | |
219 /* it's a no-connect */ | |
220 start = ce->down_portdef->array_index + ce->down_offset; | |
221 for (i = 0; i < ce->down_width; i++) { | |
222 nc_net = create_nc_net(mup, old_inst, ce); | |
223 conn_array[start + i] = nc_net; | |
224 *nc_tail = nc_net; | |
225 nc_tail = &nc_net->next; | |
226 } | |
227 } | |
228 return(nc_head); | |
229 } | |
230 | |
231 static void | |
232 report_missing_connect(new_inst, port, offset) | |
233 char *new_inst; | |
234 register struct module_net_def *port; | |
235 int offset; | |
236 { | |
237 int bus_pos; | |
238 | |
239 if (port->is_bus) { | |
240 if (port->bus_msb > port->bus_lsb) | |
241 bus_pos = port->bus_msb - offset; | |
242 else | |
243 bus_pos = port->bus_msb + offset; | |
244 fprintf(stderr, | |
245 "elaborating %s: missing connection to port %s[%d]\n", | |
246 new_inst, port->name, bus_pos); | |
247 } else | |
248 fprintf(stderr, | |
249 "elaborating %s: missing connection to port %s\n", | |
250 new_inst, port->name); | |
251 exit(1); | |
252 } | |
253 | |
254 static void | |
255 check_missing_connect(new_inst, mdown, conn_array) | |
256 char *new_inst; | |
257 struct module_def *mdown; | |
258 struct output_net **conn_array; | |
259 { | |
260 register struct module_net_def *port; | |
261 register struct output_net **connp = conn_array; | |
262 register int i; | |
263 | |
264 for (port = mdown->nets; port; port = port->next) { | |
265 if (!port->is_port) | |
266 return; /* all ports are upfront */ | |
267 if (!port->is_bus) { | |
268 if (!*connp++) | |
269 report_missing_connect(new_inst, port, 0); | |
270 continue; | |
271 } | |
272 for (i = 0; i < port->bus_width; i++) | |
273 if (!*connp++) | |
274 report_missing_connect(new_inst, port, i); | |
275 } | |
276 } | |
277 | |
278 static void | |
279 report_bad_nc_net(net) | |
280 register struct output_net *net; | |
281 { | |
282 fprintf(stderr, | |
283 "error: NC pseudo-net created at module %s line %d inst %s goes to more than one pin\n", | |
284 net->nc_module_name, net->nc_module_lineno, | |
285 net->nc_module_inst); | |
286 exit(1); | |
287 } | |
288 | |
289 static void | |
290 check_nc_nets(head) | |
291 struct output_net *head; | |
292 { | |
293 register struct output_net *net; | |
294 | |
295 for (net = head; net; net = net->next) | |
296 if (net->npoints > 1) | |
297 report_bad_nc_net(net); | |
298 } | |
299 | |
300 elaborate_subinst(mup, inst_name, hier_prefix, mod_net_array, sub) | |
301 struct module_def *mup; | |
302 char *inst_name, *hier_prefix; | |
303 struct output_net **mod_net_array; | |
304 struct module_def_subinst *sub; | |
305 { | |
306 char *new_inst, *new_prefix; | |
307 struct module_def *mdown = sub->submod_def; | |
308 struct output_net **conn_array, *nc_nets; | |
309 | |
310 new_inst = malloc(strlen(hier_prefix) + strlen(sub->inst_name) + 1); | |
311 if (!new_inst) { | |
312 perror("malloc"); | |
313 exit(1); | |
314 } | |
315 sprintf(new_inst, "%s%s", hier_prefix, sub->inst_name); | |
316 if (mdown->nports) { | |
317 conn_array = alloc_connect_net_array(mdown); | |
318 nc_nets = process_subinst_connect(mup, sub, inst_name, new_inst, | |
319 mod_net_array, conn_array); | |
320 check_missing_connect(new_inst, mdown, conn_array); | |
321 } else { | |
322 conn_array = 0; | |
323 nc_nets = 0; | |
324 } | |
325 | |
326 if (mdown->is_primitive) | |
327 elaborate_primitive(mdown, new_inst, conn_array); | |
328 else { | |
329 new_prefix = malloc(strlen(hier_prefix) + | |
330 strlen(sub->inst_name) + 2); | |
331 if (!new_prefix) { | |
332 perror("malloc"); | |
333 exit(1); | |
334 } | |
335 sprintf(new_prefix, "%s%s.", hier_prefix, sub->inst_name); | |
336 elaborate_module(mdown, new_inst, new_prefix, conn_array); | |
337 free(new_prefix); | |
338 if (conn_array) | |
339 free(conn_array); | |
340 } | |
341 | |
342 if (nc_nets) | |
343 check_nc_nets(nc_nets); | |
344 } | |
345 | |
346 static void | |
347 incr_net_points_for_output_element(elem) | |
348 struct output_element *elem; | |
349 { | |
350 register struct output_net **p, **endp; | |
351 | |
352 p = elem->connections; | |
353 endp = p + elem->prim_def->nports; | |
354 for (; p < endp; p++) | |
355 (*p)->npoints++; | |
356 } | |
357 | |
358 elaborate_primitive(mod, inst_name, in_conn_array) | |
359 struct module_def *mod; | |
360 char *inst_name; | |
361 struct output_net **in_conn_array; | |
362 { | |
363 register struct output_element *elem; | |
364 | |
365 elem = (struct output_element *) malloc(sizeof(struct output_element)); | |
366 if (!elem) { | |
367 perror("malloc"); | |
368 exit(1); | |
369 } | |
370 elem->prim_def = mod; | |
371 elem->hier_inst_name = inst_name; | |
372 elem->connections = in_conn_array; | |
373 elem->next = 0; | |
374 *output_element_tail = elem; | |
375 output_element_tail = &elem->next; | |
376 total_output_elements++; | |
377 incr_net_points_for_output_element(elem); | |
378 } | |
379 | |
380 tally_output_nets() | |
381 { | |
382 register struct output_net *net; | |
383 | |
384 for (net = output_net_head; net; net = net->next) { | |
385 if (net->npoints > 1) | |
386 total_good_nets++; | |
387 else if (net->npoints == 1) | |
388 total_singular_nets++; | |
389 else | |
390 total_null_nets++; | |
391 } | |
392 } |