Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | mjames | 1 | /* |
2 | * $Header: c:\\cygwin\\cvsroot/Vert03/vertlib/jumpering.c,v 1.1.1.1 2003/11/04 23:34:57 mjames |
||
3 | * Exp $ |
||
4 | * |
||
5 | * $Log: jumpering.c,v $ |
||
6 | * Revision 1.1.1.1 2003/11/04 23:34:57 mjames |
||
7 | * Imported into local repositrory |
||
8 | * |
||
9 | * Revision 1.10 2003/01/02 21:37:15 mjames |
||
10 | * Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L |
||
11 | * properties on the nets so that pin jumpers can be made without a problem. |
||
12 | * |
||
13 | * Still need to sort out pin assignments made to these not_routable nets |
||
14 | * which will become legal in some cases so that pullups and pulldown |
||
15 | * pins can be used on the FPGA. |
||
16 | * |
||
17 | * Revision 1.9 2002/10/02 18:41:54 MJAMES |
||
18 | * Removed diagnostic printout |
||
19 | * |
||
20 | * Revision 1.8 2002/09/27 22:37:25 MJAMES |
||
21 | * Added definition of create_vhdl_connections |
||
22 | * |
||
23 | * Revision 1.7 2002/09/09 10:13:32 mjames |
||
24 | * Moved pin remapping function to pin ident editing function from |
||
25 | * sorting pin name routine. |
||
26 | * |
||
27 | * Revision 1.6 2002/01/15 12:35:58 mjames |
||
28 | * DLL declarations put in, |
||
29 | * |
||
30 | * #ident used |
||
31 | * |
||
32 | * Revision 1.5 2001/11/19 10:41:51 mjames |
||
33 | * Merged back DTC release |
||
34 | * |
||
35 | * Revision 1.4.2.2 2001/11/15 21:06:43 mjames |
||
36 | * Promoted a jumper deletion message to an error status. |
||
37 | * |
||
38 | * Revision 1.4.2.1 2001/11/15 21:01:21 mjames |
||
39 | * Tidying up unused variables |
||
40 | * |
||
41 | * Revision 1.4 2001/10/31 22:20:07 mjames |
||
42 | * Tidying up problematical comments caused by CVS |
||
43 | * 'intelligent' comment guessing |
||
44 | * |
||
45 | * Revision 1.3 2001/06/19 05:23:59 mjames |
||
46 | * Moved some code dealing with finding nets with external connections |
||
47 | * to ext_nets.c |
||
48 | * |
||
49 | * Revision 1.2 2001/06/06 12:10:21 mjames |
||
50 | * Move from HPUX |
||
51 | * |
||
52 | * Revision 1.1.1.1 2000/10/19 21:58:38 mjames |
||
53 | * Mike put it here |
||
54 | * |
||
55 | * Revision 1.32 2000/10/04 10:37:06 10:37:06 mjames (Mike James) |
||
56 | * Modified for Vertical2 : support COMPONENTS and SIGNALS |
||
57 | * |
||
58 | * Revision 1.32 2000/10/04 10:37:06 10:37:06 mjames (Mike James) |
||
59 | * Part of Release PSAVAT01 |
||
60 | * |
||
61 | * Revision 1.31 2000/10/02 11:04:15 11:04:15 mjames (Mike James) |
||
62 | * new_vhdl |
||
63 | * |
||
64 | * Revision 1.30 2000/09/27 14:42:16 14:42:16 mjames (Mike James) |
||
65 | * Part of Release Sep_27_ST_2000 |
||
66 | * |
||
67 | * Revision 1.29 2000/09/21 10:15:46 10:15:46 mjames (Mike James) |
||
68 | * Part of Release Sep21Alpha |
||
69 | * |
||
70 | * Revision 1.28 2000/09/21 09:46:54 09:46:54 mjames (Mike James) |
||
71 | * Added code to deal with pin equivalents |
||
72 | * |
||
73 | * Revision 1.27 2000/08/25 09:57:12 09:57:12 mjames (Mike James) |
||
74 | * Part of Release Aug25_alpha |
||
75 | * |
||
76 | * Revision 1.26 2000/08/16 08:57:28 08:57:28 mjames (Mike James) |
||
77 | * Part of Release CD01_Aug2000 |
||
78 | * |
||
79 | * Revision 1.25 2000/08/14 14:45:10 14:45:10 mjames (Mike James) |
||
80 | * Part of Release Aug_14_2000 |
||
81 | * |
||
82 | * Revision 1.24 2000/08/14 14:42:53 14:42:53 mjames (Mike James) |
||
83 | * Changed checks for hierarchical jumpers |
||
84 | * |
||
85 | * Revision 1.23 2000/08/11 08:30:30 08:30:30 mjames (Mike James) |
||
86 | * Part of Release Aug_11_2000 |
||
87 | * |
||
88 | * Revision 1.22 2000/08/09 10:31:44 10:31:44 mjames (Mike James) |
||
89 | * Part of Release Aug__9_2000 |
||
90 | * |
||
91 | * Revision 1.21 2000/05/31 11:42:53 11:42:53 mjames (Mike James) |
||
92 | * Part of Release May_31_2000 |
||
93 | * |
||
94 | * Revision 1.20 2000/05/08 17:01:35 17:01:35 mjames (Mike James) |
||
95 | * Part of Release May__8_2000 |
||
96 | * |
||
97 | * Revision 1.19 2000/05/08 16:59:29 16:59:29 mjames (Mike James) |
||
98 | * Part of Release May__8_2000 |
||
99 | * |
||
100 | * Revision 1.18 2000/05/08 16:57:05 16:57:05 mjames (Mike James) |
||
101 | * Part of Release May__8_2000 |
||
102 | * |
||
103 | * Revision 1.17 2000/03/08 16:19:09 16:19:09 mjames (Mike James) |
||
104 | * New version including PC |
||
105 | * |
||
106 | * Revision 1.14 2000/01/20 15:58:45 15:58:45 mjames (Mike James) |
||
107 | * Part of Release R22 |
||
108 | * |
||
109 | * Revision 1.13 99/12/22 11:15:25 11:15:25 mjames (Mike James) |
||
110 | * Part of Release Dec_22_1999 |
||
111 | * |
||
112 | * Revision 1.12 99/06/25 14:35:36 14:35:36 mjames (Mike James) |
||
113 | * Added in reference to expression.h, but no changes made |
||
114 | * to the function of acfread yet. |
||
115 | * |
||
116 | * Revision 1.11 99/05/04 09:51:47 09:51:47 mjames (Mike James) |
||
117 | * General checkin |
||
118 | * ls |
||
119 | * |
||
120 | * Revision 1.9 98/11/30 13:48:12 13:48:12 mjames (Mike James) |
||
121 | * Corrected a create-jumper-with-no-nodes = core dump |
||
122 | * problem |
||
123 | * |
||
124 | * Revision 1.8 98/11/27 15:15:08 15:15:08 mjames (Mike James) |
||
125 | * Amended algorithm to work with newer database |
||
126 | * format |
||
127 | * |
||
128 | * Revision 1.7 98/11/25 12:46:54 12:46:54 mjames (Mike James) |
||
129 | * Checked in with some errors to do with not creating a jumper name !! |
||
130 | * |
||
131 | * Revision 1.6 98/11/16 13:18:30 13:18:30 mjames (Mike James) |
||
132 | * |
||
133 | * Revision 1.5 98/03/16 11:32:31 11:32:31 mjames (Mike James) |
||
134 | * Attempting to correct the jumpering of already jumpered jumper lists. |
||
135 | * |
||
136 | * Revision 1.4 98/02/11 11:26:28 11:26:28 mjames (Mike James) |
||
137 | * Checked in for version 6.2a |
||
138 | * |
||
139 | * Revision 1.3 97/04/23 08:42:54 08:42:54 mjames (Mike James) |
||
140 | * CHecked in for release rel23041997 |
||
141 | * |
||
142 | * Revision 1.2 96/12/13 08:43:23 08:43:23 mjames (Mike James) |
||
143 | * Update to v5.1, added Write ID , exact routing |
||
144 | * |
||
145 | * Revision 1.1 96/08/06 13:39:40 13:39:40 mjames (Mike James) |
||
146 | * Initial revision |
||
147 | * |
||
148 | * */ |
||
149 | |||
150 | #include "jumpering.h" |
||
151 | |||
152 | #include "cmdlog.h" |
||
153 | #include "cmdparse.h" |
||
154 | #include "database.h" |
||
155 | #include "expression.h" |
||
156 | #include "generic.h" |
||
157 | #include "routing.h" |
||
158 | #include "vertcl_main.h" |
||
159 | |||
160 | #include <ctype.h> |
||
161 | #include <stdio.h> |
||
162 | #include <stdlib.h> |
||
163 | #include <string.h> |
||
164 | |||
165 | #ident \ |
||
166 | "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/jumpering.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $" |
||
167 | |||
168 | /* resolve not routable H or L */ |
||
169 | HowRouted_t routing_resolve (HowRouted_t curr, HowRouted_t next) |
||
170 | { |
||
171 | /* the H property can be destroyed if it meets L or plain not_routable */ |
||
172 | if (curr == Not_Routable_H) |
||
173 | { |
||
174 | if (next == Not_Routable || next == Not_Routable_L) |
||
175 | return Not_Routable; |
||
176 | } |
||
177 | if (curr == Not_Routable_L) |
||
178 | { |
||
179 | if (next == Not_Routable || next == Not_Routable_H) |
||
180 | return Not_Routable; |
||
181 | } |
||
182 | return next; |
||
183 | } |
||
184 | |||
185 | /* takes a net and removes it from the list of nets directly searchable |
||
186 | by routing algorithms, copying all its node references to the new net, |
||
187 | This is used in creating jumpers */ |
||
188 | __declspec(dllexport) int transfer_net_to_subnet (net_t **list, net_t *topnet, net_t *subnet) |
||
189 | { |
||
190 | net_t *prev_net; |
||
191 | net_t *next_net; |
||
192 | char *subnet_orig_ident; |
||
193 | HowRouted_t subnet_how_routed; |
||
194 | int hierarchy; |
||
195 | hierarchy = 0; |
||
196 | |||
197 | /* algorithms check to see if there is a hierarchy of jumpers. |
||
198 | if there is then check to see if the jumper is basically a connection |
||
199 | to itself. If it is give up. */ |
||
200 | |||
201 | subnet_how_routed = subnet->how_routed; |
||
202 | subnet_orig_ident = subnet->identifier; |
||
203 | |||
204 | /* Log(LOG_GENERAL,"# JUMPER: Net '%s' jumpered to '%s'\n", |
||
205 | topnet->identifier,subnet->identifier); |
||
206 | */ |
||
207 | if (subnet->join_parent) |
||
208 | { |
||
209 | hierarchy = 1; |
||
210 | while (subnet->join_parent) |
||
211 | { |
||
212 | /* Log(LOG_GENERAL,"# Info : Net '%s' is already jumpered to '%s': |
||
213 | trying parent jumper\n", |
||
214 | subnet->identifier,subnet->join_parent->identifier); |
||
215 | */ |
||
216 | subnet = subnet->join_parent; |
||
217 | } |
||
218 | } |
||
219 | |||
220 | if (topnet == subnet) |
||
221 | { |
||
222 | Log ( |
||
223 | LOG_ERROR, |
||
224 | "# Error : - Cant join a net to itself !!! %s to %s : Suppressing " |
||
225 | "Jumper\n", |
||
226 | subnet_orig_ident, |
||
227 | topnet->identifier); |
||
228 | return 0; |
||
229 | } |
||
230 | else if (hierarchy) |
||
231 | { |
||
232 | Log ( |
||
233 | LOG_GENERAL, |
||
234 | "# -- Info : Net '%s' will be jumpered via '%s' to '%s' \n", |
||
235 | subnet_orig_ident, |
||
236 | subnet->identifier, |
||
237 | topnet->identifier); |
||
238 | } |
||
239 | prev_net = subnet->prev; |
||
240 | next_net = subnet->next; |
||
241 | |||
242 | /* Remove subnet from directly searchable list */ |
||
243 | |||
244 | /* if at head of list, correct list and point back at NULL */ |
||
245 | if (subnet == *list) |
||
246 | { |
||
247 | *list = next_net; |
||
248 | if (next_net) |
||
249 | next_net->prev = NULL; |
||
250 | } |
||
251 | else if (next_net) |
||
252 | next_net->prev = subnet->prev; |
||
253 | if (prev_net) |
||
254 | prev_net->next = subnet->next; |
||
255 | |||
256 | /* attach net to topnet's subnet list */ |
||
257 | /* printf("before: topnet->subnets = %p\n",topnet->subnets); */ |
||
258 | /* printf("before: subnet = %p\n",subnet); */ |
||
259 | |||
260 | subnet->prev = NULL; |
||
261 | subnet->next = NULL; |
||
262 | subnet->joined_nets = topnet->subnets; /* The subnets are linked horizontally via |
||
263 | the 'joined_nets' rather than subnet pointer now */ |
||
264 | |||
265 | subnet->join_parent = topnet; /* The subnet is joined to the parent */ |
||
266 | topnet->join_parent = NULL; /* this net does not have a parent */ |
||
267 | topnet->subnets = subnet; |
||
268 | |||
269 | /* propagate up properties */ |
||
270 | |||
271 | if (subnet->has_fix_location) |
||
272 | topnet->has_fix_location = 1; |
||
273 | |||
274 | if (IS_NOT_ROUTABLE (subnet_how_routed)) |
||
275 | { |
||
276 | Log ( |
||
277 | LOG_ERROR, |
||
278 | "# Warning - Jumpering '%s' and '%s' will be NON ROUTABLE\n", |
||
279 | subnet->identifier, |
||
280 | topnet->identifier); |
||
281 | } |
||
282 | topnet->how_routed = routing_resolve (topnet->how_routed, subnet_how_routed); |
||
283 | |||
284 | /* subnet->name = topnet->name;*/ |
||
285 | |||
286 | /* printf("after: topnet->subnets = %p\n",topnet->subnets); */ |
||
287 | /* printf("after: subnet->next = %p\n",subnet->next); */ |
||
288 | |||
289 | /* now copy the noderef list from subnet to topnet */ |
||
290 | { |
||
291 | noderef_t *newref; |
||
292 | noderef_t *oldref = subnet->nodes; |
||
293 | while (oldref) |
||
294 | { |
||
295 | /* create a new node reference */ |
||
296 | newref = calloc (1, sizeof (noderef_t)); |
||
297 | |||
298 | newref->base_noderef = oldref->base_noderef; /* point down to the |
||
299 | original node reference */ |
||
300 | |||
301 | /* copy information : probably is not needed */ |
||
302 | /* SNIP from here ? ************************************** */ |
||
303 | newref->pindir = oldref->pindir; |
||
304 | /* newref->datatype = oldref->datatype; */ |
||
305 | /* get_vhdl_buswidth(newref);*/ /* sort out the VHDL bus |
||
306 | declaration */ |
||
307 | newref->vhdltype = copy_vhdl (oldref->vhdltype, NULL); |
||
308 | |||
309 | newref->node = oldref->node; |
||
310 | /* added as forgotten 05/11/1998 */ |
||
311 | newref->orig_name = allocstr (oldref->orig_name); |
||
312 | newref->orig_vhdltype = copy_vhdl (oldref->orig_vhdltype, NULL); |
||
313 | /* end edit */ |
||
314 | |||
315 | /* SNIP to here ? ************************************** */ |
||
316 | /* new node refers to information on the top net if joined, |
||
317 | otherwise it is the sub net if aliased */ |
||
318 | if (topnet->how_joined == Jumpered) |
||
319 | { |
||
320 | newref->net = topnet; |
||
321 | newref->node->routed_net = |
||
322 | topnet; /* change routed net reference to |
||
323 | point at jumper net rather than originals */ |
||
324 | } |
||
325 | else |
||
326 | newref->net = subnet; |
||
327 | |||
328 | /* attach it to the net */ |
||
329 | newref->next = topnet->nodes; |
||
330 | topnet->nodes = newref; |
||
331 | |||
332 | /* count nodes */ |
||
333 | topnet->nodecount++; |
||
334 | |||
335 | oldref = oldref->next; |
||
336 | } |
||
337 | } |
||
338 | return 1; /* success on a plate */ |
||
339 | } |
||
340 | |||
341 | /****************************************************************************/ |
||
342 | /* this procedure takes a jumper apart as a result of failure */ |
||
343 | /* it takes the subnets and links them back into the main routed net list, |
||
344 | removes the top net that was the jumper */ |
||
345 | __declspec(dllexport) int disconnect_jumper (net_t **list, net_t *jumper) |
||
346 | |||
347 | { |
||
348 | net_t *first_member = jumper->subnets; |
||
349 | net_t *current_member; |
||
350 | net_t *previous_member = jumper; |
||
351 | net_t *next_list = jumper->next; |
||
352 | /* at this point we have |
||
353 | |||
354 | previous net<-->jumper<-->next net |
||
355 | | |
||
356 | sub1-->sub2-->sub3... |
||
357 | |||
358 | |||
359 | */ |
||
360 | current_member = first_member; |
||
361 | |||
362 | if (first_member) |
||
363 | { |
||
364 | while (current_member) |
||
365 | { |
||
366 | current_member->next = |
||
367 | current_member->joined_nets; /* copy next pointer from join list*/ |
||
368 | current_member->prev = previous_member; |
||
369 | current_member->joined_nets = NULL; |
||
370 | current_member->join_parent = NULL; /* no longer part of a jumper */ |
||
371 | |||
372 | previous_member->next = current_member; |
||
373 | previous_member = current_member; |
||
374 | Log ( |
||
375 | LOG_ERROR, |
||
376 | "-- disconnecting '%s'\n", |
||
377 | current_member->identifier); |
||
378 | current_member = current_member->next; |
||
379 | }; |
||
380 | previous_member->next = next_list; |
||
381 | if (previous_member->next) |
||
382 | previous_member->next->prev = previous_member; |
||
383 | } |
||
384 | |||
385 | /* converted to |
||
386 | previous net<-->jumper<-->sub1<-->sub2<-->sub3<-->next net |
||
387 | */ |
||
388 | |||
389 | Log (LOG_GENERAL, "-- From jumper '%s'\n\n", jumper->identifier); |
||
390 | remove_net (list, jumper); |
||
391 | return 1; |
||
392 | } |
||
393 | |||
394 | /* ******************************************** */ |
||
395 | |||
396 | static net_t * |
||
397 | check_net (int *accept_nodes, net_t **best_net, net_t *routed_net, net_t *unrouted_net) |
||
398 | { |
||
399 | if (routed_net->has_external && routed_net->nodecount >= *accept_nodes && |
||
400 | IS_ROUTABLE (routed_net->how_routed)) |
||
401 | { |
||
402 | /* possibly enough nodes, but does it go the right places ?? */ |
||
403 | int visit_count = 0; |
||
404 | noderef_t *unrouted_nodes = unrouted_net->nodes; |
||
405 | noderef_t *routed_nodes = routed_net->nodes; |
||
406 | clear_routing_flags (routed_nodes); |
||
407 | /* search for as yet unused but needed nodes on the unrouted net */ |
||
408 | while (unrouted_nodes) |
||
409 | { |
||
410 | if (unrouted_nodes->r_flag == 0 && |
||
411 | search_net_for_socket (unrouted_nodes, routed_nodes, 0) != NULL) |
||
412 | visit_count++; |
||
413 | unrouted_nodes = unrouted_nodes->next; |
||
414 | } |
||
415 | if (visit_count > *accept_nodes) |
||
416 | { |
||
417 | *accept_nodes = visit_count; |
||
418 | *best_net = routed_net; |
||
419 | } |
||
420 | } |
||
421 | return *best_net; |
||
422 | } |
||
423 | |||
424 | /* ******************************************** */ |
||
425 | /* This function tries to tidy up all nets that are currently |
||
426 | still in the unrouted list because they are blocked |
||
427 | The algorithm is to try and locate the routed net which visits |
||
428 | the highest number of sockets referred to by the unrouted net |
||
429 | and which has an external connection on it. Mark this, assign its |
||
430 | nodes to a jumpered net. Remove nodes used from the unrouted |
||
431 | net and search again. |
||
432 | Repeat until either no jumper candidates are found or all |
||
433 | nodes on the unrouted net are used up. */ |
||
434 | |||
435 | __declspec(dllexport) void perform_routing_by_making_jumpers (char *Suffix) |
||
436 | { |
||
437 | int jumper_count = 1; |
||
438 | net_t *unrouted_net = unrouted_list; |
||
439 | net_t *next_net; |
||
440 | HowRouted_t route_type = Free; |
||
441 | |||
442 | if (!Suffix) |
||
443 | Suffix = ""; |
||
444 | |||
445 | /* firstly, set up the has_external flags on all of the nets, by checking to see if any |
||
446 | nodes on any nets are connected to external sockets */ |
||
447 | |||
448 | /* code moved to ext_nets.c |
||
449 | while (routed_net) |
||
450 | { |
||
451 | noderef_t *noderefs = routed_net->nodes; |
||
452 | routed_net->has_external = 0; |
||
453 | while (noderefs) |
||
454 | { |
||
455 | if (noderefs->node->socket->is_external) |
||
456 | routed_net->has_external = 1; |
||
457 | noderefs = noderefs->next; |
||
458 | } |
||
459 | routed_net = routed_net->next; |
||
460 | } |
||
461 | */ |
||
462 | /* tidy up */ |
||
463 | |||
464 | while (unrouted_net) |
||
465 | { /* loop through all unrouted nets */ |
||
466 | int routed_ok = 1; |
||
467 | int accept_nodes = 0; |
||
468 | int nets_used = 0; |
||
469 | int nodes_left = unrouted_net->nodecount; |
||
470 | net_t *best_net; |
||
471 | net_t *routed_net; |
||
472 | noderef_t *unrouted_nodes; |
||
473 | |||
474 | char jumper_name[JUMP_NAMLEN + 1]; |
||
475 | net_t *jumper_net = NULL; |
||
476 | |||
477 | Log ( |
||
478 | LOG_GENERAL, |
||
479 | "\n--Looking to create net '%s' which has %d nodes\n", |
||
480 | unrouted_net->identifier, |
||
481 | nodes_left); |
||
482 | /* using the routing flags to indicate a net has sucessfully visited node . |
||
483 | Only clear the flags if there is actually a node list !! */ |
||
484 | if (unrouted_net->nodes) |
||
485 | clear_routing_flags (unrouted_net->nodes); |
||
486 | |||
487 | /* iterate until a loop fails to do better, or we have jumpered all of the |
||
488 | nodes we need */ |
||
489 | while (routed_ok && nodes_left) |
||
490 | { |
||
491 | net_t **list; |
||
492 | int pass; |
||
493 | best_net = NULL; |
||
494 | accept_nodes = 0; |
||
495 | for (pass = 0; pass < 1 && !best_net; pass++) |
||
496 | { |
||
497 | if (pass == 0) |
||
498 | list = &routed_list; |
||
499 | else |
||
500 | list = &named_list; |
||
501 | /* check for FIX_LOCATION pins as these are most important |
||
502 | In this case, the best_net is one that can be connected to |
||
503 | the FIX_LOCATION pin because it is not yet in use */ |
||
504 | unrouted_nodes = unrouted_net->nodes; |
||
505 | /* scan through until we find an unrouted node that has no |
||
506 | * routing flag set */ |
||
507 | while (unrouted_nodes && !best_net) |
||
508 | { |
||
509 | if (unrouted_nodes->r_flag == 0) |
||
510 | { |
||
511 | net_t *poss_routed_net = |
||
512 | unrouted_nodes->node->routed_net; |
||
513 | if (poss_routed_net && |
||
514 | poss_routed_net->list_ref == list) |
||
515 | { |
||
516 | if (level & 2) |
||
517 | { |
||
518 | Log ( |
||
519 | LOG_GENERAL, |
||
520 | "\n-- pass %d checking " |
||
521 | "net '%s'\n", |
||
522 | pass, |
||
523 | poss_routed_net |
||
524 | ->identifier); |
||
525 | } |
||
526 | /* is routed net still available on the |
||
527 | * routed list ? */ |
||
528 | /* && |
||
529 | * poss_routed_net->has_fix_location) |
||
530 | */ /* only fix_location nets on pass 1, then all nets */ |
||
531 | check_net ( |
||
532 | &accept_nodes, |
||
533 | &best_net, |
||
534 | poss_routed_net, /* ???? was |
||
535 | routed_net . no |
||
536 | sense here !! |
||
537 | */ |
||
538 | unrouted_net); |
||
539 | } |
||
540 | } |
||
541 | unrouted_nodes = unrouted_nodes->next; |
||
542 | } |
||
543 | if ((level & 2) && best_net) |
||
544 | { |
||
545 | Log ( |
||
546 | LOG_GENERAL, |
||
547 | "-- Phase 1 search Found as best match net '%s' " |
||
548 | "with %d corresponding nodes\n", |
||
549 | best_net->identifier, |
||
550 | accept_nodes); |
||
551 | } |
||
552 | |||
553 | if (!best_net) |
||
554 | { |
||
555 | /* check for any position to jumper if there are no |
||
556 | FIX_LOCATION pins Now, search simply for any useful |
||
557 | net, and try the one with the most sockets visited */ |
||
558 | |||
559 | routed_net = *list; |
||
560 | accept_nodes = 0; |
||
561 | while (routed_net) |
||
562 | { |
||
563 | if (level & 2) |
||
564 | Log ( |
||
565 | LOG_GENERAL, |
||
566 | "\n-- pass %d generally checking " |
||
567 | "net '%s'\n", |
||
568 | pass, |
||
569 | routed_net->identifier); |
||
570 | check_net ( |
||
571 | &accept_nodes, |
||
572 | &best_net, |
||
573 | routed_net, |
||
574 | unrouted_net); |
||
575 | |||
576 | routed_net = routed_net->next; |
||
577 | } |
||
578 | if ((level & 2) && best_net) |
||
579 | Log ( |
||
580 | LOG_GENERAL, |
||
581 | "-- Phase 2 search Found as best match " |
||
582 | "net '%s' with %d corresponding nodes\n", |
||
583 | best_net->identifier, |
||
584 | accept_nodes); |
||
585 | } |
||
586 | } |
||
587 | |||
588 | if (best_net) |
||
589 | { |
||
590 | Log ( |
||
591 | LOG_GENERAL, |
||
592 | "-- Found as best match net '%s' with %d corresponding " |
||
593 | "nodes\n", |
||
594 | best_net->identifier, |
||
595 | accept_nodes); |
||
596 | nodes_left -= |
||
597 | accept_nodes; /* Count down how many nodes left to go */ |
||
598 | |||
599 | { |
||
600 | noderef_t *unrouted_nodes = unrouted_net->nodes; |
||
601 | clear_routing_flags (best_net->nodes); |
||
602 | while (unrouted_nodes) |
||
603 | { |
||
604 | if (search_net_for_socket ( |
||
605 | unrouted_nodes, best_net->nodes, 0) != |
||
606 | NULL) |
||
607 | { |
||
608 | unrouted_nodes->r_flag = 1; |
||
609 | } |
||
610 | |||
611 | /* when all flags on unrouted nets go to '1' |
||
612 | then we have finished the jumpering */ |
||
613 | if (level & 2) |
||
614 | Log ( |
||
615 | LOG_GENERAL, |
||
616 | "-- flag on %s(%s) is %d\n", |
||
617 | unrouted_nodes->node->socket |
||
618 | ->identifier, |
||
619 | unrouted_nodes->node->identifier, |
||
620 | unrouted_nodes->r_flag); |
||
621 | unrouted_nodes = unrouted_nodes->next; |
||
622 | } |
||
623 | } |
||
624 | |||
625 | if (nets_used++ == 0 && nodes_left == 0) |
||
626 | { |
||
627 | /* we seem to have found a complete path already with |
||
628 | all the nodes on it. the user is obviously using |
||
629 | 'jumper' before 'route' */ |
||
630 | if (level & 2) |
||
631 | Log ( |
||
632 | LOG_GENERAL, |
||
633 | "-- This net contains all nodes " |
||
634 | "requested, simply connecting\n\n"); |
||
635 | jumper_net = best_net; |
||
636 | route_type = By_Net; |
||
637 | } |
||
638 | else |
||
639 | { |
||
640 | route_type = By_Jumpering; |
||
641 | /* try hard to create a unique jumper ID */ |
||
642 | while (!jumper_net) |
||
643 | { |
||
644 | sprintf ( |
||
645 | jumper_name, |
||
646 | JUMP_FMT, |
||
647 | Suffix, |
||
648 | jumper_count++); |
||
649 | jumper_net = find_net ( |
||
650 | &routed_list, Ident, jumper_name, Search); |
||
651 | /* if it is not found then the name proposed is |
||
652 | * unique */ |
||
653 | if (!jumper_net) |
||
654 | { |
||
655 | jumper_net = find_net ( |
||
656 | &routed_list, |
||
657 | Ident, |
||
658 | jumper_name, |
||
659 | Create); |
||
660 | /* |
||
661 | Log |
||
662 | (LOG_GENERAL, "-- Creating jumper |
||
663 | %s\n", jumper_net->identifier); |
||
664 | */ |
||
665 | jumper_net->how_joined = Jumpered; |
||
666 | break; |
||
667 | } |
||
668 | else |
||
669 | jumper_net = |
||
670 | NULL; /* if found already, it |
||
671 | should not terminate the |
||
672 | loop */ |
||
673 | } |
||
674 | Log ( |
||
675 | LOG_GENERAL, |
||
676 | "-- Jumpering %s to net %s (nodes_left=%d)\n", |
||
677 | jumper_net->identifier, |
||
678 | best_net->identifier, |
||
679 | nodes_left); |
||
680 | /* mark the used nodes by setting the r_flag on the |
||
681 | * used unrouted nodes */ |
||
682 | |||
683 | /* find the first node that is connected to an external |
||
684 | * pin on the best_net */ |
||
685 | /* record this as the external node */ |
||
686 | |||
687 | { |
||
688 | noderef_t *routed_nodes = best_net->nodes; |
||
689 | while (routed_nodes) |
||
690 | { |
||
691 | if (routed_nodes->node->socket |
||
692 | ->is_external) |
||
693 | { |
||
694 | best_net->external_node = |
||
695 | routed_nodes->node; |
||
696 | break; |
||
697 | } |
||
698 | routed_nodes = routed_nodes->next; |
||
699 | } |
||
700 | } |
||
701 | |||
702 | /* make the jumper */ |
||
703 | transfer_net_to_subnet ( |
||
704 | &routed_list, jumper_net, best_net); |
||
705 | routed_ok = 1; |
||
706 | } |
||
707 | } |
||
708 | else |
||
709 | { |
||
710 | routed_ok = 0; |
||
711 | Log ( |
||
712 | LOG_ERROR, |
||
713 | "-- Error : insufficient/no jumperable nets free\n" |
||
714 | "-- to create net '%s' which requires %d more nodes\n", |
||
715 | unrouted_net->identifier, |
||
716 | nodes_left); |
||
717 | } |
||
718 | } |
||
719 | next_net = unrouted_net->next; |
||
720 | |||
721 | if (routed_ok) |
||
722 | { |
||
723 | combine_routed_and_unrouted (jumper_net, unrouted_net); |
||
724 | transfer_net_to_named (&routed_list, jumper_net); /* jumpers are in |
||
725 | routed list */ |
||
726 | jumper_net->how_routed = route_type; |
||
727 | next_net = remove_net (&unrouted_list, unrouted_net); |
||
728 | } |
||
729 | else |
||
730 | { |
||
731 | /* Failure to complete, so remove the partially completed jumper net |
||
732 | * from the list */ |
||
733 | if (jumper_net) |
||
734 | { |
||
735 | Log ( |
||
736 | LOG_ERROR, |
||
737 | "-- failure : disconnecting partially completed jumper\n"); |
||
738 | disconnect_jumper (&routed_list, jumper_net); |
||
739 | } |
||
740 | } |
||
741 | |||
742 | unrouted_net = next_net; |
||
743 | } |
||
744 | count_nets ("After using new paths created by jumpers"); |
||
745 | } |
||
746 | |||
747 | /* ******************************************** */ |
||
748 | __declspec(dllexport) void perform_jumpering (char *Suffix) |
||
749 | { |
||
750 | count_nets ("Before jumper creation"); |
||
751 | /* remove any connections we can already make */ |
||
752 | /* perform_routing_by_exact_path (); */ |
||
753 | |||
754 | /* make the jumpers */ |
||
755 | perform_routing_by_making_jumpers (Suffix); |
||
756 | |||
757 | /* then use the jumpers */ |
||
758 | /* perform_routing_by_exact_path ();*/ |
||
759 | |||
760 | /* then use the jumpers */ |
||
761 | /* perform_routing_by_path (); */ |
||
762 | } |
||
763 | /* ******************************************** */ |
||
764 | |||
765 | /* try to join all the pins seen on ID1 to ID2 */ |
||
766 | __declspec(dllexport) void create_all_jumpers (char *ID1, char *ID2) |
||
767 | { |
||
768 | socket_t *ID1_skt, *ID2_skt; |
||
769 | node_t *ID1_node, *ID2_node; |
||
770 | net_t *jumper_net, *ID1_net, *ID2_net; |
||
771 | char rootname[MAXIDLEN]; |
||
772 | char *append_point; |
||
773 | ID1_skt = find_socket (Ident, ID1, Search, &socket_head); |
||
774 | ID2_skt = find_socket (Ident, ID2, Search, &socket_head); |
||
775 | if (!ID1_skt) |
||
776 | { |
||
777 | Log (LOG_ERROR, "# ERROR : CONNECTION cannot find socket '%s'\n", ID1); |
||
778 | return; |
||
779 | } |
||
780 | if (!ID2_skt) |
||
781 | { |
||
782 | Log (LOG_ERROR, "# ERROR : CONNECTION cannot find socket '%s'\n", ID2); |
||
783 | return; |
||
784 | } |
||
785 | |||
786 | sprintf (rootname, "cn_%s_%s_", ID1_skt->identifier, ID2_skt->identifier); |
||
787 | Log (LOG_GENERAL, "-- Creating CONNECTION '%s'\n", rootname); |
||
788 | |||
789 | append_point = rootname + strlen (rootname); /* where to append the final pin ID */ |
||
790 | /* for each node on the first chip, try and find the net that it is on in |
||
791 | the routed list, and jumper it to the net that is on the same pin ID on the second |
||
792 | chip. */ |
||
793 | |||
794 | ID1_node = ID1_skt->nodes; |
||
795 | while (ID1_node) |
||
796 | { |
||
797 | if (ID1_node->net && ID1_node->net->list_ref == &routed_list) |
||
798 | { |
||
799 | /* find the highest level of jumper and join it */ |
||
800 | ID1_net = ID1_node->net; |
||
801 | while (ID1_net->join_parent) |
||
802 | ID1_net = ID1_net->join_parent; |
||
803 | |||
804 | ID2_node = find_node (ID2_skt, Ident, ID1_node->identifier, Search); |
||
805 | if (ID2_node) |
||
806 | { |
||
807 | if (ID2_node->net && ID2_node->net->list_ref == &routed_list) |
||
808 | { |
||
809 | /* find the highest level of jumper and join it */ |
||
810 | ID2_net = ID2_node->net; |
||
811 | while (ID2_net->join_parent) |
||
812 | ID2_net = ID2_net->join_parent; |
||
813 | |||
814 | /* we now have a matched pair of nodes for which we |
||
815 | have to find the nets. |
||
816 | If the nets are both on the list of routed net, create |
||
817 | a named jumper between them */ |
||
818 | |||
819 | strcpy ( |
||
820 | append_point, |
||
821 | ID1_node->identifier); /* create the totla new net |
||
822 | name */ |
||
823 | /* |
||
824 | printf("Can make jumper '%s'\n",rootname); |
||
825 | */ |
||
826 | |||
827 | jumper_net = |
||
828 | find_net (&routed_list, Ident, rootname, Create); |
||
829 | jumper_net->how_joined = Jumpered; |
||
830 | if (transfer_net_to_subnet ( |
||
831 | &routed_list, jumper_net, ID1_net)) |
||
832 | ID1_node->net->external_node = ID1_node; |
||
833 | if (transfer_net_to_subnet ( |
||
834 | &routed_list, jumper_net, ID2_net)) |
||
835 | ID2_node->net->external_node = ID2_node; |
||
836 | } |
||
837 | else |
||
838 | Log ( |
||
839 | LOG_ERROR, |
||
840 | "-- Warning : Node '%s(%s)' does not appear on a " |
||
841 | "routed net\n", |
||
842 | ID2_skt->identifier, |
||
843 | ID2_node->identifier); |
||
844 | } |
||
845 | else |
||
846 | Log ( |
||
847 | LOG_ERROR, |
||
848 | "-- Warning : Cannot locate pin '%s' on socket '%s'\n", |
||
849 | ID1_node->identifier, |
||
850 | ID2_skt->identifier); |
||
851 | } |
||
852 | else |
||
853 | Log ( |
||
854 | LOG_ERROR, |
||
855 | "-- Warning : Node '%s(%s)' does not appear on a routed net\n", |
||
856 | ID1_skt->identifier, |
||
857 | ID1_node->identifier); |
||
858 | ID1_node = ID1_node->sktnext; /* move along the socket pins */ |
||
859 | } |
||
860 | } |
||
861 | |||
862 | /*******************************************************/ |
||
863 | |||
864 | void create_vhdl_connections (void) |
||
865 | { |
||
866 | net_t *top_net; |
||
867 | net_t *subnet; |
||
868 | /* assume that create_unrouted_list has already happened */ |
||
869 | top_net = unrouted_list; |
||
870 | while (top_net) |
||
871 | { |
||
872 | if (top_net->vhdl_connect_net) |
||
873 | { |
||
874 | printf ("root net found '%s'\n", top_net->name); |
||
875 | if (top_net->how_joined != NotJoined) |
||
876 | { |
||
877 | Log ( |
||
878 | LOG_ERROR, |
||
879 | "# Warning : %s net '%s' already exists, net is being " |
||
880 | "extended from %d nodes\n", |
||
881 | top_net->how_joined == Jumpered ? "Jumpered" : "Aliased", |
||
882 | top_net->identifier, |
||
883 | top_net->nodecount); |
||
884 | /* if the net is already in existence, it will have nodes */ |
||
885 | } |
||
886 | top_net->how_joined = Jumpered; |
||
887 | transfer_net_to_subnet ( |
||
888 | &unrouted_list, top_net, top_net->vhdl_connect_net); |
||
889 | } |
||
890 | top_net = top_net->next; |
||
891 | } |
||
892 | } |