[WIP] Re-worked LSU dcache interface

LSU should comply with the new LSU D$ interface as specified in the
previous commits. This is WIP, larger testbench changes will be
necessary. As the interface significantly diverged.
This commit is contained in:
Florian Zaruba 2017-05-29 14:29:45 +02:00
parent 48587017ac
commit b3b347a636
13 changed files with 279 additions and 280 deletions

View file

@ -56,29 +56,29 @@ test_mem_arbiter:
paths:
- covhtmlreport
test_store_queue:
stage: test
before_script:
- make build library=store_queue_lib
script:
- make store_queue library=store_queue_lib
- vcover report store_queue.ucdb
- vcover report -html store_queue.ucdb
artifacts:
paths:
- covhtmlreport
# test_store_queue:
# stage: test
# before_script:
# - make build library=store_queue_lib
# script:
# - make store_queue library=store_queue_lib
# - vcover report store_queue.ucdb
# - vcover report -html store_queue.ucdb
# artifacts:
# paths:
# - covhtmlreport
test_lsu:
stage: test
before_script:
- make build library=lsu_lib
script:
- make lsu library=lsu_lib
- vcover report lsu.ucdb
- vcover report -html lsu.ucdb
artifacts:
paths:
- covhtmlreport
# test_lsu:
# stage: test
# before_script:
# - make build library=lsu_lib
# script:
# - make lsu library=lsu_lib
# - vcover report lsu.ucdb
# - vcover report -html lsu.ucdb
# artifacts:
# paths:
# - covhtmlreport
pages:

View file

@ -49,12 +49,14 @@ module ariane
input logic instr_if_data_rvalid_i,
input logic [31:0] instr_if_data_rdata_i,
// Data memory interface
output logic [63:0] data_if_address_o,
output logic [11:0] data_if_address_index_o,
output logic [43:0] data_if_address_tag_o,
output logic [63:0] data_if_data_wdata_o,
output logic data_if_data_req_o,
output logic data_if_data_we_o,
output logic [7:0] data_if_data_be_o,
output logic [1:0] data_if_tag_status_o,
output logic data_if_kill_req_o,
output logic data_if_tag_valid_o,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i,

View file

