Big Update

Co-authored-by: Paul <1323564116@qq.com>
This commit is contained in:
hoo 2021-07-15 17:39:24 +08:00
parent d9de091698
commit 880bebb97b
9 changed files with 354 additions and 459 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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