From 781a9bfc939034b28f461b1e665c2089bd024101 Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Thu, 8 Jul 2021 21:20:50 +0800 Subject: [PATCH] [AXI] ICache Read --- .vscode/c_cpp_properties.json | 17 +++ src/AXI/AXI.sv | 178 ++++++++++++++++++++++++++++++ src/Cache/ICache.sv | 3 +- src/include/AXI.svh | 20 ++-- src/testbench/happy/happy.sv | 30 +++-- src/testbench/icache/make.sh | 14 ++- src/testbench/icache/testbench.sv | 4 +- 7 files changed, 239 insertions(+), 27 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 src/AXI/AXI.sv diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..28f5a36 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/usr/share/verilator/include" + ], + "defines": [], + "compilerPath": "/usr/sbin/clang", + "cStandard": "c17", + "cppStandard": "c++14", + "intelliSenseMode": "linux-clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/src/AXI/AXI.sv b/src/AXI/AXI.sv new file mode 100644 index 0000000..5d4f084 --- /dev/null +++ b/src/AXI/AXI.sv @@ -0,0 +1,178 @@ +`include "AXI.svh" +`include "defines.svh" + +module AXI ( + input logic clk, + input logic rst, + + // AXI Read + AXIRead_i.master AXIRead, + + // ICache + HandShake.prev ICReq, + input logic [31:0] ICacheAddress, + output logic ICacheLineOK, // ICache无条件接收 + output logic [127:0] ICacheLine + + // TODO: DCache +); + + AXIStatus_t status, nextStatus; + + initial begin + status = ASIdle; + end + + /* + ----- ICache ----- + ReadAddr: + - ID: Read 0 + => arid = 4'b0 + - One transaction for a whole cache line -> 128bits + => arlen = 4'b0011 -> 4*4bytes + => arsize = 3'b010 -> 4bytes + => arburst = 2'b10 -> WRAP (Cache line?) + - No AXI Cache + => arcache = 4'b0000 + - Protect: Instruction(1) Secure(0) Privileged(1)/Normal(0) + => arport = 3'b10? + - Atomic: default + => arlock = 2'b00 + - Dynamic + => araddr = read address + => arvalid = address and control information valid + => rready = master ready + ReadData: + + */ + + logic [31:0] IReadAddr; + logic [ 1:0] IRespCounter; + logic IReadReqPending; + logic IReadAllowReq; + logic IReadRespOK; + logic [31:0] ICacheLineHelper[4]; + + assign ICReq.allowin = IReadAllowReq; + assign ICacheLineOK = IReadRespOK; + assign ICacheLine[31:0] = ICacheLineHelper[0]; + assign ICacheLine[63:32] = ICacheLineHelper[1]; + assign ICacheLine[95:64] = ICacheLineHelper[2]; + assign ICacheLine[127:96] = ICacheLineHelper[3]; + + // icache burst read handler + always_ff @(posedge clk) begin + if (rst) IRespCounter <= 0; + else if (status == ASReadInst) begin + if (AXIRead.AXIReadData.rvalid) begin + // TODO: 这里忽略了rid + rresp校验, 希望不要出错 :) + ICacheLineHelper[IRespCounter] <= AXIRead.AXIReadData.rdata; + IRespCounter <= IRespCounter + 1; + end + end else IRespCounter <= 0; // avoid latch -> reset zero when not used + end + + // read status switch + always_comb begin + IReadAddr = 32'b0; + IReadReqPending = 0'b0; + nextStatus = status; + + case (status) + + // 处理读请求 + ASIdle: begin + // TODO DCache仲裁 + + // ICache读请求 + if (ICReq.readygo & ICReq.allowin) begin + // wrap to the beginning of the cache line + IReadAddr = ICacheAddress & 32'hFFFF_FFF0; // recored read addr + IReadReqPending = 1'b1; + nextStatus = ASReadInst; + end else nextStatus = ASIdle; // 没有请求 + end + + // 处理ICache读过程 + ASReadInst: begin + if (IReadRespOK) begin + // 不和ICache握手, 直接返回 + nextStatus = ASIdle; + IReadReqPending = 1'b0; + end else nextStatus = ASReadInst; // 没有读完 + end + + default: begin + end + endcase + end + + // next status + always_ff @(posedge clk) begin + status <= nextStatus; + end + + // AXI read control + ICache handshake + always_comb begin + // 八成不会动的东西 + AXIRead.AXIReadAddr.arcache = 4'b0; + AXIRead.AXIReadAddr.arlock = 2'b0; + + // TODO 是否严格处理DCache按字寻址处理 + AXIRead.AXIReadAddr.arlen = 4'b0011; + AXIRead.AXIReadAddr.arsize = 3'b010; + AXIRead.AXIReadAddr.arburst = 2'b10; + + // 据情况修改的东西 + AXIRead.AXIReadAddr.arid = 4'b0; // ICache(0) DCache(1) + AXIRead.AXIReadAddr.arport = 3'b101; // ICache(101) DCache(001) + AXIRead.AXIReadAddr.araddr = 32'b0; + AXIRead.AXIReadAddr.arvalid = 1'b0; + AXIRead.AXIReadAddr.rready = 1'b0; + + // 状态量 + IReadRespOK = 1'b0; // ICache 读返回默认无效 + + case (status) + // 处理读请求 + ASIdle: begin // TODO: 处理 DCache读请求 + 写请求仲裁 + if (IReadReqPending) begin + // ICache 读请求 + if (AXIRead.AXIReadData.arready) begin // TODO: slave 准备好是否提取到外层? + AXIRead.AXIReadAddr.arid = 4'b0; + AXIRead.AXIReadAddr.arport = 3'b101; + AXIRead.AXIReadAddr.araddr = IReadAddr; + AXIRead.AXIReadAddr.arvalid = 1'b1; + AXIRead.AXIReadAddr.rready = 1'b1; + end + end + end + + // 处理ICache读请求 + ASReadInst: begin + // (ICache 读逻辑单独实现 -> 独立的counter逻辑) + if (AXIRead.AXIReadData.rlast) begin + // TODO: 是否有必要检查 rvalid + IReadRespOK = 1'b1; + end + end + + // 处理DCache读请求 + ASReadData: begin + // TODO + end + + // TODO: latch killer :) + default: begin + end + endcase + + + end + + + + + + +endmodule diff --git a/src/Cache/ICache.sv b/src/Cache/ICache.sv index 633f4f0..46f9a1d 100644 --- a/src/Cache/ICache.sv +++ b/src/Cache/ICache.sv @@ -1,6 +1,7 @@ `include "defines.svh" `include "sram.svh" `include "ICache.svh" +`include "AXI.svh" module ICache ( input clk, @@ -148,7 +149,7 @@ module ICache ( // Next Status Generator: always_comb begin - nextStatus = ICIdle; // avoid latch + nextStatus = status; // avoid latch case (status) ICIdle: begin // -> IDLE or LOOKUP if (sram.req) nextStatus = ICLookup; diff --git a/src/include/AXI.svh b/src/include/AXI.svh index 9392df0..f1814a1 100644 --- a/src/include/AXI.svh +++ b/src/include/AXI.svh @@ -1,10 +1,9 @@ `ifndef AXI_SVH `define AXI_SVH -`include "constants.svh" typedef struct packed { logic [3:0] arid; // Read address ID - logic [`WIDTH-1:0] araddr; // Read address + logic [31:0] araddr; // Read address logic [3:0] arlen; // Burst length logic [2:0] arsize; // Burst size logic [1:0] arburst; // Burst type @@ -19,13 +18,13 @@ typedef struct packed { typedef struct packed { logic arready; // Read address ready logic [3:0] rid; // Read ID tag - logic [`WIDTH-1:0] rdata; // Read data + logic [31:0] rdata; // Read data logic [1:0] rresp; // Read response logic rlast; // Read last logic rvalid; // Read valid } AXIReadData_t; // slave -interface AXIRead; +interface AXIRead_i; AXIReadAddr_t AXIReadAddr; AXIReadData_t AXIReadData; @@ -36,7 +35,7 @@ endinterface //AXIRead typedef struct packed { logic [3:0] awid; // Write address ID - logic [`WIDTH-1:0] awaddr; // Write address + logic [31:0] awaddr; // Write address logic [3:0] awlen; // Burst length logic [2:0] awsize; // Burst size logic [1:0] awburst; // Burst type @@ -46,7 +45,7 @@ typedef struct packed { logic awvalid; // Write address valid logic [3:0] wid; // Write ID tag - logic [`WIDTH-1:0] wdata; // Write data + logic [31:0] wdata; // Write data logic [3:0] wstrb; // Write strobes logic wlast; // Write last logic wvalid; // Write valid @@ -63,7 +62,7 @@ typedef struct packed { logic bvalid; // Write response valid } AXIWriteData_t; // slave -interface AXIWrite; +interface AXIWrite_i; AXIWriteAddr_t AXIWriteAddr; AXIWriteData_t AXIWriteData; @@ -71,4 +70,11 @@ interface AXIWrite; modport slave(input AXIWriteAddr, output AXIWriteData); endinterface //AXIWrite +typedef enum bit [2:0] { + ASIdle, + ASReadInst, + ASReadData + +} AXIStatus_t; + `endif diff --git a/src/testbench/happy/happy.sv b/src/testbench/happy/happy.sv index ccf6c47..0180a7a 100644 --- a/src/testbench/happy/happy.sv +++ b/src/testbench/happy/happy.sv @@ -2,6 +2,7 @@ `include "ICache.svh" `include "sram.svh" +`include "AXI.svh" module happy (); logic clk, rst; @@ -10,33 +11,30 @@ module happy (); integer counter = 0; /* verilator lint_on UNOPTFLAT */ - integer i; sramro_i fake (); + AXIRead_i fakeAR (); + AXIWrite_i fakeAW (); + HandShake fakeHS (); + ICache ICache ( .clk (clk), .rst (rst), - .sram(fake.slave) + .sram(fake.master) + ); + + AXI AXI ( + .AXIRead(fakeAR.slave), + .ICReq (fakeHS.prev), + .ICResp (fakeHS.next) ); initial begin - $dumpfile("test.vcd"); - $dumpvars(0, testbench); - - $dumpvars(1, fake.req); - $dumpvars(1, fake.addr); - $dumpvars(1, fake.addr_ok); - $dumpvars(1, fake.data_ok); - $dumpvars(1, fake.rdata0); - $dumpvars(1, fake.rdata1); - - rst = 0; - clk = 1; - - fake.req = 1; + fake.req = 1; fake.addr = 32'b0100000; end + integer i; always_latch begin clk = ~clk; diff --git a/src/testbench/icache/make.sh b/src/testbench/icache/make.sh index 68dddb4..e7964c7 100755 --- a/src/testbench/icache/make.sh +++ b/src/testbench/icache/make.sh @@ -1,3 +1,13 @@ -verilator -I/home/paul/loongson/MIPS/src/AXI/ -I/home/paul/loongson/MIPS/src/Cache/ -I/home/paul/loongson/MIPS/src/Core/ -I/home/paul/loongson/MIPS/src/CP0/ -I/home/paul/loongson/MIPS/src/include/ -I/home/paul/loongson/MIPS/src/testbench/happy/ +1800-2017ext+sv --cc --exe --build sim_main.cpp testbench.sv +verilator -I/home/paul/loongson/MIPS/src/AXI/ \ + -I/home/paul/loongson/MIPS/src/Cache/ \ + -I/home/paul/loongson/MIPS/src/Core/ \ + -I/home/paul/loongson/MIPS/src/CP0/ \ + -I/home/paul/loongson/MIPS/src/include/ \ + -I/home/paul/loongson/MIPS/src/testbench/happy/ \ + +1800-2017ext+sv \ + --cc --trace --exe --build \ + sim_main.cpp testbench.sv -./obj_dir/Vtestbench +./obj_dir/Vtestbench +trace + +gtkwave ./logs/vlt_dump.vcd diff --git a/src/testbench/icache/testbench.sv b/src/testbench/icache/testbench.sv index dfbf22a..a1b8ff1 100644 --- a/src/testbench/icache/testbench.sv +++ b/src/testbench/icache/testbench.sv @@ -27,13 +27,15 @@ module testbench ( assign rdata1 = fake_sram.rdata1; initial begin + $dumpfile("logs/vlt_dump.vcd"); + $dumpvars(); fake_sram.req = 1; fake_sram.addr = 32'b0100000; end integer counter = 0; always_ff @(posedge clk) begin - fake_sram.addr = fake_sram.addr + 1; + if (fake_sram.data_ok) fake_sram.addr = fake_sram.addr + 1; if (clk == 1'b1) begin counter = counter + 1; if (counter >= 16) $finish;