Go to most recent revision | Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 2 | mjames | 1 | /* $Id: equivalent.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $ */ |
| 2 | /* |
||
| 3 | * $Log: equivalent.c,v $ |
||
| 4 | * Revision 1.1.1.1 2003/11/04 23:34:57 mjames |
||
| 5 | * Imported into local repositrory |
||
| 6 | * |
||
| 7 | * Revision 1.9 2003/01/02 21:37:15 mjames |
||
| 8 | * Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L |
||
| 9 | * properties on the nets so that pin jumpers can be made without a problem. |
||
| 10 | * |
||
| 11 | * Still need to sort out pin assignments made to these not_routable nets |
||
| 12 | * which will become legal in some cases so that pullups and pulldown |
||
| 13 | * pins can be used on the FPGA. |
||
| 14 | * |
||
| 15 | * Revision 1.8 2002/09/09 10:26:56 mjames |
||
| 16 | * Removed set generic range and replaced it with a set generic value command |
||
| 17 | * that takes both integers and ranges. |
||
| 18 | * |
||
| 19 | * Revision 1.7 2002/01/15 12:36:22 mjames |
||
| 20 | * DLL declarations put in, |
||
| 21 | * |
||
| 22 | * #ident used |
||
| 23 | * |
||
| 24 | * Revision 1.6 2001/11/01 11:06:49 mjames |
||
| 25 | * Simplified code for connection of equivalent node sets to components |
||
| 26 | * |
||
| 27 | * Revision 1.5 2001/10/31 22:20:03 mjames |
||
| 28 | * Tidying up problematical comments caused by CVS |
||
| 29 | * 'intelligent' comment guessing |
||
| 30 | * |
||
| 31 | */ |
||
| 32 | |||
| 33 | /* This file handles equivalent pins , being passthroughs or |
||
| 34 | low value resistors which can be regarded as passthrough jumpers */ |
||
| 35 | |||
| 36 | /* Extracted from ACFREAD syntax : pin equivalences within a chip or template |
||
| 37 | declaration |
||
| 38 | |||
| 39 | |||
| 40 | pin_equivalence : EQUIVALENT LBRK { curr_equiv_list = begin_equivalent_pins(); } |
||
| 41 | equivalent_pins |
||
| 42 | RBRK end_item { check_equivalent_pins(current_chip,curr_equiv_list); } |
||
| 43 | ; |
||
| 44 | |||
| 45 | |||
| 46 | equivalent_pins : equivalent_pin SEMI equivalent_pins |
||
| 47 | | equivalent_pin |
||
| 48 | | |
||
| 49 | ; |
||
| 50 | |||
| 51 | |||
| 52 | equivalent_pin : astring { add_equivalent_pin( current_chip,curr_equiv_list,$1); }; |
||
| 53 | |||
| 54 | in2 : input_pin = a1; |
||
| 55 | in3 : input_pin = f1; |
||
| 56 | |||
| 57 | e.g. EQUIVALENT ( a1;f1); |
||
| 58 | |||
| 59 | */ |
||
| 60 | |||
| 61 | /* we approach the storage of nodes with caution , deferring the |
||
| 62 | adding of information until it is correct */ |
||
| 63 | |||
| 64 | #include "equivalent.h" |
||
| 65 | |||
| 66 | #include "cmdlog.h" |
||
| 67 | #include "cmdparse.h" |
||
| 68 | #include "database.h" |
||
| 69 | #include "expression.h" |
||
| 70 | #include "generic.h" |
||
| 71 | #include "jumpering.h" |
||
| 72 | #include "printout.h" |
||
| 73 | #include "vertcl_main.h" |
||
| 74 | |||
| 75 | #include <ctype.h> |
||
| 76 | #include <stdio.h> |
||
| 77 | #include <stdlib.h> |
||
| 78 | #include <string.h> |
||
| 79 | |||
| 80 | #ident \ |
||
| 81 | "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/equivalent.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $" |
||
| 82 | |||
| 83 | /********************************************************************/ |
||
| 84 | /* this function starts to create a list of equivalent pins */ |
||
| 85 | /********************************************************************/ |
||
| 86 | equivalent_node_set_t *begin_equivalent_pins (void) |
||
| 87 | { |
||
| 88 | equivalent_node_set_t *node_set; |
||
| 89 | node_set = calloc (1, sizeof (equivalent_node_set_t)); |
||
| 90 | return node_set; |
||
| 91 | } |
||
| 92 | |||
| 93 | /********************************************************************/ |
||
| 94 | /* add a pin to the list referred to by node_set */ |
||
| 95 | /********************************************************************/ |
||
| 96 | void add_equivalent_pin (socket_t *current_chip, equivalent_node_set_t *node_set, char *ident) |
||
| 97 | { |
||
| 98 | equivalent_node_t *ptr; |
||
| 99 | equivalent_node_t *equiv_node; |
||
| 100 | node_t *node; |
||
| 101 | if (!current_chip) |
||
| 102 | { |
||
| 103 | Log (LOG_ERROR, "-- Current chip not known for equivalent pin creation\n"); |
||
| 104 | return; |
||
| 105 | } |
||
| 106 | |||
| 107 | node = find_node (current_chip, Ident, ident, Create); |
||
| 108 | /* no pin called 'ident ?? */ |
||
| 109 | if ((level & 1) && !node) |
||
| 110 | { |
||
| 111 | Log ( |
||
| 112 | LOG_ERROR, |
||
| 113 | "-- Error : Pin Equivalent : cannot find pin %s(%s)\n", |
||
| 114 | current_chip->name, |
||
| 115 | ident); |
||
| 116 | return; |
||
| 117 | } |
||
| 118 | |||
| 119 | /* pin already equivalent to another ? */ |
||
| 120 | if ((level & 1) && node->equivalent_nodes) |
||
| 121 | { |
||
| 122 | Log ( |
||
| 123 | LOG_ERROR, |
||
| 124 | "-- Error : Pin Equivalent : pin %s(%s) already member of set\n", |
||
| 125 | current_chip->name, |
||
| 126 | ident); |
||
| 127 | return; |
||
| 128 | } |
||
| 129 | |||
| 130 | /* pin is acceptable so note it */ |
||
| 131 | equiv_node = calloc (1, sizeof (equivalent_node_t)); |
||
| 132 | if (!node_set->nodes) |
||
| 133 | { |
||
| 134 | /* new node */ |
||
| 135 | node_set->nodes = equiv_node; |
||
| 136 | } |
||
| 137 | else |
||
| 138 | { |
||
| 139 | ptr = node_set->nodes; |
||
| 140 | while (ptr->next) |
||
| 141 | ptr = ptr->next; |
||
| 142 | ptr->next = equiv_node; |
||
| 143 | } |
||
| 144 | equiv_node->node = node; |
||
| 145 | } |
||
| 146 | |||
| 147 | /********************************************************************/ |
||
| 148 | /* this function will verify the current list of nodes that are equivalent, and if there is |
||
| 149 | more than one in the list then it will add them to the equivalent node list of the |
||
| 150 | chip (if only one pin is equivalent to itself then it is a waste of time .... ) */ |
||
| 151 | /********************************************************************/ |
||
| 152 | void check_equivalent_pins (socket_t *current_chip, equivalent_node_set_t *node_set) |
||
| 153 | { |
||
| 154 | equivalent_node_t *curr_node, *prev; |
||
| 155 | |||
| 156 | int equiv_count; |
||
| 157 | |||
| 158 | if (!node_set) |
||
| 159 | return; |
||
| 160 | |||
| 161 | /* count equivalent nodes */ |
||
| 162 | curr_node = node_set->nodes; |
||
| 163 | equiv_count = 0; |
||
| 164 | while (curr_node) |
||
| 165 | { |
||
| 166 | equiv_count++; |
||
| 167 | curr_node = curr_node->next; |
||
| 168 | }; |
||
| 169 | |||
| 170 | /* delete info if not sufficent equivalent nodes */ |
||
| 171 | if (equiv_count < 2) |
||
| 172 | { |
||
| 173 | curr_node = node_set->nodes; |
||
| 174 | while (curr_node) |
||
| 175 | { |
||
| 176 | prev = curr_node; |
||
| 177 | curr_node = curr_node->next; |
||
| 178 | free (prev); |
||
| 179 | }; |
||
| 180 | free (node_set); |
||
| 181 | Log (LOG_ERROR, "-- Warning : insufficient equivalent pins in list\n"); |
||
| 182 | return; |
||
| 183 | } |
||
| 184 | |||
| 185 | /* join the list to the socket as it is now validated */ |
||
| 186 | curr_node = node_set->nodes; |
||
| 187 | while (curr_node) |
||
| 188 | { |
||
| 189 | /* flag each node as being a member of an equivalent set */ |
||
| 190 | curr_node->node->equivalent_nodes = node_set; |
||
| 191 | curr_node = curr_node->next; |
||
| 192 | } |
||
| 193 | |||
| 194 | /* add an additional equivalent node set */ |
||
| 195 | node_set->next = current_chip->equivalent_node_set; |
||
| 196 | current_chip->equivalent_node_set = node_set; |
||
| 197 | |||
| 198 | return; |
||
| 199 | } |
||
| 200 | |||
| 201 | /********************************************************************/ |
||
| 202 | |||
| 203 | void list_equivalent_pins (FILE *f, socket_t *dev) |
||
| 204 | { |
||
| 205 | int itemcnt; |
||
| 206 | equivalent_node_t *curr_node; |
||
| 207 | equivalent_node_set_t *curr_set; |
||
| 208 | |||
| 209 | curr_set = dev->equivalent_node_set; |
||
| 210 | |||
| 211 | while (curr_set) |
||
| 212 | { |
||
| 213 | if (curr_set->nodes) |
||
| 214 | { |
||
| 215 | curr_node = curr_set->nodes; |
||
| 216 | fprintf (f, " EQUIVALENT ( "); |
||
| 217 | itemcnt = 2; |
||
| 218 | while (curr_node) |
||
| 219 | { |
||
| 220 | if (curr_node->next) |
||
| 221 | { |
||
| 222 | fprintf (f, "%s; ", curr_node->node->identifier); |
||
| 223 | itemcnt++; |
||
| 224 | if (itemcnt > 6) |
||
| 225 | { |
||
| 226 | fprintf (f, "\n "); |
||
| 227 | itemcnt = 0; |
||
| 228 | } |
||
| 229 | } |
||
| 230 | else |
||
| 231 | fprintf (f, "%s);\n", curr_node->node->identifier); |
||
| 232 | curr_node = curr_node->next; |
||
| 233 | } |
||
| 234 | } |
||
| 235 | curr_set = curr_set->next; |
||
| 236 | } |
||
| 237 | } |
||
| 238 | |||
| 239 | /******************************************************************** |
||
| 240 | * copies the equivalent pins list from template to device instance * |
||
| 241 | * uses the functions above to ensure validation is consistently * |
||
| 242 | * performed |
||
| 243 | ********************************************************************/ |
||
| 244 | void copy_equivalent_pins (socket_t *template, socket_t *dev) |
||
| 245 | { |
||
| 246 | equivalent_node_t *curr_node; |
||
| 247 | equivalent_node_set_t *curr_set, *new_set; |
||
| 248 | |||
| 249 | /* trap use of template when none is actually given */ |
||
| 250 | if (!template || !dev) |
||
| 251 | return; |
||
| 252 | if (level & 1) |
||
| 253 | { |
||
| 254 | Log ( |
||
| 255 | LOG_GENERAL, |
||
| 256 | "copying equivalent pins from template %s to socket %s\n", |
||
| 257 | template->type, |
||
| 258 | dev->identifier); |
||
| 259 | } |
||
| 260 | curr_set = template->equivalent_node_set; |
||
| 261 | |||
| 262 | while (curr_set) |
||
| 263 | { |
||
| 264 | new_set = begin_equivalent_pins (); |
||
| 265 | /* create a set of equivalent pins to copy into */ |
||
| 266 | |||
| 267 | curr_node = curr_set->nodes; |
||
| 268 | |||
| 269 | while (curr_node) |
||
| 270 | { |
||
| 271 | add_equivalent_pin (dev, new_set, curr_node->node->identifier); |
||
| 272 | /* traverse list */ |
||
| 273 | curr_node = curr_node->next; |
||
| 274 | } |
||
| 275 | |||
| 276 | check_equivalent_pins (dev, new_set); |
||
| 277 | curr_set = curr_set->next; |
||
| 278 | } |
||
| 279 | } |
||
| 280 | |||
| 281 | /* function to jumper together all equivalent pins on a device : |
||
| 282 | at the moment it does not distinguish between EPLD and non -epld devices */ |
||
| 283 | /* the endpoint is a socket that may be used */ |
||
| 284 | void jumper_equivalent_pins (void) |
||
| 285 | { |
||
| 286 | char equiv_buff[MAXIDLEN]; |
||
| 287 | equivalent_node_t *curr_ref; |
||
| 288 | equivalent_node_set_t *node_set; |
||
| 289 | |||
| 290 | socket_t *dev; |
||
| 291 | |||
| 292 | net_t *top_net, *current_net; |
||
| 293 | |||
| 294 | dev = socket_head; |
||
| 295 | |||
| 296 | while (dev) |
||
| 297 | { |
||
| 298 | /* any equivalent pins */ |
||
| 299 | if (dev->equivalent_node_set) |
||
| 300 | { |
||
| 301 | #if defined DEBUG_EQUIV |
||
| 302 | Log ( |
||
| 303 | LOG_GENERAL, |
||
| 304 | "-- Device %s has equivalent pins\n", |
||
| 305 | dev->identifier); |
||
| 306 | #endif |
||
| 307 | node_set = dev->equivalent_node_set; |
||
| 308 | while (node_set) |
||
| 309 | { |
||
| 310 | /* create a top level jumper name made out device ID |
||
| 311 | concatenated with current pin IDs */ |
||
| 312 | sprintf (equiv_buff, "E_%s", dev->identifier); |
||
| 313 | curr_ref = node_set->nodes; |
||
| 314 | while (curr_ref) |
||
| 315 | { |
||
| 316 | current_net = curr_ref->node->net; |
||
| 317 | /* if there is a net attached to the pin it is a routed |
||
| 318 | net. |
||
| 319 | only make the jumper if it is actually a usable net |
||
| 320 | for routing. */ |
||
| 321 | if (current_net && |
||
| 322 | IS_ROUTABLE (current_net->how_routed)) |
||
| 323 | { |
||
| 324 | strcat (equiv_buff, "_"); |
||
| 325 | strcat ( |
||
| 326 | equiv_buff, curr_ref->node->identifier); |
||
| 327 | } |
||
| 328 | curr_ref = curr_ref->next; |
||
| 329 | } |
||
| 330 | |||
| 331 | /* printf("Making %s\n",equiv_buff); */ |
||
| 332 | top_net = find_net (&routed_list, Ident, equiv_buff, Create); |
||
| 333 | top_net->how_joined = Jumpered; |
||
| 334 | #if defined DEBUG_EQUIV |
||
| 335 | Log (LOG_GENERAL, "-- making jumper %s\n", equiv_buff); |
||
| 336 | #endif |
||
| 337 | curr_ref = node_set->nodes; |
||
| 338 | while (curr_ref) |
||
| 339 | { |
||
| 340 | current_net = curr_ref->node->net; |
||
| 341 | /* if there is a net attached to the pin it is a routed |
||
| 342 | net. |
||
| 343 | only make the jumper if it is actually a usable net |
||
| 344 | for routing. */ |
||
| 345 | if (current_net && |
||
| 346 | IS_ROUTABLE (current_net->how_routed)) |
||
| 347 | { |
||
| 348 | #if defined DEBUG_EQUIV |
||
| 349 | Log ( |
||
| 350 | LOG_GENERAL, |
||
| 351 | "-- connecting net %s ( pin %s(%s))\n", |
||
| 352 | curr_ref->node->net->identifier, |
||
| 353 | dev->identifier, |
||
| 354 | curr_ref->node->identifier); |
||
| 355 | #endif |
||
| 356 | current_net->external_node = |
||
| 357 | NULL; /* jumpered by net name */ |
||
| 358 | transfer_net_to_subnet ( |
||
| 359 | &routed_list, top_net, current_net); |
||
| 360 | } |
||
| 361 | |||
| 362 | curr_ref = curr_ref->next; |
||
| 363 | } |
||
| 364 | /* no child nets or jumper joins only one subnet : delete |
||
| 365 | * jumper */ |
||
| 366 | if (!top_net->subnets || !top_net->subnets->joined_nets) |
||
| 367 | disconnect_jumper (&routed_list, top_net); |
||
| 368 | |||
| 369 | node_set = node_set->next; |
||
| 370 | } |
||
| 371 | } |
||
| 372 | |||
| 373 | dev = dev->next; |
||
| 374 | } |
||
| 375 | } |