| // This file define the kelvin base isa for mpact-sim. For more info on mpact-sim |
| // isa format, check: go/mpact-sim-codelabs-riscv-instruction-decoder |
| |
| // First disasm field is 18 char wide and left justified. |
| disasm widths = {-18}; |
| |
| // Basic integer ALU instructions, part of the RiscV 32i subset. |
| slot riscv32i { |
| includes { |
| #include "riscv/riscv_i_instructions.h" |
| } |
| default size = 4; |
| default latency = global_latency; |
| resources TwoOp = { next_pc, rs1 : rd[..rd]}; |
| resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]}; |
| opcodes { |
| addi{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "addi", "%rd, %rs1, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAdd"; |
| li{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "li", "%rd, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAdd"; |
| mv{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "mv", "%rd, %rs1", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAdd"; |
| slti{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "slti", "%rd, %rs1, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISlt"; |
| sltiu{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "sltiu", "%rd, %rs1, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISltu"; |
| andi{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "andi", "%rd, %rs1, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAnd"; |
| ori{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "ori", "%rd, %rs1, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIOr"; |
| xori{: rs1, I_imm12 : rd}, |
| resources: TwoOp, |
| disasm: "xori", "%rd, %rs1, %I_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIXor"; |
| slli{: rs1, I_uimm5 : rd}, |
| resources: TwoOp, |
| disasm: "slli", "%rd, %rs1, 0x%(I_uimm5:x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISll"; |
| srli{: rs1, I_uimm5 : rd}, |
| resources: TwoOp, |
| disasm: "srli", "%rd %rs1, 0x%(I_uimm5:x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISrl"; |
| srai{: rs1, I_uimm5 : rd}, |
| resources: TwoOp, |
| disasm: "srai", "%rd, %rs1, 0x%(I_uimm5:x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISra"; |
| lui{: U_imm20 : rd}, |
| resources: { next_pc : rd[0..]}, |
| disasm: "lui", "%rd, 0x%(U_imm20:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVILui"; |
| auipc{: U_imm20 : rd}, |
| resources: { next_pc : rd[0..]}, |
| disasm: "auipc", "%rd, 0x%(U_imm20:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAuipc"; |
| add{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "add", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAdd"; |
| slt{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "slt", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISlt"; |
| sltu{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "sltu", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISltu"; |
| and{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "and", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIAnd"; |
| or{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "or", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIOr"; |
| xor{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "xor", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIXor"; |
| sll{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "sll", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISll"; |
| srl{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "srl", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISrl"; |
| sub{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "sub", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISub"; |
| sra{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "sra", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVISra"; |
| nop{}, |
| disasm: "nop", |
| semfunc: "&mpact::sim::riscv::RiscVINop"; |
| hint{}, |
| disasm: "hint", |
| semfunc: "&mpact::sim::riscv::RiscVINop"; |
| jal{: J_imm20 : next_pc, rd}, |
| resources: { next_pc : next_pc[0..], rd[0..]}, |
| disasm: "jal", "%rd, %(@+J_imm20:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIJal"; |
| jalr{: rs1, J_imm12 : next_pc, rd}, |
| resources: { next_pc, rs1 : next_pc[0..], rd[0..]}, |
| disasm: "jalr", "%rd, %rs1, %J_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIJalr"; |
| j{: J_imm20 : next_pc, rd}, |
| resources: { next_pc : next_pc[0..], rd[0..]}, |
| disasm: "j", "%(@+J_imm20:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIJal"; |
| jr{: rs1, J_imm12 : next_pc, rd}, |
| resources: { next_pc, rs1 : next_pc[0..], rd[0..]}, |
| disasm: "jr", "%rs1, %J_imm12", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIJalr"; |
| ret{: rs1, J_imm12 : next_pc, rd}, |
| resources: { next_pc, rs1 : next_pc[0..], rd[0..]}, |
| disasm: "ret", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIJalr"; |
| beq{: rs1, rs2, B_imm12 : next_pc}, |
| resources: { next_pc, rs1, rs2 : next_pc[0..]}, |
| disasm: "beq", "%rs1, %rs2, %(@+B_imm12:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIBeq"; |
| bne{: rs1, rs2, B_imm12 : next_pc}, |
| resources: { next_pc, rs1, rs2 : next_pc[0..]}, |
| disasm: "bne", "%rs1, %rs2, %(@+B_imm12:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIBne"; |
| blt{: rs1, rs2, B_imm12 : next_pc}, |
| resources: { next_pc, rs1, rs2 : next_pc[0..]}, |
| disasm: "blt", "%rs1, %rs2, %(@+B_imm12:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIBlt"; |
| bltu{: rs1, rs2, B_imm12 : next_pc}, |
| resources: { next_pc, rs1, rs2 : next_pc[0..]}, |
| disasm: "bltu", "%rs1, %rs2, %(@+B_imm12:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIBltu"; |
| bge{: rs1, rs2, B_imm12 : next_pc}, |
| resources: { next_pc, rs1, rs2 : next_pc[0..]}, |
| disasm: "bge", "%rs1, %rs2, %(@+B_imm12:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIBge"; |
| bgeu{: rs1, rs2, B_imm12 : next_pc}, |
| resources: { next_pc, rs1, rs2 : next_pc[0..]}, |
| disasm: "bgeu", "%rs1, %rs2, %(@+B_imm12:08x)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVIBgeu"; |
| lw{(: rs1, I_imm12), (: : rd)}, |
| resources: { next_pc, rs1 : rd[0..]}, |
| disasm: "lw", "%rd, %I_imm12(%rs1)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVILw", "&mpact::sim::riscv::RV32::RiscVILwChild"; |
| lh{(: rs1, I_imm12 :), (: : rd)}, |
| resources: { next_pc, rs1 : rd[0..]}, |
| disasm: "lh", "%rd, %I_imm12(%rs1)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVILh", "&mpact::sim::riscv::RV32::RiscVILhChild"; |
| lhu{(: rs1, I_imm12 :), (: : rd)}, |
| resources: { next_pc, rs1 : rd[0..]}, |
| disasm: "lhu", "%rd, %I_imm12(%rs1)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVILhu", "&mpact::sim::riscv::RV32::RiscVILhuChild"; |
| lb{(: rs1, I_imm12 :), (: : rd)}, |
| resources: { next_pc, rs1 : rd[0..]}, |
| disasm: "lb", "%rd, %I_imm12(%rs1)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVILb", "&mpact::sim::riscv::RV32::RiscVILbChild"; |
| lbu{(: rs1, I_imm12 :), (: : rd)}, |
| resources: { next_pc, rs1 : rd[0..]}, |
| disasm: "lbu", "%rd, %I_imm12(%rs1)", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVILbu", "&mpact::sim::riscv::RV32::RiscVILbuChild"; |
| sw{: rs1, S_imm12, rs2 : }, |
| resources: { next_pc, rs1, rs2 : }, |
| disasm: "sw", "%rs2, %S_imm12(%rs1)", |
| semfunc: "&KelvinIStore<uint32_t>"; |
| sh{: rs1, S_imm12, rs2 : }, |
| resources: { next_pc, rs1, rs2 : }, |
| disasm: "sh", "%rs2, %S_imm12(%rs1)", |
| semfunc: "&KelvinIStore<uint16_t>"; |
| sb{: rs1, S_imm12, rs2 : }, |
| resources: { next_pc, rs1, rs2 : }, |
| disasm: "sb", "%rs2, %S_imm12(%rs1)", |
| semfunc: "&KelvinIStore<uint8_t>"; |
| fence{: I_imm12 : }, |
| disasm: "fence", |
| semfunc: "&mpact::sim::riscv::RiscVIFence"; |
| ecall{}, |
| disasm: "ecall", |
| semfunc: "&mpact::sim::riscv::RiscVIEcall"; |
| ebreak{}, |
| disasm: "ebreak", |
| semfunc: "&mpact::sim::riscv::RiscVIEbreak"; |
| } |
| } |
| |
| // RiscV32 multiply/divide instructions. |
| slot riscv32m { |
| includes { |
| #include "riscv/riscv_m_instructions.h" |
| } |
| default size = 4; |
| default latency = global_latency; |
| resources ThreeOp = { next_pc, rs1, rs2 : rd[..rd]}; |
| opcodes { |
| mul{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "mul", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MMul"; |
| mulh{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "mulh", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MMulh"; |
| mulhu{: rs1, rs2: rd}, |
| resources: ThreeOp, |
| disasm: "mulhu", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MMulhu"; |
| mulhsu{: rs1, rs2: rd}, |
| resources: ThreeOp, |
| disasm: "mulhsu", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MMulhsu"; |
| div{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "div", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MDiv"; |
| divu{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "divu", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MDivu"; |
| rem{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "rem", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MRem"; |
| remu{: rs1, rs2 : rd}, |
| resources: ThreeOp, |
| disasm: "remu", "%rd, %rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RV32::MRemu"; |
| } |
| } |
| |
| // RiscV32 CSR manipulation instructions. |
| slot zicsr { |
| includes { |
| #include "riscv/riscv_zicsr_instructions.h" |
| } |
| default size = 4; |
| default latency = global_latency; |
| opcodes { |
| csrrw{: rs1, csr : rd, csr}, |
| resources: { next_pc, rs1, csr : rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrw", |
| disasm: "csrw", "%rd, %csr, %rs1"; |
| csrrs{: rs1, csr : rd, csr}, |
| resources: { next_pc, rs1, csr : rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrs", |
| disasm: "csrs", "%rd, %csr, %rs1"; |
| csrrc{: rs1, csr : rd, csr}, |
| resources: { next_pc, rs1, csr : rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrc", |
| disasm: "csrc", "%rd, %csr, %rs1"; |
| csrrs_nr{: rs1, csr : rd, csr}, |
| resources: { next_pc, rs1, csr : rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrs", |
| disasm: "csrs", "%csr, %rs1"; |
| csrrc_nr{: rs1, csr : rd, csr}, |
| resources: { next_pc, rs1, csr : rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrc", |
| disasm: "csrc", "%csr, %rs1"; |
| csrrw_nr{: rs1, csr : csr}, |
| resources: { next_pc, rs1: csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrwNr", // rd == 0 (x0). |
| disasm: "csrw", "%csr, %rs1"; |
| csrrs_nw{: csr : rd}, |
| resources: { next_pc, csr: rd[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrNw", // rs1 == 0 (x0). |
| disasm: "csrs", "%rd, %csr"; |
| csrrc_nw{: csr : rd}, |
| resources: { next_pc, csr: rd[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrNw", // rs1 == 0 (x0). |
| disasm: "csrc", "%rd, %csr"; |
| csrrwi{: CSR_uimm5, csr : rd, csr}, |
| resources: { next_pc, csr: rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrw", |
| disasm: "csrwi", "%rd, %csr, %CSR_uimm5"; |
| csrrsi{: CSR_uimm5, csr : rd, csr}, |
| resources: { next_pc, csr: rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrs", |
| disasm: "csrsi", "%rd, %csr, %CSR_uimm5"; |
| csrrci{: CSR_uimm5, csr : rd, csr}, |
| resources: { next_pc, csr: rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrc", |
| disasm: "csrci", "%rd, %csr, %CSR_uimm5"; |
| csrrsi_nr{: CSR_uimm5, csr : rd, csr}, |
| resources: { next_pc, csr: rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrs", |
| disasm: "csrsi", "%csr, %CSR_uimm5"; |
| csrrci_nr{: CSR_uimm5, csr : rd, csr}, |
| resources: { next_pc, csr: rd[0..], csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrc", |
| disasm: "csrci", "%csr, %CSR_uimm5"; |
| csrrwi_nr{: CSR_uimm5, csr : csr}, |
| resources: { next_pc : csr[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrwNr", // rd == 0 (x0). |
| disasm: "csrrwi", "%csr, %CSR_uimm5"; |
| csrrsi_nw{: csr : rd}, |
| resources: { next_pc, csr : rd[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrNw", // uimm5 == 0. |
| disasm: "csrsi", "%rd, %csr, 0"; |
| csrrci_nw{: csr : rd}, |
| resources: { next_pc, csr : rd[0..]}, |
| semfunc: "&mpact::sim::riscv::RV32::RiscVZiCsrrNw", // uimm5 == 0. |
| disasm: "csrwi", "%rd, %csr, 0"; |
| } |
| } |
| |
| // Instruction fence. |
| slot zfencei { |
| includes { |
| #include "riscv/riscv_zfencei_instructions.h" |
| } |
| default size = 4; |
| default latency = global_latency; |
| opcodes { |
| fencei{: I_imm12 : }, |
| disasm: "fence.i", |
| semfunc: "&mpact::sim::riscv::RiscVZFencei"; |
| } |
| } |
| |
| // Privileged instructions. |
| slot privileged { |
| includes { |
| #include "riscv/riscv_priv_instructions.h" |
| #include "sim/kelvin_instructions.h" |
| } |
| default size = 4; |
| default latency = global_latency; |
| opcodes { |
| uret{: : next_pc}, |
| disasm: "uret", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVPrivURet"; |
| sret{: : next_pc}, |
| disasm: "sret", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVPrivSRet"; |
| mret{: : next_pc}, |
| disasm: "mret", |
| semfunc: "&mpact::sim::riscv::RV32::RiscVPrivMRet"; |
| wfi{}, |
| disasm: "wfi", |
| semfunc: "&mpact::sim::riscv::RiscVPrivWfi"; |
| mpause{}, |
| disasm: "mpause", |
| // mpause is the software breakpoint to terminate the program. |
| semfunc: "&KelvinIMpause"; |
| // The sfence instruction has 4 behaviors depending on if rs1 and/or rs2 |
| // are 0. These behaviors are split into 4 instructions. |
| sfence_vma_zz{: rs1, rs2}, |
| resources: {}, |
| disasm: "sfence.vma", "%rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RiscVPrivSFenceVmaZZ"; |
| sfence_vma_zn{: rs1, rs2}, |
| resources: {rs2}, |
| disasm: "sfence.vma", "%rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RiscVPrivSFenceVmaZN"; |
| sfence_vma_nz{: rs1, rs2}, |
| resources: { rs1 }, |
| disasm: "sfence.vma", "%rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RiscVPrivSFenceVmaNZ"; |
| sfence_vma_nn{: rs1, rs2}, |
| resources: {rs1, rs2}, |
| disasm: "sfence.vma", "%rs1, %rs2", |
| semfunc: "&mpact::sim::riscv::RiscVPrivSFenceVmaNN"; |
| // Skipping hypervisor memory management instructions for now. |
| } |
| } |
| |
| slot kelvin_log { |
| includes { |
| #include "sim/kelvin_instructions.h" |
| #include "absl/functional/bind_front.h" |
| } |
| default size = 4; |
| default latency = global_latency; |
| opcodes { |
| flog{: rs1 :}, |
| resources: { next_pc : rs1[0..]}, |
| disasm: "flog", "%rs1", |
| semfunc: "absl::bind_front(&KelvinLogInstruction, /*log_mode*/ 0)"; |
| slog{: rs1 :}, |
| resources: { next_pc : rs1[0..]}, |
| disasm: "slog", "%rs1", |
| semfunc: "absl::bind_front(&KelvinLogInstruction, /*log_mode*/ 1)"; |
| clog{: rs1 :}, |
| resources: { next_pc : rs1[0..]}, |
| disasm: "clog", "%rs1", |
| semfunc: "absl::bind_front(&KelvinLogInstruction, /*log_mode*/ 2)"; |
| klog{: rs1 :}, |
| resources: { next_pc : rs1[0..]}, |
| disasm: "klog", "%rs1", |
| semfunc: "absl::bind_front(&KelvinLogInstruction, /*log_mode*/ 3)"; |
| } |
| } |