//routeinit.bcpl

// Initialization and driver module

// last modified by Rumph, March 8, 1985 3:53 PM
// to add files and limits for split wirelist output and IC’s
// modified by McCreight, September 15, 1982 11:31 AM
// to initialize the complete random table, so we’ll get identically the
// same results on successive identical runs.

get "sysdefs.d"
get "streams.d"
get "altofilesys.d"
get "route.defs"

external
[
fpComCm
fpSysDir
sysDisk
dsp

UNPACKDT // in CTime.br
CONVUDT

OverlayScan
GenerateOverlays
OverlayNpages

LookupEntries

LoadRam

InitBcplRuntime
RamImage

initCodeEnd

PrintTWPins
PrintHoles
MakeBuzzLists

overlayCore
npBiggestOverlay
]

static
[
Correcting = false
noroute = false
whereTW = false
buzzLists = false

nlFileName = empty

board = empty
rev = empty
time = empty
pctext = empty

boardLocation = empty

wlNewFileName = empty
wlOldFileName = empty

outLimit = 1500
outThreshold = infinity
savedOutThreshold = 1000

ImplicitFile
ADFile
ErFile
CommentsFile
OldWlFile
OutFile

charTab

dontCareNet

StandardMetric

SilZone = 0
initCodeEnd

kf = empty

epvec
epsize

overlayCore
npBiggestOverlay

randomTable
randomIndex
randomTrailer
]


let OnceOnlyInitCode(blv,params,cfa) be
[ // sets up, also handles board type checking.
initCodeEnd = @#335

AddSpace(3000)
// leave for stack

@#420 = 0 //turn off display for speed

let e = vec 100
epvec = e
epsize = 0
AddDynamicEntry(lv AddEclTerminators) // in RouteTerm
AddDynamicEntry(lv LocateAvailTerms)
AddDynamicEntry(lv FreeTermStorage)

AddDynamicEntry(lv AssignTWNet)
// RouteTWNetAssign

AddDynamicEntry(lv ManhattanDistFn) // in Routec
AddDynamicEntry(lv EuclideanDistFn)

AddDynamicEntry(lv CheckUnusedPins) // in Routea

AddDynamicEntry(lv NLCompFn) // in Routeb
AddDynamicEntry(lv AssignNetNumber)

AddDynamicEntry(lv ReportRepairedPins) // in RouteCorrect
AddDynamicEntry(lv ReportNewCutPins)
AddDynamicEntry(lv PrintNewNet)

AddDynamicEntry(lv MakeConnInstFile) // in RouteBackpanel
AddDynamicEntry(lv MultiWirePanic)
AddDynamicEntry(lv PCPanic)

AddDynamicEntry(lv RouteEarlyNets) // in RouteNet
AddDynamicEntry(lv RouteNetIfExternal)
AddDynamicEntry(lv RouteNet)
AddDynamicEntry(lv ComputeLengths)

OverlayScan(lv (cfa>>CFA.fp), Allocate(SilZone, 200), 200, lv (cfa>>CFA.fa),
0, 0, 0, 0, sysDisk, epvec, epsize)
npBiggestOverlay = 0
GenerateOverlays(HowBig)
overlayCore = Allocate(SilZone, 256*npBiggestOverlay)

ReadTime(lv time)

charTab = Allocate(SilZone, 256)
Zero(charTab, 256)
AddAttribute(upperCaseMask%letterMask, $A, $Z)
AddAttribute(lowerCaseMask%letterMask, $a, $z)
AddAttribute(digitMask, $0, $9)
AddAttribute(colonMask, ":")
AddAttribute(breakMask, " :,;*t*n")
AddAttribute(legalSpecialCharMask, "$#()’[]↑←?/\|+-=&**~")

let comcm = OpenFile("COM.CM",ksTypeReadOnly,charItem,0,fpComCm,0,SilZone)
if comcm eq 0 then CallSwat("Can’t open COM.CM")
let fn = vec 128
ReadNext(comcm,fn) //throw away name
let fnl = fn>>str.length
let i=1
while i le fnl do test fn>>str.char↑i eq $/
ifso [ i=i+1; break ]
ifnot i=i+1

while i le fnl do
[
switchon fn>>str.char↑i into
[
case $C:
case $c:
Correcting = true
endcase

case $M:
case $m:
doMultiWire = true
endcase

case $T:
case $t:
whereTW = true
endcase

case $B:
case $b:
buzzLists = true
endcase

case $R:
case $r:
doResistances = true
endcase

case $P:
case $p:
if doPC then PCPrototype = true
doPC = true
endcase

default:
]
i=i+1
]

StandardMetric = ManhattanDistFn
DefaultString(lv boardLocation, "c1")

if LoadRam(RamImage) eq 0 then InitBcplRuntime() // fire up microcode

SetupSpace()

DeclareAvailableNames() // for dynamic loader

let nlFileCount = 0
until Endofs(comcm) do
[
let filestring = vec 20
unless ReadNext(comcm,filestring) then break
unless IsFunnyParameter(filestring) do
[
NeedFile(filestring, 0, true) // input file
if nlFileCount eq 0 & nlFileName eq empty then
[
DefaultString(lv nlFileName, filestring)
let lastGoodChar = nlFileName>>str.length
for i=1 to nlFileName>>str.length do
[
if nlFileName>>str.char↑i eq $. then
lastGoodChar = i-1
]
nlFileName>>str.length = lastGoodChar
]
nlFileCount = nlFileCount+1
]
]
Closes(comcm)

dontCareNet = DefineNamee("Whatever", typeNet, NewNet)
dontCareNet>>net.hasBeenRouted = true
dontCareNet>>net.dontTerminate = true

SetupICclasses() // build icclass objects for all known IC classes

SetupBoard() // assuming dynamic loader has loaded board characterization,
//plug edge connectors and trace-wired nets into data structures

SetupMoreICClasses() // in the board file

if whereTW then PrintTWPins()
if buzzLists then MakeBuzzLists()

if nlFileCount le 0 then finish

let ts = vec 30
test Correcting & (wlOldFileName eq empty)
ifso
[
ExpandTemplate(ts, "$S.wl", nlFileName)
DefaultString(lv wlOldFileName, ts)
ExpandTemplate(ts, "$S.wlNew", nlFileName)
DefaultString(lv wlNewFileName, ts)
]
ifnot
[
ExpandTemplate(ts, "$S.wl", nlFileName)
DefaultString(lv wlNewFileName, ts)
]

NeedFile(wlNewFileName)
NeedFile(wlNewFileName, "1")
// if we need to split the wirelist
NeedFile(wlNewFileName, "2")
// ditto
NeedFile(nlFileName, ".ics")
NeedFile(nlFileName, ".inl")
NeedFile(nlFileName, ".re")
NeedFile(nlFileName, ".bp")
NeedFile(nlFileName, ".lc")
NeedFile(nlFileName, ".comments")

if Correcting then
[
NeedFile(wlOldFileName, "", false, false)
NeedFile(nlFileName, ".ad")
NeedFile("route.dpf")
]

if doMultiWire then
[
NeedFile(nlFileName, ".mw")
NeedFile(nlFileName, ".mh")
NeedFile(nlFileName, ".mhi")
]

if doPC then
[
NeedFile(nlFileName, ".apc")
]

if doResistances then
[
NeedFile(nlFileName, ".resist")
]

MapNamees(typeIcinst, NeedConnInstFiles)
FindOrMakeNeededFiles()

ErFile = GetFile(nlFileName,".re",charItem) //routing errors
PutTemplate(ErFile, "[0] = worst error severity*n")

ImplicitFile = GetFile(nlFileName,".inl", charItem) // implicit net list
PutTemplate(ImplicitFile, "; Implicitly generated wiring ...*n@")

CommentsFile = GetFile(nlFileName,".comments",charItem)
TruncateDiskStream(CommentsFile)

InitRandom()
]

