From c3ff7ea4aa718e7df0da47e74c26a0fbec0c528c Mon Sep 17 00:00:00 2001 From: Vinicius Silva <1046664@pucminas.br> Date: Wed, 10 Jul 2024 17:03:10 -0300 Subject: [PATCH] Cpu instructions, Os syscalls --- src/main.v | 2 - src/os/kernel.v | 50 +++++++-- src/os/os.v | 19 ++++ src/os/sh.v | 10 +- src/os/syscall.v | 16 +-- src/vm/assembler.v | 5 - src/vm/cpu.v | 255 ++++++++++++++++++++++++++++++++++++++++-- src/vm/instructions.v | 49 +++++--- src/vm/vm.v | 8 +- 9 files changed, 354 insertions(+), 60 deletions(-) create mode 100644 src/os/os.v diff --git a/src/main.v b/src/main.v index 579878c..556287f 100644 --- a/src/main.v +++ b/src/main.v @@ -3,8 +3,6 @@ module main import vm fn main() { - println('Hello World!') - vm.start_vm() } diff --git a/src/os/kernel.v b/src/os/kernel.v index ebb3f75..999e203 100644 --- a/src/os/kernel.v +++ b/src/os/kernel.v @@ -1,27 +1,53 @@ module main import vm +import readline +mut kernel := none -mut stdin := [1024]u8; -mut stdout := [1024]u8; - - -fn read(input [u8]) -{ - +fn start_kernel(){ + kernel = Kernel{} } -fn exit() { - exit(0) +fn kill(){ + kernel = none } -fn write(input [u8]) -{ +struct Kernel{ + pub mut: + stdin := []u8{}; + stdout := []u8{}; + + input_device := 'keyboard' + output_device := 'screen' } -fn request_control() + +fn (mut kernel Kernel) read() { + mut input := none + + match kernel.input_device { + 'keyboard' { + + mut r := readline.Readline{} + input = r.read_line('')! + } + } + + kernel.stdin = input.bytes() +} + +fn (mut kernel Kernel) exit() { exit(0) } + +fn (mut kernel Kernel) write() +{ + kernel.stdout = output + + match kernel.output_device { + + 'screen' { print(stdout.bytestr()) } + } } \ No newline at end of file diff --git a/src/os/os.v b/src/os/os.v new file mode 100644 index 0000000..e3acc43 --- /dev/null +++ b/src/os/os.v @@ -0,0 +1,19 @@ + +module main + +import sh +import kernel + +os_usermode := '__user__' +os_kernelmode := '__kernel__' + +fn boot(){ + kernel.start_kernel() + start_up() +} + +fn shutdown() { kernel.kill() } + +fn start_up(){ + for { sh.sh() } +} \ No newline at end of file diff --git a/src/os/sh.v b/src/os/sh.v index 4f9cd72..bf00109 100644 --- a/src/os/sh.v +++ b/src/os/sh.v @@ -2,13 +2,7 @@ module main import readline { read_line } -import kernel - -cmds := { - 'EXIT' : 0 - 'READ' : 1 - 'WRITE' : 2 -} +import syscall fn sh(){ @@ -16,6 +10,6 @@ fn sh(){ mut read_line := readline.Readline{} cmd := read_line()! - sys_code := cmds[cmd] or { panic('Command not found:\n')} + sys_code := syscall[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 index 5078adb..a9b3f0d 100644 --- a/src/os/syscall.v +++ b/src/os/syscall.v @@ -1,17 +1,17 @@ module main -import kernel +import kernel as os -enum syscalls { - EXIT, - READ, - WRITE +cmds := { + 'EXIT' : 0 + 'READ' : 1 + 'WRITE' : 2 } fn do_syscall(sys_code int) { match sys_code : - 0 { kernel.exit() } - 1 { kernel.read() } - 2 { kernel.write() } + 0 { os.kernel.exit() } + 1 { os.kernel.read() } + 2 { os.kernel.write() } } \ No newline at end of file diff --git a/src/vm/assembler.v b/src/vm/assembler.v index 4720ba4..5bee172 100644 --- a/src/vm/assembler.v +++ b/src/vm/assembler.v @@ -1,8 +1,3 @@ - - - - - fn start_assembler() { diff --git a/src/vm/cpu.v b/src/vm/cpu.v index ee9cefc..8216ba8 100644 --- a/src/vm/cpu.v +++ b/src/vm/cpu.v @@ -2,6 +2,7 @@ module main import vm +import instruction struct Alu{ pub mut: @@ -29,26 +30,33 @@ struct CPU{ num_of_registers := 32 pub mut: - pc u32 + pc u32 := 0 + ic u32 := 0 registers[num_of_registers]u8 alu Alu - cpu_control = none + 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() { - cpu.pc := 0 - - while(true) + for { - u32 instruction := cpu.fetch() - cpu.decode(instruction) - cpu.run() + if cpu.ic != 0 { + u32 instruction := cpu.fetch() + cpu.decode(instruction) + cpu.run() + } } } -fn (cpu CPU) fetch() +fn (cpu CPU) fetch() u32 { u32 instruction := vm.RAM[cpu.pc]; cpu.pc += 4 @@ -58,10 +66,237 @@ fn (cpu CPU) fetch() fn (cpu CPU) decode(u32 instruction) { + mut opcode := (instruction & 0x7F) + + match opcode { + + 0x33 { + + mut funct3 := (instruction & 0x7000) >> 12 + mut rd := (instruction & 0x7000) >> 12 + 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-- + } } \ No newline at end of file diff --git a/src/vm/instructions.v b/src/vm/instructions.v index 40e5e99..f3e8097 100644 --- a/src/vm/instructions.v +++ b/src/vm/instructions.v @@ -1,38 +1,59 @@ module main import vm.hardware as vm +import os struct J{ pub mut: - rd i8 - imm u32 + opcode u8; + rd u8; + imm u32; } struct R{ pub mut: - rd u8; - rs1 u8; - rs2 u8; + opcode u8; + funct7 u8; + funct3 u8; + rd u8; + rs1 u8; + rs2 u8; } struct I{ pub mut: - rd u8; - rs1 u8; - imm u16; + opcode u8; + funct3 u8; + rd u8; + rs1 u8; + imm u16; } struct U{ pub mut: - rd u8; - imm u32; + opcode u8; + rd u8; + imm u32; +} + +struct S{ + pub mut: + opcode u8; + funct3 u8; + rs1 u8; + rs2 u8; + imm2 u8; + imm1 u8; } struct B{ pub mut: - rs1 u8; - rs2 u8; - imm u16; + opcode u8; + funct3 u8; + rs1 u8; + rs2 u8; + imm1 u8; + imm2 u8; } struct Instruction{ @@ -208,7 +229,7 @@ fn (inst Instruction) auipc() { } fn (inst Instruction) ecall() { - vm.cpu.cpu_control = 'kernel' + vm.cpu.cpu_control = '__kernel__' } fn (inst Instruction) addi() { diff --git a/src/vm/vm.v b/src/vm/vm.v index 886e7a9..67be9d6 100644 --- a/src/vm/vm.v +++ b/src/vm/vm.v @@ -39,8 +39,14 @@ fn start_assembler() 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() + + mut threads := []thread{} + + threads << spawn cpu.start_cpu() + threads << spawn os.boot() } \ No newline at end of file