//Program to generate the proms for the D0 control board
//For the 2716 boot proms, the program reads "D0csBoot-F.mb", and
//makes a new .mb file in the correct format
//load: bldr d0cspromgen promgen format

//
C. Thacker and B. Rosen
//Last modified February 13, 1980 3:26 PM by Jim Frandeen: input from Boot.mb, output to Proms.mb
//Last modified February 5, 1980 7:57 PM by Jim Frandeen: write to 2047 instead of 1023.
//Last modified February 5, 1980 5:21 PM by Chang.
//modified December 17, 1978by CPT.
//
changed boot EPROM to rev F

//modified September 9, 1978 2:41 PM by CT - added revision E to D0csboot.mb
//Modified August 7, 1978 9:50 AM by Rosen
//Modified April 24, 1978 4:04 PM by Rosen
// changed names of files to conform to naming conventions
//modified February 21, 1978 11:28 AM
//
by Rosen-changed parity of CS to odd

get "streams.d"
get "promgen.d"

external
[
FORMATN
dsp
Gets
Endofs
SetBlock
Zero

]


static
[
memnos
stream
]

manifest
[
nmems = 2
]

structure uInst:
[
MemInst bit 1
RMOD bit 1
RSELhibit 4
ALUFbit 4
BSELbit 2
F1bit 4

LRbit 1
LTbit 1
F2bit 4
JCbit 3
JAlowbit 6
IParbit 1

RSELlowbit 2
JAhibit 2
blankbit 12
]

structure [ lh byte; rh byte ]

let MAIN() be

[ OpenMBFile("Proms.MB")
let M = vec 4096
MEMORY = M
Zero(MEMORY,4096)
let x = ReadD0MB("Boot.mb")
if x ne 0 then [ Wss(dsp,"*n*n");Wss(dsp,x); finish ]
WriteMem("CSc12",8,2047)
for i = 0 to 2047 do MEMORY!i = (MEMORY!i) rshift 8 //high byte
WriteMem("CSg12",8,2047) //low byte
GenCSd4()
CloseMBFile()
]


and GenCSd4 () be
[
//Boot Prom 32 x 8 located in Control Store Card position d4
//****Note this prom is for control boards Rev C and above

let prombits = table
[
//
Next, Clr’, Run’, BWL’, BWH’, State
10b;0;1;1;1;//00Enter here, Clear APC
10b;0;1;1;1;//01Also an entry point if APC.00 was set
00b;1;1;1;1;//02
00b;1;1;1;1;//03
00b;1;1;1;1;//04
00b;1;1;1;1;//05
00b;1;1;1;1;//06
00b;1;1;1;1;//07
12b;1;1;1;1;//10Loop starts here
36b;0;1;1;1;//11Here when APC.00=1, Clear APC
14b;1;1;1;1;//12
00b;1;1;1;1;//13
16b;1;1;1;0;//14Prepare to Write High
00b;1;1;1;1;//15
20b;1;1;1;1;//16Write Here
00b;1;1;1;1;//17
22b;1;1;1;1;//20
00b;1;1;1;1;//21
24b;1;1;1;1;//22
00b;1;1;1;1;//23
26b;1;1;0;1;//24Prepare to Write Low
00b;1;1;1;1;//25
10b;1;1;1;1;//26Write here, Incr APC and Loop
00b;1;1;1;1;//27
00b;1;1;1;1;//30
00b;1;1;1;1;//31
00b;1;1;1;1;//32
00b;1;1;1;1;//33
00b;1;1;1;1;//34
00b;1;1;1;1;//35
36b;1;0;1;1;//36Run Loop
36b;1;0;1;1;//37Need 2 locs because APC.00 changes
]
for i = 0 to 31 do
[
let j = Rev(i,5)*5//reverse address bits and mult by table width
//Note: Next field is already multiplied by 2
MEMORY!i = ((((prombits!j +
prombits!(j+1))*2 +
prombits!(j+2))*2 +
prombits!(j+3))*2 +
prombits!(j+4))
]

WriteMem ("CSd4-B", 8, 31)
]

