-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmicrocode_gen.c
108 lines (92 loc) · 4.14 KB
/
microcode_gen.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// This project was inspired by https://github.com/beneater and his https://github.com/beneater/eeprom-programmer/blob/master/microcode-eeprom-programmer/microcode-eeprom-programmer.ino
#define MI 0b1000000000000000 // Memory address register in
#define RI 0b0100000000000000 // RAM data in
#define RO 0b0010000000000000 // RAM data out
#define IO 0b0001000000000000 // Instruction register out
#define II 0b0000100000000000 // Instruction register in
#define AI 0b0000010000000000 // A register in
#define AO 0b0000001000000000 // A register out
#define EO 0b0000000100000000 // ALU out
#define SU 0b0000000010000000 // ALU subtract
#define BI 0b0000000001000000 // B register in
#define OI 0b0000000000100000 // Output register in
#define CE 0b0000000000010000 // Program counter enable
#define CO 0b0000000000001000 // Program counter out
#define J 0b0000000000000100 // Jump (program counter in)
#define HLT 0b0000000000000010 // Halt clock
#define FI 0b0000000000000001 // Flags in
#define FLAGS_Z0C0 0
#define FLAGS_Z0C1 1
#define FLAGS_Z1C0 2
#define FLAGS_Z1C1 3
#define JC 0b0111
#define JZ 0b1000
// Microcode instructions for the CPU
uint16_t TEMPLATE[16][8] = {
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 0000 - NOP
{MI|CO, RO|II|CE, IO|MI, RO|AI, 0, 0, 0, 0}, // 0001 - LDA
{MI|CO, RO|II|CE, IO|MI, RO|BI, EO|AI|FI, 0, 0, 0}, // 0010 - ADD
{MI|CO, RO|II|CE, IO|MI, RO|BI, EO|AI|SU|FI, 0, 0, 0}, // 0011 - SUB
{MI|CO, RO|II|CE, IO|MI, AO|RI, 0, 0, 0, 0}, // 0100 - STA
{MI|CO, RO|II|CE, IO|AI, 0, 0, 0, 0, 0}, // 0101 - LDI
{MI|CO, RO|II|CE, IO|J, 0, 0, 0, 0, 0}, // 0110 - JMP
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 0111 - JC
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 1000 - JZ
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 1001
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 1010
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 1011
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 1100
{MI|CO, RO|II|CE, 0, 0, 0, 0, 0, 0}, // 1101
{MI|CO, RO|II|CE, AO|OI, 0, 0, 0, 0, 0}, // 1110 - OUT
{MI|CO, RO|II|CE, HLT, 0, 0, 0, 0, 0} // 1111 - HLT
};
uint16_t ucode[4][16][8];
void initUcode(){
// Z = 0, C = 0
memcpy(ucode[FLAGS_Z0C0], TEMPLATE, sizeof(TEMPLATE));
// Z = 0, C = 1
memcpy(ucode[FLAGS_Z0C1], TEMPLATE, sizeof(TEMPLATE));
ucode[FLAGS_Z0C1][JC][2] = IO|J;
// Z = 1, C = 0
memcpy(ucode[FLAGS_Z1C0], TEMPLATE, sizeof(TEMPLATE));
ucode[FLAGS_Z1C0][JZ][2] = IO|J;
// Z = 1, C = 1
memcpy(ucode[FLAGS_Z1C1], TEMPLATE, sizeof(TEMPLATE));
ucode[FLAGS_Z1C1][JC][2] = IO|J;
ucode[FLAGS_Z1C1][JZ][2] = IO|J;
}
int main(){
initUcode();
FILE *control_unit_rom;
control_unit_rom = fopen("control_unit", "w");
// Writing data to the ROM
if(control_unit_rom == NULL) {
printf("The file for the first ROM Control Unit was not found! Exiting... \n");
exit(0);
} else{
fprintf(control_unit_rom, "v3.0 hex words addressed\n");
int mem_cnt = 0;
int mem_step_flag = 0;
fprintf(control_unit_rom, "%02x: ", 0);
for(int address = 0; address < 1024; address += 1){
int flags = (address & 0b1100000000) >> 8;
int byte_sel = (address & 0b0010000000) >> 7;
int instructions = (address & 0b0001111000) >> 3;
int step = (address & 0b0000000111);
fprintf(control_unit_rom, "%04x ", ucode[flags][instructions][step]);
if(step == 0b111){
mem_step_flag++;
}
if(mem_step_flag == 2){
fprintf(control_unit_rom, "\n");
mem_step_flag = 0;
mem_cnt += 16;
fprintf(control_unit_rom, "%02x: ", mem_cnt);
}
}
fclose(control_unit_rom);
}
}