// Basic run module for SIL-route aid

get "route.defs"

manifest
[
//User must fill in the parameters below
//All coordinates are in 25 mil grid units
//Under no circumstances delete any of the parameters listed

MAXics=0
//Maximum number of ICs allowed on the board
MaxYPinCoor=0
//Largest Y-coordinate (used for LevelTransform)

NumVCCPins=0
//Number of VCC pins defined for the board
NumVEEPins=0
//Number of VEE pins defined for the board
NumVDDPins=0
//Number of VDD pins defined for the board
NumEPins=0
//Number of E pins defined for the board
NumCPins=0
//Number of C pins defined for the board
NumGNDPins=0
//Number of GND pins defined for the board
NumICPins=0
//Number of IC pins (Non-trace wired pins) defined for the board

CconnsAreVertical=true
//True if cable connectors are vertical and false if horizontal
//The following coordinates are in X if vertical and Y if horizontal conns
CableMin=-1
//The minimum coordinate a C pin may have
CableMax=-1
//The maximum coordinate a C pin may have
EconnsAreVertical=true
//True if edge connectors are vertical and false if horizontal
EdgeMin=-1
//The minimum coordinate an E pin may have
EdgeMax=-1
//The maximum coordinate an E pin may have

Xorigin=0
//The X-coor of column 1, row 1 of the pin table
Yorigin=0
//The Y-coor of column 1, row 1 of the pin table

//calibration points
CalPt1x=0
//The X-coor of calibration point 1
CalPt1y=0
//The Y-coor of calibration point 1

CalPt2x=0
//The X-coor of calibration point 2
CalPt2y=0
//The Y-coor of calibration point 2

CalPt3x=0
//The X-coor of calibration point 3
CalPt3y=0
//The Y-coor of calibration point 3

CalPt4x=0
//The X-coor of calibration point 4
CalPt4y=0
//The Y-coor of calibration point 4

//End of User Parameters

]

//Check items in bold italic face to see if parameters are that which are desired

manifest
[
VCCPintype=1
VEEPintype=2
VDDPintype=3
GNDPintype=4
ICPintype=5

firstEPin=1
firstCPin=firstEPin+NumEPins
firstGNDPin=firstCPin+NumCPins
firstVCCPin=firstGNDPin+NumGNDPins
firstVDDPin=firstVCCPin+NumVCCPins
firstVEEPin=firstVDDPin+NumVDDPins
firstICPin=firstVEEPin+NumVEEPins
maxpin=firstICPin+NumICPins
]

static [ maxICs = MAXics ; boardInterfaceVersion = interfaceVersion ]

let DeclareInitialNets(BuildTWNet, BuildTermNet, BuildConnector) be
[
if NumEPins ne 0 then BuildConnector("E",NumEPins, EPinPos)
if NumCPins ne 0 then BuildConnector("C",NumCPins, CPinPos)
if NumGNDPins ne 0 then BuildTWNet("GND",NumGNDPins,GNDPinPos)
if NumVCCPins ne 0 then BuildTWNet("VCC",NumVCCPins,VCCPinPos)
if NumVDDPins ne 0 then BuildTWNet("VDD",NumVDDPins,VDDPinPos)
if NumVEEPins ne 0 then BuildTWNet("VEE",NumVEEPins,VEEPinPos)
]

and ZeroTablePoint(point) = selecton point into
[
case 0: "Board Name"
case 1: "Z-1"
case 2: "Z-2"
case 3: "Z-3"
case 4: "Z-4"
default: empty
]

and LevelTransform(level,x,y,px,py,pName,pPullComponents,pWire;numargs na)=valof
[
DefaultArgs(lv na,-1,0,0,lv na,lv na,lv na,lv na,lv na)
switchon level into
[
case TopLevel:
@px = x
@py=
MaxYPinCoor-y //if you wish to define the board from the component side, replace this with "@py=y"
@pName = "
Component side"
@pPullComponents =
true //pull components for any disconnects on this side
@pWire =
false
resultis true
case BottomLevel:
@px = x
@py =
y //if you wish to define the board from the component side, replace this with "@py=MaxYPinCoor-y"
@pName = "
Wiring side"
@pPullComponents =
false
@pWire =
true
resultis true
default: resultis false
]
]

and EPinPos(icinst,pin,px,py)=valof
[
if pin gr NumEPins then [ SwatN("Illegal E-pin ",pin,0,0); resultis illegal ]

//if you wish to disable any E-pins, add the code:
//
"if pin eq Pnum1 % pin eq Pnum2 ... %pin eq PnumN then resultis illegal"
//replace Pnum1, Pnum2...PnumN with the N E-pin numbers you wish to disable.
//Note that you enter 101 if you wish to disable E101.

let res=FindConnPos(Econns,pin,px,py)
if res eq illegal then SwatN("Illegal E-pin ",pin,0,0)
resultis res
]

