Added a Tcl scripted command "readspice" that can be used to read

SPICE subcircuit definitions from a netlist file and apply the port
order in the netlist to the port labels in the corresponding cell
or cells in the magic database.  Also:  Corrected an error in the
bloat-all code introduced in a recent commit that can cause a
segfault.
This commit is contained in:
Tim Edwards 2020-05-28 11:46:57 -04:00
parent b47d4c5642
commit 626a6355ae
9 changed files with 148 additions and 15 deletions

View File

@ -1 +1 @@
8.3.17
8.3.18

View File

@ -1121,7 +1121,7 @@ cifBloatAllFunc(tile, bls)
if (type == CIF_SOLIDTYPE)
{
pmask = 0;
if (bloats->bl_isCif == TRUE)
if (bloats->bl_plane < 0) /* Bloat types are CIF types */
locScale = 1;
else
locScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
@ -1136,10 +1136,10 @@ cifBloatAllFunc(tile, bls)
else
{
int pNum = DBPlane(type);
pmask = (bloats->bl_isCif == TRUE) ? 0 :
pmask = (bloats->bl_plane < 0) ? 0 :
CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum));
if (pmask == 0) TiToRect(tile, &area);
if (bloats->bl_isCif == TRUE)
if (bloats->bl_plane < 0)
{
/* Get the tile into CIF database coordinates if it's in magic coords */
area.r_xbot *= cifScale;
@ -1155,7 +1155,7 @@ cifBloatAllFunc(tile, bls)
}
if (pmask == 0)
{
if (bloats->bl_isCif)
if (bloats->bl_plane < 0) /* Bloat types are CIF types */
{
/* This expands the area to the OR of all temp layers specified */
/* which may or may not be useful; normally one would expand */

View File

@ -45,9 +45,9 @@
typedef struct bloat_data
{
bool bl_isCif; /* TRUE if types of bl_distance are CIF types */
int bl_plane; /* Plane on which a bloat or squares
* operation is valid.
* operation is valid. If -1, then the bloat
* types are CIF types.
*/
int bl_distance[TT_MAXTYPES];
} BloatData;

View File

@ -338,7 +338,7 @@ CIFNameToMask(name, result, depend)
BloatData *bloats = (BloatData *)op->co_client;
TileType ttype;
if (bloats->bl_isCif == TRUE)
if (bloats->bl_plane < 0) /* Use CIF types */
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
if (bloats->bl_distance[ttype] > 0)
TTMaskSetType(depend, ttype);

View File

@ -1109,19 +1109,21 @@ CIFTechLine(sectionName, argc, argv)
TTMaskZero(&bloatLayers);
if (!TTMaskIsZero(&mask))
{
bloats->bl_isCif = FALSE;
TTMaskSetMask(&bloatLayers, &mask);
for (i = 0; i < TT_MAXTYPES; i++)
if (TTMaskHasType(&mask, i))
bloats->bl_distance[i] = 1;
goto bloatCheck;
}
else
{
bloats->bl_isCif = TRUE;
TTMaskSetMask(&bloatLayers, &cifMask);
for (i = 0; i < TT_MAXTYPES; i++)
if (TTMaskHasType(&cifMask, i))
bloats->bl_distance[i] = 1;
bloats->bl_plane = -1; /* Indicates CIF types */
}
break;
@ -1135,7 +1137,6 @@ CIFTechLine(sectionName, argc, argv)
bloatArg = argv + 2;
bloatLayers = newOp->co_paintMask;
bloats = (BloatData *)mallocMagic(sizeof(BloatData));
bloats->bl_isCif = FALSE;
for (i = 0; i < TT_MAXTYPES; i++)
bloats->bl_distance[i] = 0;
newOp->co_client = (ClientData)bloats;
@ -1877,7 +1878,7 @@ CIFTechFinal()
{
if (bloats->bl_distance[j] != bloats->bl_distance[TT_SPACE])
{
if (bloats->bl_isCif)
if (bloats->bl_plane < 0)
TTMaskSetType(&ourDepend, j);
else
TTMaskSetType(&ourYank, j);

View File

@ -1131,7 +1131,9 @@ portFindLabel(editDef, port, unique, nonEdit)
Rect editBox;
/*
* Check for unique label in box area
* Check for unique label in box area. Note that GEO_OVERLAP
* requires non-zero overlap area, so also check GEO_SURROUND to
* catch zero-area label rectangles.
*/
ToolGetEditBox(&editBox);
@ -1140,7 +1142,8 @@ portFindLabel(editDef, port, unique, nonEdit)
lab = NULL;
for (sl = editDef->cd_labels; sl != NULL; sl = sl->lab_next)
{
if (GEO_OVERLAP(&editBox, &sl->lab_rect))
if (GEO_OVERLAP(&editBox, &sl->lab_rect) ||
GEO_SURROUND(&editBox, &sl->lab_rect))
{
if (found > 0)
{
@ -1369,7 +1372,10 @@ CmdPort(w, cmd)
}
if (lab == NULL)
{
TxError("No label found with that name\n.");
if (StrIsInt(cmd->tx_argv[1]))
TxError("No label found with name %s.\n", cmd->tx_argv[1]);
else
TxError("No port found with index %s.\n", cmd->tx_argv[1]);
return;
}
argstart = 2;
@ -1414,7 +1420,10 @@ CmdPort(w, cmd)
{
/* Let "port remove" fail without complaining. */
if (option != PORT_REMOVE)
{
TxError("Exactly one label may be present under the cursor box.\n");
TxError("Use \"port <name> ...\" to specify a uniqe port.\n");
}
return;
}

View File

@ -28,6 +28,7 @@ TCL_FILES = \
toolkit_rev0.tcl \
bsitools.tcl \
socketcmd.tcl \
readspice.tcl \
magic.tcl
BIN_FILES = \

118
tcltk/readspice.tcl Normal file
View File

@ -0,0 +1,118 @@
#-----------------------------------------------------------------
# readspice.tcl
#-----------------------------------------------------------------
# Defines procedure "readspice <netlist>", requiring a SPICE
# netlist as an argument. Each .SUBCKT line in the netlist
# is used to force the port ordering in the layout of the cell
# with the same subcircuit name.
#
# NOTE: This is NOT a schematic-to-layout function! Its purpose
# is to annotate cells with information in a netlist. The cell
# layout must exist before reading the corresponding netlist.
#-----------------------------------------------------------------
global Opts
proc readspice {netfile} {
if [catch {open $netfile r} fnet] {
set netname [file rootname $netfile]
if [catch {open ${netfile} r} fnet] {
# Check for standard extensions (.spi, .spc, .spice, .sp, .ckt)
set testnetfile ${netfile}.spi
if [catch {open ${testnetfile} r} fnet] {
set testnetfile ${netfile}.spc
if [catch {open ${testnetfile} r} fnet] {
set testnetfile ${netfile}.spice
if [catch {open ${testnetfile} r} fnet] {
set testnetfile ${netfile}.sp
if [catch {open ${testnetfile} r} fnet] {
set testnetfile ${netfile}.ckt
if [catch {open ${testnetfile} r} fnet] {
puts stderr "Can't read netlist file $netfile"
return 1;
}
}
}
}
}
}
}
# Read data from file. Remove comment lines and concatenate
# continuation lines.
set fdata {}
set lastline ""
while {[gets $fnet line] >= 0} {
if {[lindex $line 0] != "*"} {
if {[lindex $line 0] == "+"} {
if {[string range $line end end] != " "} {
append lastline " "
}
append lastline [string range $line 1 end]
} else {
lappend fdata $lastline
set lastline $line
}
}
}
lappend fdata $lastline
# Now look for all ".subckt" lines
suspendall
foreach line $fdata {
set ftokens [split $line]
set keyword [string tolower [lindex $ftokens 0]]
if {$keyword == ".subckt"} {
set cell [lindex $ftokens 1]
set status [cellname list exists $cell]
if {$status != 0} {
load $cell
box values 0 0 0 0
set n 1
set changed false
foreach pin [lrange $ftokens 2 end] {
# NOTE: Should probably check for CDL-isms, global bang
# characters, case insensitive matches, etc. This routine
# currently expects a 1:1 match between netlist and layout.
# This routine will also make ports out of labels in the
# layout if they have not been read in or created as ports.
# However, if there are multiple labels with the same port
# name, only the one triggered by "goto" will be made into
# a port.
set pinidx [port $pin index]
if {$pinidx != ""} {
port $pin index $n
if {$pinidx != $n} {
set changed true
}
incr n
} else {
set layer [goto $pin]
if {$layer != ""} {
port make $n
incr n
set changed true
}
}
}
if {$changed} {
puts stdout "Cell $cell port order was modified."
}
} else {
puts stdout "Cell $cell in netlist has not been loaded."
}
}
}
resumeall
}
#-----------------------------------------------------------------

View File

@ -392,6 +392,10 @@ catch {source ${CAD_ROOT}/magic/tcl/drcmgr.tcl}
catch {source ${CAD_ROOT}/magic/tcl/texthelper.tcl}
# Add the readspice command for port annotation
catch {source ${CAD_ROOT}/magic/tcl/readspice.tcl}
# Create or redisplay the technology manager
proc magic::techmanager {{option "update"}} {