comparison ueda/sverp/link.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 * ueda-sverp link pass
3 */
4
5 #include <stdio.h>
6 #include <strings.h>
7 #include "struct.h"
8
9 extern struct module_def *glob_module_list, *top_module_def;
10 extern int top_module_candidates;
11
12 extern struct module_def *find_module_by_name();
13
14 static void
15 toplevel_candidate(mod)
16 struct module_def *mod;
17 {
18 top_module_candidates++;
19 if (!top_module_def)
20 top_module_def = mod;
21 }
22
23 static struct module_net_def *
24 find_port_by_name(mod, portname)
25 struct module_def *mod;
26 register char *portname;
27 {
28 register struct module_net_def *n;
29
30 for (n = mod->nets; n; n = n->next)
31 if (!strcmp(n->name, portname))
32 break;
33 if (n && n->is_port)
34 return(n);
35 else
36 return(0);
37 }
38
39 static void
40 handle_downport_range(mup, ins, conn)
41 struct module_def *mup;
42 struct module_def_subinst *ins;
43 register struct connect_entry *conn;
44 {
45 register struct module_net_def *port;
46
47 port = conn->down_portdef;
48 if (!port->is_bus) {
49 fprintf(stderr,
50 "module %s line %d: mod %s port %s is not a bus, range spec is meaningless\n",
51 mup->name, conn->src_lineno, ins->submod_name,
52 port->name);
53 exit(1);
54 }
55 if (port->bus_msb > port->bus_lsb) {
56 if (conn->down_range_msb < conn->down_range_lsb) {
57 error_reversed: fprintf(stderr,
58 "module %s line %d: reversed range on bus port %s\n",
59 mup->name, conn->src_lineno, port->name);
60 exit(1);
61 }
62 if (conn->down_range_msb > port->bus_msb) {
63 error_outofrange: fprintf(stderr,
64 "module %s line %d: subrange on bus port %s exceeds full bus range\n",
65 mup->name, conn->src_lineno, port->name);
66 exit(1);
67 }
68 if (conn->down_range_lsb < port->bus_lsb)
69 goto error_outofrange;
70 conn->down_offset = port->bus_msb - conn->down_range_msb;
71 conn->down_width = conn->down_range_msb - conn->down_range_lsb
72 + 1;
73 } else {
74 if (conn->down_range_msb > conn->down_range_lsb)
75 goto error_reversed;
76 if (conn->down_range_msb < port->bus_msb)
77 goto error_outofrange;
78 if (conn->down_range_lsb > port->bus_lsb)
79 goto error_outofrange;
80 conn->down_offset = conn->down_range_msb - port->bus_msb;
81 conn->down_width = conn->down_range_lsb - conn->down_range_msb
82 + 1;
83 }
84 }
85
86 static void
87 connect_by_name(mup, ins)
88 struct module_def *mup;
89 register struct module_def_subinst *ins;
90 {
91 register struct connect_entry *conn;
92 register struct module_net_def *port;
93
94 for (conn = ins->connections; conn; conn = conn->next) {
95 port = find_port_by_name(ins->submod_def, conn->down_portname);
96 if (!port) {
97 fprintf(stderr,
98 "instance %s in module %s: lower module %s has no port named \"%s\"\n",
99 ins->inst_name, mup->name,
100 ins->submod_name, conn->down_portname);
101 exit(1);
102 }
103 conn->down_portdef = port;
104 if (conn->down_range_given)
105 handle_downport_range(mup, ins, conn);
106 else {
107 conn->down_offset = 0;
108 conn->down_width = port->bus_width;
109 }
110 }
111 }
112
113 static void
114 connect_by_order(mup, ins)
115 struct module_def *mup;
116 register struct module_def_subinst *ins;
117 {
118 struct module_def *mdown;
119 register struct module_net_def *port;
120 register struct connect_entry *conn;
121
122 mdown = ins->submod_def;
123 if (ins->connect_by_order != mdown->nports) {
124 fprintf(stderr,
125 "instance %s in module %s: connect by order port count mismatch (%d ports, %d connections)\n",
126 ins->inst_name, mup->name, mdown->nports,
127 ins->connect_by_order);
128 exit(1);
129 }
130 for (conn = ins->connections, port = mdown->nets; conn;
131 conn = conn->next, port = port->next) {
132 conn->down_portdef = port;
133 conn->down_offset = 0;
134 conn->down_width = port->bus_width;
135 }
136 }
137
138 static void
139 check_width_match(mup, ins)
140 struct module_def *mup;
141 struct module_def_subinst *ins;
142 {
143 register struct connect_entry *conn;
144
145 for (conn = ins->connections; conn; conn = conn->next)
146 if (conn->up_netdef && conn->up_width != conn->down_width) {
147 fprintf(stderr,
148 "module %s line %d: width mismatch on connection to port %s\n",
149 mup->name, conn->src_lineno,
150 conn->down_portdef->name);
151 exit(1);
152 }
153 }
154
155 static void
156 linkpass_process_inst(mup, ins)
157 struct module_def *mup;
158 register struct module_def_subinst *ins;
159 {
160 register struct module_def *mdown;
161
162 mdown = find_module_by_name(ins->submod_name);
163 if (!mdown) {
164 fprintf(stderr,
165 "instance %s in module %s: lower module \"%s\" not found\n",
166 ins->inst_name, mup->name, ins->submod_name);
167 exit(1);
168 }
169 ins->submod_def = mdown;
170 if (ins->connect_by_order)
171 connect_by_order(mup, ins);
172 else
173 connect_by_name(mup, ins);
174 check_width_match(mup, ins);
175 }
176
177 static void
178 linkpass_process_mod(mod)
179 struct module_def *mod;
180 {
181 register struct module_def_subinst *ins;
182
183 for (ins = mod->subinst; ins; ins = ins->next)
184 linkpass_process_inst(mod, ins);
185 }
186
187 link_pass()
188 {
189 register struct module_def *m;
190
191 for (m = glob_module_list; m; m = m->next) {
192 if (m->is_primitive)
193 continue;
194 if (!m->nports)
195 toplevel_candidate(m);
196 linkpass_process_mod(m);
197 }
198 }