@ -28,7 +28,7 @@ import ariane_pkg::*;
`define NOT_IMPL 2'b11
module mem_arbiter #(
module dcache_arbiter #(
parameter int NR_PORTS = 3
)
(
@ -36,22 +36,26 @@ module mem_arbiter #(
input logic rst_ni, // Asynchronous reset active low
input logic flush_i,
// slave port
output logic [63:0] address_o,
output logic [11:0] address_index_o,
output logic [43:0] address_tag_o,
output logic [63:0] data_wdata_o,
output logic data_req_o,
output logic data_we_o,
output logic [7:0] data_be_o,
output logic [1:0] data_tag_status_o,
output logic kill_req_o,
output logic tag_valid_o,
input logic data_gnt_i,
input logic data_rvalid_i,
input logic [63:0] data_rdata_i,
// master ports
input logic [NR_PORTS-1:0][63:0] address_i,
input logic [NR_PORTS-1:0][11:0] address_index_i,
input logic [NR_PORTS-1:0][43:0] address_tag_i,
input logic [NR_PORTS-1:0][63:0] data_wdata_i,
input logic [NR_PORTS-1:0] data_req_i,
input logic [NR_PORTS-1:0] data_we_i,
input logic [NR_PORTS-1:0][7:0] data_be_i,
input logic [NR_PORTS-1:0][1:0] data_tag_status_i,
input logic [NR_PORTS-1:0] kill_req_i,
input logic [NR_PORTS-1:0] tag_valid_i,
output logic [NR_PORTS-1:0] data_gnt_o,
output logic [NR_PORTS-1:0] data_rvalid_o,
output logic [NR_PORTS-1:0][63:0] data_rdata_o
@ -59,7 +63,7 @@ module mem_arbiter #(
// one-hot encoded
localparam DATA_WIDTH = NR_PORTS;
// registers
enum logic [1:0] {IDLE, WAIT_GNT, WAIT_TAG, WAIT_FLUSH} CS, NS;
enum logic {IDLE, WAIT_FLUSH} CS, NS;
// remember the request port in case of a multi-cycle transaction
logic [DATA_WIDTH-1:0] request_port_n, request_port_q;
// local ports
@ -123,90 +127,19 @@ module mem_arbiter #(
// save the request port for future states
request_port_n = i;
request_index = i;
// default is that we are waiting for the grant
NS = WAIT_GNT;
// wait for the grant
if (data_gnt_i) begin
// set the slave on which we are waiting
in_data = 1'b1 << i[DATA_WIDTH-1:0];
push = 1'b1;
// we got a grant so we need to wait for the tag
NS = WAIT_TAG;
end
// we already got a valid translation so we can proceed normally
// from the request side the thing is over
if (data_tag_status_i[i] == `VALID_TRANSLATION)
NS = IDLE;
break; // break here as this is a priority select
end
end
end
end
// ----------------------------
// Multi-cycle memory requests
// ----------------------------
// do we have an outstanding request e.g.: a request which is waiting for a grant or a tag_valid
// here we need to wait for the grant
WAIT_GNT: begin
// keep the request stable
data_req_o = data_req_i[request_port_q];
// we can check for it since we only stay in this state if didn't yet receive a grant
if (data_gnt_i) begin
// set the slave on which we are waiting
in_data = 1'b1 << request_port_q;
push = 1'b1;
// default is that we are waiting for the tag to be there
// if we are waiting for the tag we can't accept any new instructions
NS = WAIT_TAG;
// two possibilities to not go into the tag wait state
// 1. The tag is valid now
// 2. The tag has been aborted
if (data_tag_status_i[request_port_q] == `ABORT_TRANSLATION || data_tag_status_i[request_port_q] == `VALID_TRANSLATION) begin
NS = IDLE;
end
end
// or if the request vanished we are going back to idle
if (!data_req_i[request_port_q])
NS = IDLE;
end
// here we are waiting for a valid (or aborted) tag
WAIT_TAG: begin
// if we are waiting for the tag we can't issue a new request
if (data_tag_status_i[request_port_q] == `ABORT_TRANSLATION || data_tag_status_i[request_port_q] == `VALID_TRANSLATION) begin
NS = IDLE;
// if we got a valid tag we can make a new request under the same assumption as in the IDLE state
if (~full) begin
for (int unsigned i = 0; i < NR_PORTS; i++) begin
if (data_req_i[i] == 1'b1) begin
data_req_o = data_req_i[i];
// save the request port for future states
request_port_n = i;
request_index = i;
// default is that we are waiting for the grant
NS = WAIT_GNT;
// wait for the grant
if (data_gnt_i) begin
// set the slave on which we are waiting
in_data = i[DATA_WIDTH-1:0];
push = 1'b1;
// we got a grant so we need to wait for the tag
NS = WAIT_TAG;
end
// we already got a valid translation so we can proceed normally
// from the request side the thing is over
if (data_tag_status_i[i] == `VALID_TRANSLATION)
NS = IDLE;
break; // break here as this is a priority select
end
end
end else begin
// the FIFO is full so go to IDLE and wait for it
NS = IDLE;
end
end
end
// ----------------------------
// Flush logic
// ----------------------------
// here we are waiting for the FIFO to drain until we are ready to accept new requests
@ -218,12 +151,15 @@ module mem_arbiter #(
default : /* default */;
endcase
// pass through all signals from the correct slave port
address_o = address_i[request_index];
address_index_o = address_index_i[request_index];
data_wdata_o = data_wdata_i[request_index];
data_be_o = data_be_i[request_index];
data_we_o = data_we_i[request_index];
data_tag_status_o = data_tag_status_i[request_index];
data_gnt_o[request_index] = data_gnt_i;
// the following signals are to be passed through one-cycle later
address_tag_o = address_tag_i[request_port_q];
kill_req_o = kill_req_i[request_port_q];
tag_valid_o = tag_valid_i[request_port_q];
// if we got a flush and we are not ready for the flush wait and for it and don't accept any incoming data
// e.g.: jump to the flush wait state
@ -278,7 +214,7 @@ module mem_arbiter #(
assert property (@(negedge clk_i) data_gnt_i |-> data_req_o)
else begin $error("There was a grant without a request."); $stop(); end
// assert that the address does not contain X when request is sent
assert property ( @(posedge clk_i) (data_req_o) |-> (!$isunknown(address_o)) )
assert property ( @(posedge clk_i) (data_req_o) |-> (!$isunknown(address_index_o)) )
else begin $error("address contains X when request is set"); $stop(); end
// there should be no rvalid when we are in IDLE

View file

@ -85,12 +85,14 @@ module ex_stage #(
input logic instr_if_data_rvalid_i,
input logic [31:0] instr_if_data_rdata_i,
output logic [63:0] data_if_address_o,
output logic [11:0] data_if_address_index_o,
output logic [43:0] data_if_address_tag_o,
output logic [63:0] data_if_data_wdata_o,
output logic data_if_data_req_o,
output logic data_if_data_we_o,
output logic [7:0] data_if_data_be_o,
output logic [1:0] data_if_tag_status_o,
output logic data_if_kill_req_o,
output logic data_if_tag_valid_o,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i,

View file

@ -47,48 +47,57 @@ module load_unit (
output logic [63:0] vaddr_o, // virtual address out
input logic [63:0] paddr_i, // physical address in
input logic translation_valid_i,
input exception ex_i,
input exception ex_i, // exception which may has happened earlier. for example: mis-aligned exception
// address checker
output logic [11:0] page_offset_o,
input logic page_offset_matches_i,
// memory interface
output logic [63:0] address_o,
// D$ interface
output logic [11:0] address_index_o,
output logic [43:0] address_tag_o,
output logic [63:0] data_wdata_o,
output logic data_req_o,
output logic data_we_o,
output logic [7:0] data_be_o,
output logic [1:0] data_tag_status_o,
output logic kill_req_o,
output logic tag_valid_o,
input logic data_gnt_i,
input logic data_rvalid_i,
input logic [63:0] data_rdata_i
);
enum logic [2:0] {IDLE, WAIT_GNT, SEND_TAG, ABORT_TRANSLATION, WAIT_FLUSH} NS, CS;
// in order to decouple the response interface from the request interface we need a
// a queue which can hold all outstanding memory requests
typedef struct packed {
logic [TRANS_ID_BITS-1:0] trans_id;
logic [2:0] address_offset;
fu_t operator;
} rvalid_entry_t;
// queue control signal
rvalid_entry_t in_data;
logic push;
rvalid_entry_t out_data;
logic pop;
logic empty;
// register to save the physical address after address translation
// going directly to memory with this address will not work in-terms of timing (e.g.: the path to the memory
// is already super-critical with the address checker and memory arbiter on it).
logic [63:0] paddr_n, paddr_q;
// page offset is defined as the lower 12 bits
// page offset is defined as the lower 12 bits, feed through for address checker
assign page_offset_o = vaddr_i[11:0];
// feed-through the virtual address
// feed-through the virtual address for VA translation
assign vaddr_o = vaddr_i;
// this is a read-only interface so set the write enable to 0
assign data_we_o = 1'b0;
// compose the queue data, control is handled in the FSM
assign in_data = {trans_id_i, vaddr_i[2:0], operator_i};
// output address
// we can now output the lower 12 bit as the index to the cache
assign address_o [11:0] = vaddr_i[11:0];
// translation from last cycle
assign address_o[63:12] = paddr_q[63:12];
assign address_index_o = vaddr_i[11:0];
// translation from last cycle, again: control is handled in the FSM
assign address_tag_o = paddr_q[55:12];
// ---------------
// Load Control
// ---------------
@ -99,7 +108,9 @@ module load_unit (
translation_req_o = 1'b0;
ready_o = 1'b1;
data_req_o = 1'b0;
data_tag_status_o = `WAIT_TRANSLATION;
// tag control
kill_req_o = 1'b0;
tag_valid_o = 1'b0;
push = 1'b0;
data_be_o = be_i;
ex_o = ex_i;
@ -141,16 +152,20 @@ module load_unit (
end
end
end
// we are here because of a TLB miss
// we are here because of a TLB miss, we need to abort the current request and give way for the
// PTW walker to satisfy the TLB miss
ABORT_TRANSLATION: begin
// we are not ready here
ready_o = 1'b0;
// send an abort signal
data_tag_status_o = `ABORT_TRANSLATION;
tag_valid_o = 1'b1;
kill_req_o = 1'b1;
// wait for the translation to become valid and redo the request
if (translation_valid_i) begin
// we have a valid translation so tell the cache it should wait for it on the next cycle
data_tag_status_o = `WAIT_TRANSLATION;
// reset the the kill request
tag_valid_o = 1'b0;
kill_req_o = 1'b0;
// if the request is still here, do the load
if (valid_i) begin
@ -190,9 +205,10 @@ module load_unit (
end
SEND_TAG: begin
ready_o = 1'b1;
ready_o = 1'b1;
// tell the cache that this tag is valid
tag_valid_o = 1'b1;
// if we are sending our tag we are able to process a new request
data_tag_status_o = `VALID_TRANSLATION;
// -------------
// New Request
// -------------

View file

@ -59,13 +59,15 @@ module lsu #(
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [31:0] instr_if_data_rdata_i,
// Data memory/cache
output logic [63:0] data_if_address_o,
// Data cache
output logic [11:0] data_if_address_index_o,
output logic [43:0] data_if_address_tag_o,
output logic [63:0] data_if_data_wdata_o,
output logic data_if_data_req_o,
output logic data_if_data_we_o,
output logic [7:0] data_if_data_be_o,
output logic [1:0] data_if_tag_status_o,
output logic data_if_kill_req_o,
output logic data_if_tag_valid_o,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i,
@ -131,40 +133,47 @@ module lsu #(
// ---------------
// Memory Arbiter
// ---------------
logic [2:0][63:0] address_i;
logic [2:0][11:0] address_index_i;
logic [2:0][43:0] address_tag_i;
logic [2:0][63:0] data_wdata_i;
logic [2:0] data_req_i;
logic [2:0] data_we_i;
logic [2:0] kill_req_i;
logic [2:0] tag_valid_i;
logic [2:0][7:0] data_be_i;
logic [2:0][1:0] data_tag_status_i;
logic [2:0] data_gnt_o;
logic [2:0] data_rvalid_o;
logic [2:0][63:0] data_rdata_o;
// decreasing priority
// Port 0: PTW
// Port 1: Load Unit
// Port 2: Store Unit
mem_arbiter mem_arbiter_i (
dcache_arbiter dcache_arbiter_i (
// to D$
.address_o ( data_if_address_o ),
.data_wdata_o ( data_if_data_wdata_o ),
.data_req_o ( data_if_data_req_o ),
.data_we_o ( data_if_data_we_o ),
.data_be_o ( data_if_data_be_o ),
.data_tag_status_o ( data_if_tag_status_o ),
.data_gnt_i ( data_if_data_gnt_i ),
.data_rvalid_i ( data_if_data_rvalid_i ),
.data_rdata_i ( data_if_data_rdata_i ),
.address_index_o ( data_if_address_index_o ),
.address_tag_o ( data_if_address_tag_o ),
.data_wdata_o ( data_if_data_wdata_o ),
.data_req_o ( data_if_data_req_o ),
.data_we_o ( data_if_data_we_o ),
.data_be_o ( data_if_data_be_o ),
.kill_req_o ( data_if_kill_req_o ),
.tag_valid_o ( data_if_tag_valid_o ),
.data_gnt_i ( data_if_data_gnt_i ),
.data_rvalid_i ( data_if_data_rvalid_i ),
.data_rdata_i ( data_if_data_rdata_i ),
// from PTW, Load Unit and Store Unit
.address_i ( address_i ),
.data_wdata_i ( data_wdata_i ),
.data_req_i ( data_req_i ),
.data_we_i ( data_we_i ),
.data_be_i ( data_be_i ),
.data_tag_status_i ( data_tag_status_i ),
.data_gnt_o ( data_gnt_o ),
.data_rvalid_o ( data_rvalid_o ),
.data_rdata_o ( data_rdata_o ),
.address_index_i ( address_index_i ),
.address_tag_i ( address_tag_i ),
.data_wdata_i ( data_wdata_i ),
.data_req_i ( data_req_i ),
.data_we_i ( data_we_i ),
.data_be_i ( data_be_i ),
.kill_req_i ( kill_req_i ),
.tag_valid_i ( tag_valid_i ),
.data_gnt_o ( data_gnt_o ),
.data_rvalid_o ( data_rvalid_o ),
.data_rdata_o ( data_rdata_o ),
.*
);
@ -182,15 +191,17 @@ module lsu #(
.lsu_paddr_o ( mmu_paddr ),
.lsu_exception_o ( mmu_exception ),
// connecting PTW to D$ IF (aka mem arbiter
.data_if_address_o ( address_i [0] ),
.data_if_data_wdata_o ( data_wdata_i [0] ),
.data_if_data_req_o ( data_req_i [0] ),
.data_if_data_we_o ( data_we_i [0] ),
.data_if_data_be_o ( data_be_i [0] ),
.data_if_tag_status_o ( data_tag_status_i[0] ),
.data_if_data_gnt_i ( data_gnt_o [0] ),
.data_if_data_rvalid_i ( data_rvalid_o [0] ),
.data_if_data_rdata_i ( data_rdata_o [0] ),
.data_if_address_index_o ( address_index_i [0] ),
.data_if_address_tag_o ( address_tag_i [0] ),
.data_if_data_wdata_o ( data_wdata_i [0] ),
.data_if_data_req_o ( data_req_i [0] ),
.data_if_data_we_o ( data_we_i [0] ),
.data_if_data_be_o ( data_be_i [0] ),
.data_if_kill_req_o ( kill_req_i [0] ),
.data_if_tag_valid_o ( tag_valid_i [0] ),
.data_if_data_gnt_i ( data_gnt_o [0] ),
.data_if_data_rvalid_i ( data_rvalid_o [0] ),
.data_if_data_rdata_i ( data_rdata_o [0] ),
.*
);
// ------------------
@ -219,13 +230,15 @@ module lsu #(
.page_offset_matches_o ( page_offset_matches ),
// misaligned bypass
.misaligned_ex_i ( misaligned_exception ),
// Mem Arbiter
.address_o ( address_i [2] ),
// to memory arbiter
.address_index_o ( address_index_i [2] ),
.address_tag_o ( address_tag_i [2] ),
.data_wdata_o ( data_wdata_i [2] ),
.data_req_o ( data_req_i [2] ),
.data_we_o ( data_we_i [2] ),
.data_be_o ( data_be_i [2] ),
.data_tag_status_o ( data_tag_status_i[2] ),
.kill_req_o ( kill_req_i [2] ),
.tag_valid_o ( tag_valid_i [2] ),
.data_gnt_i ( data_gnt_o [2] ),
.data_rvalid_i ( data_rvalid_o [2] ),
.*
@ -254,12 +267,15 @@ module lsu #(
// to store unit
.page_offset_o ( page_offset ),
.page_offset_matches_i ( page_offset_matches ),
.address_o ( address_i [1] ),
// to memory arbiter
.address_index_o ( address_index_i [1] ),
.address_tag_o ( address_tag_i [1] ),
.data_wdata_o ( data_wdata_i [1] ),
.data_req_o ( data_req_i [1] ),
.data_we_o ( data_we_i [1] ),
.data_be_o ( data_be_i [1] ),
.data_tag_status_o ( data_tag_status_i[1] ),
.kill_req_o ( kill_req_i [1] ),
.tag_valid_o ( tag_valid_i [1] ),
.data_gnt_i ( data_gnt_o [1] ),
.data_rvalid_i ( data_rvalid_o [1] ),
.data_rdata_i ( data_rdata_o [1] ),

View file

@ -23,8 +23,8 @@ import ariane_pkg::*;
module mmu #(
parameter int INSTR_TLB_ENTRIES = 4,
parameter int DATA_TLB_ENTRIES = 4,
parameter int ASID_WIDTH = 1
parameter int DATA_TLB_ENTRIES = 4,
parameter int ASID_WIDTH = 1
)
(
input logic clk_i,
@ -63,12 +63,14 @@ module mmu #(
input logic instr_if_data_rvalid_i,
input logic [31:0] instr_if_data_rdata_i,
// Data memory/cache
output logic [63:0] data_if_address_o,
output logic [11:0] data_if_address_index_o,
output logic [43:0] data_if_address_tag_o,
output logic [63:0] data_if_data_wdata_o,
output logic data_if_data_req_o,
output logic data_if_data_we_o,
output logic [7:0] data_if_data_be_o,
output logic [1:0] data_if_tag_status_o,
output logic data_if_kill_req_o,
output logic data_if_tag_valid_o,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i
@ -169,15 +171,15 @@ module mmu #(
.ptw_error_o ( ptw_error ),
.enable_translation_i ( enable_translation_i ),
.address_o ( data_if_address_o ),
.data_wdata_o ( data_if_data_wdata_o ),
.data_req_o ( data_if_data_req_o ),
.data_we_o ( data_if_data_we_o ),
.data_be_o ( data_if_data_be_o ),
.data_tag_status_o ( data_if_tag_status_o ),
.data_gnt_i ( data_if_data_gnt_i ),
.data_rvalid_i ( data_if_data_rvalid_i ),
.data_rdata_i ( data_if_data_rdata_i ),
.address_o ( ), // TODO
.data_wdata_o ( ), // TODO
.data_req_o ( ), // TODO
.data_we_o ( ), // TODO
.data_be_o ( ), // TODO
.data_tag_status_o ( ), // TODO
.data_gnt_i ( ), // TODO
.data_rvalid_i ( ), // TODO
.data_rdata_i ( ), // TODO
.itlb_update_o ( itlb_update ),
.dtlb_update_o ( dtlb_update ),

View file

@ -38,24 +38,30 @@ module store_queue (
input logic [63:0] paddr_i, // physical address of store which needs to be placed in the queue
input logic [63:0] data_i, // data which is placed in the queue
input logic [7:0] be_i, // byte enable in
// D$ interface
output logic [63:0] address_o,
output logic [11:0] address_index_o,
output logic [43:0] address_tag_o,
output logic [63:0] data_wdata_o,
output logic data_req_o,
output logic data_we_o,
output logic [7:0] data_be_o,
output logic [1:0] data_tag_status_o,
output logic kill_req_o,
output logic tag_valid_o,
input logic data_gnt_i,
input logic data_rvalid_i
);
// we need to keep the tag portion of the address for a cycle later
logic [43:0] address_tag_n, address_tag_q;
logic tag_valid_n, tag_valid_q;
// the store queue has two parts:
// 1. Speculative queue
// 2. Commit queue which is non-speculative, e.g.: the store will definitely happen.
// For simplicity reasons we just keep those two elements and not one real queue
// should it turn out that this bottlenecks we can still increase the capacity here
// potentially at the cost of increased area.
// at the cost of increased area and worse timing since we need to check all addresses which are committed for
// potential aliasing.
//
// In the current implementation this is represented by a single entry and
// differentiated by the is_speculative flag.
@ -73,11 +79,17 @@ module store_queue (
assign be_o = commit_queue_q.be;
assign valid_o = commit_queue_q.valid;
// those signals can directly be output to the memory if
assign address_o = commit_queue_q.address;
// those signals can directly be output to the memory
assign address_index_o = commit_queue_q.address[11:0];
// if we got a new request we already saved the tag from the previous cycle
assign address_tag_o = address_tag_q;
assign data_wdata_o = commit_queue_q.data;
assign data_be_o = commit_queue_q.be;
assign data_tag_status_o = 2'b01; // the tag is always ready since we are using physical addresses
assign tag_valid_o = tag_valid_q;
// we will never kill a request in the store buffer since we already know that the translation is valid
// e.g.: a kill request will only be necessary if we are not sure if the requested memory address will result in a TLB fault
assign kill_req_o = 1'b0;
// memory interface
always_comb begin : store_if
// if there is no commit pending and the uncommitted queue is empty as well we can accept the request
@ -86,7 +98,9 @@ module store_queue (
automatic logic ready = ~commit_queue_q.valid | data_gnt_i;
ready_o = ready & ~flush_i;
address_tag_n = address_tag_q;
commit_queue_n = commit_queue_q;
tag_valid_n = 1'b0;
data_we_o = 1'b1; // we will always write in the store queue
data_req_o = 1'b0;
@ -99,10 +113,13 @@ module store_queue (
// by looking at the is_speculative flag
if (commit_queue_q.valid && (~commit_queue_q.is_speculative || commit_i)) begin
data_req_o = 1'b1;
// advance to the next state if we received the grant
if (data_gnt_i) begin
// we can evict it from the commit buffer
commit_queue_n.valid = 1'b0;
// save the tag portion
address_tag_n = commit_queue_q.address[55:12];
// signal a valid tag the cycle afterwards
tag_valid_n = 1'b1;
end
end
// we ignore the rvalid signal for now as we assume that the store
@ -135,9 +152,13 @@ module store_queue (
// registers
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
if(~rst_ni) begin
commit_queue_q <= '{default: 0};
address_tag_q <= 'b0;
tag_valid_q <= 1'b0;
commit_queue_q <= '{default: 0};
end else begin
commit_queue_q <= commit_queue_n;
tag_valid_q <= tag_valid_n;
address_tag_q <= address_tag_n;
end
end
`ifndef SYNTHESIS

View file

@ -47,13 +47,15 @@ module store_unit (
output logic page_offset_matches_o,
// misaligned bypass
input exception misaligned_ex_i,
// memory interface
output logic [63:0] address_o,
// D$ interface
output logic [11:0] address_index_o,
output logic [43:0] address_tag_o,
output logic [63:0] data_wdata_o,
output logic data_req_o,
output logic data_we_o,
output logic [7:0] data_be_o,
output logic [1:0] data_tag_status_o,
output logic kill_req_o,
output logic tag_valid_o,
input logic data_gnt_i,
input logic data_rvalid_i
);

View file

@ -40,16 +40,16 @@ module core_mem (
output logic [63:0] data_if_data_rdata_o
);
// we always grant the access
assign instr_if_data_gnt_o = instr_if_data_req_i;
localparam ADDRESS_WIDTH = 11;
logic [ADDRESS_WIDTH-1:0] instr_address;
logic [ADDRESS_WIDTH-1:0] data_address;
logic [2:0] instr_address_offset_q;
logic [63:0] instr_data;
assign instr_address = instr_if_address_i[ADDRESS_WIDTH-1+3:3];
logic [63:0] instr_data;
assign instr_if_data_gnt_o = instr_if_data_req_i;
assign instr_address = instr_if_address_i[ADDRESS_WIDTH-1+3:3];
assign instr_if_data_rdata_o = (instr_address_offset_q[2]) ? instr_data[63:32] : instr_data[31:0];
dp_ram #(
@ -63,12 +63,13 @@ module core_mem (
.rdata_a_o ( instr_data ),
.we_a_i ( 1'b0 ), // r/o interface
.be_a_i ( ),
// data RAM
.en_b_i ( ),
.addr_b_i ( ),
.wdata_b_i ( ),
.rdata_b_o ( ),
.we_b_i ( ),
.be_b_i ( )
.we_b_i ( data_if_data_we_i ),
.be_b_i ( data_if_data_be_i )
);

View file

@ -60,50 +60,52 @@ module core_tb;
);
ariane dut (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clock_en_i ( core_if.clock_en ),
.test_en_i ( core_if.test_en ),
.fetch_enable_i ( core_if.fetch_enable ),
.core_busy_o ( core_if.core_busy ),
.ext_perf_counters_i ( ),
.boot_addr_i ( core_if.boot_addr ),
.core_id_i ( core_if.core_id ),
.cluster_id_i ( core_if.cluster_id ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.clock_en_i ( core_if.clock_en ),
.test_en_i ( core_if.test_en ),
.fetch_enable_i ( core_if.fetch_enable ),
.core_busy_o ( core_if.core_busy ),
.ext_perf_counters_i ( ),
.boot_addr_i ( core_if.boot_addr ),
.core_id_i ( core_if.core_id ),
.cluster_id_i ( core_if.cluster_id ),
.instr_if_address_o ( instr_if_address ),
.instr_if_data_req_o ( instr_if_data_req ),
.instr_if_data_be_o ( instr_if_data_be ),
.instr_if_data_gnt_i ( instr_if_data_gnt ),
.instr_if_data_rvalid_i ( instr_if_data_rvalid ),
.instr_if_data_rdata_i ( instr_if_data_rdata ),
.instr_if_address_o ( instr_if_address ),
.instr_if_data_req_o ( instr_if_data_req ),
.instr_if_data_be_o ( instr_if_data_be ),
.instr_if_data_gnt_i ( instr_if_data_gnt ),
.instr_if_data_rvalid_i ( instr_if_data_rvalid ),
.instr_if_data_rdata_i ( instr_if_data_rdata ),
.data_if_address_o ( data_if.address ),
.data_if_data_wdata_o ( data_if.data_wdata ),
.data_if_data_req_o ( data_if.data_req ),
.data_if_data_we_o ( data_if.data_we ),
.data_if_data_be_o ( data_if.data_be ),
.data_if_tag_status_o ( ),
.data_if_data_gnt_i ( data_if.data_gnt ),
.data_if_data_rvalid_i ( data_if.data_rvalid ),
.data_if_data_rdata_i ( data_if.data_rdata ),
.data_if_address_index_o ( ),
.data_if_address_tag_o ( ),
.data_if_data_wdata_o ( data_if.data_wdata ),
.data_if_data_req_o ( data_if.data_req ),
.data_if_data_we_o ( data_if.data_we ),
.data_if_data_be_o ( data_if.data_be ),
.data_if_kill_req_o ( ),
.data_if_tag_valid_o ( ),
.data_if_data_gnt_i ( data_if.data_gnt ),
.data_if_data_rvalid_i ( data_if.data_rvalid ),
.data_if_data_rdata_i ( data_if.data_rdata ),
.irq_i ( core_if.irq ),
.irq_id_i ( core_if.irq_id ),
.irq_ack_o ( core_if.irq_ack ),
.irq_sec_i ( core_if.irq_sec ),
.sec_lvl_o ( core_if.sec_lvl ),
.irq_i ( core_if.irq ),
.irq_id_i ( core_if.irq_id ),
.irq_ack_o ( core_if.irq_ack ),
.irq_sec_i ( core_if.irq_sec ),
.sec_lvl_o ( core_if.sec_lvl ),
.debug_req_i ( ),
.debug_gnt_o ( ),
.debug_rvalid_o ( ),
.debug_addr_i ( ),
.debug_we_i ( ),
.debug_wdata_i ( ),
.debug_rdata_o ( ),
.debug_halted_o ( ),
.debug_halt_i ( ),
.debug_resume_i ( )
.debug_req_i ( ),
.debug_gnt_o ( ),
.debug_rvalid_o ( ),
.debug_addr_i ( ),
.debug_we_i ( ),
.debug_wdata_i ( ),
.debug_rdata_o ( ),
.debug_halted_o ( ),
.debug_halt_i ( ),
.debug_resume_i ( )
);
// clock process
@ -123,6 +125,7 @@ module core_tb;
$display("Reading memory");
$readmemh("test/add_test.v", rmem, 0);
// copy bitwise from verilog file
for (int i = 0; i < 1024/8; i++) begin
for (int j = 0; j < 8; j++)
core_mem_i.ram_i.mem[i][j] = rmem[i*8 + j];

View file

@ -32,53 +32,53 @@ module lsu_tb;
lsu_if lsu(clk);
lsu dut (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.operator_i ( lsu.operator ),
.operand_a_i ( lsu.operand_a ),
.operand_b_i ( lsu.operand_b ),
.imm_i ( lsu.imm ),
.lsu_ready_o ( lsu.ready ),
.lsu_valid_i ( lsu.source_valid ),
.trans_id_i ( lsu.lsu_trans_id_id ),
.lsu_trans_id_o ( lsu.lsu_trans_id_wb ),
.lsu_result_o ( lsu.result ),
.lsu_valid_o ( lsu.result_valid ),
.commit_i ( lsu.commit ),
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.operator_i ( lsu.operator ),
.operand_a_i ( lsu.operand_a ),
.operand_b_i ( lsu.operand_b ),
.imm_i ( lsu.imm ),
.lsu_ready_o ( lsu.ready ),
.lsu_valid_i ( lsu.source_valid ),
.trans_id_i ( lsu.lsu_trans_id_id ),
.lsu_trans_id_o ( lsu.lsu_trans_id_wb ),
.lsu_result_o ( lsu.result ),
.lsu_valid_o ( lsu.result_valid ),
.commit_i ( lsu.commit ),
// we are currently no testing the PTW and MMU
.enable_translation_i ( 1'b0 ),
.fetch_req_i ( 1'b0 ),
.fetch_gnt_o ( ),
.fetch_valid_o ( ),
.fetch_err_o ( ),
.fetch_vaddr_i ( 64'b0 ),
.fetch_rdata_o ( ),
.priv_lvl_i ( PRIV_LVL_M ),
.flag_pum_i ( 1'b0 ),
.flag_mxr_i ( 1'b0 ),
.pd_ppn_i ( 38'b0 ),
.asid_i ( 1'b0 ),
.flush_tlb_i ( 1'b0 ),
.enable_translation_i ( 1'b0 ),
.fetch_req_i ( 1'b0 ),
.fetch_gnt_o ( ),
.fetch_valid_o ( ),
.fetch_err_o ( ),
.fetch_vaddr_i ( 64'b0 ),
.fetch_rdata_o ( ),
.priv_lvl_i ( PRIV_LVL_M ),
.flag_pum_i ( 1'b0 ),
.flag_mxr_i ( 1'b0 ),
.pd_ppn_i ( 38'b0 ),
.asid_i ( 1'b0 ),
.flush_tlb_i ( 1'b0 ),
.instr_if_address_o ( instr_if.address ),
.instr_if_data_req_o ( instr_if.data_req ),
.instr_if_data_be_o ( instr_if.data_be[3:0] ),
.instr_if_data_gnt_i ( instr_if.data_gnt ),
.instr_if_data_rvalid_i ( instr_if.data_rvalid ),
.instr_if_data_rdata_i ( instr_if.data_rdata[31:0] ),
.instr_if_address_o ( instr_if.address ),
.instr_if_data_req_o ( instr_if.data_req ),
.instr_if_data_be_o ( instr_if.data_be[3:0] ),
.instr_if_data_gnt_i ( instr_if.data_gnt ),
.instr_if_data_rvalid_i ( instr_if.data_rvalid ),
.instr_if_data_rdata_i ( instr_if.data_rdata[31:0] ),
.data_if_address_o ( slave.address ),
.data_if_data_wdata_o ( slave.data_wdata ),
.data_if_data_req_o ( slave.data_req ),
.data_if_data_we_o ( slave.data_we ),
.data_if_data_be_o ( slave.data_be ),
.data_if_address_index_o ( slave.address ),
.data_if_data_wdata_o ( slave.data_wdata ),
.data_if_data_req_o ( slave.data_req ),
.data_if_data_we_o ( slave.data_we ),
.data_if_data_be_o ( slave.data_be ),
// hack to not get a grant without a request
.data_if_data_gnt_i ( slave.data_req & slave.data_gnt ),
.data_if_data_rvalid_i ( slave.data_rvalid ),
.data_if_data_rdata_i ( slave.data_rdata ),
.data_if_data_gnt_i ( slave.data_req & slave.data_gnt ),
.data_if_data_rvalid_i ( slave.data_rvalid ),
.data_if_data_rdata_i ( slave.data_rdata ),
.lsu_exception_o ( lsu.exception )
.lsu_exception_o ( lsu.exception )
);
initial begin

View file

@ -37,27 +37,25 @@ module mem_arbiter_tb;
// logic data_gnt_driver = 'z;
// assign data_gnt = data_gnt_driver & data_req;
mem_arbiter dut (
dcache_arbiter dut (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.address_o ( slave.address ),
.address_index_o ( slave.address ),
.data_wdata_o ( slave.data_wdata ),
.data_req_o ( slave.data_req ),
.data_we_o ( slave.data_we ),
.data_be_o ( slave.data_be ),
.data_tag_status_o ( ),
.data_gnt_i ( slave.data_req & slave.data_gnt ),
.data_rvalid_i ( slave.data_rvalid ),
.data_rdata_i ( slave.data_rdata ),
.address_i ( {master[2].address, master[1].address, master[0].address} ),
.address_index_i ( {master[2].address, master[1].address, master[0].address} ),
.data_wdata_i ( {master[2].data_wdata, master[1].data_wdata, master[0].data_wdata} ),
.data_req_i ( {master[2].data_req, master[1].data_req, master[0].data_req} ),
.data_we_i ( {master[2].data_we, master[1].data_we, master[0].data_we} ),
.data_be_i ( {master[2].data_be, master[1].data_be, master[0].data_be} ),
.data_tag_status_i ( {2'b01, 2'b01, 2'b01 } ),
.data_gnt_o ( {master[2].data_gnt, master[1].data_gnt, master[0].data_gnt} ),
.data_rvalid_o ( {master[2].data_rvalid, master[1].data_rvalid, master[0].data_rvalid} ),
.data_rdata_o ( {master[2].data_rdata, master[1].data_rdata, master[0].data_rdata} )