-
Notifications
You must be signed in to change notification settings - Fork 0
/
sim.c
141 lines (129 loc) · 4.22 KB
/
sim.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include "mips32.h"
#include "consts.h"
#include "pipes.h"
#include "mem.h"
// Print simulation status
void print_status() {
printf("Executed %zu instruction(s).\n", instr_cnt);
printf("%zu cycle(s) elapsed.\n", cycles);
printf("icache hits: %zu, misses: %zu.\n", icache.hits, icache.misses);
printf("dcache hits: %zu, misses: %zu.\n", dcache.hits, dcache.misses);
printf("l2cache hits: %zu, misses: %zu.\n", l2cache.hits, l2cache.misses);
printf("pc = 0x%x\n", PC);
printf("at = 0x%x\n", regs[r_at]);
printf("v0 = 0x%x\n", regs[r_v0]);
printf("v1 = 0x%x\n", regs[r_v1]);
for (int i = 0; i < 8; i++) printf("t%d = 0x%x\n", i, regs[i+8]);
printf("sp = 0x%x\n", regs[r_sp]);
printf("ra = 0x%x\n", regs[r_ra]);
}
void print_all_registers() {
for (int i = 0; i < 4; i++) printf("a%d = 0x%x\n", i, regs[i+16]);
for (int i = 0; i < 8; i++) printf("s%d = 0x%x\n", i, regs[i+16]);
}
// Read config file stream
int read_config_stream(FILE* f) {
// Load registers
for (int i = 8; i < 16; i++) {
if (fscanf(f, "%u", ®s[i]) != 1) {
if (errno == 0) return ERROR_INVALID_CONFIG;
return ERROR_IO_ERROR;
}
}
return 0;
}
// Read cache config
int read_cache_config(FILE *f, struct cache *c) {
// Read config
if (fscanf(f, "%u,%u,%u", &c->n_sets, &c->n_blocks_per_set, &c->n_words_per_block) < 0) {
if (errno == 0) return ERROR_INVALID_CONFIG;
return ERROR_IO_ERROR;
}
D printf("DEBUG - Sets = [%u]\n", c->n_sets);
D printf("DEBUG - Blocks = [%u]\n", c->n_blocks_per_set);
D printf("DEBUG - Words Per Block = [%u]\n", c->n_words_per_block);
return cache_init(c);
}
// Read config
int read_config(const char *path) {
int ret;
FILE* f = fopen(path, "r");
if (f == NULL) return ERROR_IO_ERROR;
if ((ret = read_config_stream(f))) return ret;
D printf("DEBUG : Setup instruction cache\n");
if ((ret = read_cache_config(f, &icache))) return ret;
D printf("DEBUG : Setup data cache\n");
if ((ret = read_cache_config(f, &dcache))) return ret;
D printf("DEBUG : Setup shared l2 cache\n");
if ((ret = read_cache_config(f, &l2cache))) return ret;
D printf("\n\n\n");
return fclose(f);
}
int interp() {
int ret = 0;
while(ret == 0) {
D printf("\n\n\n");
D printf("DEBUG : Cycle %zu \n", cycles);
ret = cycle();
D printf("DEBUG : Press enter to continue...");
D getchar();
cycles++;
}
D printf("\n\n\n");
return ret;
}
int main(int argc, char* argv[]) {
int ret;
// Print usage
if (argc != 3) {
printf("Usage:\n");
printf("%s config_file mips_elf_file\n", argv[0]);
exit(-1);
}
// Read config file and print inital status
ret = read_config(argv[1]);
if (ret != 0) {
printf("Failed to load config, failed with:\n");
switch(ret) {
case ERROR_INVALID_CACHE_SIZE:
printf("Invalid cache size\n");
break;
case ERROR_MEMORY_ERROR:
printf("Memory error : Failed to allocate cache (time for an upgrade?)\n");
break;
case ERROR_INVALID_CONFIG:
printf("Failed to parse config (invalid format)\n");
break;
default:
printf("Unknown error (code = %d)\n", ret);
}
exit(ret);
}
// Setup memory
if ((ret = mem_init(argv[2], &PC))) return ret;
// Set stack pointer
regs[29] = END_OF_MEM;
D print_status();
// Run
ret = interp();
print_status();
if (ret == ERROR_UNKNOWN_OPCODE) {
printf("Found unknown opcode!\n");
} else if (ret == ERROR_UNKNOWN_FUNCT) {
printf("Found unknown funct code!\n");
} else if (ret == ERROR_OVERFLOW) {
printf("Encountered overflow!\n");
} else if (ret == ERROR_INVALID_MEM_ADDR){
printf("Accesssing invalid memory address\n");
} else if (ret < 0) {
printf("Encountered unhandled error! [%d]\n", ret);
} else if (ret != SIG_HALT_PROGRAM) {
printf("Terminated with signal: [%d]\n", ret);
ret = 0;
}
return ret;
}