riscv_emulator/src/vm/cpu.v

302 lines
6.5 KiB
V

module main
import vm
import instruction
struct Alu{
pub mut:
a u8
b u8
s u8
}
fn (alu Alu) sum() { alu.s = alu.a + alu.b; }
fn (alu Alu) sub() { alu.s = alu.a - alu.b; }
fn (alu Alu) mul() { alu.s = alu.a * alu.b; }
fn (alu Alu) div() { alu.s = alu.a / alu.b; }
fn (alu Alu) or() { alu.s = alu.a | alu.b }
fn (alu Alu) and() { alu.s = alu.a & alu.b }
fn (alu Alu) xor() { alu.s = alu.a ^ alu.b }
fn (alu Alu) sll() { alu.s = alu.a << alu.b }
fn (alu Alu) sra() { alu.s = alu.a >> alu.b }
fn (alu Alu) slt() { alu.s = alu.a < alu.b ? 1 : 0}
fn (alu Alu) slt() { alu.s = alu.a > alu.b ? 1 : 0}
fn (alu Alu) beq() { alu.s = alu.a == alu.b ? 1 : 0}
struct CPU{
pub:
num_of_registers := 32
pub mut:
pc u32 := 0
ic u32 := 0
registers[num_of_registers]u8
alu Alu
cpu_control := none
current_instruction := Instruction{
fmt_r: R{},
fmt_i: I{},
fmt_b: B{},
fmt_u: U{},
fmt_j: J{},
}
}
fn (cpu CPU) start_cpu()
{
for
{
if cpu.ic != 0 {
u32 instruction := cpu.fetch()
cpu.decode(instruction)
cpu.run()
}
}
}
fn (cpu CPU) fetch() u32
{
u32 instruction := vm.RAM[cpu.pc];
cpu.pc += 4
return instruction
}
fn (cpu CPU) decode(u32 instruction)
{
mut opcode := (instruction & 0x7F)
match opcode {
0x33 {
mut funct3 := (instruction & 0xA80) >> 7
mut rd :=
mut rs1 :=
mut rs2 :=
mut funct7 :=
cpu.current_instruction.fmt_r.opcode := opcode
cpu.current_instruction.fmt_r.funct3 := funct3
cpu.current_instruction.fmt_r.funct7 := funct7
cpu.current_instruction.fmt_r.rs1 := rs1
cpu.current_instruction.fmt_r.rs2 := rs2
cpu.current_instruction.fmt_r.rd := rd
cpu.current_instruction.fmt_i = none
cpu.current_instruction.fmt_j = none
cpu.current_instruction.fmt_s = none
cpu.current_instruction.fmt_b = none
cpu.current_instruction.fmt_u = none
}
0x13, 0x03, 0x37, 0x73 {
// I
mut funct3 := (instruction & 0x7000) >> 12
opcode u8;
funct3 u8;
rd u8;
rs1 u8;
imm u16;
cpu.current_instruction.fmt_i.opcode := opcode
cpu.current_instruction.fmt_i.funct3 := funct3
cpu.current_instruction.fmt_i.imm := imm
cpu.current_instruction.fmt_i.rs1 := rs1
cpu.current_instruction.fmt_i.rs2 := rs2
cpu.current_instruction.fmt_i.rd := rd
cpu.current_instruction.fmt_r = none
cpu.current_instruction.fmt_j = none
cpu.current_instruction.fmt_s = none
cpu.current_instruction.fmt_b = none
cpu.current_instruction.fmt_u = none
}
0x23 {
// S
opcode u8;
funct3 u8;
rs1 u8;
rs2 u8;
imm2 u8;
imm1 u8;
cpu.current_instruction.fmt_s.opcode := opcode
cpu.current_instruction.fmt_s.funct3 := funct3
cpu.current_instruction.fmt_s.imm2 := imm2
cpu.current_instruction.fmt_s.imm1 := imm1
cpu.current_instruction.fmt_s.rs1 := rs1
cpu.current_instruction.fmt_s.rs2 := rs2
cpu.current_instruction.fmt_r = none
cpu.current_instruction.fmt_j = none
cpu.current_instruction.fmt_i = none
cpu.current_instruction.fmt_b = none
cpu.current_instruction.fmt_u = none
}
0x63 {
// B
opcode u8;
funct3 u8;
rs1 u8;
rs2 u8;
imm1 u8;
imm2 u8;
cpu.current_instruction.fmt_b.opcode := opcode
cpu.current_instruction.fmt_b.funct3 := funct3
cpu.current_instruction.fmt_b.imm2 := imm2
cpu.current_instruction.fmt_b.imm1 := imm1
cpu.current_instruction.fmt_b.rs1 := rs1
cpu.current_instruction.fmt_b.rs2 := rs2
cpu.current_instruction.fmt_r = none
cpu.current_instruction.fmt_j = none
cpu.current_instruction.fmt_s = none
cpu.current_instruction.fmt_i = none
cpu.current_instruction.fmt_u = none
}
0x6F {
// J
opcode u8;
rd u8;
imm u32;
cpu.current_instruction.fmt_j.opcode := opcode
cpu.current_instruction.fmt_j.imm := imm
cpu.current_instruction.fmt_j.rd := rd
cpu.current_instruction.fmt_r = none
cpu.current_instruction.fmt_i = none
cpu.current_instruction.fmt_s = none
cpu.current_instruction.fmt_b = none
cpu.current_instruction.fmt_u = none
}
0x17 {
// U
opcode u8;
rd u8;
imm u32;
cpu.current_instruction.fmt_u.opcode := opcode
cpu.current_instruction.fmt_u.rd := rd
cpu.current_instruction.fmt_u.imm := imm
cpu.current_instruction.fmt_r = none
cpu.current_instruction.fmt_j = none
cpu.current_instruction.fmt_s = none
cpu.current_instruction.fmt_b = none
cpu.current_instruction.fmt_i = none
}
}
}
fn (cpu CPU) run(u32 instruction)
{
if cpu.current_instruction.fmt_j != none {
// inserir elementos
cpu.jal()
}else if cpu.current_instruction.fmt_r != none {
match cpu.current_instruction.funct3 {
0x0 {
match cpu.current_instruction.funct7 {
0x00 { cpu.current_instruction.add() }
0x20 { cpu.current_instruction.sub() }
}
}
0x4 { cpu.current_instruction.xor() }
0x6 { cpu.current_instruction._or() }
0x7 { cpu.current_instruction.and() }
0x1 { cpu.current_instruction.sll() }
0x5 {
match cpu.current_instruction.funct7 {
0x00 { cpu.current_instruction.srl() }
0x20 { cpu.current_instruction.sra() }
}
}
0x2 { cpu.current_instruction.slt() }
0x3 { cpu.current_instruction.sltu() }
}
}else if cpu.current_instruction.fmt_s != none {
match cpu.current_instruction.funct3 {
0x0 { cpu.current_instruction.sb() }
0x1 { cpu.current_instruction.sh() }
0x2 { cpu.current_instruction.sw() }
}
}else if cpu.current_instruction.fmt_b != none {
match cpu.current_instruction.funct3 {
0x0 { cpu.current_instruction.beq() }
0x1 { cpu.current_instruction.bne() }
0x4 { cpu.current_instruction.blt() }
0x5 { cpu.current_instruction.bge() }
0x6 { cpu.current_instruction.bltu() }
0x7 { cpu.current_instruction.bgeu() }
}
}else if chip.current_instruction.fmt_i != none {
match cpu.current_instruction.opcode {
0x13 {
match cpu.current_instruction.funct3 {
0x0 { cpu.current_instruction.addi() }
0x4 { cpu.current_instruction.xori() }
0x6 { cpu.current_instruction.ori() }
0x7 { cpu.current_instruction.andi() }
0x1 { cpu.current_instruction.slli() }
0x5 {
cpu.current_instruction.srli()
cpu.current_instruction.srai()
}
0x2 { cpu.current_instruction.slti() }
0x3 { cpu.current_instruction.sltiu() }
}
}
0x73 {
match cpu.current_instruction.imm {
0x0 { cpu.current_instruction.ecall() }
0x1 { cpu.current_instruction.ebreak() }
}
}
}
chip.ic--
}
}