From e569965556aa171e592a77bd441ef1cc0576663d Mon Sep 17 00:00:00 2001 From: Qiu Jiahao Date: Sat, 16 Jul 2022 08:44:29 +0800 Subject: [PATCH] refactor MU Co-authored-by: Paul Co-authored-by: cxy004 --- src/CP0/CP0.sv | 10 +- src/Core/Datapath.sv | 4 +- src/Gadgets/addr_virt_to_phy.sv | 44 ++++++++ src/Gadgets/bram.sv | 10 +- src/MU/AXI.sv | 11 +- src/MU/DCache.sv | 67 ++++++------ src/MU/ICache.sv | 36 +++---- src/MU/MU.sv | 175 ++++++++++++++++++++++---------- src/MU/TLB.sv | 55 +++++----- src/MU/interface.sv | 155 ++++++++++++++++++++++------ src/include/defines.svh | 14 ++- src/mycpu_top.sv | 26 ++--- 12 files changed, 406 insertions(+), 201 deletions(-) create mode 100644 src/Gadgets/addr_virt_to_phy.sv diff --git a/src/CP0/CP0.sv b/src/CP0/CP0.sv index b1a3e82..01798fc 100644 --- a/src/CP0/CP0.sv +++ b/src/CP0/CP0.sv @@ -126,6 +126,8 @@ module CP0 ( count_lo = ~count_lo; if (count_lo == 1) rf_cp0.Count = rf_cp0.Count + 1; + rf_cp0.Random.Random = &rf_cp0.Random.Random ? rf_cp0.Wired.Wired + : rf_cp0.Random.Random + 1'b1; if (en) begin case (addr) // 31: rf_cp0.DESAVE = wdata; @@ -166,7 +168,10 @@ module CP0 ( 9: rf_cp0.Count = wdata; 8: rf_cp0.BadVAddr = wdata; // 7: rf_cp0.HWREna = wdata; - 6: rf_cp0.Wired.Wired = wdata[2:0]; + 6: begin + rf_cp0.Wired.Wired = wdata[2:0]; + rf_cp0.Random.Random = 3'b111; + end // 5: rf_cp0.PageMask.Mask = wdata[24:13]; // 4: rf_cp0.Context = wdata; 3: begin @@ -213,9 +218,6 @@ module CP0 ( rf_cp0.Index.Index = tlb_Index.Index; end - rf_cp0.Random.Random = &rf_cp0.Random.Random ? rf_cp0.Wired.Wired - : rf_cp0.Random.Random + 1'b1; - if (rf_cp0.Count == rf_cp0.Compare) rf_cp0.Cause.TI = 1; if (exception.ERET) rf_cp0.Status.EXL = 1'b0; diff --git a/src/Core/Datapath.sv b/src/Core/Datapath.sv index 8a8f02f..7049344 100644 --- a/src/Core/Datapath.sv +++ b/src/Core/Datapath.sv @@ -9,7 +9,7 @@ module Datapath ( // MMU InstFetch_i.cpu fetch, Memory_i.cpu mem, - output CacheOp_t cache_op, + CacheOp_i.cpu cache_op, input logic iTLBRefill, input logic iTLBInvalid, input logic iAddressError, @@ -1133,7 +1133,7 @@ module Datapath ( assign M.I1.REFILL = M_I1_PrevREFILL | dTLBRefillB; assign M.I1.ExcCode = M_I1_PrevExcValid ? M_I1_PrevExcCode : M_I1_Trap ? `EXCCODE_TR - : dAddressErrorB ? M.I1.MCtrl.MWR ? `EXCCODE_ADES : `EXCCODE_ADES + : dAddressErrorB ? M.I1.MCtrl.MWR ? `EXCCODE_ADES : `EXCCODE_ADEL : dTLBRefillB ? M.I1.MCtrl.MWR ? `EXCCODE_TLBS : `EXCCODE_TLBL : dTLBInvalidB ? M.I1.MCtrl.MWR ? `EXCCODE_TLBS : `EXCCODE_TLBL : `EXCCODE_MOD; diff --git a/src/Gadgets/addr_virt_to_phy.sv b/src/Gadgets/addr_virt_to_phy.sv new file mode 100644 index 0000000..498733c --- /dev/null +++ b/src/Gadgets/addr_virt_to_phy.sv @@ -0,0 +1,44 @@ +module addr_virt_to_phy ( + input word_t virt_addr, + input logic [19:0] tlb_addr, + input logic tlb_hit, + input logic tlb_cached, + input logic tlb_dirty, + input logic tlb_valid, + output word_t phy_addr, + output logic hit, + output logic cached, + output logic dirty, + output logic valid, + output logic privilege +); + + always_comb begin + if (virt_addr >= 32'hC000_0000 || virt_addr < 32'h8000_0000) begin + // kseg2 + kseg3 + kuseg -> tlb + phy_addr = {tlb_addr, virt_addr[11:0]}; + hit = tlb_hit; + cached = tlb_cached; + dirty = tlb_dirty; + valid = tlb_valid; + privilege = virt_addr[31]; + end else if (virt_addr >= 32'hA000_0000) begin + // kseg1 -> uncached + phy_addr = virt_addr & 32'h1FFF_FFFF; + hit = 1'b1; + cached = 1'b0; + dirty = 1'b1; + valid = 1'b1; + privilege = 1'b1; + end else begin + // kseg0 -> CP0.K0 + phy_addr = virt_addr & 32'h1FFF_FFFF; + hit = 1'b1; + cached = K0 == 3'b011; + dirty = 1'b1; + valid = 1'b1; + privilege = 1'b1; + end + end + +endmodule diff --git a/src/Gadgets/bram.sv b/src/Gadgets/bram.sv index 807e3b1..9289768 100644 --- a/src/Gadgets/bram.sv +++ b/src/Gadgets/bram.sv @@ -6,19 +6,19 @@ module bram #( input [$clog2(DATA_DEPTH)-1:0] addra, input clka, input [DATA_WIDTH-1:0] dina, - output logic [DATA_WIDTH-1:0] douta, + output reg [DATA_WIDTH-1:0] douta, input wea ); (* RAM_STYLE="block" *) reg [DATA_WIDTH-1:0] ram [DATA_DEPTH]; for(genvar i = 0; i < DATA_DEPTH; i++) - initial ram[i] = 0; + initial ram[i] = 0; always_ff @(posedge clka) begin - if(~reset)begin - if(wea) ram[addra] <= dina; - douta <= ~wea ? ram[addra] : dina; + if (~rst) begin + if(wea) ram[addra] <= dina; + douta <= ~wea ? ram[addra] : dina; end end endmodule \ No newline at end of file diff --git a/src/MU/AXI.sv b/src/MU/AXI.sv index eb48d60..3b16ca9 100644 --- a/src/MU/AXI.sv +++ b/src/MU/AXI.sv @@ -40,14 +40,9 @@ module AXI ( input wire bvalid, output wire bready, - // ICache - SRAM_RO_AXI_i.slave inst, - - // DCache Read - SRAM_RO_AXI_i.slave rdata, - - // DCache Write - SRAM_W_AXI_i.slave wdata + AXIRead_i.axi inst, + AXIRead_i.axi rdata, + AXIWrite_i.axi wdata ); // ============================== diff --git a/src/MU/DCache.sv b/src/MU/DCache.sv index b643372..54f252c 100644 --- a/src/MU/DCache.sv +++ b/src/MU/DCache.sv @@ -32,6 +32,7 @@ module DCache ( logic [3:0] hitway; logic [3:0] victim; + DCTagL_t dirt_tag; logic [3:0] wen; @@ -68,7 +69,7 @@ module DCache ( : port.ctrl.cache_index_writeback & tag[0].dirty ? 4'b0001 : port.ctrl.cache_index_writeback & tag[1].dirty ? 4'b0010 : port.ctrl.cache_index_writeback & tag[2].dirty ? 4'b0100 - : port.ctrl.cache_index_writeback & tag[3].dirty ? 4'b1000 + : port.ctrl.cache_index_writeback ? 4'b1000 : tag[0].valid == 0 ? 4'b0001 : tag[1].valid == 0 ? 4'b0010 : tag[2].valid == 0 ? 4'b0100 @@ -82,35 +83,33 @@ module DCache ( : nowLRU[2] == 0 ? 4'b0100 : 4'b1000; - assign port.dirt_valid = victim & {tag[3].dirty, tag[2].dirty, tag[1].dirty, tag[0].dirty}; - assign port.dirt_addr = { - (victim[0] ? tag[0].tag : {(32-`DC_TAGL){1'b0}}) - | (victim[1] ? tag[1].tag : {(32-`DC_TAGL){1'b0}}) - | (victim[2] ? tag[2].tag : {(32-`DC_TAGL){1'b0}}) - | (victim[3] ? tag[3].tag : {(32-`DC_TAGL){1'b0}}), - port.index, 4'b0 - }; + assign port.dirt = |{victim & {tag[3].dirty, tag[2].dirty, tag[1].dirty, tag[0].dirty}}; + assign dirt_tag = (victim[0] ? tag[0].tag : {(32-`DC_TAGL){1'b0}}) + | (victim[1] ? tag[1].tag : {(32-`DC_TAGL){1'b0}}) + | (victim[2] ? tag[2].tag : {(32-`DC_TAGL){1'b0}}) + | (victim[3] ? tag[3].tag : {(32-`DC_TAGL){1'b0}}); + assign port.dirt_addr = {dirt_tag, port.index, 4'b0}; assign port.dirt_row = (victim[0] ? data[0] : `DC_DATA_LENGTH'b0) | (victim[1] ? data[1] : `DC_DATA_LENGTH'b0) | (victim[2] ? data[2] : `DC_DATA_LENGTH'b0) | (victim[3] ? data[3] : `DC_DATA_LENGTH'b0); assign setLRU_valid = port.ctrl.read_and_hit | port.ctrl.read_but_replace | port.ctrl.write_and_hit | port.ctrl.write_but_replace; - assign setLRU = port.ctrl.read_and_hit ? hitway : 4'b0000 - | port.ctrl.read_but_replace ? victim : 4'b0000 - | port.ctrl.write_and_hit ? hitway : 4'b0000 - | port.ctrl.write_but_replace ? victim : 4'b0000; + assign setLRU = (port.ctrl.read_and_hit ? hitway : 4'b0000) + | (port.ctrl.read_but_replace ? victim : 4'b0000) + | (port.ctrl.write_and_hit ? hitway : 4'b0000) + | (port.ctrl.write_but_replace ? victim : 4'b0000); assign nxtsetLRU = setLRU | nowLRU & {4{~&{nowLRU | setLRU}}}; assign clrLRU_valid = port.ctrl.cache_index_invalidate | port.ctrl.cache_hit_invalidate | port.ctrl.cache_index_writeback | port.ctrl.cache_hit_writeback; - assign clrLRU = port.ctrl.cache_index_invalidate ? 4'b1111 : 4'b0000 - | port.ctrl.cache_hit_invalidate ? hitway : 4'b0000 - | port.ctrl.cache_index_writeback ? 4'b1111 : 4'b0000 - | port.ctrl.cache_hit_writeback ? hitway : 4'b0000; + assign clrLRU = (port.ctrl.cache_index_invalidate ? 4'b1111 : 4'b0000) + | (port.ctrl.cache_hit_invalidate ? hitway : 4'b0000) + | (port.ctrl.cache_index_writeback ? 4'b1111 : 4'b0000) + | (port.ctrl.cache_hit_writeback ? hitway : 4'b0000); assign nxtclrLRU = ~clrLRU & nowLRU; - assign nxtLRU = setLRU_valid ? nxtsetLRU : 4'b0000 - | clrLRU_valid ? nxtclrLRU : 4'b0000; + assign nxtLRU = (setLRU_valid ? nxtsetLRU : 4'b0000) + | (clrLRU_valid ? nxtclrLRU : 4'b0000); for (genvar i = 0; i < 128; i++) initial LRU[i] = 4'b0; @@ -138,13 +137,13 @@ module DCache ( assign DataRAM3.addr = port.index_for_lookup; // 写使能 - assign wen = {4{port.ctrl.read_but_replace}} & victim - | {4{port.ctrl.write_and_hit}} & hitway - | {4{port.ctrl.write_but_replace}} & victim - | {4{port.ctrl.cache_index_invalidate}} - | {4{port.ctrl.cache_index_writeback}} & victim - | {4{port.ctrl.cache_hit_invalidate}} & hitway - | {4{port.ctrl.cache_hit_writeback}} & hitway; + assign wen = ({4{port.ctrl.read_but_replace}} & victim) + | ({4{port.ctrl.write_and_hit}} & hitway) + | ({4{port.ctrl.write_but_replace}} & victim) + | ({4{port.ctrl.cache_index_invalidate}} ) + | ({4{port.ctrl.cache_index_writeback}} & victim) + | ({4{port.ctrl.cache_hit_invalidate}} & hitway) + | ({4{port.ctrl.cache_hit_writeback}} & hitway); assign {TagRAM3.wen, TagRAM2.wen, TagRAM1.wen, TagRAM0.wen} = wen; assign {DataRAM3.wen, DataRAM2.wen, DataRAM1.wen, DataRAM0.wen} = wen; @@ -161,22 +160,22 @@ module DCache ( assign DataRAM3.wdata = port.update_row; // bram - bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) tag_ram0 (.rst(rst), .addra(TagRAM0.addr), .clka(clk), .dina(TagRAM0.wdata), .douta(TagRAM0.rdata), .wea(TagRAM0.wen)); - bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) tag_ram1 (.rst(rst), .addra(TagRAM1.addr), .clka(clk), .dina(TagRAM1.wdata), .douta(TagRAM1.rdata), .wea(TagRAM1.wen)); - bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) tag_ram2 (.rst(rst), .addra(TagRAM2.addr), .clka(clk), .dina(TagRAM2.wdata), .douta(TagRAM2.rdata), .wea(TagRAM2.wen)); - bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) tag_ram3 (.rst(rst), .addra(TagRAM3.addr), .clka(clk), .dina(TagRAM3.wdata), .douta(TagRAM3.rdata), .wea(TagRAM3.wen)); - bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) data_ram0 (.rst(rst), .addra(DataRAM0.addr), .clka(clk), .dina(DataRAM0.wdata), .douta(DataRAM0.rdata), .wea(DataRAM0.wen)); - bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) data_ram1 (.rst(rst), .addra(DataRAM1.addr), .clka(clk), .dina(DataRAM1.wdata), .douta(DataRAM1.rdata), .wea(DataRAM1.wen)); - bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) data_ram2 (.rst(rst), .addra(DataRAM2.addr), .clka(clk), .dina(DataRAM2.wdata), .douta(DataRAM2.rdata), .wea(DataRAM2.wen)); - bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH($pow(2, `DC_TAGL-`DC_INDEXL))) + bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) data_ram3 (.rst(rst), .addra(DataRAM3.addr), .clka(clk), .dina(DataRAM3.wdata), .douta(DataRAM3.rdata), .wea(DataRAM3.wen)); endmodule diff --git a/src/MU/ICache.sv b/src/MU/ICache.sv index c5d9502..da410ab 100644 --- a/src/MU/ICache.sv +++ b/src/MU/ICache.sv @@ -11,7 +11,7 @@ module ICache ( // ============ Vars ============ // ============================== - ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3; + ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3; ICDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3; (* RAM_STYLE="block" *) @@ -69,17 +69,17 @@ module ICache ( : 4'b1000; assign setLRU_valid = port.ctrl.read_and_hit | port.ctrl.read_but_replace; - assign setLRU = port.ctrl.read_and_hit ? hitway : 4'b0000 - | port.ctrl.read_but_replace ? victim : 4'b0000; + assign setLRU = (port.ctrl.read_and_hit ? hitway : 4'b0000) + | (port.ctrl.read_but_replace ? victim : 4'b0000); assign nxtsetLRU = setLRU | nowLRU & {4{~&{nowLRU | setLRU}}}; assign clrLRU_valid = port.ctrl.cache_index_invalidate | port.ctrl.cache_hit_invalidate; - assign clrLRU = port.ctrl.cache_index_invalidate ? 4'b1111 : 4'b0000 - | port.ctrl.cache_hit_invalidate ? hitway : 4'b0000; + assign clrLRU = (port.ctrl.cache_index_invalidate ? 4'b1111 : 4'b0000) + | (port.ctrl.cache_hit_invalidate ? hitway : 4'b0000); assign nxtclrLRU = ~clrLRU & nowLRU; - assign nxtLRU = setLRU_valid ? nxtsetLRU : 4'b0000 - | clrLRU_valid ? nxtclrLRU : 4'b0000; + assign nxtLRU = (setLRU_valid ? nxtsetLRU : 4'b0000) + | (clrLRU_valid ? nxtclrLRU : 4'b0000); for (genvar i = 0; i < 64; i++) initial LRU[i] = 4'b0; @@ -106,9 +106,9 @@ module ICache ( assign DataRAM2.addr = port.index_for_lookup; assign DataRAM3.addr = port.index_for_lookup; // 写使能 - assign wen = {4{port.ctrl.read_but_replace}} & victim - | {4{port.ctrl.cache_index_invalidate}} - | {4{port.ctrl.cache_hit_invalidate}} & hitway; + assign wen = ({4{port.ctrl.read_but_replace}} & victim) + | ({4{port.ctrl.cache_index_invalidate}} ) + | ({4{port.ctrl.cache_hit_invalidate}} & hitway); assign {TagRAM3.wen, TagRAM2.wen, TagRAM1.wen, TagRAM0.wen} = wen; assign {DataRAM3.wen, DataRAM2.wen, DataRAM1.wen, DataRAM0.wen} = wen; @@ -122,22 +122,22 @@ module ICache ( assign DataRAM2.wdata = port.update_row; assign DataRAM3.wdata = port.update_row; - bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) tag_ram0 (.rst(rst), .addra(TagRAM0.addr), .clka(clk), .dina(TagRAM0.wdata), .douta(TagRAM0.rdata), .wea(TagRAM0.wen)); - bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) tag_ram1 (.rst(rst), .addra(TagRAM1.addr), .clka(clk), .dina(TagRAM1.wdata), .douta(TagRAM1.rdata), .wea(TagRAM1.wen)); - bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) tag_ram2 (.rst(rst), .addra(TagRAM2.addr), .clka(clk), .dina(TagRAM2.wdata), .douta(TagRAM2.rdata), .wea(TagRAM2.wen)); - bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) tag_ram3 (.rst(rst), .addra(TagRAM3.addr), .clka(clk), .dina(TagRAM3.wdata), .douta(TagRAM3.rdata), .wea(TagRAM3.wen)); - bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) data_ram0 (.rst(rst), .addra(DataRAM0.addr), .clka(clk), .dina(DataRAM0.wdata), .douta(DataRAM0.rdata), .wea(DataRAM0.wen)); - bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) data_ram1 (.rst(rst), .addra(DataRAM1.addr), .clka(clk), .dina(DataRAM1.wdata), .douta(DataRAM1.rdata), .wea(DataRAM1.wen)); - bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) data_ram2 (.rst(rst), .addra(DataRAM2.addr), .clka(clk), .dina(DataRAM2.wdata), .douta(DataRAM2.rdata), .wea(DataRAM2.wen)); - bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH($pow(2, `IC_TAGL-`IC_INDEXL))) + bram #(.DATA_WIDTH(`IC_DATA_LENGTH), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) data_ram3 (.rst(rst), .addra(DataRAM3.addr), .clka(clk), .dina(DataRAM3.wdata), .douta(DataRAM3.rdata), .wea(DataRAM3.wen)); endmodule diff --git a/src/MU/MU.sv b/src/MU/MU.sv index 9a77d02..cc82cb9 100644 --- a/src/MU/MU.sv +++ b/src/MU/MU.sv @@ -2,42 +2,18 @@ `include "Cache.svh" `include "TLB.svh" -module MMU ( - input clk, - input rst, - ICache_i.mmu ic, - DCache_i.mmu dc, - InstFetch_i.mu inst, - Memory_i.mu data, - input CacheOp_t cacheOp, - AXI_read_i.mu inst_axi, - AXI_read_i.mu rdata_axi, - AXI_write_i.mu wdata_axi, - // CP0 - input logic [2:0] K0, - input logic in_kernel, - input logic tlbwi, // TLBWI -> Write TLB - input logic tlbwr, // TLBWR -> Write TLB - input logic tlbp, // TLBP -> Write CP0 Index - input Random_t c0_Random, // TLBWR - input Index_t c0_Index, // TLBWI + TLBR - input EntryHi_t c0_EntryHi, // TLBWI + F/M(ASID) - // input PageMask_t c0_PageMask, // TLBWI - input EntryLo_t c0_EntryLo1, // TLBWI - input EntryLo_t c0_EntryLo0, // TLBWI - output EntryHi_t EntryHi, // TLBR - // output PageMask_t PageMask, // TLBR - output EntryLo_t EntryLo1, // TLBR - output EntryLo_t EntryLo0, // TLBR - output Index_t Index, // TLBP - // Exceptions - output logic iTLBRefill, - output logic iTLBInvalid, - output logic iAddressError, - output logic dTLBRefill, - output logic dTLBInvalid, - output logic dTLBModified, - output logic dAddressError +module MU ( + input clk, + input rst, + ICache_i.mu icache, + DCache_i.mu dcache, + InstFetch_i.mu instfetch, + Memory_i.mu memory, + CacheOp_i.mu cacheop, + AXIRead_i.mu axiread_inst, + AXIRead_i.mu axiread_data, + AXIWrite_i.mu axiwrite_data, + CP0_i.mu cp0 ); // ====================== // ======== Defs ======== @@ -132,9 +108,9 @@ module MMU ( end I_WD2: begin if (inst_axi.rvalid) begin - inst.data_ok = 1; if (iCached2) iNextState = I_WD3; else begin + inst.data_ok = 1; iEn = 1; iNextState = I_IDLE; end @@ -156,7 +132,10 @@ module MMU ( if (inst_axi.rvalid) iNextState = I_WD8; end I_WD8: begin - if (inst_axi.rvalid) iNextState = I_REFILL; + if (inst_axi.rvalid) begin + iNextState = I_REFILL; + inst.data_ok = 1; + end end I_REFILL: begin iEn = 1; @@ -235,12 +214,12 @@ module MMU ( assign iValid1 = iReq1 & iHit1 & iMValid1 & (in_kernel | iUser1); assign inst.addr_ok = iEn; mux5 #(64) inst_rdata_mux ( - ic.row[63:0], - ic.row[127:64], + ic.row[ 63: 0], + ic.row[127: 64], ic.row[191:128], ic.row[255:192], - {inst_axi.rdata, iD1}, - {iState == I_WD2, iPA1[4:3]}, + {iState == I_WD2 ? inst_axi.rdata : iD2, iD1}, + {iState != I_IDLE, iPA1[4:3]}, {inst.rdata1, inst.rdata0} ); assign ic.req = iEn; @@ -341,10 +320,10 @@ module MMU ( if (rdata_axi.addr_ok) begin if (~rdata_axi.rvalid) drNextState = DR_WD1; else begin + data.data_ok = 1; if (dCached2) drNextState = DR_WD2; else begin dEn = 1; - data.data_ok = 1; drNextState = DR_IDLE; end end @@ -352,9 +331,9 @@ module MMU ( end DR_WD1: begin if (rdata_axi.rvalid) begin - if (~dwr1) data.data_ok = 1; if (dCached2) drNextState = DR_WD2; else begin + data.data_ok = 1; dEn = 1; drNextState = DR_IDLE; end @@ -367,7 +346,10 @@ module MMU ( if (rdata_axi.rvalid) drNextState = DR_WD4; end DR_WD4: begin - if (rdata_axi.rvalid) drNextState = DR_REFILL; + if (rdata_axi.rvalid) begin + drNextState = DR_REFILL; + data.data_ok = 1; + end end DR_REFILL: begin if (wdata_ok) begin @@ -416,8 +398,8 @@ module MMU ( dc.row[ 63:32], dc.row[ 95:64], dc.row[127:96], - rdata_axi.rdata, - {rdata_axi.rvalid, dPA1[3:2]}, + drState == DR_WD4 ? drD1 : rdata_axi.rdata, + {drState != DR_IDLE, dPA1[3:2]}, data.rdata ); assign dc.req = dEn; @@ -588,14 +570,19 @@ module MMU ( assign dc.wvalid = dEn2 ? data.wr : dwr1; assign dc.wdata = dEn2 ? data.wdata : dWdata1; assign dc.wstrb = dEn2 ? data.wstrb : dWstrb1; - // ============================== - // ========== VA -> PA ========== - // ============================== + + // ===================================== + // ======= virt addr -> phy addr ======= + // ===================================== + + // turns stored addr to its phy addr + +`ifdef ENABLE_TLB + logic tlbw; logic [2:0] c0_Index_u; assign tlbw = tlbwi | tlbwr; assign c0_Index_u = tlbwr ? c0_Random[2:0] : c0_Index[2:0]; -`ifdef ENABLE_TLB TLB TLB ( .clk(clk), .rst(rst), @@ -626,8 +613,94 @@ module MMU ( .dValid (dMValid1), .dUser (dUser1) ); + `else + addr_virt_to_phy instfetch_addr_convert( + .virt_addr (stored_instfetch_addr), + .tlb_addr (stored_instfetch_addr[31:12]), + .tlb_hit (1'b1), + .tlb_cached(1'b0), + .tlb_dirty (1'b1), + .tlb_valid (1'b1), + .phy_addr (instfetch_phy_addr), + .hit (instfetch_hit), + .cached (instfetch_cached), + .dirty (), + .valid (instfetch_valid), + .privilege (instfetch_privilege) + ); + addr_virt_to_phy memory_addr_convert( + .virt_addr (stored_memory_addr), + .tlb_addr (stored_memory_addr[31:12]), + .tlb_hit (1'b1), + .tlb_cached(1'b0), + .tlb_dirty (1'b1), + .tlb_valid (1'b1), + .phy_addr (memory_phy_addr), + .hit (memory_hit), + .cached (memory_cached), + .dirty (memory_dirty), + .valid (memory_valid), + .privilege (memory_privilege) + ); + `endif + // ===================================== + // == InstFetch Control State Machine == + // ===================================== + + // cache ctrl: + // read_and_hit : lookup(0) and hit(1) + // read_but_replace : lookup(0) but miss(1), replace(2) + // cache_index_invalid : lookup(0) and invalid(2) all 4 rows + // cache_hit_invalid : lookup(0) and invalid(2) the hited(1) row + + typedef enum bit [1:0] { + IFC_LOOKUP, // deal with current request + // read if non-cached or not hited + // cache + IFC_READ, // wait for AXI read + // refill if cached + IFC_CACHE_INVALID // cache_index_invalid, cache_hit_invalid + } IFC_state_t; + + IFC_state_t IFC_cur_state; + IFC_state_t IFC_next_state; + + always_ff @(posedge clk) begin + if (rst) IFC_cur_state <= IFC_LOOKUP; + else IFC_cur_state <= IFC_next_state; + end + + always_comb begin + IFC_next_state = IFC_cur_state; + + instfetch_allow_next_req = 1'b0; + + // AXI action + // ????? + + case (IFC_cur_state) + instfetch.addr_ok = 1'b0; + instfetch.data_ok = 1'b0; + instfetch.rdata0 = 32'h0; + instfetch.rdata1 = 32'h0; + + // cacheop.addr_ok + + icache.ctrl = 4'b0; + icache.index_for_lookup = stored.addr; + icache.index = ?????; + icache.tag = ?????; + icache.update_row = ?????; + + IFC_LOOKUP: begin + if (stored.cacheop.icache_op) begin + end + end + endcase + end + endmodule diff --git a/src/MU/TLB.sv b/src/MU/TLB.sv index 9c03ab6..e78e46c 100644 --- a/src/MU/TLB.sv +++ b/src/MU/TLB.sv @@ -164,6 +164,20 @@ module TLB ( iUser = 1'b0; end end + addr_virt_to_phy instfetch_addr_convert( + .virt_addr (fVAddr1), + .tlb_addr (fPAddr1), + .tlb_hit (fHit1), + .tlb_cached (fCached1), + .tlb_dirty (fDirty1), + .tlb_valid (fValid1), + .phy_addr (iPAddr), + .hit (iHit), + .cached (iCached), + .dirty (iDirty), + .valid (iValid), + .privilege (iUser) // not + ); ffenr #(56) data_ff ( clk, rst, @@ -171,32 +185,19 @@ module TLB ( 1'b1, {mVAddr1, mPAddr1, mHit1, mCached1, mValid1, mDirty1} ); - always_comb begin - if (mVAddr1 > 32'hBFFF_FFFF || mVAddr1 <= 32'h7FFF_FFFF) begin - // kseg2 + kseg3 + kuseg -> tlb - dPAddr = {mPAddr1, mVAddr1[11:0]}; - dHit = mHit1; - dCached = mCached1; - dDirty = mDirty1; - dValid = mValid1; - dUser = ~mVAddr1[31]; - end else if (mVAddr1 > 32'h9FFF_FFFF) begin - // kseg1 uncached - dPAddr = mVAddr1 & 32'h1FFF_FFFF; - dHit = 1'b1; - dCached = 1'b0; - dDirty = 1'b1; - dValid = 1'b1; - dUser = 1'b0; - end else begin - // kseg0 -> CP0.K0 - dPAddr = mVAddr1 & 32'h1FFF_FFFF; - dHit = 1'b1; - dCached = K0[0]; - dDirty = 1'b1; - dValid = 1'b1; - dUser = 1'b0; - end - end + addr_virt_to_phy memory_addr_convert( + .virt_addr (mVAddr1), + .tlb_addr (mPAddr1), + .tlb_hit (mHit1), + .tlb_cached (mCached1), + .tlb_dirty (mDirty1), + .tlb_valid (mValid1), + .phy_addr (dPAddr), + .hit (dHit), + .cached (dCached), + .dirty (dDirty), + .valid (dValid), + .privilege (dUser) // not + ); endmodule diff --git a/src/MU/interface.sv b/src/MU/interface.sv index bd52f94..2a1b637 100644 --- a/src/MU/interface.sv +++ b/src/MU/interface.sv @@ -1,6 +1,43 @@ `include "defines.svh" `include "Cache.svh" +interface InstFetch_i; + logic req; + word_t addr; + logic addr_ok; + logic data_ok; + word_t rdata0; + word_t rdata1; + + modport cpu(output req, addr, input addr_ok, data_ok, rdata0, rdata1); + modport mu (input req, addr, output addr_ok, data_ok, rdata0, rdata1); +endinterface + +interface Memory_i; + logic req; + logic wr; + word_t addr; + logic [1:0] size; + logic [3:0] wstrb; + word_t wdata; + logic addr_ok; + logic data_ok; + word_t rdata; + + modport cpu(output req, wr, addr, size, wstrb, wdata, input addr_ok, data_ok, rdata); + modport mu (input req, wr, addr, size, wstrb, wdata, output addr_ok, data_ok, rdata); +endinterface + +interface CacheOp_i; + logic req; + word_t addr; + logic addr_ok; + CacheOp_t op; + + modport cpu(output req, addr, op, input addr_ok); + modport mu (input req, addr, op, output addr_ok); +endinterface + interface ICache_i; ICacheCtrl_t ctrl; ICIndexL_t index_for_lookup; @@ -25,9 +62,9 @@ interface ICache_i; endinterface interface DCache_i; - ICacheCtrl_t ctrl; + DCacheCtrl_t ctrl; DCIndexL_t index_for_lookup; - ICIndexL_t index; + DCIndexL_t index; DCTagL_t tag; logic hit; DCData_t hit_row; @@ -52,34 +89,7 @@ interface DCache_i; ); endinterface -interface InstFetch_i; - logic req; - word_t addr; - logic addr_ok; - logic data_ok; - word_t rdata0; - word_t rdata1; - - modport cpu(output req, addr, input addr_ok, data_ok, rdata0, rdata1); - modport mu(input req, addr, output addr_ok, data_ok, rdata0, rdata1); -endinterface - -interface Memory_i; - logic req; - logic wr; - word_t addr; - logic [1:0] size; - logic [3:0] wstrb; - word_t wdata; - logic addr_ok; - logic data_ok; - word_t rdata; - - modport cpu(output req, wr, addr, size, wstrb, wdata, input addr_ok, data_ok, rdata); - modport mu(input req, wr, addr, size, wstrb, wdata, output addr_ok, data_ok, rdata); -endinterface - -interface AXI_read_i; +interface AXIRead_i; logic req; word_t addr; logic [3:0] len; @@ -93,7 +103,7 @@ interface AXI_read_i; modport mu (output req, addr, len, size, input addr_ok, data_ok, rdata, rvalid); endinterface -interface AXI_write_i; +interface AXIWrite_i; logic req; word_t addr; logic [3:0] len; @@ -109,3 +119,86 @@ interface AXI_write_i; modport axi(input req, addr, len, size, wstrb, wdata, wvalid, wlast, output addr_ok, data_ok, wready); modport mu (output req, addr, len, size, wstrb, wdata, wvalid, wlast, input addr_ok, data_ok, wready); endinterface + +interface CP0_i; + logic [2:0] cp0_K0; + logic cp0_in_kernel; + logic cpu_tlbwi; + logic cpu_tlbwr; + logic cpu_tlbp; + Random_t cp0_Random; // TLBWR + EntryHi_t cp0_EntryHi; // TLBWI + F/M(ASID) + PageMask_t cp0_PageMask; // TLBWI + EntryLo_t cp0_EntryLo1; // TLBWI + EntryLo_t cp0_EntryLo0; // TLBWI + Index_t cp0_Index; // TLBWI + TLBR + EntryHi_t tlb_EntryHi; + PageMask_t tlb_PageMask; + EntryLo_t tlb_EntryLo1; + EntryLo_t tlb_EntryLo0; + Index_t tlb_Index; // TLBP + logic tlb_iTLBRefill; + logic tlb_iTLBInvalid; + logic tlb_iAddressError; + logic tlb_dTLBRefill; + logic tlb_dTLBInvalid; + logic tlb_dTLBModified; + logic tlb_dAddressError; + + modport mu( + input cp0_K0, + input cp0_in_kernel, + input cpu_tlbwi, + input cpu_tlbwr, + input cpu_tlbp, + input cp0_Random, + input cp0_Index, + input cp0_EntryHi, + input cp0_PageMask, + input cp0_EntryLo1, + input cp0_EntryLo0, + output tlb_EntryHi, + output tlb_PageMask, + output tlb_EntryLo1, + output tlb_EntryLo0, + output tlb_Index, + output tlb_iTLBRefill, + output tlb_iTLBInvalid, + output tlb_iAddressError, + output tlb_dTLBRefill, + output tlb_dTLBInvalid, + output tlb_dTLBModified, + output tlb_dAddressError + ); + modport cp0( + output cp0_K0, + output cp0_in_kernel, + output cpu_tlbwi, + output cpu_tlbwr, + output cpu_tlbp, + output cp0_Random, + output cp0_Index, + output cp0_EntryHi, + output cp0_PageMask, + output cp0_EntryLo1, + output cp0_EntryLo0, + input tlb_EntryHi, + input tlb_PageMask, + input tlb_EntryLo1, + input tlb_EntryLo0, + input tlb_Index + ); + modport cpu( + output cpu_tlbwi, + output cpu_tlbwr, + output cpu_tlbp, + input tlb_iTLBRefill, + input tlb_iTLBInvalid, + input tlb_iAddressError, + input tlb_dTLBRefill, + input tlb_dTLBInvalid, + input tlb_dTLBModified, + input tlb_dAddressError + ); + +endinterface \ No newline at end of file diff --git a/src/include/defines.svh b/src/include/defines.svh index 46e5a9a..5109593 100644 --- a/src/include/defines.svh +++ b/src/include/defines.svh @@ -84,14 +84,12 @@ typedef enum logic [1:0] { URIGHT = 2'b10 } ALR_t; -typedef enum logic [2:0] { - CNOP = 3'b000, - IC_L = 3'b001, // I-Cache Lookup - IC_I = 3'b011, // I-Cache Index - DC_LB = 3'b100, // D-Cache Lookup writeBack - DC_LO = 3'b101, // D-Cache Lookup writeOnly - DC_IB = 3'b110, // D-Cache Index writeBack - DC_IO = 3'b111 // D-Cache Index writeOnly +typedef struct packed { + logic icache_op; + logic dcache_op; + logic index_or_hit; // 0 for index + // 1 for hit + logic writeback; } CacheOp_t; typedef enum logic [1:0] { diff --git a/src/mycpu_top.sv b/src/mycpu_top.sv index 3e93f18..00f27eb 100644 --- a/src/mycpu_top.sv +++ b/src/mycpu_top.sv @@ -1,7 +1,7 @@ `include "defines.svh" `include "CP0.svh" -`include "DCache.svhCache.svh" +`include "Cache.svh" module mycpu_top ( input wire [5:0] ext_int, //high active @@ -64,17 +64,17 @@ module mycpu_top ( output wire debug_wb_pc_A ); - AXI_read_i inst_axi; - AXI_read_i rdata_axi; - AXI_write_i wdata_axi; + AXIRead_i inst_axi(); + AXIRead_i rdata_axi(); + AXIWrite_i wdata_axi(); - ICache_i icache; - DCache_i dcache; + ICache_i icache(); + DCache_i dcache(); - InstFetch_i inst; - Memory_i data; + InstFetch_i inst(); + Memory_i data(); - CacheOp_t cache_op; + CacheOp_i cache_op(); logic C0_int; logic [4:0] C0_addr; @@ -168,7 +168,7 @@ module mycpu_top ( .dc (dcache.mu), .inst (inst.mu), .data (data.mu), - .cacheOp (cache_op), + .cacheOp (cache_op.mu), .inst_axi (inst_axi.mu), .rdata_axi (rdata_axi.mu), .wdata_axi (wdata_axi.mu), @@ -243,9 +243,9 @@ module mycpu_top ( Datapath datapath ( .clk (aclk), .rst (~aresetn), - .fetch_i (inst.cpu), - .mem_i (data.cpu), - .cache_op(cache_op), + .fetch (inst.cpu), + .mem (data.cpu), + .cache_op(cache_op.cpu), .iTLBRefill (iTLBRefill), .iTLBInvalid (iTLBInvalid),