and DefaultString(sp, s) be
[
if @sp ne empty then Free(SilZone, @sp)
@sp = Allocate(SilZone, (s>>str.length rshift 1)+1)
MoveBlock(@sp, s, (s>>str.length rshift 1)+1)
]

and AddDynamicEntry(p) be
[
epvec!epsize = p
epsize = epsize+1
]

and HowBig(od) be
[
let npThisOverlay = OverlayNpages(od)
if npThisOverlay gr npBiggestOverlay then
npBiggestOverlay = npThisOverlay
]

and NeedConnInstFiles(icinst) be
[
unless Icclass(icinst)>>icclass.isConnector do return
let filename = vec 20
ExpandTemplate(filename, "$S-$S.nl", nlFileName, FindNameesString(icinst))
NeedFile(filename)
]

and AddAttribute(attributeMask, first, last) be
[
test first le 255
ifso for char=first to last do charTab!char = charTab!char%attributeMask
ifnot for i=1 to first>>str.length do AddAttribute(attributeMask, first>>str.char↑i,
first>>str.char↑i)
]


and ReadNext(stream,string) = valof
[
let ch = $*s
if Endofs(stream) then resultis false
until (Endofs(stream)%(ch gr $*s))do ch = Gets(stream)
if ch le $*s then resultis false

string>>str.length = 1
string>>str.char↑1 = ch

[
if Endofs(stream) then break
ch = Gets(stream)
if ch le $*s then break
let sl = string>>str.length+1
string>>str.char↑sl = ch
string>>str.length = sl
] repeat
resultis true
]



