//routea.bcpl

// Net-list file read-in phase

// last modified by E. McCreight, May 11, 1979 6:30 PM

get "route.defs"

static [ copyComments ]

let FileIn(ins) be
[
char = used
copyComments = true

//Read components and board locations
while GetValidChar(ins) eq $*n do char = used // for leading CR’s
while GetValidChar(ins) ne $@ do ReadICLine(ins)

while GetValidChar(ins) eq $*n do char = used
ReadAllNetLines(ins)
]

and ReadAllNetLines(ins) be
[
char = used
copyComments = true

//read signal names and nodes
while GetValidChar(ins) ne filegone do ReadNetLine(ins)
]

and ReadICLine(ins) be
[
WeAre(doingInput)

let boardloc = vec 40
let attributes = vec 20

ReadNetName(ins, boardloc, attributes, empty, colonMask%atsignMask)
NormalizeBoardLoc(boardloc)

let ictype = ReadICType(ins)
let icinst = TryFindingNamee(boardloc, typeIcinst)

if icinst eq empty then
icinst = InsertDeviceIfPossible(boardloc,ictype,0,true)

if icinst>>icinst.ictype ne ictype then
[
Warning("*nBoard location *"$S*" has multiple IC types assigned.",
boardloc)
]
]

and ReadNetLine(ins) be
[
static [ NullName = 0 ]

WeAre(doingInput)
let snv = vec 128
let attributes = vec 10
let clusterNumber = 0
unless ReadNetName(ins,snv,attributes,lv clusterNumber) do return

if (snv>>str.length eq 0) % (snv eq " ") then //assign a name to the signal
[
ExpandTemplate(snv, "XXX$D", NullName)
NullName = NullName+1
]

let net = DefineNamee(snv, typeNet, NewNet)
for i=1 to attributes>>str.length do
[
switchon attributes>>str.char↑i into
[
case $!: net>>net.dontTerminate = true
endcase

case $%: net>>net.wireEarly = true
endcase

default:
]
]
if clusterNumber ne 0 then net>>net.wireEarly = true

//read all the pins on this line
while valof
[
GetValidChar(ins)
resultis (char ne $*n) & (char ne filegone)
] do
[
char = used // throw away the : or ,
GetPin(ins, net, attributes,clusterNumber)
]
char = used // throw away the final CR
]

and GetPin(ins, net, attributes,clusterNumber) be
[
let netname = FindNameesString(net)
let pin = vec 20;pin!0 = 0;
if GetValidChar(ins) eq filegone then return
[
if (char eq $*n)%(char eq $,) then break
if char ne $*s then AppendC(pin,char)
if Endofs(ins) then break
char = Gets(ins)
] repeat

if pin>>str.length le 0 then return //not real pin

let boardloc = vec 20
let pinNo = nil
let modifier = nil
ParsePin(pin, boardloc, lv pinNo, lv modifier)

let icinst = DefineNamee(boardloc, typeIcinst, CallSwat)
let x, y = nil,nil
if pinNo ls 1 % pinNo gr Npins(icinst) %
not GetPinCoord(icinst, pinNo, lv x, lv y) then
[
Serious("*nPin $S is illegal.", pin)
return
]


let ictype = icinst>>icinst.ictype
if ictype>>namee.type eq typeIctype then
if (modifier eq $o) then
SetBit(lv ictype>>ictype.outpins, pinNo, 1)

test icinst>>icinst.pin↑pinNo ne empty &
FindNet(lv icinst>>icinst.pin↑pinNo) ne dontCareNet
ifso // previously wired, check if to same net
[
let oldNet = FindNet(icinst>>icinst.pin↑pinNo)
test net eq oldNet
ifso // ...to the same net as before
[
unless net>>net.isTraceWired do
Warning("*nPin $S has been wired to net $S more than once.",
pin, netname)
]
ifnot // ...to a different net
[
(MayBeSerious(ins))("*nPin $S cannot be wired to net $S because it is already wired to to net $S.",
pin, netname, FindNameesString(oldNet))
return
]
]
ifnot // pin not wired by this name, cannot be wired by another name
// due to NewICInst check
[
unless net eq dontCareNet %
CutTraceIfDifferent(FindNameesName(net), x, y, pin) do return

test net eq dontCareNet
ifso icinst>>icinst.pin↑pinNo = net>>net.pinList
ifnot
[
AddPinToNet(net, lv (icinst>>icinst.pin↑pinNo), clusterNumber)

let sperge = Sperge(x,y)
if Usc(sperge, net>>net.minSperge) ls 0 then net>>net.minSperge = sperge

net>>net.hasBeenRouted = false
if net>>net.isSame then
Serious("*nNet $S changed after committed in .AD file.", netname)
]
]

AddAttributes(icinst, pinNo, attributes)
]

