From e4bfe864ba9e3a351313dbb228f143be56d9dd91 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 4 Jun 2019 09:15:56 -0400 Subject: [PATCH 1/3] Modified the techfile "wiring" section to allow a scalefactor with the same interpretation as the scalefactor for the DRC section: Values in the section are interpreted as lambda divided by the scalefactor. That allows the wiring values to be real units such as nanometers and avoid problems with fractional lambda values. --- wiring/wireInt.h | 1 + wiring/wireOps.c | 42 +++++++++++++++++++++--------------------- wiring/wireTech.c | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/wiring/wireInt.h b/wiring/wireInt.h index ed5d5b4f..68a3c5c8 100644 --- a/wiring/wireInt.h +++ b/wiring/wireInt.h @@ -30,6 +30,7 @@ extern TileType WireType; extern int WireWidth; extern int WireLastDir; +extern int WireUnits; /* Undo procedure: */ diff --git a/wiring/wireOps.c b/wiring/wireOps.c index 41a249cd..57fb40e5 100644 --- a/wiring/wireOps.c +++ b/wiring/wireOps.c @@ -768,19 +768,19 @@ WireAddContact(newType, newWidth) if ((contact->con_layer1 == oldType) && (contact->con_layer2 == WireType)) { - oldOverlap = contact->con_surround1; - newOverlap = contact->con_surround2; - oldExtend = contact->con_extend1; - newExtend = contact->con_extend2; + oldOverlap = contact->con_surround1 / WireUnits; + newOverlap = contact->con_surround2 / WireUnits; + oldExtend = contact->con_extend1 / WireUnits; + newExtend = contact->con_extend2 / WireUnits; goto gotContact; } if ((contact->con_layer2 == oldType) && (contact->con_layer1 == WireType)) { - oldOverlap = contact->con_surround2; - newOverlap = contact->con_surround1; - oldExtend = contact->con_extend2; - newExtend = contact->con_extend1; + oldOverlap = contact->con_surround2 / WireUnits; + newOverlap = contact->con_surround1 / WireUnits; + oldExtend = contact->con_extend2 / WireUnits; + newExtend = contact->con_extend1 / WireUnits; goto gotContact; } } @@ -798,7 +798,7 @@ WireAddContact(newType, newWidth) */ gotContact: - totalSize = contact->con_size + 2 * oldOverlap; + totalSize = (contact->con_size / WireUnits) + 2 * oldOverlap; contactArea = oldLeg; if ((contactArea.r_xtop - contactArea.r_xbot) < totalSize) { @@ -848,7 +848,7 @@ WireAddContact(newType, newWidth) { TTMaskSetOnlyType(&mask, contact->con_layer1); TTMaskSetType(&allmask, contact->con_layer1); - GEO_EXPAND(&tmp, contact->con_surround1, &tmp2); + GEO_EXPAND(&tmp, contact->con_surround1 / WireUnits, &tmp2); (void) GeoInclude(&tmp2, &editArea); DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); } @@ -856,7 +856,7 @@ WireAddContact(newType, newWidth) { TTMaskSetOnlyType(&mask, contact->con_layer2); TTMaskSetType(&allmask, contact->con_layer2); - GEO_EXPAND(&tmp, contact->con_surround2, &tmp2); + GEO_EXPAND(&tmp, contact->con_surround2 / WireUnits, &tmp2); (void) GeoInclude(&tmp2, &editArea); DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); } @@ -869,13 +869,13 @@ WireAddContact(newType, newWidth) { case GEO_NORTH: case GEO_SOUTH: - tmp2.r_ybot -= contact->con_extend1; - tmp2.r_ytop += contact->con_extend1; + tmp2.r_ybot -= contact->con_extend1 / WireUnits; + tmp2.r_ytop += contact->con_extend1 / WireUnits; break; case GEO_EAST: case GEO_WEST: - tmp2.r_xbot -= contact->con_extend1; - tmp2.r_xtop += contact->con_extend1; + tmp2.r_xbot -= contact->con_extend1 / WireUnits; + tmp2.r_xtop += contact->con_extend1 / WireUnits; break; } (void) GeoInclude(&tmp2, &editArea); @@ -890,13 +890,13 @@ WireAddContact(newType, newWidth) { case GEO_NORTH: case GEO_SOUTH: - tmp2.r_xbot -= contact->con_extend2; - tmp2.r_xtop += contact->con_extend2; + tmp2.r_xbot -= contact->con_extend2 / WireUnits; + tmp2.r_xtop += contact->con_extend2 / WireUnits; break; case GEO_EAST: case GEO_WEST: - tmp2.r_ybot -= contact->con_extend2; - tmp2.r_ytop += contact->con_extend2; + tmp2.r_ybot -= contact->con_extend2 / WireUnits; + tmp2.r_ytop += contact->con_extend2 / WireUnits; break; } (void) GeoInclude(&tmp2, &editArea); @@ -923,13 +923,13 @@ WireAddContact(newType, newWidth) SelectArea(&scx, &mask, 0); if (contact->con_surround1 != 0) { - GEO_EXPAND(&tmp, contact->con_surround1, &scx.scx_area); + GEO_EXPAND(&tmp, contact->con_surround1 / WireUnits, &scx.scx_area); TTMaskSetOnlyType(&mask, contact->con_layer1); SelectArea(&scx, &mask, 0); } if (contact->con_surround2 != 0) { - GEO_EXPAND(&tmp, contact->con_surround2, &scx.scx_area); + GEO_EXPAND(&tmp, contact->con_surround2 / WireUnits, &scx.scx_area); TTMaskSetOnlyType(&mask, contact->con_layer2); SelectArea(&scx, &mask, 0); } diff --git a/wiring/wireTech.c b/wiring/wireTech.c index a857080b..7f49e9a9 100644 --- a/wiring/wireTech.c +++ b/wiring/wireTech.c @@ -37,6 +37,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ /* Linked list to store contact information collected by this module: */ Contact *WireContacts; +int WireUnits; // Units per lambda for wiring sizes /* @@ -65,6 +66,7 @@ WireTechInit() freeMagic((char *) WireContacts); WireContacts = WireContacts->con_next; } + WireUnits = 1; } /* @@ -93,6 +95,21 @@ WireTechLine(sectionName, argc, argv) Contact *new; int hasExtend = 0; + if (!strcmp(argv[0], "scalefactor")) + { + if (argc != 2) + { + TechError("\"scalefactor\" line must have exactly 2 arguments.\n"); + return TRUE; + } + if (!StrIsInt(argv[1])) + { + TechError("\"scalefactor\" argument must be an integer.\n"); + return TRUE; + } + WireUnits = atoi(argv[1]); + } + if (strcmp(argv[0], "contact") != 0) { TechError("Unknown wiring keyword: %s. Line ignored.\n", argv[0]); From 8170dbe01f9f7af2e0f6dd0a2f3c5025394eed33 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 4 Jun 2019 12:13:47 -0400 Subject: [PATCH 2/3] Additional corrections to the wiring for some code changes that were made where contacts are placed when shifting up on metal layer but not made for the reverse case. Also corrected one inconsistency with non-minimum width wires. --- commands/CmdTZ.c | 4 +- wiring/wireOps.c | 135 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 104 insertions(+), 35 deletions(-) diff --git a/commands/CmdTZ.c b/commands/CmdTZ.c index 3065450d..36969938 100644 --- a/commands/CmdTZ.c +++ b/commands/CmdTZ.c @@ -1348,7 +1348,7 @@ CmdWire(w, cmd) case DECREMENT: if (cmd->tx_argc != 3 && cmd->tx_argc != 4) goto badargs; - if (!strcmp(cmd->tx_argv[2], "type")) + if (!strcmp(cmd->tx_argv[2], "type") || !strcmp(cmd->tx_argv[2], "layer")) { Contact *contact; type = TT_SPACE; @@ -1371,7 +1371,7 @@ CmdWire(w, cmd) else { width = DRCGetDefaultLayerWidth(type); - WireAddContact(type, width); + WireAddContact(type, (WireWidth < width) ? width : WireWidth); } } else if (!strcmp(cmd->tx_argv[2], "width")) diff --git a/wiring/wireOps.c b/wiring/wireOps.c index 57fb40e5..5a9e09b0 100644 --- a/wiring/wireOps.c +++ b/wiring/wireOps.c @@ -706,6 +706,9 @@ WireShowLeg() * ---------------------------------------------------------------------------- */ +#define WIRING_CONTACT_UP 1 +#define WIRING_CONTACT_DOWN 0 + void WireAddContact(newType, newWidth) TileType newType; /* New type of material to use for wiring. @@ -723,8 +726,9 @@ WireAddContact(newType, newWidth) CellDef *boxRootDef; TileType oldType; TileTypeBitMask mask, allmask; - int oldOverlap, newOverlap, oldExtend, newExtend; - int i, totalSize, oldDir; + int conSurround1, conSurround2, conExtend1, conExtend2, conSize; + int oldOverlap, newOverlap; + int i, totalSize, oldDir, updown; Contact *contact; SearchContext scx; @@ -768,19 +772,39 @@ WireAddContact(newType, newWidth) if ((contact->con_layer1 == oldType) && (contact->con_layer2 == WireType)) { - oldOverlap = contact->con_surround1 / WireUnits; - newOverlap = contact->con_surround2 / WireUnits; - oldExtend = contact->con_extend1 / WireUnits; - newExtend = contact->con_extend2 / WireUnits; + conSurround1 = contact->con_surround1 / WireUnits; + if ((contact->con_surround1 % WireUnits) != 0) conSurround1++; + conSurround2 = contact->con_surround2 / WireUnits; + if ((contact->con_surround2 % WireUnits) != 0) conSurround2++; + conExtend1 = contact->con_extend1 / WireUnits; + if ((contact->con_extend1 % WireUnits) != 0) conExtend1++; + conExtend2 = contact->con_extend2 / WireUnits; + if ((contact->con_extend2 % WireUnits) != 0) conExtend2++; + conSize = contact->con_size / WireUnits; + if ((contact->con_size % WireUnits) != 0) conSize++; + + oldOverlap = conSurround1; + newOverlap = conSurround2; + updown = WIRING_CONTACT_UP; goto gotContact; } if ((contact->con_layer2 == oldType) && (contact->con_layer1 == WireType)) { - oldOverlap = contact->con_surround2 / WireUnits; - newOverlap = contact->con_surround1 / WireUnits; - oldExtend = contact->con_extend2 / WireUnits; - newExtend = contact->con_extend1 / WireUnits; + conSurround1 = contact->con_surround1 / WireUnits; + if ((contact->con_surround1 % WireUnits) != 0) conSurround1++; + conSurround2 = contact->con_surround2 / WireUnits; + if ((contact->con_surround2 % WireUnits) != 0) conSurround2++; + conExtend1 = contact->con_extend1 / WireUnits; + if ((contact->con_extend1 % WireUnits) != 0) conExtend1++; + conExtend2 = contact->con_extend2 / WireUnits; + if ((contact->con_extend2 % WireUnits) != 0) conExtend2++; + conSize = contact->con_size / WireUnits; + if ((contact->con_size % WireUnits) != 0) conSize++; + + oldOverlap = conSurround2; + newOverlap = conSurround1; + updown = WIRING_CONTACT_DOWN; goto gotContact; } } @@ -798,7 +822,8 @@ WireAddContact(newType, newWidth) */ gotContact: - totalSize = (contact->con_size / WireUnits) + 2 * oldOverlap; + totalSize = conSize + 2 * oldOverlap; + if (totalSize < WireWidth) totalSize = WireWidth; contactArea = oldLeg; if ((contactArea.r_xtop - contactArea.r_xbot) < totalSize) { @@ -816,22 +841,22 @@ WireAddContact(newType, newWidth) switch (oldDir) { case GEO_NORTH: - i = contactArea.r_ytop - WireWidth; + i = contactArea.r_ytop - totalSize; if (i > contactArea.r_ybot) contactArea.r_ybot = i; break; case GEO_SOUTH: - i = contactArea.r_ybot + WireWidth; + i = contactArea.r_ybot + totalSize; if (i < contactArea.r_ytop) contactArea.r_ytop = i; break; case GEO_EAST: - i = contactArea.r_xtop - WireWidth; + i = contactArea.r_xtop - totalSize; if (i > contactArea.r_xbot) contactArea.r_xbot = i; break; case GEO_WEST: - i = contactArea.r_xbot + WireWidth; + i = contactArea.r_xbot + totalSize; if (i < contactArea.r_xtop) contactArea.r_xtop = i; break; @@ -844,23 +869,23 @@ WireAddContact(newType, newWidth) TTMaskSetOnlyType(&mask, contact->con_type); TTMaskSetOnlyType(&allmask, contact->con_type); DBPaintValid(EditCellUse->cu_def, &tmp, &mask, 0); - if (contact->con_surround1 != 0) + if (conSurround1 != 0) { TTMaskSetOnlyType(&mask, contact->con_layer1); TTMaskSetType(&allmask, contact->con_layer1); - GEO_EXPAND(&tmp, contact->con_surround1 / WireUnits, &tmp2); + GEO_EXPAND(&tmp, conSurround1, &tmp2); (void) GeoInclude(&tmp2, &editArea); DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); } - if (contact->con_surround2 != 0) + if (conSurround2 != 0) { TTMaskSetOnlyType(&mask, contact->con_layer2); TTMaskSetType(&allmask, contact->con_layer2); - GEO_EXPAND(&tmp, contact->con_surround2 / WireUnits, &tmp2); + GEO_EXPAND(&tmp, conSurround2, &tmp2); (void) GeoInclude(&tmp2, &editArea); DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); } - if (contact->con_extend1 != 0) + if (conExtend1 != 0) { TTMaskSetOnlyType(&mask, contact->con_layer1); TTMaskSetType(&allmask, contact->con_layer1); @@ -869,19 +894,41 @@ WireAddContact(newType, newWidth) { case GEO_NORTH: case GEO_SOUTH: - tmp2.r_ybot -= contact->con_extend1 / WireUnits; - tmp2.r_ytop += contact->con_extend1 / WireUnits; + if (updown == WIRING_CONTACT_UP) + { + tmp2.r_ybot -= conExtend1; + tmp2.r_ytop += conExtend1; + tmp2.r_xbot -= conSurround1; + tmp2.r_xtop += conSurround1; + } + else { + tmp2.r_xbot -= conExtend1; + tmp2.r_xtop += conExtend1; + tmp2.r_ybot -= conSurround1; + tmp2.r_ytop += conSurround1; + } break; case GEO_EAST: case GEO_WEST: - tmp2.r_xbot -= contact->con_extend1 / WireUnits; - tmp2.r_xtop += contact->con_extend1 / WireUnits; + if (updown == WIRING_CONTACT_UP) + { + tmp2.r_xbot -= conExtend1; + tmp2.r_xtop += conExtend1; + tmp2.r_ybot -= conSurround1; + tmp2.r_ytop += conSurround1; + } + else { + tmp2.r_ybot -= conExtend1; + tmp2.r_ytop += conExtend1; + tmp2.r_xbot -= conSurround1; + tmp2.r_xtop += conSurround1; + } break; } (void) GeoInclude(&tmp2, &editArea); DBPaintValid(EditCellUse->cu_def, &tmp2, &mask, 0); } - if (contact->con_extend2 != 0) + if (conExtend2 != 0) { TTMaskSetOnlyType(&mask, contact->con_layer2); TTMaskSetType(&allmask, contact->con_layer2); @@ -890,13 +937,35 @@ WireAddContact(newType, newWidth) { case GEO_NORTH: case GEO_SOUTH: - tmp2.r_xbot -= contact->con_extend2 / WireUnits; - tmp2.r_xtop += contact->con_extend2 / WireUnits; + if (updown == WIRING_CONTACT_UP) + { + tmp2.r_xbot -= conExtend2; + tmp2.r_xtop += conExtend2; + tmp2.r_ybot -= conSurround2; + tmp2.r_ytop += conSurround2; + } + else { + tmp2.r_ybot -= conExtend2; + tmp2.r_ytop += conExtend2; + tmp2.r_xbot -= conSurround2; + tmp2.r_xtop += conSurround2; + } break; case GEO_EAST: case GEO_WEST: - tmp2.r_ybot -= contact->con_extend2 / WireUnits; - tmp2.r_ytop += contact->con_extend2 / WireUnits; + if (updown == WIRING_CONTACT_UP) + { + tmp2.r_ybot -= conExtend2; + tmp2.r_ytop += conExtend2; + tmp2.r_xbot -= conSurround2; + tmp2.r_xtop += conSurround2; + } + else { + tmp2.r_xbot -= conExtend2; + tmp2.r_xtop += conExtend2; + tmp2.r_ybot -= conSurround2; + tmp2.r_ytop += conSurround2; + } break; } (void) GeoInclude(&tmp2, &editArea); @@ -921,15 +990,15 @@ WireAddContact(newType, newWidth) scx.scx_area = tmp; TTMaskSetOnlyType(&mask, contact->con_type); SelectArea(&scx, &mask, 0); - if (contact->con_surround1 != 0) + if (conSurround1 != 0) { - GEO_EXPAND(&tmp, contact->con_surround1 / WireUnits, &scx.scx_area); + GEO_EXPAND(&tmp, conSurround1, &scx.scx_area); TTMaskSetOnlyType(&mask, contact->con_layer1); SelectArea(&scx, &mask, 0); } - if (contact->con_surround2 != 0) + if (conSurround2 != 0) { - GEO_EXPAND(&tmp, contact->con_surround2 / WireUnits, &scx.scx_area); + GEO_EXPAND(&tmp, conSurround2, &scx.scx_area); TTMaskSetOnlyType(&mask, contact->con_layer2); SelectArea(&scx, &mask, 0); } From 8f7db3942c29be12d6ee3bb2fe0e3d7dc86dc299 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 4 Jun 2019 16:17:17 -0400 Subject: [PATCH 3/3] Fixed the "writeall force" command, which was behaving exactly the same as "writeall", meaning that "force" was not being honored and only cells that were modified were being written, in either case. --- commands/CmdTZ.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/commands/CmdTZ.c b/commands/CmdTZ.c index 36969938..ff9559d9 100644 --- a/commands/CmdTZ.c +++ b/commands/CmdTZ.c @@ -1736,17 +1736,20 @@ CmdWriteall(w, cmd) int cmdWriteallFunc(); static char *force[] = { "force", 0 }; int argc; + int flags = CDMODIFIED | CDBOXESCHANGED | CDSTAMPSCHANGED; - if ((cmd->tx_argc >= 2) && (Lookup(cmd->tx_argv[1], force) < 0)) + if (cmd->tx_argc >= 2) { - TxError("Usage: %s [force [cellname ...]]\n", cmd->tx_argv[0]); - return; + flags = 0; + if (Lookup(cmd->tx_argv[1], force) < 0) + { + TxError("Usage: %s [force [cellname ...]]\n", cmd->tx_argv[0]); + return; + } } - DBUpdateStamps(); argc = cmd->tx_argc; - (void) DBCellSrDefs(CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED, - cmdWriteallFunc, (ClientData)cmd); + (void) DBCellSrDefs(flags, cmdWriteallFunc, (ClientData)cmd); cmd->tx_argc = argc; }