and ReadD0MB(file) = valof
// file is a filename
// returns 0 if OK, otherwise error string
[
stream = OpenFile(file)
if stream eq 0 then resultis "Can’t open .MB file"
let curmemx, curaddr = -1, 0
let memnames = vec nmems
memnames!0 = "IM"
memnames!1 = "RM"
let memwidths = table[ 64;16 ] //MicroD outputs data,,address
let mnos = vec nmems
memnos = mnos
SetBlock(memnos, -1, nmems)


[
if Endofs(stream) then resultis "Unexpected end of stream"
let blocktype = Gets(stream)
switchon blocktype into
[ case 0:// end of data
Closes(stream);resultis 0
case 2:// set address
[ curmemx = findmem(Gets(stream))
if curmemx eq -1 then resultis "Bad Memory Number"
curaddr = Gets(stream)
endcase
]
case 1:// data word
[ Gets(stream) //discard sequence number
switchon curmemx into
[ case 0: [ let wd0=Gets(stream)
let wd1=Gets(stream); let wd2=Gets(stream)
let addr = Gets(stream); //4th word is address
let r =WriteIMData(addr,wd0,wd1,wd2)
if r ne 0 then resultis r
endcase
]
case 1: [ WriteRMData(curaddr,Gets(stream)); endcase ]
default: resultis "Data for undefined memory"
]
curaddr = curaddr+1
endcase
]
case 4:// define memory
[ let memno = Gets(stream)
let width = Gets(stream)
let name = vec 128
readname(name)
for j = 0 to nmems-1 do
if strequal(name, memnames!j) then
[ if width ne memwidths!j then
resultis "Bad width"
memnos!j = memno
endcase
]
resultis "Bad memory name"
]
case 5:// define symbol
[ let memno = Gets(stream)
let val = Gets(stream)
let name = vec 128
readname(name)
let memx = findmem(memno)
if memx eq -1 then resultis "Bad memory #"
endcase
]
default: resultis "Invalid block type"
]
] repeat
]

and noop(x, y, z) be [ ]

and findmem(memno) = valof
[
for j = 0 to nmems-1 do
if memnos!j eq memno then resultis j
resultis -1
]

and readname(strg) be
[
let j = 0
[
let wd = Gets(stream)
if wd<<lh eq 0 break
j = j+1
strg>>BS.CHAR↑j = wd<<lh
if wd<<rh eq 0 break
j = j+1
strg>>BS.CHAR↑j = wd<<rh
] repeat
strg>>BS.LENGTH = j
]

and strequal(str1, str2) = valof
[
for i = 0 to str1>>BS.LENGTH do
if str1>>BS.CHAR↑i ne str2>>BS.CHAR↑i resultis false
resultis true
]

and WriteRMData(place,curaddr,data) be
[

]

and WriteIMData(addr,wd0,wd1,wd2) =valof
[
//write to MEMORY
if (addr & #300) ne 0 then resultis "Bad address for boot EPROM"
if (wd2 & #170000) ne #140000 then resultis "Bad default bits for boot EPROM"
let Eaddr = fixCSaddr(addr)

wd1 = wd1 & #177776//mask out parity bit
wd1 = wd1 % ( Parity(wd0) xor Parity(wd1) xor 1) //fix parity bit
MEMORY!Eaddr =wd0
MEMORY!(Eaddr % #1)=wd1
resultis 0

]




and fixCSaddr(addr) = valof
[
//the EPROM address is (CSaddr[1:3],,CSaddr[6:11])*2
let r = 2*(((addr rshift 2) & #1700) % (addr & #77))
//for 1k control store, use following line
//resultis r % #1000 //******kludge for 1k control board********
//for 4k control store, use following line
resultis r
]




and Parity(x) = valof
[
let parity = 0
for i = 0 to 15 do [ parity = parity+x; x = x rshift 1 ]
resultis parity & 1
]