From 95b2be3ab733bab9c95e71e45ffcfcdc73d6995f Mon Sep 17 00:00:00 2001 From: xwashere Date: Fri, 29 Dec 2023 16:59:32 -0500 Subject: [PATCH] memory instructions --- board/parts/hart.sv | 64 ++++++++++++++++++++++++++++++++++++++++++--- board/parts/pmmu.sv | 38 ++++++++++++++++++++++----- board/parts/ram.sv | 25 ++++++++++++++++++ board/system.sv | 10 +++++-- makefile | 3 ++- os/kernel/boot.s | 33 +++++++++++++++-------- 6 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 board/parts/ram.sv diff --git a/board/parts/hart.sv b/board/parts/hart.sv index 33afb65..ccf1477 100644 --- a/board/parts/hart.sv +++ b/board/parts/hart.sv @@ -85,6 +85,7 @@ module hart( reg [31:0] t_e_result; reg t_e_branch; reg [31:0] t_e_address; + reg [31:0] t_e_tmp1; always begin // instruction fetch @@ -203,8 +204,57 @@ module hart( t_e_branch = 1; end end - { `INS_LOAD, `F3_DONT_CARE, `F7_DONT_CARE }: $error("NOT IMPLEMENTED"); - { `INS_STORE, `F3_DONT_CARE, `F7_DONT_CARE }: $error("NOT IMPLEMENTED"); + { `INS_LOAD, `F3_DONT_CARE, `F7_DONT_CARE }: begin + t_e_address = t_d_imm + t_r_a; + pmmu_addr = t_e_address; + pmmu_rd = 1; + + #1; + pmmu_rd = 0; + case (t_d_f3[1:0]) + 0: t_e_result = (pmmu_datar >> (8 * (t_e_address & 3))) & 255; + 1: begin + if (t_e_address[0] != 0) $error("UNALIGNED READ %08x", t_e_address); + t_e_result = (pmmu_datar >> (8 * (t_e_address & 2))) & 'hffff; + end + 2: begin + if (t_e_address[1:0] != 0) $error("UNALIGNED READ %08x", t_e_address); + t_e_result = pmmu_datar; + end + 3: $error("INVALID INSTRUCTION"); + endcase + + case (t_d_f3) + 1,2,3,4:; + 4: t_e_result = { {24{t_e_result[7]}}, t_e_result[7:0] }; + 5: t_e_result = { {16{t_e_result[16]}}, t_e_result[15:0] }; + 6, 7: $error("INVALID INSTRUCTION"); + endcase + end + { `INS_STORE, `F3_DONT_CARE, `F7_DONT_CARE }: begin + t_e_address = t_d_imm + t_r_a; + pmmu_addr = t_e_address; + pmmu_rd = 1; + + #1; + case (t_d_f3) + 0: begin + pmmu_dataw = pmmu_datar & ~('hff << (8 * t_e_address[1:0])) | (t_r_b & 'hff) << (8 * t_e_address[1:0]); + end + 1: begin + if (t_e_address[0] != 0) $error("UNALIGNED STORE %08x", t_e_address); + pmmu_dataw = pmmu_datar & ~('hffff << (8 * t_e_address[1:0])) | (t_r_b & 'hffff) << (8 * t_e_address[1:0]); + end + 2: begin + if (t_e_address[1:0] != 0) $error("UNALIGNED STORE %08x", t_e_address); + pmmu_dataw = t_r_b; + end + 3, 4, 5, 6, 7: $error("INVALID INSTRUCTION"); + endcase + + pmmu_wr = 1; + pmmu_rd = 0; + end { `INS_IMMOP, `INS_ALUOP_ADD, `F7_DONT_CARE }: begin t_e_result = $signed(t_r_a) + $signed(t_d_imm); end @@ -267,8 +317,8 @@ module hart( default: $error("INVALID INSTRUCTION"); endcase - // write back - @(posedge clk); + // write back (ignore the delay, its not important) + @(posedge clk); #1; $display("== WRITE REGISTERS =="); case (t_d_op) @@ -280,5 +330,11 @@ module hart( // finish up reg_pc = t_e_branch ? t_e_address : reg_pc + 4; + + // shhhh... you dont see this... + pmmu_rd = 0; + pmmu_wr = 0; + pmmu_addr = 0; + pmmu_dataw = 0; end endmodule \ No newline at end of file diff --git a/board/parts/pmmu.sv b/board/parts/pmmu.sv index 14378ca..3ea5cac 100644 --- a/board/parts/pmmu.sv +++ b/board/parts/pmmu.sv @@ -5,7 +5,10 @@ module pmmu( addr, datar, dataw, rom_rd, - rom_addr, rom_datar + rom_addr, rom_datar, + + ram_rd, ram_wr, + ram_addr, ram_datar, ram_dataw ); // INPUT SHIT input clk; @@ -20,16 +23,39 @@ module pmmu( output reg [31:0] rom_addr; input reg [31:0] rom_datar; + // RAM + output reg ram_rd; + output reg ram_wr; + output reg [31:0] ram_addr; + output reg [31:0] ram_dataw; + input reg [31:0] ram_datar; + always @(posedge clk) begin rom_rd = 0; + ram_rd = 0; + ram_wr = 0; - if ((addr == 0 || addr > 0) && addr < 'h100) begin - rom_addr = addr >> 2; - rom_rd = rd; - #1; // wait for it to finish + if ((addr == 0 || addr > 0) && addr < 'h1000) begin + rom_addr = addr >> 2; + rom_rd = rd; + + #1; if (rd) datar = rom_datar; + + rom_rd = 0; + end else if ((addr == 'h100000 || addr > 'h100000) && addr < 'h101000) begin + ram_addr = addr >> 2; + ram_rd = rd; + ram_wr = wr; + if (wr) ram_dataw = dataw; + + #1; + if (rd) datar = ram_datar; + + ram_wr = 0; + ram_rd = 0; end else begin - $error("THIS IS BAD"); + $error("INVALID MEMORY ACCESS %08x", addr); end end endmodule \ No newline at end of file diff --git a/board/parts/ram.sv b/board/parts/ram.sv new file mode 100644 index 0000000..aa962bb --- /dev/null +++ b/board/parts/ram.sv @@ -0,0 +1,25 @@ +module ram( + input clk, + input reg rd, + input reg wr, + input reg[31:0] addr, + output reg[31:0] datar, + input reg[31:0] dataw +); + parameter SIZE = 'h1000; + + reg [31:0] data[0 : SIZE - 1]; + + always @(posedge clk) begin + // $display("RAM: %c%c", wr ? "W" : "-", rd ? "R" : "-"); + + if (wr) begin + $display("RAM: [%08x] <= %d", addr << 2, dataw); + data[addr] = dataw; + end + if (rd) begin + $display("RAM: [%08x] => %d", addr << 2, data[addr]); + datar = data[addr]; + end else datar = 0; + end +endmodule \ No newline at end of file diff --git a/board/system.sv b/board/system.sv index 2bd7d08..ef42d18 100644 --- a/board/system.sv +++ b/board/system.sv @@ -1,6 +1,7 @@ `include "parts/hart.sv"; `include "parts/pmmu.sv"; `include "parts/rom.sv"; +`include "parts/ram.sv"; module system(); reg clock = 0; // its the clock @@ -13,12 +14,17 @@ module system(); reg wire_rom_rd; reg [31:0] wire_rom_addr; reg [31:0] wire_rom_datar; - + reg wire_ram_rd; + reg wire_ram_wr; + reg [31:0] wire_ram_addr; + reg [31:0] wire_ram_datar; + reg [31:0] wire_ram_dataw; hart core(clock, wire_rd, wire_wr, wire_addr, wire_datar, wire_dataw); // cpu thing rom#(.FILE("./build/kernel.mem")) rom(clock, wire_rom_rd, wire_rom_addr, wire_rom_datar); - pmmu pmmu(clock, wire_rd, wire_wr, wire_addr, wire_datar, wire_dataw, wire_rom_rd, wire_rom_addr, wire_rom_datar); + ram#(.SIZE('h1000)) ram(clock, wire_ram_rd, wire_ram_wr, wire_ram_addr, wire_ram_datar, wire_ram_dataw); + pmmu pmmu(clock, wire_rd, wire_wr, wire_addr, wire_datar, wire_dataw, wire_rom_rd, wire_rom_addr, wire_rom_datar, wire_ram_rd, wire_ram_wr, wire_ram_addr, wire_ram_datar, wire_ram_dataw); // run the clock always #5 clock = ~clock; diff --git a/makefile b/makefile index e3a93ab..09944ec 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,8 @@ VERILOG_SOURCES = \ board/system.sv \ board/parts/hart.sv \ board/parts/pmmu.sv \ - board/parts/rom.sv + board/parts/rom.sv \ + board/parts/ram.sv KERNEL_SOURCES = \ os/kernel/boot.s diff --git a/os/kernel/boot.s b/os/kernel/boot.s index 450e8b7..55a96c3 100644 --- a/os/kernel/boot.s +++ b/os/kernel/boot.s @@ -1,12 +1,23 @@ _start: - li x1, 0 - li x2, 1 - li x3, 0 - li x4, 0 - li x5, 32 -fib: - add x3, x1, x2 - mv x1, x2 - mv x2, x3 - add x4, x4, 1 - bne x4, x5, fib \ No newline at end of file + li x1, 8 // ITERATION * 4 + li x2, 5 * 4 // MAX ITERATIONS * 4 + li x6, 0x100000 // MEM OFFSET + + li x5, 1 + sw x5, 4(x6) +fib: + add x3, x6, x1 + lw x4, -4(x3) // get a + lw x5, -8(x3) // get b + add x4, x4, x5 // a = a + b + sw x4, (x3) // store a to c + + // increment or stop + add x1, x1, 4 + bne x1, x2, fib + + li x5, 12345678 + sw x5, (x6) + li x5, 0 + lw x5, (x6) + mv x6, x5 \ No newline at end of file