1const TEST_MEMORY_CAPACITY: u64 = 1024 * 512;
3const PROGRAM_MEMORY_CAPACITY: u64 = 1024 * 1024 * 128; pub mod cpu;
6pub mod terminal;
7pub mod default_terminal;
8pub mod memory;
9pub mod mmu;
10pub mod device;
11
12use cpu::{Cpu, Xlen};
13use terminal::Terminal;
14
15pub struct Emulator {
29 cpu: Cpu,
30
31 is_test: bool,
35
36 tohost_addr: u64
39}
40
41struct SectionHeader {
43 sh_name: u64,
44 _sh_type: u64,
45 _sh_flags: u64,
46 sh_addr: u64,
47 sh_offset: u64,
48 sh_size: u64,
49 _sh_link: u64,
50 _sh_info: u64,
51 _sh_addralign: u64,
52 _sh_entsize: u64
53}
54
55impl Emulator {
56 pub fn new(terminal: Box<dyn Terminal>) -> Self {
62 Emulator {
63 cpu: Cpu::new(terminal),
64
65 is_test: false,
67 tohost_addr: 0
68 }
69 }
70
71 pub fn run(&mut self) {
75 match self.is_test {
76 true => self.run_test(),
77 false => self.run_program()
78 };
79 }
80
81 pub fn run_program(&mut self) {
83 loop {
84 self.tick();
85 }
86 }
87
88 pub fn run_test(&mut self) {
94 println!("This elf file seems riscv-tests elf file. Running in test mode.");
96 loop {
97 let disas = self.cpu.disassemble_next_instruction();
98 self.put_bytes_to_terminal(disas.as_bytes());
99 self.put_bytes_to_terminal(&[10]); self.tick();
102
103 let endcode = self.cpu.get_mut_mmu().load_word_raw(self.tohost_addr);
110 if endcode != 0 {
111 match endcode {
112 1 => {
113 self.put_bytes_to_terminal(format!("Test Passed with {:X}\n", endcode).as_bytes())
114 },
115 _ => {
116 self.put_bytes_to_terminal(format!("Test Failed with {:X}\n", endcode).as_bytes())
117 }
118 };
119 break;
120 }
121 }
122 }
123
124 fn put_bytes_to_terminal(&mut self, bytes: &[u8]) {
129 for i in 0..bytes.len() {
130 self.cpu.get_mut_terminal().put_byte(bytes[i]);
131 }
132 }
133
134 pub fn tick(&mut self) {
136 self.cpu.tick();
137 }
138
139 pub fn setup_program(&mut self, data: Vec<u8>) {
148 if data[0] != 0x7f || data[1] != 0x45 || data[2] != 0x4c || data[3] != 0x46 {
152 panic!("This file does not seem ELF file");
153 }
154
155 let e_class = data[4];
156
157 let e_width = match e_class {
158 1 => 32,
159 2 => 64,
160 _ => panic!("Unknown e_class:{:X}", e_class)
161 };
162
163 let _e_endian = data[5];
164 let _e_elf_version = data[6];
165 let _e_osabi = data[7];
166 let _e_abi_version = data[8];
167
168 let mut offset = 0x10;
169
170 let mut _e_type = 0 as u64;
171 for i in 0..2 {
172 _e_type |= (data[offset] as u64) << (8 * i);
173 offset += 1;
174 }
175
176 let mut _e_machine = 0 as u64;
177 for i in 0..2 {
178 _e_machine |= (data[offset] as u64) << (8 * i);
179 offset += 1;
180 }
181
182 let mut _e_version = 0 as u64;
183 for i in 0..4 {
184 _e_version |= (data[offset] as u64) << (8 * i);
185 offset += 1;
186 }
187
188 let mut e_entry = 0 as u64;
189 for i in 0..e_width / 8 {
190 e_entry |= (data[offset] as u64) << (8 * i);
191 offset += 1;
192 }
193
194 let mut _e_phoff = 0 as u64;
195 for i in 0..e_width / 8 {
196 _e_phoff |= (data[offset] as u64) << (8 * i);
197 offset += 1;
198 }
199
200 let mut e_shoff = 0 as u64;
201 for i in 0..e_width / 8 {
202 e_shoff |= (data[offset] as u64) << (8 * i);
203 offset += 1;
204 }
205
206 let mut _e_flags = 0 as u64;
207 for i in 0..4 {
208 _e_flags |= (data[offset] as u64) << (8 * i);
209 offset += 1;
210 }
211
212 let mut _e_ehsize = 0 as u64;
213 for i in 0..2 {
214 _e_ehsize |= (data[offset] as u64) << (8 * i);
215 offset += 1;
216 }
217
218 let mut _e_phentsize = 0 as u64;
219 for i in 0..2 {
220 _e_phentsize |= (data[offset] as u64) << (8 * i);
221 offset += 1;
222 }
223
224 let mut _e_phnum = 0 as u64;
225 for i in 0..2 {
226 _e_phnum |= (data[offset] as u64) << (8 * i);
227 offset += 1;
228 }
229
230 let mut _e_shentsize = 0 as u64;
231 for i in 0..2 {
232 _e_shentsize |= (data[offset] as u64) << (8 * i);
233 offset += 1;
234 }
235
236 let mut e_shnum = 0 as u64;
237 for i in 0..2 {
238 e_shnum |= (data[offset] as u64) << (8 * i);
239 offset += 1;
240 }
241
242 let mut _e_shstrndx = 0 as u64;
243 for i in 0..2 {
244 _e_shstrndx |= (data[offset] as u64) << (8 * i);
245 offset += 1;
246 }
247
248 let mut program_data_section_headers = vec![];
348 let mut string_table_section_headers = vec![];
349
350 offset = e_shoff as usize;
351 for _i in 0..e_shnum {
352 let mut sh_name = 0 as u64;
353 for i in 0..4 {
354 sh_name |= (data[offset] as u64) << (8 * i);
355 offset += 1;
356 }
357
358 let mut sh_type = 0 as u64;
359 for i in 0..4 {
360 sh_type |= (data[offset] as u64) << (8 * i);
361 offset += 1;
362 }
363
364 let mut sh_flags = 0 as u64;
365 for i in 0..e_width / 8 {
366 sh_flags |= (data[offset] as u64) << (8 * i);
367 offset += 1;
368 }
369
370 let mut sh_addr = 0 as u64;
371 for i in 0..e_width / 8 {
372 sh_addr |= (data[offset] as u64) << (8 * i);
373 offset += 1;
374 }
375
376 let mut sh_offset = 0 as u64;
377 for i in 0..e_width / 8 {
378 sh_offset |= (data[offset] as u64) << (8 * i);
379 offset += 1;
380 }
381
382 let mut sh_size = 0 as u64;
383 for i in 0..e_width / 8 {
384 sh_size |= (data[offset] as u64) << (8 * i);
385 offset += 1;
386 }
387
388 let mut sh_link = 0 as u64;
389 for i in 0..4 {
390 sh_link |= (data[offset] as u64) << (8 * i);
391 offset += 1;
392 }
393
394 let mut sh_info = 0 as u64;
395 for i in 0..4 {
396 sh_info |= (data[offset] as u64) << (8 * i);
397 offset += 1;
398 }
399
400 let mut sh_addralign = 0 as u64;
401 for i in 0..e_width / 8 {
402 sh_addralign |= (data[offset] as u64) << (8 * i);
403 offset += 1;
404 }
405
406 let mut sh_entsize = 0 as u64;
407 for i in 0..e_width / 8 {
408 sh_entsize |= (data[offset] as u64) << (8 * i);
409 offset += 1;
410 }
411
412 let section_header = SectionHeader {
428 sh_name: sh_name,
429 _sh_type: sh_type,
430 _sh_flags: sh_flags,
431 sh_addr: sh_addr,
432 sh_offset: sh_offset,
433 sh_size: sh_size,
434 _sh_link: sh_link,
435 _sh_info: sh_info,
436 _sh_addralign: sh_addralign,
437 _sh_entsize: sh_entsize
438 };
439
440 if sh_type == 1 {
441 program_data_section_headers.push(section_header);
442 } else if sh_type == 3 {
443 string_table_section_headers.push(section_header);
444 }
445 }
446
447 let tohost_values = vec![0x2e, 0x74, 0x6f, 0x68, 0x6f, 0x73, 0x74, 0x00]; let mut tohost_addr = 0; for i in 0..program_data_section_headers.len() {
453 let sh_addr = program_data_section_headers[i].sh_addr;
454 let sh_name = program_data_section_headers[i].sh_name;
455 for j in 0..string_table_section_headers.len() {
456 let sh_offset = string_table_section_headers[j].sh_offset;
457 let sh_size = string_table_section_headers[j].sh_size;
458 let mut found = true;
459 for k in 0..tohost_values.len() as u64{
460 let addr = sh_offset + sh_name + k;
461 if addr >= sh_offset + sh_size || data[addr as usize] != tohost_values[k as usize] {
462 found = false;
463 break;
464 }
465 }
466 if found {
467 tohost_addr = sh_addr;
468 }
469 }
470 if tohost_addr != 0 {
471 break;
472 }
473 }
474
475 self.cpu.update_xlen(match e_width {
479 32 => Xlen::Bit32,
480 64 => Xlen::Bit64,
481 _ => panic!("No happen")
482 });
483
484 if tohost_addr != 0 {
485 self.is_test = true;
486 self.tohost_addr = tohost_addr;
487 self.cpu.get_mut_mmu().init_memory(TEST_MEMORY_CAPACITY);
488 } else {
489 self.is_test = false;
490 self.tohost_addr = 0;
491 self.cpu.get_mut_mmu().init_memory(PROGRAM_MEMORY_CAPACITY);
492 }
493
494 for i in 0..program_data_section_headers.len() {
495 let sh_addr = program_data_section_headers[i].sh_addr;
496 let sh_offset = program_data_section_headers[i].sh_offset;
497 let sh_size = program_data_section_headers[i].sh_size;
498 if sh_addr >= 0x80000000 && sh_offset > 0 && sh_size > 0 {
499 for j in 0..sh_size as usize {
500 self.cpu.get_mut_mmu().store_raw(sh_addr + j as u64, data[sh_offset as usize + j]);
501 }
502 }
503 }
504
505 self.cpu.update_pc(e_entry);
506 }
507
508 pub fn setup_filesystem(&mut self, content: Vec<u8>) {
514 self.cpu.get_mut_mmu().init_disk(content);
515 }
516
517 pub fn setup_dtb(&mut self, content: Vec<u8>) {
524 self.cpu.get_mut_mmu().init_dtb(content);
525 }
526
527 pub fn update_xlen(&mut self, xlen: Xlen) {
532 self.cpu.update_xlen(xlen);
533 }
534
535 pub fn get_mut_terminal(&mut self) -> &mut Box<dyn Terminal> {
537 self.cpu.get_mut_terminal()
538 }
539
540 pub fn get_cpu(&self) -> &Cpu {
542 &self.cpu
543 }
544
545 pub fn get_mut_cpu(&mut self) -> &mut Cpu {
547 &mut self.cpu
548 }
549}