and CPinPos(icinst,pin,px,py)=valof
[
if pin gr NumCPins then [ SwatN("Illegal C-pin ",pin,0,0); resultis illegal ]

//if you wish to disable any C-pins, add the code:
//
"if pin eq Pnum1 % pin eq Pnum2 ... %pin eq PnumN then resultis illegal"
//replace Pnum1, Pnum2...PnumN with the N C-pin numbers you wish to disable.
//Note that you enter 101 if you wish to disable C101.

let res=FindConnPos(Cconns,pin,px,py)
if res eq illegal then SwatN("Illegal C-pin ",pin,0,0)
resultis res
]

and FindConnPos(cv,pin,px,py)=valof
[
if cv>>Cspecs.NumOfSpecs eq 0 then resultis illegal
for i=1 to cv>>Cspecs.NumOfSpecs do
[ //look at each defined connector
let cp=Conns>>Cdescs.Num↑(cv>>Cspecs.ConnNum↑i) //points to connector descriptor
let MinCol1Num=cv>>Cspecs.Pin1Col1Num↑i
let NumsConsec=cp>>Cdesc.NumsConsec
let MaxCol1Num=MinCol1Num+((cp>>Cdesc.NumPinsCol1-1)*(NumsConsec ? 1,2)*(cp>>Cdesc.NumsDescending ? -1,1))
if cp>>Cdesc.NumsDescending then
[ //nums are descending, swap to get right
let swap=MaxCol1Num
MaxCol1Num=MinCol1Num
MinCol1Num=swap
]
if (pin ge MinCol1Num) & (pin le MaxCol1Num) & ((NumsConsec) % (((pin-MinCol1Num) rem 2) eq 0)) then
[ //pin is in this connector
@px=cv>>Cspecs.Xcoor↑i
@py=cv>>Cspecs.Ycoor↑i
let off=0
test cp>>Cdesc.NumsDescending
ifso [ off=(MaxCol1Num-pin)*cp>>Cdesc.DispBetPins ]
ifnot [ off=(pin-MinCol1Num)*cp>>Cdesc.DispBetPins ]
if not NumsConsec then off=off/2 //every other pin number
test cp>>Cdesc.ConnIsVert
ifso [ @py=@py+off ]
ifnot [ @px=@px+off ]
resultis absolute
] //end pin is in this connector
let MinCol2Num=cv>>Cspecs.Pin1Col2Num↑i
let MaxCol2Num=MinCol2Num+((cp>>Cdesc.NumPinsCol2-1)*(NumsConsec ? 1,2)*(cp>>Cdesc.NumsDescending ? -1,1))
if cp>>Cdesc.NumsDescending then
[ //nums are descending, swap to get right
let swap=MaxCol2Num
MaxCol2Num=MinCol2Num
MinCol2Num=swap
]
if (pin ge MinCol2Num) & (pin le MaxCol2Num) & ((NumsConsec) % (((pin-MinCol2Num) rem 2) eq 0)) then
[ //pin is in this connector
@px=cv>>Cspecs.Xcoor↑i
@py=cv>>Cspecs.Ycoor↑i
let off=0
test cp>>Cdesc.NumsDescending
ifso [ off=(MaxCol2Num-pin)*cp>>Cdesc.DispBetPins ]
ifnot [ off=(pin-MinCol2Num)*cp>>Cdesc.DispBetPins ]
if not NumsConsec then off=off/2 //every other pin number
off=off+(cp>>Cdesc.DispNeg ? -cp>>Cdesc.Disp4sec, cp>>Cdesc.Disp4sec)
test cp>>Cdesc.ConnIsVert
ifso [ @px=@px+cp>>Cdesc.DispBetRC; @py=@py+off ]
ifnot [ @py=@py+cp>>Cdesc.DispBetRC; @px=@px+off ]
resultis absolute
] //end pin is in this connector
] //end look at each defined connector
resultis illegal //pin not defined
] //end FindConnPos
//The following defines the parameters used to describe information associated with each trace-wired net:
//noDisconnect means a disconnection is not needed when using this pin as a signal pin. Use Disconnect if the opposite is desired
//noReconnect means on a rework, do not fix (ie. solder) a previously cut (disconnected) trace-wired pin, rather, go to the nearest existing pin of this type. Use Reconnect if the opposite is desired
//TopLevel means this trace wiring is on the side defined as TopLevel in LevelTransform...Usually the component side
//BottomLevel means this trace wiring is on the side defined as TopLevel in LevelTransform...Usually the component side

and VCCPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
noDisconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumVCCPins) then
[
SwatN("Illegal VCC pin",pin,0,0)
resultis illegal
]
GetXY4Pin(VCCPins,pin,VCCPintype,px,py)
resultis absolute
]

and VEEPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
noDisconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumVEEPins) then
[
SwatN("Illegal VCC pin",pin,0,0)
resultis illegal
]
GetXY4Pin(VEEPins,pin,VEEPintype,px,py)
resultis absolute
]

and VDDPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
noDisconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumVDDPins) then
[
SwatN("Illegal VDD pin",pin,0,0)
resultis illegal
]
GetXY4Pin(VDDPins,pin,VDDPintype,px,py)
resultis absolute
]

and GNDPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
Disconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumGNDPins) then
[
SwatN("Illegal VEE pin",pin,0,0)
resultis illegal
]
GetXY4Pin(GndPins,pin,GNDPintype,px,py)
resultis absolute
]

and BoardPinCoord(string,icinst,pinNo,px,py) = valof
[
let vop1,hop1 = nil,nil
let numpins = Npins(icinst)
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,numpins) eq absolute)
default: resultis false
]
]

and FindCoordFromString(s,px,py,vop1,hop1,numpins; numargs na) = valof
[
// vop1 is the "vertical offset" from pin 1, that is, the offset along the 0.1’
// spacing: hop1 is the :horizontal offset: from 1. In a standard 16-pin DIP,
// for pin 2 vop1=4 and hop1=0 and for pin 16, vop1=0 and hop1=12. For this
// board, vop1 grow in the -x direction hop1 in the +y direction.

// s can be of form <lower-case letter><number> or
// <number>s (meaning vertically offset <number>*0.1 or
// ↑<number>s (meaning vertically offset <number>*0.1) or
// ←<number>s (meaning horizontal offset <number>*0.1) or
// #s a special form "Z-s" is for ZeroTable point
// %s for insert IC upside down
DefaultArgs(lv na,3,0,0,20)
let zchar = s>>str.char↑1
let znum = s>>str.char↑3
if zchar eq $Z do
[
if znum eq $1 do [ @px= CalPt1x ; @py = CalPt1y ]
if znum eq $2 do [ @px= CalPt2x ; @py = CalPt2y ]
if znum eq $3 do [ @px = CalPt3x ; @py = CalPt3y ]
if znum eq $4 do [ @px = CalPt4x ; @py = CalPt4y ]
resultis absolute
]
let bpVOffset,bpHOffset = 0,0
let i,c,offsetIsVertical = 0,$#,nil
while i le s>>str.length & (c ls $a %c gr $z) do
[
if c eq $↑ % c eq $← % c eq $# % c eq $% then
[
offsetIsVertical = not(c eq $←)
//to disengage code to allow ICs to be inserted upside down, remove all code that is bold italic face

if c eq $% then
[ //code to insert IC upside down
vop1=numpins*2-4-vop1
hop1=((hop1 eq 0)?(numpins le 20?12,24),0)
]
i = i+1
c = s>>str.char↑i
loop
]
if c ge $0 & c le $9 then
[
let bpOffset = 0
while i le s>>str.length & c ge $0 & c le $9 do
[
bpOffset = 10*bpOffset+c-$0
i = i+1
c = s>>str.char↑i
]
@(offsetIsVertical? lv bpVOffset, lv bpHOffset) = bpOffset
offsetIsVertical = true
loop
]
resultis illegal
]

vop1 = vop1-4*bpVOffset //Vertical displacement currently in the -y direction...change sign to + if +y direction is desired

hop1 = hop1+4*bpHOffset //horizontal displacement is currently in the +x direction...change sign to - if -x direction is desired

// IC position of the form <letter><number>

if i gr s>>str.length % c ls $a % c gr $z then resultis illegal
let alph,num = c,0
while i ls s>>str.length do
[
i = i+1 ; let c = s>>str.char↑i
if (c ls $0)%(c gr $9) then resultis illegal
num = 10*num+(c-$0)
]

//change alpha to numeric
alph=alph-$a+1
if (alph gr NumDipRows) % (num ls 1) % (num gr NumDipCols) then resultis illegal

//find dip descriptor
let DescPtr=DipColVec>>DipCols.ColDescPtr↑num
let DipNum=DescPtr>>DipRow.DipDescNum↑alph
if DipNum eq 0 then resultis illegal //not a dip site
let DipPtr=DipDesc>>DipVec.DipDnum↑DipNum

//DipPtr points to the dip configurations at this site...see if this site allows the dip
//specified and if so, check the x-y offsets. If all is OK then stuff the coordinates
//in the x-y

let Ycoor=4*DescPtr>>DipRow.Ycoor↑alph //put in 25 mil grid coor
let Xcoor=2*DipColVec>>DipCols.Xcoor↑num

for i=1 to MaxDips do
[ //check for the number of pins allowed
if DipPtr>>DipDesc.NumPins↑i eq numpins then
[ //valid dip site for this number of pins
vop1=vop1+4*DipPtr>>DipDesc.Yoffset↑i
hop1=hop1+4*DipPtr>>DipDesc.Xoffset↑i
if (vop1 gr (DipPtr>>DipDesc.MaxYoffset*4)) % (vop1 ls 0) then resultis illegal
if (hop1 gr (DipPtr>>DipDesc.MaxXoffset*4)) % (hop1 ls 0) then resultis illegal
@px=Xcoor+hop1+Xorigin-2
@py=Ycoor+vop1+Yorigin-4
resultis absolute
]
]

//if we get this far, dip with numpins not allowed at this site
resultis illegal

]

