pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00065 #include "toporouter.h" 00066 #include "pcb-printf.h" 00067 00068 #define BOARD_EDGE_RESOLUTION MIL_TO_COORD (100.) 00069 #define VIA_COST_AS_DISTANCE MIL_TO_COORD (100.) 00070 #define ROAR_DETOUR_THRESHOLD MIL_TO_COORD (10.) 00071 00072 00076 static void 00077 toporouter_edge_init (toporouter_edge_t *edge) 00078 { 00079 edge->routing = NULL; 00080 edge->flags = 0; 00081 } 00082 00083 toporouter_edge_class_t * 00084 toporouter_edge_class(void) 00085 { 00086 static toporouter_edge_class_t *klass = NULL; 00087 00088 if (klass == NULL) { 00089 GtsObjectClassInfo constraint_info = { 00090 "toporouter_edge_t", 00091 sizeof (toporouter_edge_t), 00092 sizeof (toporouter_edge_class_t), 00093 (GtsObjectClassInitFunc) NULL, 00094 (GtsObjectInitFunc) toporouter_edge_init, 00095 (GtsArgSetFunc) NULL, 00096 (GtsArgGetFunc) NULL 00097 }; 00098 klass = (toporouter_edge_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_edge_class ()), &constraint_info); 00099 } 00100 00101 return klass; 00102 } 00103 00107 static void 00108 toporouter_bbox_init (toporouter_bbox_t *box) 00109 { 00110 box->data = NULL; 00111 box->type = OTHER; 00112 box->constraints = NULL; 00113 box->cluster = NULL; 00114 } 00115 00116 toporouter_bbox_class_t * 00117 toporouter_bbox_class(void) 00118 { 00119 static toporouter_bbox_class_t *klass = NULL; 00120 00121 if (klass == NULL) { 00122 GtsObjectClassInfo constraint_info = { 00123 "toporouter_bbox_t", 00124 sizeof (toporouter_bbox_t), 00125 sizeof (toporouter_bbox_class_t), 00126 (GtsObjectClassInitFunc) NULL, 00127 (GtsObjectInitFunc) toporouter_bbox_init, 00128 (GtsArgSetFunc) NULL, 00129 (GtsArgGetFunc) NULL 00130 }; 00131 klass = (toporouter_bbox_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_bbox_class ()), &constraint_info); 00132 } 00133 00134 return klass; 00135 } 00136 00140 static void 00141 toporouter_vertex_class_init (toporouter_vertex_class_t *klass) 00142 { 00143 00144 } 00145 00149 static void 00150 toporouter_vertex_init (toporouter_vertex_t *vertex) 00151 { 00152 vertex->bbox = NULL; 00153 vertex->parent = NULL; 00154 vertex->child = NULL; 00155 vertex->flags = 0; 00156 vertex->routingedge = NULL; 00157 vertex->arc = NULL; 00158 vertex->oproute = NULL; 00159 vertex->route = NULL; 00160 00161 vertex->gcost = 0.; 00162 vertex->hcost = 0.; 00163 vertex->gn = 0; 00164 } 00165 00166 toporouter_vertex_class_t * 00167 toporouter_vertex_class(void) 00168 { 00169 static toporouter_vertex_class_t *klass = NULL; 00170 00171 if (klass == NULL) { 00172 GtsObjectClassInfo constraint_info = { 00173 "toporouter_vertex_t", 00174 sizeof (toporouter_vertex_t), 00175 sizeof (toporouter_vertex_class_t), 00176 (GtsObjectClassInitFunc) toporouter_vertex_class_init, 00177 (GtsObjectInitFunc) toporouter_vertex_init, 00178 (GtsArgSetFunc) NULL, 00179 (GtsArgGetFunc) NULL 00180 }; 00181 klass = (toporouter_vertex_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_vertex_class ()), &constraint_info); 00182 } 00183 00184 return klass; 00185 } 00186 00190 static void 00191 toporouter_constraint_class_init (toporouter_constraint_class_t *klass) 00192 { 00193 00194 } 00195 00199 static void 00200 toporouter_constraint_init (toporouter_constraint_t *constraint) 00201 { 00202 constraint->box = NULL; 00203 constraint->routing = NULL; 00204 } 00205 00206 toporouter_constraint_class_t * 00207 toporouter_constraint_class(void) 00208 { 00209 static toporouter_constraint_class_t *klass = NULL; 00210 00211 if (klass == NULL) { 00212 GtsObjectClassInfo constraint_info = { 00213 "toporouter_constraint_t", 00214 sizeof (toporouter_constraint_t), 00215 sizeof (toporouter_constraint_class_t), 00216 (GtsObjectClassInitFunc) toporouter_constraint_class_init, 00217 (GtsObjectInitFunc) toporouter_constraint_init, 00218 (GtsArgSetFunc) NULL, 00219 (GtsArgGetFunc) NULL 00220 }; 00221 klass = (toporouter_constraint_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_constraint_class ()), &constraint_info); 00222 } 00223 00224 return klass; 00225 } 00226 00230 static void 00231 toporouter_arc_init (toporouter_arc_t *arc) 00232 { 00233 arc->x0 = -1.; 00234 arc->y0 = -1.; 00235 arc->x1 = -1.; 00236 arc->y1 = -1.; 00237 arc->centre = NULL; 00238 arc->v = NULL; 00239 arc->v1 = NULL; 00240 arc->v2 = NULL; 00241 arc->r = -1.; 00242 arc->dir = 31337; 00243 arc->clearance = NULL; 00244 arc->oproute = NULL; 00245 } 00246 00247 toporouter_arc_class_t * 00248 toporouter_arc_class(void) 00249 { 00250 static toporouter_arc_class_t *klass = NULL; 00251 00252 if (klass == NULL) { 00253 GtsObjectClassInfo constraint_info = { 00254 "toporouter_arc_t", 00255 sizeof (toporouter_arc_t), 00256 sizeof (toporouter_arc_class_t), 00257 (GtsObjectClassInitFunc) NULL, 00258 (GtsObjectInitFunc) toporouter_arc_init, 00259 (GtsArgSetFunc) NULL, 00260 (GtsArgGetFunc) NULL 00261 }; 00262 klass = (toporouter_arc_class_t *)gts_object_class_new (GTS_OBJECT_CLASS (gts_constraint_class ()), &constraint_info); 00263 } 00264 00265 return klass; 00266 } 00267 00268 #define MARGIN 10.0f 00269 00273 drawing_context_t * 00274 toporouter_output_init(int w, int h, char *filename) 00275 { 00276 drawing_context_t *dc; 00277 00278 dc = (drawing_context_t *)malloc(sizeof(drawing_context_t)); 00279 00280 dc->iw = w; 00281 dc->ih = h; 00282 dc->filename = filename; 00283 00284 /* Calculate scaling to maintain aspect ratio */ 00285 if(PCB->MaxWidth > PCB->MaxHeight) { 00286 /* Scale board width to match image width minus 2xMARGIN */ 00287 dc->s = ((double)dc->iw - (2 * MARGIN)) / (double)PCB->MaxWidth; 00288 dc->ih = (double)PCB->MaxHeight * dc->s + (2 * MARGIN); 00289 }else{ 00290 /* Scale board height to match image height minus 2xMARGIN */ 00291 dc->s = ((double)dc->ih - (2 * MARGIN)) / (double)PCB->MaxHeight; 00292 dc->iw = (double)PCB->MaxWidth * dc->s + (2 * MARGIN); 00293 } 00294 00295 #if TOPO_OUTPUT_ENABLED 00296 dc->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dc->iw, dc->ih); 00297 dc->cr = cairo_create (dc->surface); 00298 00299 cairo_rectangle (dc->cr, 0, 0, dc->iw, dc->ih); 00300 cairo_set_source_rgb (dc->cr, 0, 0, 0); 00301 cairo_fill (dc->cr); 00302 00303 #endif 00304 00305 return dc; 00306 } 00307 00311 void 00312 toporouter_output_close(drawing_context_t *dc) 00313 { 00314 #if TOPO_OUTPUT_ENABLED 00315 cairo_surface_write_to_png (dc->surface, dc->filename); 00316 cairo_destroy (dc->cr); 00317 cairo_surface_destroy (dc->surface); 00318 #endif 00319 } 00320 00324 gdouble 00325 lookup_keepaway(char *name) 00326 { 00327 if(name) 00328 STYLE_LOOP(PCB); 00329 { 00330 // if(!strcmp(style->Name, name)) return style->Keepaway + 1.; 00331 if(!strcmp(style->Name, name)) return style->Keepaway; 00332 } 00333 END_LOOP; 00334 // return Settings.Keepaway + 1.; 00335 return Settings.Keepaway ; 00336 } 00337 00341 gdouble 00342 lookup_thickness(char *name) 00343 { 00344 if(name) 00345 STYLE_LOOP(PCB); 00346 { 00347 if(!strcmp(style->Name, name)) return style->Thick; 00348 } 00349 END_LOOP; 00350 return Settings.LineThickness; 00351 } 00352 00353 static inline gdouble 00354 cluster_keepaway(toporouter_cluster_t *cluster) 00355 { 00356 if(cluster) return lookup_keepaway(cluster->netlist->style); 00357 return lookup_keepaway(NULL); 00358 } 00359 00360 static inline gdouble 00361 cluster_thickness(toporouter_cluster_t *cluster) 00362 { 00363 if(cluster) return lookup_thickness(cluster->netlist->style); 00364 return lookup_thickness(NULL); 00365 } 00366 00370 gint 00371 toporouter_draw_vertex(gpointer item, gpointer data) 00372 { 00373 #if TOPO_OUTPUT_ENABLED 00374 drawing_context_t *dc = (drawing_context_t *) data; 00375 toporouter_vertex_t *tv; 00376 PinType *pin; 00377 PadType *pad; 00378 gdouble blue; 00379 00380 if(TOPOROUTER_IS_VERTEX((GtsObject*)item)) { 00381 tv = TOPOROUTER_VERTEX((GtsObject*)item); 00382 00383 if(tv->flags & VERTEX_FLAG_RED) { 00384 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f); 00385 cairo_arc(dc->cr, 00386 tv->v.p.x * dc->s + MARGIN, 00387 tv->v.p.y * dc->s + MARGIN, 00388 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00389 cairo_fill(dc->cr); 00390 00391 }else if(tv->flags & VERTEX_FLAG_GREEN) { 00392 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f); 00393 cairo_arc(dc->cr, 00394 tv->v.p.x * dc->s + MARGIN, 00395 tv->v.p.y * dc->s + MARGIN, 00396 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00397 cairo_fill(dc->cr); 00398 00399 }else if(tv->flags & VERTEX_FLAG_BLUE) { 00400 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f); 00401 cairo_arc(dc->cr, 00402 tv->v.p.x * dc->s + MARGIN, 00403 tv->v.p.y * dc->s + MARGIN, 00404 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00405 cairo_fill(dc->cr); 00406 00407 00408 } 00409 //printf("tv->type = %d\n", tv->type); 00410 if(!dc->mode) { 00411 if(tv->bbox) { 00412 pin = (PinType*) tv->bbox->data; 00413 pad = (PadType*) tv->bbox->data; 00414 00415 blue = 0.0f; 00416 switch(tv->bbox->type) { 00417 case PIN: 00418 cairo_set_source_rgba(dc->cr, 1.0f, 0., 0.0f, 0.2f); 00419 cairo_arc(dc->cr, 00420 tv->v.p.x * dc->s + MARGIN, 00421 tv->v.p.y * dc->s + MARGIN, 00422 (((gdouble)pin->Thickness / 2.0f) + (gdouble)lookup_keepaway(pin->Name) ) * dc->s, 0, 2 * M_PI); 00423 cairo_fill(dc->cr); 00424 00425 cairo_set_source_rgba(dc->cr, 1.0f, 0., 0., 0.4f); 00426 cairo_arc(dc->cr, 00427 tv->v.p.x * dc->s + MARGIN, 00428 tv->v.p.y * dc->s + MARGIN, 00429 (gdouble)(pin->Thickness) / 2.0f * dc->s, 00430 0, 2 * M_PI); 00431 cairo_fill(dc->cr); 00432 00433 break; 00434 case VIA: 00435 cairo_set_source_rgba(dc->cr, 0.0f, 0., 1., 0.2f); 00436 cairo_arc(dc->cr, 00437 tv->v.p.x * dc->s + MARGIN, 00438 tv->v.p.y * dc->s + MARGIN, 00439 (((gdouble)pin->Thickness / 2.0f) + (gdouble)lookup_keepaway(pin->Name) ) * dc->s, 0, 2 * M_PI); 00440 cairo_fill(dc->cr); 00441 00442 cairo_set_source_rgba(dc->cr, 0.0f, 0., 1., 0.4f); 00443 cairo_arc(dc->cr, 00444 tv->v.p.x * dc->s + MARGIN, 00445 tv->v.p.y * dc->s + MARGIN, 00446 (gdouble)(pin->Thickness) / 2.0f * dc->s, 00447 0, 2 * M_PI); 00448 cairo_fill(dc->cr); 00449 00450 break; 00451 case PAD: 00452 cairo_set_source_rgba(dc->cr, 0.0f, 1., 0., 0.5f); 00453 cairo_arc(dc->cr, 00454 tv->v.p.x * dc->s + MARGIN, 00455 tv->v.p.y * dc->s + MARGIN, 00456 MIL_TO_COORD (4.) * dc->s, 0, 2 * M_PI); 00457 cairo_fill(dc->cr); 00458 00459 break; 00460 default: 00461 break; 00462 } 00463 } 00464 }else{ 00465 if(tv->flags & VERTEX_FLAG_BLUE) { 00466 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f); 00467 cairo_arc(dc->cr, 00468 tv->v.p.x * dc->s + MARGIN, 00469 tv->v.p.y * dc->s + MARGIN, 00470 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00471 cairo_fill(dc->cr); 00472 }else if(tv->flags & VERTEX_FLAG_RED) { 00473 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f); 00474 cairo_arc(dc->cr, 00475 tv->v.p.x * dc->s + MARGIN, 00476 tv->v.p.y * dc->s + MARGIN, 00477 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00478 cairo_fill(dc->cr); 00479 00480 }else if(tv->flags & VERTEX_FLAG_GREEN) { 00481 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f); 00482 cairo_arc(dc->cr, 00483 tv->v.p.x * dc->s + MARGIN, 00484 tv->v.p.y * dc->s + MARGIN, 00485 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00486 cairo_fill(dc->cr); 00487 } 00488 00489 } 00490 }else{ 00491 fprintf(stderr, "Unknown data passed to toporouter_draw_vertex, aborting foreach\n"); 00492 return -1; 00493 } 00494 return 0; 00495 #else 00496 return -1; 00497 #endif 00498 } 00499 00503 gint 00504 toporouter_draw_edge(gpointer item, gpointer data) 00505 { 00506 #if TOPO_OUTPUT_ENABLED 00507 drawing_context_t *dc = (drawing_context_t *) data; 00508 toporouter_edge_t *te; 00509 toporouter_constraint_t *tc; 00510 00511 if(TOPOROUTER_IS_EDGE((GtsObject*)item)) { 00512 te = TOPOROUTER_EDGE((GtsObject*)item); 00513 cairo_set_source_rgba(dc->cr, 1.0f, 1.0f, 1.0f, 0.5f); 00514 cairo_move_to(dc->cr, 00515 te->e.segment.v1->p.x * dc->s + MARGIN, 00516 te->e.segment.v1->p.y * dc->s + MARGIN); 00517 cairo_line_to(dc->cr, 00518 te->e.segment.v2->p.x * dc->s + MARGIN, 00519 te->e.segment.v2->p.y * dc->s + MARGIN); 00520 cairo_stroke(dc->cr); 00521 }else if(TOPOROUTER_IS_CONSTRAINT((GtsObject*)item)) { 00522 tc = TOPOROUTER_CONSTRAINT((GtsObject*)item); 00523 if(tc->box) { 00524 switch(tc->box->type) { 00525 case BOARD: 00526 cairo_set_source_rgba(dc->cr, 1.0f, 0.0f, 1.0f, 0.9f); 00527 cairo_move_to(dc->cr, 00528 tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 00529 tc->c.edge.segment.v1->p.y * dc->s + MARGIN); 00530 cairo_line_to(dc->cr, 00531 tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 00532 tc->c.edge.segment.v2->p.y * dc->s + MARGIN); 00533 cairo_stroke(dc->cr); 00534 break; 00535 case PIN: 00536 case PAD: 00537 cairo_set_source_rgba(dc->cr, 1.0f, 0.0f, 0.0f, 0.9f); 00538 cairo_move_to(dc->cr, 00539 tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 00540 tc->c.edge.segment.v1->p.y * dc->s + MARGIN); 00541 cairo_line_to(dc->cr, 00542 tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 00543 tc->c.edge.segment.v2->p.y * dc->s + MARGIN); 00544 cairo_stroke(dc->cr); 00545 break; 00546 case LINE: 00547 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.9f); 00548 cairo_move_to(dc->cr, 00549 tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 00550 tc->c.edge.segment.v1->p.y * dc->s + MARGIN); 00551 cairo_line_to(dc->cr, 00552 tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 00553 tc->c.edge.segment.v2->p.y * dc->s + MARGIN); 00554 cairo_stroke(dc->cr); 00555 break; 00556 00557 default: 00558 cairo_set_source_rgba(dc->cr, 1.0f, 1.0f, 0.0f, 0.9f); 00559 cairo_move_to(dc->cr, 00560 tc->c.edge.segment.v1->p.x * dc->s + MARGIN, 00561 tc->c.edge.segment.v1->p.y * dc->s + MARGIN); 00562 cairo_line_to(dc->cr, 00563 tc->c.edge.segment.v2->p.x * dc->s + MARGIN, 00564 tc->c.edge.segment.v2->p.y * dc->s + MARGIN); 00565 cairo_stroke(dc->cr); 00566 break; 00567 } 00568 }else{ 00569 printf("CONSTRAINT without box\n"); 00570 00571 } 00572 }else{ 00573 fprintf(stderr, "Unknown data passed to toporouter_draw_edge, aborting foreach\n"); 00574 return -1; 00575 } 00576 00577 return 0; 00578 #else 00579 return -1; 00580 #endif 00581 } 00582 00583 //#define vertex_bbox(v) (v->bbox) 00585 toporouter_bbox_t * 00586 vertex_bbox(toporouter_vertex_t *v) 00587 { 00588 return v ? v->bbox : NULL; 00589 } 00590 //*/ 00591 char * 00592 vertex_netlist(toporouter_vertex_t *v) 00593 { 00594 toporouter_bbox_t *box = vertex_bbox(v); 00595 00596 if(box && box->cluster) return box->cluster->netlist->netlist; 00597 00598 return NULL; 00599 } 00600 00601 char * 00602 constraint_netlist(toporouter_constraint_t *c) 00603 { 00604 toporouter_bbox_t *box = c->box; 00605 00606 if(box && box->cluster) return box->cluster->netlist->netlist; 00607 00608 return NULL; 00609 } 00610 00611 static inline guint 00612 epsilon_equals(gdouble a, gdouble b) 00613 { 00614 if(a > b - EPSILON && a < b + EPSILON) return 1; 00615 return 0; 00616 } 00617 00621 void 00622 print_bbox(toporouter_bbox_t *box) 00623 { 00624 printf("[BBOX "); 00625 switch(box->type) { 00626 case PAD: 00627 printf("PAD "); break; 00628 case PIN: 00629 printf("PIN "); break; 00630 case VIA: 00631 printf("VIA "); break; 00632 case LINE: 00633 printf("LINE "); break; 00634 case BOARD: 00635 printf("BOARD "); break; 00636 case POLYGON: 00637 printf("POLYGON "); break; 00638 default: 00639 printf("UNKNOWN "); break; 00640 } 00641 00642 if(box->point) 00643 printf("P: %f,%f,%f ", vx(box->point), vy(box->point), vz(box->point)); 00644 else 00645 printf("P: NONE "); 00646 00647 printf("LAYER: %d ", box->layer); 00648 printf("CLUSTER: %d]\n", box->cluster ? box->cluster->c : -1); 00649 00650 } 00651 00655 void 00656 print_vertex(toporouter_vertex_t *v) 00657 { 00658 if(v) 00659 printf("[V %f,%f,%f ", vx(v), vy(v), vz(v)); 00660 else 00661 printf("[V (null) "); 00662 00663 printf("%s ", vertex_netlist(v)); 00664 if(v->route && v->route->netlist) 00665 printf("%s ", v->route->netlist->netlist); 00666 00667 if(v->routingedge) { 00668 guint n = g_list_length(edge_routing(v->routingedge)); 00669 guint pos = g_list_index(edge_routing(v->routingedge), v); 00670 00671 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 00672 printf("[CONST "); 00673 else 00674 printf("[EDGE "); 00675 00676 printf("%d/%d] ", pos, n); 00677 00678 } 00679 00680 00681 if(v->flags & VERTEX_FLAG_TEMP) printf("TEMP "); 00682 if(v->flags & VERTEX_FLAG_ROUTE) printf("ROUTE "); 00683 if(v->flags & VERTEX_FLAG_SPECCUT) printf("SPECCUT "); 00684 if(v->flags & VERTEX_FLAG_FAKE) printf("FAKE "); 00685 00686 printf("]\n"); 00687 00688 } 00689 00690 gdouble 00691 vertex_net_thickness(toporouter_vertex_t *v) 00692 { 00693 toporouter_bbox_t *box = vertex_bbox(v); 00694 00695 if(!box) { 00696 00697 while(v && (v->flags & VERTEX_FLAG_TEMP || v->flags & VERTEX_FLAG_ROUTE)) { 00698 v = v->parent; 00699 } 00700 00701 box = vertex_bbox(v); 00702 00703 }else{ 00704 if(box->type == PIN || box->type == VIA) { 00705 PinType *pin = (PinType *)box->data; 00706 if(TEST_FLAG(SQUAREFLAG, pin) || TEST_FLAG(OCTAGONFLAG, pin)) { 00707 return 0.; 00708 } 00709 // return ((PinType *)box->data)->Thickness + 1.; 00710 return ((PinType *)box->data)->Thickness; 00711 }else if(box->type == PAD) { 00712 PadType *pad = (PadType *)box->data; 00713 if(pad->Point1.X == pad->Point2.X && pad->Point1.Y == pad->Point2.Y && !TEST_FLAG(SQUAREFLAG, pad)) { 00714 return pad->Thickness; 00715 } 00716 return 0.; 00717 }else if(box->type == BOARD) { 00718 return 0.; 00719 }else if(box->type == LINE) { 00720 LineType *line = (LineType *) box->data; 00721 return line->Thickness; 00722 }else if(box->type == POLYGON) { 00723 return 0.; 00724 } 00725 00726 printf("Unrecognized type in thickness lookup..\n"); 00727 } 00728 00729 // if(!box || !box->cluster) return Settings.LineThickness + 1.; 00730 if(!box || !box->cluster) return Settings.LineThickness; 00731 00732 return cluster_thickness(box->cluster); 00733 } 00734 00735 gdouble 00736 vertex_net_keepaway(toporouter_vertex_t *v) 00737 { 00738 toporouter_bbox_t *box = vertex_bbox(v); 00739 if(!box) { 00740 00741 while(v && (v->flags & VERTEX_FLAG_TEMP || v->flags & VERTEX_FLAG_ROUTE)) { 00742 v = v->parent; 00743 } 00744 box = vertex_bbox(v); 00745 } 00746 else{ 00747 // if(box->type == PIN || box->type == VIA) 00748 // return ((PinType *)box->data)->Clearance; 00749 // else if(box->type == PAD) 00750 // return ((PadType *)box->data)->Clearance; 00751 00752 } 00753 00754 // if(!box || !box->cluster) return Settings.Keepaway + 1.; 00755 if(!box || !box->cluster) return Settings.Keepaway; 00756 return cluster_keepaway(box->cluster); 00757 } 00758 00763 static void 00764 point_from_point_to_point (toporouter_vertex_t *a, 00765 toporouter_vertex_t *b, 00766 double d, 00767 double *x, double *y) 00768 { 00769 double theta = atan2 (vy(b) - vy(a), vx(b) - vx(a)); 00770 00771 *x = vx(a) + d * cos (theta); 00772 *y = vy(a) + d * sin (theta); 00773 } 00774 00775 static inline gint 00776 coord_wind(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy) 00777 { 00778 gdouble rval, dx1, dx2, dy1, dy2; 00779 dx1 = bx - ax; dy1 = by - ay; 00780 dx2 = cx - bx; dy2 = cy - by; 00781 rval = (dx1*dy2)-(dy1*dx2); 00782 return (rval > EPSILON) ? 1 : ((rval < -EPSILON) ? -1 : 0); 00783 } 00784 00793 int 00794 point_wind(GtsPoint *a, GtsPoint *b, GtsPoint *c) 00795 { 00796 gdouble rval, dx1, dx2, dy1, dy2; 00797 dx1 = b->x - a->x; dy1 = b->y - a->y; 00798 dx2 = c->x - b->x; dy2 = c->y - b->y; 00799 rval = (dx1*dy2)-(dy1*dx2); 00800 return (rval > EPSILON) ? 1 : ((rval < -EPSILON) ? -1 : 0); 00801 } 00802 00803 static inline int 00804 vertex_wind(GtsVertex *a, GtsVertex *b, GtsVertex *c) 00805 { 00806 return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c)); 00807 } 00808 00809 static inline int 00810 tvertex_wind(toporouter_vertex_t *a, toporouter_vertex_t *b, toporouter_vertex_t *c) 00811 { 00812 return point_wind(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c)); 00813 } 00814 00818 static void 00819 coord_move_towards_coord_values (double ax, double ay, 00820 double px, double py, 00821 double d, 00822 double *x, double *y) 00823 { 00824 double theta = atan2 (py - ay, px - ax); 00825 00826 *x = ax + d * cos (theta); 00827 *y = ay + d * sin (theta); 00828 } 00829 00833 static void 00834 vertex_move_towards_vertex_values (GtsVertex *v, 00835 GtsVertex *p, 00836 double d, 00837 double *x, double *y) 00838 { 00839 double theta = atan2 (GTS_POINT(p)->y - GTS_POINT(v)->y, 00840 GTS_POINT(p)->x - GTS_POINT(v)->x); 00841 00842 *x = GTS_POINT(v)->x + d * cos (theta); 00843 *y = GTS_POINT(v)->y + d * sin (theta); 00844 } 00845 00846 #define tv_on_layer(v,l) (l == TOPOROUTER_BBOX(TOPOROUTER_VERTEX(v)->boxes->data)->layer) 00847 00848 static inline gdouble 00849 min_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2) 00850 { 00851 00852 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms; 00853 // toporouter_edge_t *e = v1->routingedge; 00854 00855 v1halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v1)) / 2.; 00856 v2halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v2)) / 2.; 00857 00858 v1keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v1)); 00859 v2keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v2)); 00860 00861 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway); 00862 00863 #ifdef SPACING_DEBUG 00864 printf("v1halfthick = %f v2halfthick = %f v1keepaway = %f v2keepaway = %f ms = %f\n", 00865 v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms); 00866 #endif 00867 00868 return ms; 00869 } 00870 00871 // v1 is a vertex in the CDT, and v2 is a net... other way around? 00872 static inline gdouble 00873 min_vertex_net_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2) 00874 { 00875 00876 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms; 00877 00878 v1halfthick = vertex_net_thickness(TOPOROUTER_VERTEX(v1)) / 2.; 00879 v2halfthick = cluster_thickness(vertex_bbox(v2)->cluster) / 2.; 00880 00881 v1keepaway = vertex_net_keepaway(TOPOROUTER_VERTEX(v1)); 00882 v2keepaway = cluster_keepaway(vertex_bbox(v2)->cluster); 00883 00884 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway); 00885 00886 return ms; 00887 } 00888 00889 static inline gdouble 00890 min_oproute_vertex_spacing(toporouter_oproute_t *oproute, toporouter_vertex_t *v2) 00891 { 00892 00893 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms; 00894 00895 v1halfthick = lookup_thickness(oproute->style) / 2.; 00896 v2halfthick = vertex_net_thickness(v2) / 2.; 00897 00898 v1keepaway = lookup_keepaway(oproute->style); 00899 v2keepaway = vertex_net_keepaway(v2); 00900 00901 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway); 00902 00903 return ms; 00904 } 00905 00906 gdouble 00907 min_oproute_net_spacing(toporouter_oproute_t *oproute, toporouter_vertex_t *v2) 00908 { 00909 00910 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms; 00911 00912 v1halfthick = lookup_thickness(oproute->style) / 2.; 00913 v2halfthick = cluster_thickness(v2->route->src) / 2.; 00914 00915 v1keepaway = lookup_keepaway(oproute->style); 00916 v2keepaway = cluster_keepaway(v2->route->src); 00917 00918 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway); 00919 00920 return ms; 00921 } 00922 00923 gdouble 00924 min_net_net_spacing(toporouter_vertex_t *v1, toporouter_vertex_t *v2) 00925 { 00926 00927 gdouble v1halfthick, v2halfthick, v1keepaway, v2keepaway, ms; 00928 00929 v1halfthick = cluster_thickness(v1->route->src) / 2.; 00930 v2halfthick = cluster_thickness(v2->route->src) / 2.; 00931 00932 v1keepaway = cluster_keepaway(v1->route->src); 00933 v2keepaway = cluster_keepaway(v2->route->src); 00934 00935 ms = v1halfthick + v2halfthick + MAX(v1keepaway, v2keepaway); 00936 00937 return ms; 00938 } 00939 00940 void 00941 toporouter_draw_cluster(toporouter_t *r, drawing_context_t *dc, toporouter_cluster_t *cluster, gdouble red, gdouble green, gdouble blue, guint layer) 00942 { 00943 #if TOPO_OUTPUT_ENABLED 00944 //GList *i = cluster->i; 00945 00946 //while(i) { 00947 // toporouter_bbox_t *box = TOPOROUTER_BBOX(i->data); 00948 00949 // if(box->point && vz(box->point) == layer) { 00950 // cairo_set_source_rgba(dc->cr, red, green, blue, 0.8f); 00951 // cairo_arc(dc->cr, vx(box->point) * dc->s + MARGIN, vy(box->point) * dc->s + MARGIN, MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00952 // cairo_fill(dc->cr); 00953 // } 00954 00955 // i = i->next; 00956 //} 00957 #endif 00958 } 00959 00960 void 00961 toporouter_draw_surface(toporouter_t *r, GtsSurface *s, char *filename, int w, int h, int mode, GList *datas, int layer, GList *candidatepoints) 00962 { 00963 #if TOPO_OUTPUT_ENABLED 00964 drawing_context_t *dc; 00965 GList *i; 00966 toporouter_vertex_t *tv, *tv2 = NULL; 00967 00968 dc = toporouter_output_init(w, h, filename); 00969 dc->mode = mode; 00970 dc->data = NULL; 00971 00972 gts_surface_foreach_edge(s, toporouter_draw_edge, dc); 00973 gts_surface_foreach_vertex(s, toporouter_draw_vertex, dc); 00974 00975 i = r->routednets; 00976 while(i) { 00977 GList *j = TOPOROUTER_ROUTE(i->data)->path; 00978 tv2 = NULL; 00979 while(j) { 00980 tv = TOPOROUTER_VERTEX(j->data); 00981 if(GTS_POINT(tv)->z == layer) { 00982 if(tv && tv2) { 00983 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.8f); 00984 cairo_move_to(dc->cr, 00985 GTS_POINT(tv)->x * dc->s + MARGIN, 00986 GTS_POINT(tv)->y * dc->s + MARGIN); 00987 cairo_line_to(dc->cr, 00988 GTS_POINT(tv2)->x * dc->s + MARGIN, 00989 GTS_POINT(tv2)->y * dc->s + MARGIN); 00990 cairo_stroke(dc->cr); 00991 } 00992 00993 if(tv->flags & VERTEX_FLAG_RED) { 00994 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f); 00995 cairo_arc(dc->cr, 00996 tv->v.p.x * dc->s + MARGIN, 00997 tv->v.p.y * dc->s + MARGIN, 00998 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 00999 cairo_fill(dc->cr); 01000 01001 }else if(tv->flags & VERTEX_FLAG_GREEN) { 01002 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f); 01003 cairo_arc(dc->cr, 01004 tv->v.p.x * dc->s + MARGIN, 01005 tv->v.p.y * dc->s + MARGIN, 01006 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01007 cairo_fill(dc->cr); 01008 01009 }else if(tv->flags & VERTEX_FLAG_BLUE) { 01010 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f); 01011 cairo_arc(dc->cr, 01012 tv->v.p.x * dc->s + MARGIN, 01013 tv->v.p.y * dc->s + MARGIN, 01014 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01015 cairo_fill(dc->cr); 01016 01017 } 01018 else { 01019 01020 cairo_set_source_rgba(dc->cr, 1., 1., 1., 0.8f); 01021 cairo_arc(dc->cr, 01022 tv->v.p.x * dc->s + MARGIN, 01023 tv->v.p.y * dc->s + MARGIN, 01024 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01025 cairo_fill(dc->cr); 01026 01027 01028 } 01029 01030 if(tv->routingedge && !TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) { 01031 gdouble tempx, tempy, nms, pms; 01032 GList *i = g_list_find(edge_routing(tv->routingedge), tv); 01033 toporouter_vertex_t *nextv, *prevv; 01034 01035 nextv = edge_routing_next(tv->routingedge,i); 01036 prevv = edge_routing_prev(tv->routingedge,i); 01037 01038 nms = min_spacing(tv,nextv); 01039 pms = min_spacing(tv,prevv); 01040 01041 g_assert(isfinite(nms)); g_assert(isfinite(pms)); 01042 01043 point_from_point_to_point(tv, nextv, nms, &tempx, &tempy); 01044 01045 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 1.0f, 0.8f); 01046 cairo_move_to(dc->cr, vx(tv) * dc->s + MARGIN, vy(tv) * dc->s + MARGIN); 01047 cairo_line_to(dc->cr, tempx * dc->s + MARGIN, tempy * dc->s + MARGIN); 01048 cairo_stroke(dc->cr); 01049 01050 point_from_point_to_point(tv, prevv, pms, &tempx, &tempy); 01051 01052 cairo_move_to(dc->cr, vx(tv) * dc->s + MARGIN, vy(tv) * dc->s + MARGIN); 01053 cairo_line_to(dc->cr, tempx * dc->s + MARGIN, tempy * dc->s + MARGIN); 01054 cairo_stroke(dc->cr); 01055 01056 01057 01058 01059 } 01060 01061 01062 } 01063 tv2 = tv; 01064 j = j->next; 01065 } 01066 i = i->next; 01067 } 01068 01069 while(datas) { 01070 toporouter_route_t *routedata = (toporouter_route_t *) datas->data; 01071 01072 GList *i;//, *k; 01073 01074 toporouter_draw_cluster(r, dc, routedata->src, 1., 0., 0., layer); 01075 toporouter_draw_cluster(r, dc, routedata->dest, 0., 0., 1., layer); 01076 01077 tv2 = NULL; 01078 i = routedata->path; 01079 while(i) { 01080 tv = TOPOROUTER_VERTEX(i->data); 01081 if(GTS_POINT(tv)->z == layer) { 01082 if(tv && tv2) { 01083 cairo_set_source_rgba(dc->cr, 0.0f, 1.0f, 0.0f, 0.8f); 01084 cairo_move_to(dc->cr, 01085 GTS_POINT(tv)->x * dc->s + MARGIN, 01086 GTS_POINT(tv)->y * dc->s + MARGIN); 01087 cairo_line_to(dc->cr, 01088 GTS_POINT(tv2)->x * dc->s + MARGIN, 01089 GTS_POINT(tv2)->y * dc->s + MARGIN); 01090 cairo_stroke(dc->cr); 01091 } 01092 } 01093 tv2 = tv; 01094 i = i->next; 01095 } 01096 01097 01098 if(routedata->alltemppoints) { 01099 GList *i, *j; 01100 i = j = g_hash_table_get_keys (routedata->alltemppoints); 01101 while(i) { 01102 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 01103 01104 if(GTS_POINT(tv)->z != layer) { 01105 i = i->next; 01106 continue; 01107 } 01108 if(tv->flags & VERTEX_FLAG_BLUE) { 01109 cairo_set_source_rgba(dc->cr, 0., 0., 1., 0.8f); 01110 cairo_arc(dc->cr, 01111 tv->v.p.x * dc->s + MARGIN, 01112 tv->v.p.y * dc->s + MARGIN, 01113 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01114 cairo_fill(dc->cr); 01115 }else if(tv->flags & VERTEX_FLAG_RED) { 01116 cairo_set_source_rgba(dc->cr, 1., 0., 0., 0.8f); 01117 cairo_arc(dc->cr, 01118 tv->v.p.x * dc->s + MARGIN, 01119 tv->v.p.y * dc->s + MARGIN, 01120 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01121 cairo_fill(dc->cr); 01122 01123 }else if(tv->flags & VERTEX_FLAG_GREEN) { 01124 cairo_set_source_rgba(dc->cr, 0., 1., 0., 0.8f); 01125 cairo_arc(dc->cr, 01126 tv->v.p.x * dc->s + MARGIN, 01127 tv->v.p.y * dc->s + MARGIN, 01128 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01129 cairo_fill(dc->cr); 01130 }else{ 01131 cairo_set_source_rgba(dc->cr, 1., 1., 1., 0.8f); 01132 cairo_arc(dc->cr, 01133 tv->v.p.x * dc->s + MARGIN, 01134 tv->v.p.y * dc->s + MARGIN, 01135 MIL_TO_COORD (5.) * dc->s, 0, 2 * M_PI); 01136 cairo_fill(dc->cr); 01137 } 01138 i = i->next; 01139 } 01140 g_list_free(j); 01141 } 01142 datas = datas->next; 01143 } 01144 toporouter_output_close(dc); 01145 #endif 01146 } 01147 01148 01152 void 01153 toporouter_layer_free(toporouter_layer_t *l) 01154 { 01155 g_list_free(l->vertices); 01156 g_list_free(l->constraints); 01157 01158 } 01159 01160 guint 01161 groupcount(void) 01162 { 01163 int group; 01164 guint count = 0; 01165 01166 for (group = 0; group < max_group; group++) { 01167 if(PCB->LayerGroups.Number[group] > 0) count++; 01168 } 01169 01170 return count; 01171 } 01172 01173 void 01174 toporouter_free(toporouter_t *r) 01175 { 01176 struct timeval endtime; 01177 double time_delta; 01178 01179 int i; 01180 for(i=0;i<groupcount();i++) { 01181 toporouter_layer_free(&r->layers[i]); 01182 } 01183 01184 gettimeofday (&endtime, NULL); 01185 time_delta = endtime.tv_sec - r->starttime.tv_sec + 01186 (endtime.tv_usec - r->starttime.tv_usec) / 1000000.; 01187 01188 Message(_("Elapsed time: %.2f seconds\n"), time_delta); 01189 free(r->layers); 01190 free(r); 01191 01192 } 01193 01202 int 01203 wind(toporouter_spoint_t *p1, toporouter_spoint_t *p2, toporouter_spoint_t *p3) 01204 { 01205 double rval, dx1, dx2, dy1, dy2; 01206 dx1 = p2->x - p1->x; dy1 = p2->y - p1->y; 01207 dx2 = p3->x - p2->x; dy2 = p3->y - p2->y; 01208 rval = (dx1*dy2)-(dy1*dx2); 01209 return (rval > 0.0001) ? 1 : ((rval < -0.0001) ? -1 : 0); /* XXX: Depends on PCB coordinate scaling */ 01210 } 01211 01212 static inline void 01213 print_toporouter_constraint(toporouter_constraint_t *tc) 01214 { 01215 printf("%f,%f -> %f,%f ", 01216 tc->c.edge.segment.v1->p.x, 01217 tc->c.edge.segment.v1->p.y, 01218 tc->c.edge.segment.v2->p.x, 01219 tc->c.edge.segment.v2->p.y); 01220 } 01221 01222 static inline void 01223 print_toporouter_vertex(toporouter_vertex_t *tv) 01224 { 01225 printf("%f,%f ", tv->v.p.x, tv->v.p.y); 01226 } 01227 01228 01237 static void 01238 vertices_on_line (toporouter_spoint_t *a, 01239 double m, 01240 double r, 01241 toporouter_spoint_t *b0, 01242 toporouter_spoint_t *b1) 01243 { 01244 01245 double c, dx; 01246 01247 if (m == INFINITY || m == -INFINITY) { 01248 01249 b0->x = a->x; 01250 b0->y = a->y + r; 01251 01252 b1->x = a->x; 01253 b1->y = a->y - r; 01254 01255 return; 01256 } 01257 01258 c = a->y - m * a->x; 01259 dx = r / hypot (1, m); 01260 01261 b0->x = a->x + dx; 01262 b0->y = m * b0->x + c; 01263 01264 b1->x = a->x - dx; 01265 b1->y = m * b1->x + c; 01266 } 01267 01276 static void 01277 coords_on_line (double ax, gdouble ay, 01278 double m, 01279 double r, 01280 double *b0x, double *b0y, 01281 double *b1x, double *b1y) 01282 { 01283 double c, dx; 01284 01285 if (m == INFINITY || m == -INFINITY) { 01286 01287 *b0x = ax; 01288 *b0y = ay + r; 01289 01290 *b1x = ax; 01291 *b1y = ay - r; 01292 01293 return; 01294 } 01295 01296 c = ay - m * ax; 01297 dx = r / hypot (1, m); 01298 01299 *b0x = ax + dx; 01300 *b0y = m * *b0x + c; 01301 01302 *b1x = ax - dx; 01303 *b1y = m * *b1x + c; 01304 } 01305 01309 gdouble 01310 vertex_gradient(toporouter_spoint_t *a, toporouter_spoint_t *b) 01311 { 01312 if(a->x == b->x) return INFINITY; 01313 01314 return ((b->y - a->y) / (b->x - a->x)); 01315 } 01316 01320 static inline gdouble 01321 cartesian_gradient(gdouble x0, gdouble y0, gdouble x1, gdouble y1) 01322 { 01323 if(epsilon_equals(x0,x1)) return INFINITY; 01324 01325 return ((y1 - y0) / (x1 - x0)); 01326 } 01327 01331 static inline gdouble 01332 point_gradient(GtsPoint *a, GtsPoint *b) 01333 { 01334 return cartesian_gradient(a->x, a->y, b->x, b->y); 01335 } 01336 01337 gdouble 01338 segment_gradient(GtsSegment *s) 01339 { 01340 return cartesian_gradient( 01341 GTS_POINT(s->v1)->x, 01342 GTS_POINT(s->v1)->y, 01343 GTS_POINT(s->v2)->x, 01344 GTS_POINT(s->v2)->y); 01345 } 01346 01350 gdouble 01351 perpendicular_gradient(gdouble m) 01352 { 01353 if(isinf(m)) return 0.0f; 01354 if(m < EPSILON && m > -EPSILON) return INFINITY; 01355 return -1.0f/m; 01356 } 01357 01361 gdouble 01362 vertices_plane_distance(toporouter_spoint_t *a, toporouter_spoint_t *b) { 01363 return hypot(a->x - b->x, a->y - b->y); 01364 } 01365 01370 static inline void 01371 vertex_outside_segment(toporouter_spoint_t *a, toporouter_spoint_t *b, gdouble r, toporouter_spoint_t *p) 01372 { 01373 toporouter_spoint_t temp[2]; 01374 01375 vertices_on_line(a, vertex_gradient(a,b), r, &temp[0], &temp[1]); 01376 01377 if(vertices_plane_distance(&temp[0], b) > vertices_plane_distance(&temp[1], b)) { 01378 p->x = temp[0].x; 01379 p->y = temp[0].y; 01380 }else{ 01381 p->x = temp[1].x; 01382 p->y = temp[1].y; 01383 } 01384 01385 } 01386 01395 static bool 01396 coord_intersect_prop (double ax, double ay, 01397 double bx, double by, 01398 double cx, double cy, 01399 double dx, double dy) 01400 { 01401 int wind_abc = coord_wind (ax, ay, bx, by, cx, cy); 01402 int wind_abd = coord_wind (ax, ay, bx, by, dx, dy); 01403 int wind_cda = coord_wind (cx, cy, dx, dy, ax, ay); 01404 int wind_cdb = coord_wind (cx, cy, dx, dy, bx, by); 01405 01406 /* If any of the line end-points are colinear with the other line, return false */ 01407 if (wind_abc == 0 || wind_abd == 0 || wind_cda == 0 || wind_cdb == 0) 01408 return false; 01409 01410 return (wind_abc != wind_abd) && (wind_cda != wind_cdb); 01411 } 01412 01421 static bool 01422 point_intersect_prop (GtsPoint *a, GtsPoint *b, GtsPoint *c, GtsPoint *d) 01423 { 01424 int wind_abc = point_wind (a, b, c); 01425 int wind_abd = point_wind (a, b, d); 01426 int wind_cda = point_wind (c, d, a); 01427 int wind_cdb = point_wind (c, d, b); 01428 01429 /* If any of the line end-points are colinear with the other line, return false */ 01430 if (wind_abc == 0 || wind_abd == 0 || wind_cda == 0 || wind_cdb == 0) 01431 return false; 01432 01433 return (wind_abc != wind_abd) && (wind_cda != wind_cdb); 01434 } 01435 01439 static inline int 01440 vertex_intersect_prop(GtsVertex *a, GtsVertex *b, GtsVertex *c, GtsVertex *d) 01441 { 01442 return point_intersect_prop(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c), GTS_POINT(d)); 01443 } 01444 01453 GtsVertex * 01454 vertex_intersect(GtsVertex *a, GtsVertex *b, GtsVertex *c, GtsVertex *d) 01455 { 01456 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 01457 GtsVertex *rval; 01458 gdouble ua_top, ua_bot, ua, rx, ry; 01459 01460 /* TODO: this could be done more efficiently without duplicating computation */ 01461 if(!vertex_intersect_prop(a, b, c, d)) return NULL; 01462 01463 ua_top = ((d->p.x - c->p.x) * (a->p.y - c->p.y)) - 01464 ((d->p.y - c->p.y) * (a->p.x - c->p.x)); 01465 ua_bot = ((d->p.y - c->p.y) * (b->p.x - a->p.x)) - 01466 ((d->p.x - c->p.x) * (b->p.y - a->p.y)); 01467 ua = ua_top / ua_bot; 01468 rx = a->p.x + (ua * (b->p.x - a->p.x)); 01469 ry = a->p.y + (ua * (b->p.y - a->p.y)); 01470 01471 rval = gts_vertex_new (vertex_class, rx, ry, 0.0f); 01472 01473 return rval; 01474 } 01475 01484 void 01485 coord_intersect(gdouble ax, gdouble ay, gdouble bx, gdouble by, gdouble cx, gdouble cy, gdouble dx, gdouble dy, gdouble *rx, gdouble *ry) 01486 { 01487 gdouble ua_top, ua_bot, ua; 01488 01489 ua_top = ((dx - cx) * (ay - cy)) - ((dy - cy) * (ax - cx)); 01490 ua_bot = ((dy - cy) * (bx - ax)) - ((dx - cx) * (by - ay)); 01491 ua = ua_top / ua_bot; 01492 *rx = ax + (ua * (bx - ax)); 01493 *ry = ay + (ua * (by - ay)); 01494 01495 } 01496 01497 01503 int 01504 point_between(GtsPoint *a, GtsPoint *b, GtsPoint *c) 01505 { 01506 if( point_wind(a, b, c) != 0 ) return 0; 01507 01508 if( a->x != b->x ) { 01509 return ((a->x <= c->x) && 01510 (c->x <= b->x)) || 01511 ((a->x >= c->x) && 01512 (c->x >= b->x)); 01513 } 01514 return ((a->y <= c->y) && 01515 (c->y <= b->y)) || 01516 ((a->y >= c->y) && 01517 (c->y >= b->y)); 01518 } 01519 01520 static inline int 01521 vertex_between(GtsVertex *a, GtsVertex *b, GtsVertex *c) 01522 { 01523 return point_between(GTS_POINT(a), GTS_POINT(b), GTS_POINT(c)); 01524 } 01525 01526 void 01527 delaunay_create_from_vertices(GList *vertices, GtsSurface **surface, GtsTriangle **t) 01528 { 01529 GList *i = vertices; 01530 GtsVertex *v1, *v2, *v3; 01531 GSList *vertices_slist = NULL; 01532 01533 while (i) { 01534 vertices_slist = g_slist_prepend(vertices_slist, i->data); 01535 i = i->next; 01536 } 01537 01538 // TODO: just work this out from the board outline 01539 *t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 100000.0f); 01540 gts_triangle_vertices (*t, &v1, &v2, &v3); 01541 01542 *surface = gts_surface_new (gts_surface_class (), gts_face_class (), 01543 GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) ); 01544 01545 gts_surface_add_face (*surface, gts_face_new (gts_face_class (), (*t)->e1, (*t)->e2, (*t)->e3)); 01546 01547 i = vertices; 01548 while (i) { 01549 toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (*surface, (GtsVertex *)i->data, NULL)); 01550 01551 if(v) { 01552 printf("ERROR: vertex could not be added to CDT "); 01553 print_vertex(v); 01554 } 01555 01556 i = i->next; 01557 } 01558 01559 gts_allow_floating_vertices = TRUE; 01560 gts_object_destroy (GTS_OBJECT (v1)); 01561 gts_object_destroy (GTS_OBJECT (v2)); 01562 gts_object_destroy (GTS_OBJECT (v3)); 01563 gts_allow_floating_vertices = FALSE; 01564 01565 g_slist_free(vertices_slist); 01566 // return surface; 01567 } 01568 01569 GSList * 01570 list_to_slist(GList *i) 01571 { 01572 GSList *rval = NULL; 01573 while(i) { 01574 rval = g_slist_prepend(rval, i->data); 01575 i = i->next; 01576 } 01577 return rval; 01578 } 01579 01580 toporouter_bbox_t * 01581 toporouter_bbox_create_from_points(int layer, GList *vertices, toporouter_term_t type, gpointer data) 01582 { 01583 toporouter_bbox_t *bbox; 01584 GSList *vertices_slist = list_to_slist(vertices); 01585 01586 // delaunay_create_from_vertices(vertices, &s, &t); 01587 bbox = TOPOROUTER_BBOX( gts_bbox_points(GTS_BBOX_CLASS(toporouter_bbox_class()), vertices_slist) ); 01588 bbox->type = type; 01589 bbox->data = data; 01590 01591 bbox->surface = NULL; 01592 bbox->enclosing = NULL; 01593 01594 bbox->layer = layer; 01595 01596 bbox->point = NULL; 01597 bbox->realpoint = NULL; 01598 01599 g_slist_free(vertices_slist); 01600 return bbox; 01601 } 01602 01603 toporouter_bbox_t * 01604 toporouter_bbox_create(int layer, GList *vertices, toporouter_term_t type, gpointer data) 01605 { 01606 toporouter_bbox_t *bbox; 01607 GtsSurface *s; 01608 GtsTriangle *t; 01609 01610 delaunay_create_from_vertices(vertices, &s, &t); 01611 bbox = TOPOROUTER_BBOX( gts_bbox_surface(GTS_BBOX_CLASS(toporouter_bbox_class()), s) ); 01612 bbox->type = type; 01613 bbox->data = data; 01614 01615 bbox->surface = s; 01616 bbox->enclosing = t; 01617 01618 bbox->layer = layer; 01619 01620 return bbox; 01621 } 01622 01623 GtsVertex * 01624 insert_vertex(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y, toporouter_bbox_t *box) 01625 { 01626 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 01627 GtsVertex *v; 01628 GList *i; 01629 01630 i = l->vertices; 01631 while (i) { 01632 v = (GtsVertex *)i->data; 01633 if(v->p.x == x && v->p.y == y) { 01634 TOPOROUTER_VERTEX(v)->bbox = box; 01635 return v; 01636 } 01637 i = i->next; 01638 } 01639 01640 v = gts_vertex_new (vertex_class , x, y, l - r->layers); 01641 TOPOROUTER_VERTEX(v)->bbox = box; 01642 l->vertices = g_list_prepend(l->vertices, v); 01643 01644 return v; 01645 } 01646 01647 GList * 01648 insert_constraint_edge(toporouter_t *r, toporouter_layer_t *l, gdouble x1, gdouble y1, guint flags1, 01649 gdouble x2, gdouble y2, guint flags2, toporouter_bbox_t *box) 01650 { 01651 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 01652 GtsEdgeClass *edge_class = GTS_EDGE_CLASS (toporouter_constraint_class ()); 01653 GtsVertex *p[2]; 01654 GtsVertex *v; 01655 GList *i; 01656 GtsEdge *e; 01657 01658 p[0] = p[1] = NULL; 01659 01660 /* insert or find points */ 01661 01662 i = l->vertices; 01663 while (i) { 01664 v = (GtsVertex *)i->data; 01665 if(v->p.x == x1 && v->p.y == y1) 01666 p[0] = v; 01667 if(v->p.x == x2 && v->p.y == y2) 01668 p[1] = v; 01669 i = i->next; 01670 } 01671 01672 if(p[0] == NULL) { 01673 p[0] = gts_vertex_new (vertex_class, x1, y1, l - r->layers); 01674 TOPOROUTER_VERTEX(p[0])->bbox = box; 01675 l->vertices = g_list_prepend(l->vertices, p[0]); 01676 } 01677 if(p[1] == NULL) { 01678 p[1] = gts_vertex_new (vertex_class, x2, y2, l - r->layers); 01679 TOPOROUTER_VERTEX(p[1])->bbox = box; 01680 l->vertices = g_list_prepend(l->vertices, p[1]); 01681 } 01682 01683 TOPOROUTER_VERTEX(p[0])->flags = flags1; 01684 TOPOROUTER_VERTEX(p[1])->flags = flags2; 01685 01686 e = gts_edge_new (edge_class, p[0], p[1]); 01687 TOPOROUTER_CONSTRAINT(e)->box = box; 01688 l->constraints = g_list_prepend (l->constraints, e); 01689 // return insert_constraint_edge_rec(r, l, p, box); 01690 return g_list_prepend(NULL, e); 01691 01692 } 01693 01694 void 01695 insert_constraints_from_list(toporouter_t *r, toporouter_layer_t *l, GList *vlist, toporouter_bbox_t *box) 01696 { 01697 GList *i = vlist; 01698 toporouter_vertex_t *pv = NULL, *v; 01699 01700 while(i) { 01701 v = TOPOROUTER_VERTEX(i->data); 01702 01703 if(pv) { 01704 box->constraints = 01705 g_list_concat(box->constraints, insert_constraint_edge(r, l, vx(v), vy(v), v->flags, vx(pv), vy(pv), pv->flags, box)); 01706 } 01707 01708 pv = v; 01709 i = i->next; 01710 } 01711 01712 v = TOPOROUTER_VERTEX(vlist->data); 01713 box->constraints = 01714 g_list_concat(box->constraints, insert_constraint_edge(r, l, vx(v), vy(v), v->flags, vx(pv), vy(pv), pv->flags, box)); 01715 01716 } 01717 01718 void 01719 insert_centre_point(toporouter_t *r, toporouter_layer_t *l, gdouble x, gdouble y) 01720 { 01721 GList *i; 01722 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 01723 01724 i = l->vertices; 01725 while (i) { 01726 GtsPoint *p = GTS_POINT(i->data); 01727 if(p->x == x && p->y == y) 01728 return; 01729 i = i->next; 01730 } 01731 01732 l->vertices = g_list_prepend(l->vertices, gts_vertex_new(vertex_class, x, y, 0.0f)); 01733 } 01734 01735 GtsPoint * 01736 midpoint(GtsPoint *a, GtsPoint *b) 01737 { 01738 return gts_point_new(gts_point_class(), (a->x + b->x) / 2., (a->y + b->y) / 2., 0.); 01739 } 01740 01741 static inline gdouble 01742 pad_rad(PadType *pad) 01743 { 01744 return (lookup_thickness(pad->Name) / 2.) + lookup_keepaway(pad->Name); 01745 } 01746 01747 static inline gdouble 01748 pin_rad(PinType *pin) 01749 { 01750 return (lookup_thickness(pin->Name) / 2.) + lookup_keepaway(pin->Name); 01751 } 01752 01753 GList * 01754 rect_with_attachments(gdouble rad, 01755 gdouble x0, gdouble y0, 01756 gdouble x1, gdouble y1, 01757 gdouble x2, gdouble y2, 01758 gdouble x3, gdouble y3, 01759 gdouble z) 01760 { 01761 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 01762 GList *r = NULL, *rr = NULL, *i; 01763 toporouter_vertex_t *curpoint, *temppoint; 01764 01765 01766 curpoint = TOPOROUTER_VERTEX(gts_vertex_new (vertex_class, x0, y0, z)); 01767 01768 r = g_list_prepend(NULL, curpoint); 01769 r = g_list_prepend(r, gts_vertex_new (vertex_class, x1, y1, z)); 01770 r = g_list_prepend(r, gts_vertex_new (vertex_class, x2, y2, z)); 01771 r = g_list_prepend(r, gts_vertex_new (vertex_class, x3, y3, z)); 01772 01773 i = r; 01774 while(i) { 01775 temppoint = TOPOROUTER_VERTEX(i->data); 01776 rr = g_list_prepend(rr, curpoint); 01777 01778 curpoint = temppoint; 01779 i = i->next; 01780 } 01781 01782 g_list_free(r); 01783 01784 return rr; 01785 } 01786 01787 #define VERTEX_CENTRE(x) TOPOROUTER_VERTEX( vertex_bbox(x)->point ) 01788 01794 int 01795 read_pads(toporouter_t *r, toporouter_layer_t *l, guint layer) 01796 { 01797 toporouter_spoint_t p[2], rv[5]; 01798 gdouble x[2], y[2], t, m; 01799 01800 GList *vlist = NULL; 01801 toporouter_bbox_t *bbox = NULL; 01802 01803 guint front = GetLayerGroupNumberBySide (TOP_SIDE); 01804 guint back = GetLayerGroupNumberBySide (BOTTOM_SIDE); 01805 01806 // printf("read_pads: front = %d back = %d layer = %d\n", 01807 // front, back, layer); 01808 01809 /* If its not the top or bottom layer, there are no pads to read */ 01810 if(l - r->layers != front && l - r->layers != back) return 0; 01811 01812 ELEMENT_LOOP(PCB->Data); 01813 { 01814 PAD_LOOP(element); 01815 { 01816 if( (l - r->layers == back && TEST_FLAG(ONSOLDERFLAG, pad)) || 01817 (l - r->layers == front && !TEST_FLAG(ONSOLDERFLAG, pad)) ) { 01818 01819 t = (gdouble)pad->Thickness / 2.0f; 01820 x[0] = pad->Point1.X; 01821 x[1] = pad->Point2.X; 01822 y[0] = pad->Point1.Y; 01823 y[1] = pad->Point2.Y; 01824 01825 01826 if(TEST_FLAG(SQUAREFLAG, pad)) { 01827 /* Square or oblong pad. Four points and four constraint edges are 01828 * used */ 01829 01830 if(x[0] == x[1] && y[0] == y[1]) { 01831 /* Pad is square */ 01832 01833 // vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, x[0]-t, y[0]-t, 0.)); 01834 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]-t, y[0]+t, 0.)); 01835 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]+t, y[0]+t, 0.)); 01836 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, x[0]+t, y[0]-t, 0.)); 01837 vlist = rect_with_attachments(pad_rad(pad), 01838 x[0]-t, y[0]-t, 01839 x[0]-t, y[0]+t, 01840 x[0]+t, y[0]+t, 01841 x[0]+t, y[0]-t, 01842 l - r->layers); 01843 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad); 01844 r->bboxes = g_slist_prepend(r->bboxes, bbox); 01845 insert_constraints_from_list(r, l, vlist, bbox); 01846 g_list_free(vlist); 01847 01848 //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, x[0], y[0], 0.) ); 01849 bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) ); 01850 g_assert(TOPOROUTER_VERTEX(bbox->point)->bbox == bbox); 01851 }else { 01852 /* Pad is diagonal oblong or othogonal oblong */ 01853 01854 m = cartesian_gradient(x[0], y[0], x[1], y[1]); 01855 01856 p[0].x = x[0]; p[0].y = y[0]; 01857 p[1].x = x[1]; p[1].y = y[1]; 01858 01859 vertex_outside_segment(&p[0], &p[1], t, &rv[0]); 01860 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[1], &rv[2]); 01861 01862 vertex_outside_segment(&p[1], &p[0], t, &rv[0]); 01863 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[3], &rv[4]); 01864 01865 if(wind(&rv[1], &rv[2], &rv[3]) != wind(&rv[2], &rv[3], &rv[4])) { 01866 rv[0].x = rv[3].x; rv[0].y = rv[3].y; 01867 rv[3].x = rv[4].x; rv[3].y = rv[4].y; 01868 rv[4].x = rv[0].x; rv[4].y = rv[0].y; 01869 } 01870 01871 // vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, rv[1].x, rv[1].y, 0.)); 01872 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[2].x, rv[2].y, 0.)); 01873 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[3].x, rv[3].y, 0.)); 01874 // vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, rv[4].x, rv[4].y, 0.)); 01875 vlist = rect_with_attachments(pad_rad(pad), 01876 rv[1].x, rv[1].y, 01877 rv[2].x, rv[2].y, 01878 rv[3].x, rv[3].y, 01879 rv[4].x, rv[4].y, 01880 l - r->layers); 01881 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad); 01882 r->bboxes = g_slist_prepend(r->bboxes, bbox); 01883 insert_constraints_from_list(r, l, vlist, bbox); 01884 g_list_free(vlist); 01885 01886 //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., 0.) ); 01887 bbox->point = GTS_POINT( insert_vertex(r, l, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., bbox) ); 01888 g_assert(TOPOROUTER_VERTEX(bbox->point)->bbox == bbox); 01889 01890 } 01891 01892 }else { 01893 /* Either round pad or pad with curved edges */ 01894 01895 if(x[0] == x[1] && y[0] == y[1]) { 01896 /* One point */ 01897 01898 /* bounding box same as square pad */ 01899 vlist = rect_with_attachments(pad_rad(pad), 01900 x[0]-t, y[0]-t, 01901 x[0]-t, y[0]+t, 01902 x[0]+t, y[0]+t, 01903 x[0]+t, y[0]-t, 01904 l - r->layers); 01905 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad); 01906 r->bboxes = g_slist_prepend(r->bboxes, bbox); 01907 g_list_free(vlist); 01908 01909 //bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) ); 01910 bbox->point = GTS_POINT( insert_vertex(r, l, x[0], y[0], bbox) ); 01911 01912 }else{ 01913 /* Two points and one constraint edge */ 01914 01915 /* the rest is just for bounding box */ 01916 m = cartesian_gradient(x[0], y[0], x[1], y[1]); 01917 01918 p[0].x = x[0]; p[0].y = y[0]; 01919 p[1].x = x[1]; p[1].y = y[1]; 01920 01921 vertex_outside_segment(&p[0], &p[1], t, &rv[0]); 01922 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[1], &rv[2]); 01923 01924 vertex_outside_segment(&p[1], &p[0], t, &rv[0]); 01925 vertices_on_line(&rv[0], perpendicular_gradient(m), t, &rv[3], &rv[4]); 01926 01927 if(wind(&rv[1], &rv[2], &rv[3]) != wind(&rv[2], &rv[3], &rv[4])) { 01928 rv[0].x = rv[3].x; rv[0].y = rv[3].y; 01929 rv[3].x = rv[4].x; rv[3].y = rv[4].y; 01930 rv[4].x = rv[0].x; rv[4].y = rv[0].y; 01931 } 01932 01933 vlist = rect_with_attachments(pad_rad(pad), 01934 rv[1].x, rv[1].y, 01935 rv[2].x, rv[2].y, 01936 rv[3].x, rv[3].y, 01937 rv[4].x, rv[4].y, 01938 l - r->layers); 01939 bbox = toporouter_bbox_create(l - r->layers, vlist, PAD, pad); 01940 r->bboxes = g_slist_prepend(r->bboxes, bbox); 01941 insert_constraints_from_list(r, l, vlist, bbox); 01942 g_list_free(vlist); 01943 01944 //bbox->point = GTS_POINT( gts_vertex_new(vertex_class, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., 0.) ); 01945 bbox->point = GTS_POINT( insert_vertex(r, l, (x[0] + x[1]) / 2., (y[0] + y[1]) / 2., bbox) ); 01946 01947 //bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, x[0], y[0], x[1], y[1], bbox)); 01948 01949 } 01950 01951 01952 } 01953 01954 } 01955 } 01956 END_LOOP; 01957 } 01958 END_LOOP; 01959 01960 return 0; 01961 } 01962 01968 int 01969 read_points(toporouter_t *r, toporouter_layer_t *l, int layer) 01970 { 01971 gdouble x, y, t; 01972 01973 GList *vlist = NULL; 01974 toporouter_bbox_t *bbox = NULL; 01975 01976 ELEMENT_LOOP(PCB->Data); 01977 { 01978 PIN_LOOP(element); 01979 { 01980 01981 t = (gdouble)pin->Thickness / 2.0f; 01982 x = pin->X; 01983 y = pin->Y; 01984 01985 if(TEST_FLAG (SQUAREFLAG, pin)) { 01986 01987 vlist = rect_with_attachments(pin_rad(pin), 01988 x-t, y-t, 01989 x-t, y+t, 01990 x+t, y+t, 01991 x+t, y-t, 01992 l - r->layers); 01993 bbox = toporouter_bbox_create(l - r->layers, vlist, PIN, pin); 01994 r->bboxes = g_slist_prepend(r->bboxes, bbox); 01995 insert_constraints_from_list(r, l, vlist, bbox); 01996 g_list_free(vlist); 01997 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) ); 01998 01999 }else if(TEST_FLAG(OCTAGONFLAG, pin)){ 02000 /* TODO: Handle octagon pins */ 02001 fprintf(stderr, "No support for octagon pins yet\n"); 02002 }else{ 02003 vlist = rect_with_attachments(pin_rad(pin), 02004 x-t, y-t, 02005 x-t, y+t, 02006 x+t, y+t, 02007 x+t, y-t, 02008 l - r->layers); 02009 bbox = toporouter_bbox_create(l - r->layers, vlist, PIN, pin); 02010 r->bboxes = g_slist_prepend(r->bboxes, bbox); 02011 g_list_free(vlist); 02012 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) ); 02013 } 02014 } 02015 END_LOOP; 02016 } 02017 END_LOOP; 02018 02019 VIA_LOOP(PCB->Data); 02020 { 02021 02022 t = (gdouble)via->Thickness / 2.0f; 02023 x = via->X; 02024 y = via->Y; 02025 02026 if(TEST_FLAG (SQUAREFLAG, via)) { 02027 02028 vlist = rect_with_attachments(pin_rad((PinType*)via), 02029 x-t, y-t, 02030 x-t, y+t, 02031 x+t, y+t, 02032 x+t, y-t, 02033 l - r->layers); 02034 bbox = toporouter_bbox_create(l - r->layers, vlist, VIA, via); 02035 r->bboxes = g_slist_prepend(r->bboxes, bbox); 02036 insert_constraints_from_list(r, l, vlist, bbox); 02037 g_list_free(vlist); 02038 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) ); 02039 02040 }else if(TEST_FLAG(OCTAGONFLAG, via)){ 02041 /* TODO: Handle octagon vias */ 02042 fprintf(stderr, "No support for octagon vias yet\n"); 02043 }else{ 02044 02045 vlist = rect_with_attachments(pin_rad((PinType*)via), 02046 x-t, y-t, 02047 x-t, y+t, 02048 x+t, y+t, 02049 x+t, y-t, 02050 l - r->layers); 02051 bbox = toporouter_bbox_create(l - r->layers, vlist, VIA, via); 02052 r->bboxes = g_slist_prepend(r->bboxes, bbox); 02053 g_list_free(vlist); 02054 02055 bbox->point = GTS_POINT( insert_vertex(r, l, x, y, bbox) ); 02056 02057 } 02058 } 02059 END_LOOP; 02060 return 0; 02061 } 02062 02068 int 02069 read_lines(toporouter_t *r, toporouter_layer_t *l, LayerType *layer, int ln) 02070 { 02071 gdouble xs[2], ys[2]; 02072 02073 GList *vlist = NULL; 02074 toporouter_bbox_t *bbox = NULL; 02075 02076 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 02077 02078 LINE_LOOP(layer); 02079 { 02080 xs[0] = line->Point1.X; 02081 xs[1] = line->Point2.X; 02082 ys[0] = line->Point1.Y; 02083 ys[1] = line->Point2.Y; 02084 if(!(xs[0] == xs[1] && ys[0] == ys[1])) { 02085 vlist = g_list_prepend(NULL, gts_vertex_new (vertex_class, xs[0], ys[0], l - r->layers)); 02086 vlist = g_list_prepend(vlist, gts_vertex_new (vertex_class, xs[1], ys[1], l - r->layers)); 02087 // TODO: replace this with surface version 02088 bbox = toporouter_bbox_create_from_points(GetLayerGroupNumberByNumber(ln), vlist, LINE, line); 02089 r->bboxes = g_slist_prepend(r->bboxes, bbox); 02090 //new;; 02091 //insert_constraints_from_list(r, l, vlist, bbox); 02092 g_list_free(vlist); 02093 // bbox->point = GTS_POINT( insert_vertex(r, l, (xs[0]+xs[1])/2., (ys[0]+ys[1])/2., bbox) ); 02094 02095 bbox->constraints = g_list_concat(bbox->constraints, insert_constraint_edge(r, l, xs[0], ys[0], 0, xs[1], ys[1], 0, bbox)); 02096 } 02097 } 02098 END_LOOP; 02099 02100 return 0; 02101 } 02102 02103 static void 02104 create_board_edge (double x0, double y0, 02105 double x1, double y1, 02106 int layer, 02107 GList **vlist) 02108 { 02109 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 02110 double edge_length = hypot (x0 - x1, y0 - y1); 02111 unsigned int vertices_per_edge = MIN (1, edge_length / BOARD_EDGE_RESOLUTION); 02112 unsigned int count; 02113 double inc = edge_length / vertices_per_edge; 02114 double x = x0, y = y0; 02115 02116 *vlist = g_list_prepend (*vlist, gts_vertex_new (vertex_class, x, y, layer)); 02117 02118 for (count = 1; count < vertices_per_edge; count ++) { 02119 coord_move_towards_coord_values (x, y, x1, y1, inc, &x, &y); 02120 *vlist = g_list_prepend (*vlist, gts_vertex_new (vertex_class, x, y, layer)); 02121 } 02122 } 02123 02124 02125 static void 02126 read_board_constraints (toporouter_t *r, toporouter_layer_t *l, int layer) 02127 { 02128 GList *vlist = NULL; 02129 toporouter_bbox_t *bbox; 02130 02131 /* Create points for the board edges and constrain those edges */ 02132 create_board_edge (0., 0., PCB->MaxWidth, 0., layer, &vlist); 02133 create_board_edge (PCB->MaxWidth, 0., PCB->MaxWidth, PCB->MaxHeight, layer, &vlist); 02134 create_board_edge (PCB->MaxWidth, PCB->MaxHeight, 0., PCB->MaxHeight, layer, &vlist); 02135 create_board_edge (0., PCB->MaxHeight, 0., 0., layer, &vlist); 02136 02137 bbox = toporouter_bbox_create (layer, vlist, BOARD, NULL); 02138 r->bboxes = g_slist_prepend (r->bboxes, bbox); 02139 insert_constraints_from_list (r, l, vlist, bbox); 02140 g_list_free (vlist); 02141 } 02142 02143 gdouble 02144 triangle_cost(GtsTriangle *t, gpointer *data){ 02145 02146 gdouble *min_quality = (gdouble *)data[0]; 02147 gdouble *max_area = (gdouble *)data[1]; 02148 gdouble quality = gts_triangle_quality(t); 02149 gdouble area = gts_triangle_area(t); 02150 02151 if (quality < *min_quality || area > *max_area) 02152 return quality; 02153 return 0.0; 02154 } 02155 02156 02157 void 02158 print_constraint(toporouter_constraint_t *e) 02159 { 02160 printf("CONSTRAINT:\n"); 02161 print_vertex(tedge_v1(e)); 02162 print_vertex(tedge_v2(e)); 02163 } 02164 02165 void 02166 print_edge(toporouter_edge_t *e) 02167 { 02168 GList *i = edge_routing(e); 02169 02170 printf("EDGE:\n"); 02171 02172 print_vertex(tedge_v1(e)); 02173 02174 while(i) { 02175 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 02176 print_vertex(v); 02177 i = i->next; 02178 } 02179 02180 print_vertex(tedge_v2(e)); 02181 } 02182 static void pick_first_face (GtsFace * f, GtsFace ** first) 02183 { 02184 if (*first == NULL) 02185 *first = f; 02186 } 02187 02188 void 02189 unconstrain(toporouter_layer_t *l, toporouter_constraint_t *c) 02190 { 02191 toporouter_edge_t *e; 02192 02193 gts_allow_floating_vertices = TRUE; 02194 e = TOPOROUTER_EDGE(gts_edge_new (GTS_EDGE_CLASS (toporouter_edge_class ()), GTS_SEGMENT(c)->v1, GTS_SEGMENT(c)->v2)); 02195 gts_edge_replace(GTS_EDGE(c), GTS_EDGE(e)); 02196 l->constraints = g_list_remove(l->constraints, c); 02197 c->box->constraints = g_list_remove(c->box->constraints, c); 02198 c->box = NULL; 02199 gts_object_destroy (GTS_OBJECT (c)); 02200 gts_allow_floating_vertices = FALSE; 02201 } 02202 02203 void 02204 build_cdt(toporouter_t *r, toporouter_layer_t *l) 02205 { 02206 /* TODO: generalize into surface *cdt_create(vertices, constraints) */ 02207 GList *i; 02208 //GtsEdge *temp; 02209 //GtsVertex *v; 02210 GtsTriangle *t; 02211 GtsVertex *v1, *v2, *v3; 02212 GSList *vertices_slist; 02213 02214 vertices_slist = list_to_slist(l->vertices); 02215 02216 if(l->surface) { 02217 GtsFace * first = NULL; 02218 gts_surface_foreach_face (l->surface, (GtsFunc) pick_first_face, &first); 02219 gts_surface_traverse_destroy(gts_surface_traverse_new (l->surface, first)); 02220 } 02221 02222 t = gts_triangle_enclosing (gts_triangle_class (), vertices_slist, 1000.0f); 02223 gts_triangle_vertices (t, &v1, &v2, &v3); 02224 02225 g_slist_free(vertices_slist); 02226 02227 l->surface = gts_surface_new (gts_surface_class (), gts_face_class (), 02228 GTS_EDGE_CLASS(toporouter_edge_class ()), GTS_VERTEX_CLASS(toporouter_vertex_class ()) ); 02229 02230 gts_surface_add_face (l->surface, gts_face_new (gts_face_class (), t->e1, t->e2, t->e3)); 02231 02232 02233 // fprintf(stderr, "ADDED VERTICES\n"); 02234 /* 02235 GtsFace *debugface; 02236 02237 if((debugface = gts_delaunay_check(l->surface))) { 02238 fprintf(stderr, "WARNING: Delaunay check failed\n"); 02239 fprintf(stderr, "\tViolating triangle:\n"); 02240 fprintf(stderr, "\t%f,%f %f,%f\n", 02241 debugface->triangle.e1->segment.v1->p.x, 02242 debugface->triangle.e1->segment.v1->p.y, 02243 debugface->triangle.e1->segment.v2->p.x, 02244 debugface->triangle.e1->segment.v2->p.y 02245 ); 02246 fprintf(stderr, "\t%f,%f %f,%f\n", 02247 debugface->triangle.e2->segment.v1->p.x, 02248 debugface->triangle.e2->segment.v1->p.y, 02249 debugface->triangle.e2->segment.v2->p.x, 02250 debugface->triangle.e2->segment.v2->p.y 02251 ); 02252 fprintf(stderr, "\t%f,%f %f,%f\n", 02253 debugface->triangle.e3->segment.v1->p.x, 02254 debugface->triangle.e3->segment.v1->p.y, 02255 debugface->triangle.e3->segment.v2->p.x, 02256 debugface->triangle.e3->segment.v2->p.y 02257 ); 02258 // toporouter_draw_surface(r, l->surface, "debug.png", 4096, 4096); 02259 { 02260 int i; 02261 for(i=0;i<groupcount();i++) { 02262 char buffer[256]; 02263 sprintf(buffer, "debug-%d.png", i); 02264 toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL); 02265 } 02266 } 02267 02268 } 02269 */ 02270 check_cons_continuation: 02271 i = l->constraints; 02272 while (i) { 02273 toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data); 02274 GList *j = i->next; 02275 // printf("adding cons: "); print_constraint(c1); 02276 02277 while(j) { 02278 toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data); 02279 guint rem = 0; 02280 GList *temp; 02281 02282 // printf("\tconflict: "); print_constraint(c2); 02283 toporouter_bbox_t *c1box = c1->box, *c2box = c2->box; 02284 toporouter_vertex_t *c1v1 = tedge_v1(c1); 02285 toporouter_vertex_t *c1v2 = tedge_v2(c1); 02286 toporouter_vertex_t *c2v1 = tedge_v1(c2); 02287 toporouter_vertex_t *c2v2 = tedge_v2(c2); 02288 02289 if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_IN) { 02290 toporouter_vertex_t *v; 02291 unconstrain(l, c1); unconstrain(l, c2); 02292 rem = 1; 02293 // proper intersection 02294 v = TOPOROUTER_VERTEX(vertex_intersect( 02295 GTS_VERTEX(c1v1), 02296 GTS_VERTEX(c1v2), 02297 GTS_VERTEX(c2v1), 02298 GTS_VERTEX(c2v2))); 02299 02300 // remove both constraints 02301 // replace with 4x constraints 02302 // insert new intersection vertex 02303 GTS_POINT(v)->z = vz(c1v1); 02304 02305 l->vertices = g_list_prepend(l->vertices, v); 02306 // gts_delaunay_add_vertex (l->surface, GTS_VERTEX(v), NULL); 02307 02308 v->bbox = c1box; 02309 02310 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(v), vy(v), 0, c1box); 02311 c1box->constraints = g_list_concat(c1box->constraints, temp); 02312 02313 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(v), vy(v), 0, c1box); 02314 c1box->constraints = g_list_concat(c1box->constraints, temp); 02315 02316 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(v), vy(v), 0, c2box); 02317 c2box->constraints = g_list_concat(c2box->constraints, temp); 02318 02319 temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(v), vy(v), 0, c2box); 02320 c2box->constraints = g_list_concat(c2box->constraints, temp); 02321 02322 }else if(gts_segments_are_intersecting(GTS_SEGMENT(c1), GTS_SEGMENT(c2)) == GTS_ON || 02323 gts_segments_are_intersecting(GTS_SEGMENT(c2), GTS_SEGMENT(c1)) == GTS_ON) { 02324 02325 if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1))) { 02326 unconstrain(l, c1); unconstrain(l, c2); 02327 rem = 1; 02328 // remove c1 02329 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box); 02330 c2box->constraints = g_list_concat(c2box->constraints, temp); 02331 02332 }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) { 02333 unconstrain(l, c1); unconstrain(l, c2); 02334 rem = 1; 02335 // remove c2 02336 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box); 02337 c1box->constraints = g_list_concat(c1box->constraints, temp); 02338 02339 //}else if(!vertex_wind(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && !vertex_wind(edge_v1(c1), edge_v2(c1), edge_v2(c2))) { 02340 /* }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) || vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2))) { 02341 unconstrain(l, c1); unconstrain(l, c2); 02342 rem = 1; 02343 printf("all colinear\n"); 02344 // exit(1); 02345 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box); 02346 c1box->constraints = g_list_concat(c1box->constraints, temp); 02347 02348 if(vertex_between(GTS_VERTEX(c1v1), GTS_VERTEX(c1v2), GTS_VERTEX(c2v2))) { 02349 // v2 of c2 is inner 02350 if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) { 02351 // v2 of c1 is inner 02352 // c2 = c1.v2 -> c2.v1 02353 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c2box); 02354 c2box->constraints = g_list_concat(c2box->constraints, temp); 02355 }else{ 02356 // v1 of c1 is inner 02357 // c2 = c1.v1 -> c2.v1 02358 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c2box); 02359 c2box->constraints = g_list_concat(c2box->constraints, temp); 02360 } 02361 }else{ 02362 // v1 of c2 is inner 02363 if(vertex_between(GTS_VERTEX(c2v1), GTS_VERTEX(c2v2), GTS_VERTEX(c1v2))) { 02364 // v2 of c1 is inner 02365 // c2 = c1.v2 -> c2.v2 02366 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c2box); 02367 c2box->constraints = g_list_concat(c2box->constraints, temp); 02368 }else{ 02369 // v1 of c1 is inner 02370 // c2 = c1.v1 -> c2.v2 02371 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c2box); 02372 c2box->constraints = g_list_concat(c2box->constraints, temp); 02373 } 02374 }*/ 02375 }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v1(c1)) && c1v1 != c2v1 && c1v1 != c2v2) { 02376 unconstrain(l, c1); unconstrain(l, c2); 02377 rem = 1; 02378 //v1 of c1 is on c2 02379 printf("v1 of c1 on c2\n"); 02380 02381 // replace with 2x constraints 02382 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v1), vy(c1v1), 0, c2box); 02383 c2box->constraints = g_list_concat(c2box->constraints, temp); 02384 temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v1), vy(c1v1), 0, c2box); 02385 c2box->constraints = g_list_concat(c2box->constraints, temp); 02386 02387 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box); 02388 c1box->constraints = g_list_concat(c1box->constraints, temp); 02389 02390 // restore c1 02391 //temp = insert_constraint_edge(r, l, vx(tedge_v2(c1)), vy(tedge_v2(c1)), 0, vx(tedge_v1(c1)), vy(tedge_v1(c1)), 0, c1->box); 02392 //c2->box->constraints = g_list_concat(c2->box->constraints, temp); 02393 02394 }else if(vertex_between(edge_v1(c2), edge_v2(c2), edge_v2(c1)) && c1v2 != c2v1 && c1v2 != c2v2) { 02395 unconstrain(l, c1); unconstrain(l, c2); 02396 rem = 1; 02397 //v2 of c1 is on c2 02398 printf("v2 of c1 on c2\n"); 02399 02400 // replace with 2x constraints 02401 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c1v2), vy(c1v2), 0, c2box); 02402 c2box->constraints = g_list_concat(c2box->constraints, temp); 02403 temp = insert_constraint_edge(r, l, vx(c2v2), vy(c2v2), 0, vx(c1v2), vy(c1v2), 0, c2box); 02404 c2box->constraints = g_list_concat(c2box->constraints, temp); 02405 02406 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c1v2), vy(c1v2), 0, c1box); 02407 c1box->constraints = g_list_concat(c1box->constraints, temp); 02408 02409 }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v1(c2)) && c2v1 != c1v1 && c2v1 != c1v2) { 02410 unconstrain(l, c1); unconstrain(l, c2); 02411 rem = 1; 02412 //v1 of c2 is on c1 02413 printf("v1 of c2 on c1\n"); 02414 02415 // replace with 2x constraints 02416 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v1), vy(c2v1), 0, c1box); 02417 c1box->constraints = g_list_concat(c1box->constraints, temp); 02418 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v1), vy(c2v1), 0, c1box); 02419 c1box->constraints = g_list_concat(c1box->constraints, temp); 02420 02421 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box); 02422 c2box->constraints = g_list_concat(c2box->constraints, temp); 02423 }else if(vertex_between(edge_v1(c1), edge_v2(c1), edge_v2(c2)) && c2v2 != c1v1 && c2v2 != c1v2) { 02424 unconstrain(l, c1); unconstrain(l, c2); 02425 rem = 1; 02426 //v2 of c2 is on c1 02427 printf("v2 of c2 on c1\n"); 02428 02429 // replace with 2x constraints 02430 temp = insert_constraint_edge(r, l, vx(c1v1), vy(c1v1), 0, vx(c2v2), vy(c2v2), 0, c1box); 02431 c1box->constraints = g_list_concat(c1box->constraints, temp); 02432 temp = insert_constraint_edge(r, l, vx(c1v2), vy(c1v2), 0, vx(c2v2), vy(c2v2), 0, c1box); 02433 c1box->constraints = g_list_concat(c1box->constraints, temp); 02434 02435 temp = insert_constraint_edge(r, l, vx(c2v1), vy(c2v1), 0, vx(c2v2), vy(c2v2), 0, c2box); 02436 c2box->constraints = g_list_concat(c2box->constraints, temp); 02437 } 02438 } 02439 if(rem) goto check_cons_continuation; 02440 02441 j = j->next; 02442 } 02443 02444 i = i->next; 02445 } 02446 02447 i = l->vertices; 02448 while (i) { 02449 //v = i->data; 02450 //if(r->flags & TOPOROUTER_FLAG_DEBUG_CDTS) 02451 // fprintf(stderr, "\tadding vertex %f,%f\n", v->p.x, v->p.y); 02452 toporouter_vertex_t *v = TOPOROUTER_VERTEX(gts_delaunay_add_vertex (l->surface, (GtsVertex *)i->data, NULL)); 02453 if(v) { 02454 printf("conflict: "); print_vertex(v); 02455 } 02456 02457 i = i->next; 02458 } 02459 i = l->constraints; 02460 while (i) { 02461 02462 // toporouter_constraint_t *c1 = TOPOROUTER_CONSTRAINT(i->data); 02463 // printf("adding cons: "); print_constraint(c1); 02464 02465 GSList *conflicts = gts_delaunay_add_constraint (l->surface, (GtsConstraint *)i->data); 02466 GSList *j = conflicts; 02467 while(j) { 02468 if(TOPOROUTER_IS_CONSTRAINT(j->data)) { 02469 toporouter_constraint_t *c2 = TOPOROUTER_CONSTRAINT(j->data); 02470 02471 printf("\tconflict: "); print_constraint(c2); 02472 02473 } 02474 j = j->next; 02475 } 02476 g_slist_free(conflicts); 02477 02478 i = i->next; 02479 } 02480 02481 // if(rerun) 02482 // goto build_cdt_continuation; 02483 // fprintf(stderr, "ADDED CONSTRAINTS\n"); 02484 gts_allow_floating_vertices = TRUE; 02485 gts_object_destroy (GTS_OBJECT (v1)); 02486 gts_object_destroy (GTS_OBJECT (v2)); 02487 gts_object_destroy (GTS_OBJECT (v3)); 02488 gts_allow_floating_vertices = FALSE; 02489 02490 /* 02491 { 02492 gpointer data[2]; 02493 gdouble quality = 0.50, area = G_MAXDOUBLE; 02494 guint num = gts_delaunay_conform(l->surface, -1, (GtsEncroachFunc) gts_vertex_encroaches_edge, NULL); 02495 02496 if (num == 0){ 02497 data[0] = &quality; 02498 data[1] = &area; 02499 num = gts_delaunay_refine(l->surface, -1, (GtsEncroachFunc) gts_vertex_encroaches_edge, NULL, (GtsKeyFunc) triangle_cost, data); 02500 } 02501 } 02502 */ 02503 #ifdef DEBUG_IMPORT 02504 gts_surface_print_stats(l->surface, stderr); 02505 #endif 02506 02507 #if 0 02508 { 02509 char buffer[64]; 02510 FILE *fout2; 02511 sprintf(buffer, "surface%d.gts", l - r->layers); 02512 fout2 = fopen(buffer, "w"); 02513 gts_surface_write(l->surface, fout2); 02514 } 02515 #endif 02516 02517 } 02518 02519 gint 02520 visited_cmp(gconstpointer a, gconstpointer b) 02521 { 02522 if(a<b) return -1; 02523 if(a>b) return 1; 02524 return 0; 02525 } 02526 02527 static double 02528 coord_angle (double ax, double ay, double bx, double by) 02529 { 02530 return atan2 (by - ay, bx - ax); 02531 } 02532 02533 GList * 02534 cluster_vertices(toporouter_t *r, toporouter_cluster_t *c) 02535 { 02536 GList *rval = NULL; 02537 02538 if(!c) return NULL; 02539 02540 FOREACH_CLUSTER(c->netlist->clusters) { 02541 if((r->flags & TOPOROUTER_FLAG_AFTERRUBIX && cluster->c == c->c) || (!(r->flags & TOPOROUTER_FLAG_AFTERRUBIX) && cluster == c)) { 02542 FOREACH_BBOX(cluster->boxes) { 02543 if(box->type == LINE) { 02544 g_assert(box->constraints->data); 02545 rval = g_list_prepend(rval, tedge_v1(box->constraints->data)); 02546 rval = g_list_prepend(rval, tedge_v2(box->constraints->data)); 02547 }else if(box->point) { 02548 rval = g_list_prepend(rval, TOPOROUTER_VERTEX(box->point)); 02549 //g_assert(vertex_bbox(TOPOROUTER_VERTEX(box->point)) == box); 02550 }else { 02551 printf("WARNING: cluster_vertices: unhandled bbox type\n"); 02552 } 02553 02554 } FOREACH_END; 02555 02556 02557 } 02558 02559 } FOREACH_END; 02560 02561 return rval; 02562 } 02563 02564 void 02565 print_cluster(toporouter_cluster_t *c) 02566 { 02567 02568 if(!c) { 02569 printf("[CLUSTER (NULL)]\n"); 02570 return; 02571 } 02572 02573 printf("CLUSTER %d: NETLIST = %s STYLE = %s\n", c->c, c->netlist->netlist, c->netlist->style); 02574 02575 FOREACH_BBOX(c->boxes) { 02576 print_bbox(box); 02577 } FOREACH_END; 02578 } 02579 02580 02581 toporouter_cluster_t * 02582 cluster_create(toporouter_t *r, toporouter_netlist_t *netlist) 02583 { 02584 toporouter_cluster_t *c = (toporouter_cluster_t *)malloc(sizeof(toporouter_cluster_t)); 02585 02586 c->c = c->pc = netlist->clusters->len; 02587 g_ptr_array_add(netlist->clusters, c); 02588 c->netlist = netlist; 02589 c->boxes = g_ptr_array_new(); 02590 02591 return c; 02592 } 02593 02594 toporouter_bbox_t * 02595 toporouter_bbox_locate(toporouter_t *r, toporouter_term_t type, void *data, gdouble x, gdouble y, guint layergroup) 02596 { 02597 GtsPoint *p = gts_point_new(gts_point_class(), x, y, layergroup); 02598 GSList *boxes = gts_bb_tree_stabbed(r->bboxtree, p), *i = boxes; 02599 02600 gts_object_destroy(GTS_OBJECT(p)); 02601 02602 while(i) { 02603 toporouter_bbox_t *box = TOPOROUTER_BBOX(i->data); 02604 02605 if(box->type == type && box->data == data) { 02606 g_slist_free(boxes); 02607 return box; 02608 } 02609 02610 i = i->next; 02611 } 02612 02613 g_slist_free(boxes); 02614 return NULL; 02615 } 02616 02617 void 02618 cluster_join_bbox(toporouter_cluster_t *cluster, toporouter_bbox_t *box) 02619 { 02620 if(box) { 02621 g_ptr_array_add(cluster->boxes, box); 02622 box->cluster = cluster; 02623 } 02624 } 02625 02626 toporouter_netlist_t * 02627 netlist_create(toporouter_t *r, char *netlist, char *style) 02628 { 02629 toporouter_netlist_t *nl = (toporouter_netlist_t *)malloc(sizeof(toporouter_netlist_t)); 02630 nl->netlist = netlist; 02631 nl->style = style; 02632 nl->clusters = g_ptr_array_new(); 02633 nl->routes = g_ptr_array_new(); 02634 nl->routed = NULL; 02635 nl->pair = NULL; 02636 g_ptr_array_add(r->netlists, nl); 02637 return nl; 02638 } 02639 02640 void 02641 import_clusters(toporouter_t *r) 02642 { 02643 NetListListType nets; 02644 nets = CollectSubnets(false); 02645 NETLIST_LOOP(&nets); 02646 { 02647 if(netlist->NetN > 0) { 02648 toporouter_netlist_t *nl = netlist_create(r, netlist->Net->Connection->menu->Name, netlist->Net->Connection->menu->Style); 02649 02650 NET_LOOP(netlist); 02651 { 02652 02653 toporouter_cluster_t *cluster = cluster_create(r, nl); 02654 #ifdef DEBUG_MERGING 02655 printf("NET:\n"); 02656 #endif 02657 CONNECTION_LOOP (net); 02658 { 02659 02660 if(connection->type == LINE_TYPE) { 02661 LineType *line = (LineType *) connection->ptr2; 02662 toporouter_bbox_t *box = toporouter_bbox_locate(r, LINE, line, connection->X, connection->Y, connection->group); 02663 cluster_join_bbox(cluster, box); 02664 02665 #ifdef DEBUG_MERGING 02666 pcb_printf("\tLINE %#mD\n", connection->X, connection->Y); 02667 #endif 02668 }else if(connection->type == PAD_TYPE) { 02669 PadType *pad = (PadType *) connection->ptr2; 02670 toporouter_bbox_t *box = toporouter_bbox_locate(r, PAD, pad, connection->X, connection->Y, connection->group); 02671 cluster_join_bbox(cluster, box); 02672 02673 #ifdef DEBUG_MERGING 02674 pcb_printf("\tPAD %#mD\n", connection->X, connection->Y); 02675 #endif 02676 }else if(connection->type == PIN_TYPE) { 02677 02678 for(guint m=0;m<groupcount();m++) { 02679 PinType *pin = (PinType *) connection->ptr2; 02680 toporouter_bbox_t *box = toporouter_bbox_locate(r, PIN, pin, connection->X, connection->Y, m); 02681 cluster_join_bbox(cluster, box); 02682 } 02683 02684 #ifdef DEBUG_MERGING 02685 pcb_printf("\tPIN %#mD\n", connection->X, connection->Y); 02686 #endif 02687 }else if(connection->type == VIA_TYPE) { 02688 02689 for(guint m=0;m<groupcount();m++) { 02690 PinType *pin = (PinType *) connection->ptr2; 02691 toporouter_bbox_t *box = toporouter_bbox_locate(r, VIA, pin, connection->X, connection->Y, m); 02692 cluster_join_bbox(cluster, box); 02693 } 02694 02695 #ifdef DEBUG_MERGING 02696 pcb_printf("\tVIA %#mD\n", connection->X, connection->Y); 02697 #endif 02698 }else if(connection->type == POLYGON_TYPE) { 02699 PolygonType *polygon = (PolygonType *) connection->ptr2; 02700 toporouter_bbox_t *box = toporouter_bbox_locate(r, POLYGON, polygon, connection->X, connection->Y, connection->group); 02701 cluster_join_bbox(cluster, box); 02702 02703 #ifdef DEBUG_MERGING 02704 pcb_printf("\tPOLYGON %#mD\n", connection->X, connection->Y); 02705 #endif 02706 02707 } 02708 } 02709 END_LOOP; 02710 #ifdef DEBUG_MERGING 02711 printf("\n"); 02712 #endif 02713 } 02714 END_LOOP; 02715 02716 } 02717 } 02718 END_LOOP; 02719 FreeNetListListMemory(&nets); 02720 } 02721 02722 void 02723 import_geometry(toporouter_t *r) 02724 { 02725 toporouter_layer_t *cur_layer; 02726 02727 int group; 02728 02729 #ifdef DEBUG_IMPORT 02730 for (group = 0; group < max_group; group++) { 02731 printf("Group %d: Number %d:\n", group, PCB->LayerGroups.Number[group]); 02732 02733 for (int entry = 0; entry < PCB->LayerGroups.Number[group]; entry++) { 02734 printf("\tEntry %d\n", PCB->LayerGroups.Entries[group][entry]); 02735 } 02736 } 02737 #endif 02738 /* Allocate space for per layer struct */ 02739 cur_layer = r->layers = (toporouter_layer_t *)malloc(groupcount() * sizeof(toporouter_layer_t)); 02740 02741 /* Foreach layer, read in pad vertices and constraints, and build CDT */ 02742 for (group = 0; group < max_group; group++) { 02743 #ifdef DEBUG_IMPORT 02744 printf("*** LAYER GROUP %d ***\n", group); 02745 #endif 02746 if(PCB->LayerGroups.Number[group] > 0){ 02747 cur_layer->vertices = NULL; 02748 cur_layer->constraints = NULL; 02749 02750 #ifdef DEBUG_IMPORT 02751 printf("reading board constraints from layer %d into group %d\n", PCB->LayerGroups.Entries[group][0], group); 02752 #endif 02753 read_board_constraints(r, cur_layer, PCB->LayerGroups.Entries[group][0]); 02754 #ifdef DEBUG_IMPORT 02755 printf("reading points from layer %d into group %d \n",PCB->LayerGroups.Entries[group][0], group); 02756 #endif 02757 read_points(r, cur_layer, PCB->LayerGroups.Entries[group][0]); 02758 02759 //#ifdef DEBUG_IMPORT 02760 // printf("reading pads from layer %d into group %d\n", number, group); 02761 //#endif 02762 read_pads(r, cur_layer, group); 02763 02764 GROUP_LOOP(PCB->Data, group) 02765 { 02766 02767 #ifdef DEBUG_IMPORT 02768 printf("reading lines from layer %d into group %d\n", number, group); 02769 #endif 02770 read_lines(r, cur_layer, layer, number); 02771 02772 } 02773 END_LOOP; 02774 02775 02776 02777 #ifdef DEBUG_IMPORT 02778 printf("building CDT\n"); 02779 #endif 02780 build_cdt(r, cur_layer); 02781 printf("finished\n"); 02782 /* { 02783 int i; 02784 for(i=0;i<groupcount();i++) { 02785 char buffer[256]; 02786 sprintf(buffer, "build%d.png", i); 02787 toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, NULL, i, NULL); 02788 } 02789 }*/ 02790 #ifdef DEBUG_IMPORT 02791 printf("finished building CDT\n"); 02792 #endif 02793 cur_layer++; 02794 } 02795 } 02796 02797 r->bboxtree = gts_bb_tree_new(r->bboxes); 02798 02799 import_clusters(r); 02800 02801 #ifdef DEBUG_IMPORT 02802 printf("finished import!\n"); 02803 #endif 02804 } 02805 02806 02807 gint 02808 compare_points(gconstpointer a, gconstpointer b) 02809 { 02810 GtsPoint *i = GTS_POINT(a); 02811 GtsPoint *j = GTS_POINT(b); 02812 02813 if(i->x == j->x) { 02814 if(i->y == j->y) return 0; 02815 if(i->y < j->y) return -1; 02816 return 1; 02817 } 02818 if(i->x < j->x) return -1; 02819 return 1; 02820 } 02821 02822 gint 02823 compare_segments(gconstpointer a, gconstpointer b) 02824 { 02825 if(a == b) return 0; 02826 if(a < b) return -1; 02827 return 1; 02828 } 02829 #define DEBUG_CLUSTER_FIND 1 02830 toporouter_cluster_t * 02831 cluster_find(toporouter_t *r, gdouble x, gdouble y, gdouble z) 02832 { 02833 GtsPoint *p = gts_point_new(gts_point_class(), x, y, z); 02834 GSList *hits = gts_bb_tree_stabbed(r->bboxtree, p); 02835 toporouter_cluster_t *rval = NULL; 02836 02837 #ifdef DEBUG_CLUSTER_FIND 02838 printf("FINDING %f,%f,%f\n\n", x, y, z); 02839 #endif 02840 02841 while(hits) { 02842 toporouter_bbox_t *box = TOPOROUTER_BBOX(hits->data); 02843 02844 #ifdef DEBUG_CLUSTER_FIND 02845 printf("HIT BOX: "); print_bbox(box); 02846 #endif 02847 02848 if(box->layer == (int)z) { 02849 if(box->type != BOARD) { 02850 if(box->type == LINE) { 02851 LineType *line = (LineType *)box->data; 02852 gint linewind = coord_wind(line->Point1.X, line->Point1.Y, x, y, line->Point2.X, line->Point2.Y); 02853 02854 if(line->Point1.X > x - EPSILON && line->Point1.X < x + EPSILON && 02855 line->Point1.Y > y - EPSILON && line->Point1.Y < y + EPSILON) { 02856 rval = box->cluster; 02857 // break; 02858 } 02859 if(line->Point2.X > x - EPSILON && line->Point2.X < x + EPSILON && 02860 line->Point2.Y > y - EPSILON && line->Point2.Y < y + EPSILON) { 02861 rval = box->cluster; 02862 // break; 02863 } 02864 if(!linewind) { 02865 rval = box->cluster; 02866 // break; 02867 } 02868 02869 }else if(box->surface) { 02870 02871 if(gts_point_locate(p, box->surface, NULL)) { 02872 rval = box->cluster; 02873 break; 02874 } 02875 02876 } 02877 } 02878 } 02879 hits = hits->next; 02880 } 02881 02882 gts_object_destroy(GTS_OBJECT(p)); 02883 02884 02885 #ifdef DEBUG_CLUSTER_FIND 02886 printf("cluster_find: %f,%f,%f: ", x, y, z); 02887 print_cluster(rval); 02888 #endif 02889 02890 return rval; 02891 } 02892 02893 gdouble 02894 simple_h_cost(toporouter_t *r, toporouter_vertex_t *curpoint, toporouter_vertex_t *destpoint) 02895 { 02896 gdouble layerpenalty = (vz(curpoint) == vz(destpoint)) ? 0. : r->viacost; 02897 02898 return gts_point_distance(GTS_POINT(curpoint), GTS_POINT(destpoint)) + layerpenalty; 02899 } 02900 02901 #define FCOST(x) (x->gcost + x->hcost) 02902 gdouble 02903 route_heap_cmp(gpointer item, gpointer data) 02904 { 02905 return FCOST(TOPOROUTER_VERTEX(item)); 02906 } 02907 02908 #define closelist_insert(p) closelist = g_list_prepend(closelist, p) 02909 02910 typedef struct { 02911 toporouter_vertex_t *key; 02912 toporouter_vertex_t *result; 02913 }toporouter_heap_search_data_t; 02914 02915 void 02916 toporouter_heap_search(gpointer data, gpointer user_data) 02917 { 02918 toporouter_vertex_t *v = TOPOROUTER_VERTEX(data); 02919 toporouter_heap_search_data_t *heap_search_data = (toporouter_heap_search_data_t *)user_data; 02920 if(v == heap_search_data->key) heap_search_data->result = v; 02921 } 02922 /* 02923 void 02924 toporouter_heap_color(gpointer data, gpointer user_data) 02925 { 02926 toporouter_vertex_t *v = TOPOROUTER_VERTEX(data); 02927 v->flags |= (guint) user_data; 02928 } 02929 */ 02930 static inline gdouble 02931 angle_span(gdouble a1, gdouble a2) 02932 { 02933 if(a1 > a2) 02934 return ((2*M_PI)-a1 + a2); 02935 return a2-a1; 02936 } 02937 02938 gdouble 02939 edge_capacity(toporouter_edge_t *e) 02940 { 02941 return gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))); 02942 } 02943 02944 gdouble 02945 edge_flow(toporouter_edge_t *e, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *dest) 02946 { 02947 GList *i = edge_routing(e); 02948 toporouter_vertex_t *pv = tedge_v1(e), *v = NULL; 02949 gdouble flow = 0.; 02950 guint waiting = 1; 02951 02952 if((pv == v1 || pv == v2) && waiting) { 02953 flow += min_vertex_net_spacing(pv, dest); 02954 pv = dest; 02955 waiting = 0; 02956 } 02957 02958 g_assert(v1 != v2); 02959 02960 while(i) { 02961 v = TOPOROUTER_VERTEX(i->data); 02962 02963 02964 if(pv == dest) 02965 flow += min_vertex_net_spacing(v, pv); 02966 else 02967 flow += min_spacing(v, pv); 02968 02969 if((v == v1 || v == v2) && waiting) { 02970 flow += min_vertex_net_spacing(v, dest); 02971 pv = dest; 02972 waiting = 0; 02973 }else{ 02974 pv = v; 02975 } 02976 i = i->next; 02977 } 02978 02979 if(pv == dest) 02980 flow += min_vertex_net_spacing(tedge_v2(e), pv); 02981 else 02982 flow += min_spacing(tedge_v2(e), pv); 02983 02984 return flow; 02985 } 02986 02987 void 02988 print_path(GList *path) 02989 { 02990 GList *i = path; 02991 02992 printf("PATH:\n"); 02993 while(i) { 02994 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 02995 // printf("[V %f,%f,%f]\n", vx(v), vy(v), vz(v)); 02996 print_vertex(v); 02997 02998 if(v->child && !g_list_find(path, v->child)) 02999 printf("\t CHILD NOT IN LIST\n"); 03000 if(v->parent && !g_list_find(path, v->parent)) 03001 printf("\t parent NOT IN LIST\n"); 03002 i = i->next; 03003 } 03004 03005 03006 } 03007 03008 GList * 03009 split_path(GList *path) 03010 { 03011 toporouter_vertex_t *pv = NULL; 03012 GList *curpath = NULL, *i, *paths = NULL; 03013 #ifdef DEBUG_ROUTE 03014 printf("PATH:\n"); 03015 #endif 03016 i = path; 03017 while(i) { 03018 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 03019 03020 #ifdef DEBUG_ROUTE 03021 printf("v = %f,%f ", vx(v), vy(v)); 03022 if(v->parent) printf("parent = %f,%f ", vx(v->parent), vy(v->parent)); 03023 if(v->child) printf("child = %f,%f ", vx(v->child), vy(v->child)); 03024 printf("\n"); 03025 #endif 03026 // printf("***\n"); 03027 // if(v) printf("v = %f,%f\n", GTS_POINT(v)->x, GTS_POINT(v)->y); 03028 // if(pv) printf("pv = %f,%f\n", GTS_POINT(pv)->x, GTS_POINT(pv)->y); 03029 03030 03031 if(pv) 03032 if(GTS_POINT(v)->x == GTS_POINT(pv)->x && GTS_POINT(v)->y == GTS_POINT(pv)->y) { 03033 if(g_list_length(curpath) > 1) paths = g_list_prepend(paths, curpath); 03034 curpath = NULL; 03035 03036 pv->child = NULL; 03037 v->parent = NULL; 03038 } 03039 03040 curpath = g_list_append(curpath, v); 03041 03042 pv = v; 03043 i = i->next; 03044 } 03045 03046 if(g_list_length(curpath) > 1) 03047 paths = g_list_prepend(paths, curpath); 03048 03049 return paths; 03050 } 03051 03052 03053 03054 #define edge_gradient(e) (cartesian_gradient(GTS_POINT(GTS_SEGMENT(e)->v1)->x, GTS_POINT(GTS_SEGMENT(e)->v1)->y, \ 03055 GTS_POINT(GTS_SEGMENT(e)->v2)->x, GTS_POINT(GTS_SEGMENT(e)->v2)->y)) 03056 03057 03061 gint 03062 routing_edge_insert(gconstpointer a, gconstpointer b, gpointer user_data) 03063 { 03064 GtsPoint *v1 = GTS_POINT(edge_v1(user_data)); 03065 03066 if(gts_point_distance2(v1, GTS_POINT(a)) < gts_point_distance2(v1, GTS_POINT(b)) - EPSILON) 03067 return -1; 03068 if(gts_point_distance2(v1, GTS_POINT(a)) > gts_point_distance2(v1, GTS_POINT(b)) + EPSILON) 03069 return 1; 03070 /* 03071 printf("a = %x b = %x\n", (int) a, (int) b); 03072 03073 printf("WARNING: routing_edge_insert() with same points..\n \ 03074 v1 @ %f,%f\n\ 03075 a @ %f,%f\n\ 03076 b @ %f,%f\n", 03077 v1->x, v1->y, 03078 vx(a), vy(a), 03079 vx(a), vy(b)); 03080 printf("A: "); print_vertex(TOPOROUTER_VERTEX(a)); 03081 printf("B: "); print_vertex(TOPOROUTER_VERTEX(b)); 03082 03083 TOPOROUTER_VERTEX(a)->flags |= VERTEX_FLAG_RED; 03084 TOPOROUTER_VERTEX(b)->flags |= VERTEX_FLAG_RED; 03085 */ 03086 return 0; 03087 } 03088 03089 03090 toporouter_vertex_t * 03091 new_temp_toporoutervertex(gdouble x, gdouble y, toporouter_edge_t *e) 03092 { 03093 GtsVertexClass *vertex_class = GTS_VERTEX_CLASS (toporouter_vertex_class ()); 03094 GList *i = edge_routing(e); 03095 toporouter_vertex_t *r; 03097 while(i) { 03098 r = TOPOROUTER_VERTEX(i->data); 03099 if(epsilon_equals(vx(r),x) && epsilon_equals(vy(r),y)) { 03100 if(r->flags & VERTEX_FLAG_TEMP) return r; 03101 } 03102 i = i->next; 03103 } 03104 //*/ 03105 r = TOPOROUTER_VERTEX( gts_vertex_new (vertex_class, x, y, vz(edge_v1(e))) ); 03106 r->flags |= VERTEX_FLAG_TEMP; 03107 r->routingedge = e; 03108 03109 if(TOPOROUTER_IS_CONSTRAINT(e)) 03110 TOPOROUTER_CONSTRAINT(e)->routing = g_list_insert_sorted_with_data(edge_routing(e), r, routing_edge_insert, e); 03111 else 03112 e->routing = g_list_insert_sorted_with_data(edge_routing(e), r, routing_edge_insert, e); 03113 03114 return r; 03115 } 03116 03117 03121 toporouter_vertex_t * 03122 new_temp_toporoutervertex_in_segment(toporouter_edge_t *e, toporouter_vertex_t *v, gdouble r, toporouter_vertex_t *ref) 03123 { 03124 gdouble m = edge_gradient(e); 03125 toporouter_spoint_t p, np1, np2; 03126 // toporouter_vertex_t *b = TOPOROUTER_VERTEX((GTS_VERTEX(v) == edge_v1(e)) ? edge_v2(e) : edge_v1(e)); 03127 toporouter_vertex_t *rval = NULL; 03128 p.x = vx(v); p.y = vy(v); 03129 03130 vertices_on_line(&p, m, r, &np1, &np2); 03131 03132 if( (pow(np1.x - vx(ref), 2) + pow(np1.y - vy(ref), 2)) < (pow(np2.x - vx(ref), 2) + pow(np2.y - vy(ref), 2)) ) 03133 rval = new_temp_toporoutervertex(np1.x, np1.y, e); 03134 else 03135 rval = new_temp_toporoutervertex(np2.x, np2.y, e); 03136 03137 return rval; 03138 } 03139 03140 gint 03141 vertex_keepout_test(toporouter_t *r, toporouter_vertex_t *v) 03142 { 03143 GList *i = r->keepoutlayers; 03144 while(i) { 03145 gdouble keepout = *((double *) i->data); 03146 if(vz(v) == keepout) return 1; 03147 i = i->next; 03148 } 03149 return 0; 03150 } 03151 03152 void 03153 closest_cluster_pair(toporouter_t *r, GList *src_vertices, GList *dest_vertices, toporouter_vertex_t **a, toporouter_vertex_t **b) 03154 { 03155 GList *i = src_vertices, *j = dest_vertices; 03156 03157 gdouble min = 0.; 03158 *a = NULL; *b = NULL; 03159 03160 i = src_vertices; 03161 while(i) { 03162 toporouter_vertex_t *v1 = TOPOROUTER_VERTEX(i->data); 03163 03164 if(vertex_keepout_test(r, v1)) { i = i->next; continue; } 03165 03166 j = dest_vertices; 03167 while(j) { 03168 toporouter_vertex_t *v2 = TOPOROUTER_VERTEX(j->data); 03169 if(vertex_keepout_test(r, v2) || vz(v2) != vz(v1)) { j = j->next; continue; } 03170 03171 if(!*a) { 03172 *a = v1; *b = v2; min = simple_h_cost(r, *a, *b); 03173 }else{ 03174 gdouble tempd = simple_h_cost(r, v1, v2); 03175 if(r->flags & TOPOROUTER_FLAG_GOFAR && tempd > min) { 03176 *a = v1; *b = v2; min = tempd; 03177 }else 03178 if(tempd < min) { 03179 *a = v1; *b = v2; min = tempd; 03180 } 03181 } 03182 03183 j = j->next; 03184 } 03185 03186 i = i->next; 03187 } 03188 03189 // g_list_free(src_vertices); 03190 // g_list_free(dest_vertices); 03191 } 03192 03193 03194 toporouter_vertex_t * 03195 closest_dest_vertex(toporouter_t *r, toporouter_vertex_t *v, toporouter_route_t *routedata) 03196 { 03197 GList //*vertices = cluster_vertices(r, routedata->dest), 03198 *i = routedata->destvertices; 03199 toporouter_vertex_t *closest = NULL; 03200 gdouble closest_distance = 0.; 03201 03202 // if(routedata->flags & TOPOROUTER_FLAG_FLEX) i = r->destboxes; 03203 03204 while(i) { 03205 toporouter_vertex_t *cv = TOPOROUTER_VERTEX(i->data); 03206 03207 if(vz(cv) != vz(v)) { i = i->next; continue; } 03208 03209 if(!closest) { 03210 closest = cv; closest_distance = simple_h_cost(r, v, closest); 03211 }else{ 03212 gdouble tempd = simple_h_cost(r, v, cv); 03213 if(r->flags & TOPOROUTER_FLAG_GOFAR && tempd > closest_distance) { 03214 closest = cv; closest_distance = tempd; 03215 }else 03216 if(tempd < closest_distance) { 03217 closest = cv; closest_distance = tempd; 03218 } 03219 } 03220 i = i->next; 03221 } 03222 03223 // g_list_free(vertices); 03224 03225 #ifdef DEBUG_ROUTE 03226 printf("CLOSEST = %f,%f,%f\n", vx(closest), vy(closest), vz(closest)); 03227 #endif 03228 return closest; 03229 } 03230 03231 #define toporouter_edge_gradient(e) (cartesian_gradient(vx(edge_v1(e)), vy(edge_v1(e)), vx(edge_v2(e)), vy(edge_v2(e)))) 03232 03233 03237 gdouble 03238 triangle_interior_capacity(GtsTriangle *t, toporouter_vertex_t *v) 03239 { 03240 toporouter_edge_t *e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v))); 03241 gdouble x, y, m1, m2, c2, c1; 03242 #ifdef DEBUG_ROUTE 03243 gdouble len; 03244 #endif 03245 03246 g_assert(e); 03247 03248 m1 = toporouter_edge_gradient(e); 03249 m2 = perpendicular_gradient(m1); 03250 c2 = (isinf(m2)) ? vx(v) : vy(v) - (m2 * vx(v)); 03251 c1 = (isinf(m1)) ? vx(edge_v1(e)) : vy(edge_v1(e)) - (m1 * vx(edge_v1(e))); 03252 03253 if(isinf(m2)) 03254 x = vx(v); 03255 else if(isinf(m1)) 03256 x = vx(edge_v1(e)); 03257 else 03258 x = (c2 - c1) / (m1 - m2); 03259 03260 y = (isinf(m2)) ? vy(edge_v1(e)) : (m2 * x) + c2; 03261 03262 #ifdef DEBUG_ROUTE 03263 len = gts_point_distance2(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))); 03264 printf("%f,%f len = %f v = %f,%f\n", x, y, len, vx(v), vy(v)); 03265 #endif 03266 03267 if(epsilon_equals(x,vx(edge_v1(e))) && epsilon_equals(y,vy(edge_v1(e)))) return INFINITY; 03268 if(epsilon_equals(x,vx(edge_v2(e))) && epsilon_equals(y,vy(edge_v2(e)))) return INFINITY; 03269 03270 if(x >= MIN(vx(edge_v1(e)),vx(edge_v2(e))) && 03271 x <= MAX(vx(edge_v1(e)),vx(edge_v2(e))) && 03272 y >= MIN(vy(edge_v1(e)),vy(edge_v2(e))) && 03273 y <= MAX(vy(edge_v1(e)),vy(edge_v2(e)))) 03274 03275 // if( (pow(vx(edge_v1(e)) - x, 2) + pow(vy(edge_v1(e)) - y, 2)) < len && (pow(vx(edge_v2(e)) - x, 2) + pow(vy(edge_v2(e)) - y, 2)) < len ) 03276 return hypot(vx(v) - x, vy(v) - y); 03277 03278 return INFINITY; 03279 } 03280 03281 static inline toporouter_vertex_t * 03282 segment_common_vertex(GtsSegment *s1, GtsSegment *s2) 03283 { 03284 if(!s1 || !s2) return NULL; 03285 if(s1->v1 == s2->v1) return TOPOROUTER_VERTEX(s1->v1); 03286 if(s1->v2 == s2->v1) return TOPOROUTER_VERTEX(s1->v2); 03287 if(s1->v1 == s2->v2) return TOPOROUTER_VERTEX(s1->v1); 03288 if(s1->v2 == s2->v2) return TOPOROUTER_VERTEX(s1->v2); 03289 return NULL; 03290 } 03291 03292 static inline toporouter_vertex_t * 03293 route_vertices_common_vertex(toporouter_vertex_t *v1, toporouter_vertex_t *v2) 03294 { 03295 return segment_common_vertex(GTS_SEGMENT(v1->routingedge), GTS_SEGMENT(v2->routingedge)); 03296 } 03297 03298 03299 static inline guint 03300 edges_third_edge(GtsSegment *s1, GtsSegment *s2, toporouter_vertex_t **v1, toporouter_vertex_t **v2) 03301 { 03302 if(!s1 || !s2) return 0; 03303 if(s1->v1 == s2->v1) { 03304 *v1 = TOPOROUTER_VERTEX(s1->v2); 03305 *v2 = TOPOROUTER_VERTEX(s2->v2); 03306 return 1; 03307 } 03308 if(s1->v2 == s2->v1) { 03309 *v1 = TOPOROUTER_VERTEX(s1->v1); 03310 *v2 = TOPOROUTER_VERTEX(s2->v2); 03311 return 1; 03312 } 03313 if(s1->v1 == s2->v2) { 03314 *v1 = TOPOROUTER_VERTEX(s1->v2); 03315 *v2 = TOPOROUTER_VERTEX(s2->v1); 03316 return 1; 03317 } 03318 if(s1->v2 == s2->v2) { 03319 *v1 = TOPOROUTER_VERTEX(s1->v1); 03320 *v2 = TOPOROUTER_VERTEX(s2->v1); 03321 return 1; 03322 } 03323 return 0; 03324 } 03325 03330 gdouble 03331 flow_from_edge_to_edge(GtsTriangle *t, toporouter_edge_t *e1, toporouter_edge_t *e2, 03332 toporouter_vertex_t *common_v, toporouter_vertex_t *curpoint) 03333 { 03334 gdouble r = 0.; 03335 toporouter_vertex_t *pv = common_v, *v; 03336 toporouter_edge_t *op_edge; 03337 03338 GList *i = edge_routing(e1); 03339 while(i) { 03340 v = TOPOROUTER_VERTEX(i->data); 03341 03342 if(v == curpoint) { 03343 r += min_spacing(v, pv); 03344 pv = v; 03345 i = i->next; continue; 03346 } 03347 // if(!(v->flags & VERTEX_FLAG_TEMP)) { 03348 if((v->flags & VERTEX_FLAG_ROUTE)) { 03349 if(v->parent) 03350 if(v->parent->routingedge == e2) { 03351 r += min_spacing(v, pv); 03352 pv = v; 03353 i = i->next; continue; 03354 } 03355 03356 if(v->child) 03357 if(v->child->routingedge == e2) { 03358 r += min_spacing(v, pv); 03359 pv = v; 03360 i = i->next; continue; 03361 } 03362 } 03363 i = i->next; 03364 } 03365 03366 op_edge = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(common_v))); 03367 03368 g_assert(op_edge); 03369 g_assert(e1); 03370 g_assert(e2); 03371 03372 v = segment_common_vertex(GTS_SEGMENT(e2), GTS_SEGMENT(op_edge)); 03373 g_assert(v); 03374 03375 //v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e1))); 03376 if(v->flags & VERTEX_FLAG_ROUTE && v->parent && v->parent->routingedge) { 03377 if(v->parent->routingedge == e1) 03378 r += min_spacing(v, pv); 03379 } 03380 03381 v = segment_common_vertex(GTS_SEGMENT(e1), GTS_SEGMENT(op_edge)); 03382 g_assert(v); 03383 03384 //v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e2))); 03385 if(v->flags & VERTEX_FLAG_ROUTE && v->parent && v->parent->routingedge) { 03386 if(v->parent->routingedge == e1) 03387 r += min_spacing(v, pv); 03388 } 03389 03390 if(TOPOROUTER_IS_CONSTRAINT(op_edge)) { 03391 toporouter_bbox_t *box = vertex_bbox(TOPOROUTER_VERTEX(edge_v1(op_edge))); 03392 r += vertex_net_thickness(v) / 2.; 03393 if(box) { 03394 r += MAX(vertex_net_keepaway(v), cluster_keepaway(box->cluster)); 03395 r += cluster_thickness(box->cluster) / 2.; 03396 }else{ 03397 r += vertex_net_keepaway(v); 03398 03399 } 03400 } 03401 03402 return r; 03403 } 03404 03405 03406 03407 guint 03408 check_triangle_interior_capacity(GtsTriangle *t, toporouter_vertex_t *v, toporouter_vertex_t *curpoint, 03409 toporouter_edge_t *op_edge, toporouter_edge_t *adj_edge1, toporouter_edge_t *adj_edge2) 03410 { 03411 gdouble ic = triangle_interior_capacity(t, v); 03412 gdouble flow = flow_from_edge_to_edge(t, adj_edge1, adj_edge2, v, curpoint); 03413 03414 if(TOPOROUTER_IS_CONSTRAINT(adj_edge1) || TOPOROUTER_IS_CONSTRAINT(adj_edge2)) return 1; 03415 03416 03417 if(flow > ic) { 03418 #ifdef DEBUG_ROUTE 03419 printf("fail interior capacity flow = %f ic = %f\n", flow, ic); 03420 #endif 03421 return 0; 03422 } 03423 03424 return 1; 03425 } 03426 03427 toporouter_vertex_t * 03428 edge_routing_next_not_temp(toporouter_edge_t *e, GList *list) 03429 { 03430 if(!TOPOROUTER_IS_CONSTRAINT(e)) { 03431 while(list) { 03432 toporouter_vertex_t *v = TOPOROUTER_VERTEX(list->data); 03433 if(!(v->flags & VERTEX_FLAG_TEMP)) 03434 return v; 03435 03436 list = list->next; 03437 } 03438 } 03439 return tedge_v2(e); 03440 } 03441 03442 toporouter_vertex_t * 03443 edge_routing_prev_not_temp(toporouter_edge_t *e, GList *list) 03444 { 03445 if(!TOPOROUTER_IS_CONSTRAINT(e)) { 03446 while(list) { 03447 toporouter_vertex_t *v = TOPOROUTER_VERTEX(list->data); 03448 if(!(v->flags & VERTEX_FLAG_TEMP)) 03449 return v; 03450 03451 list = list->prev; 03452 } 03453 } 03454 return tedge_v1(e); 03455 } 03456 03457 void 03458 edge_adjacent_vertices(toporouter_edge_t *e, toporouter_vertex_t *v, toporouter_vertex_t **v1, toporouter_vertex_t **v2) 03459 { 03460 GList *r = g_list_find(edge_routing(e), v); 03461 03462 if(v == tedge_v1(e)) { 03463 *v1 = NULL; 03464 *v2 = edge_routing_next_not_temp(e, edge_routing(e)); 03465 }else if(v == tedge_v2(e)) { 03466 *v1 = edge_routing_prev_not_temp(e, g_list_last(edge_routing(e))); 03467 *v2 = NULL; 03468 }else{ 03469 // r = g_list_find(r, v); 03470 *v1 = edge_routing_prev_not_temp(e, r); 03471 *v2 = edge_routing_next_not_temp(e, r); 03472 03473 } 03474 03475 } 03476 03477 03478 GList * 03479 candidate_vertices(toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *dest, toporouter_edge_t *e) 03480 { 03481 gdouble totald, v1ms, v2ms, flow, capacity, ms; 03482 GList *vs = NULL; 03483 03484 g_assert(v1); 03485 g_assert(v2); 03486 g_assert(dest); 03487 03488 g_assert(!(v1->flags & VERTEX_FLAG_TEMP)); 03489 g_assert(!(v2->flags & VERTEX_FLAG_TEMP)); 03490 #ifdef DEBUG_ROUTE 03491 printf("starting candidate vertices\n"); 03492 printf("v1 = %f,%f v2 = %f,%f dest = %f,%f\n", vx(v1), vy(v1), vx(v2), vy(v2), vx(dest), vy(dest)); 03493 #endif 03494 totald = gts_point_distance(GTS_POINT(v1), GTS_POINT(v2)); 03495 v1ms = min_spacing(v1, dest); 03496 v2ms = min_spacing(v2, dest); 03497 ms = min_spacing(dest, dest); 03498 flow = TOPOROUTER_IS_CONSTRAINT(e) ? 0. : edge_flow(e, v1, v2, dest); 03499 capacity = edge_capacity(e); 03500 03501 #ifdef DEBUG_ROUTE 03502 g_assert(totald > 0); 03503 03504 printf("v1ms = %f v2ms = %f totald = %f ms = %f capacity = %f flow = %f\n", v1ms, v2ms, totald, ms, capacity, flow); 03505 #endif 03506 03507 if(flow >= capacity) return NULL; 03508 03509 03510 if(v1ms + v2ms + ms >= totald) { 03511 vs = g_list_prepend(vs, new_temp_toporoutervertex((vx(v1)+vx(v2)) / 2., (vy(v1)+vy(v2)) / 2., e)); 03512 }else{ 03513 gdouble x0, y0, x1, y1, d; 03514 03515 vertex_move_towards_vertex_values(GTS_VERTEX(v1), GTS_VERTEX(v2), v1ms, &x0, &y0); 03516 03517 vs = g_list_prepend(vs, new_temp_toporoutervertex(x0, y0, e)); 03518 03519 vertex_move_towards_vertex_values(GTS_VERTEX(v2), GTS_VERTEX(v1), v2ms, &x1, &y1); 03520 03521 vs = g_list_prepend(vs, new_temp_toporoutervertex(x1, y1, e)); 03522 03523 d = hypot(x0-x1,y0-y1); 03524 03525 if(ms < d) { 03526 // guint nint = d / ms; 03527 // gdouble dif = d / (nint + 1); 03528 gdouble dif = d / 2; 03529 03530 // for(guint j=0;j<nint;j++) { 03531 gdouble x, y; 03532 03533 // coord_move_towards_coord_values(x0, y0, x1, y1, dif * j, &x, &y); 03534 coord_move_towards_coord_values(x0, y0, x1, y1, dif, &x, &y); 03535 03536 vs = g_list_prepend(vs, new_temp_toporoutervertex(x, y, e)); 03537 03538 // } 03539 03540 } 03541 03542 } 03543 #ifdef DEBUG_ROUTE 03544 printf("candidate vertices returning %d\n", g_list_length(vs)); 03545 #endif 03546 return vs; 03547 } 03548 03549 GList * 03550 edge_routing_first_not_temp(toporouter_edge_t *e) 03551 { 03552 GList *i = edge_routing(e); 03553 toporouter_vertex_t *v; 03554 03555 while(i) { 03556 v = TOPOROUTER_VERTEX(i->data); 03557 if(!(v->flags & VERTEX_FLAG_TEMP)) return i; 03558 03559 i = i->next; 03560 } 03561 03562 return NULL; 03563 } 03564 03565 GList * 03566 edge_routing_last_not_temp(toporouter_edge_t *e) 03567 { 03568 GList *i = edge_routing(e), *last = NULL; 03569 toporouter_vertex_t *v; 03570 03571 while(i) { 03572 v = TOPOROUTER_VERTEX(i->data); 03573 if(!(v->flags & VERTEX_FLAG_TEMP)) last = i; 03574 03575 i = i->next; 03576 } 03577 03578 return last; 03579 } 03580 03581 void 03582 delete_vertex(toporouter_vertex_t *v) 03583 { 03584 03585 if(v->flags & VERTEX_FLAG_TEMP) { 03586 if(v->routingedge) { 03587 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 03588 TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v); 03589 else 03590 v->routingedge->routing = g_list_remove(v->routingedge->routing, v); 03591 } 03592 03593 gts_object_destroy ( GTS_OBJECT(v) ); 03594 } 03595 } 03596 03597 #define edge_is_blocked(e) (TOPOROUTER_IS_EDGE(e) ? (e->flags & EDGE_FLAG_DIRECTCONNECTION) : 0) 03598 03599 GList * 03600 triangle_candidate_points_from_vertex(GtsTriangle *t, toporouter_vertex_t *v, toporouter_vertex_t *dest, toporouter_route_t *routedata) 03601 { 03602 toporouter_edge_t *op_e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v))); 03603 toporouter_vertex_t *vv1, *vv2, *constraintv = NULL; 03604 toporouter_edge_t *e1, *e2; 03605 GList *i; 03606 GList *rval = NULL; 03607 03608 #ifdef DEBUG_ROUTE 03609 printf("\tTRIANGLE CAND POINT FROM VERTEX\n"); 03610 03611 g_assert(op_e); 03612 #endif 03613 03614 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), edge_v1(op_e))); 03615 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), edge_v2(op_e))); 03616 03617 03618 if(TOPOROUTER_IS_CONSTRAINT(op_e)) { 03619 if(TOPOROUTER_CONSTRAINT(op_e)->box->type == BOARD) { 03620 #ifdef DEBUG_ROUTE 03621 printf("BOARD constraint\n"); 03622 #endif 03623 return NULL; 03624 } 03625 if(constraint_netlist(TOPOROUTER_CONSTRAINT(op_e)) != vertex_netlist(dest)) { // || TOPOROUTER_CONSTRAINT(op_e)->routing) { 03626 #ifdef DEBUG_ROUTE 03627 printf("op_e routing:\n"); 03628 print_edge(op_e); 03629 #endif 03630 return NULL; 03631 } 03632 #ifdef DEBUG_ROUTE 03633 printf("RETURNING CONSTRAINT POING\n"); 03634 #endif 03635 constraintv = new_temp_toporoutervertex_in_segment(op_e, TOPOROUTER_VERTEX(edge_v1(op_e)), 03636 gts_point_distance(GTS_POINT(edge_v1(op_e)), GTS_POINT(edge_v2(op_e))) / 2., TOPOROUTER_VERTEX(edge_v2(op_e))); 03637 // return g_list_prepend(NULL, vv1); 03638 03639 03640 } 03641 03642 if(edge_is_blocked(op_e)) { 03643 goto triangle_candidate_points_from_vertex_exit; 03644 } 03645 // v1 = tedge_v1(op_e); 03646 // v2 = tedge_v2(op_e); 03647 03648 if(v == tedge_v1(e1)) { 03649 i = edge_routing_first_not_temp(e1); 03650 }else{ 03651 i = edge_routing_last_not_temp(e1); 03652 } 03653 03654 if(i) { 03655 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data); 03656 03657 if(temp->parent == tedge_v2(op_e) || temp->child == tedge_v2(op_e)) { 03658 #ifdef DEBUG_ROUTE 03659 printf("temp -> op_e->v2\n"); 03660 #endif 03661 goto triangle_candidate_points_from_vertex_exit; 03662 } 03663 if(temp->parent->routingedge == op_e) { 03664 vv1 = temp->parent; 03665 #ifdef DEBUG_ROUTE 03666 printf("vv1->parent\n"); 03667 #endif 03668 03669 }else if(temp->child->routingedge == op_e) { 03670 vv1 = temp->child; 03671 #ifdef DEBUG_ROUTE 03672 printf("vv1->child\n"); 03673 #endif 03674 03675 }else{ 03676 // must be to e2 03677 #ifdef DEBUG_ROUTE 03678 printf("temp -> e2?\n"); 03679 printf("op_e = %f,%f\t\t%f,%f\n", vx(edge_v1(op_e)), vy(edge_v1(op_e)), vx(edge_v2(op_e)), vy(edge_v2(op_e)) ); 03680 if(temp->parent->routingedge) 03681 printf("temp->parent->routingedge = %f,%f \t\t %f,%f\n", 03682 vx(edge_v1(temp->parent->routingedge)), vy(edge_v1(temp->parent->routingedge)), 03683 vx(edge_v2(temp->parent->routingedge)), vy(edge_v2(temp->parent->routingedge)) 03684 ); 03685 else 03686 printf("temp->parent->routingedge = NULL\n"); 03687 03688 if(temp->child->routingedge) 03689 printf("temp->child->routingedge = %f,%f \t\t %f,%f\n", 03690 vx(edge_v1(temp->child->routingedge)), vy(edge_v1(temp->child->routingedge)), 03691 vx(edge_v2(temp->child->routingedge)), vy(edge_v2(temp->child->routingedge)) 03692 ); 03693 else 03694 printf("temp->child->routingedge = NULL\n"); 03695 #endif 03696 goto triangle_candidate_points_from_vertex_exit; 03697 } 03698 03699 }else{ 03700 vv1 = tedge_v1(op_e); 03701 #ifdef DEBUG_ROUTE 03702 printf("nothing on e1\n"); 03703 #endif 03704 } 03705 03706 if(v == tedge_v1(e2)) { 03707 i = edge_routing_first_not_temp(e2); 03708 }else{ 03709 i = edge_routing_last_not_temp(e2); 03710 } 03711 03712 if(i) { 03713 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data); 03714 03715 if(temp->parent == tedge_v1(op_e) || temp->child == tedge_v1(op_e)) { 03716 #ifdef DEBUG_ROUTE 03717 printf("temp -> op_e->v2\n"); 03718 #endif 03719 goto triangle_candidate_points_from_vertex_exit; 03720 } 03721 03722 if(temp->parent->routingedge == op_e) { 03723 vv2 = temp->parent; 03724 #ifdef DEBUG_ROUTE 03725 printf("vv2->parent\n"); 03726 #endif 03727 }else if(temp->child->routingedge == op_e) { 03728 vv2 = temp->child; 03729 #ifdef DEBUG_ROUTE 03730 printf("vv2->child\n"); 03731 #endif 03732 03733 }else{ 03734 // must be to e1 03735 #ifdef DEBUG_ROUTE 03736 printf("temp -> e1?\n"); 03737 printf("op_e = %f,%f\t\t%f,%f\n", vx(edge_v1(op_e)), vy(edge_v1(op_e)), vx(edge_v2(op_e)), vy(edge_v2(op_e)) ); 03738 if(temp->parent->routingedge) 03739 printf("temp->parent->routingedge = %f,%f \t\t %f,%f\n", 03740 vx(edge_v1(temp->parent->routingedge)), vy(edge_v1(temp->parent->routingedge)), 03741 vx(edge_v2(temp->parent->routingedge)), vy(edge_v2(temp->parent->routingedge)) 03742 ); 03743 else 03744 printf("temp->parent->routingedge = NULL\n"); 03745 03746 if(temp->child->routingedge) 03747 printf("temp->child->routingedge = %f,%f \t\t %f,%f\n", 03748 vx(edge_v1(temp->child->routingedge)), vy(edge_v1(temp->child->routingedge)), 03749 vx(edge_v2(temp->child->routingedge)), vy(edge_v2(temp->child->routingedge)) 03750 ); 03751 else 03752 printf("temp->child->routingedge = NULL\n"); 03753 #endif 03754 goto triangle_candidate_points_from_vertex_exit; 03755 } 03756 03757 }else{ 03758 vv2 = tedge_v2(op_e); 03759 #ifdef DEBUG_ROUTE 03760 printf("nothing on e2\n"); 03761 #endif 03762 } 03763 03764 #ifdef DEBUG_ROUTE 03765 printf("size of e1 routing = %d e2 routing = %d op_e routing = %d\n", 03766 g_list_length(edge_routing(e1)), g_list_length(edge_routing(e2)), g_list_length(edge_routing(op_e))); 03767 #endif 03768 03769 if(constraintv) { 03770 #ifdef DEBUG_ROUTE 03771 print_vertex(constraintv); 03772 printf("constraintv %f,%f returning\n", vx(constraintv), vy(constraintv)); 03773 #endif 03774 return g_list_prepend(NULL, constraintv); 03775 } 03776 03777 i = edge_routing(op_e); 03778 while(i) { 03779 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data); 03780 03781 if(temp->parent == v || temp->child == v) { 03782 rval = g_list_concat(rval, candidate_vertices(vv1, temp, dest, op_e)); 03783 vv1 = temp; 03784 } 03785 03786 i = i->next; 03787 } 03788 03789 rval = g_list_concat(rval, candidate_vertices(vv1, vv2, dest, op_e)); 03790 03791 return rval; 03792 03793 03794 03795 triangle_candidate_points_from_vertex_exit: 03796 if(constraintv) //delete_vertex(constraintv); 03797 g_hash_table_insert(routedata->alltemppoints, constraintv, constraintv); 03798 03799 g_list_free(rval); 03800 03801 return NULL; 03802 } 03803 03804 void 03805 routedata_insert_temppoints(toporouter_route_t *data, GList *temppoints) { 03806 GList *j = temppoints; 03807 while(j) { 03808 g_hash_table_insert(data->alltemppoints, j->data, j->data); 03809 j = j->next; 03810 } 03811 } 03812 03813 03814 static inline gint 03815 constraint_route_test(toporouter_constraint_t *c, toporouter_route_t *routedata) 03816 { 03817 if(c->box->cluster && c->box->cluster->netlist == routedata->src->netlist) { 03818 if(c->box->cluster->c == routedata->dest->c || c->box->cluster->c == routedata->src->c) return 1; 03819 } 03820 return 0; 03821 } 03822 03823 GList * 03824 all_candidates_on_edge(toporouter_edge_t *e, toporouter_route_t *routedata) 03825 { 03826 GList *rval = NULL; 03827 if(edge_is_blocked(e)) return NULL; 03828 03829 if(!TOPOROUTER_IS_CONSTRAINT(e)) { 03830 GList *i = edge_routing(e); 03831 toporouter_vertex_t *pv = tedge_v1(e); 03832 03833 while(i) { 03834 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 03835 if(!(v->flags & VERTEX_FLAG_TEMP)) { 03836 rval = g_list_concat(rval, candidate_vertices(pv, v, TOPOROUTER_VERTEX(routedata->destvertices->data), e)); 03837 pv = v; 03838 } 03839 i = i->next; 03840 } 03841 03842 rval = g_list_concat(rval, candidate_vertices(pv, tedge_v2(e), TOPOROUTER_VERTEX(routedata->destvertices->data), e)); 03843 }else if(TOPOROUTER_CONSTRAINT(e)->box->type == BOARD) { 03844 return NULL; 03845 }else if(constraint_route_test(TOPOROUTER_CONSTRAINT(e), routedata)) { 03846 toporouter_vertex_t *consv = new_temp_toporoutervertex_in_segment(e, tedge_v1(e), tvdistance(tedge_v1(e), tedge_v2(e)) / 2., tedge_v2(e)); 03847 rval = g_list_prepend(rval, consv); 03848 // g_hash_table_insert(routedata->alltemppoints, consv, consv); 03849 } 03850 03851 return rval; 03852 } 03853 03854 GList * 03855 triangle_all_candidate_points_from_vertex(GtsTriangle *t, toporouter_vertex_t *v, toporouter_route_t *routedata) 03856 { 03857 toporouter_edge_t *op_e = TOPOROUTER_EDGE(gts_triangle_edge_opposite(t, GTS_VERTEX(v))); 03858 return all_candidates_on_edge(op_e, routedata); 03859 } 03860 03861 GList * 03862 triangle_all_candidate_points_from_edge(toporouter_t *r, GtsTriangle *t, toporouter_edge_t *e, toporouter_route_t *routedata, 03863 toporouter_vertex_t **dest, toporouter_vertex_t *curpoint) 03864 { 03865 toporouter_vertex_t *op_v; 03866 toporouter_edge_t *e1, *e2; 03867 GList *i, *rval = NULL, *rval2 = NULL; 03868 toporouter_vertex_t *boxpoint = NULL; 03869 guint e1intcap, e2intcap; 03870 03871 op_v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e))); 03872 03873 03874 if(vertex_bbox(op_v)) boxpoint = TOPOROUTER_VERTEX(vertex_bbox(op_v)->point); 03875 03876 if(g_list_find(routedata->destvertices, op_v)) { 03877 rval = g_list_prepend(rval, op_v); 03878 *dest = op_v; 03879 return rval; 03880 }else if(g_list_find(routedata->destvertices, boxpoint)) { 03881 *dest = boxpoint; 03882 }else if(g_list_find(routedata->srcvertices, op_v)) { 03883 rval = g_list_prepend(rval, op_v); 03884 } 03885 03886 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v1(e))); 03887 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v2(e))); 03888 03889 rval = g_list_concat(rval, all_candidates_on_edge(e1, routedata)); 03890 rval = g_list_concat(rval, all_candidates_on_edge(e2, routedata)); 03891 03892 e1intcap = check_triangle_interior_capacity(t, tedge_v1(e), curpoint, e2, e, e1); 03893 e2intcap = check_triangle_interior_capacity(t, tedge_v2(e), curpoint, e1, e, e2); 03894 03895 i = rval; 03896 while(i) { 03897 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 03898 03899 if(!v->routingedge) 03900 rval2 = g_list_prepend(rval2, v); 03901 else if(v->routingedge == e1 && !(!TOPOROUTER_IS_CONSTRAINT(e1) && !e1intcap)) 03902 rval2 = g_list_prepend(rval2, v); 03903 else if(v->routingedge == e2 && !(!TOPOROUTER_IS_CONSTRAINT(e2) && !e2intcap)) 03904 rval2 = g_list_prepend(rval2, v); 03905 03906 i = i->next; 03907 } 03908 g_list_free(rval); 03909 03910 return rval2; 03911 } 03912 03913 GList * 03914 triangle_candidate_points_from_edge(toporouter_t *r, GtsTriangle *t, toporouter_edge_t *e, toporouter_vertex_t *v, toporouter_vertex_t **dest, 03915 toporouter_route_t *routedata) 03916 { 03917 toporouter_vertex_t *v1, *v2, *op_v, *vv = NULL, *e1constraintv = NULL, *e2constraintv = NULL; 03918 toporouter_edge_t *e1, *e2; 03919 GList *e1cands = NULL, *e2cands = NULL, *rval = NULL; 03920 guint noe1 = 0, noe2 = 0; 03921 03922 op_v = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(t, GTS_EDGE(e))); 03923 03924 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v1(e))); 03925 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(op_v), edge_v2(e))); 03926 03927 g_assert(*dest); 03928 03929 // v1 is prev dir, v2 is next dir 03930 edge_adjacent_vertices(e, v, &v1, &v2); 03931 03932 if(TOPOROUTER_IS_CONSTRAINT(e1)) { 03933 GList *i = edge_routing(e1); 03934 03935 if(TOPOROUTER_CONSTRAINT(e1)->box->type == BOARD) { 03936 noe1 = 1; 03937 }else if(!constraint_route_test(TOPOROUTER_CONSTRAINT(e1), routedata)) { 03938 noe1 = 1; 03939 #ifdef DEBUG_ROUTE 03940 printf("noe1 netlist\n"); 03941 #endif 03942 }else 03943 03944 if(v1 == tedge_v1(e) || 03945 (v1->parent->routingedge && v1->parent->routingedge == e1) || 03946 (v1->child->routingedge && v1->child->routingedge == e1)) { 03947 e1constraintv = new_temp_toporoutervertex_in_segment(e1, tedge_v1(e1), gts_point_distance(GTS_POINT(edge_v1(e1)), GTS_POINT(edge_v2(e1))) / 2., tedge_v2(e1)); 03948 } 03949 03950 while(i) { 03951 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data); 03952 03953 if((temp->child == tedge_v2(e) || temp->parent == tedge_v2(e)) && !(temp->flags & VERTEX_FLAG_TEMP)) noe2 = 1; 03954 03955 i = i->next; 03956 } 03957 03958 goto triangle_candidate_points_e2; 03959 } 03960 03961 if(edge_is_blocked(e1)) { 03962 noe1 = 1; 03963 goto triangle_candidate_points_e2; 03964 } 03965 03966 if(v1 == tedge_v1(e)) { 03967 // continue up e1 03968 toporouter_vertex_t *vv1, *vv2; 03969 edge_adjacent_vertices(e1, v1, &vv1, &vv2); 03970 03971 #ifdef DEBUG_ROUTE 03972 printf("v1 == e->v1\n"); 03973 #endif 03974 03975 if(vv1) { 03976 // candidates from v1 until vv1 03977 vv = vv1; 03978 }else{ 03979 // candidates from v1 until vv2 03980 vv = vv2; 03981 } 03982 03983 if(!e1constraintv) e1cands = candidate_vertices(v1, vv, *dest, e1); 03984 03985 if(vv != op_v) { 03986 if(vv->parent == tedge_v2(e) || vv->child == tedge_v2(e)) { 03987 #ifdef DEBUG_ROUTE 03988 printf("noe2 0\n"); 03989 #endif 03990 noe2 = 1; 03991 } 03992 } 03993 03994 }else if(v1->parent != op_v && v1->child != op_v) { 03995 toporouter_vertex_t *vv1 = NULL, *vv2 = NULL; 03996 03997 #ifdef DEBUG_ROUTE 03998 printf("v1 != e->v1\n"); 03999 #endif 04000 04001 if(v1->parent->routingedge == e1) { 04002 vv1 = v1->parent; 04003 #ifdef DEBUG_ROUTE 04004 printf("v1 parent = e1\n"); 04005 #endif 04006 if(op_v == tedge_v1(e1)) { 04007 // candidates from v1->parent until prev vertex 04008 vv2 = edge_routing_prev_not_temp(e1, g_list_find(edge_routing(e1), v1->parent)->prev); 04009 }else{ 04010 // candidates from v1->parent until next vertex 04011 vv2 = edge_routing_next_not_temp(e1, g_list_find(edge_routing(e1), v1->parent)->next); 04012 } 04013 04014 }else if(v1->child->routingedge == e1) { 04015 vv1 = v1->child; 04016 #ifdef DEBUG_ROUTE 04017 printf("v1 child = e1\n"); 04018 #endif 04019 if(op_v == tedge_v1(e1)) { 04020 // candidates from v1->child until prev vertex 04021 vv2 = edge_routing_prev_not_temp(e1, g_list_find(edge_routing(e1), v1->child)->prev); 04022 }else{ 04023 // candidates from v1->child until next vertex 04024 vv2 = edge_routing_next_not_temp(e1, g_list_find(edge_routing(e1), v1->child)->next); 04025 } 04026 04027 }else{ 04028 #ifdef DEBUG_ROUTE 04029 printf("v1 ? \n"); 04030 #endif 04031 goto triangle_candidate_points_e2; 04032 } 04033 04034 if(vv1 && vv2) { 04035 if(vv2->parent == tedge_v2(e) || vv2->child == tedge_v2(e)) { 04036 #ifdef DEBUG_ROUTE 04037 printf("noe2 1\n"); 04038 #endif 04039 noe2 = 1; 04040 } 04041 04042 if(!e1constraintv) e1cands = candidate_vertices(vv1, vv2, *dest, e1); 04043 04044 vv = vv2; 04045 } 04046 } 04047 04048 if(vv && vv == op_v) { 04049 toporouter_vertex_t *boxpoint = NULL; 04050 04051 if(vertex_bbox(op_v)) boxpoint = TOPOROUTER_VERTEX(vertex_bbox(op_v)->point); 04052 04053 if(g_list_find(routedata->destvertices, op_v)) { 04054 rval = g_list_prepend(rval, op_v); 04055 *dest = op_v; 04056 }else if(g_list_find(routedata->destvertices, boxpoint)) { 04057 *dest = boxpoint; 04058 }else if(g_list_find(routedata->srcvertices, op_v)) { 04059 rval = g_list_prepend(rval, op_v); 04060 } 04061 } 04062 04063 triangle_candidate_points_e2: 04064 04065 if(noe2) { 04066 // printf("noe2\n"); 04067 goto triangle_candidate_points_finish; 04068 } 04069 04070 if(TOPOROUTER_IS_CONSTRAINT(e2)) { 04071 GList *i = edge_routing(e2); 04072 04073 if(TOPOROUTER_CONSTRAINT(e2)->box->type == BOARD) { 04074 noe2 = 1; 04075 // goto triangle_candidate_points_finish; 04076 }else if(!constraint_route_test(TOPOROUTER_CONSTRAINT(e2), routedata)) { 04077 #ifdef DEBUG_ROUTE 04078 printf("noe2 netlist\n"); 04079 #endif 04080 noe2 = 1; 04081 // goto triangle_candidate_points_finish; 04082 }else if(v2 == tedge_v2(e) || 04083 (v2->parent->routingedge && v2->parent->routingedge == e2) || 04084 (v2->child->routingedge && v2->child->routingedge == e2)) { 04085 04086 e2constraintv = new_temp_toporoutervertex_in_segment(e2, tedge_v1(e2), gts_point_distance(GTS_POINT(edge_v1(e2)), GTS_POINT(edge_v2(e2))) / 2., tedge_v2(e2)); 04087 04088 } 04089 04090 while(i) { 04091 toporouter_vertex_t *temp = TOPOROUTER_VERTEX(i->data); 04092 04093 if((temp->child == tedge_v1(e) || temp->parent == tedge_v1(e)) && !(temp->flags & VERTEX_FLAG_TEMP)) 04094 noe1 = 1; 04095 04096 i = i->next; 04097 } 04098 04099 04100 04101 goto triangle_candidate_points_finish; 04102 } 04103 04104 if(edge_is_blocked(e2)) { 04105 noe2 = 1; 04106 goto triangle_candidate_points_finish; 04107 } 04108 04109 if(v2 == tedge_v2(e)) { 04110 // continue up e2 04111 toporouter_vertex_t *vv1 = NULL, *vv2 = NULL; 04112 edge_adjacent_vertices(e2, v2, &vv1, &vv2); 04113 04114 #ifdef DEBUG_ROUTE 04115 printf("v2 == e->v2\n"); 04116 #endif 04117 04118 if(vv1) { 04119 // candidates from v2 until vv1 04120 vv = vv1; 04121 }else{ 04122 // candidates from v2 until vv2 04123 vv = vv2; 04124 } 04125 04126 if(!e2constraintv) e2cands = candidate_vertices(v2, vv, *dest, e2); 04127 04128 if(vv != op_v) { 04129 if(vv->parent == tedge_v1(e) || vv->child == tedge_v1(e)) { 04130 #ifdef DEBUG_ROUTE 04131 printf("noe1 0\n"); 04132 #endif 04133 noe1 = 1; 04134 } 04135 } 04136 04137 }else if(v2->parent != op_v && v2->child != op_v) { 04138 toporouter_vertex_t *vv1 = NULL, *vv2 = NULL; 04139 04140 #ifdef DEBUG_ROUTE 04141 printf("v2 == e->v2\n"); 04142 #endif 04143 04144 if(v2->parent->routingedge == e2) { 04145 vv1 = v2->parent; 04146 if(op_v == tedge_v1(e2)) { 04147 // candidates from v2->parent until prev vertex 04148 vv2 = edge_routing_prev_not_temp(e2, g_list_find(edge_routing(e2), vv1)->prev); 04149 }else{ 04150 // candidates from v2->parent until next vertex 04151 vv2 = edge_routing_next_not_temp(e2, g_list_find(edge_routing(e2), vv1)->next); 04152 } 04153 04154 }else if(v2->child->routingedge == e2) { 04155 vv1 = v2->child; 04156 if(op_v == tedge_v1(e2)) { 04157 // candidates from v2->child until prev vertex 04158 vv2 = edge_routing_prev_not_temp(e2, g_list_find(edge_routing(e2), vv1)->prev); 04159 }else{ 04160 // candidates from v2->child until next vertex 04161 vv2 = edge_routing_next_not_temp(e2, g_list_find(edge_routing(e2), vv1)->next); 04162 } 04163 04164 }else{ 04165 goto triangle_candidate_points_finish; 04166 } 04167 04168 if(vv1 && vv2) { 04169 if(vv2->parent == tedge_v1(e) || vv2->child == tedge_v1(e)) { 04170 #ifdef DEBUG_ROUTE 04171 printf("noe1 1\n"); 04172 #endif 04173 noe1 = 1; 04174 } 04175 04176 if(!e2constraintv) e2cands = candidate_vertices(vv1, vv2, *dest, e2); 04177 } 04178 } 04179 04180 triangle_candidate_points_finish: 04181 04182 v1 = segment_common_vertex(GTS_SEGMENT(e), GTS_SEGMENT(e1)); 04183 v2 = segment_common_vertex(GTS_SEGMENT(e), GTS_SEGMENT(e2)); 04184 04185 if(noe1 || !check_triangle_interior_capacity(t, v1, v, e2, e, e1)) { 04186 #ifdef DEBUG_ROUTE 04187 printf("freeing e1cands\n"); 04188 #endif 04189 routedata_insert_temppoints(routedata, e1cands); 04190 g_list_free(e1cands); 04191 e1cands = NULL; 04192 } 04193 04194 if(noe2 || !check_triangle_interior_capacity(t, v2, v, e1, e, e2)) { 04195 #ifdef DEBUG_ROUTE 04196 printf("freeing e2cands\n"); 04197 #endif 04198 routedata_insert_temppoints(routedata, e2cands); 04199 g_list_free(e2cands); 04200 e2cands = NULL; 04201 } 04202 04203 if(!noe1 && e1constraintv) { 04204 e1cands = g_list_prepend(e1cands, e1constraintv); 04205 }else if(e1constraintv) { 04206 g_hash_table_insert(routedata->alltemppoints, e1constraintv, e1constraintv); 04207 // delete_vertex(e1constraintv); 04208 } 04209 04210 if(!noe2 && e2constraintv) { 04211 e2cands = g_list_prepend(e2cands, e2constraintv); 04212 }else if(e2constraintv) { 04213 g_hash_table_insert(routedata->alltemppoints, e2constraintv, e2constraintv); 04214 // delete_vertex(e2constraintv); 04215 } 04216 04217 if(!noe1 && !noe2) return g_list_concat(rval, g_list_concat(e1cands, e2cands)); 04218 04219 return g_list_concat(e1cands, e2cands); 04220 } 04221 04222 GList * 04223 compute_candidate_points(toporouter_t *tr, toporouter_layer_t *l, toporouter_vertex_t *curpoint, toporouter_route_t *data, 04224 toporouter_vertex_t **closestdest) 04225 { 04226 GList *r = NULL, *j; 04227 toporouter_edge_t *edge = curpoint->routingedge, *tempedge; 04228 04229 if(vertex_keepout_test(tr, curpoint)) goto compute_candidate_points_finish; 04230 04231 /* direct connection */ 04232 // if(curpoint == TOPOROUTER_VERTEX(data->src->point)) 04233 if((tempedge = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(curpoint), GTS_VERTEX(*closestdest))))) { 04234 04235 if(TOPOROUTER_IS_CONSTRAINT(tempedge)) { 04236 goto compute_candidate_points_finish; 04237 }else{ 04238 if(!tempedge->routing) { 04239 r = g_list_prepend(NULL, *closestdest); 04240 tempedge->flags |= EDGE_FLAG_DIRECTCONNECTION; 04241 goto compute_candidate_points_finish; 04242 }else{ 04243 #ifdef DEBUG_ROUTE 04244 printf("Direct connection, but has routing\n"); 04245 #endif 04246 } 04247 04248 } 04249 /* if we get to here, there is routing blocking the direct connection, 04250 * continue as per normal */ 04251 } 04252 04253 /* a real point origin */ 04254 if(!(curpoint->flags & VERTEX_FLAG_TEMP)) { 04255 GSList *triangles, *i; 04256 i = triangles = gts_vertex_triangles(GTS_VERTEX(curpoint), NULL); 04257 #ifdef DEBUG_ROUTE 04258 printf("triangle count = %d\n", g_slist_length(triangles)); 04259 #endif 04260 while(i) { 04261 GtsTriangle *t = GTS_TRIANGLE(i->data); 04262 GList *temppoints; 04263 04264 if(tr->flags & TOPOROUTER_FLAG_LEASTINVALID) temppoints = triangle_all_candidate_points_from_vertex(t, curpoint, data); 04265 else temppoints = triangle_candidate_points_from_vertex(t, curpoint, *closestdest, data); 04266 04267 #ifdef DEBUG_ROUTE 04268 printf("\treturned %d points\n", g_list_length(temppoints)); 04269 #endif 04270 routedata_insert_temppoints(data, temppoints); 04271 04272 r = g_list_concat(r, temppoints); 04273 i = i->next; 04274 } 04275 g_slist_free(triangles); 04276 }else /* a temp point */ { 04277 int prevwind = vertex_wind(GTS_SEGMENT(edge)->v1, GTS_SEGMENT(edge)->v2, GTS_VERTEX(curpoint->parent)); 04278 // printf("tempoint\n"); 04279 04280 GSList *i = GTS_EDGE(edge)->triangles; 04281 04282 while(i) { 04283 GtsVertex *oppv = gts_triangle_vertex_opposite(GTS_TRIANGLE(i->data), GTS_EDGE(edge)); 04284 if(prevwind != vertex_wind(GTS_SEGMENT(edge)->v1, GTS_SEGMENT(edge)->v2, oppv)) { 04285 GList *temppoints; 04286 04287 if(tr->flags & TOPOROUTER_FLAG_LEASTINVALID) temppoints = triangle_all_candidate_points_from_edge(tr, GTS_TRIANGLE(i->data), edge, 04288 data, closestdest, curpoint); 04289 else temppoints = triangle_candidate_points_from_edge(tr, GTS_TRIANGLE(i->data), edge, curpoint, closestdest, data); 04290 04291 j = temppoints; 04292 while(j) { 04293 toporouter_vertex_t *tempj = TOPOROUTER_VERTEX(j->data); 04294 if(tempj->flags & VERTEX_FLAG_TEMP) 04295 g_hash_table_insert(data->alltemppoints, j->data, j->data); 04296 #ifdef DEBUG_ROUTE 04297 else 04298 printf("got cand not a temp\n"); 04299 #endif 04300 j = j->next; 04301 } 04302 r = g_list_concat(r, temppoints); 04303 04304 break; 04305 } 04306 i = i->next; 04307 } 04308 } 04309 04310 compute_candidate_points_finish: 04311 04312 if(vertex_bbox(curpoint) && vertex_bbox(curpoint)->cluster) { 04313 if(vertex_bbox(curpoint)->cluster->c == data->src->c) { 04314 r = g_list_concat(r, g_list_copy(data->srcvertices)); 04315 } 04316 } 04317 04318 return r; 04319 } 04320 04321 gboolean 04322 temp_point_clean(gpointer key, gpointer value, gpointer user_data) 04323 { 04324 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(value); 04325 if(tv->flags & VERTEX_FLAG_TEMP) { 04326 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 04327 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv); 04328 else 04329 tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv); 04330 gts_object_destroy ( GTS_OBJECT(tv) ); 04331 } 04332 return TRUE; 04333 } 04334 04335 void 04336 clean_routing_edges(toporouter_t *r, toporouter_route_t *data) 04337 { 04338 g_hash_table_foreach_remove(data->alltemppoints, temp_point_clean, NULL); 04339 g_hash_table_destroy(data->alltemppoints); 04340 data->alltemppoints = NULL; 04341 } 04342 04343 gdouble 04344 path_score(toporouter_t *r, GList *path) 04345 { 04346 gdouble score = 0.; 04347 toporouter_vertex_t *pv = NULL; 04348 toporouter_vertex_t *v0 = NULL; 04349 04350 if(!path) return INFINITY; 04351 04352 v0 = TOPOROUTER_VERTEX(path->data); 04353 04354 while(path) { 04355 toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data); 04356 04357 if(pv) { 04358 score += gts_point_distance(GTS_POINT(pv), GTS_POINT(v)); 04359 if(pv != v0 && vz(pv) != vz(v)) 04360 if(path->next) 04361 score += r->viacost; 04362 04363 } 04364 04365 pv = v; 04366 path = path->next; 04367 } 04368 04369 return score; 04370 } 04371 04372 void 04373 print_vertices(GList *vertices) 04374 { 04375 while(vertices) { 04376 toporouter_vertex_t *v = TOPOROUTER_VERTEX(vertices->data); 04377 print_vertex(v); 04378 print_bbox(vertex_bbox(v)); 04379 if(vertex_bbox(v)) { 04380 printf("has bbox\n"); 04381 if(vertex_bbox(v)->cluster) 04382 printf("has cluster\n"); 04383 else 04384 printf("no cluster\n"); 04385 }else printf("no bbox\n"); 04386 vertices = vertices->next; 04387 } 04388 } 04389 04390 gint 04391 space_edge(gpointer item, gpointer data) 04392 { 04393 toporouter_edge_t *e = TOPOROUTER_EDGE(item); 04394 GList *i; 04395 gdouble *forces; 04396 04397 if(TOPOROUTER_IS_CONSTRAINT(e)) return 0; 04398 04399 if(!edge_routing(e) || !g_list_length(edge_routing(e))) return 0; 04400 04401 forces = (gdouble *)malloc(sizeof(double) * g_list_length(edge_routing(e))); 04402 04403 for(guint j=0;j<100;j++) { 04404 guint k=0; 04405 guint equilibrium = 1; 04406 04407 i = edge_routing(e); 04408 while(i) { 04409 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 04410 gdouble ms, d; 04411 04412 if(i->prev) { 04413 // ms = min_net_net_spacing(TOPOROUTER_VERTEX(i->prev->data), v); 04414 ms = min_spacing(TOPOROUTER_VERTEX(i->prev->data), v); 04415 d = gts_point_distance(GTS_POINT(i->prev->data), GTS_POINT(v)); 04416 }else{ 04417 // ms = min_vertex_net_spacing(v, tedge_v1(e)); 04418 ms = min_spacing(v, tedge_v1(e)); 04419 d = gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(v)); 04420 } 04421 04422 if(d < ms) forces[k] = ms - d; 04423 else forces[k] = 0.; 04424 04425 if(i->next) { 04426 // ms = min_net_net_spacing(TOPOROUTER_VERTEX(i->next->data), v); 04427 ms = min_spacing(TOPOROUTER_VERTEX(i->next->data), v); 04428 d = gts_point_distance(GTS_POINT(i->next->data), GTS_POINT(v)); 04429 }else{ 04430 // ms = min_vertex_net_spacing(v, tedge_v2(e)); 04431 ms = min_spacing(v, tedge_v2(e)); 04432 d = gts_point_distance(GTS_POINT(edge_v2(e)), GTS_POINT(v)); 04433 } 04434 04435 if(d < ms) forces[k] += d - ms; 04436 04437 k++; i = i->next; 04438 } 04439 04440 k = 0; 04441 i = edge_routing(e); 04442 while(i) { 04443 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 04444 if(forces[k] > EPSILON || forces[k] < -EPSILON) equilibrium = 0; 04445 vertex_move_towards_vertex_values(GTS_VERTEX(v), edge_v2(e), forces[k] * 0.1, &(GTS_POINT(v)->x), &(GTS_POINT(v)->y)); 04446 k++; i = i->next; 04447 } 04448 04449 if(equilibrium) { 04450 // printf("reached equilibriium at %d\n", j); 04451 break; 04452 } 04453 04454 } 04455 04456 free(forces); 04457 return 0; 04458 } 04459 04460 void 04461 swap_vertices(toporouter_vertex_t **v1, toporouter_vertex_t **v2) 04462 { 04463 toporouter_vertex_t *tempv = *v1; 04464 *v1 = *v2; 04465 *v2 = tempv; 04466 } 04467 04468 void 04469 split_edge_routing(toporouter_vertex_t *v, GList **l1, GList **l2) 04470 { 04471 GList *base, *i; 04472 04473 g_assert(v); 04474 g_assert(v->routingedge); 04475 04476 base = g_list_find(vrouting(v), v); 04477 04478 *l1 = g_list_prepend(*l1, tedge_v1(v->routingedge)); 04479 *l2 = g_list_prepend(*l2, tedge_v2(v->routingedge)); 04480 04481 g_assert(base); 04482 04483 i = base->next; 04484 while(i) { 04485 if(!(TOPOROUTER_VERTEX(i->data)->flags & VERTEX_FLAG_TEMP)) *l2 = g_list_prepend(*l2, i->data); 04486 i = i->next; 04487 } 04488 04489 i = base->prev; 04490 while(i) { 04491 if(!(TOPOROUTER_VERTEX(i->data)->flags & VERTEX_FLAG_TEMP)) *l1 = g_list_prepend(*l1, i->data); 04492 i = i->prev; 04493 } 04494 } 04495 04496 GList * 04497 vertices_routing_conflicts(toporouter_vertex_t *v, toporouter_vertex_t *pv) 04498 { 04499 toporouter_edge_t *e; 04500 GList *rval = NULL, *l1 = NULL, *l2 = NULL, *i; 04501 04502 if(vz(v) != vz(pv)) return NULL; 04503 g_assert(v != pv); 04504 04505 if(!v->routingedge && !pv->routingedge) { 04506 e = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(v), GTS_VERTEX(pv))); 04507 if(!e) return NULL; 04508 i = edge_routing(e); 04509 while(i) { 04510 rval = g_list_prepend(rval, TOPOROUTER_VERTEX(i->data)->route); 04511 i = i->next; 04512 } 04513 return rval; 04514 } 04515 04516 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge) && TOPOROUTER_IS_CONSTRAINT(pv->routingedge)) 04517 return NULL; 04518 04519 if(TOPOROUTER_IS_CONSTRAINT(pv->routingedge)) swap_vertices(&pv, &v); 04520 04521 if(!v->routingedge) swap_vertices(&pv, &v); 04522 04523 e = v->routingedge; 04524 04525 split_edge_routing(v, &l1, &l2); 04526 g_assert(l2); 04527 g_assert(l1); 04528 04529 if(!pv->routingedge) { 04530 toporouter_edge_t *e1, *e2; 04531 e1 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(pv), edge_v1(e))); 04532 e2 = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(pv), edge_v2(e))); 04533 04534 l1 = g_list_concat(l1, g_list_copy(edge_routing(e1))); 04535 l2 = g_list_concat(l2, g_list_copy(edge_routing(e2))); 04536 04537 }else{ 04538 GList *pvlist1 = NULL, *pvlist2 = NULL; 04539 toporouter_vertex_t *commonv = route_vertices_common_vertex(v, pv); 04540 04541 g_assert(commonv); 04542 04543 split_edge_routing(pv, &pvlist1, &pvlist2); 04544 04545 if(commonv == tedge_v1(e)) { 04546 toporouter_edge_t *ope; 04547 04548 if(commonv == tedge_v1(pv->routingedge)) { 04549 l1 = g_list_concat(l1, pvlist1); 04550 l2 = g_list_concat(l2, pvlist2); 04551 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v2(e), edge_v2(pv->routingedge))); 04552 }else{ 04553 l1 = g_list_concat(l1, pvlist2); 04554 l2 = g_list_concat(l2, pvlist1); 04555 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v2(e), edge_v1(pv->routingedge))); 04556 } 04557 g_assert(ope); 04558 l2 = g_list_concat(l2, g_list_copy(edge_routing(ope))); 04559 04560 }else{ 04561 toporouter_edge_t *ope; 04562 if(commonv == tedge_v1(pv->routingedge)) { 04563 l1 = g_list_concat(l1, pvlist2); 04564 l2 = g_list_concat(l2, pvlist1); 04565 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v1(e), edge_v2(pv->routingedge))); 04566 }else{ 04567 l1 = g_list_concat(l1, pvlist1); 04568 l2 = g_list_concat(l2, pvlist2); 04569 ope = TOPOROUTER_EDGE(gts_vertices_are_connected(edge_v1(e), edge_v1(pv->routingedge))); 04570 } 04571 g_assert(ope); 04572 l1 = g_list_concat(l1, g_list_copy(edge_routing(ope))); 04573 } 04574 } 04575 04576 i = l1; 04577 while(i) { 04578 toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data); 04579 04580 if(curv->flags & VERTEX_FLAG_ROUTE && (g_list_find(l2, curv->parent) || g_list_find(l2, curv->child))) { 04581 if(!g_list_find(rval, curv->route)) rval = g_list_prepend(rval, curv->route); 04582 } 04583 i = i->next; 04584 } 04585 i = l2; 04586 while(i) { 04587 toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data); 04588 04589 if(curv->flags & VERTEX_FLAG_ROUTE && (g_list_find(l1, curv->parent) || g_list_find(l1, curv->child))) { 04590 if(!g_list_find(rval, curv->route)) rval = g_list_prepend(rval, curv->route); 04591 } 04592 i = i->next; 04593 } 04594 04595 g_list_free(l1); 04596 g_list_free(l2); 04597 04598 return rval; 04599 } 04600 04601 gdouble 04602 vertices_routing_conflict_cost(toporouter_t *r, toporouter_vertex_t *v, toporouter_vertex_t *pv, guint *n) 04603 { 04604 GList *conflicts = vertices_routing_conflicts(v, pv), *i; 04605 gdouble penalty = 0.; 04606 04607 i = conflicts; 04608 while(i) { 04609 (*n) += 1; 04610 penalty += TOPOROUTER_ROUTE(i->data)->score; 04611 i = i->next; 04612 } 04613 g_list_free(conflicts); 04614 // if(penalty > 0.) printf("conflict penalty of %f with %f,%f %f,%f\n", penalty, vx(v), vy(v), vx(pv), vy(pv)); 04615 return penalty; 04616 } 04617 04618 gdouble 04619 gcost(toporouter_t *r, toporouter_route_t *data, toporouter_vertex_t *srcv, toporouter_vertex_t *v, toporouter_vertex_t *pv, guint *n, 04620 toporouter_netlist_t *pair) 04621 { 04622 gdouble cost = 0., segcost; 04623 04624 *n = pv->gn; 04625 04626 if(g_list_find(data->srcvertices, v)) return 0.; 04627 04628 segcost = tvdistance(pv, v); 04629 04630 if(pair && !TOPOROUTER_IS_CONSTRAINT(v->routingedge) && v->routingedge) { 04631 GList *list = g_list_find(v->routingedge->routing, v); 04632 toporouter_vertex_t *pv = edge_routing_prev_not_temp(v->routingedge, list); 04633 toporouter_vertex_t *nv = edge_routing_next_not_temp(v->routingedge, list); 04634 04635 if(pv->route && pv->route->netlist == pair) { 04636 }else if(nv->route && nv->route->netlist == pair) { 04637 }else{ 04638 segcost *= 10.; 04639 } 04640 } 04641 04642 cost = pv->gcost + segcost; 04643 04644 if(r->flags & TOPOROUTER_FLAG_LEASTINVALID) { 04645 gdouble conflictcost = 0.; 04646 04647 if(pv && v != pv && vz(v) == vz(pv)) conflictcost = vertices_routing_conflict_cost(r, v, pv, n); 04648 04649 if(!(r->flags & TOPOROUTER_FLAG_DETOUR && *n == 1)) { 04650 cost += conflictcost * (pow(*n,2)); 04651 } 04652 } 04653 04654 return cost; 04655 } 04656 04657 #define vlayer(x) (&r->layers[(int)vz(x)]) 04658 04659 guint 04660 candidate_is_available(toporouter_vertex_t *pv, toporouter_vertex_t *v) 04661 { 04662 // TODO: still needed? 04663 while(pv) { 04664 if(pv == v) return 0; 04665 pv = pv->parent; 04666 } 04667 04668 return 1; 04669 } 04670 04671 GList * 04672 route(toporouter_t *r, toporouter_route_t *data, guint debug) 04673 { 04674 GtsEHeap *openlist = gts_eheap_new(route_heap_cmp, NULL); 04675 GList *closelist = NULL; 04676 GList *i, *rval = NULL; 04677 toporouter_netlist_t *pair = NULL; 04678 gint count = 0; 04679 04680 toporouter_vertex_t *srcv = NULL, *destv = NULL, *curpoint = NULL; 04681 toporouter_layer_t *cur_layer; //, *dest_layer; 04682 04683 g_assert(data->src->c != data->dest->c); 04684 04685 if(data->destvertices) g_list_free(data->destvertices); 04686 if(data->srcvertices) g_list_free(data->srcvertices); 04687 04688 data->destvertices = cluster_vertices(r, data->dest); 04689 data->srcvertices = cluster_vertices(r, data->src); 04690 04691 closest_cluster_pair(r, data->srcvertices, data->destvertices, &curpoint, &destv); 04692 04693 if(!curpoint || !destv) goto routing_return; 04694 04695 srcv = curpoint; 04696 cur_layer = vlayer(curpoint); 04697 //dest_layer = vlayer(destv); 04698 04699 data->path = NULL; 04700 04701 data->alltemppoints = g_hash_table_new(g_direct_hash, g_direct_equal); 04702 04703 curpoint->parent = NULL; 04704 curpoint->child = NULL; 04705 curpoint->gcost = 0.; 04706 curpoint->gn = 0; 04707 curpoint->hcost = simple_h_cost(r, curpoint, destv); 04708 04709 if(data->netlist && data->netlist->pair) { 04710 GList *i = r->routednets; 04711 while(i) { 04712 toporouter_route_t *curroute = TOPOROUTER_ROUTE(i->data); 04713 if(curroute->netlist == data->netlist->pair) { 04714 pair = data->netlist->pair; 04715 break; 04716 } 04717 i = i->next; 04718 } 04719 } 04720 04721 gts_eheap_insert(openlist, curpoint); 04722 04723 while(gts_eheap_size(openlist) > 0) { 04724 GList *candidatepoints; 04725 data->curpoint = curpoint; 04726 //draw_route_status(r, closelist, openlist, curpoint, data, count++); 04727 04728 curpoint = TOPOROUTER_VERTEX( gts_eheap_remove_top(openlist, NULL) ); 04729 if(curpoint->parent && !(curpoint->flags & VERTEX_FLAG_TEMP)) { 04730 if(vz(curpoint) != vz(destv)) { 04731 toporouter_vertex_t *tempv; 04732 cur_layer = vlayer(curpoint);//&r->layers[(int)vz(curpoint)]; 04733 tempv = closest_dest_vertex(r, curpoint, data); 04734 if(tempv) { 04735 destv = tempv; 04736 //dest_layer = vlayer(destv);//&r->layers[(int)vz(destv)]; 04737 04738 } 04739 } 04740 } 04741 04742 // destpoint = closest_dest_vertex(r, curpoint, data); 04743 // dest_layer = &r->layers[(int)vz(destpoint)]; 04744 04745 if(g_list_find(data->destvertices, curpoint)) { 04746 toporouter_vertex_t *temppoint = curpoint; 04747 srcv = NULL; 04748 destv = curpoint; 04749 04750 data->path = NULL; 04751 04752 while(temppoint) { 04753 data->path = g_list_prepend(data->path, temppoint); 04754 if(g_list_find(data->srcvertices, temppoint)) { 04755 srcv = temppoint; 04756 if(r->flags & TOPOROUTER_FLAG_AFTERORDER) break; 04757 } 04758 temppoint = temppoint->parent; 04759 } 04760 rval = data->path; 04761 data->score = path_score(r, data->path); 04762 #ifdef DEBUG_ROUTE 04763 printf("ROUTE: path score = %f computation cost = %d\n", data->score, count); 04764 #endif 04765 04766 if(srcv->bbox->cluster != data->src) { 04767 data->src = srcv->bbox->cluster; 04768 } 04769 04770 if(destv->bbox->cluster != data->dest) { 04771 data->dest = destv->bbox->cluster; 04772 } 04773 goto route_finish; 04774 } 04775 closelist_insert(curpoint); 04776 #ifdef DEBUG_ROUTE 04777 printf("\n\n\n*** ROUTE COUNT = %d\n", count); 04778 #endif 04779 candidatepoints = compute_candidate_points(r, cur_layer, curpoint, data, &destv); 04780 04781 //#ifdef DEBUG_ROUTE 04782 /********************* 04783 if(debug && !strcmp(data->dest->netlist, " unnamed_net2")) 04784 { 04785 unsigned int mask = ~(VERTEX_FLAG_RED | VERTEX_FLAG_GREEN | VERTEX_FLAG_BLUE); 04786 char buffer[256]; 04787 int j; 04788 04789 for(j=0;j<groupcount();j++) { 04790 i = r->layers[j].vertices; 04791 while(i) { 04792 TOPOROUTER_VERTEX(i->data)->flags &= mask; 04793 i = i->next; 04794 } 04795 } 04796 04797 i = candidatepoints; 04798 while(i) { 04799 TOPOROUTER_VERTEX(i->data)->flags |= VERTEX_FLAG_GREEN; 04800 // printf("flagged a candpoint @ %f,%f\n", 04801 // vx(i->data), vy(i->data)); 04802 i = i->next; 04803 } 04804 04805 curpoint->flags |= VERTEX_FLAG_BLUE; 04806 if(curpoint->parent) 04807 curpoint->parent->flags |= VERTEX_FLAG_RED; 04808 04809 04810 for(j=0;j<groupcount();j++) { 04811 GList *datas = g_list_prepend(NULL, data); 04812 sprintf(buffer, "route-%d-%05d.png", j, count); 04813 toporouter_draw_surface(r, r->layers[j].surface, buffer, 1024, 1024, 2, datas, j, candidatepoints); 04814 g_list_free(datas); 04815 } 04816 } 04817 //#endif 04818 *********************/ 04819 count++; 04820 // if(count > 100) exit(0); 04821 i = candidatepoints; 04822 while(i) { 04823 toporouter_vertex_t *temppoint = TOPOROUTER_VERTEX(i->data); 04824 if(!g_list_find(closelist, temppoint) && candidate_is_available(curpoint, temppoint)) { //&& temppoint != curpoint) { 04825 toporouter_heap_search_data_t heap_search_data = { temppoint, NULL }; 04826 04827 guint temp_gn; 04828 gdouble temp_g_cost = gcost(r, data, srcv, temppoint, curpoint, &temp_gn, pair); 04829 04830 04831 gts_eheap_foreach(openlist,toporouter_heap_search, &heap_search_data); 04832 04833 if(heap_search_data.result) { 04834 if(temp_g_cost < temppoint->gcost) { 04835 04836 temppoint->gcost = temp_g_cost; 04837 temppoint->gn = temp_gn; 04838 04839 temppoint->parent = curpoint; 04840 curpoint->child = temppoint; 04841 04842 gts_eheap_update(openlist); 04843 } 04844 }else{ 04845 temppoint->parent = curpoint; 04846 curpoint->child = temppoint; 04847 04848 temppoint->gcost = temp_g_cost; 04849 temppoint->gn = temp_gn; 04850 04851 temppoint->hcost = simple_h_cost(r, temppoint, destv); 04852 // if(cur_layer != dest_layer) temppoint->hcost += r->viacost; 04853 gts_eheap_insert(openlist, temppoint); 04854 } 04855 04856 } 04857 i = i->next; 04858 } 04859 g_list_free(candidatepoints); 04860 04861 } 04862 #ifdef DEBUG_ROUTE 04863 printf("ROUTE: could not find path!\n"); 04864 #endif 04865 04866 data->score = INFINITY; 04867 clean_routing_edges(r, data); 04868 04869 data->path = NULL; 04870 //TOPOROUTER_VERTEX(data->src->point)->parent = NULL; 04871 //TOPOROUTER_VERTEX(data->src->point)->child = NULL; 04872 goto routing_return; 04873 04874 /* 04875 { 04876 int i; 04877 for(i=0;i<groupcount();i++) { 04878 char buffer[256]; 04879 sprintf(buffer, "route-error-%d-%d.png", r->routecount, i); 04880 toporouter_draw_surface(r, r->layers[i].surface, buffer, 1280, 1280, 2, data, i, NULL); 04881 } 04882 r->routecount++; 04883 } 04884 // exit(0); 04885 */ 04886 route_finish: 04887 // printf(" * finished a*\n"); 04888 /* 04889 { 04890 int i; 04891 for(i=0;i<groupcount();i++) { 04892 char buffer[256]; 04893 sprintf(buffer, "route-preclean-%d-%d.png", i, r->routecount); 04894 toporouter_draw_surface(r, r->layers[i].surface, buffer, 1024, 1024, 2, data, i, NULL); 04895 } 04896 r->routecount++; 04897 } 04898 */ 04899 /* { 04900 i = data->path; 04901 while(i) { 04902 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 04903 04904 if(tv->routingedge) { 04905 GList *list = g_list_find(edge_routing(tv->routingedge), tv); 04906 toporouter_vertex_t *restartv = NULL, *boxpoint; 04907 04908 g_assert(list); 04909 04910 if(!list->next) { 04911 if(vertex_bbox(tedge_v2(tv->routingedge))) 04912 boxpoint = TOPOROUTER_VERTEX(vertex_bbox(tedge_v2(tv->routingedge))->point); 04913 else 04914 boxpoint = NULL; 04915 04916 if(tedge_v2(tv->routingedge) != srcv && g_list_find(data->srcvertices, tedge_v2(tv->routingedge))) 04917 restartv = tedge_v2(tv->routingedge); 04918 else if(boxpoint != srcv && g_list_find(data->srcvertices, boxpoint)) 04919 restartv = boxpoint; 04920 } 04921 04922 if(!list->prev) { 04923 if(vertex_bbox(tedge_v1(tv->routingedge))) 04924 boxpoint = TOPOROUTER_VERTEX(vertex_bbox(tedge_v1(tv->routingedge))->point); 04925 else 04926 boxpoint = NULL; 04927 04928 if(tedge_v1(tv->routingedge) != srcv && g_list_find(data->srcvertices, tedge_v1(tv->routingedge))) 04929 restartv = tedge_v1(tv->routingedge); 04930 else if(boxpoint != srcv && g_list_find(data->srcvertices, boxpoint)) 04931 restartv = boxpoint; 04932 04933 } 04934 04935 if(restartv) { 04936 clean_routing_edges(r, data); 04937 gts_eheap_destroy(openlist); 04938 g_list_free(closelist); 04939 openlist = gts_eheap_new(route_heap_cmp, NULL); 04940 closelist = NULL; 04941 g_list_free(data->path); 04942 printf("ROUTING RESTARTING with new src %f,%f,%f\n", vx(restartv), vy(restartv), vz(restartv)); 04943 curpoint = restartv; 04944 goto route_begin; 04945 } 04946 } 04947 04948 i = i->next; 04949 } 04950 }*/ 04952 { 04953 toporouter_vertex_t *pv = NULL; 04954 GList *i = data->path; 04955 while(i) { 04956 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 04957 04958 if(pv && g_list_find(data->srcvertices, tv)) { 04959 GList *temp = g_list_copy(i); 04960 g_list_free(data->path); 04961 data->path = temp; 04962 i = data->path; 04963 } 04964 pv = tv; 04965 i = i->next; 04966 } 04967 } 04968 //*/ 04969 { 04970 toporouter_vertex_t *pv = NULL; 04971 GList *i = data->path; 04972 while(i) { 04973 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 04974 if(tv->flags & VERTEX_FLAG_TEMP) { 04975 tv->flags ^= VERTEX_FLAG_TEMP; 04976 tv->flags |= VERTEX_FLAG_ROUTE; 04977 } 04978 if(pv) pv->child = tv; 04979 04980 if(tv->routingedge) tv->route = data; 04981 04982 // if(tv->routingedge && !TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) space_edge(tv->routingedge, NULL); 04983 04984 pv = tv; 04985 i = i->next; 04986 } 04987 } 04988 04989 { 04990 toporouter_vertex_t *pv = NULL, *v = NULL; 04991 04992 GList *i = data->path; 04993 while(i) { 04994 v = TOPOROUTER_VERTEX(i->data); 04995 04996 if(pv) { 04997 v->parent = pv; 04998 pv->child = v; 04999 }else{ 05000 v->parent = NULL; 05001 } 05002 05003 pv = v; 05004 i = i->next; 05005 } 05006 05007 if(v) v->child = NULL; 05008 } 05009 05010 clean_routing_edges(r, data); 05011 // /* 05012 { 05013 GList *i = data->path; 05014 while(i) { 05015 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 05016 05017 if(v->routingedge && !TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 05018 space_edge(v->routingedge, NULL); 05019 i = i->next; 05020 } 05021 } 05022 // */ 05023 routing_return: 05024 05025 g_list_free(data->destvertices); 05026 g_list_free(data->srcvertices); 05027 data->destvertices = NULL; 05028 data->srcvertices = NULL; 05029 gts_eheap_destroy(openlist); 05030 g_list_free(closelist); 05031 05032 data->alltemppoints = NULL; 05033 05034 return rval; 05035 } 05036 05037 /* moves vertex v d units in the direction of vertex p */ 05038 void 05039 vertex_move_towards_vertex (GtsVertex *v, 05040 GtsVertex *p, 05041 double d) 05042 { 05043 double theta = atan2 (GTS_POINT(p)->y - GTS_POINT(v)->y, 05044 GTS_POINT(p)->x - GTS_POINT(v)->x); 05045 05046 GTS_POINT(v)->x += d * cos (theta); 05047 GTS_POINT(v)->y += d * sin (theta); 05048 } 05049 05050 05051 gdouble 05052 pathvertex_arcing_through_constraint(toporouter_vertex_t *pathv, toporouter_vertex_t *arcv) 05053 { 05054 toporouter_vertex_t *v = pathv->child; 05055 05056 if(!v || !v->routingedge) return 0.; 05057 05058 while(v->flags & VERTEX_FLAG_ROUTE && (tedge_v1(v->routingedge) == arcv || tedge_v2(v->routingedge) == arcv)) { 05059 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 05060 return gts_point_distance(GTS_POINT(tedge_v1(v->routingedge)), GTS_POINT(tedge_v2(v->routingedge))); 05061 v = v->child; 05062 } 05063 05064 v = pathv->parent; 05065 while(v->flags & VERTEX_FLAG_ROUTE && (tedge_v1(v->routingedge) == arcv || tedge_v2(v->routingedge) == arcv)) { 05066 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 05067 return gts_point_distance(GTS_POINT(tedge_v1(v->routingedge)), GTS_POINT(tedge_v2(v->routingedge))); 05068 v = v->parent; 05069 } 05070 05071 return 0.; 05072 } 05073 05074 gint 05075 vertices_connected(toporouter_vertex_t *a, toporouter_vertex_t *b) 05076 { 05077 return ((a->route->netlist == b->route->netlist && a->route->src->c == b->route->src->c) ? 1 : 0); 05078 } 05079 05080 gdouble 05081 edge_min_spacing(GList *list, toporouter_edge_t *e, toporouter_vertex_t *v, guint debug) 05082 { 05083 toporouter_vertex_t *origin; 05084 GList *i = list; 05085 gdouble space = 0.; 05086 toporouter_vertex_t *nextv, *prevv; 05087 //toporouter_vertex_t *edgev; 05088 //gdouble constraint_spacing; 05089 05090 if(!list) return INFINITY; 05091 05092 // printf("\t CMS %f,%f - %f,%f\n", vx(tedge_v1(e)), vy(tedge_v1(e)), vx(tedge_v2(e)), vy(tedge_v2(e))); 05093 05094 prevv = origin = TOPOROUTER_VERTEX(list->data); 05095 05096 // print_edge(e); 05097 05098 i = list; 05099 if(gts_point_distance2(GTS_POINT(origin), GTS_POINT(edge_v1(e))) < gts_point_distance2(GTS_POINT(v), GTS_POINT(edge_v1(e)))) { 05100 05101 /* towards v2 */ 05102 while(i) { 05103 nextv = edge_routing_next(e, i); 05104 if(nextv->route && vertices_connected(nextv, prevv)) { i = i->next; continue; } 05105 if(!(nextv->flags & VERTEX_FLAG_TEMP)) { 05106 gdouble ms = min_spacing(prevv, nextv); 05107 if(nextv == tedge_v2(e)) { 05108 gdouble cms = pathvertex_arcing_through_constraint(TOPOROUTER_VERTEX(i->data), tedge_v2(e)); 05109 // printf("\t CMS to %f,%f = %f \t ms = %f\n", vx(tedge_v2(e)), vy(tedge_v2(e)), cms, ms); 05110 // if(vx(tedge_v2(e)) > -EPSILON && vx(tedge_v2(e)) < EPSILON) { 05111 // printf("\t\tPROB: "); 05112 // print_vertex(tedge_v2(e)); 05113 // } 05114 if(cms > EPSILON) space += MIN(ms, cms / 2.); 05115 else space += ms; 05116 } else 05117 space += ms; 05118 05119 prevv = nextv; 05120 } 05121 // printf("%f ", space); 05122 i = i->next; 05123 } 05124 }else{ 05125 05126 /* towards v1 */ 05127 while(i) { 05128 nextv = edge_routing_prev(e, i); 05129 if(nextv->route && vertices_connected(nextv, prevv)) { i = i->prev; continue; } 05130 if(!(nextv->flags & VERTEX_FLAG_TEMP)) { 05131 gdouble ms = min_spacing(prevv, nextv); 05132 if(nextv == tedge_v1(e)) { 05133 gdouble cms = pathvertex_arcing_through_constraint(TOPOROUTER_VERTEX(i->data), tedge_v1(e)); 05134 // printf("\t CMS to %f,%f = %f \t ms = %f\n", vx(tedge_v1(e)), vy(tedge_v1(e)), cms, ms); 05135 // if(vx(tedge_v1(e)) > -EPSILON && vx(tedge_v1(e)) < EPSILON) { 05136 // printf("\t\tPROB: "); 05137 // print_vertex(tedge_v1(e)); 05138 // } 05139 if(cms > EPSILON) space += MIN(ms, cms / 2.); 05140 else space += ms; 05141 } else 05142 space += ms; 05143 05144 prevv = nextv; 05145 } 05146 // printf("%f ", space); 05147 i = i->prev; 05148 } 05149 } 05150 05151 if(TOPOROUTER_IS_CONSTRAINT(e) && space > gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) / 2.) 05152 space = gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) / 2.; 05153 05154 // if(debug) printf("\tedge_min_spacing: %f\n", space); 05155 return space; 05156 } 05157 05158 /* line segment is 1 & 2, point is 3 05159 returns 0 if v3 is outside seg 05160 */ 05161 guint 05162 vertex_line_normal_intersection(gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble x3, gdouble y3, gdouble *x, gdouble *y) 05163 { 05164 gdouble m1 = cartesian_gradient(x1,y1,x2,y2); 05165 gdouble m2 = perpendicular_gradient(m1); 05166 gdouble c2 = (isinf(m2)) ? x3 : y3 - (m2 * x3); 05167 gdouble c1 = (isinf(m1)) ? x1 : y1 - (m1 * x1); 05168 05169 if(isinf(m2)) 05170 *x = x3; 05171 else if(isinf(m1)) 05172 *x = x1; 05173 else 05174 *x = (c2 - c1) / (m1 - m2); 05175 05176 *y = (isinf(m2)) ? y1 : (m2 * (*x)) + c2; 05177 05178 if(*x >= MIN(x1,x2) - EPSILON && *x <= MAX(x1,x2) + EPSILON && *y >= MIN(y1,y2) - EPSILON && *y <= MAX(y1,y2) + EPSILON) 05179 return 1; 05180 return 0; 05181 } 05182 05183 void 05184 print_toporouter_arc(toporouter_arc_t *arc) 05185 { 05186 // GList *i = arc->vs; 05187 05188 printf("ARC CENTRE: %f,%f ", vx(arc->centre), vy(arc->centre));// print_vertex(arc->centre); 05189 printf("RADIUS: %f", arc->r); 05190 05191 if(arc->dir>0) printf(" COUNTERCLOCKWISE "); 05192 else if(arc->dir<0) printf(" CLOCKWISE "); 05193 else printf(" COLINEAR(ERROR) "); 05194 /* 05195 printf("\n\tVS: "); 05196 05197 while(i) { 05198 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 05199 printf("%f,%f ", vx(v), vy(v)); 05200 05201 i = i->next; 05202 } 05203 */ 05204 } 05205 05206 void 05207 toporouter_arc_remove(toporouter_oproute_t *oproute, toporouter_arc_t *arc) 05208 { 05209 oproute->arcs = g_list_remove(oproute->arcs, arc); 05210 05211 if(arc->v) arc->v->arc = NULL; 05212 } 05213 05214 toporouter_arc_t * 05215 toporouter_arc_new(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_vertex_t *centre, gdouble r, gint dir) 05216 { 05217 toporouter_arc_t *arc = TOPOROUTER_ARC(gts_object_new(GTS_OBJECT_CLASS(toporouter_arc_class()))); 05218 arc->centre = centre; 05219 arc->v = v1; 05220 arc->v1 = v1; 05221 arc->v2 = v2; 05222 arc->r = r; 05223 arc->dir = dir; 05224 05225 if(v1) v1->arc = arc; 05226 arc->oproute = oproute; 05227 05228 arc->clearance = NULL; 05229 05230 return arc; 05231 } 05232 05233 void 05234 path_set_oproute(GList *path, toporouter_oproute_t *oproute) 05235 { 05236 while(path) { 05237 toporouter_vertex_t *v = TOPOROUTER_VERTEX(path->data); 05238 05239 if(v->flags & VERTEX_FLAG_ROUTE) 05240 v->oproute = oproute; 05241 05242 path = path->next; 05243 } 05244 } 05245 05246 void 05247 print_oproute(toporouter_oproute_t *oproute) 05248 { 05249 GList *i = oproute->arcs; 05250 05251 printf("Optimized Route:\n"); 05252 printf("\tNetlist:\t\t%s\n\tStyle:\t\t%s\n", oproute->netlist, oproute->style); 05253 // printf("%s\n", oproute->netlist); 05254 /* 05255 i = oproute->term1->zlink; 05256 while(i) { 05257 toporouter_vertex_t *thisv = TOPOROUTER_VERTEX(i->data); 05258 printf("\tNetlist:\t\t%s\n\tStyle:\t\t%s\n", vertex_bbox(thisv)->netlist, vertex_bbox(thisv)->style); 05259 i = i->next; 05260 } 05261 */ 05262 printf("\t"); print_vertex(oproute->term1); printf("\n"); 05263 i = oproute->arcs; 05264 while(i) { 05265 toporouter_arc_t *arc = (toporouter_arc_t *)i->data; 05266 printf("\t"); print_toporouter_arc(arc); printf("\n"); 05267 i = i->next; 05268 } 05269 printf("\t"); print_vertex(oproute->term2); printf("\n"); 05270 } 05271 05272 gdouble 05273 export_pcb_drawline(guint layer, guint x0, guint y0, guint x1, guint y1, guint thickness, guint keepaway) 05274 { 05275 gdouble d = 0.; 05276 LineType *line; 05277 line = CreateDrawnLineOnLayer( LAYER_PTR(layer), x0, y0, x1, y1, 05278 thickness, keepaway, 05279 MakeFlags (AUTOFLAG | (TEST_FLAG (CLEARNEWFLAG, PCB) ? CLEARLINEFLAG : 0))); 05280 05281 if(line) { 05282 AddObjectToCreateUndoList (LINE_TYPE, LAYER_PTR(layer), line, line); 05283 d = hypot(x0 - x1, y0 - y1); 05284 } 05285 return d; 05286 } 05287 05288 gdouble 05289 arc_angle(toporouter_arc_t *arc) 05290 { 05291 gdouble x0, x1, y0, y1; 05292 05293 x0 = arc->x0 - vx(arc->centre); 05294 x1 = arc->x1 - vx(arc->centre); 05295 y0 = arc->y0 - vy(arc->centre); 05296 y1 = arc->y1 - vy(arc->centre); 05297 05298 return fabs(acos(((x0*x1)+(y0*y1))/(hypot(x0,y0)*hypot(x1,y1)))); 05299 } 05300 05301 gdouble 05302 export_pcb_drawarc(guint layer, toporouter_arc_t *a, guint thickness, guint keepaway) 05303 { 05304 gdouble sa, da, theta; 05305 gdouble d = 0.; 05306 ArcType *arc; 05307 gint wind; 05308 05309 wind = coord_wind(a->x0, a->y0, a->x1, a->y1, vx(a->centre), vy(a->centre)); 05310 05311 /* NB: PCB's arcs have a funny coorindate system, with 0 degrees as the -ve X axis (left), 05312 * continuing clockwise, with +90 degrees being along the +ve Y axis (bottom). Because 05313 * Y+ points down, our internal angles increase clockwise from the +ve X axis. 05314 */ 05315 sa = (M_PI - coord_angle (vx (a->centre), vy (a->centre), a->x0, a->y0)) * 180. / M_PI; 05316 05317 theta = arc_angle(a); 05318 05319 if(!a->dir || !wind) return 0.; 05320 05321 if(a->dir != wind) theta = 2. * M_PI - theta; 05322 05323 da = -a->dir * theta * 180. / M_PI; 05324 05325 if(da < 1. && da > -1.) return 0.; 05326 if(da > 359. || da < -359.) return 0.; 05327 05328 arc = CreateNewArcOnLayer(LAYER_PTR(layer), vx(a->centre), vy(a->centre), a->r, a->r, 05329 sa, da, thickness, keepaway, 05330 MakeFlags( AUTOFLAG | (TEST_FLAG (CLEARNEWFLAG, PCB) ? CLEARLINEFLAG : 0))); 05331 05332 if(arc) { 05333 AddObjectToCreateUndoList( ARC_TYPE, LAYER_PTR(layer), arc, arc); 05334 d = a->r * theta; 05335 } 05336 05337 return d; 05338 } 05339 05340 void 05341 calculate_term_to_arc(toporouter_vertex_t *v, toporouter_arc_t *arc, guint dir) 05342 { 05343 gdouble theta, a, b, bx, by, a0x, a0y, a1x, a1y; 05344 gint winddir; 05345 05346 theta = acos(arc->r / gts_point_distance(GTS_POINT(v), GTS_POINT(arc->centre))); 05347 a = arc->r * sin(theta); 05348 b = arc->r * cos(theta); 05349 #ifdef DEBUG_EXPORT 05350 printf("drawing arc with r %f theta %f d %f centre = %f,%f\n", arc->r, theta, gts_point_distance(GTS_POINT(v), GTS_POINT(arc->centre)), vx(arc->centre), vy(arc->centre)); 05351 #endif 05352 point_from_point_to_point(arc->centre, v, b, &bx, &by); 05353 05354 coords_on_line(bx, by, perpendicular_gradient(point_gradient(GTS_POINT(v), GTS_POINT(arc->centre))), a, &a0x, &a0y, &a1x, &a1y); 05355 05356 winddir = coord_wind(vx(v), vy(v), a0x, a0y, vx(arc->centre), vy(arc->centre)); 05357 05358 if(!winddir) { 05359 printf("!winddir @ v %f,%f arc->centre %f,%f\n", vx(v), vy(v), vx(arc->centre), vy(arc->centre)); 05360 //TODO: fix hack: this shouldn't happen 05361 arc->x0 = vx(v); 05362 arc->y0 = vy(v); 05363 arc->x1 = vx(v); 05364 arc->y1 = vy(v); 05365 return; 05366 } 05367 05368 g_assert(winddir); 05369 05370 if(dir) winddir = -winddir; 05371 05372 if(winddir == arc->dir) { 05373 if(!dir) { arc->x0 = a0x; arc->y0 = a0y; } 05374 else{ arc->x1 = a0x; arc->y1 = a0y; } 05375 }else{ 05376 if(!dir) { arc->x0 = a1x; arc->y0 = a1y; } 05377 else{ arc->x1 = a1x; arc->y1 = a1y; } 05378 } 05379 05380 } 05381 05382 05383 05390 void 05391 arc_ortho_projections(toporouter_arc_t *arc, toporouter_arc_t *narc, gdouble *b1, gdouble *b2) 05392 { 05393 gdouble nax, nay, ax, ay, alen, c; 05394 gdouble b1x, b1y, b2x, b2y; 05395 05396 #ifdef DEBUG_EXPORT 05397 printf("arc c = %f,%f narc c = %f,%f arc->0 = %f,%f\n", 05398 vx(arc->centre), vy(arc->centre), 05399 vx(narc->centre), vy(narc->centre), 05400 arc->x0, arc->y0); 05401 #endif 05402 05403 nax = vx(narc->centre) - vx(arc->centre); 05404 nay = vy(narc->centre) - vy(arc->centre); 05405 alen = hypot(nax, nay); 05406 05407 05408 ax = arc->x0 - vx(arc->centre); 05409 ay = arc->y0 - vy(arc->centre); 05410 05411 #ifdef DEBUG_EXPORT 05412 printf("norm narc = %f,%f - %f\tA=%f,%f\n", nax, nay, alen, ax, ay); 05413 #endif 05414 05415 c = ((ax*nax)+(ay*nay)) / (alen*alen); 05416 05417 b1x = c * nax; 05418 b1y = c * nay; 05419 b2x = ax - b1x; 05420 b2y = ay - b1y; 05421 05422 #ifdef DEBUG_EXPORT 05423 printf("proj = %f,%f perp proj = %f,%f\n", b1x, b1y, b2x, b2y); 05424 #endif 05425 05426 *b1 = hypot(b1x,b1y); 05427 *b2 = hypot(b2x,b2y); 05428 05429 } 05430 05431 guint 05432 calculate_arc_to_arc(toporouter_t *ar, toporouter_arc_t *parc, toporouter_arc_t *arc) 05433 { 05434 gdouble theta, a, b, bx, by, a0x, a0y, a1x, a1y, m, preva, prevb; 05435 gint winddir; 05436 toporouter_arc_t *bigr, *smallr; 05437 05438 if(parc->r > arc->r) { 05439 bigr = parc; smallr = arc; 05440 }else{ 05441 bigr = arc; smallr = parc; 05442 } 05443 #ifdef DEBUG_EXPORT 05444 printf("bigr centre = %f,%f smallr centre = %f,%f\n", vx(bigr->centre), vy(bigr->centre), 05445 vx(smallr->centre), vy(smallr->centre)); 05446 #endif 05447 05448 m = perpendicular_gradient(point_gradient(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre))); 05449 05450 if(bigr->centre == smallr->centre) { 05451 05452 printf("bigr->centre == smallr->centre @ %f,%f\n", vx(smallr->centre), vy(smallr->centre)); 05453 } 05454 05455 g_assert(bigr->centre != smallr->centre); 05456 05457 if(parc->dir == arc->dir) { 05458 //export_arc_straight: 05459 05460 theta = acos((bigr->r - smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre))); 05461 a = bigr->r * sin(theta); 05462 b = bigr->r * cos(theta); 05463 05464 point_from_point_to_point(bigr->centre, smallr->centre, b, &bx, &by); 05465 05466 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y); 05467 05468 winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre)); 05469 05470 arc_ortho_projections(parc, arc, &prevb, &preva); 05471 //#ifdef DEBUG_EXPORT 05472 if(!winddir) { 05473 05474 printf("STRAIGHT:\n"); 05475 printf("bigr centre = %f,%f smallr centre = %f,%f\n", vx(bigr->centre), vy(bigr->centre), 05476 vx(smallr->centre), vy(smallr->centre)); 05477 printf("theta = %f a = %f b = %f bigrr = %f d = %f po = %f\n", theta, a, b, bigr->r, 05478 gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)), 05479 bigr->r / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre))); 05480 printf("bigr-r = %f smallr-r = %f ratio = %f\n", 05481 bigr->r, smallr->r, (bigr->r - smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre))); 05482 printf("preva = %f prevb = %f\n\n", preva, prevb); 05483 05484 } 05485 //#endif 05486 g_assert(winddir); 05487 05488 if(bigr==parc) winddir = -winddir; 05489 05490 if(winddir == bigr->dir) { 05491 if(bigr==arc) { 05492 bigr->x0 = a0x; 05493 bigr->y0 = a0y; 05494 }else{ 05495 bigr->x1 = a0x; 05496 bigr->y1 = a0y; 05497 } 05498 }else{ 05499 if(bigr==arc) { 05500 bigr->x0 = a1x; 05501 bigr->y0 = a1y; 05502 }else{ 05503 bigr->x1 = a1x; 05504 bigr->y1 = a1y; 05505 } 05506 } 05507 05508 a = smallr->r * sin(theta); 05509 b = smallr->r * cos(theta); 05510 05511 #ifdef DEBUG_EXPORT 05512 printf("a = %f b = %f\n", a, b); 05513 #endif 05514 point_from_point_to_point(smallr->centre, bigr->centre, -b, &bx, &by); 05515 05516 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y); 05517 05518 if(winddir == bigr->dir) { 05519 if(bigr==arc) { 05520 smallr->x1 = a0x; 05521 smallr->y1 = a0y; 05522 }else{ 05523 smallr->x0 = a0x; 05524 smallr->y0 = a0y; 05525 } 05526 }else{ 05527 if(bigr==arc) { 05528 smallr->x1 = a1x; 05529 smallr->y1 = a1y; 05530 }else{ 05531 smallr->x0 = a1x; 05532 smallr->y0 = a1y; 05533 } 05534 } 05535 05536 }else{ 05537 05538 //export_arc_twist: 05539 05540 theta = acos((bigr->r + smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre))); 05541 a = bigr->r * sin(theta); 05542 b = bigr->r * cos(theta); 05543 05544 point_from_point_to_point(bigr->centre, smallr->centre, b, &bx, &by); 05545 05546 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y); 05547 05548 winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre)); 05549 //#ifdef DEBUG_EXPORT 05550 if(!winddir) { 05551 printf("TWIST:\n"); 05552 printf("theta = %f a = %f b = %f r = %f d = %f po = %f\n", theta, a, b, bigr->r + smallr->r, 05553 gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre)), 05554 (bigr->r+smallr->r) / gts_point_distance(GTS_POINT(bigr->centre), GTS_POINT(smallr->centre))); 05555 05556 printf("bigr centre = %f,%f smallr centre = %f,%f\n\n", vx(bigr->centre), vy(bigr->centre), 05557 vx(smallr->centre), vy(smallr->centre)); 05558 05559 printf("big wind = %d small wind = %d\n", bigr->dir, smallr->dir); 05560 return 1; 05561 } 05562 //#endif 05563 /* if(!winddir) { 05564 smallr->centre->flags |= VERTEX_FLAG_RED; 05565 bigr->centre->flags |= VERTEX_FLAG_GREEN; 05566 //bigr->centre->flags |= VERTEX_FLAG_RED; 05567 { 05568 int i; 05569 for(i=0;i<groupcount();i++) { 05570 char buffer[256]; 05571 sprintf(buffer, "wind%d.png", i); 05572 toporouter_draw_surface(ar, ar->layers[i].surface, buffer, 2096, 2096, 2, NULL, i, NULL); 05573 } 05574 } 05575 return; 05576 } 05577 */ 05578 g_assert(winddir); 05579 05580 if(bigr==parc) winddir = -winddir; 05581 05582 if(winddir == bigr->dir) { 05583 if(bigr==arc) { 05584 bigr->x0 = a0x; 05585 bigr->y0 = a0y; 05586 }else{ 05587 bigr->x1 = a0x; 05588 bigr->y1 = a0y; 05589 } 05590 }else{ 05591 if(bigr==arc) { 05592 bigr->x0 = a1x; 05593 bigr->y0 = a1y; 05594 }else{ 05595 bigr->x1 = a1x; 05596 bigr->y1 = a1y; 05597 } 05598 } 05599 05600 a = smallr->r * sin(theta); 05601 b = smallr->r * cos(theta); 05602 05603 point_from_point_to_point(smallr->centre, bigr->centre, b, &bx, &by); 05604 05605 coords_on_line(bx, by, m, a, &a0x, &a0y, &a1x, &a1y); 05606 05607 winddir = coord_wind(vx(smallr->centre), vy(smallr->centre), a0x, a0y, vx(bigr->centre), vy(bigr->centre)); 05608 05609 g_assert(winddir); 05610 05611 if(bigr==parc) winddir = -winddir; 05612 05613 if(winddir == smallr->dir) { 05614 if(bigr==arc) { 05615 smallr->x1 = a0x; 05616 smallr->y1 = a0y; 05617 }else{ 05618 smallr->x0 = a0x; 05619 smallr->y0 = a0y; 05620 } 05621 }else{ 05622 if(bigr==arc) { 05623 smallr->x1 = a1x; 05624 smallr->y1 = a1y; 05625 }else{ 05626 smallr->x0 = a1x; 05627 smallr->y0 = a1y; 05628 } 05629 } 05630 05631 } 05632 05633 return 0; 05634 } 05635 05636 void 05637 export_oproutes(toporouter_t *ar, toporouter_oproute_t *oproute) 05638 { 05639 guint layer = PCB->LayerGroups.Entries[oproute->layergroup][0]; 05640 guint thickness = lookup_thickness(oproute->style); 05641 guint keepaway = lookup_keepaway(oproute->style); 05642 GList *arcs = oproute->arcs; 05643 toporouter_arc_t *arc, *parc = NULL; 05644 05645 if(!arcs) { 05646 ar->wiring_score += export_pcb_drawline(layer, vx(oproute->term1), vy(oproute->term1), vx(oproute->term2), vy(oproute->term2), thickness, keepaway); 05647 return; 05648 } 05649 05650 05651 // calculate_term_to_arc(oproute->term1, TOPOROUTER_ARC(arcs->data), 0, layer); 05652 05653 while(arcs) { 05654 arc = TOPOROUTER_ARC(arcs->data); 05655 05656 if(parc && arc) { 05657 ar->wiring_score += export_pcb_drawarc(layer, parc, thickness, keepaway); 05658 ar->wiring_score += export_pcb_drawline(layer, parc->x1, parc->y1, arc->x0, arc->y0, thickness, keepaway); 05659 }else if(!parc) { 05660 ar->wiring_score += export_pcb_drawline(layer, vx(oproute->term1), vy(oproute->term1), arc->x0, arc->y0, thickness, keepaway); 05661 } 05662 05663 parc = arc; 05664 arcs = arcs->next; 05665 } 05666 ar->wiring_score += export_pcb_drawarc(layer, arc, thickness, keepaway); 05667 ar->wiring_score += export_pcb_drawline(layer, arc->x1, arc->y1, vx(oproute->term2), vy(oproute->term2), thickness, keepaway); 05668 05669 } 05670 05671 05672 05673 void 05674 oproute_free(toporouter_oproute_t *oproute) 05675 { 05676 GList *i = oproute->arcs; 05677 while(i) { 05678 toporouter_arc_t *arc = (toporouter_arc_t *) i->data; 05679 if(arc->centre->flags & VERTEX_FLAG_TEMP) 05680 gts_object_destroy(GTS_OBJECT(arc->centre)); 05681 05682 i = i->next; 05683 } 05684 05685 g_list_free(oproute->arcs); 05686 free(oproute); 05687 } 05688 05689 void 05690 oproute_calculate_tof(toporouter_oproute_t *oproute) 05691 { 05692 GList *arcs = oproute->arcs; 05693 toporouter_arc_t *parc = NULL, *arc; 05694 05695 oproute->tof = 0.; 05696 05697 if(!arcs) { 05698 oproute->tof = gts_point_distance(GTS_POINT(oproute->term1), GTS_POINT(oproute->term2)); 05699 return; 05700 } 05701 05702 while(arcs) { 05703 arc = TOPOROUTER_ARC(arcs->data); 05704 05705 if(parc && arc) { 05706 oproute->tof += arc_angle(parc) * parc->r; 05707 oproute->tof += hypot(parc->x1-arc->x0,parc->y1-arc->y0); 05708 }else if(!parc) { 05709 oproute->tof += hypot(arc->x0-vx(oproute->term1), arc->y0-vy(oproute->term1)); 05710 } 05711 05712 parc = arc; 05713 arcs = arcs->next; 05714 } 05715 05716 oproute->tof += arc_angle(parc) * parc->r; 05717 oproute->tof += hypot(arc->x1-vx(oproute->term2), arc->y1-vy(oproute->term2)); 05718 05719 } 05720 05721 gdouble 05722 line_line_distance_at_normal( 05723 gdouble line1_x1, gdouble line1_y1, 05724 gdouble line1_x2, gdouble line1_y2, 05725 gdouble line2_x1, gdouble line2_y1, 05726 gdouble line2_x2, gdouble line2_y2, 05727 gdouble x, gdouble y) 05728 { 05729 gdouble m1 = perpendicular_gradient(cartesian_gradient(line1_x1, line1_y1, line1_x2, line1_y2)); 05730 gdouble m2 = cartesian_gradient(line2_x1, line2_y1, line2_x2, line2_y2); 05731 gdouble c1 = (isinf(m1)) ? x : y - (m1 * x); 05732 gdouble c2 = (isinf(m2)) ? line2_x1 : line2_y1 - (m2 * line2_x1); 05733 05734 gdouble intx, inty; 05735 05736 if(isinf(m2)) intx = line2_x1; 05737 else if(isinf(m1)) intx = x; 05738 else intx = (c2 - c1) / (m1 - m2); 05739 05740 inty = (isinf(m2)) ? (m1 * intx) + c1 : (m2 * intx) + c2; 05741 05742 return hypot(x-intx,y-inty); 05743 } 05744 05745 void 05746 calculate_serpintine(gdouble delta, gdouble r, gdouble initiala, gdouble *a, guint *nhalfcycles) 05747 { 05748 gdouble lhalfcycle = 2.*(initiala-r)+(M_PI*r); 05749 guint n; 05750 05751 printf("lhalfcycle = %f r = %f\n", lhalfcycle, r); 05752 05753 n = (delta - M_PI*r) / (lhalfcycle - 2.*r) + 1; 05754 *a = (delta + 4.*n*r - n*M_PI*r + 4.*r - M_PI*r)/(2.*n); 05755 *nhalfcycles = n; 05756 } 05757 05758 gdouble 05759 oproute_min_spacing(toporouter_oproute_t *a, toporouter_oproute_t *b) 05760 { 05761 return lookup_thickness(a->style) / 2. + lookup_thickness(b->style) / 2. + MAX(lookup_keepaway(a->style), lookup_keepaway(b->style)); 05762 } 05763 05764 gdouble 05765 vector_angle(gdouble ox, gdouble oy, gdouble ax, gdouble ay, gdouble bx, gdouble by) 05766 { 05767 gdouble alen = hypot(ax-ox,ay-oy); 05768 gdouble blen = hypot(bx-ox,by-oy); 05769 return acos( ((ax-ox)*(bx-ox)+(ay-oy)*(by-oy)) / (alen * blen) ); 05770 } 05771 05772 toporouter_serpintine_t * 05773 toporouter_serpintine_new(gdouble x, gdouble y, gdouble x0, gdouble y0, gdouble x1, gdouble y1, gpointer start, gdouble halfa, gdouble 05774 radius, guint nhalfcycles) 05775 { 05776 toporouter_serpintine_t *serp = (toporouter_serpintine_t *)malloc(sizeof(toporouter_serpintine_t)); 05777 serp->x = x; 05778 serp->y = y; 05779 serp->x0 = x0; 05780 serp->y0 = y0; 05781 serp->x1 = x1; 05782 serp->y1 = y1; 05783 serp->start = start; 05784 serp->halfa = halfa; 05785 serp->radius = radius; 05786 serp->nhalfcycles = nhalfcycles; 05787 serp->arcs = NULL; 05788 return serp; 05789 } 05790 05791 //#define DEBUG_RUBBERBAND 1 05792 05793 gdouble 05794 check_non_intersect_vertex(gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *pathv, toporouter_vertex_t *arcv, 05795 toporouter_vertex_t *opv, gint wind, gint *arcwind, gdouble *arcr, guint debug) 05796 { 05797 gdouble ms, line_int_x, line_int_y, x, y, d = 0., m; 05798 gdouble tx0, ty0, tx1, ty1; 05799 gint wind1, wind2; 05800 05801 g_assert(pathv->routingedge); 05802 05803 if(TOPOROUTER_IS_CONSTRAINT(pathv->routingedge)) { 05804 gdouble d = tvdistance(tedge_v1(pathv->routingedge), tedge_v2(pathv->routingedge)) / 2.; 05805 ms = min_spacing(pathv, arcv); 05806 if(ms > d) ms = d; 05807 }else{ 05808 ms = edge_min_spacing(g_list_find(edge_routing(pathv->routingedge), pathv), pathv->routingedge, arcv, debug); 05809 } 05810 05811 05812 if(!vertex_line_normal_intersection(x0, y0, x1, y1, vx(arcv), vy(arcv), &line_int_x, &line_int_y)) { 05813 05814 if(hypot(x0 - line_int_x, y0 - line_int_y) < hypot(x1 - line_int_x, y1 - line_int_y)) 05815 { line_int_x = x0; line_int_y = y0; }else{ line_int_x = x1; line_int_y = y1; } 05816 05817 m = perpendicular_gradient(cartesian_gradient(vx(arcv), vy(arcv), line_int_x, line_int_y)); 05818 }else{ 05819 m = cartesian_gradient(x0, y0, x1, y1); 05820 } 05821 05822 coords_on_line(vx(arcv), vy(arcv), m, MIL_TO_COORD (1.), &tx0, &ty0, &tx1, &ty1); 05823 05824 wind1 = coord_wind(tx0, ty0, tx1, ty1, line_int_x, line_int_y); 05825 wind2 = coord_wind(tx0, ty0, tx1, ty1, vx(opv), vy(opv)); 05826 05827 if(!wind2 || wind1 == wind2) return -1.; 05828 05829 if(!wind) { 05830 coords_on_line(line_int_x, line_int_y, perpendicular_gradient(m), ms, &tx0, &ty0, &tx1, &ty1); 05831 if(hypot(tx0 - vx(opv), ty0 - vy(opv)) < hypot(tx1 - vx(opv), ty1 - vy(opv))) 05832 { x = tx0; y = ty0; }else{ x = tx1; y = ty1; } 05833 }else{ 05834 toporouter_vertex_t *parent = pathv->parent, *child = pathv->child; 05835 guint windtests = 0; 05836 05837 d = hypot(vx(arcv) - line_int_x, vy(arcv) - line_int_y); 05838 coord_move_towards_coord_values(line_int_x, line_int_y, vx(arcv), vy(arcv), ms + d, &x, &y); 05839 rewind_test: 05840 wind1 = coord_wind(line_int_x, line_int_y, x, y, vx(parent), vy(parent)); 05841 wind2 = coord_wind(line_int_x, line_int_y, x, y, vx(child), vy(child)); 05842 if(wind1 && wind2 && wind1 == wind2) { 05843 // return -1.; 05844 if(windtests++ == 2) return -1.; 05845 05846 if(parent->flags & VERTEX_FLAG_ROUTE) parent = parent->parent; 05847 if(child->flags & VERTEX_FLAG_ROUTE) child = child->child; 05848 goto rewind_test; 05849 } 05850 } 05851 05852 05853 *arcr = ms; 05854 *arcwind = tvertex_wind(pathv->parent, pathv, arcv); 05855 05856 #ifdef DEBUG_RUBBERBAND 05857 //if(debug) 05858 // printf("non-int check %f,%f ms %f d %f arcv %f,%f opv %f,%f\n", vx(arcv), vy(arcv), ms, d + ms, 05859 // vx(arcv), vy(arcv), vx(opv), vy(opv)); 05860 #endif 05861 05862 return d + ms; 05863 } 05864 05865 gdouble 05866 check_intersect_vertex(gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *pathv, toporouter_vertex_t *arcv, 05867 toporouter_vertex_t *opv, gint wind, gint *arcwind, gdouble *arcr, guint debug) 05868 { 05869 gdouble ms, line_int_x, line_int_y, x, y, d = 0.; 05870 05871 if(TOPOROUTER_IS_CONSTRAINT(pathv->routingedge)) { 05872 gdouble d = tvdistance(tedge_v1(pathv->routingedge), tedge_v2(pathv->routingedge)) / 2.; 05873 ms = min_spacing(pathv, arcv); 05874 if(ms > d) ms = d; 05875 }else { 05876 ms = edge_min_spacing(g_list_find(edge_routing(pathv->routingedge), pathv), pathv->routingedge, arcv, debug); 05877 } 05878 05879 if(!vertex_line_normal_intersection(x0, y0, x1, y1, vx(arcv), vy(arcv), &line_int_x, &line_int_y)) 05880 return -1.; 05881 05882 d = hypot(line_int_x - vx(arcv), line_int_y - vy(arcv)); 05883 05884 05885 if(d > ms - EPSILON) 05886 return -1.; 05887 05888 coord_move_towards_coord_values(vx(arcv), vy(arcv), line_int_x, line_int_y, ms, &x, &y); 05889 05890 *arcr = ms; 05891 *arcwind = tvertex_wind(pathv->parent, pathv, arcv); 05892 // *arcwind = coord_wind(x0, y0, x, y, x1, y1); 05893 #ifdef DEBUG_RUBBERBAND 05894 //if(debug) 05895 // printf("int check %f,%f ms %f d %f arcv %f,%f opv %f,%f\n", vx(arcv), vy(arcv), ms, ms - d, 05896 // vx(arcv), vy(arcv), vx(opv), vy(opv)); 05897 #endif 05898 05899 return ms - d; 05900 } 05901 05905 guint 05906 check_arc_for_loops(gpointer t1, toporouter_arc_t *arc, gpointer t2) 05907 { 05908 gdouble x0, y0, x1, y1; 05909 05910 if(TOPOROUTER_IS_VERTEX(t1)) { x0 = vx(TOPOROUTER_VERTEX(t1)); y0 = vy(TOPOROUTER_VERTEX(t1)); } 05911 else { x0 = TOPOROUTER_ARC(t1)->x1; y0 = TOPOROUTER_ARC(t1)->y1; } 05912 05913 if(TOPOROUTER_IS_VERTEX(t2)) { x1 = vx(TOPOROUTER_VERTEX(t2)); y1 = vy(TOPOROUTER_VERTEX(t2)); } 05914 else { x1 = TOPOROUTER_ARC(t2)->x0; y1 = TOPOROUTER_ARC(t2)->y0; } 05915 05916 if(coord_intersect_prop(x0, y0, arc->x0, arc->y0, arc->x1, arc->y1, x1, y1) ) { 05917 // || 05918 // (arc->x0 > arc->x1 - EPSILON && arc->x0 < arc->x1 + EPSILON && 05919 // arc->y0 > arc->y1 - EPSILON && arc->y0 < arc->y1 + EPSILON) 05920 // ) { 05921 #ifdef DEBUG_RUBBERBAND 05922 printf("LOOPS %f %f -> %f %f & %f %f -> %f %f\n", x0, y0, arc->x0, arc->y0, arc->x1, arc->y1, x1, y1); 05923 #endif 05924 return 1; 05925 } 05926 return 0; 05927 } 05928 05929 toporouter_rubberband_arc_t * 05930 new_rubberband_arc(toporouter_vertex_t *pathv, toporouter_vertex_t *arcv, gdouble r, gdouble d, gint wind, GList *list) 05931 { 05932 toporouter_rubberband_arc_t *rba = (toporouter_rubberband_arc_t *)malloc(sizeof(toporouter_rubberband_arc_t)); 05933 rba->pathv = pathv; 05934 rba->arcv = arcv; 05935 rba->r = r; 05936 rba->d = d; 05937 rba->wind = wind; 05938 rba->list = list; 05939 return rba; 05940 } 05941 05942 gint 05943 compare_rubberband_arcs(toporouter_rubberband_arc_t *a, toporouter_rubberband_arc_t *b) 05944 { return b->d - a->d; } 05945 05946 void 05947 free_list_elements(gpointer data, gpointer user_data) 05948 { free(data); } 05949 05950 05951 /* returns the edge opposite v from the triangle facing (x,y), or NULL if v is colinear with an edge between v and a neighbor */ 05952 /* 05953 GtsEdge * 05954 vertex_edge_facing_vertex(GtsVertex *v, gdouble x, gdouble y) 05955 { 05956 GSList *ts = gts_vertex_triangles(GTS_VERTEX(n), NULL); 05957 GSList *i = ts; 05958 05959 while(i) { 05960 GtsTriangle *t = GTS_TRIANGLE(i->data); 05961 GtsEdge *e = gts_triangle_edge_opposite(t, v); 05962 05963 if(coord_wind(vx(edge_v1(e)), vy(edge_v1(e)), vx(v), vy(v), x, y) == vertex_wind(edge_v1(e), v, edge_v2(e)) && 05964 coord_wind(vx(edge_v2(e)), vy(edge_v2(e)), vx(v), vy(v), x, y) == vertex_wind(edge_v2(e), v, edge_v1(e)) 05965 ) { 05966 g_slist_free(ts); 05967 return e; 05968 } 05969 05970 i = i->next; 05971 } 05972 05973 g_slist_free(ts); 05974 return NULL; 05975 } 05976 */ 05977 05978 gdouble 05979 check_adj_pushing_vertex(toporouter_oproute_t *oproute, gdouble x0, gdouble y0, gdouble x1, gdouble y1, toporouter_vertex_t *v, gdouble *arcr, gint *arcwind, toporouter_vertex_t **arc) 05980 { 05981 GSList *ns = gts_vertex_neighbors(GTS_VERTEX(v), NULL, NULL); 05982 GSList *i = ns; 05983 gdouble maxd = 0.; 05984 05985 while(i) { 05986 toporouter_vertex_t *n = TOPOROUTER_VERTEX(i->data); 05987 gdouble segintx, seginty; 05988 if(vertex_line_normal_intersection(x0, y0, x1, y1, vx(n), vy(n), &segintx, &seginty)) { 05989 toporouter_edge_t *e = tedge(n, v); 05990 gdouble ms = 0., d = hypot(segintx - vx(n), seginty - vy(n)); 05991 //toporouter_vertex_t *a; 05992 toporouter_vertex_t *b; 05993 GList *closestnet = NULL; 05994 05995 g_assert(e); 05996 05997 if(v == tedge_v1(e)) { 05998 //a = tedge_v1(e); 05999 b = tedge_v2(e); 06000 closestnet = edge_routing(e); 06001 }else{ 06002 //a = tedge_v2(e); 06003 b = tedge_v1(e); 06004 closestnet = g_list_last(edge_routing(e)); 06005 } 06006 06007 if(closestnet) { 06008 ms = edge_min_spacing(closestnet, e, b, 0); 06009 ms += min_oproute_net_spacing(oproute, TOPOROUTER_VERTEX(closestnet->data)); 06010 }else{ 06011 ms = min_oproute_vertex_spacing(oproute, b); 06012 } 06013 06014 if(ms - d > maxd) { 06015 *arcr = ms; 06016 *arc = n; 06017 maxd = ms - d; 06018 if(vx(v) == x0 && vy(v) == y0) { 06019 *arcwind = coord_wind(x0, y0, vx(n), vy(n), x1, y1); 06020 }else if(vx(v) == x1 && vy(v) == y1) { 06021 *arcwind = coord_wind(x1, y1, vx(n), vy(n), x0, y0); 06022 }else{ 06023 fprintf(stderr, "ERROR: check_adj_pushing_vertex encountered bad vertex v (coordinates don't match)\n"); 06024 } 06025 } 06026 } 06027 06028 i = i->next; 06029 } 06030 06031 g_slist_free(ns); 06032 return maxd; 06033 } 06034 06035 06041 GList * 06042 oproute_rubberband_segment(toporouter_t *r, toporouter_oproute_t *oproute, GList *path, gpointer t1, gpointer t2, guint debug) 06043 { 06044 gdouble x0, y0, x1, y1; 06045 toporouter_vertex_t *v1, *v2, *av1, *av2; /* v{1,2} are the vertex terminals of the segment, or arc terminal centres */ 06046 toporouter_arc_t *arc1 = NULL, *arc2 = NULL, *newarc = NULL; /* arc{1,2} are the arc terminals of the segment, if they exist */ 06047 GList *i = path; 06048 GList *list1, *list2; 06049 06050 GList *arcs = NULL; 06051 toporouter_rubberband_arc_t *max = NULL; 06052 06053 gdouble d, arcr; 06054 gint v1wind, v2wind, arcwind; 06055 06056 if(TOPOROUTER_IS_VERTEX(t1)) { 06057 v1 = TOPOROUTER_VERTEX(t1); 06058 x0 = vx(v1); y0 = vy(v1); 06059 }else{ 06060 g_assert(TOPOROUTER_IS_ARC(t1)); 06061 arc1 = TOPOROUTER_ARC(t1); 06062 v1 = TOPOROUTER_VERTEX(arc1->v1); 06063 x0 = arc1->x1; 06064 y0 = arc1->y1; 06065 } 06066 06067 if(TOPOROUTER_IS_VERTEX(t2)) { 06068 v2 = TOPOROUTER_VERTEX(t2); 06069 x1 = vx(v2); y1 = vy(v2); 06070 }else{ 06071 g_assert(TOPOROUTER_IS_ARC(t2)); 06072 arc2 = TOPOROUTER_ARC(t2); 06073 v2 = TOPOROUTER_VERTEX(arc2->v2); 06074 x1 = arc2->x0; 06075 y1 = arc2->y0; 06076 } 06077 06078 #define TEST_AND_INSERT(z) if(d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v, z, arcr, d, arcwind, i)); 06079 #define ARC_CHECKS(z) (!(arc1 && arc1->centre == z) && !(arc2 && arc2->centre == z) && \ 06080 !(TOPOROUTER_IS_VERTEX(t1) && z == v1) && !(TOPOROUTER_IS_VERTEX(t2) && z == v2)) 06081 06082 if(v1 == v2 || !i->next || TOPOROUTER_VERTEX(i->data) == v2) return NULL; 06083 06084 //#ifdef DEBUG_RUBBERBAND 06085 if(debug) { 06086 printf("\nRB: line %f,%f %f,%f v1 = %f,%f v2 = %f,%f \n ", x0, y0, x1, y1, vx(v1), vy(v1), vx(v2), vy(v2)); 06087 // if(v1->routingedge) print_edge(v1->routingedge); 06088 // if(v2->routingedge) print_edge(v2->routingedge); 06089 06090 } 06091 //#endif 06092 06093 /* check the vectices adjacent to the terminal vectices for push against the segment */ 06094 //if(TOPOROUTER_IS_VERTEX(t1)) { 06095 // toporouter_vertex_t *arcc = NULL; 06096 // d = check_adj_pushing_vertex(oproute, x0, y0, x1, y1, v1, &arcr, &arcwind, &arcc); 06097 // g_assert(arcc != v1); 06098 // if(ARC_CHECKS(arcc) && d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v1, arcc, arcr, d, arcwind, path->next)); 06099 //} 06100 // 06101 //if(TOPOROUTER_IS_VERTEX(t2)) { 06102 // toporouter_vertex_t *arcc = NULL; 06103 // d = check_adj_pushing_vertex(oproute, x0, y0, x1, y1, v2, &arcr, &arcwind, &arcc); 06104 // g_assert(arcc != v2); 06105 // if(ARC_CHECKS(arcc) && d > EPSILON) arcs = g_list_prepend(arcs, new_rubberband_arc(v2, arcc, arcr, d, arcwind, g_list_last(path)->prev)); 06106 //} 06107 06108 i = i->next; 06109 while(i) { 06110 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 06111 06112 if(v == v2 || v == v1 || !v->routingedge) break; 06113 06114 #ifdef DEBUG_RUBBERBAND 06115 // if(debug) 06116 // printf("current v %f,%f - edge %f,%f %f,%f\n", vx(v), vy(v), 06117 // vx(tedge_v1(v->routingedge)), vy(tedge_v1(v->routingedge)), 06118 // vx(tedge_v2(v->routingedge)), vy(tedge_v2(v->routingedge)) 06119 // ); 06120 #endif 06121 g_assert(v->routingedge); 06122 06123 v1wind = coord_wind(x0, y0, x1, y1, vx(tedge_v1(v->routingedge)), vy(tedge_v1(v->routingedge))); 06124 v2wind = coord_wind(x0, y0, x1, y1, vx(tedge_v2(v->routingedge)), vy(tedge_v2(v->routingedge))); 06125 // if(debug) printf("\twinds: %d %d\n", v1wind, v2wind); 06126 if(!v1wind && !v2wind) { i = i->next; continue; } 06127 06128 06129 if(v1wind && v2wind && v1wind != v2wind) { /* edge is cutting through the current segment */ 06130 06131 if(ARC_CHECKS(tedge_v1(v->routingedge)) ){ /* edge v1 is not the centre of an arc terminal */ 06132 d = check_intersect_vertex(x0, y0, x1, y1, v, tedge_v1(v->routingedge), tedge_v2(v->routingedge), v1wind, &arcwind, &arcr, debug); 06133 TEST_AND_INSERT(tedge_v1(v->routingedge)); 06134 } 06135 06136 if(ARC_CHECKS(tedge_v2(v->routingedge)) ){ /* edge v2 is not the centre of an arc terminal */ 06137 d = check_intersect_vertex(x0, y0, x1, y1, v, tedge_v2(v->routingedge), tedge_v1(v->routingedge), v2wind, &arcwind, &arcr, debug); 06138 TEST_AND_INSERT(tedge_v2(v->routingedge)); 06139 } 06140 }else{ /* edge is on one side of the segment */ 06141 06142 if(ARC_CHECKS(tedge_v1(v->routingedge)) ){ /* edge v1 is not the centre of an arc terminal */ 06143 d = check_non_intersect_vertex(x0, y0, x1, y1, v, tedge_v1(v->routingedge), tedge_v2(v->routingedge), v1wind, &arcwind, &arcr, debug); 06144 TEST_AND_INSERT(tedge_v1(v->routingedge)); 06145 } 06146 06147 if(ARC_CHECKS(tedge_v2(v->routingedge)) ){ /* edge v2 is not the centre of an arc terminal */ 06148 d = check_non_intersect_vertex(x0, y0, x1, y1, v, tedge_v2(v->routingedge), tedge_v1(v->routingedge), v2wind, &arcwind, &arcr, debug); 06149 TEST_AND_INSERT(tedge_v2(v->routingedge)); 06150 } 06151 } 06152 06153 i = i->next; 06154 } 06155 06156 arcs = g_list_sort(arcs, (GCompareFunc) compare_rubberband_arcs); 06157 //rubberband_insert_maxarc: 06158 if(!arcs) return NULL; 06159 max = TOPOROUTER_RUBBERBAND_ARC(arcs->data); 06160 06161 av2 = max->pathv; i = max->list->next; 06162 while(i) { 06163 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 06164 if(v->routingedge && (tedge_v1(v->routingedge) == max->arcv || tedge_v2(v->routingedge) == max->arcv)) { 06165 av2 = v; i = i->next; continue; 06166 } 06167 break; 06168 } 06169 06170 av1 = max->pathv; i = max->list->prev; 06171 while(i) { 06172 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 06173 if(v->routingedge && (tedge_v1(v->routingedge) == max->arcv || tedge_v2(v->routingedge) == max->arcv)) { 06174 av1 = v; i = i->prev; continue; 06175 } 06176 break; 06177 } 06178 //#ifdef DEBUG_RUBBERBAND 06179 if(debug) 06180 printf("newarc @ %f,%f \t v1 = %f,%f v2 = %f,%f r = %f\n", vx(max->arcv), vy(max->arcv), vx(av1), vy(av1), vx(av2), vy(av2), max->r); 06181 //#endif 06182 newarc = toporouter_arc_new(oproute, av1, av2, max->arcv, max->r, max->wind); 06183 06184 if(TOPOROUTER_IS_VERTEX(t1)) 06185 calculate_term_to_arc(TOPOROUTER_VERTEX(t1), newarc, 0); 06186 else if(calculate_arc_to_arc(r, TOPOROUTER_ARC(t1), newarc)) { 06187 printf("\tERROR: best: r = %f d = %f\n", max->r, max->d); 06188 printf("\tOPROUTE: %s\n", oproute->netlist); 06189 print_vertex(oproute->term1); 06190 print_vertex(oproute->term2); 06191 return NULL; 06192 } 06193 06194 if(TOPOROUTER_IS_VERTEX(t2)) 06195 calculate_term_to_arc(TOPOROUTER_VERTEX(t2), newarc, 1); 06196 else if(calculate_arc_to_arc(r, newarc, TOPOROUTER_ARC(t2))) { 06197 printf("\tERROR: best: r = %f d = %f\n", max->r, max->d); 06198 printf("\tOPROUTE: %s\n", oproute->netlist); 06199 print_vertex(oproute->term1); 06200 print_vertex(oproute->term2); 06201 return NULL; 06202 } 06203 06204 //if(check_arc_for_loops(t1, newarc, t2)) { 06205 // if(arc1 && arc2) calculate_arc_to_arc(r, arc1, arc2); 06206 // else if(arc1) calculate_term_to_arc(TOPOROUTER_VERTEX(t2), arc1, 1); 06207 // else if(arc2) calculate_term_to_arc(TOPOROUTER_VERTEX(t1), arc2, 0); 06208 06209 //#ifdef DEBUG_RUBBERBAND 06210 // printf("REMOVING NEW ARC @ %f,%f\n", vx(newarc->centre), vy(newarc->centre)); 06211 // //TODO: properly remove newarc 06212 //#endif 06213 06214 // arcs = g_list_remove(arcs, max); 06215 // free(max); 06216 // goto rubberband_insert_maxarc; 06217 //} 06218 06219 06220 list1 = oproute_rubberband_segment(r, oproute, path, t1, newarc, debug); 06221 list2 = oproute_rubberband_segment(r, oproute, i->next, newarc, t2, debug); 06222 06223 if(list1) { 06224 GList *list = g_list_last(list1); 06225 toporouter_arc_t *testarc = TOPOROUTER_ARC(list->data); 06226 toporouter_arc_t *parc = list->prev ? TOPOROUTER_ARC(list->prev->data) : arc1; 06227 gdouble px = parc ? parc->x1 : vx(TOPOROUTER_VERTEX(t1)), py = parc ? parc->y1 : vy(TOPOROUTER_VERTEX(t1)); 06228 06229 if(coord_intersect_prop(px, py, testarc->x0, testarc->y0, testarc->x1, testarc->y1, newarc->x0, newarc->y0)) { 06230 list1 = g_list_remove(list1, testarc); 06231 if(parc) calculate_arc_to_arc(r, parc, newarc); 06232 else calculate_term_to_arc(TOPOROUTER_VERTEX(t1), newarc, 0); 06233 //#ifdef DEBUG_RUBBERBAND 06234 if(debug) 06235 printf("REMOVING ARC @ %f,%f\n", vx(testarc->centre), vy(testarc->centre)); 06236 //#endif 06237 } 06238 } 06239 if(list2) { 06240 toporouter_arc_t *testarc = TOPOROUTER_ARC(list2->data); 06241 toporouter_arc_t *narc = list2->next ? TOPOROUTER_ARC(list2->next->data) : arc2; 06242 gdouble nx = narc ? narc->x0 : vx(TOPOROUTER_VERTEX(t2)), ny = narc ? narc->y0 : vy(TOPOROUTER_VERTEX(t2)); 06243 06244 if(coord_intersect_prop(newarc->x1, newarc->y1, testarc->x0, testarc->y0, testarc->x1, testarc->y1, nx, ny)) { 06245 list2 = g_list_remove(list2, testarc); 06246 if(narc) calculate_arc_to_arc(r, newarc, narc); 06247 else calculate_term_to_arc(TOPOROUTER_VERTEX(t2), newarc, 1); 06248 06249 //#ifdef DEBUG_RUBBERBAND 06250 if(debug) 06251 printf("REMOVING ARC @ %f,%f\n", vx(testarc->centre), vy(testarc->centre)); 06252 //#endif 06253 } 06254 } 06255 06256 g_list_foreach(arcs, free_list_elements, NULL); 06257 g_list_free(arcs); 06258 06259 return g_list_concat(list1, g_list_prepend(list2, newarc)); 06260 } 06261 06262 void 06263 oproute_check_all_loops(toporouter_t *r, toporouter_oproute_t *oproute) 06264 { 06265 GList *i; 06266 gpointer t1; 06267 06268 loopcheck_restart: 06269 t1 = oproute->term1; 06270 i = oproute->arcs; 06271 while(i) { 06272 toporouter_arc_t *arc = TOPOROUTER_ARC(i->data); 06273 gpointer t2 = i->next ? i->next->data : oproute->term2; 06274 06275 if(check_arc_for_loops(t1, arc, t2)) { 06276 06277 if(TOPOROUTER_IS_ARC(t1) && TOPOROUTER_IS_ARC(t2)) 06278 calculate_arc_to_arc(r, TOPOROUTER_ARC(t1), TOPOROUTER_ARC(t2)); 06279 else if(TOPOROUTER_IS_ARC(t1)) 06280 calculate_term_to_arc(TOPOROUTER_VERTEX(t2), TOPOROUTER_ARC(t1), 1); 06281 else if(TOPOROUTER_IS_ARC(t2)) 06282 calculate_term_to_arc(TOPOROUTER_VERTEX(t1), TOPOROUTER_ARC(t2), 0); 06283 06284 oproute->arcs = g_list_remove(oproute->arcs, arc); 06285 goto loopcheck_restart; 06286 } 06287 06288 t1 = arc; 06289 06290 i = i->next; 06291 } 06292 06293 } 06294 06295 GtsTriangle * 06296 opposite_triangle(GtsTriangle *t, toporouter_edge_t *e) 06297 { 06298 GSList *i = GTS_EDGE(e)->triangles; 06299 06300 g_assert(e && t); 06301 06302 while(i) { 06303 if(GTS_TRIANGLE(i->data) != t) return GTS_TRIANGLE(i->data); 06304 i = i->next; 06305 } 06306 06307 return NULL; 06308 } 06309 06310 06311 void 06312 speccut_edge_routing_from_edge(GList *i, toporouter_edge_t *e) 06313 { 06314 g_assert(TOPOROUTER_IS_EDGE(e)); 06315 while(i) { 06316 toporouter_vertex_t *curv = TOPOROUTER_VERTEX(i->data); 06317 06318 if(!(curv->flags & VERTEX_FLAG_TEMP)) { 06319 toporouter_vertex_t *newv = tvertex_intersect(curv, curv->parent, tedge_v1(e), tedge_v2(e)); 06320 06321 // printf("\nCURV:\n"); 06322 // print_vertex(curv); 06323 // 06324 // printf("CURV child:\n"); 06325 // if(curv->child) 06326 // print_vertex(curv->child); 06327 // else 06328 // printf("NULL\n"); 06329 // 06330 // printf("CURV parent:\n"); 06331 // if(curv->parent) 06332 // print_vertex(curv->parent); 06333 // else 06334 // printf("NULL\n"); 06335 06336 if(newv) { 06337 gint index; 06338 newv->flags |= VERTEX_FLAG_ROUTE; 06339 newv->flags |= VERTEX_FLAG_SPECCUT; 06340 e->routing = g_list_insert_sorted_with_data(e->routing, newv, routing_edge_insert, e); 06341 newv->route = curv->route; 06342 newv->oproute = curv->oproute; 06343 newv->routingedge = e; 06344 GTS_POINT(newv)->z = vz(curv); 06345 06346 newv->parent = curv->parent; 06347 newv->child = curv; 06348 06349 // curv->parent = newv; 06350 06351 index = g_list_index(newv->route->path, curv); 06352 06353 newv->route->path = g_list_insert(newv->route->path, newv, index); 06354 06355 06356 if(newv->oproute) newv->oproute->path = newv->route->path; 06357 } 06358 06359 if(!(curv->child->routingedge)) { 06360 newv = tvertex_intersect(curv, curv->child, tedge_v1(e), tedge_v2(e)); 06361 06362 if(newv) { 06363 gint index; 06364 newv->flags |= VERTEX_FLAG_ROUTE; 06365 newv->flags |= VERTEX_FLAG_SPECCUT; 06366 e->routing = g_list_insert_sorted_with_data(e->routing, newv, routing_edge_insert, e); 06367 newv->route = curv->route; 06368 newv->oproute = curv->oproute; 06369 newv->routingedge = e; 06370 GTS_POINT(newv)->z = vz(curv); 06371 06372 newv->parent = curv; 06373 newv->child = curv->child; 06374 06375 // curv->child = newv; 06376 06377 index = g_list_index(newv->route->path, curv); 06378 06379 newv->route->path = g_list_insert(newv->route->path, newv, index+1); 06380 06381 06382 if(newv->oproute) newv->oproute->path = newv->route->path; 06383 } 06384 06385 } 06386 06387 } 06388 i = i->next; 06389 } 06390 06391 } 06392 06393 void 06394 speccut_edge_patch_links(toporouter_edge_t *e) 06395 { 06396 GList *i = e->routing; 06397 g_assert(TOPOROUTER_IS_EDGE(e)); 06398 while(i) { 06399 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 06400 v->parent->child = v; 06401 v->child->parent = v; 06402 i = i->next; 06403 } 06404 } 06405 06406 gint 06407 check_speccut(toporouter_oproute_t *oproute, toporouter_vertex_t *v1, toporouter_vertex_t *v2, toporouter_edge_t *e, toporouter_edge_t *e1, toporouter_edge_t *e2) 06408 { 06409 GtsTriangle *t, *opt; 06410 toporouter_vertex_t *opv, *opv2; 06411 toporouter_edge_t *ope1, *ope2; 06412 gdouble cap, flow, line_int_x, line_int_y; 06413 06414 if(TOPOROUTER_IS_CONSTRAINT(e)) return 0; 06415 06416 if(!(t = gts_triangle_use_edges(GTS_EDGE(e), GTS_EDGE(e1), GTS_EDGE(e2)))) { 06417 printf("check_speccut: NULL t\n"); 06418 return 0; 06419 } 06420 06421 if(!(opt = opposite_triangle(t, e))) { 06422 // printf("check_speccut: NULL opt\n"); 06423 return 0; 06424 } 06425 06426 if(!(opv = segment_common_vertex(GTS_SEGMENT(e1), GTS_SEGMENT(e2)))) { 06427 printf("check_speccut: NULL opv\n"); 06428 return 0; 06429 } 06430 06431 if(!(opv2 = TOPOROUTER_VERTEX(gts_triangle_vertex_opposite(opt, GTS_EDGE(e))))) { 06432 printf("check_speccut: NULL opv2\n"); 06433 return 0; 06434 } 06435 06436 //TODO: shifting it out of the way would be better 06437 if(e->routing) { 06438 GList *i = e->routing; 06439 while(i) { 06440 toporouter_vertex_t *ev = TOPOROUTER_VERTEX(i->data); 06441 if(!tvertex_wind(opv, ev, opv2)) return 0; 06442 i = i->next; 06443 } 06444 06445 } 06446 06447 ope1 = tedge(opv2, tedge_v1(e)); 06448 ope2 = tedge(opv2, tedge_v2(e)); 06449 06450 //this fixes the weird pad exits in r8c board 06451 // if(TOPOROUTER_IS_CONSTRAINT(ope1)) return 0; 06452 if(TOPOROUTER_IS_CONSTRAINT(ope2)) return 0; 06453 06454 if(!tvertex_wind(opv2, tedge_v1(e), opv)) return 0; 06455 if(!tvertex_wind(opv2, tedge_v2(e), opv)) return 0; 06456 06457 if(!vertex_line_normal_intersection( 06458 vx(tedge_v1(e)), vy(tedge_v1(e)), 06459 vx(tedge_v2(e)), vy(tedge_v2(e)), 06460 vx(opv2), vy(opv2), 06461 &line_int_x, &line_int_y)) return 0; 06462 06463 06464 // return 0; 06465 //if(vertex_line_normal_intersection(tev1x(e), tev1y(e), tev2x(e), tev2y(e), vx(opv), vy(opv), &line_int_x, &line_int_y)) 06466 // return 0; 06467 06468 g_assert(opt && opv2); 06469 06470 /* this is just temp, for the purposes of determining flow */ 06471 if(tedge_v1(ope1) == opv2) { 06472 if(TOPOROUTER_IS_CONSTRAINT(ope1)) 06473 TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_append(TOPOROUTER_CONSTRAINT(ope1)->routing, v1); 06474 else 06475 ope1->routing = g_list_append(ope1->routing, v1); 06476 }else{ 06477 if(TOPOROUTER_IS_CONSTRAINT(ope1)) 06478 TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_prepend(TOPOROUTER_CONSTRAINT(ope1)->routing, v1); 06479 else 06480 ope1->routing = g_list_prepend(ope1->routing, v1); 06481 } 06482 06483 cap = triangle_interior_capacity(opt, opv2); 06484 flow = flow_from_edge_to_edge(opt, tedge(opv2, tedge_v1(e)), tedge(opv2, tedge_v2(e)), opv2, v1); 06485 06486 /* temp v1 removed */ 06487 if(TOPOROUTER_IS_CONSTRAINT(ope1)) 06488 TOPOROUTER_CONSTRAINT(ope1)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(ope1)->routing, v1); 06489 else 06490 ope1->routing = g_list_remove(ope1->routing, v1); 06491 06492 if(flow >= cap) { 06493 toporouter_edge_t *newe = TOPOROUTER_EDGE(gts_edge_new(GTS_EDGE_CLASS(toporouter_edge_class()), GTS_VERTEX(opv), GTS_VERTEX(opv2))); 06494 06495 speccut_edge_routing_from_edge(edge_routing(e1), newe); 06496 speccut_edge_routing_from_edge(edge_routing(e2), newe); 06497 speccut_edge_routing_from_edge(edge_routing(ope1), newe); 06498 speccut_edge_routing_from_edge(edge_routing(ope2), newe); 06499 06500 speccut_edge_patch_links(newe); 06501 /* 06502 printf("SPECCUT WITH v %f,%f for seg %f,%f %f,%f detected\n", vx(opv2), vy(opv2), 06503 vx(v1), vy(v1), 06504 vx(v2), vy(v2)); 06505 printf("\tflow %f cap %f\n", flow, cap); 06506 print_edge(newe); 06507 */ 06508 if(newe->routing) return 1; 06509 } 06510 06511 06512 return 0; 06513 } 06514 06515 06516 gint 06517 oproute_path_speccut(toporouter_oproute_t *oproute) 06518 { 06519 GList *i; 06520 toporouter_vertex_t *pv; 06521 path_speccut_restart: 06522 i = oproute->path; 06523 pv = NULL; 06524 while(i) { 06525 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 06526 06527 06528 if(pv && (v->routingedge || pv->routingedge) && !(pv->flags & VERTEX_FLAG_SPECCUT) && !(v->flags & VERTEX_FLAG_SPECCUT)) { 06529 06530 if(!v->routingedge) { 06531 if(check_speccut(oproute, pv, v, tedge(tedge_v1(pv->routingedge), v), pv->routingedge, tedge(tedge_v2(pv->routingedge), v))) 06532 goto path_speccut_restart; 06533 if(check_speccut(oproute, pv, v, tedge(tedge_v2(pv->routingedge), v), pv->routingedge, tedge(tedge_v1(pv->routingedge), v))) 06534 goto path_speccut_restart; 06535 }else if(!pv->routingedge) { 06536 if(check_speccut(oproute, v, pv, tedge(tedge_v1(v->routingedge), pv), v->routingedge, tedge(tedge_v2(v->routingedge), pv))) 06537 goto path_speccut_restart; 06538 if(check_speccut(oproute, v, pv, tedge(tedge_v2(v->routingedge), pv), v->routingedge, tedge(tedge_v1(v->routingedge), pv))) 06539 goto path_speccut_restart; 06540 }else{ 06541 toporouter_vertex_t *v1 = NULL, *v2 = NULL; 06542 edges_third_edge(GTS_SEGMENT(v->routingedge), GTS_SEGMENT(pv->routingedge), &v1, &v2); 06543 if(check_speccut(oproute, v, pv, tedge(v1, v2), v->routingedge, pv->routingedge)) 06544 goto path_speccut_restart; 06545 } 06546 } 06547 06548 06549 pv = v; 06550 i = i->next; 06551 } 06552 06553 return 0; 06554 } 06555 06556 toporouter_oproute_t * 06557 oproute_rubberband(toporouter_t *r, GList *path) 06558 { 06559 toporouter_oproute_t *oproute = (toporouter_oproute_t *)malloc(sizeof(toporouter_oproute_t)); 06560 06561 g_assert(path); 06562 06563 oproute->term1 = TOPOROUTER_VERTEX(path->data); 06564 oproute->term2 = TOPOROUTER_VERTEX(g_list_last(path)->data); 06565 oproute->arcs = NULL; 06566 oproute->style = vertex_bbox(oproute->term1)->cluster->netlist->style; 06567 oproute->netlist = vertex_bbox(oproute->term1)->cluster->netlist->netlist; 06568 oproute->layergroup = vz(oproute->term1); 06569 oproute->path = path; 06570 oproute->serp = NULL; 06571 06572 oproute->term1->parent = NULL; 06573 oproute->term2->child = NULL; 06574 06575 path_set_oproute(path, oproute); 06576 06577 // if(!strcmp(oproute->netlist, " unnamed_net1")) 06578 oproute_path_speccut(oproute); 06579 06580 #ifdef DEBUG_RUBBERBAND 06581 if(strcmp(oproute->netlist, " VCC3V3" == 0) && 06582 vx(oproute->term1) == MIL_TO_COORD (957.) && 06583 vy(oproute->term1) == MIL_TO_COORD (708.) && 06584 vx(oproute->term2) == MIL_TO_COORD (1967.) && 06585 vy(oproute->term2) == MIL_TO_COORD (673.)) 06586 { 06587 // printf("OPROUTE %s - %f,%f %f,%f\n", oproute->netlist, vx(oproute->term1), vy(oproute->term1), vx(oproute->term2), vy(oproute->term2)); 06588 // print_path(path); 06589 oproute->arcs = oproute_rubberband_segment(r, oproute, path, oproute->term1, oproute->term2, 1); 06590 }else 06591 #endif 06592 oproute->arcs = oproute_rubberband_segment(r, oproute, path, oproute->term1, oproute->term2, 0); 06593 06594 oproute_check_all_loops(r, oproute); 06595 return oproute; 06596 06597 } 06598 06599 void 06600 toporouter_export(toporouter_t *r) 06601 { 06602 GList *i = r->routednets; 06603 GList *oproutes = NULL; 06604 06605 while(i) { 06606 toporouter_route_t *routedata = TOPOROUTER_ROUTE(i->data); 06607 toporouter_oproute_t *oproute = oproute_rubberband(r, routedata->path); 06608 oproutes = g_list_prepend(oproutes, oproute); 06609 i = i->next; 06610 } 06611 06612 i = oproutes; 06613 while(i) { 06614 toporouter_oproute_t *oproute = (toporouter_oproute_t *) i->data; 06615 export_oproutes(r, oproute); 06616 oproute_free(oproute); 06617 i = i->next; 06618 } 06619 06620 Message (_("Reticulating splines... successful\n\n")); 06621 /* NB: We could use the %$mS specifier to print these distances, but we would 06622 * have to cast to Coord, which might overflow for complex routing when 06623 * PCB is built with Coord as a 32-bit integer. 06624 */ 06625 Message (_("Wiring cost: %f inches\n"), COORD_TO_INCH (r->wiring_score)); 06626 printf (_("Wiring cost: %f inches\n"), COORD_TO_INCH (r->wiring_score)); 06627 06628 g_list_free(oproutes); 06629 06630 } 06631 06632 toporouter_route_t * 06633 routedata_create(void) 06634 { 06635 toporouter_route_t *routedata = (toporouter_route_t *)malloc(sizeof(toporouter_route_t)); 06636 routedata->netlist = NULL; 06637 routedata->alltemppoints = NULL; 06638 routedata->path = NULL; 06639 routedata->curpoint = NULL; 06640 routedata->pscore = routedata->score = 0.; 06641 routedata->flags = 0; 06642 routedata->src = routedata->dest = NULL; 06643 routedata->psrc = routedata->pdest = NULL; 06644 routedata->ppath = routedata->topopath = NULL; 06645 06646 routedata->ppathindices = NULL; 06647 06648 routedata->destvertices = routedata->srcvertices = NULL; 06649 return routedata; 06650 } 06651 /* 06652 void 06653 print_routedata(toporouter_route_t *routedata) 06654 { 06655 GList *srcvertices = cluster_vertices(routedata->src); 06656 GList *destvertices = cluster_vertices(routedata->dest); 06657 06658 printf("ROUTEDATA:\n"); 06659 printf("SRCVERTICES:\n"); 06660 print_vertices(srcvertices); 06661 printf("DESTVERTICES:\n"); 06662 print_vertices(destvertices); 06663 06664 g_list_free(srcvertices); 06665 g_list_free(destvertices); 06666 }*/ 06667 06668 toporouter_route_t * 06669 import_route(toporouter_t *r, RatType *line) 06670 { 06671 toporouter_route_t *routedata = routedata_create(); 06672 06673 routedata->src = cluster_find(r, line->Point1.X, line->Point1.Y, line->group1); 06674 routedata->dest = cluster_find(r, line->Point2.X, line->Point2.Y, line->group2); 06675 06676 if(!routedata->src) printf("couldn't locate src\n"); 06677 if(!routedata->dest) printf("couldn't locate dest\n"); 06678 06679 if(!routedata->src || !routedata->dest) { 06680 pcb_printf("PROBLEM: couldn't locate rat src or dest for rat %#mD, %d -> %#mD, %d\n", 06681 line->Point1.X, line->Point1.Y, line->group1, line->Point2.X, line->Point2.Y, line->group2); 06682 free(routedata); 06683 return NULL; 06684 } 06685 06686 routedata->netlist = routedata->src->netlist; 06687 06688 g_assert(routedata->src->netlist == routedata->dest->netlist); 06689 06690 g_ptr_array_add(r->routes, routedata); 06691 g_ptr_array_add(routedata->netlist->routes, routedata); 06692 06693 r->failednets = g_list_prepend(r->failednets, routedata); 06694 06695 return routedata; 06696 } 06697 06698 void 06699 delete_route(toporouter_route_t *routedata, guint destroy) 06700 { 06701 GList *i = routedata->path; 06702 toporouter_vertex_t *pv = NULL; 06703 06704 while(i) { 06705 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 06706 06707 g_assert(tv); 06708 06709 if(tv && pv && !(tv->flags & VERTEX_FLAG_ROUTE) && !(pv->flags & VERTEX_FLAG_ROUTE)) { 06710 toporouter_edge_t *e = TOPOROUTER_EDGE(gts_vertices_are_connected(GTS_VERTEX(tv), GTS_VERTEX(pv))); 06711 06712 if(e && (e->flags & EDGE_FLAG_DIRECTCONNECTION)) { 06713 e->flags ^= EDGE_FLAG_DIRECTCONNECTION; 06714 } 06715 } 06716 pv = tv; 06717 i = i->next; 06718 } 06719 06720 i = routedata->path; 06721 while(i) { 06722 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 06723 06724 tv->parent = NULL; 06725 tv->child = NULL; 06726 06727 if(tv->routingedge) { 06728 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 06729 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv); 06730 else 06731 tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv); 06732 if(destroy) gts_object_destroy ( GTS_OBJECT(tv) ); 06733 } 06734 06735 i = i->next; 06736 } 06737 06738 if(routedata->path) g_list_free(routedata->path); 06739 routedata->path = NULL; 06740 routedata->curpoint = NULL; 06741 routedata->score = INFINITY; 06742 routedata->alltemppoints = NULL; 06743 } 06744 06748 void 06749 remove_route(GList *path) 06750 { 06751 GList *i = path; 06752 06753 while(i) { 06754 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 06755 06756 tv->parent = NULL; 06757 tv->child = NULL; 06758 06759 // if(tv->flags & VERTEX_FLAG_ROUTE) g_assert(tv->route == routedata); 06760 06761 if(tv->routingedge) { 06762 06763 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 06764 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, tv); 06765 else 06766 tv->routingedge->routing = g_list_remove(tv->routingedge->routing, tv); 06767 } 06768 i = i->next; 06769 } 06770 06771 } 06772 06773 gint 06774 apply_route(GList *path, toporouter_route_t *routedata) 06775 { 06776 GList *i = path; 06777 toporouter_vertex_t *pv = NULL; 06778 gint count = 0; 06779 06780 if(!path) return 0; 06781 // g_assert(path); 06782 06783 while(i) { 06784 toporouter_vertex_t *tv = TOPOROUTER_VERTEX(i->data); 06785 06786 if(tv->routingedge) { 06787 if(TOPOROUTER_IS_CONSTRAINT(tv->routingedge)) 06788 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing = g_list_insert_sorted_with_data( 06789 TOPOROUTER_CONSTRAINT(tv->routingedge)->routing, 06790 tv, 06791 routing_edge_insert, 06792 tv->routingedge); 06793 else 06794 tv->routingedge->routing = g_list_insert_sorted_with_data( 06795 tv->routingedge->routing, 06796 tv, 06797 routing_edge_insert, 06798 tv->routingedge); 06799 06800 count++; 06801 } 06802 06803 if(pv) { 06804 pv->child = tv; 06805 tv->parent = pv; 06806 } 06807 06808 if(tv->flags & VERTEX_FLAG_ROUTE) g_assert(tv->route == routedata); 06809 06810 pv = tv; 06811 i = i->next; 06812 } 06813 06814 TOPOROUTER_VERTEX(path->data)->parent = NULL; 06815 pv->child = NULL; 06816 06817 return count; 06818 } 06819 06820 06821 gint 06822 compare_routedata_ascending(gconstpointer a, gconstpointer b) 06823 { 06824 toporouter_route_t *ra = (toporouter_route_t *)a; 06825 toporouter_route_t *rb = (toporouter_route_t *)b; 06826 return ra->score - rb->score; 06827 } 06828 06829 void 06830 print_costmatrix(gdouble *m, guint n) 06831 { 06832 printf("COST MATRIX:\n"); 06833 for(guint i = 0;i<n;i++) { 06834 for(guint j = 0;j<n;j++) { 06835 printf("%f ", m[(i*n)+j]); 06836 } 06837 printf("\n"); 06838 } 06839 } 06840 06841 06842 static inline void 06843 init_cost_matrix(gdouble *m, guint n) 06844 { 06845 for(guint i=0;i<n;i++) { 06846 for(guint j=0;j<n;j++) { 06847 m[(i*n)+j] = INFINITY; 06848 } 06849 } 06850 } 06851 06852 06853 toporouter_netscore_t * 06854 netscore_create(toporouter_t *r, toporouter_route_t *routedata, guint n, guint id) 06855 { 06856 toporouter_netscore_t *netscore = (toporouter_netscore_t *)malloc(sizeof(toporouter_netscore_t)); 06857 GList *path = route(r, routedata, 0); 06858 06859 netscore->id = id; 06860 06861 netscore->routedata = routedata; 06862 routedata->detourscore = netscore->score = routedata->score; 06863 06864 if(!isfinite(routedata->detourscore)) { 06865 printf("WARNING: !isfinite(detourscore)\n"); 06866 print_cluster(routedata->src); 06867 print_cluster(routedata->dest); 06868 return NULL; 06869 } 06870 06871 netscore->pairwise_nodetour = (guint *)malloc(n * sizeof(guint)); 06872 06873 for(guint i=0;i<n;i++) { 06874 netscore->pairwise_nodetour[i] = 0; 06875 } 06876 06877 netscore->pairwise_detour_sum = 0.; 06878 netscore->pairwise_fails = 0; 06879 06880 netscore->r = r; 06881 06882 if(path) { 06883 routedata->topopath = g_list_copy(routedata->path); 06884 delete_route(routedata, 0); 06885 } 06886 06887 return netscore; 06888 } 06889 06890 static inline void 06891 netscore_destroy(toporouter_netscore_t *netscore) 06892 { 06893 free(netscore->pairwise_nodetour); 06894 free(netscore); 06895 } 06896 06897 void 06898 print_netscores(GPtrArray* netscores) 06899 { 06900 printf("NETSCORES: \n\n"); 06901 printf(" %15s %15s %15s\n----------------------------------------------------\n", "Score", "Detour Sum", "Pairwise Fails"); 06902 06903 for(toporouter_netscore_t **i = (toporouter_netscore_t **) netscores->pdata; i < (toporouter_netscore_t **) netscores->pdata + netscores->len; i++) { 06904 #ifdef DEBUG_NETSCORES 06905 printf("%4d %15f %15f %15d %15x\n", (*i)->id, (*i)->score, (*i)->pairwise_detour_sum, (*i)->pairwise_fails, (guint)*i); 06906 #endif 06907 } 06908 06909 printf("\n"); 06910 } 06911 06912 void 06913 netscore_pairwise_calculation(toporouter_netscore_t *netscore, GPtrArray *netscores) 06914 { 06915 toporouter_netscore_t **netscores_base = (toporouter_netscore_t **) (netscores->pdata); 06916 toporouter_route_t *temproutedata = routedata_create(); 06917 06918 //route(netscore->r, netscore->routedata, 0); 06919 apply_route(netscore->routedata->topopath, netscore->routedata); 06920 06921 for(toporouter_netscore_t **i = netscores_base; i < netscores_base + netscores->len; i++) { 06922 06923 if(!netscore->pairwise_nodetour[i-netscores_base] && *i != netscore && (*i)->routedata->netlist != netscore->routedata->netlist) { 06924 06925 temproutedata->src = (*i)->routedata->src; 06926 temproutedata->dest = (*i)->routedata->dest; 06927 06928 route(netscore->r, temproutedata, 0); 06929 06930 if(temproutedata->score == (*i)->score) { 06931 netscore->pairwise_nodetour[i-netscores_base] = 1; 06932 (*i)->pairwise_nodetour[netscore->id] = 1; 06933 }else 06934 if(!isfinite(temproutedata->score)) { 06935 netscore->pairwise_fails += 1; 06936 }else{ 06937 netscore->pairwise_detour_sum += temproutedata->score - (*i)->score; 06938 } 06939 06940 delete_route(temproutedata, 1); 06941 } 06942 06943 } 06944 06945 // delete_route(netscore->routedata, 1); 06946 remove_route(netscore->routedata->topopath); 06947 06948 free(temproutedata); 06949 } 06950 06951 gint 06952 netscore_pairwise_size_compare(toporouter_netscore_t **a, toporouter_netscore_t **b) 06953 { 06954 // infinite scores are last 06955 if(!isfinite((*a)->score) && !isfinite((*b)->score)) return 0; 06956 if(isfinite((*a)->score) && !isfinite((*b)->score)) return -1; 06957 if(isfinite((*b)->score) && !isfinite((*a)->score)) return 1; 06958 06959 // order by pairwise fails 06960 if((*a)->pairwise_fails < (*b)->pairwise_fails) return -1; 06961 if((*b)->pairwise_fails < (*a)->pairwise_fails) return 1; 06962 06963 // order by pairwise detour 06964 if((*a)->pairwise_detour_sum < (*b)->pairwise_detour_sum) return -1; 06965 if((*b)->pairwise_detour_sum < (*a)->pairwise_detour_sum) return 1; 06966 06967 // order by score 06968 if((*a)->score < (*b)->score) return -1; 06969 if((*b)->score < (*a)->score) return 1; 06970 06971 return 0; 06972 } 06973 06974 gint 06975 netscore_pairwise_compare(toporouter_netscore_t **a, toporouter_netscore_t **b) 06976 { 06977 // infinite scores are last 06978 if(!isfinite((*a)->score) && !isfinite((*b)->score)) return 0; 06979 if(isfinite((*a)->score) && !isfinite((*b)->score)) return -1; 06980 if(isfinite((*b)->score) && !isfinite((*a)->score)) return 1; 06981 06982 // order by pairwise fails 06983 if((*a)->pairwise_fails < (*b)->pairwise_fails) return -1; 06984 if((*b)->pairwise_fails < (*a)->pairwise_fails) return 1; 06985 06986 // order by pairwise detour 06987 if((*a)->pairwise_detour_sum < (*b)->pairwise_detour_sum) return -1; 06988 if((*b)->pairwise_detour_sum < (*a)->pairwise_detour_sum) return 1; 06989 06990 return 0; 06991 } 06992 06993 guint 06994 order_nets_preroute_greedy(toporouter_t *r, GList *nets, GList **rnets) 06995 { 06996 gint len = g_list_length(nets); 06997 GPtrArray* netscores = g_ptr_array_sized_new(len); 06998 guint failcount = 0; 06999 07000 while(nets) { 07001 toporouter_netscore_t *ns = netscore_create(r, TOPOROUTER_ROUTE(nets->data), len, failcount++); 07002 if(ns) g_ptr_array_add(netscores, ns); 07003 nets = nets->next; 07004 } 07005 07006 failcount = 0; 07007 07008 g_ptr_array_foreach(netscores, (GFunc) netscore_pairwise_calculation, netscores); 07009 07010 g_ptr_array_sort(netscores, (GCompareFunc) r->netsort); 07011 07012 #ifdef DEBUG_ORDERING 07013 print_netscores(netscores); 07014 #endif 07015 07016 *rnets = NULL; 07017 FOREACH_NETSCORE(netscores) { 07018 *rnets = g_list_prepend(*rnets, netscore->routedata); 07019 if(!isfinite(netscore->score)) failcount++; 07020 netscore_destroy(netscore); 07021 } FOREACH_END; 07022 07023 g_ptr_array_free(netscores, TRUE); 07024 07025 return failcount; 07026 } 07027 07028 toporouter_vertex_t * 07029 edge_closest_vertex(toporouter_edge_t *e, toporouter_vertex_t *v) 07030 { 07031 GList *i = v->routingedge ? edge_routing(v->routingedge) : NULL; 07032 gdouble closestd = 0.; 07033 toporouter_vertex_t *closestv = NULL; 07034 07035 while(i) { 07036 toporouter_vertex_t *ev = TOPOROUTER_VERTEX(i->data); 07037 gdouble tempd = gts_point_distance2(GTS_POINT(ev), GTS_POINT(v)); 07038 07039 if(!closestv || (tempd < closestd)) { 07040 closestd = tempd; 07041 closestv = ev; 07042 } 07043 07044 i = i->next; 07045 } 07046 07047 return closestv; 07048 } 07049 07050 void 07051 snapshot(toporouter_t *r, char *name, GList *datas) 07052 { 07054 { 07055 int i; 07056 for(i=0;i<groupcount();i++) { 07057 char buffer[256]; 07058 sprintf(buffer, "route-%s-%d.png", name, i); 07059 toporouter_draw_surface(r, r->layers[i].surface, buffer, 2048, 2048, 2, datas, i, NULL); 07060 } 07061 } 07062 //*/ 07063 07064 } 07065 /* 07066 gdouble 07067 route_conflict(toporouter_t *r, toporouter_route_t *route, guint *n) 07068 { 07069 GList *i = route->path; 07070 toporouter_vertex_t *pv = NULL; 07071 gdouble cost = 0.; 07072 07073 while(i) { 07074 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 07075 if(pv && vz(v) == vz(pv)) 07076 cost += vertices_routing_conflict_cost(r, v, pv, n); 07077 pv = v; 07078 i = i->next; 07079 } 07080 07081 return cost; 07082 } 07083 */ 07084 GList * 07085 route_conflicts(toporouter_route_t *route) 07086 { 07087 GList *conflicts = NULL, *i = route->path; 07088 toporouter_vertex_t *pv = NULL; 07089 07090 while(i) { 07091 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 07092 07093 if(pv && vz(pv) == vz(v)) { 07094 GList *temp = vertices_routing_conflicts(pv, v), *j; 07095 07096 j = temp; 07097 while(j) { 07098 toporouter_route_t *conroute = TOPOROUTER_ROUTE(j->data); 07099 if(!g_list_find(conflicts, conroute)) 07100 conflicts = g_list_prepend(conflicts, conroute); 07101 j = j->next; 07102 } 07103 07104 if(temp) g_list_free(temp); 07105 } 07106 07107 pv = v; 07108 i = i->next; 07109 } 07110 return conflicts; 07111 } 07112 07113 gint 07114 spread_edge(gpointer item, gpointer data) 07115 { 07116 toporouter_edge_t *e = TOPOROUTER_EDGE(item); 07117 toporouter_vertex_t *v; 07118 gdouble spacing, s; 07119 GList *i; 07120 07121 if(TOPOROUTER_IS_CONSTRAINT(e)) return 0; 07122 07123 i = edge_routing(e); 07124 07125 if(!g_list_length(i)) return 0; 07126 07127 if(g_list_length(i) == 1) { 07128 v = TOPOROUTER_VERTEX(i->data); 07129 GTS_POINT(v)->x = (vx(edge_v1(e)) + vx(edge_v2(e))) / 2.; 07130 GTS_POINT(v)->y = (vy(edge_v1(e)) + vy(edge_v2(e))) / 2.; 07131 return 0; 07132 } 07133 07134 s = spacing = (gts_point_distance(GTS_POINT(edge_v1(e)), GTS_POINT(edge_v2(e))) ) / (g_list_length(i) + 1); 07135 07136 while(i) { 07137 v = TOPOROUTER_VERTEX(i->data); 07138 vertex_move_towards_vertex_values(edge_v1(e), edge_v2(e), s, &(GTS_POINT(v)->x), &(GTS_POINT(v)->y)); 07139 07140 s += spacing; 07141 i = i->next; 07142 } 07143 07144 return 0; 07145 } 07146 07147 void 07148 route_checkpoint(toporouter_route_t *route, toporouter_route_t *temproute) 07149 { 07150 GList *i = g_list_last(route->path); 07151 gint n = g_list_length(route->path); 07152 07153 if(route->ppathindices) free(route->ppathindices); 07154 route->ppathindices = (gint *)malloc(sizeof(gint)*n); 07155 07156 // n = 0; 07157 while(i) { 07158 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 07159 n--; 07160 07161 if(v->routingedge) { 07162 GList *j = g_list_find(edge_routing(v->routingedge), v)->prev; 07163 gint tempindex = g_list_index(edge_routing(v->routingedge), v); 07164 07165 while(j) { 07166 if(TOPOROUTER_VERTEX(j->data)->route == temproute) tempindex--; 07167 j = j->prev; 07168 } 07169 07170 route->ppathindices[n] = tempindex; 07171 07172 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 07173 TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_remove(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v); 07174 else 07175 v->routingedge->routing = g_list_remove(v->routingedge->routing, v); 07176 } 07177 07178 i = i->prev; 07179 } 07180 07181 route->pscore = route->score; 07182 route->ppath = route->path; 07183 remove_route(route->path); 07184 route->path = NULL; 07185 route->psrc = route->src; 07186 route->pdest = route->dest; 07187 //route->src->pc = route->src->c; 07188 //route->dest->pc = route->dest->c; 07189 } 07190 07191 void 07192 route_restore(toporouter_route_t *route) 07193 { 07194 GList *i; 07195 toporouter_vertex_t *pv = NULL; 07196 gint n = 0; 07197 07198 g_assert(route->ppath); 07199 g_assert(route->ppathindices); 07200 07201 route->path = route->ppath; 07202 i = route->ppath; 07203 while(i) { 07204 toporouter_vertex_t *v = TOPOROUTER_VERTEX(i->data); 07205 07206 if(v->routingedge) { 07207 if(TOPOROUTER_IS_CONSTRAINT(v->routingedge)) 07208 TOPOROUTER_CONSTRAINT(v->routingedge)->routing = g_list_insert(TOPOROUTER_CONSTRAINT(v->routingedge)->routing, v, route->ppathindices[n]); 07209 else 07210 v->routingedge->routing = g_list_insert(v->routingedge->routing, v, route->ppathindices[n]); 07211 07212 // space_edge(v->routingedge, NULL); 07213 } 07214 07215 if(pv) { 07216 pv->child = v; 07217 v->parent = pv; 07218 } 07219 07220 n++; 07221 pv = v; 07222 i = i->next; 07223 } 07224 07225 route->score = route->pscore; 07226 route->src = route->psrc; 07227 route->dest = route->pdest; 07228 //route->src->c = route->src->pc; 07229 //route->dest->c = route->dest->pc; 07230 07231 } 07232 07233 void 07234 cluster_merge(toporouter_route_t *routedata) 07235 { 07236 gint oldc = routedata->dest->c, newc = routedata->src->c; 07237 07238 FOREACH_CLUSTER(routedata->netlist->clusters) { 07239 if(cluster->c == oldc) 07240 cluster->c = newc; 07241 } FOREACH_END; 07242 07243 } 07244 07245 void 07246 netlist_recalculate(toporouter_netlist_t *netlist, GList *ignore) 07247 { 07248 GList *i = g_list_last(netlist->routed); 07249 gint n = netlist->clusters->len-1; 07250 07251 FOREACH_CLUSTER(netlist->clusters) { 07252 cluster->c = n--; 07253 } FOREACH_END; 07254 07255 while(i) { 07256 if(!ignore || !g_list_find(ignore, i->data)) cluster_merge(TOPOROUTER_ROUTE(i->data)); 07257 i = i->prev; 07258 } 07259 07260 } 07261 07262 void 07263 netlists_recalculate(GList *netlists, GList *ignore) 07264 { 07265 GList *i = netlists; 07266 while(i) { 07267 netlist_recalculate(TOPOROUTER_NETLIST(i->data), ignore); 07268 i = i->next; 07269 } 07270 } 07271 07272 void 07273 netlists_rollback(GList *netlists) 07274 { 07275 // netlists_recalculate(netlists, NULL); 07276 while(netlists) { 07277 toporouter_netlist_t *netlist = TOPOROUTER_NETLIST(netlists->data); 07278 07279 FOREACH_CLUSTER(netlist->clusters) { 07280 cluster->c = cluster->pc; 07281 } FOREACH_END; 07282 07283 netlists = netlists->next; 07284 } 07285 } 07286 07287 void 07288 print_netlist(toporouter_netlist_t *netlist) 07289 { 07290 07291 printf("NETLIST %s: ", netlist->netlist); 07292 07293 FOREACH_CLUSTER(netlist->clusters) { 07294 printf("%d ", cluster->c); 07295 07296 } FOREACH_END; 07297 printf("\n"); 07298 } 07299 07300 #define REMOVE_ROUTING(x) x->netlist->routed = g_list_remove(x->netlist->routed, x); \ 07301 r->routednets = g_list_remove(r->routednets, x); \ 07302 r->failednets = g_list_prepend(r->failednets, x) 07303 07304 #define INSERT_ROUTING(x) x->netlist->routed = g_list_prepend(x->netlist->routed, x); \ 07305 r->routednets = g_list_prepend(r->routednets, x); \ 07306 r->failednets = g_list_remove(r->failednets, x) 07307 07308 gint 07309 roar_route(toporouter_t *r, toporouter_route_t *routedata, gint threshold) 07310 { 07311 gint intfails = 0; 07312 GList *netlists = NULL, *routed = NULL; 07313 07314 g_assert(!routedata->path); 07315 07316 if(routedata->src->c == routedata->dest->c) { 07317 printf("ERROR: attempt to route already complete route\n"); 07318 g_assert(routedata->src->c != routedata->dest->c); 07319 } 07320 07321 routedata->src->pc = routedata->src->c; 07322 routedata->dest->pc = routedata->dest->c; 07323 routedata->psrc = routedata->src; 07324 routedata->pdest = routedata->dest; 07325 07326 r->flags |= TOPOROUTER_FLAG_LEASTINVALID; 07327 if(route(r, routedata, 0)) { 07328 GList *conflicts, *j; 07329 07330 INSERT_ROUTING(routedata); 07331 07332 conflicts = route_conflicts(routedata); 07333 cluster_merge(routedata); 07334 07335 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID; 07336 07337 j = conflicts; 07338 while(j) { 07339 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data); 07340 if(!g_list_find(netlists, conflict->netlist)) 07341 netlists = g_list_prepend(netlists, conflict->netlist); 07342 07343 route_checkpoint(conflict, routedata); 07344 07345 REMOVE_ROUTING(conflict); 07346 j = j->next; 07347 } 07348 07349 netlists = g_list_prepend(netlists, routedata->netlist); 07350 netlists_recalculate(netlists, NULL); 07351 07352 j = conflicts; 07353 while(j) { 07354 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data); 07355 g_assert(conflict->src->c != conflict->dest->c); 07356 if(route(r, conflict, 0)) { 07357 cluster_merge(conflict); 07358 07359 routed = g_list_prepend(routed, conflict); 07360 07361 INSERT_ROUTING(conflict); 07362 07363 netlist_recalculate(conflict->netlist, NULL); 07364 07365 }else{ 07366 if(++intfails >= threshold) { 07367 GList *i = routed; 07368 while(i) { 07369 toporouter_route_t *intconflict = TOPOROUTER_ROUTE(i->data); 07370 REMOVE_ROUTING(intconflict); 07371 delete_route(intconflict, 1); 07372 i = i->next; 07373 } 07374 delete_route(routedata, 1); 07375 i = g_list_last(conflicts); 07376 while(i) { 07377 toporouter_route_t *intconflict = TOPOROUTER_ROUTE(i->data); 07378 07379 route_restore(intconflict); 07380 INSERT_ROUTING(intconflict); 07381 07382 i = i->prev; 07383 } 07384 REMOVE_ROUTING(routedata); 07385 intfails = 0; 07386 netlists_recalculate(netlists, NULL); 07387 goto roar_route_end; 07388 } 07389 07390 } 07391 j = j->next; 07392 } 07393 07394 07395 netlists_recalculate(netlists, NULL); 07396 07397 intfails--; 07398 roar_route_end: 07399 g_list_free(conflicts); 07400 g_list_free(netlists); 07401 07402 }else{ 07403 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID; 07404 } 07405 07406 g_list_free(routed); 07407 return intfails; 07408 } 07409 07410 gint 07411 roar_router(toporouter_t *r, gint failcount, gint threshold) 07412 { 07413 gint pfailcount = failcount +1; 07414 07415 Message(_("ROAR router: ")); 07416 for(guint j=0;j<6;j++) { 07417 GList *failed = g_list_copy(r->failednets), *k = failed; 07418 07419 k = failed; 07420 while(k) { 07421 failcount += roar_route(r, TOPOROUTER_ROUTE(k->data), threshold); 07422 k = k->next; 07423 } 07424 g_list_free(failed); 07425 07426 printf("\tROAR pass %d - %d routed - %d failed\n", j, g_list_length(r->routednets), g_list_length(r->failednets)); 07427 07428 if(!failcount || failcount >= pfailcount) { 07429 Message(_("%d nets remaining\n"), failcount); 07430 break; 07431 } 07432 Message(_("%d -> "), failcount); 07433 pfailcount = failcount; 07434 } 07435 07436 return failcount; 07437 } 07438 07439 gint 07440 route_detour_compare(toporouter_route_t **a, toporouter_route_t **b) 07441 { return ((*b)->score - (*b)->detourscore) - ((*a)->score - (*a)->detourscore); } 07442 07443 07444 07445 void 07446 roar_detour_route(toporouter_t *r, toporouter_route_t *data) 07447 { 07448 gdouble pscore = data->score, nscore = 0.; 07449 GList *netlists = NULL; 07450 07451 route_checkpoint(data, NULL); 07452 07453 REMOVE_ROUTING(data); 07454 07455 netlists = g_list_prepend(NULL, data->netlist); 07456 netlists_recalculate(netlists, NULL); 07457 07458 r->flags |= TOPOROUTER_FLAG_LEASTINVALID; 07459 if(route(r, data, 0)) { 07460 GList *conflicts, *j; 07461 07462 nscore = data->score; 07463 conflicts = route_conflicts(data); 07464 07465 INSERT_ROUTING(data); 07466 07467 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID; 07468 07469 j = conflicts; 07470 while(j) { 07471 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data); 07472 07473 if(!g_list_find(netlists, conflict->netlist)) 07474 netlists = g_list_prepend(netlists, conflict->netlist); 07475 pscore += conflict->score; 07476 07477 route_checkpoint(conflict, NULL); 07478 REMOVE_ROUTING(conflict); 07479 07480 j = j->next; 07481 } 07482 netlists_recalculate(netlists, NULL); 07483 07484 j = conflicts; 07485 while(j) { 07486 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data); 07487 07488 if(route(r, conflict, 0)) { 07489 cluster_merge(conflict); 07490 INSERT_ROUTING(conflict); 07491 nscore += conflict->score; 07492 }else{ 07493 j = j->prev; 07494 goto roar_detour_route_rollback_int; 07495 } 07496 j = j->next; 07497 } 07498 07499 if(nscore > pscore) { 07500 j = g_list_last(conflicts); 07501 roar_detour_route_rollback_int: 07502 REMOVE_ROUTING(data); 07503 07504 while(j) { 07505 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data); 07506 REMOVE_ROUTING(conflict); 07507 delete_route(conflict, 1); 07508 j = j->prev; 07509 } 07510 07511 j = g_list_last(conflicts); 07512 while(j) { 07513 toporouter_route_t *conflict = TOPOROUTER_ROUTE(j->data); 07514 route_restore(conflict); 07515 INSERT_ROUTING(conflict); 07516 j = j->prev; 07517 } 07518 delete_route(data, 1); 07519 07520 goto roar_detour_route_rollback_exit; 07521 07522 } 07523 07524 g_list_free(conflicts); 07525 }else{ 07526 r->flags &= ~TOPOROUTER_FLAG_LEASTINVALID; 07527 roar_detour_route_rollback_exit: 07528 route_restore(data); 07529 INSERT_ROUTING(data); 07530 } 07531 netlists_recalculate(netlists, NULL); 07532 07533 g_list_free(netlists); 07534 } 07535 07536 void 07537 detour_router(toporouter_t *r) 07538 { 07539 GList *i = r->routednets; 07540 guint n = g_list_length(r->routednets); 07541 GPtrArray* scores = g_ptr_array_sized_new(n); 07542 07543 while(i) { 07544 toporouter_route_t *curroute = TOPOROUTER_ROUTE(i->data); 07545 curroute->score = path_score(r, curroute->path); 07546 g_ptr_array_add(scores, i->data); 07547 i = i->next; 07548 } 07549 07550 g_ptr_array_sort(scores, (GCompareFunc) route_detour_compare); 07551 07552 r->flags |= TOPOROUTER_FLAG_DETOUR; 07553 07554 for(toporouter_route_t **i = (toporouter_route_t **) scores->pdata; i < (toporouter_route_t **) scores->pdata + scores->len; i++) { 07555 toporouter_route_t *curroute = (*i); 07556 07557 if(isfinite(curroute->score) && isfinite(curroute->detourscore)) { 07558 // printf("%15s %15f \t %8f,%8f - %8f,%8f\n", (*i)->src->netlist + 2, (*i)->score - (*i)->detourscore, 07559 // vx(curroute->mergebox1->point), vy(curroute->mergebox1->point), 07560 // vx(curroute->mergebox2->point), vy(curroute->mergebox2->point)); 07561 07562 if(curroute->score - curroute->detourscore > ROAR_DETOUR_THRESHOLD) { 07563 roar_detour_route(r, curroute); 07564 }else break; 07565 07566 } 07567 } 07568 printf("\n"); 07569 07570 r->flags ^= TOPOROUTER_FLAG_DETOUR; 07571 07572 g_ptr_array_free(scores, TRUE); 07573 07574 } 07575 07576 gint 07577 rubix_router(toporouter_t *r, gint failcount) 07578 { 07579 GList *i, *ordering; 07580 order_nets_preroute_greedy(r, r->failednets, &ordering); 07581 07582 i = ordering; 07583 while(i) { 07584 toporouter_route_t *data = TOPOROUTER_ROUTE(i->data); 07585 07586 if(route(r, data, 0)) { 07587 INSERT_ROUTING(data); 07588 cluster_merge(data); 07589 failcount--; 07590 } 07591 07592 i = i->next; 07593 } 07594 07595 g_list_free(ordering); 07596 07597 return failcount; 07598 } 07599 07600 guint 07601 hybrid_router(toporouter_t *r) 07602 { 07603 gint failcount = g_list_length(r->failednets); 07604 r->flags |= TOPOROUTER_FLAG_AFTERORDER; 07605 r->flags |= TOPOROUTER_FLAG_AFTERRUBIX; 07606 failcount = rubix_router(r, failcount); 07607 07608 Message(_("RUBIX router: %d nets remaining\n"), failcount); 07609 printf(_("RUBIX router: %d nets remaining\n"), failcount); 07610 07611 r->flags |= TOPOROUTER_FLAG_GOFAR; 07612 07613 for(guint i=0;i<6 && failcount;i++) { 07614 if(i % 2 == 1) { 07615 failcount = roar_router(r, failcount, 5); 07616 // printf("THRESH 5\n"); 07617 }else{ 07618 failcount = roar_router(r, failcount, 2); 07619 // printf("THRESH 2\n"); 07620 } 07621 07622 detour_router(r); 07623 } 07624 07625 failcount = roar_router(r, failcount, 2); 07626 detour_router(r); 07627 07628 return failcount; 07629 } 07630 07631 void 07632 parse_arguments(toporouter_t *r, int argc, char **argv) 07633 { 07634 int i, tempint; 07635 for(i=0;i<argc;i++) { 07636 if(sscanf(argv[i], "viacost=%d", &tempint)) { 07637 /* XXX: We should be using PCB's generic value with unit parsing here */ 07638 r->viacost = (double)tempint; 07639 }else if(sscanf(argv[i], "l%d", &tempint)) { 07640 gdouble *layer = (gdouble *)malloc(sizeof(gdouble)); 07641 *layer = (double)tempint; 07642 r->keepoutlayers = g_list_prepend(r->keepoutlayers, layer); 07643 } 07644 } 07645 07646 for (guint group = 0; group < max_group; group++) 07647 for (i = 0; i < PCB->LayerGroups.Number[group]; i++) 07648 if ((PCB->LayerGroups.Entries[group][i] < max_copper_layer) && !(PCB->Data->Layer[PCB->LayerGroups.Entries[group][i]].On)) { 07649 gdouble *layer = (gdouble *)malloc(sizeof(gdouble)); 07650 *layer = (double)group; 07651 r->keepoutlayers = g_list_prepend(r->keepoutlayers, layer); 07652 } 07653 07654 } 07655 07656 toporouter_t * 07657 toporouter_new(void) 07658 { 07659 toporouter_t *r = (toporouter_t *)calloc(1, sizeof(toporouter_t)); 07660 time_t ltime; 07661 07662 gettimeofday(&r->starttime, NULL); 07663 07664 r->netsort = netscore_pairwise_compare; 07665 07666 r->destboxes = NULL; 07667 r->consumeddestboxes = NULL; 07668 07669 r->paths = NULL; 07670 07671 r->layers = NULL; 07672 r->flags = 0; 07673 r->viacost = VIA_COST_AS_DISTANCE; 07674 07675 r->wiring_score = 0.; 07676 07677 r->bboxes = NULL; 07678 r->bboxtree = NULL; 07679 07680 r->netlists = g_ptr_array_new(); 07681 r->routes = g_ptr_array_new(); 07682 07683 r->keepoutlayers = NULL; 07684 07685 r->routednets = NULL; 07686 r->failednets = NULL; 07687 07688 ltime=time(NULL); 07689 07690 gts_predicates_init(); 07691 07692 Message(_("Topological Autorouter\n")); 07693 Message(_("Started %s"),asctime(localtime(<ime))); 07694 Message(_("-------------------------------------\n")); 07695 return r; 07696 } 07697 07698 void 07699 acquire_twonets(toporouter_t *r) 07700 { 07701 RAT_LOOP(PCB->Data); 07702 if( TEST_FLAG(SELECTEDFLAG, line) ) import_route(r, line); 07703 END_LOOP; 07704 // /* 07705 if(!r->routes->len) { 07706 RAT_LOOP(PCB->Data); 07707 import_route(r, line); 07708 END_LOOP; 07709 } 07710 // */ 07711 07712 } 07713 07714 toporouter_netlist_t * 07715 find_netlist_by_name(toporouter_t *r, char *name) 07716 { 07717 FOREACH_NETLIST(r->netlists) { 07718 if(!strcmp(netlist->netlist, name)) return netlist; 07719 } FOREACH_END; 07720 return NULL; 07721 } 07722 07723 gint 07724 toporouter_set_pair(toporouter_t *r, toporouter_netlist_t *n1, toporouter_netlist_t *n2) 07725 { 07726 if(!n1 || !n2) return 0; 07727 n1->pair = n2; 07728 n2->pair = n1; 07729 return 1; 07730 } 07731 07732 static int 07733 toporouter (int argc, char **argv, Coord x, Coord y) 07734 { 07735 toporouter_t *r = toporouter_new(); 07736 parse_arguments(r, argc, argv); 07737 import_geometry(r); 07738 acquire_twonets(r); 07739 07740 //if(!toporouter_set_pair(r, find_netlist_by_name(r, " DRAM_DQS_N"), find_netlist_by_name(r, " DRAM_DQS"))) { 07741 // printf("Couldn't associate pair\n"); 07742 //} 07743 07744 hybrid_router(r); 07745 /* 07746 for(gint i=0;i<groupcount();i++) { 07747 gts_surface_foreach_edge(r->layers[i].surface, space_edge, NULL); 07748 } 07749 { 07750 int i; 07751 for(i=0;i<groupcount();i++) { 07752 char buffer[256]; 07753 sprintf(buffer, "route%d.png", i); 07754 toporouter_draw_surface(r, r->layers[i].surface, buffer, 1024, 1024, 2, NULL, i, NULL); 07755 } 07756 } 07757 */ 07758 toporouter_export(r); 07759 toporouter_free(r); 07760 07761 SaveUndoSerialNumber (); 07762 DeleteRats (false); 07763 RestoreUndoSerialNumber (); 07764 AddAllRats (false, NULL); 07765 RestoreUndoSerialNumber (); 07766 IncrementUndoSerialNumber (); 07767 Redraw (); 07768 07769 return 0; 07770 } 07771 07772 static int 07773 escape (int argc, char **argv, Coord x, Coord y) 07774 { 07775 guint dir, viax, viay; 07776 gdouble pitch, dx, dy; 07777 07778 if(argc != 1) return 0; 07779 07780 dir = atoi(argv[0]); 07781 07782 07783 ALLPAD_LOOP(PCB->Data); 07784 { 07785 if( TEST_FLAG(SELECTEDFLAG, pad) ) { 07786 PinType *via; 07787 LineType *line; 07788 07789 PadType *pad0 = element->Pad->data; 07790 PadType *pad1 = g_list_next (element->Pad)->data; 07791 07792 pitch = hypot (pad0->Point1.X - pad1->Point1.X, pad0->Point1.Y - pad1->Point1.Y); 07793 07794 dx = pitch / 2; 07795 dy = pitch / 2; 07796 07797 switch(dir) { 07798 case 1: 07799 viax = pad->Point1.X - dx; 07800 viay = pad->Point1.Y + dy; 07801 break; 07802 case 3: 07803 viax = pad->Point1.X + dx; 07804 viay = pad->Point1.Y + dy; 07805 break; 07806 case 9: 07807 viax = pad->Point1.X + dx; 07808 viay = pad->Point1.Y - dy; 07809 break; 07810 case 7: 07811 viax = pad->Point1.X - dx; 07812 viay = pad->Point1.Y - dy; 07813 break; 07814 case 2: 07815 viax = pad->Point1.X; 07816 viay = pad->Point1.Y + dy; 07817 break; 07818 case 8: 07819 viax = pad->Point1.X; 07820 viay = pad->Point1.Y - dy; 07821 break; 07822 case 4: 07823 viax = pad->Point1.X - dx; 07824 viay = pad->Point1.Y; 07825 break; 07826 case 6: 07827 viax = pad->Point1.X + dx; 07828 viay = pad->Point1.Y; 07829 break; 07830 default: 07831 printf("ERROR: escape() with bad direction (%d)\n", dir); 07832 return 1; 07833 } 07834 07835 if ((via = CreateNewVia (PCB->Data, viax, viay, 07836 Settings.ViaThickness, 2 * Settings.Keepaway, 07837 0, Settings.ViaDrillingHole, NULL, 07838 NoFlags ())) != NULL) 07839 { 07840 AddObjectToCreateUndoList (VIA_TYPE, via, via, via); 07841 // if (gui->shift_is_pressed ()) 07842 // ChangeObjectThermal (VIA_TYPE, via, via, via, PCB->ThermStyle); 07843 DrawVia (via); 07844 if((line = CreateDrawnLineOnLayer (CURRENT, pad->Point1.X + 1., pad->Point1.Y + 1., viax + 1., viay + 1., 07845 Settings.LineThickness, 2 * Settings.Keepaway, 07846 NoFlags()))) 07847 { 07848 07849 AddObjectToCreateUndoList (LINE_TYPE, CURRENT, line, line); 07850 DrawLine (CURRENT, line); 07851 07852 } 07853 07854 } 07855 07856 } 07857 } 07858 END_LOOP; 07859 END_LOOP; 07860 07861 IncrementUndoSerialNumber (); 07862 Draw (); 07863 return 0; 07864 } 07865 07866 static HID_Action toporouter_action_list[] = { 07867 {"Escape", N_("Select a set of pads"), escape, 07868 N_("Pad escape"), N_("Escape()")}, 07869 {"Toporouter", N_("Select net(s)"), toporouter, 07870 N_("Topological autorouter"), N_("Toporouter()")} 07871 }; 07872 07873 REGISTER_ACTIONS (toporouter_action_list) 07874 07875 void hid_toporouter_init() 07876 { 07877 register_toporouter_action_list(); 07878 } 07879