Add some stuff related to cache
This commit is contained in:
0
sim/application_wrapper/application_wrapper.yaml
Normal file
0
sim/application_wrapper/application_wrapper.yaml
Normal file
19
sim/application_wrapper/cache/application_wrapper_cache_l1_test.py
vendored
Normal file
19
sim/application_wrapper/cache/application_wrapper_cache_l1_test.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import cocotb
|
||||
from cocotb.handle import Immediate
|
||||
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import Timer, RisingEdge, FallingEdge, with_timeout
|
||||
|
||||
|
||||
CLK_PERIOD = 5
|
||||
|
||||
@cocotb.test
|
||||
async def sanity_test(dut):
|
||||
cocotb.start_soon(Clock(dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
dut.i_rst.value = Immediate(1)
|
||||
for _ in range(10):
|
||||
await RisingEdge(dut.i_clk)
|
||||
dut.i_rst.value = 0
|
||||
|
||||
await Timer(1, "us")
|
||||
7
sim/application_wrapper/cache/cache.yaml
vendored
Normal file
7
sim/application_wrapper/cache/cache.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
tests:
|
||||
- name: "application_wrapper_cache_l1_test"
|
||||
toplevel: "application_wrapper_cache_l1"
|
||||
modules:
|
||||
- "application_wrapper_cache_l1_test"
|
||||
sources: "sources.list"
|
||||
waves: True
|
||||
1
sim/application_wrapper/cache/sources.list
vendored
Normal file
1
sim/application_wrapper/cache/sources.list
vendored
Normal file
@@ -0,0 +1 @@
|
||||
../../../src/application_wrapper/sources.list
|
||||
3
src/application_wrapper/application_wrapper_top.sv
Normal file
3
src/application_wrapper/application_wrapper_top.sv
Normal file
@@ -0,0 +1,3 @@
|
||||
module application_wrapper_top();
|
||||
|
||||
endmodule
|
||||
108
src/application_wrapper/cache/application_wrapper_cache_l1.sv
vendored
Normal file
108
src/application_wrapper/cache/application_wrapper_cache_l1.sv
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
import application_wrapper_cache_pkg::*;
|
||||
|
||||
module application_wrapper_cache_l1 #(
|
||||
parameter CACHELINE_SIZE = 64,
|
||||
parameter CACHELINE_COUNT = 64,
|
||||
localparam ADDR_WIDTH = 32
|
||||
)(
|
||||
input logic i_clk,
|
||||
input logic i_rst,
|
||||
|
||||
/* CPU Interface */
|
||||
input logic [ADDR_WIDTH-1:0] i_addr,
|
||||
input logic i_we,
|
||||
input logic [7:0] i_data,
|
||||
output logic [7:0] o_data,
|
||||
|
||||
input logic i_rdy,
|
||||
output logic o_rdy,
|
||||
|
||||
/* MMU Interface */
|
||||
input logic [ADDR_WIDTH-1:0] i_phys_address,
|
||||
output page_table_entry_t i_table_entry,
|
||||
input logic i_mmu_valid,
|
||||
|
||||
/* Higher level cache interface */
|
||||
output logic [ADDR_WIDTH-1:0] o_addr,
|
||||
output logic [1:0] o_cache_cmd,
|
||||
output logic o_cache_valid,
|
||||
|
||||
output logic [63:0] o_cache_data,
|
||||
input logic [31:0] i_cache_data,
|
||||
input logic i_cache_rdy
|
||||
);
|
||||
|
||||
// we have 32 bit addresses, 64 byte cache lines, and 64 total lines.
|
||||
// Thats 6 bit for offset, 6 bit for index, and 20 bit for cache.
|
||||
|
||||
// cache is virtually indexed, physically tagged
|
||||
|
||||
localparam OFFSET_W = $clog2(CACHELINE_SIZE);
|
||||
localparam INDEX_W = $clog2(CACHELINE_COUNT);
|
||||
localparam TAG_W = ADDR_WIDTH - INDEX_W - OFFSET_W;
|
||||
localparam META_W = 3; // valid, unique, clean
|
||||
|
||||
logic [OFFSET_W-1:0] offset;
|
||||
logic [INDEX_W-1:0] index;
|
||||
logic [TAG_W-1:0] tag;
|
||||
|
||||
assign offset = i_addr[OFFSET_W-1:0];
|
||||
assign index = i_addr[INDEX_W+OFFSET_W-1:OFFSET_W];
|
||||
assign tag = i_addr[INDEX_W+OFFSET_W+TAG_W-1:INDEX_W+OFFSET_W];
|
||||
|
||||
// cacheline size is in bytes, not bits
|
||||
// direct mapped cache, read one line so we have data ready if its a hit.
|
||||
logic [CACHELINE_SIZE*8-1:0] data_array [CACHELINE_COUNT];
|
||||
logic [META_W+TAG_W-1:0] meta_tag_array [CACHELINE_COUNT];
|
||||
|
||||
enum logic [1:0] {IDLE, READY, EVICT, READ} state, state_next;
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
state <= IDLE;
|
||||
end else begin
|
||||
state <= state_next;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
state_next = state;
|
||||
|
||||
o_rdy = '0;
|
||||
|
||||
case (state)
|
||||
IDLE: begin
|
||||
state_next = READY;
|
||||
end
|
||||
|
||||
READY: begin
|
||||
o_rdy = '1;
|
||||
end
|
||||
|
||||
EVICT: begin
|
||||
|
||||
end
|
||||
|
||||
READ: begin
|
||||
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
/*
|
||||
|
||||
In the ready state, we read from the data array and if the line is valid
|
||||
and the tag matches with the address, we present the data to the cpu.
|
||||
Otherwise, we lower o_rdy and send the request to the higher level cache.
|
||||
|
||||
If what we read was valid but the tag didn't match, then we need to evict it.
|
||||
If the line was not valid, then we don't need to evict it and can just request
|
||||
the new data.
|
||||
|
||||
One thing that we also need is an MMU. The TLB can be 1 cycle, then if the TLB
|
||||
says that we are allowed to read from the cache, we can read from the cache.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
13
src/application_wrapper/cache/application_wrapper_cache_pkg.sv
vendored
Normal file
13
src/application_wrapper/cache/application_wrapper_cache_pkg.sv
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package application_wrapper_cache_pkg;
|
||||
|
||||
typedef struct {
|
||||
logic cache_disable;
|
||||
logic read_eanble;
|
||||
logic write_enable;
|
||||
logic execute_enable;
|
||||
logic supervisor;
|
||||
logic present;
|
||||
logic write_through;
|
||||
} page_table_entry_t;
|
||||
|
||||
endpackage
|
||||
0
src/application_wrapper/cache/application_wrapper_cache_top.sv
vendored
Normal file
0
src/application_wrapper/cache/application_wrapper_cache_top.sv
vendored
Normal file
21
src/application_wrapper/cache/application_wrapper_mmu.sv
vendored
Normal file
21
src/application_wrapper/cache/application_wrapper_mmu.sv
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import application_wrapper_cache_pkg::*;
|
||||
|
||||
module application_wrapper_mmu #(
|
||||
parameter TLB_COUNT = 32,
|
||||
parameter ADDR_WIDTH = 32,
|
||||
parameter LOG2_PAGE_SIZE = 12
|
||||
) (
|
||||
input logic i_clk,
|
||||
input logic i_rst,
|
||||
|
||||
input logic [ADDR_WIDTH-1:0] i_cpu_addr,
|
||||
input i_we,
|
||||
input i_rdy,
|
||||
input o_rdy,
|
||||
|
||||
output logic [ADDR_WIDTH-1:0] o_phys_address,
|
||||
output page_table_entry_t o_table_entry,
|
||||
output logic o_mmu_valid
|
||||
);
|
||||
|
||||
endmodule
|
||||
6
src/application_wrapper/sources.list
Normal file
6
src/application_wrapper/sources.list
Normal file
@@ -0,0 +1,6 @@
|
||||
cache/application_wrapper_cache_pkg.sv
|
||||
cache/application_wrapper_cache_l1.sv
|
||||
cache/application_wrapper_mmu.sv
|
||||
cache/application_wrapper_cache_top.sv
|
||||
|
||||
application_wrapper_top.sv
|
||||
Reference in New Issue
Block a user