Big Update
Co-authored-by: Paul <1323564116@qq.com>
This commit is contained in:
parent
d9de091698
commit
880bebb97b
@ -97,8 +97,22 @@ module AXI (
|
||||
// ======= Write Request ========
|
||||
// ==============================
|
||||
|
||||
always_comb begin
|
||||
assign wdata.data_ok = AXIWrite.AXIWriteData.bvalid;
|
||||
|
||||
always_comb begin
|
||||
AXIWrite.AXIWriteData.wid = 1;
|
||||
AXIWrite.AXIWriteData.wdata = 0;
|
||||
AXIWrite.AXIWriteData.wstrb = 0;
|
||||
AXIWrite.AXIWriteData.wlast = 0;
|
||||
AXIWrite.AXIWriteData.wvalid = 0;
|
||||
|
||||
if(AXIWrite.AXIWriteData.wready & wdata.wvalid) begin
|
||||
AXIWrite.AXIWriteData.wid = 4'b1;
|
||||
AXIWrite.AXIWriteData.wdata = wdata.wdata;
|
||||
AXIWrite.AXIWriteData.wstrb = wdata.wstrb;
|
||||
AXIWrite.AXIWriteData.wlast = wdata.wlast;
|
||||
AXIWrite.AXIWriteData.wvalid = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -4,382 +4,222 @@
|
||||
`include "AXI.svh"
|
||||
|
||||
module ICache (
|
||||
input clk,
|
||||
input rst,
|
||||
// Core
|
||||
sramro_i.slave sram,
|
||||
// AXI
|
||||
HandShake.next AXIReq,
|
||||
output logic [31:0] ICacheAddress,
|
||||
input logic ICacheLineOK,
|
||||
input logic [`IC_DATA_LENGTH-1:0] ICacheLine
|
||||
input clk, rst,
|
||||
ICache_i.cache port
|
||||
);
|
||||
|
||||
|
||||
// ==============================
|
||||
// ============ Vars ============
|
||||
// ==============================
|
||||
|
||||
|
||||
// Four way assoc bram controller:
|
||||
ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3;
|
||||
ICDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3;
|
||||
wire ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3;
|
||||
wire ICDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3;
|
||||
|
||||
// LRU
|
||||
logic [3:0] LRU[64]; // Recent Access bitmap
|
||||
logic [3:0] nextLRU[64];
|
||||
logic [3:0] LRU[64];
|
||||
wire logic [3:0] nextLRU;
|
||||
wire logic [3:0] nowLRU;
|
||||
|
||||
// IDLE / REFILL
|
||||
reg ctrl0; // BRAM addr control
|
||||
wire [5:0] cacheAddress0; // BRAM w/r address
|
||||
wire logic [`IC_TAG_LENGTH-1:0] tagOut[4];
|
||||
wire IC_data_t dataOut[4];
|
||||
wire logic [3:0] tagV;
|
||||
|
||||
wire [5:0] wAddr4;
|
||||
wire [3:0] wen4;
|
||||
wire uncached4;
|
||||
wire wen4comb; // wen4comb -> combinition of wen4 + uncached4
|
||||
wire wen4comb_r; // wen4comb_r -> combinition of wen4
|
||||
wire [`IC_DATA_LENGTH-1:0] wData4;
|
||||
wire [`IC_TAG_LENGTH-2:0] tag4;
|
||||
wire [`IC_TAG_LENGTH-1:0] wTag4;
|
||||
wire logic valid;
|
||||
wire word_t addr;
|
||||
wire logic [21:0] tag;
|
||||
wire logic [5:0] index;
|
||||
|
||||
reg req0; // request or not
|
||||
wire logic hit;
|
||||
wire logic [3:0] hitWay;
|
||||
wire IC_data_t cacheLine;
|
||||
|
||||
// Lookup
|
||||
wire req1; // valid
|
||||
wire logic [1:0] victim;
|
||||
wire logic [3:0] wen;
|
||||
wire logic [3:0] replaceWen;
|
||||
|
||||
wire [31:0] PC1;
|
||||
wire [21:0] tag1;
|
||||
wire [5:0] addr1;
|
||||
wire logic en1, en2; // en1: Lookup->Lookup, en2: Lookup->Rep
|
||||
|
||||
reg [31:0] PA1;
|
||||
reg uncached1;
|
||||
wire logic [5:0] baddr;
|
||||
wire logic bwe;
|
||||
|
||||
wire [`IC_TAG_LENGTH-1:0] tagOut1[4];
|
||||
wire [`IC_DATA_LENGTH-1:0] dataOut1[4];
|
||||
wire [3:0] tagV1;
|
||||
// ===========================
|
||||
// ======== Flip-Flop ========
|
||||
// ===========================
|
||||
|
||||
wire hit1; // Cache hit or not
|
||||
// TODO: verilator warn me hitWay1 has some problems
|
||||
wire [3:0] hitWay1; // Cache Line hit or not
|
||||
ffenr#(1) valid_ff(clk, rst, port.valid, en1, valid);
|
||||
ffen#(32) addr_ff(clk, port.addr, en1, addr);
|
||||
ffen#(6) wen_ff(clk, wen, en2, replaceWen);
|
||||
|
||||
wire [`IC_DATA_LENGTH-1:0] cacheLine1; // Cache Line
|
||||
wire [31:0] cacheLineData1[4]; // tmp: Map Cache Line into 4 Cache Data
|
||||
// ===============================
|
||||
// ======== State Machine ========
|
||||
// ===============================
|
||||
|
||||
wire cacheMiss;
|
||||
|
||||
// Miss
|
||||
wire req2;
|
||||
|
||||
wire [31:0] PC2;
|
||||
wire [31:0] PA2;
|
||||
|
||||
wire uncached2;
|
||||
|
||||
wire hit2;
|
||||
wire [3:0] hitWay2;
|
||||
wire [3:0] tagV2;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
Idle,
|
||||
Wait,
|
||||
Done
|
||||
} AXIBlock;
|
||||
|
||||
AXIBlock AXIBlocker, nextAXIBlocker;
|
||||
|
||||
// Replace
|
||||
wire [`IC_DATA_LENGTH-1:0] ICacheLine3;
|
||||
wire ICacheLineOK3;
|
||||
wire [5:0] addr3;
|
||||
wire [`IC_TAG_LENGTH-2:0] tag3;
|
||||
wire [1:0] victim3;
|
||||
wire [3:0] tagV3;
|
||||
wire [3:0] wen3;
|
||||
wire uncached3;
|
||||
|
||||
|
||||
// ==============================
|
||||
// ==== IDLE / REFILL Stage =====
|
||||
// ==============================
|
||||
|
||||
// BRAM addr 选择控制信号
|
||||
assign wen4comb_r = wen4[0] | wen4[1] | wen4[2] | wen4[3];
|
||||
assign wen4comb = wen4comb_r | uncached4;
|
||||
|
||||
always_comb begin
|
||||
if (wen4comb_r) begin
|
||||
ctrl0 = 1'b1;
|
||||
req0 = 1'b0;
|
||||
end else if (sram.req) begin
|
||||
ctrl0 = 1'b0;
|
||||
req0 = 1'b1;
|
||||
end else begin
|
||||
ctrl0 = 1'b0;
|
||||
req0 = 1'b0;
|
||||
end
|
||||
enum bit { LOOKUP = 1'b0, REPLACE = 1'b1 } state;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) state <= LOOKUP;
|
||||
else if(state == LOOKUP & valid & ~hit)
|
||||
state <= REPLACE;
|
||||
else if(state == REPLACE & port.wvalid)
|
||||
state <= LOOKUP;
|
||||
end
|
||||
|
||||
mux3 #(6) ctrl0_mux (
|
||||
sram.addr[9:4],
|
||||
PC1[9:4],
|
||||
wAddr4,
|
||||
{ctrl0, ~sram.addr_ok},
|
||||
cacheAddress0
|
||||
);
|
||||
|
||||
assign sram.addr_ok = (ctrl0 == 0) & sram.req & (cacheMiss == 0);
|
||||
|
||||
// ==============================
|
||||
// ==== Pipeline Register 1 =====
|
||||
// ==============================
|
||||
|
||||
ffenr #(33) pipelineReg1 (
|
||||
.clk(clk),
|
||||
.rst(rst | wen4comb_r), // TODO: wen4comb or wen4comb_r
|
||||
.en (~cacheMiss),
|
||||
.d ({sram.addr, req0}),
|
||||
.q ({PC1, req1})
|
||||
);
|
||||
|
||||
// ==============================
|
||||
// ========== VA -> PA ==========
|
||||
// ==============================
|
||||
|
||||
always_comb begin
|
||||
if (PC1 > 32'hC0000000 || PC1 < 32'h7FFFFFFF) begin // kseg2 + kseg3 + kuseg? -> tlb
|
||||
PA1 = PC1;
|
||||
uncached1 = 0;
|
||||
end else if (PC1 > 32'h9fff_ffff) begin // kseg1 uncached
|
||||
PA1 = PC1 - 32'h9FFF_FFFF;
|
||||
uncached1 = 1;
|
||||
end else begin // kseg0 -> CP0.K0 default: uncached
|
||||
PA1 = PC1 - 32'h7FFF_FFFF;
|
||||
uncached1 = 1;
|
||||
end
|
||||
end
|
||||
assign en1 = state == LOOKUP & (~valid | hit);
|
||||
assign en2 = state == LOOKUP & valid & ~hit;
|
||||
|
||||
// ==============================
|
||||
// =========== Lookup ===========
|
||||
// ==============================
|
||||
|
||||
// 确保cacheMiss时tagOut1和dataOut1不变 -> L106 mux3解决?
|
||||
assign tagOut1[0] = TagRAM0.rdata;
|
||||
assign tagOut1[1] = TagRAM1.rdata;
|
||||
assign tagOut1[2] = TagRAM2.rdata;
|
||||
assign tagOut1[3] = TagRAM3.rdata;
|
||||
// BRAM Out
|
||||
assign tagOut[0] = TagRAM0.rdata;
|
||||
assign tagOut[1] = TagRAM1.rdata;
|
||||
assign tagOut[2] = TagRAM2.rdata;
|
||||
assign tagOut[3] = TagRAM3.rdata;
|
||||
|
||||
assign dataOut1[0] = DataRAM0.rdata;
|
||||
assign dataOut1[1] = DataRAM1.rdata;
|
||||
assign dataOut1[2] = DataRAM2.rdata;
|
||||
assign dataOut1[3] = DataRAM3.rdata;
|
||||
assign dataOut[0] = DataRAM0.rdata;
|
||||
assign dataOut[1] = DataRAM1.rdata;
|
||||
assign dataOut[2] = DataRAM2.rdata;
|
||||
assign dataOut[3] = DataRAM3.rdata;
|
||||
|
||||
assign tagV1[0] = tagOut1[0][0];
|
||||
assign tagV1[1] = tagOut1[1][0];
|
||||
assign tagV1[2] = tagOut1[2][0];
|
||||
assign tagV1[3] = tagOut1[3][0];
|
||||
assign tagV[0] = tagOut[0][0];
|
||||
assign tagV[1] = tagOut[1][0];
|
||||
assign tagV[2] = tagOut[2][0];
|
||||
assign tagV[3] = tagOut[3][0];
|
||||
|
||||
// Hit Check
|
||||
assign tag1 = PC1[31:10];
|
||||
assign addr1 = PC1[9:4];
|
||||
assign tag = addr[31:10];
|
||||
assign index = addr[9:4];
|
||||
|
||||
assign hitWay1[0] = tagV1[0] & tagOut1[0][`IC_TAG_LENGTH-1:1] == tag1;
|
||||
assign hitWay1[1] = tagV1[1] & tagOut1[1][`IC_TAG_LENGTH-1:1] == tag1;
|
||||
assign hitWay1[2] = tagV1[2] & tagOut1[2][`IC_TAG_LENGTH-1:1] == tag1;
|
||||
assign hitWay1[3] = tagV1[3] & tagOut1[3][`IC_TAG_LENGTH-1:1] == tag1;
|
||||
assign hit1 = (hitWay1[0] | hitWay1[1] | hitWay1[2] | hitWay1[3]) & ~uncached1;
|
||||
assign hitWay[0] = tagV[0] & tagOut[0][`IC_TAG_LENGTH-1:1] == tag;
|
||||
assign hitWay[1] = tagV[1] & tagOut[1][`IC_TAG_LENGTH-1:1] == tag;
|
||||
assign hitWay[2] = tagV[2] & tagOut[2][`IC_TAG_LENGTH-1:1] == tag;
|
||||
assign hitWay[3] = tagV[3] & tagOut[3][`IC_TAG_LENGTH-1:1] == tag;
|
||||
assign hit = hitWay[0] | hitWay[1] | hitWay[2] | hitWay[3];
|
||||
|
||||
assign cacheLine1 = (hitWay1[0] ? dataOut1[0] : `IC_DATA_LENGTH'b0) |
|
||||
(hitWay1[1] ? dataOut1[1] : `IC_DATA_LENGTH'b0) |
|
||||
(hitWay1[2] ? dataOut1[2] : `IC_DATA_LENGTH'b0) |
|
||||
(hitWay1[3] ? dataOut1[3] : `IC_DATA_LENGTH'b0);
|
||||
assign cacheLine = (hitWay[0] ? dataOut[0] : `IC_DATA_LENGTH'b0)
|
||||
| (hitWay[1] ? dataOut[1] : `IC_DATA_LENGTH'b0)
|
||||
| (hitWay[2] ? dataOut[2] : `IC_DATA_LENGTH'b0)
|
||||
| (hitWay[3] ? dataOut[3] : `IC_DATA_LENGTH'b0);
|
||||
|
||||
assign cacheLineData1[0] = cacheLine1[31:0];
|
||||
assign cacheLineData1[1] = cacheLine1[63:32];
|
||||
assign cacheLineData1[2] = cacheLine1[95:64];
|
||||
assign cacheLineData1[3] = cacheLine1[127:96];
|
||||
assign port.hit = hit;
|
||||
assign port.row = cacheLine;
|
||||
|
||||
// Cache Miss
|
||||
assign cacheMiss = ~hit1 & ~wen4comb & req1; // TODO: 这里是否需要添加uncached1条件 + ~wen4comb可否去除
|
||||
|
||||
// SRAM
|
||||
// Lookup + Replace
|
||||
wire [1:0] tmpAddr[2];
|
||||
assign tmpAddr[0] = {PC1[3], 1'b0};
|
||||
assign tmpAddr[1] = {PC1[3], 1'b1};
|
||||
|
||||
wire [31:0] tmpData[4];
|
||||
assign tmpData[0] = ICacheLine3[31:0];
|
||||
assign tmpData[1] = ICacheLine3[63:32];
|
||||
assign tmpData[2] = ICacheLine3[95:64];
|
||||
assign tmpData[3] = ICacheLine3[127:96];
|
||||
|
||||
assign sram.data_ok = hit1 & req1 | ICacheLineOK3;
|
||||
assign sram.rdata0 = ICacheLineOK3 ? tmpData[tmpAddr[0]] : cacheLineData1[tmpAddr[0]];
|
||||
assign sram.rdata1 = ICacheLineOK3 ? tmpData[tmpAddr[1]] : cacheLineData1[tmpAddr[1]];
|
||||
|
||||
// LRU
|
||||
// TODO: 时序爆炸?
|
||||
always_comb begin
|
||||
nextLRU = LRU;
|
||||
if (hitWay1[0]) begin
|
||||
casez (LRU[addr1])
|
||||
4'b111?: nextLRU[addr1] = 4'b0001;
|
||||
default: nextLRU[addr1][0] = 1'b1;
|
||||
endcase
|
||||
end else if (hitWay1[1]) begin
|
||||
casez (LRU[addr1])
|
||||
4'b11?1: nextLRU[addr1] = 4'b0010;
|
||||
default: nextLRU[addr1][1] = 1'b1;
|
||||
endcase
|
||||
end else if (hitWay1[2]) begin
|
||||
casez (LRU[addr1])
|
||||
4'b1?11: nextLRU[addr1] = 4'b0100;
|
||||
default: nextLRU[addr1][2] = 1'b1;
|
||||
endcase
|
||||
end else if (hitWay1[3]) begin
|
||||
casez (LRU[addr1])
|
||||
4'b?111: nextLRU[addr1] = 4'b1000;
|
||||
default: nextLRU[addr1][3] = 1'b1;
|
||||
endcase
|
||||
end else nextLRU = LRU;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
for (integer i = 0; i < 64; i++) LRU[i] <= 4'b0;
|
||||
end else LRU <= nextLRU;
|
||||
end
|
||||
|
||||
// ==============================
|
||||
// ==== Pipeline Register 2 =====
|
||||
// ==============================
|
||||
|
||||
ffenr #(74) pipelineReg2 (
|
||||
.clk(clk),
|
||||
.rst(rst | AXIBlocker == Done),
|
||||
.en (AXIBlocker == Idle), // TODO: 这里需要重新设计一下: AXI是否流水
|
||||
.d ({PC1, hitWay1, cacheMiss, tagV1, PA1, uncached1}),
|
||||
.q ({PC2, hitWay2, req2, tagV2, PA2, uncached2})
|
||||
);
|
||||
|
||||
|
||||
// ==============================
|
||||
// ============ Miss ============
|
||||
// ==============================
|
||||
|
||||
assign hit2 = (hitWay2[0] | hitWay2[1] | hitWay2[2] | hitWay2[3]) & ~uncached2;
|
||||
// 不要在cacheMiss处理过程中重复处理
|
||||
assign AXIReq.readygo = AXIReq.allowin & ~hit2 & req2 & (AXIBlocker == Idle);
|
||||
assign ICacheAddress = {PA2[31:4], 4'b0}; // 使用实地址
|
||||
|
||||
always_comb begin
|
||||
casez (AXIBlocker)
|
||||
Idle: begin
|
||||
if (req2) nextAXIBlocker = Wait;
|
||||
else nextAXIBlocker = AXIBlocker;
|
||||
end
|
||||
Wait: begin
|
||||
if (ICacheLineOK) nextAXIBlocker = Done;
|
||||
else nextAXIBlocker = AXIBlocker;
|
||||
end
|
||||
Done: begin
|
||||
if (~cacheMiss) nextAXIBlocker = Idle;
|
||||
else nextAXIBlocker = AXIBlocker;
|
||||
end
|
||||
default: begin
|
||||
nextAXIBlocker = Idle;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) AXIBlocker <= Idle;
|
||||
else AXIBlocker <= nextAXIBlocker;
|
||||
end
|
||||
|
||||
// ==============================
|
||||
// ==== Pipeline Register 3 =====
|
||||
// ==============================
|
||||
|
||||
ffenr #(`IC_DATA_LENGTH + 1 + 6 + 22 + 4 + 1) pipelineReg3 (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.en (1'b1),
|
||||
.d ({ICacheLine, ICacheLineOK, PC2[9:4], PC2[31:10], tagV2, uncached2}),
|
||||
.q ({ICacheLine3, ICacheLineOK3, addr3, tag3, tagV3, uncached3})
|
||||
);
|
||||
assign nowLRU = LRU[index];
|
||||
|
||||
// ==============================
|
||||
// ========== Replace ===========
|
||||
// ==============================
|
||||
|
||||
assign victim3 = tagV3[0] == 0 ? 2'b00 :
|
||||
tagV3[1] == 0 ? 2'b01 :
|
||||
tagV3[2] == 0 ? 2'b10 :
|
||||
tagV3[3] == 0 ? 2'b11 :
|
||||
LRU[addr3][0] == 0 ? 2'b00 :
|
||||
LRU[addr3][1] == 0 ? 2'b01 :
|
||||
LRU[addr3][2] == 0 ? 2'b10 :
|
||||
LRU[addr3][3] == 0 ? 2'b11 :
|
||||
2'b11;
|
||||
assign wen3[0] = (victim3 == 0) & ICacheLineOK3 & ~uncached3;
|
||||
assign wen3[1] = (victim3 == 1) & ICacheLineOK3 & ~uncached3;
|
||||
assign wen3[2] = (victim3 == 2) & ICacheLineOK3 & ~uncached3;
|
||||
assign wen3[3] = (victim3 == 3) & ICacheLineOK3 & ~uncached3;
|
||||
// Choose Victim
|
||||
assign victim = tagV[0] == 0 ? 2'b00 :
|
||||
tagV[1] == 0 ? 2'b01 :
|
||||
tagV[2] == 0 ? 2'b10 :
|
||||
tagV[3] == 0 ? 2'b11 :
|
||||
nowLRU[0] == 0 ? 2'b00 :
|
||||
nowLRU[1] == 0 ? 2'b01 :
|
||||
nowLRU[2] == 0 ? 2'b10 :
|
||||
nowLRU[3] == 0 ? 2'b11 :
|
||||
2'b11;
|
||||
assign wen[0] = (victim == 0);
|
||||
assign wen[1] = (victim == 1);
|
||||
assign wen[2] = (victim == 2);
|
||||
assign wen[3] = (victim == 3);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (wen3 != 0) begin
|
||||
$display("Victim Found: wen3=0x%b, addr3=0x%8h, tagV3=0x%b, LRU=0x%b", wen3, addr3, tagV3,
|
||||
LRU[addr3]);
|
||||
// Update LRU
|
||||
always_comb begin
|
||||
nextLRU = nowLRU;
|
||||
|
||||
// Hit
|
||||
|
||||
if (hitWay[0]) begin
|
||||
casez (nowLRU)
|
||||
4'b111?: nextLRU = 4'b0001;
|
||||
default: nextLRU[0] = 1'b1;
|
||||
endcase
|
||||
end else if (hitWay[1]) begin
|
||||
casez (nowLRU)
|
||||
4'b11?1: nextLRU = 4'b0010;
|
||||
default: nextLRU[1] = 1'b1;
|
||||
endcase
|
||||
end else if (hitWay[2]) begin
|
||||
casez (nowLRU)
|
||||
4'b1?11: nextLRU = 4'b0100;
|
||||
default: nextLRU[2] = 1'b1;
|
||||
endcase
|
||||
end else if (hitWay[3]) begin
|
||||
casez (nowLRU)
|
||||
4'b?111: nextLRU = 4'b1000;
|
||||
default: nextLRU[3] = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
||||
// Not Hit
|
||||
|
||||
else if (wen[0]) begin
|
||||
casez (nowLRU)
|
||||
4'b111?: nextLRU = 4'b0001;
|
||||
default: nextLRU[0] = 1'b1;
|
||||
endcase
|
||||
end else if (wen[1]) begin
|
||||
casez (nowLRU)
|
||||
4'b11?1: nextLRU = 4'b0010;
|
||||
default: nextLRU[1] = 1'b1;
|
||||
endcase
|
||||
end else if (wen[2]) begin
|
||||
casez (nowLRU)
|
||||
4'b1?11: nextLRU = 4'b0100;
|
||||
default: nextLRU[2] = 1'b1;
|
||||
endcase
|
||||
end else if (wen[3]) begin
|
||||
casez (nowLRU)
|
||||
4'b?111: nextLRU = 4'b1000;
|
||||
default: nextLRU[3] = 1'b1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ==============================
|
||||
// ==== Pipeline Register 4 =====
|
||||
// ==============================
|
||||
|
||||
// 防止uncached3提前传播 -> uncached3 & ICacheLineOK3
|
||||
ffenr #(`IC_DATA_LENGTH + 6 + 4 + 22 + 1) pipelineReg4 (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.en (1'b1),
|
||||
.d ({ICacheLine3, addr3, wen3, tag3, uncached3 & ICacheLineOK3}),
|
||||
.q ({wData4, wAddr4, wen4, tag4, uncached4})
|
||||
);
|
||||
|
||||
assign wTag4 = {tag4, 1'b1};
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
for (integer i = 0; i < 64; i++) LRU[i] <= 4'b0;
|
||||
end else if(state == LOOKUP)
|
||||
LRU[index] <= nextLRU;
|
||||
end
|
||||
|
||||
// ==============================
|
||||
// ========= Block RAM ==========
|
||||
// ==============================
|
||||
|
||||
mux2#(6) index_mux(index, port.addr[9:4], en1, baddr);
|
||||
assign bwe = (state == REPLACE) & port.wvalid;
|
||||
|
||||
// 地址
|
||||
assign TagRAM0.addr = cacheAddress0;
|
||||
assign TagRAM1.addr = cacheAddress0;
|
||||
assign TagRAM2.addr = cacheAddress0;
|
||||
assign TagRAM3.addr = cacheAddress0;
|
||||
assign DataRAM0.addr = cacheAddress0;
|
||||
assign DataRAM1.addr = cacheAddress0;
|
||||
assign DataRAM2.addr = cacheAddress0;
|
||||
assign DataRAM3.addr = cacheAddress0;
|
||||
assign TagRAM0.addr = baddr;
|
||||
assign TagRAM1.addr = baddr;
|
||||
assign TagRAM2.addr = baddr;
|
||||
assign TagRAM3.addr = baddr;
|
||||
assign DataRAM0.addr = baddr;
|
||||
assign DataRAM1.addr = baddr;
|
||||
assign DataRAM2.addr = baddr;
|
||||
assign DataRAM3.addr = baddr;
|
||||
// 写使能
|
||||
assign TagRAM0.wen = wen4[0];
|
||||
assign TagRAM1.wen = wen4[1];
|
||||
assign TagRAM2.wen = wen4[2];
|
||||
assign TagRAM3.wen = wen4[3];
|
||||
assign DataRAM0.wen = wen4[0];
|
||||
assign DataRAM1.wen = wen4[1];
|
||||
assign DataRAM2.wen = wen4[2];
|
||||
assign DataRAM3.wen = wen4[3];
|
||||
assign TagRAM0.wen = bwe & replaceWen[0];
|
||||
assign TagRAM1.wen = bwe & replaceWen[1];
|
||||
assign TagRAM2.wen = bwe & replaceWen[2];
|
||||
assign TagRAM3.wen = bwe & replaceWen[3];
|
||||
assign DataRAM0.wen = bwe & replaceWen[0];
|
||||
assign DataRAM1.wen = bwe & replaceWen[1];
|
||||
assign DataRAM2.wen = bwe & replaceWen[2];
|
||||
assign DataRAM3.wen = bwe & replaceWen[3];
|
||||
// 写数据
|
||||
assign TagRAM0.wdata = wTag4;
|
||||
assign TagRAM1.wdata = wTag4;
|
||||
assign TagRAM2.wdata = wTag4;
|
||||
assign TagRAM3.wdata = wTag4;
|
||||
assign DataRAM0.wdata = wData4;
|
||||
assign DataRAM1.wdata = wData4;
|
||||
assign DataRAM2.wdata = wData4;
|
||||
assign DataRAM3.wdata = wData4;
|
||||
assign TagRAM0.wdata = {tag, 1'b1};
|
||||
assign TagRAM1.wdata = {tag, 1'b1};
|
||||
assign TagRAM2.wdata = {tag, 1'b1};
|
||||
assign TagRAM3.wdata = {tag, 1'b1};
|
||||
assign DataRAM0.wdata = port.wdata;
|
||||
assign DataRAM1.wdata = port.wdata;
|
||||
assign DataRAM2.wdata = port.wdata;
|
||||
assign DataRAM3.wdata = port.wdata;
|
||||
|
||||
cache_tag_bram tag_ram0 (
|
||||
.addra(TagRAM0.addr),
|
||||
|
Binary file not shown.
@ -87,8 +87,14 @@ readygo to valid
|
||||
assign en2 = ~judge[3] | judge[1];
|
||||
assign en3 = (~judge[3] & ~judge[1] & judge[2] | judge[3] & (~judge[1] & ~judge[4] | judge[1] & (~judge[4] & ~judge[0] | judge[4])));
|
||||
assign en4 = (~judge[4] & judge[3] & ~judge[1] | judge[4] & (~judge[1] & ~judge[5] | judge[1] & (~judge[5] & ~judge[0] | judge[5])));
|
||||
assign HandShake_in1.allowin = ~judge[5] | judge[1];
|
||||
assign HandShake_in2.allowin = (~judge[4] | judge[1] & (~judge[5] | judge[0]));
|
||||
// 11 >= 4
|
||||
// 10 == 3
|
||||
// others:00
|
||||
// {HandShake_in1, HandShake_in2}
|
||||
assign HandShake_in1.allowin = (~judge[4] & (~judge[3] | judge[1]) | judge[4] & judge[0] & ~judge[5]);
|
||||
assign HandShake_in2.allowin = (~judge[3] & (~judge[2] | judge[1]) | judge[3] & ~judge[4] & judge[0]);
|
||||
// assign HandShake_in1.allowin = ~judge[5] | judge[1];
|
||||
// assign HandShake_in2.allowin = (~judge[4] | judge[1] & (~judge[5] | judge[0]));
|
||||
ffen #(128) out (
|
||||
clk,
|
||||
{qi1, qi2, qp1, qp2},
|
||||
@ -148,114 +154,4 @@ readygo to valid
|
||||
|
||||
end
|
||||
end
|
||||
//assign HandShake_out1.readygo = judge[1] & judge[2];
|
||||
//assign HandShake_out2.readygo = judge[0] & judge[3];
|
||||
//assign HandShake_in1.allowin = ~judge[5] | judge[1];
|
||||
//assign HandShake_in2.allowin = (~judge[4] | judge[1] & (~judge[5] | judge[0]));
|
||||
//assign en1 = ~judge[2] | judge[1];
|
||||
//assign en2 = ~judge[3] | judge[1];
|
||||
//assign en3 = (~judge[3] & ~judge[1] & judge[2] | judge[3] & (~judge[1] & ~judge[4] | judge[1] & (~judge[4] & ~judge[0] | judge[4])));
|
||||
//assign en4 = (~judge[4] & judge[3] & ~judge[1] | judge[4] & (~judge[1] & ~judge[5] | judge[1] & (~judge[5] & ~judge[0] | judge[5])));
|
||||
|
||||
// mux3 #(65) mux3_d1 (
|
||||
// {in1, HandShake_in1.readygo, pin1},
|
||||
// {qi3, qv3, qp3},
|
||||
// {qi2, qv2, qp2},
|
||||
// (judge[3] & ~judge[0]) ? 2'b10 : ((judge[3] & judge[0] & judge[4]) ? 2'b01 : 2'b00),
|
||||
// {di1, dv1, dp1}
|
||||
// );
|
||||
// mux4 #(65) mux4_d2 (
|
||||
// {in2, HandShake_in2.readygo, pin2},
|
||||
// {in1, HandShake_in1.readygo, pin1},
|
||||
// {qi4, qv4, qp4},
|
||||
// {qi3, qv3, qp3},
|
||||
// (judge[4] & ~judge[0]) ? 2'b11 : ((judge[4] & judge[0] & judge[5]) ? 2'b10 : ((~judge[4] & (~judge[2] | (~judge[3] & judge[1] | judge[0]))) ? 2'b00 : 2'b01)),
|
||||
// {di2, dv2, dp2}
|
||||
// );
|
||||
// mux3 #(65) mux3_d3 (
|
||||
// {in1, HandShake_in1.readygo, pin1},
|
||||
// {in2, HandShake_in2.readygo, pin2},
|
||||
// {qi4, qv4, qp4},
|
||||
// (judge[5] & ~judge[0]) ? 2'b10 : ((~judge[5] & (~judge[3] | ~judge[4] & judge[1] | judge[0])) ? 2'b01 : 2'b00),
|
||||
// {di3, dv3, dp3}
|
||||
// );
|
||||
// assign di4 = (judge[4] & ~judge[0] & (~judge[1] | judge[5])) ? in1 : in2;
|
||||
// assign dv4 = ((judge[4] & ~judge[0] & (~judge[1] | judge[5])) ? HandShake_in1.readygo : HandShake_in2.readygo);
|
||||
// assign dp4 = (judge[4] & ~judge[0] & (~judge[1] | judge[5])) ? pin1 : pin2;
|
||||
// ffen #(32) pc1 (
|
||||
// clk,
|
||||
// dp1,
|
||||
// en1,
|
||||
// qp1
|
||||
// );
|
||||
// ffen #(32) pc2 (
|
||||
// clk,
|
||||
// dp2,
|
||||
// en2,
|
||||
// qp2
|
||||
// );
|
||||
// ffen #(32) pc3 (
|
||||
// clk,
|
||||
// dp3,
|
||||
// en3,
|
||||
// qp3
|
||||
// );
|
||||
// ffen #(32) pc4 (
|
||||
// clk,
|
||||
// dp4,
|
||||
// en4,
|
||||
// qp4
|
||||
// );
|
||||
// ffen #(32) instr1 (
|
||||
// clk,
|
||||
// di1,
|
||||
// en1,
|
||||
// qi1
|
||||
// );
|
||||
// ffen #(32) instr2 (
|
||||
// clk,
|
||||
// di2,
|
||||
// en2,
|
||||
// qi2
|
||||
// );
|
||||
// ffen #(32) instr3 (
|
||||
// clk,
|
||||
// di3,
|
||||
// en3,
|
||||
// qi3
|
||||
// );
|
||||
// ffen #(32) instr4 (
|
||||
// clk,
|
||||
// di4,
|
||||
// en4,
|
||||
// qi4
|
||||
// );
|
||||
// ffenr #(1) valid1 (
|
||||
// clk,
|
||||
// rst,
|
||||
// dv1,
|
||||
// en1,
|
||||
// qv1
|
||||
// );
|
||||
// ffenr #(1) valid2 (
|
||||
// clk,
|
||||
// rst,
|
||||
// dv2,
|
||||
// en2,
|
||||
// qv2
|
||||
// );
|
||||
// ffenr #(1) valid3 (
|
||||
// clk,
|
||||
// rst,
|
||||
// dv3,
|
||||
// en3,
|
||||
// qv3
|
||||
// );
|
||||
// ffenr #(1) valid4 (
|
||||
// clk,
|
||||
// rst,
|
||||
// dv4,
|
||||
// en4,
|
||||
// qv4
|
||||
// );
|
||||
endmodule
|
||||
|
131
src/MMU/MMU.sv
Normal file
131
src/MMU/MMU.sv
Normal file
@ -0,0 +1,131 @@
|
||||
`include "defines.svh"
|
||||
`include "sram.svh"
|
||||
`include "ICache.svh"
|
||||
`include "AXI.svh"
|
||||
|
||||
module MMU (
|
||||
input clk, rst,
|
||||
|
||||
input logic [1:0] K0,
|
||||
|
||||
ICache_i.mmu ic,
|
||||
// DCache_i.mmu dc,
|
||||
|
||||
sramro_i.slave inst,
|
||||
sram_i.slave data,
|
||||
|
||||
SRAM_RO_AXI_i.master inst_axi
|
||||
);
|
||||
|
||||
// ======================
|
||||
// ======== iVar ========
|
||||
// ======================
|
||||
|
||||
wire word_t iVA = inst.addr;
|
||||
wire word_t iPA;
|
||||
wire logic iCached;
|
||||
|
||||
wire logic iEn;
|
||||
wire logic iValid1;
|
||||
wire logic iCached1;
|
||||
wire word_t iPA1;
|
||||
wire logic inst_axi_req;
|
||||
wire logic inst_data_ok;
|
||||
|
||||
logic [127:0] iDataLine;
|
||||
|
||||
// ================================
|
||||
// ======== iState Machine ========
|
||||
// ================================
|
||||
|
||||
enum bit [2:0] { I_IDLE, I_WA, I_WD1, I_WD2, I_WD3 } iState;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) iState <= I_IDLE;
|
||||
else if(inst_axi_req) iState <= I_WA;
|
||||
else if(iState == I_WA & inst_axi_req.addr_ok) iState <= I_WD1;
|
||||
end
|
||||
|
||||
// ============================
|
||||
// ======== iFlip-Flop ========
|
||||
// ============================
|
||||
|
||||
assign iEn = iState == I_IDLE;
|
||||
ffenr#(1) ivalid_ff(clk, rst, inst.req, iEn, iValid1);
|
||||
ffen#(1) icached_ff(clk, iCached, iEn, iCached1);
|
||||
ffen#(32) ipa_ff(clk, iPA, iEn, iPA1);
|
||||
|
||||
// ===============================
|
||||
// ========== iFunction ==========
|
||||
// ===============================
|
||||
|
||||
assign inst.addr_ok = iEn;
|
||||
assign ic.valid = inst.req & iEn & iCached;
|
||||
|
||||
assign inst_axi_req = (state == I_IDLE) & iValid1 & (~iCached1 | inst.hit);
|
||||
assign inst_axi.req = inst_axi_req;
|
||||
assign inst_axi.addr = iPA1;
|
||||
assign inst_axi.size = iCached1 ? 2'b11 : 2'b01;
|
||||
|
||||
assign inst_data_ok = (iState == I_WD2) & inst_axi.rvalid;
|
||||
assign inst_data_ok = ((iState == I_WD2) | (iState == I_IDLE)) & iValid1;
|
||||
|
||||
// ======================
|
||||
// ======== dVar ========
|
||||
// ======================
|
||||
|
||||
wire word_t dVA;
|
||||
wire word_t dPA;
|
||||
wire logic dCached;
|
||||
|
||||
// ================================
|
||||
// ======== dState Machine ========
|
||||
// ================================
|
||||
|
||||
|
||||
// ============================
|
||||
// ======== dFlip-Flop ========
|
||||
// ============================
|
||||
|
||||
|
||||
// ===============================
|
||||
// ========== dFunction ==========
|
||||
// ===============================
|
||||
|
||||
|
||||
// ==============================
|
||||
// ========== VA -> PA ==========
|
||||
// ==============================
|
||||
|
||||
mapping mapping_inst (
|
||||
.addr_in (iVA),
|
||||
.addr_out(iPA),
|
||||
.cached (iCached)
|
||||
);
|
||||
|
||||
mapping mapping_data (
|
||||
.addr_in (dVA),
|
||||
.addr_out(dPA),
|
||||
.cached (dCached)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module mapping (
|
||||
input word_t addr_in,
|
||||
output word_t addr_out,
|
||||
output logic cached
|
||||
);
|
||||
always_comb begin
|
||||
if (addr_in > 32'hBFFF_FFFF || addr_in <= 32'h7FFF_FFFF) begin // kseg2 + kseg3 + kuseg? -> tlb
|
||||
addr_out = addr_in;
|
||||
cached = 0;
|
||||
end else if (addr_in > 32'h9FFF_FFFF) begin // kseg1 uncached
|
||||
addr_out = addr_in & 32'h1FFF_FFFF;
|
||||
cached = 0;
|
||||
end else begin // kseg0 -> CP0.K0 default: uncached
|
||||
addr_out = addr_in & 32'h1FFF_FFFF;
|
||||
cached = (K0 == 2'b11);
|
||||
end
|
||||
end
|
||||
endmodule
|
@ -1,11 +1,15 @@
|
||||
`ifndef ICACHE_SVH
|
||||
`define ICACHE_SVH
|
||||
|
||||
`include "defines.svh"
|
||||
|
||||
// IC for I-Cache
|
||||
|
||||
`define IC_TAG_LENGTH 22+1 // Tag + Valid
|
||||
`define IC_DATA_LENGTH 128 // 16Bytes
|
||||
|
||||
typedef logic [`IC_DATA_LENGTH-1:0] IC_data_t;
|
||||
|
||||
// TODO: 考虑到指令4字节对齐,可否给TAG减少两位?Cache是否处理4字节对齐异常?
|
||||
|
||||
typedef struct packed {
|
||||
@ -18,8 +22,20 @@ typedef struct packed {
|
||||
typedef struct packed {
|
||||
logic wen;
|
||||
logic [5:0] addr; // Index
|
||||
logic [`IC_DATA_LENGTH-1:0] wdata;
|
||||
logic [`IC_DATA_LENGTH-1:0] rdata;
|
||||
IC_data_t wdata;
|
||||
IC_data_t rdata;
|
||||
} ICDataRAM_t; // 64 * 128
|
||||
|
||||
interface ICache_i;
|
||||
logic valid;
|
||||
word_t addr;
|
||||
logic hit;
|
||||
IC_data_t row;
|
||||
logic wvalid;
|
||||
IC_data_t wdata;
|
||||
|
||||
modport cache(input valid, addr, output hit, row, input wvalid, wdata);
|
||||
modport mmu(output valid, addr, input hit, row, output wvalid, wdata);
|
||||
endinterface //ICache_i
|
||||
|
||||
`endif
|
||||
|
@ -55,11 +55,12 @@ interface SRAM_W_AXI_i;
|
||||
logic [3:0] wstrb;
|
||||
word_t wdata;
|
||||
logic wvalid;
|
||||
logic wlast;
|
||||
logic addr_ok;
|
||||
logic data_ok;
|
||||
|
||||
modport master(output req, addr, size, wstrb, wdata, wvalid, input addr_ok, data_ok);
|
||||
modport slave(input req, addr, size, wstrb, wdata, wvalid, output addr_ok, data_ok);
|
||||
modport master(output req, addr, size, wstrb, wdata, wvalid, wlast, input addr_ok, data_ok);
|
||||
modport slave(input req, addr, size, wstrb, wdata, wvalid, wlast, output addr_ok, data_ok);
|
||||
|
||||
endinterface
|
||||
|
||||
|
@ -42,19 +42,16 @@ module happy ();
|
||||
HandShake fake_hs ();
|
||||
SRAM_RO_AXI_i fake_ic ();
|
||||
SRAM_W_AXI_i fake_dc ();
|
||||
ICache_i fake_ici ();
|
||||
|
||||
wire [31:0] ICacheAddress;
|
||||
wire ICacheLineOK;
|
||||
wire [`IC_DATA_LENGTH-1:0] ICacheLine;
|
||||
|
||||
ICache ic (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.sram(fake_sram.slave),
|
||||
.AXIReq(fake_hs.next),
|
||||
.ICacheAddress(ICacheAddress),
|
||||
.ICacheLineOK(ICacheLineOK),
|
||||
.ICacheLine(ICacheLine)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.port(fake_ici.cache)
|
||||
);
|
||||
|
||||
AXI AXI (
|
||||
|
@ -2,15 +2,15 @@
|
||||
6'b000000 0 0 qi1 qi2 1 1 1 1 0 0 in1 in2 ? ?
|
||||
6'b000010 0 0 qi1 qi2 1 1 1 1 0 0 in1 in2 ? ?
|
||||
6'b000011 0 0 qi1 qi2 1 1 1 1 0 0 in1 in2 ? ?
|
||||
6'b000100 0 0 qi1 qi2 1 1 0 1 1 0 ? in1 in2 ?
|
||||
6'b000100 0 0 qi1 qi2 1 0 0 1 1 0 ? in1 in2 ?
|
||||
6'b000110 1 0 qi1 qi2 1 1 1 1 0 0 in1 in2 ? ?
|
||||
6'b000111 1 0 qi1 qi2 1 1 1 1 0 0 in1 in2 ? ?
|
||||
6'b001100 0 0 qi1 qi2 1 1 0 0 1 1 ? ? in1 in2
|
||||
6'b001110 1 0 qi1 qi2 1 1 1 1 1 0 qi2 in1 in2 ?
|
||||
6'b001100 0 0 qi1 qi2 0 0 0 0 1 1 ? ? in1 in2
|
||||
6'b001110 1 0 qi1 qi2 1 0 1 1 1 0 qi2 in1 in2 ?
|
||||
6'b001111 1 1 qi1 qi2 1 1 1 1 0 0 in1 in2 ? ?
|
||||
6'b011100 0 0 qi1 qi2 1 0 0 0 0 1 ? ? ? in1
|
||||
6'b011110 1 0 qi1 qi2 1 1 1 1 1 1 qi2 qi3 in1 in2
|
||||
6'b011111 1 1 qi1 qi2 1 1 1 1 1 0 qi3 in1 in2 ?
|
||||
6'b011100 0 0 qi1 qi2 0 0 0 0 0 1 ? ? ? in1
|
||||
6'b011110 1 0 qi1 qi2 0 0 1 1 1 1 qi2 qi3 in1 in2
|
||||
6'b011111 1 1 qi1 qi2 1 0 1 1 1 0 qi3 in1 in2 ?
|
||||
6'b111100 0 0 qi1 qi2 0 0 0 0 0 0 ? ? ? ?
|
||||
6'b111110 1 0 qi1 qi2 1 0 1 1 1 1 qi2 qi3 qi4 in1
|
||||
6'b111111 1 1 qi1 qi2 1 1 1 1 1 1 qi3 qi4 in1 in2
|
||||
6'b111110 1 0 qi1 qi2 0 0 1 1 1 1 qi2 qi3 qi4 in1
|
||||
6'b111111 1 1 qi1 qi2 0 0 1 1 1 1 qi3 qi4 in1 in2
|
Loading…
Reference in New Issue
Block a user