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 }