#![allow(dead_code)] #![allow(unused_variables)] use super::decode::{Instruction}; use super::global::*; const NAMES_OP: [&str; 8] = ["add", "sll", "slt", "sltu", "xor", "sr", "or", "and"]; const NAMES_OPI: [&str; 8] = ["addi", "slli", "slti", "sltiu", "xori", "slri", "ori", "andi"]; const NAMES_MUL: [&str; 8] = ["mpylo", "mpyhi", "mpyhi", "mpyhi", "divhi", "divhi", "divlo", "divlo"]; const NAMES_BR: [&str; 8] = ["beq", "bne", "", "", "blt", "bge", "bltu", "bgeu"]; const NAMES_ST: [&str; 4] = ["sb", "sh", "sw", "sd"]; const NAMES_LD: [&str; 7] = ["lb", "lh", "lw", "ld", "lbu", "lhu", "lwu"]; const NAMES_OPW: [&str; 8] = ["addw", "sllw", "", "", "", "srw", "", ""]; const NAMES_OPIW: [&str; 8] = ["addiw", "slliw", "", "", "", "sri", "", ""]; // Register name mapping const REG_X: [&str; 32] = ["zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", // fp ou s0 ? "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"]; const REG_F: [&str; 32] = ["ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"]; pub fn print(ins: Instruction, pc: i32) -> String { //TODO pc should be u64 let rd = ins.rd as usize; let rs1 = ins.rs1 as usize; let rs2 = ins.rs2 as usize; match ins.opcode { RISCV_OP => { let name: &str; if ins.funct7 == 1 { // Use mul array name = NAMES_MUL[ins.funct3 as usize] } else if ins.funct3 == RISCV_OP_ADD { // Add or Sub if ins.funct7 == RISCV_OP_ADD_ADD { name = "add"; } else { name = "sub"; } } else if ins.funct3 == RISCV_OP_SR { // Srl or Sra if ins.funct7 == RISCV_OP_SR_SRL { name = "srl"; } else { name = "sra"; } } else { name = NAMES_OP[ins.funct3 as usize]; } format!("{}\t{},{},{}", name, REG_X[rd], REG_X[rs1], REG_X[rs2]) }, RISCV_OPI => { // SHAMT OR IMM if ins.funct3 == RISCV_OPI_SRI { if ins.funct7 == RISCV_OPI_SRI_SRLI { format!("srli\t{},{},{}", REG_X[rd], REG_X[rs1], ins.shamt) } else { format!("srai\t{},{},{}", REG_X[rd], REG_X[rs1], ins.shamt) } } else if ins.funct3 == RISCV_OPI_SLLI { format!("{}\t{},{},{}", NAMES_OPI[ins.funct3 as usize], REG_X[rd], REG_X[rs1], ins.shamt) } else { format!("{}\t{},{},{}", NAMES_OPI[ins.funct3 as usize], REG_X[rd], REG_X[rs1], ins.imm12_I_signed) } }, RISCV_LUI => { format!("lui\t{},{:x}", REG_X[rd], ins.imm31_12) }, RISCV_AUIPC => { format!("auipc\t{},{:x}", REG_X[rd], ins.imm31_12) }, RISCV_JAL => { format!("jal\t{},{:x}", REG_X[rd], (pc + ins.imm21_1_signed)) }, RISCV_JALR => { format!("jalr\t{},{}({})", REG_X[rd], ins.imm12_I_signed, REG_X[rs1]) }, RISCV_BR => { format!("{}\t{},{},{:x}", NAMES_BR[ins.funct3 as usize], REG_X[rs1], REG_X[rs2], pc + (ins.imm13_signed as i32)) }, RISCV_LD => { format!("{}\t{},{}({})", NAMES_LD[ins.funct3 as usize], REG_X[rd], ins.imm12_I_signed, REG_X[rs1]) }, RISCV_ST => { format!("{}\t{},{}({})", NAMES_ST[ins.funct3 as usize], REG_X[rs2], ins.imm12_S_signed, REG_X[rs1]) }, RISCV_OPIW => { if ins.funct3 == RISCV_OPIW_SRW { if ins.funct7 == RISCV_OPIW_SRW_SRLIW { format!("srliw\t{},{},{}", REG_X[rd], REG_X[rs1], REG_X[rs2]) } else { format!("sraiw\t{},{},{}", REG_X[rd], REG_X[rs1], REG_X[rs2]) } } else if ins.funct3 == RISCV_OPIW_SLLIW { format!("{}\t{},{},{}", NAMES_OPI[ins.funct3 as usize], REG_X[rd], REG_X[rs1], REG_X[rs2]) } else { format!("{}\t{},{},{}", NAMES_OPIW[ins.funct3 as usize], REG_X[rd], REG_X[rs1], ins.imm12_I_signed) } }, RISCV_OPW => { if ins.funct7 == 1 { format!("{}w\t{},{},{}", NAMES_MUL[ins.funct3 as usize], REG_X[rd], REG_X[rs1], REG_X[rs2]) } else if ins.funct3 == RISCV_OP_ADD { if ins.funct7 == RISCV_OPW_ADDSUBW_ADDW { format!("addw\t{},{},{}", REG_X[rd], REG_X[rs1], REG_X[rs2]) } else { format!("subw\t{},{},{}", REG_X[rd], REG_X[rs1], REG_X[rs2]) } } else if ins.funct3 == RISCV_OPW_SRW { if ins.funct7 == RISCV_OPW_SRW_SRLW { format!("srlw\t{},{},{}", REG_X[rd], REG_X[rs1], REG_X[rs2]) } else { format!("sraw\t{},{},{}", REG_X[rd], REG_X[rs1], REG_X[rs2]) } } else { format!("{}\t{},{},{}", NAMES_OPW[ins.funct3 as usize], REG_X[rd], REG_X[rs1], REG_X[rs2]) } }, RISCV_SYSTEM => { "ecall".to_string() }, _ => todo!("Unknown or currently unsupported opcode") // Change todo! to panic! in the future, I put todo! because there's a lot of opcode currently not implemented } } #[cfg(test)] mod test { #![allow(clippy::unusual_byte_groupings)] use crate::simulator::{decode, print}; #[test] fn test_op() { let sub = decode::decode(0b0100000_10000_10001_000_11100_0110011); let add = decode::decode(0b0000000_10000_10001_000_11100_0110011); let xor = decode::decode(0b0000000_10000_10001_100_11100_0110011); let slr = decode::decode(0b0000000_10000_10001_101_11100_0110011); let sra = decode::decode(0b0100000_10000_10001_101_11100_0110011); assert_eq!("sub\tt3,a7,a6", print::print(sub, 0)); assert_eq!("xor\tt3,a7,a6", print::print(xor, 0)); assert_eq!("srl\tt3,a7,a6", print::print(slr, 0)); assert_eq!("sra\tt3,a7,a6", print::print(sra, 0)); assert_eq!("add\tt3,a7,a6", print::print(add, 0)); } #[test] fn test_opi() { let addi = decode::decode(0b0000000000_10001_000_11100_0010011); let slli = decode::decode(0b0000000000_10001_001_11100_0010011); let slti = decode::decode(0b0000000000_10001_010_11100_0010011); let sltiu = decode::decode(0b0000000000_10001_011_11100_0010011); let xori = decode::decode(0b_0000000000010001_100_11100_0010011); let ori = decode::decode(0b00000000000_10001_110_11100_0010011); let andi = decode::decode(0b000000000000_10001_111_11100_0010011); assert_eq!("andi\tt3,a7,0", print::print(andi, 0)); assert_eq!("addi\tt3,a7,0", print::print(addi, 0)); assert_eq!("slli\tt3,a7,0", print::print(slli, 0)); assert_eq!("slti\tt3,a7,0", print::print(slti, 0)); assert_eq!("sltiu\tt3,a7,0", print::print(sltiu, 0)); assert_eq!("xori\tt3,a7,0", print::print(xori, 0)); assert_eq!("ori\tt3,a7,0", print::print(ori, 0)); } #[test] fn test_lui() { let lui = decode::decode(0b01110001000011111000_11100_0110111); let lui_negatif = decode::decode(0b11110001000011111000_11100_0110111); assert_eq!("lui\tt3,710f8000", print::print(lui, 0)); assert_eq!("lui\tt3,f10f8000", print::print(lui_negatif, 0)); } #[test] fn test_ld() { // imm rs1 f3 rd opcode let lb = decode::decode(0b010111110000_10001_000_11100_0000011); let lh = decode::decode(0b010111110000_10001_001_11100_0000011); let lw = decode::decode(0b010111110000_10001_010_11100_0000011); let lbu = decode::decode(0b010111110000_10001_100_11100_0000011); let lhu = decode::decode(0b010111110000_10001_101_11100_0000011); let ld = decode::decode(0b010111110000_10001_011_11100_0000011); let lwu = decode::decode(0b010111110000_10001_110_11100_0000011); assert_eq!("lb\tt3,1520(a7)", print::print(lb, 0)); assert_eq!("lh\tt3,1520(a7)", print::print(lh, 0)); assert_eq!("lw\tt3,1520(a7)", print::print(lw, 0)); assert_eq!("lbu\tt3,1520(a7)", print::print(lbu, 0)); assert_eq!("lhu\tt3,1520(a7)", print::print(lhu, 0)); assert_eq!("ld\tt3,1520(a7)", print::print(ld, 0)); assert_eq!("lwu\tt3,1520(a7)", print::print(lwu, 0)); } #[test] fn test_opw() { let addw: decode::Instruction = decode::decode(0b0000000_10000_10001_000_11100_0111011); let sllw: decode::Instruction = decode::decode(0b0000000_10000_10001_001_11100_0111011); let srlw: decode::Instruction = decode::decode(0b0000000_10000_10001_101_11100_0111011); let sraw: decode::Instruction = decode::decode(0b0100000_10000_10001_101_11100_0111011); assert_eq!("addw\tt3,a7,a6", print::print(addw, 0)); assert_eq!("sllw\tt3,a7,a6", print::print(sllw, 0)); assert_eq!("srlw\tt3,a7,a6", print::print(srlw, 0)); assert_eq!("sraw\tt3,a7,a6", print::print(sraw, 0)); } #[test] fn test_opwi() { let addiw: decode::Instruction =decode::decode(0b000000000000_10001_000_11100_0011011); let slliw: decode::Instruction = decode::decode(0b0000000_10000_10001_001_11100_0011011); let srai: decode::Instruction = decode::decode(0b010000010001_10001_101_11100_0010011); assert_eq!("addiw\tt3,a7,0", print::print(addiw, 0)); assert_eq!("slli\tt3,a7,a6", print::print(slliw, 0)); assert_eq!("srai\tt3,a7,17", print::print(srai, 0)); } #[test] fn test_br() { let beq: decode::Instruction = decode::decode(0b0000000_10000_10001_000_00000_1100011); let bne: decode::Instruction = decode::decode(0b0000000_10000_10001_001_00000_1100011); let blt: decode::Instruction = decode::decode(0b0000000_10000_10001_100_00000_1100011); let bge: decode::Instruction = decode::decode(0b0000000_10000_10001_101_00000_1100011); let bltu: decode::Instruction = decode::decode(0b0000000_10000_10001_110_00000_1100011); let bgeu: decode::Instruction = decode::decode(0b0000000_10000_10001_111_00000_1100011); assert_eq!("blt\ta7,a6,0", print::print(blt, 0)); assert_eq!("bge\ta7,a6,0", print::print(bge, 0)); assert_eq!("bltu\ta7,a6,0", print::print(bltu, 0)); assert_eq!("bgeu\ta7,a6,0", print::print(bgeu, 0)); assert_eq!("bne\ta7,a6,0", print::print(bne, 0)); assert_eq!("beq\ta7,a6,0", print::print(beq, 0)); } #[test] fn test_small_program() { /* Code for : int a = 0; int b = 5; a = b; a = a * b; a = a + b; b = a - b; */ assert_eq!("addi sp,sp,-32", print::print(decode::decode(0xfe010113), 0)); assert_eq!("sd s0,24(sp)", print::print(decode::decode(0x00813c23), 0)); assert_eq!("addi s0,sp,32", print::print(decode::decode(0x02010413), 0)); assert_eq!("sw zero,-20(s0)", print::print(decode::decode(0xfe042623), 0)); assert_eq!("addi a5,zero,5", print::print(decode::decode(0x00500793), 0)); assert_eq!("sw a5,-24(s0)", print::print(decode::decode(0xfef42423), 0)); assert_eq!("lw a5,-24(s0)", print::print(decode::decode(0xfe842783), 0)); assert_eq!("sw a5,-20(s0)", print::print(decode::decode(0xfef42623), 0)); assert_eq!("lw a5,-20(s0)", print::print(decode::decode(0xfec42783), 0)); assert_eq!("addi a4,a5,0", print::print(decode::decode(0x00078713), 0)); assert_eq!("lw a5,-24(s0)", print::print(decode::decode(0xfe842783), 0)); //Waiting for mulw implementation assert_eq!("mulw a5,a4,a5", print::print(decode::decode(0x02f707bb), 0)); assert_eq!("sw a5,-20(s0)", print::print(decode::decode(0xfef42623), 0)); assert_eq!("lw a5,-20(s0)", print::print(decode::decode(0xfec42783), 0)); assert_eq!("addi a4,a5,0", print::print(decode::decode(0x00078713), 0)); assert_eq!("lw a5,-24(s0)", print::print(decode::decode(0xfe842783), 0)); assert_eq!("addw a5,a4,a5", print::print(decode::decode(0x00f707bb), 0)); assert_eq!("sw a5,-20(s0)", print::print(decode::decode(0xfef42623), 0)); assert_eq!("lw a5,-20(s0)", print::print(decode::decode(0xfec42783), 0)); assert_eq!("addi a4,a5,0", print::print(decode::decode(0x00078713), 0)); assert_eq!("lw a5,-24(s0)", print::print(decode::decode(0xfe842783), 0)); assert_eq!("subw a5,a4,a5", print::print(decode::decode(0x40f707bb), 0)); assert_eq!("sw a5,-24(s0)", print::print(decode::decode(0xfef42423), 0)); assert_eq!("addi a5,zero,0", print::print(decode::decode(0x00000793), 0)); assert_eq!("addi a0,a5,0", print::print(decode::decode(0x00078513), 0)); assert_eq!("ld s0,24(sp)", print::print(decode::decode(0x01813403), 0)); assert_eq!("addi sp,sp,32", print::print(decode::decode(0x02010113), 0)); assert_eq!("jalr zero,0(ra)", print::print(decode::decode(0x00008067), 0)); } #[test] fn test_fibo() { assert_eq!("jal zero,10504", print::print(decode::decode(0x0500006f), 0x104b4)); assert_eq!("blt a4,a5,104b8", print::print(decode::decode(0xfaf740e3), 0x10518)); } }