From f7d57c913c795046931782cf048b67293d98529b Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 11 May 2019 15:09:01 -0400 Subject: [PATCH] Modified "def write" to prevent out-of-bounds array access when writing vias. However, the underlying problem, which is that stacked vias are not decomposed into their constituent parts, has not been addressed. A "-units" option was added to the "def write" command to force the units of the output file to be different than the default of 1000 (nanometers). No checks are made for whether values can be accurately represented at the specified scale. --- lef/defWrite.c | 30 ++++++++++++++++++------------ lef/lefCmd.c | 23 +++++++++++++++++++++-- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lef/defWrite.c b/lef/defWrite.c index def222be..acd15a73 100644 --- a/lef/defWrite.c +++ b/lef/defWrite.c @@ -84,10 +84,11 @@ char *defGetType(); /* Forward declaration */ */ void -defWriteHeader(def, f, oscale) +defWriteHeader(def, f, oscale, units) CellDef *def; /* Def for which to generate DEF output */ FILE *f; /* Output to this file */ float oscale; + int units; /* Units for UNITS; could be derived from oscale */ { TileType type; @@ -113,10 +114,10 @@ defWriteHeader(def, f, oscale) /* technology). */ fprintf(f, " TECHNOLOGY %s ;\n", DBTechName); - /* As I understand it, this refers to the scalefactor of the GDS */ - /* file output. Magic does all GDS in nanometers, so the LEF */ - /* scalefactor (conversion to microns) is always 1000. */ - fprintf(f, " UNITS DISTANCE MICRONS 1000 ;\n"); + /* The DEF scalefactor (conversion to microns) is always 1000 */ + /* (nanometers) unless overridden on the command line. */ + + fprintf(f, " UNITS DISTANCE MICRONS %d ;\n", units); /* Die area, taken from the cell def bounding box. */ fprintf(f, " DIEAREA ( %.10g %.10g ) ( %.10g %.10g ) ;\n", @@ -1864,10 +1865,10 @@ defMakeInverseLayerMap() TileType i; char *lefname; - lefMagicToLefLayer = (LefMapping *)mallocMagic(DBNumUserLayers + lefMagicToLefLayer = (LefMapping *)mallocMagic(DBNumTypes * sizeof(LefMapping)); memset(lefMagicToLefLayer, 0, sizeof(LefMapping) * TT_TECHDEPBASE); - for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++) + for (i = TT_TECHDEPBASE; i < DBNumTypes; i++) { lefname = defGetType(i, &lefl); lefMagicToLefLayer[i].lefName = lefname; @@ -1916,23 +1917,28 @@ defMakeInverseLayerMap() */ void -DefWriteCell(def, outName, allSpecial) +DefWriteCell(def, outName, allSpecial, units) CellDef *def; /* Cell being written */ char *outName; /* Name of output file, or NULL. */ bool allSpecial; /* Treat all nets as SPECIALNETS? */ + int units; /* Force units to this value (default 1000) */ { char *filename; FILE *f; NetCount nets; int total; - float scale = CIFGetOutputScale(1); /* Note that "1" here corresponds - * to "1000" in the header UNITS line - */ + float scale; + LefMapping *lefMagicToLefLayer; int i; lefLayer *lefl; HashEntry *he; + /* Note that "1" corresponds to "1000" in the header UNITS line, */ + /* or units of nanometers. 10 = centimicrons, 1000 = microns. */ + + scale = CIFGetOutputScale(1000 / units); + f = lefFileOpen(def, outName, ".def", "w", &filename); TxPrintf("Generating DEF output %s for cell %s:\n", filename, def->cd_name); @@ -1949,7 +1955,7 @@ DefWriteCell(def, outName, allSpecial) return; } - defWriteHeader(def, f, scale); + defWriteHeader(def, f, scale, units); lefMagicToLefLayer = defMakeInverseLayerMap(); diff --git a/lef/lefCmd.c b/lef/lefCmd.c index 86e390cf..546988db 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -61,7 +61,7 @@ CmdLef(w, cmd) MagWindow *w; TxCommand *cmd; { - int option, i, cargs; + int option, i, cargs, units = 1000; /* Default nanometers */ char **msg, *namep; CellUse *selectedUse; CellDef *selectedDef; @@ -219,6 +219,25 @@ CmdLef(w, cmd) else TxPrintf("The \"-hide\" option is only for lef write\n"); } + else if (!strncmp(cmd->tx_argv[i], "-units", 5)) + { + if (is_lef) + TxPrintf("The \"-units\" option is only for def write\n"); + else + { + i++; + cargs--; + if ((cmd->tx_argc < i) || (!StrIsInt(cmd->tx_argv[i]))) + { + TxPrintf("The \"-units\" option requires an argument.\n"); + } + else + { + units = atoi(cmd->tx_argv[i]); + // To do: Check range of units + } + } + } else goto wrongNumArgs; cargs--; } @@ -236,7 +255,7 @@ CmdLef(w, cmd) else namep = cmd->tx_argv[2]; if (!is_lef) - DefWriteCell(selectedUse->cu_def, namep, allSpecial); + DefWriteCell(selectedUse->cu_def, namep, allSpecial, units); else LefWriteCell(selectedUse->cu_def, namep, selectedUse->cu_def == EditRootDef, lefTech, lefHide);