and FindIndexFromCoord(x,y,picclass,pPinNo; numargs na) = valof
[
static [ hotIndex = -1; maxpin = 0]

DefaultArgs(lv na, -2,lv na , lv na)

if maxpin eq 0 then maxpin = FIFC(-1,-1)
let result = FIFC(x,y,picclass,pPinNo)
if result ls 0 % result gr maxpin then SwatN("Illegal index..",result,x,y)
if result eq hotIndex then CallSwat("Hot index computed...")
resultis result
]

and FIFC(x,y,picclass,pPinNo;numargs na) = valof
[
// Given coordinates x,y return pin index.
// picclass is set to the icclass describing the trace wire net
// and pPinNo is set to the number of the pin within the trace
// wire net.
if x eq -1 & y eq -1 then resultis maxpin
DefaultArgs(lv na, -2, lv na, lv na)
@picclass = empty

// Test for C connector
if (CconnsAreVertical & x le CableMax & x ge CableMin) % ((not CconnsAreVertical) & y le CableMax & y ge CableMin) then
[
resultis FIFC4conn(Cconns,x,y,firstCPin)
]

// Test for edge connector
if (EconnsAreVertical & x le EdgeMax & x ge EdgeMin) % ((not EconnsAreVertical) & y le EdgeMax & y ge EdgeMin) then
[
resultis FIFC4conn(Econns,x,y,firstEPin)
]

let dx=x-Xorigin
if (dx rem 2) ne 0 then resultis 0
dx=(dx/2)+1 //column number
let dy=y-Yorigin
if (dy rem 4) ne 0 then resultis 0
dy=(dy/4)+1 //row number

if dy le 0 % dx le 0 % dy gr NumPinRows % dx gr NumPinCols then resultis 0

let DescPtr=PinCols>>Cols.Cnum↑dx
if DescPtr eq 0 then resultis 0
if not GetBit(DescPtr,dy) then resultis 0

//count number of defined pins to this one in the column descriptor
let cnt=0
for i=1 to dy do
[
if GetBit(DescPtr,i) then cnt=cnt+1
]

let Ptype=DescPtr>>ColDesc.Ptype↑cnt
if Ptype ne ICPintype then
[ //trace wired pin
let Pnum=DescPtr>>ColDesc.Pnum↑cnt
let resultval=0
let ptr=0
switchon Ptype into
[
case VCCPintype:
[ @picclass=MustFindNamee("VCC",typeIcclass)
resultval=firstVCCPin
ptr=VCCPins
]; endcase
case VEEPintype:
[ @picclass=MustFindNamee("VEE",typeIcclass)
resultval=firstVEEPin
ptr=VEEPins
]; endcase
case VDDPintype:
[ @picclass=MustFindNamee("VDD",typeIcclass)
resultval=firstVDDPin
ptr=VDDPins
]; endcase
case GNDPintype:
[ @picclass=MustFindNamee("GND",typeIcclass)
resultval=firstGNDPin
ptr=GndPins
]; endcase
] //end cases
for j=1 to ptr>>PinCol.NumCols do
[ //add all prior pins to get pin # within class
if ptr>>PinCol.Cnum↑j eq dx then break
Pnum=Pnum+ptr>>PinCol.NumPins↑j
]
@pPinNo=Pnum
resultis (resultval+Pnum-1)
] //end tracewired pin
//IC pin
let Pnum=ICPins>>Cols.Cnum↑dx+DescPtr>>ColDesc.Poffset↑cnt
resultis firstICPin+Pnum-1
]

