Diaries & Misc.
Home ] Up ] New Stuff ] Minix Port ] Magic-2? ] Overview ] Photo Gallery ] Construction ] My Other Projects ] Links ]

What's this?

Here are links to the development diaries I've kept, along with some miscellaneous documentation

Development Diaries

bullet2004 Diary
bullet2003 Diary
bullet2002 Diary
bullet2001 Diary

Stream of Consciousness Rantings

bulletSimulator Design
bulletFaults and Interrupts

Miscellaneous Documentation

bulletLCC machine description for Magic-1
bulletLCC machine description for D16/M
bulletLCC retargeting notes
bulletDaughter card PCB Express file [note - contains errors, see here]
bulletSignal Def/Use spreadsheet
bulletMagic-1 architecture validation test suite
bulletHP Kittyhawk 1.3" Microdrive Information

Serial port header pinouts

Not in the schematics are the pin assignments for the ribbon cable header for the two serial ports.  Here they are:

Serial port 0 signal Header pin
1 9
2 8
3 7
4 6
5 5
6 12
7 13
8 14
9 15
Serial port 1 signal Header pin
1 16
2 17
3 18
4 19
5 20
6 4
7 3
8 2
9 1

Branch Codes

There will be two bits in the microcode to control conditional branches.  These, combined with bits [1..3] of the opcode (ir[1..3]) will determine whether a branch is taken and on which condition.  The branch instructions are scattered through the opcode space in order to match up the condition with bits 1..3.  Note that there are two flavors of conditional branch:  compare and branch (cmpb.<cond>) and branch on condition (br.<cond>).  Within the microcode, the compare and branch instructions do a compare and branch on the condition codes produced by the operation.  

The two microcode bits are "branch" and "negate".  If branch==0, we won't do an conditional branch.  If it is 1, we'll select IR[1..3] to lookup the correct code and the output will be exclusive or'd with negate bit to provide the final branch code.  In the microcode engine, if we don't take a branch, the sequencer reverts to location 0, the fetch microinstruction.  Else, it continues with the address specified in the "next" field.  For conditional branches, thatwould point to a sequence to add the displacement to pc to effect the branch.  The "u" varieties are the unsigned comparisons.

Note that I'm only supporting a subset of the branch codes for my atomic compare and branch, due to limited opcode space.  I decided to fully support signed comparisons.  Actually, not really fully -- I don't have greater than or greater than or equal.  For these cases, I hope to be able to swap operand order and use the le and lt flavors.  If for some reason my compiler can't easily do this, I can just do a compare and follow it with a branch on condition (which does have full condition support).  Note also that I don't have any branch on overflow conditions  I do have a trap on overflow, and you can also do a branch on bit of the flags register (after moving it to A).

Here are the branch codes (note - redundancy in eq/ne needed because there are too many ops to fit into 1):


Raw condition

Negated condition
0 eq (flags[z]) ne (!flags[z])
1 eq (flags[z]) ne (!flags[z])
2 lt (flags[s]^flags[v]) ge (!(flags[s]^flags[v]))
3 le ((flags[s]^flags[v])|flags[z]) gt (!((flags[s]^flags[v])|flags[z]))
4 ltu (!flags[c]) geu (!(!flags[c]))
5 leu (!flags[c]|flags[z]) gtu (!(!flags[c]|flags[z]))
6 eq (flags[z]) ne (!flags[z])
7 ne (!flags[z]) eq (flags[z])


ALU Codes

These are getting a bit messy.  We use ir[1..3] to select the code, but also need a few stragglers.  To do a copy of the contents of the L bus to the Z bus, we will AND with imm(-1).  For the compare operations, we need to explicitly select SUB because they fall all over the opcode map.  The branch on bit opcodes can use AND, and the ADC, SBC and XOR stragglers must fall in the appropriate space in the opcode map.  Further, we will have 8 and 16-bit operations, which will be controlled by the OPSIZE microcode bit.  If OPSIZE==0, flags will be computed for an 8-bit result, and the ALU will only drive the low byte of the Z bus (and the high byte will be the extended sign of Z[8].  If OPSIZE==1, we'll do a 16-bit operation.  Further, we need another bit to control carry-in.  So, looks like we need 4 bits total:

bulletOP:2 - 00 -> ir[1..3], 01-> AND, 10-> SUB, 11->ADD
bulletCARRY_IN:1 - 0 -> 0 carry in, 1-> flags[c] in.
bulletOPSIZE:1 -- 0-> 8-bit, 1->16-bit

The codes themselves are what is expected by the 74F381 4-bit alu parts.

Code Operation
2 sub
3 add
4 xor
5 or
6 and

Misc Notes [mostly historical]

bulletPossible problems in the page table circuitry when running in front panel active (_DMA_ACK) mode.   The MEMORY signal is not being driven at all.  Also not being driven are the present and writeable bits.  This should be okay because the computed signals which rely on them also take _DMA_ACK into account, so their value is a don't care at this point.  Still, somewhat unclean.   UPDATE: it looks like I already handled MEMORY.  When _DMA_ACK is asserted, the MEMORY signal is taken from the front panel Mem/device switch.  For cleanliness, I could also drive P and W high when _DMA_ACK.
bulletThe "D" MSW bit is a little odd.  It latches a bit to denote whether a memory fault occurred while accessing the Data vs. Code potions of the page table.  So, the flip-flop latches on AND(FAULT,MEMREF).  However, we also need to reset this guy, and it turns out easy to reset when we switch to supervisor mode as a consequence of the fault (the latch happens even if we already were in supervisor mode).  So, that's why we tie the asynchronous clear of the FF to NOT(LMODE).  When LMODE stobes high, the async clear is brought low to clear the bit.  It is always safe to clear this bit at times other than fault.  It only has a lifetime of a few microcode cycles during a fault - long enough to copy MSW out to the stack.