From 1267567eb6c1c093e919fe50ff1543aec702271b Mon Sep 17 00:00:00 2001 From: Vinicius Silva <1046664@pucminas.br> Date: Tue, 9 Jul 2024 19:55:33 -0300 Subject: [PATCH] Initial commit --- src/main.v | 10 ++ src/os/kernel.v | 27 ++++ src/os/sh.v | 21 ++++ src/os/syscall.v | 17 +++ src/vm/assembler.v | 9 ++ src/vm/cpu.v | 67 ++++++++++ src/vm/instructions.v | 287 ++++++++++++++++++++++++++++++++++++++++++ src/vm/vm.v | 46 +++++++ v.mod | 7 ++ vchip8 | 1 + 10 files changed, 492 insertions(+) create mode 100644 src/main.v create mode 100644 src/os/kernel.v create mode 100644 src/os/sh.v create mode 100644 src/os/syscall.v create mode 100644 src/vm/assembler.v create mode 100644 src/vm/cpu.v create mode 100644 src/vm/instructions.v create mode 100644 src/vm/vm.v create mode 100644 v.mod create mode 160000 vchip8 diff --git a/src/main.v b/src/main.v new file mode 100644 index 0000000..579878c --- /dev/null +++ b/src/main.v @@ -0,0 +1,10 @@ +module main + +import vm + +fn main() { + println('Hello World!') + + vm.start_vm() +} + diff --git a/src/os/kernel.v b/src/os/kernel.v new file mode 100644 index 0000000..ebb3f75 --- /dev/null +++ b/src/os/kernel.v @@ -0,0 +1,27 @@ +module main + +import vm + + +mut stdin := [1024]u8; +mut stdout := [1024]u8; + + +fn read(input [u8]) +{ + +} + +fn exit() { + exit(0) +} + +fn write(input [u8]) +{ + +} + +fn request_control() +{ + +} \ No newline at end of file diff --git a/src/os/sh.v b/src/os/sh.v new file mode 100644 index 0000000..4f9cd72 --- /dev/null +++ b/src/os/sh.v @@ -0,0 +1,21 @@ +module main + +import readline { read_line } + +import kernel + +cmds := { + 'EXIT' : 0 + 'READ' : 1 + 'WRITE' : 2 +} + +fn sh(){ + + print("# ") + mut read_line := readline.Readline{} + cmd := read_line()! + + sys_code := cmds[cmd] or { panic('Command not found:\n')} + kernel.do_syscall(sys_code) +} \ No newline at end of file diff --git a/src/os/syscall.v b/src/os/syscall.v new file mode 100644 index 0000000..5078adb --- /dev/null +++ b/src/os/syscall.v @@ -0,0 +1,17 @@ +module main + +import kernel + +enum syscalls { + EXIT, + READ, + WRITE +} + +fn do_syscall(sys_code int) +{ + match sys_code : + 0 { kernel.exit() } + 1 { kernel.read() } + 2 { kernel.write() } +} \ No newline at end of file diff --git a/src/vm/assembler.v b/src/vm/assembler.v new file mode 100644 index 0000000..4720ba4 --- /dev/null +++ b/src/vm/assembler.v @@ -0,0 +1,9 @@ + + + + + +fn start_assembler() +{ + +} \ No newline at end of file diff --git a/src/vm/cpu.v b/src/vm/cpu.v new file mode 100644 index 0000000..ee9cefc --- /dev/null +++ b/src/vm/cpu.v @@ -0,0 +1,67 @@ + +module main + +import vm + +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 + registers[num_of_registers]u8 + alu Alu + cpu_control = none +} + + +fn (cpu CPU) start_cpu() +{ + cpu.pc := 0 + + while(true) + { + u32 instruction := cpu.fetch() + cpu.decode(instruction) + cpu.run() + } +} + +fn (cpu CPU) fetch() +{ + u32 instruction := vm.RAM[cpu.pc]; + cpu.pc += 4 + + return instruction +} + +fn (cpu CPU) decode(u32 instruction) +{ + +} + +fn (cpu CPU) run(u32 instruction) +{ + +} \ No newline at end of file diff --git a/src/vm/instructions.v b/src/vm/instructions.v new file mode 100644 index 0000000..40e5e99 --- /dev/null +++ b/src/vm/instructions.v @@ -0,0 +1,287 @@ +module main + +import vm.hardware as vm + +struct J{ + pub mut: + rd i8 + imm u32 +} + +struct R{ + pub mut: + rd u8; + rs1 u8; + rs2 u8; +} + +struct I{ + pub mut: + rd u8; + rs1 u8; + imm u16; +} + +struct U{ + pub mut: + rd u8; + imm u32; +} + +struct B{ + pub mut: + rs1 u8; + rs2 u8; + imm u16; +} + +struct Instruction{ + pub mut: + fmt_r R + fmt_i I + fmt_b B + fmt_u U +} + +fn (inst Instruction) add() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.sum(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) sub() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.sub(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) xor() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.xor(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) _or () { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu._or(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) and() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.and(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) sll() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.sll(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) sra() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.sra(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) slt() { + + mut rd := inst.fmt_r.rd + mut rs1 := inst.fmt_r.rs1 + mut rs2 := inst.fmt_r.rs2 + + vm.cpu.registers[rd] = vm.cpu.alu.slt(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) +} + +fn (inst Instruction) sltu() { inst.slt() } + +fn (inst Instruction) lw() { + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.RAM[vm.cpu.slu.sum(vm.cpu.registers[rs1], imm)] +} + +fn (inst Instruction) beq() { + mut rs1 := inst.fmt_b.rs1 + mut rs2 := inst.fmt_b.rs2 + mut imm := inst.fmt_b.imm + + vm.cpu.alu.beq(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) + + if vm.cpu.alu.s == 1 { vm.cpu.pc += imm } +} + +fn (inst Instruction) bne() { + + mut rs1 := inst.fmt_b.rs1 + mut rs2 := inst.fmt_b.rs2 + mut imm := inst.fmt_b.imm + + vm.cpu.alu.beq(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) + + if vm.cpu.alu.s == 0 { vm.cpu.pc += imm } +} + +fn (inst Instruction) blt() { + + mut rs1 := inst.fmt_b.rs1 + mut rs2 := inst.fmt_b.rs2 + mut imm := inst.fmt_b.imm + + vm.cpu.alu.slt(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) + + if vm.cpu.alu.s == 1 { vm.cpu.pc += imm } +} + +fn (inst Instruction) bge() { + + mut rs1 := inst.fmt_b.rs1 + mut rs2 := inst.fmt_b.rs2 + mut imm := inst.fmt_b.imm + + vm.cpu.alu.beq(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) + if vm.cpu.alu.s == 1 { vm.cpu.pc += imm } + + vm.cpu.alu.slt(vm.cpu.registers[rs1], vm.cpu.registers[rs2]) + if vm.cpu.alu.s == 1 { vm.cpu.pc += imm } +} + +fn (inst Instruction) bltu() { inst.blt() } + +fn (inst Instruction) bgeu() { inst.bgeu() } + +fn (inst Instruction) jal() { + mut rd := inst.fmt_j.rd + mut imm := inst.fmt_j.imm + + vm.cpu.registers[rd] = vm.cpu.pc + 4 + vm.cpu.pc += imm +} + +fn (inst Instruction) jalr() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.pc + 4 + vm.cpu.pc = vm.cpu.registers[rs1] + imm +} + +fn (inst Instruction) lui() { + + mut rd := inst.fmt_u.rd + mut imm := inst.fmt_u.imm + + vm.cpu.registers[rd] = vm.cpu.alu.sll(imm, 12) +} + +fn (inst Instruction) auipc() { + mut rd := inst.fmt_u.rd + mut imm := inst.fmt_u.imm + + vm.cpu.registers[rd] = vm.cpu.pc + vm.cpu.alu.sll(imm, 12) +} + +fn (inst Instruction) ecall() { + vm.cpu.cpu_control = 'kernel' +} + +fn (inst Instruction) addi() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.addi(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) subi() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.subi(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) xori() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.xori(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) ori () { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.ori(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) andi() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.andi(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) slli() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.slli(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) srai() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.srai(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) slti() { + + mut rd := inst.fmt_i.rd + mut rs1 := inst.fmt_i.rs1 + mut imm := inst.fmt_i.imm + + vm.cpu.registers[rd] = vm.cpu.alu.slti(vm.cpu.registers[rs1], imm) +} + +fn (inst Instruction) sltiu() { inst.slti() } + diff --git a/src/vm/vm.v b/src/vm/vm.v new file mode 100644 index 0000000..886e7a9 --- /dev/null +++ b/src/vm/vm.v @@ -0,0 +1,46 @@ +module main + +import cpu + + +mut hardware := Hardware{ram: RAM{}, cpu: Cpu{}} + +struct Hardware +{ + pub mut: + ram RAM; + cpu cpu.CPU; +} + + +struct RAM +{ + pub: + mem_size_in_mb := 100 + + pub mut: + memory[mem_size_in_mb]u32 + current_memory_addess u32 +} + + + +fn load_instructions(asm_instructions[string]) +{ + for mut instruction in asm_instructions { + + } +} + +fn start_assembler() +{ + mut instructions := {"ADD s0, s1, s2", "ADDI s0, s1, s2", "MUL s2, s3, s3"} +} + +fn start_vm() +{ + // Load asm instructions, converts to machine instructions and save in memory + start_assembler() + // Get in memory, decode and run instructions + cpu.start_cpu() +} \ No newline at end of file diff --git a/v.mod b/v.mod new file mode 100644 index 0000000..4f8c875 --- /dev/null +++ b/v.mod @@ -0,0 +1,7 @@ +Module { + name: 'riscv_vm' + description: 'Virtual Machine for RISCV CPU' + version: '0.0.0' + license: 'MIT' + dependencies: [] +} diff --git a/vchip8 b/vchip8 new file mode 160000 index 0000000..f3d3310 --- /dev/null +++ b/vchip8 @@ -0,0 +1 @@ +Subproject commit f3d331096556256d477b129cb199d193795ae35f