2020-05-28 17:46:57 +02:00
|
|
|
#-----------------------------------------------------------------
|
|
|
|
|
# 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} {
|
2020-05-29 17:23:39 +02:00
|
|
|
if {[file ext $netfile] == ".cdl"} {
|
2020-05-29 17:27:16 +02:00
|
|
|
set is_cdl true
|
2020-05-29 17:23:39 +02:00
|
|
|
} else {
|
2020-05-29 17:27:16 +02:00
|
|
|
set is_cdl false
|
2020-05-29 17:23:39 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-28 17:46:57 +02:00
|
|
|
if [catch {open $netfile r} fnet] {
|
|
|
|
|
set netname [file rootname $netfile]
|
|
|
|
|
|
2020-05-29 17:23:39 +02:00
|
|
|
# Check for standard extensions (.spi, .spc, .spice, .sp, .ckt, .cdl)
|
2020-05-28 17:46:57 +02:00
|
|
|
|
2020-05-29 17:19:37 +02:00
|
|
|
set testnetfile ${netname}.spi
|
|
|
|
|
if [catch {open ${testnetfile} r} fnet] {
|
|
|
|
|
set testnetfile ${netname}.spc
|
2020-05-28 17:46:57 +02:00
|
|
|
if [catch {open ${testnetfile} r} fnet] {
|
2020-05-29 17:19:37 +02:00
|
|
|
set testnetfile ${netname}.spice
|
2020-05-28 17:46:57 +02:00
|
|
|
if [catch {open ${testnetfile} r} fnet] {
|
2020-05-29 17:19:37 +02:00
|
|
|
set testnetfile ${netname}.sp
|
2020-05-28 17:46:57 +02:00
|
|
|
if [catch {open ${testnetfile} r} fnet] {
|
2020-05-29 17:19:37 +02:00
|
|
|
set testnetfile ${netname}.ckt
|
2020-05-28 17:46:57 +02:00
|
|
|
if [catch {open ${testnetfile} r} fnet] {
|
2020-05-29 17:23:39 +02:00
|
|
|
set testnetfile ${netname}.cdl
|
|
|
|
|
if [catch {open ${testnetfile} r} fnet] {
|
|
|
|
|
puts stderr "Error: Can't read netlist file $netfile"
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
2020-05-29 17:27:16 +02:00
|
|
|
set is_cdl true
|
2020-05-29 17:23:39 +02:00
|
|
|
}
|
2020-05-28 17:46:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-29 17:19:37 +02:00
|
|
|
set netfile $testnetfile
|
2020-05-28 17:46:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Read data from file. Remove comment lines and concatenate
|
|
|
|
|
# continuation lines.
|
|
|
|
|
|
2020-05-29 17:19:37 +02:00
|
|
|
puts stderr "Annotating port orders from $netfile"
|
2020-05-28 17:46:57 +02:00
|
|
|
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
|
2020-05-29 17:25:13 +02:00
|
|
|
close $fnet
|
2020-05-28 17:46:57 +02:00
|
|
|
|
|
|
|
|
# Now look for all ".subckt" lines
|
|
|
|
|
|
|
|
|
|
suspendall
|
|
|
|
|
foreach line $fdata {
|
|
|
|
|
set ftokens [split $line]
|
|
|
|
|
set keyword [string tolower [lindex $ftokens 0]]
|
2020-05-29 20:31:48 +02:00
|
|
|
|
|
|
|
|
# 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"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-28 17:46:57 +02:00
|
|
|
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] {
|
2020-05-29 17:55:30 +02:00
|
|
|
# Tcl "split" will not group spaces and tabs but leaves
|
|
|
|
|
# empty strings.
|
|
|
|
|
if {$pin == {}} {continue}
|
2020-05-28 17:46:57 +02:00
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
|
|
2020-05-29 17:55:30 +02:00
|
|
|
set testpin $pin
|
|
|
|
|
set pinidx [port $testpin index]
|
|
|
|
|
|
|
|
|
|
# Test a few common delimiter translations. This list
|
|
|
|
|
# is by no means exhaustive.
|
|
|
|
|
|
|
|
|
|
if {$pinidx == ""} {
|
|
|
|
|
set testpin [string map {\[ < \] >]} $pin
|
|
|
|
|
set pinidx [port $testpin index]
|
|
|
|
|
}
|
|
|
|
|
if {$pinidx == ""} {
|
|
|
|
|
set testpin [string map {< \[ > \]} $pin
|
|
|
|
|
set pinidx [port $testpin index]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Also test some case sensitivity issues (also not exhaustive)
|
|
|
|
|
|
|
|
|
|
if {$pinidx == ""} {
|
|
|
|
|
set testpin [string tolower $pin]
|
|
|
|
|
set pinidx [port $testpin index]
|
|
|
|
|
}
|
|
|
|
|
if {$pinidx == ""} {
|
|
|
|
|
set testpin [string toupper $pin]
|
|
|
|
|
set pinidx [port $testpin index]
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-28 17:46:57 +02:00
|
|
|
if {$pinidx != ""} {
|
2020-05-29 17:55:30 +02:00
|
|
|
port $testpin index $n
|
2020-05-28 17:46:57 +02:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------
|
|
|
|
|
|