blob: 280937146be055153b05c1252f71080b5b7194ea [file] [log] [blame]
// 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";
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";
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: "&mpact::sim::riscv::RV32::RiscVISw";
sh{: rs1, S_imm12, rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sh", "%rs2, %S_imm12(%rs1)",
semfunc: "&mpact::sim::riscv::RV32::RiscVISh";
sb{: rs1, S_imm12, rs2 : },
resources: { next_pc, rs1, rs2 : },
disasm: "sb", "%rs2, %S_imm12(%rs1)",
semfunc: "&mpact::sim::riscv::RV32::RiscVISb";
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)";
}
}