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:
parent
b47d4c5642
commit
626a6355ae
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ TCL_FILES = \
|
|||
toolkit_rev0.tcl \
|
||||
bsitools.tcl \
|
||||
socketcmd.tcl \
|
||||
readspice.tcl \
|
||||
magic.tcl
|
||||
|
||||
BIN_FILES = \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
||||
|
|
@ -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"}} {
|
||||
|
|
|
|||
Loading…
Reference in New Issue