and FIFC4conn(cv,x,y,FirstPin)=valof
[
for i=1 to cv>>Cspecs.NumOfSpecs do
[ //check each defined connector
let cp=Conns>>Cdescs.Num↑(cv>>Cspecs.ConnNum↑i) //ptr to connector descriptor
let Ycoor=cv>>Cspecs.Ycoor↑i
let Xcoor=cv>>Cspecs.Xcoor↑i
if not cp>>Cdesc.ConnIsVert then
[ //conn is horizontal...swap coors so tests can be made with same code
let temp=x
x=y
y=temp
temp=Xcoor
Xcoor=Ycoor
Ycoor=temp
]
let DispBetPins=cp>>Cdesc.DispBetPins
if x eq Xcoor then
[ //maybe in column 1
let maxY=Ycoor+(DispBetPins*(cp>>Cdesc.NumPinsCol1-1))
if (y ge Ycoor) & (y le maxY) & (((y-Ycoor) rem DispBetPins) eq 0) then
[ //is in this conn
resultis FirstPin+cv>>Cspecs.Pin1Col1Num↑i+(((y-Ycoor)/DispBetPins) * (cp>>Cdesc.NumsConsec ? 1,2) * (cp>>Cdesc.NumsDescending ? -1,1))-1
]
loop //not in col 1 of this conn
] //end maybe in column 1
if x eq (Xcoor+cp>>Cdesc.DispBetRC) then
[ //maybe in column 2
Ycoor=Ycoor+(cp>>Cdesc.DispNeg ? -cp>>Cdesc.Disp4sec, cp>>Cdesc.Disp4sec)
let maxY=Ycoor+(DispBetPins*(cp>>Cdesc.NumPinsCol2-1))
if (y ge Ycoor) & (y le maxY) & (((y-Ycoor) rem DispBetPins) eq 0) then
[ //is in this conn
resultis FirstPin+cv>>Cspecs.Pin1Col2Num↑i+(((y-Ycoor)/DispBetPins) * (cp>>Cdesc.NumsConsec ? 1,2) * (cp>>Cdesc.NumsDescending ? -1,1))-1
]
//not in col 2 of this conn
] //end maybe in column 2
] //end check each defined connector
resultis 0 //not found
]

and GetXY4Pin(PinVec,PinNum,Pintype,px,py) be
[
let NumCols=PinVec>>PinCol.NumCols
let cnt=0
for i=1 to NumCols do
[
let oldcnt=cnt
cnt=cnt+PinVec>>PinCol.NumPins↑i
if (PinNum gr oldcnt) & (PinNum le cnt) then
[ //found column with this pin
let column=PinVec>>PinCol.Cnum↑i
let DescPtr=PinCols>>Cols.Cnum↑column
let typecnt=oldcnt
for j=1 to NumPinRows do
[ //find the pin
if Pintype eq DescPtr>>ColDesc.Ptype↑j then typecnt=typecnt+1
if (PinNum eq typecnt) then
[ //found the pin now determine the row
let row=0
let Icnt=0
until Icnt eq j do
[ //loop until we find the jth defined pin
row=row+1
if GetBit(DescPtr,row) then Icnt=Icnt+1
]
@px=(column*2)+Xorigin-2
@py=(row*4)+Yorigin-4
break
] //end found the pin now determine the row
] //end find the pin
break
] //end found column with this pin
] //end for i
] //end GetXY4Pin

and SwatN(f1,f2,f3,f4) be
[ let f5 = vec 40 ; f5>>str.length = 0
AppndS(f5,f1) ; AppndN(f5,f2) ; AppndS(f5," ")
AppndN(f5,f3) ; AppndS(f5," ") ; AppndN(f5,f4)
CallSwat(f5)
]

and AppndS(f1,f2) be
[ let i,j=1,f1>>str.length+1
while i le f2>>str.length do
[ f1>>str.char↑j = f2>>str.char↑i ; i = i+1 ; j = j+1 ]
f1>>str.length = j-1
]

and AppndN(f1,f2) be
[ let i,j,m=f1>>str.length+1,nil,10000
for j = 1 to 5 do
[ f1>>str.char↑i = f2/m +$0 ; i = i+1 ; f2 = f2-(f2/m)*m
m=m/10
]
f1>>str.length = i-1
]