From b6cb1fb54a1935c9cb6c2c90f392a846c149b5ed Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 3 Mar 2020 17:13:37 -0500 Subject: [PATCH 1/3] Modified the LEF VIAGEN reading such that it can accomodate a different order of layers than specified in the LEF/DEF spec. It is not clear whether this is common practice, or a bug in the tool that produced the DEF file that prompted this change. NOTE: The "grow" function applied in this case should be replaced by the actual GDS input rule sequence, that includes the grow and shrink merge. Otherwise, vias read from DEF files do not match the layout from those read from GDS, even though the mask layers represented by the layouts are the same. --- ext2spice/ext2spice.c | 9 ++++++++- lef/defRead.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index b51215ce..94b2eb53 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2873,7 +2873,14 @@ int spcnAP(node, resClass, scale, asterm, psterm, m, outf, w) if (!esDistrJunct || w == -1) goto oldFmt; - dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + if (((nodeClient*)node->efnode_client)->m_w.widths != NULL) + dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + else + { + TxError("Device missing records for source/drain area/perim.\n"); + dsc = w; + } + if (esScale < 0) { if (asterm) diff --git a/lef/defRead.c b/lef/defRead.c index 70446ab4..7091c1c9 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -1287,6 +1287,35 @@ DefReadVias(f, sname, oscale, total) blayer = LefReadLayer(f, FALSE); clayer = LefReadLayer(f, FALSE); tlayer = LefReadLayer(f, FALSE); + + /* Provisional behavior: A known tool generating */ + /* DEF uses the order (bottom, top, cut). This may */ + /* be a bug in the tool and an issue is being */ + /* raised. However, there is no harm in detecting */ + /* which layer is the cut and swapping as needed. */ + + if (!DBIsContact(clayer)) + { + TileType swaplayer; + LefError(DEF_WARNING, "Improper layer order for" + " VIARULE.\n"); + if (DBIsContact(tlayer)) + { + swaplayer = clayer; + clayer = tlayer; + tlayer = swaplayer; + } + else if (DBIsContact(blayer)) + { + swaplayer = clayer; + clayer = blayer; + blayer = swaplayer; + } + else + LefError(DEF_ERROR, "No cut layer specified in" + " VIARULE.\n"); + } + generated = TRUE; break; case DEF_VIAS_PROP_CUTSPACING: From 7413d89da1deef60f780a471ccf0866da3add6d7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 5 Mar 2020 13:14:47 -0500 Subject: [PATCH 2/3] Corrected the "lef writeall" command to add the "-hide" option, as is available for "lef write". This was inadvertently omitted. --- VERSION | 2 +- commands/CmdCD.c | 2 +- drc/DRCtech.c | 3 ++- lef/lefCmd.c | 4 +++- lef/lefWrite.c | 5 +++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 77db8419..e3635811 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.190 +8.2.192 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 0d31dff3..dc817c6f 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -1434,7 +1434,7 @@ CmdCif(w, cmd) if (!ToolGetBox(&rootDef, &box)) { TxError("Use the box to select the area in"); - TxError(" which you want to see CIF.\n"); + TxError(" which you want to paint CIF.\n"); return; } if (argc == 5) diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 48009a51..d56bdaaf 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -361,7 +361,8 @@ drcWhyCreate(whystring) int i; char **newList; newList = (char **)mallocMagic((DRCCurStyle->DRCWhySize + 51) * sizeof(char *)); - for (i = 0; i < DRCCurStyle->DRCWhySize; i++) + newList[0] = (char *)NULL; + for (i = 1; i <= DRCCurStyle->DRCWhySize; i++) newList[i] = DRCCurStyle->DRCWhyList[i]; if (DRCCurStyle->DRCWhySize > 0) freeMagic((char *)DRCCurStyle->DRCWhyList); diff --git a/lef/lefCmd.c b/lef/lefCmd.c index 0322467a..df80f310 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -190,13 +190,15 @@ CmdLef(w, cmd) lefTopCell = FALSE; else if (!strncmp(cmd->tx_argv[i], "-tech", 5)) lefTech = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-hide", 5)) + lefHide = TRUE; else if (!strncmp(cmd->tx_argv[i], "-all", 4)) recurse = TRUE; else goto wrongNumArgs; } else goto wrongNumArgs; } - LefWriteAll(selectedUse, lefTopCell, lefTech, recurse); + LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse); } break; case LEF_WRITE: diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 2984a2fb..b522684c 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1133,10 +1133,11 @@ lefWriteMacro(def, f, scale, hide) */ void -LefWriteAll(rootUse, writeTopCell, lefTech, recurse) +LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) CellUse *rootUse; bool writeTopCell; bool lefTech; + bool lefHide; bool recurse; { CellDef *def, *rootdef; @@ -1190,7 +1191,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech, recurse) { def->cd_client = (ClientData) 0; if (!SigInterruptPending) - lefWriteMacro(def, f, scale); + lefWriteMacro(def, f, scale, lefHide); } /* End the LEF file */ From a37fc1e242be934891b26a2ced211caebbca746d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 5 Mar 2020 14:29:54 -0500 Subject: [PATCH 3/3] Implemented the "def read ... -labels" option, which labels each net with the name given to the net in the DEF file. Especially useful for LVS. --- lef/Depend | 6 +++--- lef/defRead.c | 35 ++++++++++++++++++++++++++++------- lef/lefCmd.c | 34 +++++++++++++++++++++++++--------- utils/main.c | 2 +- 4 files changed, 57 insertions(+), 20 deletions(-) diff --git a/lef/Depend b/lef/Depend index 9b997139..76825257 100644 --- a/lef/Depend +++ b/lef/Depend @@ -23,6 +23,6 @@ lefRead.o: lefRead.c ../tcltk/tclmagic.h ../utils/magic.h \ ../lef/lefInt.h defRead.o: defRead.c ../tcltk/tclmagic.h ../utils/magic.h \ ../utils/geometry.h ../tiles/tile.h ../utils/hash.h ../utils/undo.h \ - ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ - ../utils/malloc.h ../graphics/graphics.h ../utils/main.h ../cif/cif.h \ - ../lef/lefInt.h + ../utils/utils.h ../database/database.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/malloc.h ../graphics/graphics.h \ + ../utils/main.h ../cif/cif.h ../lef/lefInt.h diff --git a/lef/defRead.c b/lef/defRead.c index 7091c1c9..a62a5099 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "tiles/tile.h" #include "utils/hash.h" #include "utils/undo.h" +#include "utils/utils.h" #include "database/database.h" #include "windows/windows.h" #include "dbwind/dbwind.h" @@ -73,11 +74,12 @@ enum def_netspecial_shape_keys { DEF_SPECNET_SHAPE_DRCFILL}; char * -DefAddRoutes(rootDef, f, oscale, special, defLayerMap) +DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap) CellDef *rootDef; /* Cell to paint */ FILE *f; /* Input file */ float oscale; /* Scale factor between LEF and magic units */ bool special; /* True if this section is SPECIALNETS */ + char *netname; /* Name of the net, if net is to be labeled */ LefMapping *defLayerMap; /* magic-to-lef layer mapping array */ { char *token; @@ -85,6 +87,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) Point refp; /* reference point */ bool valid = FALSE; /* is there a valid reference point? */ bool initial = TRUE; + bool labeled = TRUE; Rect locarea; int extend, lextend, hextend; float x, y, z, w; @@ -124,6 +127,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) NULL }; + if (netname != NULL) labeled = FALSE; + while (initial || (token = LefNextToken(f, TRUE)) != NULL) { /* Get next point, token "NEW", or via name */ @@ -605,6 +610,16 @@ endCoord: /* paint */ DBPaint(rootDef, &routeTop->r_r, routeTop->r_type); + /* label */ + if (labeled == FALSE) + { + Rect r; + r.r_xbot = r.r_xtop = (routeTop->r_r.r_xbot + routeTop->r_r.r_xtop) / 2; + r.r_ybot = r.r_ytop = (routeTop->r_r.r_ybot + routeTop->r_r.r_ytop) / 2; + DBPutLabel(rootDef, &r, GEO_CENTER, netname, routeTop->r_type, 0); + labeled = TRUE; + } + /* advance to next point and free record (1-delayed) */ freeMagic((char *)routeTop); routeTop = routeTop->r_next; @@ -636,15 +651,17 @@ enum def_netprop_keys { DEF_NETPROP_PROPERTY}; void -DefReadNets(f, rootDef, sname, oscale, special, total) +DefReadNets(f, rootDef, sname, oscale, special, dolabels, total) FILE *f; CellDef *rootDef; char *sname; float oscale; bool special; /* True if this section is SPECIALNETS */ + bool dolabels; /* If true, create a label for each net */ int total; { char *token; + char *netname = NULL; int keyword, subkey; int processed = 0; LefMapping *defLayerMap; @@ -684,8 +701,8 @@ DefReadNets(f, rootDef, sname, oscale, special, total) case DEF_NET_START: /* Get net name */ - /* Presently, we ignore net names completely. */ token = LefNextToken(f, TRUE); + if (dolabels) netname = StrDup((char **)NULL, token); /* Update the record of the number of nets processed */ /* and spit out a message for every 5% finished. */ @@ -725,10 +742,11 @@ DefReadNets(f, rootDef, sname, oscale, special, total) case DEF_NETPROP_FIXED: case DEF_NETPROP_COVER: token = DefAddRoutes(rootDef, f, oscale, special, - defLayerMap); + netname, defLayerMap); break; } } + if (dolabels) freeMagic(netname); break; case DEF_NET_END: @@ -1648,8 +1666,9 @@ enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE, DEF_END}; void -DefRead(inName) +DefRead(inName, dolabels) char *inName; + bool dolabels; { CellDef *rootDef; FILE *f; @@ -1825,13 +1844,15 @@ DefRead(inName) token = LefNextToken(f, TRUE); if (sscanf(token, "%d", &total) != 1) total = 0; LefEndStatement(f); - DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, total); + DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, + dolabels, total); break; case DEF_NETS: token = LefNextToken(f, TRUE); if (sscanf(token, "%d", &total) != 1) total = 0; LefEndStatement(f); - DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, total); + DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, + dolabels, total); break; case DEF_IOTIMINGS: LefSkipSection(f, sections[DEF_IOTIMINGS]); diff --git a/lef/lefCmd.c b/lef/lefCmd.c index df80f310..b5ba0b12 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -92,6 +92,10 @@ CmdLef(w, cmd) * only the immediate children of the * top level cell are output. */ + bool defLabelNets = FALSE; /* If TRUE, attach a label to the + * center of the first rectangle + * found on that net. + */ static char *cmdLefOption[] = { @@ -101,7 +105,8 @@ CmdLef(w, cmd) " write [filename] -hide hide all details other than ports", "writeall write all cells including the top-level cell\n" " writeall -notop write all children of the top-level cell\n" - " writeall -all recurse on all subcells of the top-level cell", + " writeall -all recurse on all subcells of the top-level cell\n", + " writeall -hide hide all details other than ports", "help print this help information", NULL }; @@ -109,7 +114,8 @@ CmdLef(w, cmd) static char *cmdDefOption[] = { "read [filename] read a DEF file filename[.def]", - "write [cell] [-allspecial] write DEF for current or indicated cell", + "write [cell] [-allspecial] write DEF for current or indicated cell\n", + "write -labels label every net in NETS with the net name", "writeall (use \"flatten -nosubckt\" + \"def" " write\" instead)", "help print this help information", @@ -157,22 +163,32 @@ CmdLef(w, cmd) switch (option) { case LEF_READ: - if (cmd->tx_argc != 3) + if (cmd->tx_argc > 3) { - if (cmd->tx_argc == 4) + for (i = 3; i < cmd->tx_argc; i++) { - if (*(cmd->tx_argv[3]) == '-') - if (!strncmp(cmd->tx_argv[3], "-import", 7)) + if (*(cmd->tx_argv[i]) == '-') + { + if (!strncmp(cmd->tx_argv[i], "-import", 7)) lefImport = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-label", 6)) + { + if (is_lef) + TxPrintf("The \"-labels\" option is only for def read\n"); + else + defLabelNets = TRUE; + } + } } - else - goto wrongNumArgs; } + else if (cmd->tx_argc < 3) + goto wrongNumArgs; + namep = cmd->tx_argv[2]; if (is_lef) LefRead(namep, lefImport); else - DefRead(namep); + DefRead(namep, defLabelNets); break; case LEF_WRITEALL: if (!is_lef) diff --git a/utils/main.c b/utils/main.c index 73eea16a..708f0354 100644 --- a/utils/main.c +++ b/utils/main.c @@ -1156,7 +1156,7 @@ mainInitFinal() LefRead(temporary->fn, FALSE); break; case FN_DEF_FILE: - DefRead(temporary->fn); + DefRead(temporary->fn, FALSE); break; #endif #ifdef MAGIC_WRAPPER