YARISIM: add a register-use decode map
[yari.git] / yarisim / sim.c
blob1f9b97f6e0099b9e5599ce0cd6b918d0db583731
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <assert.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <termios.h>
10 #include <netinet/in.h>
11 #include <signal.h>
12 #include "elf.h"
13 #include <getopt.h>
14 #include "mips32.h"
15 #include "runmips.h"
17 int enable_disass = 0;
18 int enable_disass_user= 0; // Enable disass once we reach user code (0x4...)
19 int enable_verb_elf = 0;
20 int enable_forwarding = 0;
21 int enable_fastbranch = 0;
22 int enable_testcases = 0;
23 int enable_regwrites = 1; // XXX
24 int enable_firmware_mode = 0;
25 int enable_cosimulation = 0;
27 int endian_is_big = 0;
28 struct timeval stat_start_time, stat_stop_time;
30 void *memory_segment[NSEGMENT];
31 unsigned memory_segment_size[NSEGMENT];
33 unsigned program_entry = 0;
36 * struct option {
37 * const char *name;
38 * int has_arg;
39 * int *flag;
40 * int val;
41 * };
44 static int run = '1';
45 static char *filename = 0;
48 static struct option long_options[] = {
49 {"help", 0, NULL, '?'},
50 {"data-generation",0, &run, 'd'}, // for Icarus Verilog simulation
51 {"hex-generation", 0, &run, 'h'}, // for Quartus (HEX)
52 {"mif-generation", 0, &run, 'm'}, // for Quartus (MIF)
53 {"tinymon-generation", 0, &run, 't'}, // for Tinymon
54 {"forward-values", 0, &enable_forwarding, 1},
55 {"fast-branch", 0, &enable_fastbranch, 1},
56 {"verbose", 0, &enable_disass, 1},
57 {"disass-usercode",0, &enable_disass_user, 1},
58 {"elf-header", 0, &enable_verb_elf, 1},
59 {"testcases", 0, &enable_testcases, 1},
60 {"regwrites", 0, &enable_regwrites, 1},
61 {"firmware", 0, &enable_firmware_mode, 1}, // load only .text
62 {"cosimulation", 0, &enable_cosimulation, 1},
63 // {"file", 1, 0, 'f'}, // 1 = required arg
64 // {"serial_in", 1, 0, 'i'}, // 1 = required arg
65 // {"serial_out", 1, 0, 'o'}, // 1 = required arg
66 {0, 0, 0, 0}
70 void usage(char *program)
72 int i;
74 if (strchr(program, '/')) {
75 program = strrchr(program, '/') + 1;
78 fprintf(stderr,
79 "YARI ISA Simulator\n"
80 "\n"
81 "Usage: %s [options] <mips-elf-files ...>\n"
82 "\n"
83 " where options can be one or more of\n"
84 "\n",
85 program);
87 for (i = 0; long_options[i].name; ++i) {
88 fprintf(stderr, " --%s\n", long_options[i].name);
91 fprintf(stderr,
92 " -i serialtty/file\n"
93 " -s serialtty/file\n"
94 "\n"
95 "Comments to <tommy-git@thorn.ws>\n");
97 exit(1);
100 void print_stats(void)
102 gettimeofday(&stat_stop_time, NULL);
104 double delta = stat_stop_time.tv_sec - stat_start_time.tv_sec
105 + 1e-6 * (stat_stop_time.tv_usec - stat_start_time.tv_usec);
107 putchar('\n');
108 printf("Simulation of %llu instructions in %4.2fs ~= %4.6f MIPS \n",
109 n_issue, delta, n_issue / (1e6 * delta));
111 // printf("%4.2f%% jal\n", 100.0 * n_call / n_issue);
112 printf("I$ %llu hits / %llu misses = %4.2f%% miss rate\n",
113 n_icache_hits, n_icache_misses,
114 100.0 * n_icache_misses / (n_icache_hits + n_icache_misses));
116 if (enable_cosimulation) {
117 double freq = 25.0;
119 printf("RTL stalls %llu\n", n_stall);
120 printf("RTL CPI: %4.2f ", (double) n_cycle / (double) n_issue);
121 printf("Cosim speed %4.2fX slower than realtime (assuming %g MHz)\n",
122 freq * 1e6 / (n_cycle / delta), freq);
125 printf("Gen load hazards: %12llu (%5.2f%%)\n", stat_gen_load_hazard,
126 stat_gen_load_hazard * 100.0 / n_issue);
128 printf("Load use hazards, rs: %12llu (%5.2f%%)\n", stat_load_use_hazard_rs,
129 stat_load_use_hazard_rs * 100.0 / n_issue);
131 printf(" rt: %12llu (%5.2f%%)\n", stat_load_use_hazard_rt,
132 stat_load_use_hazard_rt * 100.0 / n_issue);
134 printf("LW use hazards: %12llu (%5.2f%%)\n", stat_load32_use_hazard,
135 stat_load32_use_hazard * 100.0 / n_issue);
136 printf("Shift use hazards: %12llu (%5.2f%%)\n", stat_shift_use_hazard,
137 stat_shift_use_hazard * 100.0 / n_issue);
138 printf("Nops: %12llu (%5.2f%%)\n", stat_nop,
139 stat_nop * 100.0 / n_issue);
140 printf("Nops in delay slots: %12llu (%5.2f%%)\n", stat_nop_delay_slots,
141 stat_nop_delay_slots * 100.0 / n_issue);
142 printf("Nops after loads that aren't needed:\n"
143 " %12llu (%5.2f%%)\n", stat_nop_useless,
144 stat_nop_useless * 100.0 / n_issue);
147 int main(int argc, char **argv)
149 /* The Global MIPS State */
150 MIPS_state_t mips_state;
152 rs232in_fd = rs232out_fd = -1;
153 char *serial_input_file = NULL;
154 char *serial_output_file = NULL;
156 for (;;) {
157 int c;
158 int option_index = 0;
160 c = getopt_long(argc, argv, "tf:i:o:",
161 long_options, &option_index);
162 if (c == -1)
163 break;
165 switch (c) {
166 case 0:
167 break;
169 case 'f':
170 printf("file %s\n", filename = optarg);
171 break;
173 case 'i': serial_input_file = optarg; break;
174 case 'o': serial_output_file = optarg; break;
175 case '?':
176 usage(argv[0]);
177 break;
179 default:
180 printf ("?? getopt returned character code 0%o ??\n", c);
184 if (optind >= argc) {
185 usage(argv[0]);
188 while (optind < argc) {
189 readelf(argv[optind++]);
192 if (serial_input_file) {
193 printf("serial input %s\n", serial_input_file);
194 rs232in_fd = open(serial_input_file, O_RDONLY | O_NONBLOCK);
195 if (rs232in_fd < 0)
196 perror(optarg), exit(1);
199 /* Turn off echo */
200 struct termios t;
201 if (tcgetattr(rs232in_fd, &t))
202 /*perror("getattr")*/;
203 else {
204 t.c_lflag &= ~(ECHO|ECHOE|ECHOK);
205 if (tcsetattr(rs232in_fd, TCSANOW, &t))
206 perror("setattr");
211 if (serial_output_file) {
212 printf("serial output %s\n", serial_output_file);
213 rs232out_fd = open(serial_output_file, O_WRONLY | O_NONBLOCK);
214 if (rs232out_fd < 0)
215 perror(optarg), exit(1);
218 gettimeofday(&stat_start_time, NULL);
220 switch (run) {
221 case '1':
222 atexit(print_stats);
223 signal(SIGINT, exit);
224 mips_state.pc = program_entry;
225 init_reg_use_map();
226 run_simple(&mips_state);
227 break;
229 case 'r':
230 case 'd':
231 case 'm':
232 dump(run);
233 exit(0);
235 case 't':
236 dump_tinymon();
237 exit(0);
239 default:
240 printf("No XX-run option given\n");
241 exit(1);
244 if (enable_testcases) {
245 printf("Test ");
246 if (mips_state.r[7] == 0x1729) {
247 printf("SUCCEED!\n");
248 exit(0);
249 } else {
250 printf("FAILED! r7 = 0x%08x != 0x1729\n", mips_state.r[7]);
251 exit(1);
255 exit(0);
258 // Local Variables:
259 // mode: C
260 // c-style-variables-are-local-p: t
261 // c-file-style: "linux"
262 // End: