perilus

RISC-V processor built with Chisel
git clone https://git.bradleygannon.com/perilus.git
Log | Files | Refs | Submodules | README

main.rs (1925B)


      1 use std::{error::Error, path::PathBuf};
      2 
      3 use clap::{Parser, Subcommand};
      4 use perilus_core::perilus::Perilus;
      5 
      6 #[derive(Parser)]
      7 struct Cli {
      8     #[command(subcommand)]
      9     command: Command,
     10 }
     11 
     12 #[derive(Subcommand)]
     13 enum Command {
     14     /// Run a raw binary program to completion and report pass/fail
     15     Test { file: PathBuf },
     16 }
     17 
     18 const EBREAK_INSTRUCTION: u32 = 0x00100073;
     19 const TEST_MAX_CYCLES: u32 = 1_000_000;
     20 const TEST_PASS_VALUE: u32 = 0xebbb3689;
     21 const TEST_FAIL_VALUE: u32 = 0xd02a545a;
     22 
     23 fn main() -> Result<(), Box<dyn Error>> {
     24     let cli = Cli::parse();
     25     let perilus = Perilus::init();
     26 
     27     match cli.command {
     28         Command::Test { file } => {
     29             perilus.load_file(file)?;
     30             let mut cycles = 0;
     31             loop {
     32                 perilus.pulse_clock();
     33                 cycles += 1;
     34                 if cycles > TEST_MAX_CYCLES {
     35                     return Err("Test execution hit maximum cycle count limit".into());
     36                 }
     37                 if perilus.get_control_unit_state() == 0 {
     38                     let pc = perilus.get_pc();
     39                     let instr = perilus.get_memory().get((pc / 4) as usize);
     40                     if instr.is_none() {
     41                         return Err(format!(
     42                             "Program counter diverged to an address outside memory: 0x{pc:08x}"
     43                         )
     44                         .into());
     45                     }
     46                     if let Some(&EBREAK_INSTRUCTION) = instr {
     47                         let result = perilus.get_registers()[1];
     48                         match result {
     49                             TEST_PASS_VALUE => return Ok(()),
     50                             TEST_FAIL_VALUE => return Err("Test failed".into()),
     51                             v => return Err(format!("Got unexpected test result 0x{v:08x}").into()),
     52                         }
     53                     }
     54                 }
     55             }
     56         }
     57     }
     58 }