FreeCalypso > hg > ueda-linux
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 } |