//routeBackPanel.bcpl

// Backpanel & Other auxiliary descriptive files module

// last modified by Taft, September 16, 1979 8:20 PM

get "streams.d"
get "route.defs"

static
[
BPFile; doMultiWire=false
doResistances=false; conductance; resistanceFile
wiredPins; holesFile; holeSizes; holePlating; holeNet; currentHoleType
lastHoleType; pinsThisLine
]

manifest [ plated = true; unplated = not plated ]

let OutputBPFiles() be
[
MapNamees(typeIcinst, MakeConnInstFile)
MakeOldBPFile()
MakeLoadingChart()
if doMultiWire then MultiWire()
if doResistances then MakeResistanceFile()
]

and MakeConnInstFile(icinst) be
[
unless Icclass(icinst)>>icclass.isConnector do return
let filename = vec 20
let connstr = FindNameesString(icinst)
ExpandTemplate(filename, "$S-$S.nl", nlFileName, connstr)
let file = GetFile(filename)
PutTemplate(file, "; Nets for connector $S of class $S on board located at $S*n@*n",
connstr, FindNameesString(Icclass(icinst)), boardLocation)
for pinNo=1 to Npins(icinst) do if icinst>>icinst.pin↑pinNo ne empty then
[
PutTemplate(file, "$S: #$S-$S.$D*n", FindNameesString(FindNet(icinst>>icinst.pin↑pinNo)),
boardLocation, connstr, pinNo)
]
TruncateAndClose(file)
]


and MakeOldBPFile() be
[
BPFile = GetFile(nlFileName, ".bp")
DoInSortOrder(typeNet, NameCompareFn, WriteBPLine)
TruncateAndClose(BPFile)
]

and MakeLoadingChart() be
[
BPFile = GetFile(nlFileName, ".lc")
DoInSortOrder(typeIcinst, TypeCompareFn, WriteLoadingLine)
TruncateAndClose(BPFile)
]

and WriteBPLine(net) be
[
let pin = net>>net.pinList
let connectorList = vec 50
connectorList>>str.length = 0
let needsComma = false
while @pin ne mark do
[
let icinst = pin-offset icinst.pin↑1/16
let pinNo = 1
pin = @pin
while icinst>>icinst.type ne typeIcinst do
[
icinst = icinst-1
pinNo = pinNo+1
]
unless Icclass(icinst)>>icclass.isConnector do loop
ExpandTemplate(connectorList, "$S$S$S$D", connectorList,
(needsComma? ",",""), FindNameesString(icinst), pinNo)
needsComma = true
]
if connectorList>>str.length ne 0 then
PutTemplate(BPFile, "$S: $S*n", FindNameesString(FindNet(net>>net.pinList)),
connectorList) // this circumlocution gets GND instead of GND45, for example
]

and TypeCompareFn(inst1, inst2) = valof
[
let t1 = inst1>>icinst.ictype
let t2 = inst2>>icinst.ictype

if t1>>namee.type ne typeIctype then resultis -1
if t2>>namee.type ne typeIctype then resultis 1

let result = NameCompareFn(t1, t2)
resultis (result ne 0)? result, NameCompareFn(inst1, inst2)
]

and WriteLoadingLine(icinst) be
[
static [ currentType = empty; loadCount; lastInstLen ]
if (icinst>>icinst.ictype)>>namee.type ne typeIctype then return
if currentType ne empty & icinst>>icinst.ictype ne currentType then
[
Wss(BPFile, "*n*n")
currentType = empty
]
if currentType eq empty then
[
currentType = icinst>>icinst.ictype
PutTemplate(BPFile, "$S:*n", FindNameesString(currentType))
loadCount = 0
]
test loadCount eq 0 % loadCount gr 7
ifso [ loadCount = 0; Wss(BPFile, "*n ") ]
ifnot for i=1 to 10-lastInstLen do Puts(BPFile, $*s)

Puts(BPFile, $*s)
Wss(BPFile, FindNameesString(icinst))
lastInstLen = FindNameesString(icinst)>>str.length
loadCount = loadCount+1
]

and MultiWire() be
[
BPFile = GetFile(nlFileName, ".mw")
DoInSortOrder(typeNet, NetNumCompareFn, OutputMWNet)
FinishMWFile(BPFile)

let pinVecLen = (FindIndexFromCoord(-1,-1)+15)/16
wiredPins = Allocate(SilZone, pinVecLen)
Zero(wiredPins, pinVecLen)

MapNamees(typeIcinst, MarkUsedPins)

holesFile = GetFile(nlFileName, ".mh")
let hs = vec 20; holeSizes = hs
let hp = vec 20; holePlating = hp
let hn = vec 20; holeNet = hn
currentHoleType = 0
lastHoleType = 0
pinsThisLine = 0
DescribeHoles(PrintAHole)
Puts(holesFile, $*n)
FinishMWFile(holesFile)
Free(SilZone, wiredPins)

let indexFile = GetFile(nlFileName, ".mhi")
let netLine = vec 30
for i=1 to lastHoleType do
PutTemplate(indexFile, "*nHole type $D: $D mils, $Splated$S",
i, holeSizes!i, (holePlating!i? "","un"),
(holeNet!i eq empty? "", ExpandTemplate(netLine, ", net = $S",
FindNameesString(holeNet!i))))
PutTemplate(indexFile, "*n")
TruncateAndClose(indexFile)
]

and NetNumCompareFn(n1, n2) = n2>>net.netnum-n1>>net.netnum

