//routec.bcpl

// Resident route-related utility module.

// last modified by Taft, September 22, 1979 7:32 PM

get "route.defs"

static [ char; maxitems; nitems; itemHeap; CompareFn; greatestFinishedItem ]
let NewICInst(icinst, ictype) be
[
icinst>>icinst.ictype = ictype
(Icclass(icinst)>>icclass.ImplicitICNets)(icinst)
]

and NewNet(net) be
[
net>>net.pinList = lv FindNameesName(net)>>name.mark
net>>net.minSperge = -1
]
and FindIcinst(picinst, pPinNo, px, py; numargs na) = valof
[
let icinst = @pPinNo-offset icinst.pin↑1/16
let pinNo = 1
while icinst>>icinst.type ne typeIcinst do
[
icinst = icinst-1
pinNo = pinNo+1
]
@picinst = icinst
@pPinNo = pinNo
resultis na le 2? true,
BoardPinCoord(FindNameesString(icinst), icinst, pinNo, px, py)
]

and GetPinCoord(icinst, pinNo, px, py) = valof
[
if icinst eq 0 then
[
icinst = pinNo-offset icinst.pin↑1/16
pinNo = 1
while icinst>>icinst.type ne typeIcinst do
[
icinst = icinst-1
pinNo = pinNo+1
]
]

resultis BoardPinCoord(FindNameesString(icinst), icinst, pinNo, px, py)
]

and BoardPinCoord(string, icinst, pinNo, px, py) = valof // can be replaced by
// board-specific routine with same name
[
let vop1, hop1 = nil, nil
switchon (Icclass(icinst)>>icclass.PinOffset)(icinst, pinNo, lv vop1, lv hop1) into
[
case absolute:
@px = vop1
@py = hop1
resultis true

case relative: resultis (FindCoordFromString(string, px, py, vop1, hop1) eq absolute)

default: resultis false
]
]

and Icclass(namee) = valof
[
while true do switchon namee>>namee.type into
[
case typeIcinst: namee = namee>>icinst.ictype; loop
case typeOldinst: namee = namee>>oldinst.ictype; loop
case typeIctype: namee = namee>>ictype.icclass; loop
case typeIcclass: resultis namee
default: CallSwat()
]
]

and Npins(namee) = valof
[
while true do switchon namee>>namee.type into
[
case typeIcinst: namee = namee>>icinst.ictype; loop
case typeOldinst: namee = namee>>oldinst.ictype; loop
case typeIctype: resultis namee>>ictype.npins
case typeIcclass: resultis namee>>icclass.npins
default: CallSwat()
]
]

and FindNet(pin) = valof
[
while @pin ne mark do pin = @pin
resultis DefineNamee(pin+(offset name.nameString-offset name.mark)/16,
typeNet, CallSwat)
]

and DoInSortOrder(type, CFn, Action) be
[
nitems = 0

MapNamees(type, Count)
maxitems = nitems
let biggestBlockLen = nil
itemHeap = Allocate(SilZone, nitems+1, lv biggestBlockLen)
if itemHeap eq empty then
[
if biggestBlockLen ls 100 then
CallSwat("Sort block too small")
itemHeap = Allocate(SilZone, biggestBlockLen)
maxitems = biggestBlockLen-1
]

CompareFn = CFn
greatestFinishedItem = empty

[
itemHeap!0 = 0
MapNamees(type, NextBatchToHeap)
let itemsInHeap = itemHeap!0

for i=itemsInHeap to 2 by -1 do
itemHeap!i = PullFromHeap(itemHeap, CompleteCompare)
for i=1 to itemsInHeap do Action(itemHeap!i)
greatestFinishedItem = itemHeap!itemsInHeap
nitems = nitems-itemsInHeap
] repeatuntil nitems eq 0

Free(SilZone, itemHeap)
]

and Count(namee) be nitems = nitems+1

and NextBatchToHeap(namee) be
[
if greatestFinishedItem ne empty &
CompleteCompare(namee, greatestFinishedItem) le 0 then return

if itemHeap!0 ge maxitems then // get largest next time around
[
if CompleteCompare(namee, itemHeap!1) ge 0 then return
PullFromHeap(itemHeap, CompleteCompare)
]

AddToHeap(itemHeap, namee, CompleteCompare)
]

and CompleteCompare(x, y) = valof
[
let c = CompareFn(x, y)
resultis (c ne 0)? c, (x eq y? 0, (x gr y? 1, -1))
]

and NameCompareFn(namee1, namee2) = StComp(FindNameesString(namee1),
FindNameesString(namee2))

and ManhattanDistFn(X1, Y1, X2, Y2) = valof
[
let deltaX = X1-X2
let deltaY = Y1-Y2
resultis ((deltaX ls 0)? -deltaX, deltaX)+((deltaY ls 0)? -deltaY, deltaY)
]


and EuclideanDistFn(X1, Y1, X2, Y2) = valof
[
let deltaX = X1-X2
let deltaY = Y1-Y2
deltaX = (deltaX ls 0)? -deltaX, deltaX
deltaY = (deltaY ls 0)? -deltaY, deltaY

let bigDelta = nil
let smallDelta = nil

test deltaX ge deltaY
ifso [ bigDelta = deltaX; smallDelta = deltaY ]
ifnot [ bigDelta = deltaY; smallDelta = deltaX ]

let ftIndex = (smallDelta ge #3777)?
smallDelta/(bigDelta rshift 4),
(smallDelta lshift 4)/bigDelta

let fractionTable = table
[ // entryK = 32*(sec(atan(K/16))-1)
0; 0; 0; 1; 1; 1; 2; 3; 4; 5; 6; 7; 8; 9; 11; 12; 13
]

let fraction = fractionTable!ftIndex

resultis bigDelta+(fraction*((bigDelta+16) rshift 4))
]

and NoAddedCaps() be
[
]

and ComputeClusters(clusterBaseVec, net) be
[
SetBlock(lv (clusterBaseVec!1), infinity, clusterBaseVec!0)
clusterBaseVec!0 = 1
clusterBaseVec!1 = 1
let cluster = net>>net.clusterList
while cluster ne empty do
[
AddToHeap(clusterBaseVec, cluster>>cluster.index+1, Usc)
cluster = cluster>>cluster.next
]
let itemsInCluster = clusterBaseVec!0
for i=itemsInCluster to 2 by -1 do
clusterBaseVec!i = PullFromHeap(clusterBaseVec, Usc)
clusterBaseVec!0 = itemsInCluster
]