FreeCalypso > hg > ueda-linux
comparison ueda/libuschem/graphnets.c @ 0:cd92449fdb51
initial import of ueda and ifctf-part-lib from ifctfvax CVS
| author | Space Falcon <falcon@ivan.Harhan.ORG> |
|---|---|
| date | Mon, 20 Jul 2015 00:24:37 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:cd92449fdb51 |
|---|---|
| 1 /* | |
| 2 * preen_graphnets() functionality | |
| 3 */ | |
| 4 | |
| 5 #include <sys/types.h> | |
| 6 #include <stdio.h> | |
| 7 #include <strings.h> | |
| 8 #include "schemstruct.h" | |
| 9 #include "graphsym.h" | |
| 10 | |
| 11 extern char *malloc(); | |
| 12 | |
| 13 extern struct graphsym_pininst *find_comp_pininst(); | |
| 14 extern struct graphsym_pininst *find_pin_by_coord(); | |
| 15 | |
| 16 static struct schem *schem_being_preened; | |
| 17 static int dowarn, docorrect, severe_err; | |
| 18 | |
| 19 static int | |
| 20 tjoin_hit_check(obj, tjoin) | |
| 21 struct schemobj *obj; | |
| 22 register struct netpoint *tjoin; | |
| 23 { | |
| 24 register struct netpoint *netpt, *nextpt; | |
| 25 | |
| 26 for (netpt = obj->netobj_points; netpt && (nextpt = netpt->netpt_next); | |
| 27 netpt = nextpt) { | |
| 28 if (!netpt->netpt_coord_valid || !nextpt->netpt_coord_valid) { | |
| 29 fprintf(stderr, | |
| 30 "%s: line %d: Pin w/o coordinates impedes search for Tjoin antecedent\n", | |
| 31 schem_being_preened->orig_filename, | |
| 32 obj->obj_lineno); | |
| 33 severe_err = -1; | |
| 34 return(-1); | |
| 35 } | |
| 36 /* check for horizontal segments */ | |
| 37 if (netpt->netpt_y == tjoin->netpt_y && | |
| 38 nextpt->netpt_y == tjoin->netpt_y) { | |
| 39 if (tjoin->netpt_x > netpt->netpt_x && | |
| 40 tjoin->netpt_x < nextpt->netpt_x) | |
| 41 return(1); | |
| 42 if (tjoin->netpt_x < netpt->netpt_x && | |
| 43 tjoin->netpt_x > nextpt->netpt_x) | |
| 44 return(1); | |
| 45 } | |
| 46 /* check for vertical segments */ | |
| 47 if (netpt->netpt_x == tjoin->netpt_x && | |
| 48 nextpt->netpt_x == tjoin->netpt_x) { | |
| 49 if (tjoin->netpt_y > netpt->netpt_y && | |
| 50 tjoin->netpt_y < nextpt->netpt_y) | |
| 51 return(1); | |
| 52 if (tjoin->netpt_y < netpt->netpt_y && | |
| 53 tjoin->netpt_y > nextpt->netpt_y) | |
| 54 return(1); | |
| 55 } | |
| 56 } | |
| 57 return(0); | |
| 58 } | |
| 59 | |
| 60 static struct schemobj * | |
| 61 find_grouphead_tail(ghead) | |
| 62 register struct schemobj *ghead; | |
| 63 { | |
| 64 register struct schemobj *obj, *next; | |
| 65 | |
| 66 for (obj = ghead; ; obj = next) { | |
| 67 next = obj->obj_next; | |
| 68 if (next->obj_type != OBJTYPE_GRAPHNET) | |
| 69 return(obj); | |
| 70 if (next->netobj_grouphead != ghead) | |
| 71 return(obj); | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 static | |
| 76 preen_tjoin(obj, netpt, first, got_tjoin) | |
| 77 struct schemobj *obj; | |
| 78 register struct netpoint *netpt; | |
| 79 int first, *got_tjoin; | |
| 80 { | |
| 81 register struct schem *schem; | |
| 82 register struct schemobj *prevobj; | |
| 83 struct schemobj *ghead; | |
| 84 register int c; | |
| 85 | |
| 86 schem = schem_being_preened; | |
| 87 if (first) | |
| 88 *got_tjoin = 1; | |
| 89 else if (!netpt->netpt_next) { | |
| 90 if (*got_tjoin) { | |
| 91 fprintf(stderr, | |
| 92 "%s: line %d: Tjoin on both ends of a GraphNet is illegal\n", | |
| 93 schem->orig_filename, obj->obj_lineno); | |
| 94 severe_err = -1; | |
| 95 return; | |
| 96 } | |
| 97 *got_tjoin = 1; | |
| 98 } else { | |
| 99 fprintf(stderr, | |
| 100 "%s: line %d: Tjoin in the middle of a GraphNet is meaningless\n", | |
| 101 schem->orig_filename, obj->obj_lineno); | |
| 102 severe_err = -1; | |
| 103 return; | |
| 104 } | |
| 105 for (prevobj = obj->obj_prev, c = 0; | |
| 106 prevobj != (struct schemobj *)schem; prevobj = prevobj->obj_prev) | |
| 107 if (prevobj->obj_type == OBJTYPE_GRAPHNET) { | |
| 108 c = tjoin_hit_check(prevobj, netpt); | |
| 109 if (c < 0) | |
| 110 return; | |
| 111 if (c) | |
| 112 break; | |
| 113 } | |
| 114 if (!c) { | |
| 115 fprintf(stderr, "%s: line %d: Tjoin antecedent not found\n", | |
| 116 schem->orig_filename, obj->obj_lineno); | |
| 117 severe_err = -1; | |
| 118 return; | |
| 119 } | |
| 120 netpt->netpt_tjoin_to = prevobj; | |
| 121 obj->netobj_grouphead = ghead = prevobj->netobj_grouphead; | |
| 122 /* netname logic */ | |
| 123 if (obj->netobj_netname) { | |
| 124 /* accumulate on the group head */ | |
| 125 if (!ghead->netobj_netname) | |
| 126 ghead->netobj_netname = obj->netobj_netname; | |
| 127 else if (strcmp(ghead->netobj_netname, obj->netobj_netname)) { | |
| 128 fprintf(stderr, | |
| 129 "%s: line %d: Tjoin connects two netnames: %s and %s\n", | |
| 130 schem->orig_filename, obj->obj_lineno, | |
| 131 ghead->netobj_netname, obj->netobj_netname); | |
| 132 severe_err = -1; | |
| 133 return; | |
| 134 } | |
| 135 } | |
| 136 /* shuffling around to bring groups together */ | |
| 137 prevobj = obj->obj_prev; | |
| 138 if (prevobj->obj_type != OBJTYPE_GRAPHNET || | |
| 139 prevobj->netobj_grouphead != ghead) { | |
| 140 prevobj = find_grouphead_tail(ghead); | |
| 141 schemobj_unlink(obj); | |
| 142 schemobj_insert_after(prevobj, obj); | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 static | |
| 147 preen_pin(obj, netpt) | |
| 148 struct schemobj *obj; | |
| 149 register struct netpoint *netpt; | |
| 150 { | |
| 151 register int i = 0, c; | |
| 152 struct graphsym_pininst *pinc, *pinn; | |
| 153 struct schemobj *comp; | |
| 154 char *soughtpin; | |
| 155 int bynum; | |
| 156 | |
| 157 if (netpt->netpt_coord_valid) { | |
| 158 i |= 2; | |
| 159 pinc = find_pin_by_coord(schem_being_preened, netpt->netpt_x, | |
| 160 netpt->netpt_y); | |
| 161 } | |
| 162 if (netpt->netpt_pin_nameref) { | |
| 163 i |= 1; | |
| 164 c = parse_pin_nameref(schem_being_preened, obj->obj_lineno, | |
| 165 netpt->netpt_pin_nameref, &comp, | |
| 166 &soughtpin, &bynum); | |
| 167 if (c < 0) | |
| 168 severe_err = -1; | |
| 169 } | |
| 170 switch (i) { | |
| 171 case 1: | |
| 172 if (dowarn) | |
| 173 fprintf(stderr, | |
| 174 "%s: line %d: Pin w/o coordinates, run uschem-rewrite -g to fix\n", | |
| 175 schem_being_preened->orig_filename, | |
| 176 obj->obj_lineno); | |
| 177 if (c < 0) | |
| 178 return; | |
| 179 if (!comp->compobj_isgraph) { | |
| 180 nograph: fprintf(stderr, | |
| 181 "%s: line %d: %s: GraphNet refers to a non-graphical component\n", | |
| 182 schem_being_preened->orig_filename, | |
| 183 obj->obj_lineno, netpt->netpt_pin_nameref); | |
| 184 severe_err = -1; | |
| 185 return; | |
| 186 } | |
| 187 pinn = find_comp_pininst(comp, soughtpin, bynum); | |
| 188 if (!pinn) { | |
| 189 pinnotfound: fprintf(stderr, "%s: line %d: %s: pin not found\n", | |
| 190 schem_being_preened->orig_filename, | |
| 191 obj->obj_lineno, netpt->netpt_pin_nameref); | |
| 192 severe_err = -1; | |
| 193 return; | |
| 194 } | |
| 195 /* fix it */ | |
| 196 netpt->netpt_x = pinn->x; | |
| 197 netpt->netpt_y = pinn->y; | |
| 198 netpt->netpt_coord_valid = 1; | |
| 199 return; | |
| 200 case 2: | |
| 201 if (dowarn) | |
| 202 fprintf(stderr, | |
| 203 "%s: line %d: Pin given by coordinates only, run uschem-rewrite -g to fix\n", | |
| 204 schem_being_preened->orig_filename, | |
| 205 obj->obj_lineno); | |
| 206 if (!pinc) { | |
| 207 fprintf(stderr, | |
| 208 "%s: line %d: no pin found at (%d,%d)\n", | |
| 209 schem_being_preened->orig_filename, | |
| 210 obj->obj_lineno, netpt->netpt_x, | |
| 211 netpt->netpt_y); | |
| 212 severe_err = -1; | |
| 213 return; | |
| 214 } | |
| 215 comp = pinc->compinst; | |
| 216 if (comp->obj_type != OBJTYPE_COMPINST) { | |
| 217 fprintf(stderr, | |
| 218 "%s: line %d: Pin refers to a non-component\n", | |
| 219 schem_being_preened->orig_filename, | |
| 220 obj->obj_lineno); | |
| 221 severe_err = -1; | |
| 222 return; | |
| 223 } | |
| 224 if (!docorrect) | |
| 225 return; | |
| 226 if (pinc->pindef->gspd_pinname) { | |
| 227 soughtpin = pinc->pindef->gspd_pinname; | |
| 228 bynum = 0; | |
| 229 } else if (pinc->pindef->gspd_pinnumber) { | |
| 230 soughtpin = pinc->pindef->gspd_pinnumber; | |
| 231 bynum = 1; | |
| 232 } else { | |
| 233 fprintf(stderr, | |
| 234 "%s: %s pin at (%d,%d) has no pinname or pinnumber attribute\n", | |
| 235 schem_being_preened->orig_filename, | |
| 236 comp->compobj_instname, netpt->netpt_x, | |
| 237 netpt->netpt_y); | |
| 238 severe_err = -1; | |
| 239 return; | |
| 240 } | |
| 241 netpt->netpt_pin_nameref = | |
| 242 malloc(strlen(comp->compobj_instname) + | |
| 243 strlen(soughtpin) + 2); | |
| 244 if (!netpt->netpt_pin_nameref) { | |
| 245 perror("malloc"); | |
| 246 exit(1); | |
| 247 } | |
| 248 sprintf(netpt->netpt_pin_nameref, "%s%c%s", | |
| 249 comp->compobj_instname, bynum ? '-' : '.', soughtpin); | |
| 250 return; | |
| 251 case 3: | |
| 252 if (!dowarn || c < 0) | |
| 253 return; | |
| 254 if (!comp->compobj_isgraph) | |
| 255 goto nograph; | |
| 256 pinn = find_comp_pininst(comp, soughtpin, bynum); | |
| 257 if (!pinn) | |
| 258 goto pinnotfound; | |
| 259 if (pinc != pinn) | |
| 260 fprintf(stderr, | |
| 261 "%s: line %d: Pin(%d,%d)=%s: pin name and coordinates don't match\n", | |
| 262 schem_being_preened->orig_filename, | |
| 263 obj->obj_lineno, netpt->netpt_x, netpt->netpt_y, | |
| 264 netpt->netpt_pin_nameref); | |
| 265 return; | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 static | |
| 270 preen_pseudopin(obj, netpt) | |
| 271 struct schemobj *obj; | |
| 272 register struct netpoint *netpt; | |
| 273 { | |
| 274 register struct graphsym_pininst *pin; | |
| 275 register struct schemobj *ghead; | |
| 276 | |
| 277 pin = find_pin_by_coord(schem_being_preened, netpt->netpt_x, | |
| 278 netpt->netpt_y); | |
| 279 if (!pin) { | |
| 280 fprintf(stderr, "%s: line %d: no pin found at (%d,%d)\n", | |
| 281 schem_being_preened->orig_filename, obj->obj_lineno, | |
| 282 netpt->netpt_x, netpt->netpt_y); | |
| 283 severe_err = -1; | |
| 284 return; | |
| 285 } | |
| 286 if (pin->compinst->obj_type != OBJTYPE_GRAPHSYM) { | |
| 287 fprintf(stderr, | |
| 288 "%s: line %d: Pseudo refers to a real component pin (use Pin instead)\n", | |
| 289 schem_being_preened->orig_filename, obj->obj_lineno); | |
| 290 severe_err = -1; | |
| 291 return; | |
| 292 } | |
| 293 if (!pin->pindef->gspd_forcenet) | |
| 294 return; | |
| 295 obj->netobj_forcenets++; | |
| 296 ghead = obj->netobj_grouphead; | |
| 297 if (!ghead) | |
| 298 ghead = obj; | |
| 299 if (!ghead->netobj_netname) { | |
| 300 if (dowarn) | |
| 301 fprintf(stderr, | |
| 302 "%s: line %d: GraphNet needs to be forced to net %s (run uschem-rewrite -g to fix)\n", | |
| 303 schem_being_preened->orig_filename, | |
| 304 obj->obj_lineno, pin->pindef->gspd_forcenet); | |
| 305 if (docorrect) | |
| 306 ghead->netobj_netname = pin->pindef->gspd_forcenet; | |
| 307 } else if (strcmp(ghead->netobj_netname, pin->pindef->gspd_forcenet)) { | |
| 308 fprintf(stderr, | |
| 309 "%s: line %d: Graphnet %s is forced to net %s by a special symbol connection\n", | |
| 310 schem_being_preened->orig_filename, obj->obj_lineno, | |
| 311 ghead->netobj_netname, pin->pindef->gspd_forcenet); | |
| 312 severe_err = -1; | |
| 313 } | |
| 314 } | |
| 315 | |
| 316 static | |
| 317 do_graphnet(obj, do_tjoin, do_pins) | |
| 318 struct schemobj *obj; | |
| 319 { | |
| 320 register struct netpoint *netpt; | |
| 321 register int first; | |
| 322 int got_tjoin = 0; | |
| 323 | |
| 324 if (do_tjoin) | |
| 325 obj->netobj_grouphead = obj; /* for now at least */ | |
| 326 for (netpt = obj->netobj_points, first = 1; netpt; | |
| 327 netpt = netpt->netpt_next, first = 0) { | |
| 328 if (dowarn && first && !netpt->netpt_next) | |
| 329 fprintf(stderr, "%s: line %d: singular GraphNet\n", | |
| 330 schem_being_preened->orig_filename, | |
| 331 obj->obj_lineno); | |
| 332 switch (netpt->netpt_type) { | |
| 333 case NETPT_TYPE_TJOIN: | |
| 334 if (do_tjoin) | |
| 335 preen_tjoin(obj, netpt, first, &got_tjoin); | |
| 336 continue; | |
| 337 case NETPT_TYPE_PIN: | |
| 338 if (do_pins) | |
| 339 preen_pin(obj, netpt); | |
| 340 continue; | |
| 341 case NETPT_TYPE_PSEUDO: | |
| 342 if (do_pins) | |
| 343 preen_pseudopin(obj, netpt); | |
| 344 continue; | |
| 345 } | |
| 346 } | |
| 347 } | |
| 348 | |
| 349 preen_graphnets(schem, do_tjoin, do_pins, warn, correct) | |
| 350 struct schem *schem; | |
| 351 { | |
| 352 register struct schemobj *obj, *next; | |
| 353 | |
| 354 schem_being_preened = schem; | |
| 355 dowarn = warn; | |
| 356 docorrect = correct; | |
| 357 severe_err = 0; | |
| 358 for (obj = schem->obj_next; obj != (struct schemobj *)schem; | |
| 359 obj = next) { | |
| 360 next = obj->obj_next; | |
| 361 if (obj->obj_type == OBJTYPE_GRAPHNET) | |
| 362 do_graphnet(obj, do_tjoin, do_pins); | |
| 363 } | |
| 364 return(severe_err); | |
| 365 } |
