using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EEPROM_Data_Generator { public static class Microcode { public const int OpcodeCount = 64; public const int MicroinstructionCount = 16; public const int UsedmicroinstructionCount =8; public const int FlagCount = 16; #region Control Bits private const ulong HLT = 0b00000000_00000000_00000000_00000000_00000001u; // Inverted Done private const ulong A_IN = 0b00000000_00000000_00000000_00000000_00000010u; // Done private const ulong A_OUT = 0b00000000_00000000_00000000_00000000_00000100u; // Inverted Done private const ulong B_IN = 0b00000000_00000000_00000000_00000000_00001000u; // Done private const ulong B_OUT = 0b00000000_00000000_00000000_00000000_00010000u; // Inverted Done private const ulong PC_IN = 0b00000000_00000000_00000000_00000000_00100000u; // Inverted Done private const ulong O_IN = 0b00000000_00000000_00000000_00000000_01000000u; // Done private const ulong PC_INC = 0b00000000_00000000_00000000_00000000_10000000u; // Done private const ulong PC_OUT = 0b00000000_00000000_00000000_00000001_00000000u; // Inverted Done private const ulong X_IN = 0b00000000_00000000_00000000_00000010_00000000u; // Inverted Done private const ulong X_OUT = 0b00000000_00000000_00000000_00000100_00000000u; // Inverted Done private const ulong X_INC = 0b00000000_00000000_00000000_00001000_00000000u; // Done private const ulong RAM_IN = 0b00000000_00000000_00000000_00010000_00000000u; // Inverted Done private const ulong RAM_OUT = 0b00000000_00000000_00000000_00100000_00000000u; // Inverted Done private const ulong MAR_IN = 0b00000000_00000000_00000000_01000000_00000000u; // Done private const ulong PMA_IN = 0b00000000_00000000_00000000_10000000_00000000u; // Done private const ulong IR_OUT_FAST = 0b00000000_00000000_00000001_00000000_00000000u; // Done private const ulong IR_OUT_FULL = 0b00000000_00000000_00000010_00000000_00000000u; // Done private const ulong IR_OUT_MLT_0 = 0b00000000_00000000_00000100_00000000_00000000u; // Done private const ulong IR_OUT_MLT_1 = 0b00000000_00000000_00001000_00000000_00000000u; // Inverted Done private const ulong PM_OUT = 0b00000000_00000000_00010000_00000000_00000000u; // Inverted Done private const ulong I_OUT = 0b00000000_00000000_00100000_00000000_00000000u; // Inverted Done private const ulong IR_IN_0 = 0b00000000_00000000_01000000_00000000_00000000u; // Done private const ulong IR_IN_1 = 0b00000000_00000000_10000000_00000000_00000000u; // Done private const ulong F_IN = 0b00000000_00000001_00000000_00000000_00000000u; // Inverted Done private const ulong ALU_OUT = 0b00000000_00000010_00000000_00000000_00000000u; // Inverted Done private const ulong ALU_SUB = 0b00000000_00000100_00000000_00000000_00000000u; // Done private const ulong MIR = 0b00000000_00001000_00000000_00000000_00000000u; // Done private const ulong IRQ = 0b00000000_00010000_00000000_00000000_00000000u; // Done private const ulong FETCH_ADDRESS = PC_OUT | MAR_IN; private const ulong FETCH_DATA_0 = RAM_OUT | IR_IN_0 | PC_INC; private const ulong FETCH_DATA_1 = RAM_OUT | IR_IN_1 | PC_INC; private const ulong ALU_OP = ALU_OUT | A_IN | F_IN; #endregion #region Instructions // We don't need to be able to index all of them, so these are just the ones we need private const int IN_N = 24; private const int IN_A = 25; private const int IN_XA = 26; private const int JEZ = 33; private const int JNZ = 35; private const int JGT = 37; private const int JLT = 39; private const int JGE = 41; private const int JLE = 43; #endregion private const int OPCODE_MASK = 0b0_00000000_00111111; private const int MI_MASK = 0b0_00000011_11000000; private const int FLAG_MASK = 0b0_00111100_00000000; private const int FLAG_ZERO = 0b0001; private const int FLAG_CARRY = 0b0010; private const int FLAG_INPUT_READY = 0b0100; private const int FLAG_3 = 0b1000; private static readonly ulong[][] baseMicrocode = { new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 0 000000 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, IR_OUT_FAST | A_IN , MIR , 0 , 0 , 0 , 0 }, // 1 000001 LDA Number 10 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | A_IN , MIR , 0 , 0 }, // 2 000010 LDA Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | A_IN , MIR , 0 }, // 3 000011 LDA Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | A_IN , MIR , 0 , 0 , 0 , 0 }, // 4 000100 LDA None 0 #X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | MAR_IN , RAM_OUT | A_IN , MIR , 0 , 0 , 0 }, // 5 000101 LDA None 0 &X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , A_OUT | RAM_IN , MIR , 0 }, // 6 000110 STA Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | MAR_IN , A_OUT | RAM_IN , MIR , 0 , 0 , 0 }, // 7 000111 STA None 0 &X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, IR_OUT_FAST | X_IN , MIR , 0 , 0 , 0 , 0 }, // 8 001000 LDX Number 10 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | X_IN , MIR , 0 , 0 }, // 9 001001 LDX Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | X_IN , MIR , 0 }, // 10 001010 LDX Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, A_OUT | X_IN , MIR , 0 , 0 , 0 , 0 }, // 11 001011 LDX None 0 #A new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , X_OUT | RAM_IN , MIR , 0 }, // 12 001100 STX Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, IR_OUT_FAST | B_IN , ALU_OP , MIR , 0 , 0 , 0 }, // 13 001101 ADD Number 10 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | B_IN , ALU_OP , MIR , 0 }, // 14 001110 ADD Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | B_IN , ALU_OP , MIR }, // 15 001111 ADD Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | B_IN , ALU_OP , MIR , 0 , 0 , 0 }, // 16 010000 ADD None 0 #X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | MAR_IN , RAM_OUT | B_IN , ALU_OP , MIR , 0 , 0 }, // 17 010001 ADD None 0 &X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, IR_OUT_FAST | B_IN , ALU_OP | ALU_SUB , MIR , 0 , 0 , 0 }, // 18 010010 SUB Number 10 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | B_IN , ALU_OP | ALU_SUB , MIR , 0 }, // 19 010011 SUB Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | B_IN , ALU_OP | ALU_SUB , MIR }, // 20 010100 SUB Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | B_IN , ALU_OP | ALU_SUB , MIR , 0 , 0 , 0 }, // 21 010101 SUB None 0 #X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | MAR_IN , RAM_OUT | B_IN , ALU_OP | ALU_SUB , MIR , 0 , 0 }, // 22 010110 SUB None 0 &X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_INC , MIR , 0 , 0 , 0 , 0 }, // 23 010111 INC None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, IRQ , I_OUT | A_IN , MIR , 0 , 0 , 0 }, // 24 011000 IN None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , IRQ , I_OUT | RAM_IN , MIR }, // 25 011001 IN Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | MAR_IN , IRQ , I_OUT | RAM_IN , MIR , 0 , 0 }, // 26 011010 IN None 0 &X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, A_OUT | O_IN , MIR , 0 , 0 , 0 , 0 }, // 27 011011 OUT None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | O_IN , MIR , 0 }, // 28 011100 OUT Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | MAR_IN , RAM_OUT | O_IN , MIR , 0 , 0 , 0 }, // 29 011101 OUT None 0 &X new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, X_OUT | PMA_IN , PM_OUT | A_IN , MIR , 0 , 0 , 0 }, // 30 011110 RPM None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | PC_IN , MIR , 0 , 0 }, // 31 011111 JMP Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | PC_IN , MIR , 0 }, // 32 100000 JMP Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 33 100001 JEZ Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 34 100010 JEZ Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 35 100011 JNZ Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 36 100100 JNZ Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 37 100101 JGT Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 38 100110 JGT Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 39 100111 JLT Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 40 101000 JLT Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 41 101001 JGE Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 42 101010 JGE Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 43 101011 JLE Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , MIR , 0 , 0 , 0 }, // 44 101100 JLE Address 16 @ new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 45 101101 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 46 101110 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 47 101111 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 48 110000 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 49 110001 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 50 110010 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 51 110011 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 52 110100 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 53 110101 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 54 110110 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 55 110111 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 56 111000 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 57 111001 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 58 111010 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 59 111011 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 60 111100 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 61 111101 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, MIR , 0 , 0 , 0 , 0 , 0 }, // 62 111110 NOP None 0 new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, HLT , MIR , 0 , 0 , 0 , 0 }, // 63 111111 HLT None 0 }; private static readonly ulong[][] validJump = { new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | PC_IN , MIR , 0 , 0 }, // Number 16 # new ulong[] { FETCH_ADDRESS, FETCH_DATA_0, FETCH_ADDRESS , FETCH_DATA_1 , IR_OUT_FULL | MAR_IN , RAM_OUT | PC_IN , MIR , 0 }, // Address 16 @ }; public static ulong[,,] GenerateMicroCode () { ulong[,,] microCode = new ulong[OpcodeCount, MicroinstructionCount, FlagCount]; // Copy base microcode for (int op = 0; op < OpcodeCount; op++) { for (int i = 0; i < UsedmicroinstructionCount; i++) { for (int f = 0; f < FlagCount; f++) { microCode[op, i, f] = baseMicrocode[op][i]; } } } // Correct for flags // Jumps // FLAG_ZERO is set when the result equals 0 // FLAG_CARRY is set when the result is greater than or equal to 0 for (int i = 0; i < UsedmicroinstructionCount; i++) { for (int op = 0; op < 2; op++) { for (int f = 0; f < FlagCount; f++) { // JEZ if ((f & FLAG_ZERO) != 0) microCode[JEZ + op, i, f] = validJump[op][i]; // JNZ if ((f & FLAG_ZERO) == 0) microCode[JNZ + op, i, f] = validJump[op][i]; // JGT if ((f & FLAG_CARRY) != 0 && (f & FLAG_ZERO) == 0) microCode[JGT + op, i, f] = validJump[op][i]; // JLT if ((f & FLAG_CARRY) == 0) microCode[JLT + op, i, f] = validJump[op][i]; // JGE if ((f & FLAG_CARRY) != 0 || (f & FLAG_ZERO) != 0) microCode[JGE + op, i, f] = validJump[op][i]; // JLE if ((f & FLAG_CARRY) == 0 || (f & FLAG_ZERO) != 0) microCode[JLE + op, i, f] = validJump[op][i]; } } } // Input // FLAG_INPUT_READY is set when the input module has set RDY high for (int f = 0; f < FlagCount; f++) { if ((f & FLAG_INPUT_READY) == 0) { microCode[IN_N , 2, f] |= HLT; microCode[IN_A , 5, f] |= HLT; microCode[IN_XA, 3, f] |= HLT; } } return microCode; } public static int GetMicroinstructionIndex (int op, int i, int f) { return ((f << 10) & FLAG_MASK) | ((i << 6) & MI_MASK) | (op & OPCODE_MASK); } } }