and IsFunnyParameter(string) = valof
[
let lastSlashPos = 0
for i=1 to string>>str.length do
if string>>str.char↑i eq $/ then lastSlashPos = i

if lastSlashPos eq 0 then resultis false

string>>str.length = lastSlashPos-1
switchon string>>str.char↑(lastSlashPos+1) into
[
case $h:
case $H:
heuristicWork = CSN(string)
endcase

case $m:
case $M:
StandardMetric = selecton string>>str.char↑1 into
[
case $M:
case $m:
ManhattanDistFn

case $E:
case $e:
EuclideanDistFn

default:
ManhattanDistFn
]
endcase

case $E:
case $e:
exhaustThresh = CSN(string)
endcase

case $L:
case $l:
DefaultString(lv boardLocation, string)
endcase

case $B:
case $b:
ReadBoardCode(string)
endcase

case $C:
case $c:
Correcting = true
DefaultString(lv wlOldFileName, string)
endcase

case $F:
case $f:
DefaultString(lv nlFileName, string)
endcase

case $I:
case $i:
DefaultString(lv board, string)
endcase

case $R:
case $r:
DefaultString(lv rev, string)
endcase

case $P:
case $p:
[
let file = OpenFile(string, ksTypeReadOnly, charItem, 0,
0, 0, SilZone)
let length = 0
until Endofs(file) do [ Gets(file); length = length+1]
pctext = Allocate(SilZone, (length rshift 1)+1)
pctext>>string.length = length
Resets(file)
length = 0
until Endofs(file) do
[
length = length+1
pctext>>string.char↑length = Gets(file)
]
Closes(file)
]
endcase

case $S:
case $s:
outLimit = CSN(string)
endcase

case $T:
case $t:
savedOutThreshold = CSN(string)
endcase

default:
]

resultis true
]

and CSN(string) = valof
[
let value = 0
for i=1 to string>>str.length do
[
let c = string>>str.char↑i
unless (charTab!c&digitMask)ne 0 do
[
CallSwat("*nIllegal number in command file.",
string)
finish
]
value = value*10+c-$0
]
resultis value
]

and NeedFile(fn, suffix, isInput, okToCreate; numargs na) be
[
DefaultArgs(lv na, -1, "", false, false)
let filename = vec 20
ExpandTemplate(filename, "$S$S", fn, suffix)
let fnwords = (filename>>str.length rshift 1)+1
let newkf = Allocate(SilZone, offset KF.string/16+fnwords)
MoveBlock(lv newkf>>KF.string, filename, fnwords)
newkf>>KF.input = isInput
newkf>>KF.oktocreate = na gr 3? okToCreate, not isInput
newkf>>KF.next = kf
kf = newkf
]

and FindOrMakeNeededFiles() be
[
let kfCount = 0
let kfIndex = kf
let kfRev = empty
// reversed list
until kfIndex eq empty do
[
kfCount = kfCount+1
let kfTemp = kfIndex>>KF.next
kfIndex>>KF.next = kfRev
kfRev = kfIndex
kfIndex = kfTemp
]
kf = kfRev

let names = Allocate(SilZone, kfCount)
let kfCount = 0
let kfIndex = kf
until kfIndex eq empty do
[
names!kfCount = lv kfIndex>>KF.string
kfCount = kfCount+1
kfIndex = kfIndex>>KF.next
]

let dvs = Allocate(SilZone, kfCount*lDV)
Zero(dvs, kfCount*lDV)

let q = OpenFile(0,0,0,0,fpSysDir,0,SilZone)
if q eq 0 then CallSwat("Can’t open SysDir")
LookupEntries(q, names, dvs, kfCount, true)
Closes(q)

kfIndex = kf
kfCount = 0
until kfIndex eq empty do
[
test dvs!(kfCount*lDV) eq 0
ifnot
[
MoveBlock(lv kfIndex>>KF.fp,
lv dvs!(kfCount*lDV+offset DV.fp/16), lFP)
]
ifso
[
if not kfIndex>>KF.oktocreate then CallSwat("Can’t find input file ",
lv kfIndex>>KF.string)
let file = OpenFile(lv kfIndex>>KF.string,ksTypeReadWrite,
0,0,0,0,SilZone)
let cfa = vec lCFA
GetCompleteFa(file, cfa)
MoveBlock(lv kfIndex>>KF.fp, lv cfa>>CFA.fp, lFP)
Closes(file)
]
kfCount = kfCount+1
kfIndex = kfIndex>>KF.next
]
]

and AddSpace(stackNeeds) be
[
static [ malFormed = 0 ]
let Space = FixedLeft()
while Usc(Space, stackNeeds+20) gr 0 do
[
let grab = Space-stackNeeds
if Usc(grab, #77777) gr 0 then grab = #77777 //+ infinity
test SilZone eq 0
ifso SilZone = InitializeZone(GetFixed(grab), grab, SysErr, malFormed)
ifnot AddToZone(SilZone, GetFixed(grab), grab)

Space = FixedLeft()
]
]

and ReadTime(ps) be
[
let uv = vec 7
UNPACKDT(0, uv)
@ps = Allocate(SilZone, 12) // for date and time
CONVUDT(@ps, uv)
]

and InitRandom() be
[
randomTable = Allocate(objectZone, degree+1)
for i=0 to degree do randomTable!i = #101011
randomIndex = 0
randomTrailer = degree-midPower

for i=1 to 2000 do Random(1)
]