From 4ad7ce3cf4fb12b55550b3c19d1644234830a721 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 29 May 2020 14:31:48 -0400 Subject: [PATCH] Modified LEF read and write to preserve macro PROPERTY lines. This probably needs revisiting, because "lef write" and "lef writeall" need handling to generate the PROPERTYDEFINITIONS block for the PROPERTY entries to be correct. --- lef/lefRead.c | 38 ++++++++++++++++++++++++++++++-------- lef/lefWrite.c | 43 +++++++++++++++++++++++++++++++++++++++++++ tcltk/readspice.tcl | 9 +++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/lef/lefRead.c b/lef/lefRead.c index 3104a3ba..57408c7f 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1697,7 +1697,7 @@ LefEndStatement(f) enum lef_macro_keys {LEF_CLASS = 0, LEF_SIZE, LEF_ORIGIN, LEF_SYMMETRY, LEF_SOURCE, LEF_SITE, LEF_PIN, LEF_OBS, - LEF_TIMING, LEF_FOREIGN, LEF_MACRO_END}; + LEF_TIMING, LEF_FOREIGN, LEF_PROPERTY, LEF_MACRO_END}; void LefReadMacro(f, mname, oscale, importForeign) @@ -1712,9 +1712,9 @@ LefReadMacro(f, mname, oscale, importForeign) HashEntry *he; char *token, tsave[128], *propval; - int keyword, pinNum; + int keyword, pinNum, propsize; float x, y; - bool has_size, is_imported = FALSE; + bool has_size, is_imported = FALSE, propfound; Rect lefBBox; static char *macro_keys[] = { @@ -1728,6 +1728,7 @@ LefReadMacro(f, mname, oscale, importForeign) "OBS", "TIMING", "FOREIGN", + "PROPERTY", "END", NULL }; @@ -1856,6 +1857,31 @@ origin_error: DBPropPut(lefMacro, "LEFsite", StrDup((char **)NULL, token)); LefEndStatement(f); break; + case LEF_PROPERTY: + /* Append property key:value pairs to the cell property LEFproperties */ + propval = (char *)DBPropGet(lefMacro, "LEFproperties", &propfound); + if (propfound) + propsize = strlen(propval); + else + propsize = 0; + + token = LefNextToken(f, TRUE); + if (*token != '\n') + { + char *propext; + sprintf(tsave, "%.127s", token); + token = LefNextToken(f, TRUE); + propext = (char *)mallocMagic(propsize + strlen(tsave) + + strlen(token) + 4); + if (propsize > 0) + sprintf(propext, "%s %s %s", propval, tsave, token); + else + sprintf(propext, "%s %s", tsave, token); + + DBPropPut(lefMacro, "LEFproperties", StrDup((char **)NULL, propext)); + } + LefEndStatement(f); + break; case LEF_PIN: token = LefNextToken(f, TRUE); /* Diagnostic */ @@ -2464,7 +2490,7 @@ enum lef_sections {LEF_VERSION = 0, LEF_PROPERTYDEFS, LEF_UNITS, LEF_SECTION_LAYER, LEF_SECTION_VIA, LEF_SECTION_VIARULE, LEF_SECTION_NONDEFAULTRULE, LEF_NOWIREEXTENSIONATPIN, LEF_SECTION_SPACING, LEF_SECTION_SITE, - LEF_PROPERTY, LEF_NOISETABLE, LEF_CORRECTIONTABLE, LEF_IRDROP, + LEF_NOISETABLE, LEF_CORRECTIONTABLE, LEF_IRDROP, LEF_ARRAY, LEF_SECTION_TIMING, LEF_EXTENSION, LEF_MACRO, LEF_END}; @@ -2499,7 +2525,6 @@ LefRead(inName, importForeign) "NOWIREEXTENSIONATPIN", "SPACING", "SITE", - "PROPERTY", "NOISETABLE", "CORRECTIONTABLE", "IRDROP", @@ -2676,9 +2701,6 @@ LefRead(inName, importForeign) sprintf(tsave, "%.127s", token); LefSkipSection(f, tsave); break; - case LEF_PROPERTY: - LefSkipSection(f, NULL); - break; case LEF_NOISETABLE: LefSkipSection(f, sections[LEF_NOISETABLE]); break; diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 94c35430..e2213670 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1432,6 +1432,49 @@ lefWriteMacro(def, f, scale, hide) if (lc.numWrites > 0) fprintf(f, IN0 "END\n"); /* end of obstruction geometries */ + /* If there are any properties saved in LEFproperties, write them out */ + + propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound); + if (propfound) + { + char *delim; + char *propfind = propvalue; + bool endfound = FALSE; + + /* Properties are in space-separated key:value pairs. */ + /* The value is in quotes and may contain spaces. */ + /* One PROPERTY line is written per key:value pair. */ + + while (*propfind != '\0') + { + char dsave; + + delim = propfind; + while (*delim != ' ' && *delim != '\0') delim++; + if (*delim == '\0') break; + while (*delim == ' ' && *delim != '\0') delim++; + if (*delim == '\0') break; + if (*delim == '\"') + { + delim++; + while (*delim != '\"' && *delim != '\0') delim++; + if (*delim == '\0') break; + delim++; + } + else + while (*delim != ' ' && *delim != '\0') delim++; + + if (*delim == '\0') endfound = TRUE; + dsave = *delim; + *delim = '\0'; + fprintf(f, IN0 "PROPERTY %s ;\n", propfind); + *delim = dsave; + if (endfound) break; + while (*delim == ' ' && *delim != '\0') delim++; + propfind = delim; + } + } + fprintf(f, "END %s\n", def->cd_name); /* end of macro */ SigDisableInterrupts(); diff --git a/tcltk/readspice.tcl b/tcltk/readspice.tcl index ee1fab83..a282cf39 100644 --- a/tcltk/readspice.tcl +++ b/tcltk/readspice.tcl @@ -78,6 +78,15 @@ proc readspice {netfile} { foreach line $fdata { set ftokens [split $line] set keyword [string tolower [lindex $ftokens 0]] + + # Handle SPECTRE model format + if {$keyword == "inline"} { + if {[string tolower [lindex $ftokens 1]] == "subckt"} { + set ftokens [lrange [split $line " \t()"] 1 end] + set keyword ".subckt" + } + } + if {$keyword == ".subckt"} { set cell [lindex $ftokens 1] set status [cellname list exists $cell]