and OutputMWNet(net) be
[
static [ MWNetNum = 0 ]
let nodecount = 0
let pin = net>>net.pinList
while @pin ne mark do
[
pin = @pin
nodecount = nodecount+1
]

if nodecount ls 2 then return
MWNetNum = MWNetNum+1
PutTemplate(BPFile, "$5D", MWNetNum)
let pinsThisLine = 0
let pin = net>>net.pinList
while @pin ne mark do
[
let x,y = nil,nil
GetPinCoord(0, pin, lv x, lv y)
if pinsThisLine ge 5 then
[
PutTemplate(BPFile, "*n$5D", MWNetNum) // we re-iterate the net #
pinsThisLine = 0
]
ComputeMWCoords(lv x, lv y, false)
PutTemplate(BPFile, "$S $5D $5D", (pinsThisLine gr 0? " ",""),
x, y)
pinsThisLine = pinsThisLine+1
pin = @pin
]
PutTemplate(BPFile, "*n")
]

and FinishMWFile(file) be
[
PutTemplate(file, "$5D*n", -1)
TruncateAndClose(file)
]

and MarkUsedPins(icinst) be
[
let icclass = Icclass(icinst)
for i=1 to Npins(icinst) do if icinst>>icinst.pin↑i ne empty %
(not icclass>>icclass.isTraceWired) then
[
let x,y = nil,nil
GetPinCoord(icinst, i, lv x, lv y)
let index = FindIndexFromCoord(x, y)
SetBit(wiredPins, index, 1)
]
]

and PrintAHole(x, y, holeSize, isPlated, isMils, alwaysDrill; numargs na) be
[
static [ allPinsAreHoles = false; encodeTWNets = false ]

DefaultArgs(lv na, 3, true, false, false, false)

let icclass, pinNo = empty, 0
let index = FindIndexFromCoord(x, y, lv icclass, lv pinNo)
if allPinsAreHoles % alwaysDrill % index eq 0 %
GetBit(wiredPins, index) ne 0 then
[
ComputeMWCoords(lv x, lv y, isMils)

let i=1
while i le lastHoleType &
(holeSize ne holeSizes!i % isPlated ne holePlating!i %
(encodeTWNets & (icclass ne holeNet!i))) do
i=i+1
if i gr lastHoleType then
[
lastHoleType = i
holeSizes!i = holeSize
holePlating!i = isPlated
holeNet!i = encodeTWNets? icclass, empty
]

if i ne currentHoleType % pinsThisLine ge 5 then
[
if pinsThisLine gr 0 then
Puts(holesFile, $*n)
PutTemplate(holesFile, "$5D", i)
currentHoleType = i
pinsThisLine = 0
]

PutTemplate(holesFile, "$S $5D $5D", (pinsThisLine gr 0? " ",""),
x, y)
pinsThisLine = pinsThisLine+1
]
]

and MultiWirePanic(x, y, z) be CallSwat("No board-specific multi-wire code")

and MakeResistanceFile() be
[
resistanceFile = GetFile(nlFileName, ".resist")
DoInSortOrder(typeIcinst,NameCompareFn,ScanICsNets)
TruncateAndClose(resistanceFile)
]

and ScanICsNets(icinst) be
[
let icclass = Icclass(icinst)
if icclass>>icclass.isConnector %
icclass>>icclass.isTraceWired then return

let icpkg = (icclass>>icclass.PinOffset eq DIP3Wide? "DIP3",
(icclass>>icclass.PinOffset eq SIP? "SIP", "OddPkg"))


PutTemplate(resistanceFile,
"$S ($S, $D, $S) ",
FindNameesString(icinst),
icpkg, Npins(icinst),
FindNameesString(icinst>>icinst.ictype))

for i=1 to Npins(icinst) do
[
NetResistance(icinst>>icinst.pin↑i)
if i ne Npins(icinst) then Puts(resistanceFile,$,)
]
Puts(resistanceFile, $*n)
]

and NetResistance(pin) be
[
if pin eq empty then
[
Puts(resistanceFile, $$)
return
]

let net = FindNet(pin)
if net eq dontCareNet then
[
Puts(resistanceFile, $?)
return
]

conductance = 0
// in milliSiemens, infinity means short
if net>>net.isTraceWired then conductance = infinity

pin = net>>net.pinList
while @pin ne mark do
[
if conductance ne infinity then PinResistance(pin)
pin = @pin
]

test conductance eq infinity
ifso Puts(resistanceFile, $0)
ifnot
[
test conductance eq 0
ifso Puts(resistanceFile, $$)
ifnot PutTemplate(resistanceFile,"$D",1000/conductance)
]
]

and PinResistance(pin) be
[
static [ Term100Ohms = empty]
if Term100Ohms eq empty then
Term100Ohms = MustFindNamee("Term100/8/Term100",typeIctype)

let icinst = nil
FindIcinst(lv icinst, lv pin)
let icclass = Icclass(icinst)
let pinAttributes = (icclass>>icclass.PinAttributes)(icinst,pin)
if pinAttributes<<pinattributes.isTerminator then
if icinst>>icinst.ictype eq Term100Ohms then
conductance = conductance+10
// 100 ohms or 10 mS.
if icclass>>icclass.isConnector then
conductance = conductance+10
// added termination at each connector
if icclass>>icclass.isTraceWired then
conductance = infinity
]

and TruncateAndClose(file) be
[
TruncateDiskStream(file)
Closes(file)
]