summaryrefslogtreecommitdiff
path: root/rtl/cache
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/cache')
-rw-r--r--rtl/cache/cache.sv26
-rw-r--r--rtl/cache/cache_control.sv152
-rw-r--r--rtl/cache/cache_debug.sv71
-rw-r--r--rtl/cache/defs.sv19
-rw-r--r--rtl/cache/monitor.sv103
5 files changed, 292 insertions, 79 deletions
diff --git a/rtl/cache/cache.sv b/rtl/cache/cache.sv
index 29403e2..6d5a204 100644
--- a/rtl/cache/cache.sv
+++ b/rtl/cache/cache.sv
@@ -16,13 +16,12 @@ module cache
output logic[1:0] core_response,
output word core_readdata,
- //TODO
- /*input TODO/ dbg_address,
+ input logic[2:0] dbg_address,
input logic dbg_read,
dbg_write,
input word dbg_writedata,
output logic dbg_waitrequest,
- output word dbg_readdata,*/
+ output word dbg_readdata,
input logic mem_waitrequest,
input line mem_readdata,
@@ -47,9 +46,6 @@ module cache
output logic out_token_valid
);
- //TODO
- //assign dbg_waitrequest = 1;
-
logic write_data, write_state;
line data_wr, data_rd;
addr_tag tag_wr, tag_rd;
@@ -63,7 +59,8 @@ module cache
word cache_mem_address;
line cache_mem_writedata;
- logic cache_core_waitrequest, cache_mem_waitrequest, cache_mem_read, cache_mem_write;
+ logic cache_core_waitrequest, cache_mem_waitrequest, cache_mem_read, cache_mem_write,
+ debug_ready;
cache_control #(.TOKEN_AT_RESET(TOKEN_AT_RESET)) control
(
@@ -97,4 +94,19 @@ module cache
.*
);
+ line monitor_update;
+ logic monitor_acquire, monitor_commit, monitor_fail, monitor_release;
+
+ cache_monitor monitor
+ (
+ .*
+ );
+
+ addr_index debug_index;
+
+ cache_debug debug
+ (
+ .*
+ );
+
endmodule
diff --git a/rtl/cache/cache_control.sv b/rtl/cache/cache_control.sv
index fb7896a..33d380a 100644
--- a/rtl/cache/cache_control.sv
+++ b/rtl/cache/cache_control.sv
@@ -3,51 +3,60 @@
module cache_control
#(parameter TOKEN_AT_RESET=0)
(
- input logic clk,
- rst_n,
+ input logic clk,
+ rst_n,
- input addr_tag core_tag,
- input addr_index core_index,
- input logic core_read,
- core_write,
- core_lock,
- input line core_data_wr,
- output logic core_waitrequest,
- output logic[1:0] core_response,
+ input addr_tag core_tag,
+ input addr_index core_index,
+ input logic core_read,
+ core_write,
+ core_lock,
+ input line core_data_wr,
+ output logic core_waitrequest,
- input ring_req in_data,
- input logic in_data_valid,
- output logic in_data_ready,
+ input ring_req in_data,
+ input logic in_data_valid,
+ output logic in_data_ready,
- input logic out_data_ready,
- output ring_req out_data,
- output logic out_data_valid,
+ input logic out_data_ready,
+ output ring_req out_data,
+ output logic out_data_valid,
- input ring_token in_token,
- input logic in_token_valid,
+ input ring_token in_token,
+ input logic in_token_valid,
- output ring_token out_token,
- output logic out_token_valid,
+ output ring_token out_token,
+ output logic out_token_valid,
// Señales para la SRAM
- input addr_tag tag_rd,
- input line data_rd,
- input line_state state_rd,
-
- output addr_index index_rd,
- index_wr,
- output logic write_data,
- write_state,
- output addr_tag tag_wr,
- output line data_wr,
- output line_state state_wr,
-
- input logic mem_waitrequest,
- input line mem_readdata,
- output word mem_address,
- output logic mem_read,
- mem_write,
- output line mem_writedata
+ input addr_tag tag_rd,
+ input line data_rd,
+ input line_state state_rd,
+
+ input line monitor_update,
+ input logic monitor_commit,
+ output logic monitor_acquire,
+ monitor_fail,
+ monitor_release,
+
+ output addr_index index_rd,
+ index_wr,
+ output logic write_data,
+ write_state,
+ output addr_tag tag_wr,
+ output line data_wr,
+ output line_state state_wr,
+
+ input logic mem_waitrequest,
+ input line mem_readdata,
+ output word mem_address,
+ output logic mem_read,
+ mem_write,
+ output line mem_writedata,
+
+ input logic dbg_write,
+ input addr_index debug_index,
+ output logic debug_ready
);
enum int unsigned
@@ -58,24 +67,15 @@ module cache_control
REPLY
} state, next_state;
- logic accept_snoop, end_reply, in_hold_valid, last_hop, lock_line, locked,
- may_send, may_send_if_token_held, mem_begin, mem_end, mem_read_end, mem_wait,
- monitor_acquire, monitor_commit, monitor_fail, out_stall, wait_reply, replace,
- retry, send, send_inval, send_read, snoop_hit, set_reply, unlock_line, writeback;
+ logic accept_snoop, debug, end_reply, in_hold_valid, last_hop, lock_line,
+ locked, may_send, may_send_if_token_held, mem_begin, mem_end, mem_read_end,
+ mem_wait, out_stall, wait_reply, replace, retry, send, send_inval,
+ send_read, snoop_hit, set_reply, unlock_line, writeback;
ring_req in_hold, send_data, fwd_data, stall_data, out_data_next;
- line monitor_data_rd, monitor_data_wr;
- addr_tag mem_tag, monitor_tag;
- addr_index mem_index, monitor_index;
-
- /* Avalon p. 15:
- * - 00: OKAY - Successful response for a transaction.
- * - 10: SLVERR - Error from an endpoint agent. Indicates an unsuccessful transaction.
- */
- assign core_response = {monitor_fail, 1'b0};
- assign monitor_commit = !core_lock || (monitor_tag == core_tag && monitor_index == core_index
- && monitor_data_rd == data_rd);
+ addr_tag mem_tag;
+ addr_index mem_index;
assign mem_end = (mem_read || mem_write) && !mem_waitrequest;
assign mem_wait = (mem_read || mem_write) && mem_waitrequest;
@@ -135,6 +135,7 @@ module cache_control
monitor_fail = 0;
monitor_acquire = 0;
+ monitor_release = 0;
core_waitrequest = 1;
in_data_ready = !in_hold_valid;
@@ -146,17 +147,19 @@ module cache_control
end_reply = in_hold_valid; // Se termina el paso de ese mensaje
in_data_ready = 1;
end
+
// Si no es el último salto y hay reply
- if (!last_hop && in_hold.reply)
+ if (!last_hop && in_hold.reply && !in_hold.inval)
in_data_ready = 1;
if (accept_snoop)
index_rd = in_hold.index;
+
+ if (debug)
+ index_rd = debug_index;
end
CORE: begin
- monitor_acquire = core_read && core_lock;
-
if (replace) begin
state_wr = INVALID;
write_state = 1;
@@ -175,8 +178,10 @@ module cache_control
send_inval = 1;
end
- {SHARED, 1'b0}:
+ {SHARED, 1'b0}: begin
+ monitor_acquire = core_lock;
core_waitrequest = 0;
+ end
{SHARED, 1'b1}: begin
/* No hacemos write_data ya que reintentaremos el
@@ -192,8 +197,10 @@ module cache_control
send_inval = 1;
end
- {EXCLUSIVE, 1'b0}:
+ {EXCLUSIVE, 1'b0}: begin
+ monitor_acquire = core_lock;
core_waitrequest = 0;
+ end
{EXCLUSIVE, 1'b1}: begin
state_wr = MODIFIED;
@@ -201,19 +208,28 @@ module cache_control
write_state = monitor_commit;
monitor_fail = !monitor_commit;
+ monitor_release = core_lock;
+
core_waitrequest = 0;
end
- {MODIFIED, 1'b0}:
+ {MODIFIED, 1'b0}: begin
+ monitor_acquire = core_lock;
core_waitrequest = 0;
+ end
{MODIFIED, 1'b1}: begin
write_data = monitor_commit;
monitor_fail = !monitor_commit;
+ monitor_release = core_lock;
+
core_waitrequest = 0;
end
endcase
+
+ if (monitor_release)
+ data_wr = monitor_update;
end
SNOOP: begin
@@ -286,6 +302,9 @@ module cache_control
write_data = 0;
write_state = 0;
+ monitor_acquire = 0;
+ monitor_release = 0;
+
in_data_ready = !in_hold_valid;
core_waitrequest = 1;
end
@@ -314,6 +333,7 @@ module cache_control
end
always_comb begin
+ debug = 0;
next_state = ACCEPT;
unique case (state)
@@ -322,6 +342,8 @@ module cache_control
next_state = SNOOP;
else if (in_hold_valid && last_hop && in_hold.read)
next_state = REPLY;
+ else if (dbg_write && !debug_ready)
+ debug = 1;
else if ((core_read || core_write) && !wait_reply && (!locked || may_send))
next_state = CORE;
@@ -349,6 +371,8 @@ module cache_control
mem_read <= 0;
mem_write <= 0;
+
+ debug_ready <= 0;
end else begin
out_token.e0.tag <= core_tag;
out_token.e0.index <= core_index;
@@ -384,6 +408,8 @@ module cache_control
mem_read <= !writeback;
mem_write <= writeback;
end
+
+ debug_ready <= debug;
end
always_ff @(posedge clk) begin
@@ -398,14 +424,6 @@ module cache_control
mem_index <= index_wr;
mem_writedata <= data_rd;
end
-
- if (monitor_acquire && !core_waitrequest) begin
- monitor_tag <= core_tag;
- monitor_index <= core_index;
-
- monitor_data_rd <= data_rd;
- monitor_data_wr <= data_rd;
- end
end
endmodule
diff --git a/rtl/cache/cache_debug.sv b/rtl/cache/cache_debug.sv
new file mode 100644
index 0000000..14b73e5
--- /dev/null
+++ b/rtl/cache/cache_debug.sv
@@ -0,0 +1,71 @@
+`include "cache/defs.sv"
+
+module cache_debug
+(
+ input logic clk,
+ rst_n,
+
+ input logic[2:0] dbg_address,
+ input logic dbg_read,
+ input word dbg_writedata,
+ output logic dbg_waitrequest,
+ output word dbg_readdata,
+
+ input logic debug_ready,
+ input addr_tag tag_rd,
+ input line data_rd,
+ input line_state state_rd,
+ output addr_index debug_index
+);
+
+ struct packed
+ {
+ logic[2:0] mbz_0;
+ addr_tag tag;
+ addr_index index;
+ line_state state;
+ logic cached,
+ mbz_1;
+ } status;
+
+ line line_dump;
+ word word_dump, word_3, word_2, word_1, word_0;
+ addr_bits debug_addr_bits;
+
+ logic cached;
+ addr_tag tag;
+ addr_index index;
+ line_state state;
+
+ assign debug_index = debug_addr_bits.index;
+ assign dbg_readdata = dbg_address[2] ? word_dump : status;
+ assign dbg_waitrequest = !debug_ready && !dbg_read;
+
+ assign status.tag = tag;
+ assign status.index = index;
+ assign status.state = state;
+ assign status.mbz_0 = 3'b000;
+ assign status.mbz_1 = 0;
+ assign status.cached = cached;
+ assign debug_addr_bits = dbg_writedata;
+
+ assign {word_3, word_2, word_1, word_0} = line_dump;
+
+ always_comb
+ unique case (dbg_address[1:0])
+ 2'b00: word_dump = word_0;
+ 2'b01: word_dump = word_1;
+ 2'b10: word_dump = word_2;
+ 2'b11: word_dump = word_3;
+ endcase
+
+ always @(posedge clk)
+ if (debug_ready) begin
+ tag <= tag_rd;
+ index <= debug_addr_bits.index;
+ state <= state_rd;
+ cached <= !(|debug_addr_bits.io);
+ line_dump <= data_rd;
+ end
+
+endmodule
diff --git a/rtl/cache/defs.sv b/rtl/cache/defs.sv
index e21e587..d7c43dc 100644
--- a/rtl/cache/defs.sv
+++ b/rtl/cache/defs.sv
@@ -13,21 +13,30 @@ typedef logic[31:0] word;
`endif
/* Tenemos 512MiB de SDRAM, el resto del espacio es I/O (uncached). Usamos
- * 512 líneas direct-mapped de 16 bytes cada una. El core solo realiza
+ * 4096 líneas direct-mapped de 16 bytes cada una. El core solo realiza
* operaciones alineadas. Por tanto, cada dirección de 32 bits consta de:
* - 2 bits que siempre son 0 (traducidos a byteenable por core)
* - 2 bits de offset (ya que para cache la unidad direccionable es la word)
- * - 9 bits de index
- * - 16 bits de tag
+ * - 12 bits de index
+ * - 13 bits de tag
* - 3 bits que son == 0 si cached, != 0 si uncached
*/
typedef logic[1:0] addr_mbz;
typedef logic[1:0] addr_offset;
-typedef logic[8:0] addr_index;
-typedef logic[15:0] addr_tag;
+typedef logic[11:0] addr_index;
+typedef logic[12:0] addr_tag;
typedef logic[2:0] addr_io_region;
typedef logic[26:0] addr_cacheable;
+typedef struct packed
+{
+ addr_io_region io;
+ addr_tag tag;
+ addr_index index;
+ addr_offset offset;
+ addr_mbz mbz;
+} addr_bits;
+
typedef enum logic[1:0]
{
INVALID,
diff --git a/rtl/cache/monitor.sv b/rtl/cache/monitor.sv
new file mode 100644
index 0000000..b7f0d15
--- /dev/null
+++ b/rtl/cache/monitor.sv
@@ -0,0 +1,103 @@
+`include "cache/defs.sv"
+
+module cache_monitor
+(
+ input logic clk,
+ rst_n,
+
+ input addr_tag core_tag,
+ input addr_index core_index,
+ input addr_offset core_offset,
+ input logic core_lock,
+ input word core_writedata,
+ output logic[1:0] core_response,
+
+ input line data_rd,
+
+ input logic monitor_acquire,
+ monitor_fail,
+ monitor_release,
+ output line monitor_update,
+ output logic monitor_commit
+);
+
+ line monitor_rd, monitor_wr;
+ word update_3, update_2, update_1, update_0;
+ logic dirty, done, hit, known;
+ addr_tag tag;
+ addr_index index;
+
+ logic[3:0] mask, mask_clear, core_ex_mask;
+
+ assign monitor_commit = !core_lock || (hit && known && done);
+ assign monitor_update = {update_3, update_2, update_1, update_0};
+
+ /* Avalon p. 15:
+ * - 00: OKAY - Successful response for a transaction.
+ * - 10: SLVERR - Error from an endpoint agent. Indicates an unsuccessful transaction.
+ */
+ assign core_response = {monitor_fail, 1'b0};
+
+ assign hit = tag == core_tag && index == core_index;
+ assign done = monitor_rd == data_rd && mask_clear == 4'b0000;
+ assign known = mask[core_offset];
+ assign mask_clear = mask & ~core_ex_mask;
+
+ always_comb begin
+ {update_3, update_2, update_1, update_0} = monitor_wr;
+
+ unique case (core_offset)
+ 2'b00: begin
+ update_0 = core_writedata;
+ core_ex_mask = 4'b0001;
+ end
+
+ 2'b01: begin
+ update_1 = core_writedata;
+ core_ex_mask = 4'b0010;
+ end
+
+ 2'b10: begin
+ update_2 = core_writedata;
+ core_ex_mask = 4'b0100;
+ end
+
+ 2'b11: begin
+ update_3 = core_writedata;
+ core_ex_mask = 4'b1000;
+ end
+ endcase
+ end
+
+ always @(posedge clk or negedge rst_n)
+ if (!rst_n) begin
+ mask <= 4'b0000;
+ dirty <= 0;
+ end else begin
+ if (monitor_acquire) begin
+ mask <= hit && !known && !dirty ? mask | core_ex_mask : core_ex_mask;
+ dirty <= 0;
+ end
+
+ if (monitor_release) begin
+ mask <= hit && known ? mask_clear : 4'b0000;
+ dirty <= hit && known;
+ end
+ end
+
+ always_ff @(posedge clk) begin
+ if (monitor_acquire) begin
+ tag <= core_tag;
+ index <= core_index;
+
+ if (!hit || known || dirty || mask == 4'b0000) begin
+ monitor_rd <= data_rd;
+ monitor_wr <= data_rd;
+ end
+ end
+
+ if (monitor_release)
+ monitor_wr <= monitor_update;
+ end
+
+endmodule