[AXI] ICache Read

This commit is contained in:
Paul Pan 2021-07-08 21:20:50 +08:00
parent 2d3b15752c
commit 781a9bfc93
7 changed files with 239 additions and 27 deletions

17
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -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
}

178
src/AXI/AXI.sv Normal file
View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;