Some notes on the MIT CADR, "principles of operation" (original) (raw)
Some notes on the CADR "principles of operation"
Brad Parker 10/17/04 brad@heeltoe.com
Notes on (my) confusion or discrepancies in MIT AI Memo 528
While writing a CADR emulator I ran into some issues and/or discrepancies in the available documentation. I've tried to list them here.
[These are my conclusions; If you read them and disagree, please send me email and set me straight. I do not have a functional hardware description (i.e. verilog) yet, so some things are assuptions based on quick scans of the schematics]
- The description of the ALU mode selection using IR7 seems inverted. IR7=0 should select the 'logic' side of the ALU. IR7=1 should select the "math" side.
- The modification of the rotation count due to "misc function 3", in 16 bit mode talks about XOR of IR4 and LC1. I think this is inverted, i.e. POS4 := NOT (IR4 XOR LC1)
- The modification of the dispatch address due to L2 map bits talks about bits 14 & 15. In fact the map bits select L2 bit 18 & 19.
- The modification of the dispatch address due to L2 map bits talks about replacing bit 0. In fact the l2 map result is or'd with the existing bit 0 (see msi 2F01)
- The PDL pointer, when used in PDL push, increments *before* the write. Conversely, the PDL pointer, when used in PDL pop, decrements *after* the read.
- The SPC stack pointer, on a push, increments *before* the write. Conversly, the SPC stack pointer, on a pop, increments *before* the write.
- Here's an interesting quote:
;NOTE THAT THE LC HARDWARE IGNORES THE LOW BIT
;AND READS IT BACK AS ZERO IN HALFWORD MODE - It seems a page fault should be generated on a write access if the read access bit is not set, even if the write access bit is set.
- If the "length of byte" field in a dispatch is zero, the mask is zero and no bits contribute to the dispatch offset.
- The microcode uses the fact that the MD is valid (for one additional cycle) with the result of a previous memory-read even when a new memory read has been started. (so the memory read pipe must be modeled)
- The dispatch instruction is affected by the instruction pipeline. Below some of the cases are enumerated for clarity. First, let me quote from "lmdocs: popj.2", a document which I found illuminating.
POPJ-AFTER-NEXT in combination with JUMP and DISPATCH [CONTRL]
Dispatch R P N PC SPC NOP 0 0 0 jump pop no 0 0 1 jump pop yes 0 1 0 jump push no 0 1 1 jump push yes 1 0 0 popj pop no 1 0 1 popj pop yes 1 1 0 popj pop no 1 1 1 popj pop yes
Jump R P N PC SPC NOP (cond 0 0 0 jump pop no satisfied) 0 0 1 jump pop yes 0 1 0 jump push no 0 1 1 jump push yes 1 0 0 popj pop no 1 0 1 popj pop yes 1 1 0 iwrite 1 1 1 iwrite
Jump with condition not satisfied is similar to ALU and BYTE instructions.
Possible mods to increase usefulness: A dispatch-call or jump-call in combination with popj-after-next should neither popj nor pushj but just jump. If it's xct-next the right thing happens. If the next instruction is inhibited, well that's OK. However, if the next instruction is not inhibited, and it's a CALL, normally (without the previous call) would be like tail recursive, but here will end up with two return addresses on pdl, however, the top one is the address of the place called in the first instruction and the one under that is the original return so that's right too.
Dispatch example - POPJ+DISPATCH, enumerating cases
001 LABEL (CHECK-PAGE-READ) 002 (POPJ-AFTER-NEXT DISPATCH TRANSPORT READ-MEMORY-DATA) ;FOLLOW ALL INVZ 003 ((M-T) Q-TYPED-POINTER READ-MEMORY-DATA) ;RETURN C(E) IN M-T 004 005
dispatch yields N=0,P=0,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu new pc<- dispatch address (disable popj)
- exec alu fetch new pc (dispatch address)
dispatch yields N=0,P=0,R=1
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu new pc <- spc[spc-ptr--] (disable popj)
- exec alu fetch new pc (from stack)
dispatch yields N=0,P=1,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu spc[++spc-ptr] <- 004 new pc <- dispatch address (disable popj)
- exec alu fetch new pc (dispatch address)
dispatch yields N=0,P=1,R=1
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu ignore dispatch, do popj new pc <- spc[spc-ptr--] if pc14, advance-lc
- exec alu fetch new pc
dispatch yields N=1,P=0,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu new pc<- dispatch address (disable popj)
- (nop - pipe flush) fetch new pc
dispatch yields N=1,P=0,R=1
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu new pc <- spc[spc-ptr--] if pc14, advance-lc (disable popj)
- (nop - pipe flush) fetch new pc
dispatch yields N=1,P=1,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/alu spc[++spc-ptr] <- 005 new pc <- dispatch address (disable popj)
- exec alu fetch new pc
Another Dispatch example - POPJ+DISPATCH with CALL, enumerating cases
001 LABEL (CHECK-PAGE-READ) 002 (POPJ-AFTER-NEXT DISPATCH TRANSPORT READ-MEMORY-DATA) ;FOLLOW ALL INVZ 003 (CALL-XCT-NEXT FUNC) 004 005
dispatch yields N=0,P=0,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call new pc<- dispatch address (disable popj)
- exec call fetch new pc (dispatch address) spc[++spc-ptr] <- new pc+1 new pc<- call address
- exec 1st inst @ dispatch address fetch call address
- exec 1st inst @ call address
[help! I'm confused here. I don't think the action above is correct. When the call returns it will return to new pc + 1...]
dispatch yields N=0,P=0,R=1
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call new pc <- spc[spc-ptr--] (disable popj)
- exec call fetch new pc (from stack) spc[++spc-ptr] <- new pc+1 new pc<- call address
- exec 1st inst @ new pc fetch call address
- exec 1st inst @ call address
[again; I don't think the action above is correct. When the call returns it will return to new pc + 1...]
dispatch yields N=0,P=1,R=0a
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call spc[++spc-ptr] <- 004 new pc <- dispatch address (disable popj)
- exec call fetch new pc (dispatch address) spc[++spc-ptr] <- new pc+1 new pc<- call address
- exec 1st inst @ dispatch address fetch call address
- exec 1st inst @ call address
dispatch yields N=0,P=1,R=1
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call ignore dispatch, do popj new pc <- spc[spc-ptr--] if pc14, advance-lc
- exec call fetch new pc (from stack) spc[++spc-ptr] <- new pc+1 new pc<- call address
- exec 1st inst @ new pc fetch call address
- exec 1st inst @ call address
dispatch yields N=1,P=0,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call new pc<- dispatch address (disable popj)
- (nop - pipe flush) fetch new pc (dispatch address)
- exec 1st inst @ new pc fetch new pc+1
dispatch yields N=1,P=0,R=1
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call new pc <- spc[spc-ptr--] if pc14, advance-lc (disable popj)
- (nop - pipe flush) fetch new pc (from stack)
- exec 1st inst @ new pc fetch new pc+1
dispatch yields N=1,P=1,R=0
- exec check-page-read jump fetch 002/popj
- exec popj + dispatch fetch 003/call spc[++spc-ptr] <- 005 new pc <- dispatch address (disable popj)
- exec call fetch new pc (dispatch address) spc[++spc-ptr] <- dispatch address+1 new pc<- call address
- exec 1st inst @ new pc fetch call address
- exec 1st inst @ call address
Another Dispatch example - with CALL, enumerating cases
001 (NOP) 002 (DISPATCH TRANSPORT READ-MEMORY-DATA) ;FOLLOW ALL INVZ 003 (CALL FUNC) 004 005
dispatch yields N=0,P=0,R=0
- exec check-page-read jump fetch 002/dispatch
- exec dispatch fetch 003/call new pc <- dispatch address
- exec call w/n-bit fetch new pc (dispatch address) spc[++spc-ptr] <- new pc+1 new pc<- call address
- (nop - pipe flush) fetch call address
- exec 1nd inst @ call address
The call pushes the dispatch address + 1 and the pipe stalls because the call has the N bit set, followed by the 1st instruction at the call address.