and AddPinToNet(net, newpin, clusterNumber) be
[
let thisCluster = empty
let firstGreaterClusterIndex = 0

// Find all the clusters that must come first

if clusterNumber gr 0 then
[
firstGreaterClusterIndex = infinity
let cluster = net>>net.clusterList
while cluster ne empty do
[
if cluster>>cluster.number ge clusterNumber then
if cluster>>cluster.index ls firstGreaterClusterIndex then
[
firstGreaterClusterIndex = cluster>>cluster.index
]
if cluster>>cluster.number eq clusterNumber then
[
thisCluster = cluster; break
]
cluster = cluster>>cluster.next
]

if thisCluster eq empty then
[
thisCluster = Allocate(objectZone, size cluster/16)
thisCluster>>cluster.next = net>>net.clusterList
net>>net.clusterList = thisCluster
thisCluster>>cluster.number = clusterNumber

if firstGreaterClusterIndex eq infinity then
[
// count all pins in the net
firstGreaterClusterIndex = 0
let pin = @(net>>net.pinList)
while pin ne mark do
[
firstGreaterClusterIndex =
firstGreaterClusterIndex+1
pin = @pin
]
]

thisCluster>>cluster.index = firstGreaterClusterIndex
]
]

let pin = lv (net>>net.pinList)
while firstGreaterClusterIndex gr 0 do
[
pin = @pin
firstGreaterClusterIndex = firstGreaterClusterIndex-1
]

@newpin = @pin
@pin = newpin

let cluster = net>>net.clusterList
while cluster ne empty do
[
if cluster>>cluster.number gr clusterNumber then
cluster>>cluster.index = cluster>>cluster.index+1
cluster = cluster>>cluster.next
]
]

and MayBeSerious(stream) = stream eq ImplicitFile? Warning, Serious

and CheckUnusedPins(icinst) be
[
unless Icclass(icinst)>>icclass.printUsedList do return
for pin=1 to Npins(icinst) do
[
if icinst>>icinst.pin↑pin ne empty then loop // wired-up
let x,y = nil,nil
unless GetPinCoord(icinst, pin, lv x, lv y) do loop // pin missing
let str = vec 20
CutTraceIfDifferent(DefineName("UNCONNECTED"), x, y,
ExpandTemplate(str, "$S.$D", FindNameesString(icinst), pin))
]
]

and CutTraceIfDifferent(name, x, y, pin) = valof
[
let TWicclass, TWpinNo = 0,0
let index = FindIndexFromCoord(x, y, lv TWicclass, lv TWpinNo)
if TWicclass ne 0 then if FindNameesName(TWicclass) ne name then
[
let info = 0
(TWicclass>>icclass.PinOffset)(TWicclass, TWpinNo, lv x, lv y, lv info)
unless (info<<info.disconnect) do
[
Warning("*nPin $S of net $S cannot be disconnected from $S.",
pin, lv name>>name.nameString,
FindNameesString(TWicclass))
]
if TWicclass>>icclass.cutPins ne empty then
SetBit(TWicclass>>icclass.cutPins, TWpinNo, 1)
]
resultis true
]
and AddAttributes(icinst, pinNo, attributes) be
[
for i=1 to attributes>>str.length do
AddAttribute(icinst, pinNo, attributes>>str.char↑i, 0)
]

and AddAttribute(icinst, pinNo, attribute, value) be
[
let pinattribute = icinst>>icinst.pinattribute
while pinattribute ne empty do
[
if pinattribute>>pinattribute.pinNo eq pinNo &
pinattribute>>pinattribute.attribute eq attribute &
pinattribute>>pinattribute.value eq value then return

pinattribute = pinattribute>>pinattribute.next
]

pinattribute = Allocate(objectZone, size pinattribute/16)

pinattribute>>pinattribute.pinNo = pinNo
pinattribute>>pinattribute.attribute = attribute
pinattribute>>pinattribute.value = value

pinattribute>>pinattribute.next = icinst>>icinst.pinattribute
icinst>>icinst.pinattribute = pinattribute
]