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