11 #include <netinet/in.h>
18 int enable_disass
= 0;
19 int enable_disass_user
= 0; // Enable disass once we reach user code (0x4...)
20 int enable_verb_elf
= 0;
21 int enable_forwarding
= 0;
22 int enable_fastbranch
= 0;
23 int enable_testcases
= 0;
24 int enable_regwrites
= 1; // XXX
25 int enable_firmware_mode
= 0;
26 int enable_cosimulation
= 0;
28 int endian_is_big
= 0;
29 struct timeval stat_start_time
, stat_stop_time
;
31 void *memory_segment
[NSEGMENT
];
32 unsigned memory_segment_size
[NSEGMENT
];
34 unsigned program_entry
= 0;
35 static SDL_Surface
*screen
;
47 static char *filename
= 0;
50 static struct option long_options
[] = {
51 {"help", 0, NULL
, '?'},
52 {"data-generation",0, &run
, 'd'}, // for Icarus Verilog simulation
53 {"hex-generation", 0, &run
, 'h'}, // for Quartus (HEX)
54 {"mif-generation", 0, &run
, 'm'}, // for Quartus (MIF)
55 {"tinymon-generation", 0, &run
, 't'}, // for Tinymon
56 {"forward-values", 0, &enable_forwarding
, 1},
57 {"fast-branch", 0, &enable_fastbranch
, 1},
58 {"verbose", 0, &enable_disass
, 1},
59 {"disass-usercode",0, &enable_disass_user
, 1},
60 {"elf-header", 0, &enable_verb_elf
, 1},
61 {"testcases", 0, &enable_testcases
, 1},
62 {"regwrites", 0, &enable_regwrites
, 1},
63 {"firmware", 0, &enable_firmware_mode
, 1}, // load only .text
64 {"cosimulation", 0, &enable_cosimulation
, 1},
65 // {"file", 1, 0, 'f'}, // 1 = required arg
66 // {"serial_in", 1, 0, 'i'}, // 1 = required arg
67 // {"serial_out", 1, 0, 'o'}, // 1 = required arg
72 void usage(char *program
)
76 if (strchr(program
, '/')) {
77 program
= strrchr(program
, '/') + 1;
81 "YARI ISA Simulator\n"
83 "Usage: %s [options] <mips-elf-files ...>\n"
85 " where options can be one or more of\n"
89 for (i
= 0; long_options
[i
].name
; ++i
) {
90 fprintf(stderr
, " --%s\n", long_options
[i
].name
);
94 " -i serialtty/file\n"
95 " -s serialtty/file\n"
97 "Comments to <tommy-git@thorn.ws>\n");
102 void print_stats(void)
104 gettimeofday(&stat_stop_time
, NULL
);
106 double delta
= stat_stop_time
.tv_sec
- stat_start_time
.tv_sec
107 + 1e-6 * (stat_stop_time
.tv_usec
- stat_start_time
.tv_usec
);
110 printf("Simulation of %llu instructions in %4.2fs ~= %4.6f MIPS \n",
111 n_issue
, delta
, n_issue
/ (1e6
* delta
));
113 // printf("%4.2f%% jal\n", 100.0 * n_call / n_issue);
114 printf("I$ %llu hits / %llu misses = %4.2f%% miss rate\n",
115 n_icache_hits
, n_icache_misses
,
116 100.0 * n_icache_misses
/ (n_icache_hits
+ n_icache_misses
));
118 if (enable_cosimulation
) {
121 printf("RTL stalls %llu\n", n_stall
);
122 printf("RTL CPI: %4.2f ", (double) n_cycle
/ (double) n_issue
);
123 printf("Cosim speed %4.2fX slower than realtime (assuming %g MHz)\n",
124 freq
* 1e6
/ (n_cycle
/ delta
), freq
);
127 printf("Gen load hazards: %12llu (%5.2f%%)\n", stat_gen_load_hazard
,
128 stat_gen_load_hazard
* 100.0 / n_issue
);
130 printf("Load use hazards, rs: %12llu (%5.2f%%)\n", stat_load_use_hazard_rs
,
131 stat_load_use_hazard_rs
* 100.0 / n_issue
);
133 printf(" rt: %12llu (%5.2f%%)\n", stat_load_use_hazard_rt
,
134 stat_load_use_hazard_rt
* 100.0 / n_issue
);
136 printf("LW use hazards: %12llu (%5.2f%%)\n", stat_load32_use_hazard
,
137 stat_load32_use_hazard
* 100.0 / n_issue
);
138 printf("Shift use hazards: %12llu (%5.2f%%)\n", stat_shift_use_hazard
,
139 stat_shift_use_hazard
* 100.0 / n_issue
);
140 printf("Nops: %12llu (%5.2f%%)\n", stat_nop
,
141 stat_nop
* 100.0 / n_issue
);
142 printf("Nops in delay slots: %12llu (%5.2f%%)\n", stat_nop_delay_slots
,
143 stat_nop_delay_slots
* 100.0 / n_issue
);
144 printf("Nops after loads that aren't needed:\n"
145 " %12llu (%5.2f%%)\n", stat_nop_useless
,
146 stat_nop_useless
* 100.0 / n_issue
);
151 unsigned last_generation
= 0;
156 while (SDL_PollEvent(&event
)) {
157 switch (event
.type
) {
158 case SDL_MOUSEMOTION
:
159 /*printf("Mouse moved by %d,%d to (%d,%d)\n",
160 event.motion.xrel, event.motion.yrel,
161 event.motion.x, event.motion.y);*/
163 case SDL_MOUSEBUTTONDOWN
:
164 /*printf("Mouse button %d pressed at (%d,%d)\n",
165 event.button.button, event.button.x, event.button.y);*/
168 //printf("Key down: %s\n", SDL_GetKeyName(event.key.keysym.sym));
169 if (event
.key
.keysym
.sym
== SDLK_ESCAPE
)
173 //printf("Key down: %s\n", SDL_GetKeyName(event.key.keysym.sym));
179 //printf("Unknown event: %d\n", event.type);
184 /* Only update the screen if the framebuffer has been written
186 if (last_generation
!= framebuffer_generation
) {
187 last_generation
= framebuffer_generation
;
188 memcpy(screen
->pixels
, addr2phys(framebuffer_start
),
191 SDL_UpdateRect(screen
, 0, 0, screen
->w
, screen
->h
);
192 // SDL_Flip(screen); either seem to work
195 SDL_Delay(1000 / 30); // 30 fps
201 framebuffer_start
= 0x40000000 + 1024*1024;
202 framebuffer_size
= 1024*768;
204 if (SDL_Init(SDL_INIT_VIDEO
) < 0) {
205 fprintf(stderr
, "Unable to init SDL: %s\n", SDL_GetError());
211 screen
= SDL_SetVideoMode(1024, 768, 8, SDL_SWSURFACE
);
212 if (screen
== NULL
) {
213 fprintf(stderr
, "Unable to set video: %s\n", SDL_GetError());
217 /* Set the window caption */
218 SDL_WM_SetCaption("Yarisim framebuffer", "YARISIM");
220 /* Populate the palette */
221 SDL_Color colors
[256];
224 /* Fill colors with color information RGB332 */
225 for (i
= 0; i
< 256; ++i
) {
226 colors
[i
].r
= (i
>> 5) * (255 / 7.0);
227 colors
[i
].g
= ((i
>> 2) & 7) * (255 / 7.0);
228 colors
[i
].b
= (i
& 3) * (255 / 3.0);
232 if (!SDL_SetColors(screen
, colors
, 0, 256)) {
233 fprintf(stderr
, "Unable to create framebuffer palette: %s\n",
235 screen
= 0; //XXX should free it
240 int main(int argc
, char **argv
)
242 /* The Global MIPS State */
243 MIPS_state_t mips_state
;
245 rs232in_fd
= rs232out_fd
= -1;
246 char *serial_input_file
= NULL
;
247 char *serial_output_file
= NULL
;
251 int option_index
= 0;
253 c
= getopt_long(argc
, argv
, "tf:i:o:",
254 long_options
, &option_index
);
263 printf("file %s\n", filename
= optarg
);
266 case 'i': serial_input_file
= optarg
; break;
267 case 'o': serial_output_file
= optarg
; break;
273 printf ("?? getopt returned character code 0%o ??\n", c
);
277 if (optind
>= argc
) {
281 while (optind
< argc
) {
282 readelf(argv
[optind
++]);
285 if (serial_input_file
) {
286 printf("serial input %s\n", serial_input_file
);
287 rs232in_fd
= open(serial_input_file
, O_RDONLY
| O_NONBLOCK
);
289 perror(optarg
), exit(1);
294 if (tcgetattr(rs232in_fd
, &t
))
295 /*perror("getattr")*/;
297 t
.c_lflag
&= ~(ECHO
|ECHOE
|ECHOK
);
298 if (tcsetattr(rs232in_fd
, TCSANOW
, &t
))
304 if (serial_output_file
) {
305 printf("serial output %s\n", serial_output_file
);
306 rs232out_fd
= open(serial_output_file
, O_WRONLY
| O_NONBLOCK
);
308 perror(optarg
), exit(1);
311 gettimeofday(&stat_start_time
, NULL
);
317 signal(SIGINT
, exit
);
318 mips_state
.pc
= program_entry
;
322 SDL_CreateThread((int (*)(void *))run_simple
, &mips_state
);
325 run_simple(&mips_state
);
339 printf("No XX-run option given\n");
343 if (enable_testcases
) {
345 if (mips_state
.r
[7] == 0x1729) {
346 printf("SUCCEED!\n");
349 printf("FAILED! r7 = 0x%08x != 0x1729\n", mips_state
.r
[7]);
359 // c-style-variables-are-local-p: t
360 // c-file-style: "linux"