🎨 Remove memory interfaces in Ariane

This commit is contained in:
Florian Zaruba 2017-05-03 17:11:35 +02:00
parent 7e4b58d258
commit ba166ba645
8 changed files with 195 additions and 115 deletions

View file

@ -68,7 +68,7 @@ $(tests):
vopt${questa_version} ${compile_flag} $@_tb -o $@_tb_optimized +acc -check_synthesis
# vsim${questa_version} $@_tb_optimized
# vsim${questa_version} +UVM_TESTNAME=$@_test -coverage -classdebug $@_tb_optimized
vsim${questa_version} +UVM_TESTNAME=$@_test +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c -coverage -classdebug -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" $@_tb_optimized
# vsim${questa_version} +UVM_TESTNAME=$@_test +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c -coverage -classdebug -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" $@_tb_optimized
# User Verilator to lint the target
lint:

View file

@ -28,9 +28,21 @@ module ariane
input logic [ 3:0] core_id_i,
input logic [ 5:0] cluster_id_i,
// Instruction memory interface
mem_if.Slave instr_if,
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [7:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
// Data memory interface
mem_if.Slave data_if,
output logic [63:0] data_if_address_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,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i,
// Interrupt inputs
input logic irq_i, // level sensitive IR lines
input logic [4:0] irq_id_i,
@ -200,11 +212,10 @@ module ariane
.pd_ppn_i ( pd_ppn_i ), // from CSR
.asid_i ( asid_i ), // from CSR
.flush_tlb_i ( flush_tlb_i ),
.instr_if ( instr_if ),
.data_if ( data_if ),
.mult_ready_o ( mult_ready_o ),
.mult_valid_i ( mult_valid_i )
.mult_valid_i ( mult_valid_i ),
.*
);
commit_stage commit_stage_i (

View file

@ -60,8 +60,22 @@ module ex_stage #(
input logic [37:0] pd_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic flush_tlb_i,
mem_if.Slave instr_if,
mem_if.Slave data_if,
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [7:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
output logic [63:0] data_if_address_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,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i,
// MULT
output logic mult_ready_o, // FU is ready

View file

@ -52,9 +52,22 @@ module lsu #(
input logic [37:0] pd_ppn_i, // From CSR register file
input logic [ASID_WIDTH-1:0] asid_i, // From CSR register file
input logic flush_tlb_i,
mem_if.slave instr_if, // Instruction memory/cache
mem_if.slave data_if, // Data memory/cache
// Instruction memory/cache
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [7:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
// Data memory/cache
output logic [63:0] data_if_address_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,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i,
output exception lsu_exception_o // to WB, signal exception status LD/ST exception
@ -119,37 +132,28 @@ module lsu #(
// port 0 PTW, port 1 loads, port 2 stores
mem_arbiter mem_arbiter_i (
// to D$
.address_o ( data_if.address ),
.data_wdata_o ( data_if.data_wdata ),
.data_req_o ( data_if.data_req ),
.data_we_o ( data_if.data_we ),
.data_be_o ( data_if.data_be ),
.data_gnt_i ( data_if.data_gnt ),
.data_rvalid_i ( data_if.data_rvalid ),
.data_rdata_i ( data_if.data_rdata ),
.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_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 logic and store queue
.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_gnt_o ( data_gnt_o ),
.data_rvalid_o ( data_rvalid_o ),
.data_rdata_o ( data_rdata_o ),
.flush_ready_o ( ), // TODO: connect, wait for flush to be valid
.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_gnt_o ( data_gnt_o ),
.data_rvalid_o ( data_rvalid_o ),
.data_rdata_o ( data_rdata_o ),
.flush_ready_o ( ), // TODO: connect, wait for flush to be valid
.*
);
// connecting PTW to D$ IF (aka mem arbiter)
assign address_i [0] = ptw_if.address;
assign data_wdata_i[0] = ptw_if.data_wdata;
assign data_req_i [0] = ptw_if.data_req;
assign data_we_i [0] = ptw_if.data_we;
assign data_be_i [0] = ptw_if.data_be;
assign ptw_if.data_rvalid = data_rvalid_o[0];
assign ptw_if.data_rdata = data_rdata_o[0];
// connect the load logic to the memory arbiter
assign address_i [1] = paddr_o;
// this is a read only interface
@ -171,7 +175,15 @@ module lsu #(
.lsu_vaddr_i ( vaddr ),
.lsu_valid_o ( translation_valid ),
.lsu_paddr_o ( paddr_o ),
.data_if ( ptw_if ),
// 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_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] ),
.*
);
@ -421,6 +433,7 @@ module lsu #(
// Byte Enable - TODO: Find a more beautiful way to accomplish this functionality
// ---------------
always_comb begin : byte_enable
be = 8'b0;
// we can generate the byte enable from the virtual address since the last
// 12 bit are the same anyway
// and we can always generate the byte enable from the address at hand

View file

@ -54,18 +54,30 @@ module mmu #(
input logic [ASID_WIDTH-1:0] asid_i,
input logic flush_tlb_i,
// Memory interfaces
// Instruction memory interface
mem_if.slave instr_if,
// Data memory interface
mem_if.slave data_if
// Instruction memory/cache
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [7:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
// Data memory/cache
output logic [63:0] data_if_address_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,
input logic data_if_data_gnt_i,
input logic data_if_data_rvalid_i,
input logic [63:0] data_if_data_rdata_i
);
// assignments necessary to use interfaces here
// only done for the few signals of the instruction interface
logic [63:0] fetch_paddr;
logic fetch_req;
assign instr_if.data_req = fetch_req;
assign instr_if.address = fetch_paddr;
assign fetch_rdata_o = instr_if.data_rdata;
assign instr_if_data_req_o = fetch_req;
assign instr_if_address_o = fetch_paddr;
assign fetch_rdata_o = instr_if_data_rdata_i;
// instruction error
logic ierr_valid_q, ierr_valid_n;
logic iaccess_err;
@ -143,40 +155,41 @@ module mmu #(
ptw #(
.ASID_WIDTH ( ASID_WIDTH )
.ASID_WIDTH ( ASID_WIDTH )
) ptw_i
(
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_tlb_i ),
.ptw_active_o ( ptw_active ),
.walking_instr_o ( walking_instr ),
.ptw_error_o ( ptw_error ),
.enable_translation_i ( enable_translation_i ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_tlb_i ),
.ptw_active_o ( ptw_active ),
.walking_instr_o ( walking_instr ),
.ptw_error_o ( ptw_error ),
.enable_translation_i ( enable_translation_i ),
.address_o ( data_if.address ),
.data_wdata_o ( data_if.data_wdata ),
.data_req_o ( data_if.data_req ),
.data_we_o ( data_if.data_we ),
.data_be_o ( data_if.data_be ),
.data_gnt_i ( data_if.data_gnt ),
.data_rvalid_i ( data_if.data_rvalid ),
.data_rdata_i ( data_if.data_rdata ),
.itlb_update_o ( itlb_update ),
.dtlb_update_o ( dtlb_update ),
.update_content_o ( update_content ),
.update_is_2M_o ( update_is_2M ),
.update_is_1G_o ( update_is_1G ),
.update_vpn_o ( update_vpn ),
.update_asid_o ( update_asid ),
.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_gnt_i ( data_if_data_gnt_i ),
.data_rvalid_i ( data_if_data_rvalid_i ),
.data_rdata_i ( data_if_data_rdata_i ),
.itlb_access_i ( itlb_lu_access ),
.itlb_miss_i ( ~itlb_lu_hit ),
.itlb_vaddr_i ( fetch_vaddr_i ),
.itlb_update_o ( itlb_update ),
.dtlb_update_o ( dtlb_update ),
.update_content_o ( update_content ),
.update_is_2M_o ( update_is_2M ),
.update_is_1G_o ( update_is_1G ),
.update_vpn_o ( update_vpn ),
.update_asid_o ( update_asid ),
.dtlb_access_i ( dtlb_lu_access ),
.dtlb_miss_i ( ~dtlb_lu_hit ),
.dtlb_vaddr_i ( lsu_vaddr_i ),
.itlb_access_i ( itlb_lu_access ),
.itlb_miss_i ( ~itlb_lu_hit ),
.itlb_vaddr_i ( fetch_vaddr_i ),
.dtlb_access_i ( dtlb_lu_access ),
.dtlb_miss_i ( ~dtlb_lu_hit ),
.dtlb_vaddr_i ( lsu_vaddr_i ),
.*
);
@ -193,10 +206,10 @@ module mmu #(
//-----------------------
always_comb begin : instr_interface
// MMU disabled: just pass through
automatic logic fetch_valid = instr_if.data_rvalid;
automatic logic fetch_valid = instr_if_data_rvalid_i;
fetch_req = fetch_req_i;
fetch_paddr = fetch_vaddr_i;
fetch_gnt_o = instr_if.data_gnt;
fetch_gnt_o = instr_if_data_gnt_i;
fetch_err_o = 1'b0;
ierr_valid_n = 1'b0;
@ -217,7 +230,7 @@ module mmu #(
fetch_paddr[29:12] = fetch_vaddr_i[29:12];
end
fetch_gnt_o = instr_if.data_gnt;
fetch_gnt_o = instr_if_data_gnt_i;
// TODO the following two ifs should be mutually exclusive
if (itlb_lu_hit) begin
@ -260,7 +273,7 @@ module mmu #(
// lsu_vaddr_i
// lsu_valid_o
// lsu_paddr_o
lsu_paddr_o = lsu_vaddr_i;
lsu_paddr_o = (enable_translation_i) ? dtlb_content : lsu_vaddr_i;
lsu_valid_o = lsu_req_i;
end

View file

@ -151,7 +151,7 @@ module tlb #(
// ... ... ... ...
// Just predefine which nodes will be set/cleared
// E.g. for a TLB with 8 entries, the for-loop is semantically
// following pseudecode:
// equivalent to the following pseudo-code:
// unique case (1'b1)
// lu_hit[7]: plru_tree_n[0, 2, 6] = {1, 1, 1};
// lu_hit[6]: plru_tree_n[0, 2, 6] = {1, 1, 0};
@ -167,7 +167,7 @@ module tlb #(
// we got a hit so update the pointer as it was least recently used
if (lu_hit[i] & lu_access_i) begin
// Set the nodes to the values we would expect
for (int unsigned lvl = 0; lvl < $clog2(TLB_ENTRIES); lvl += 1) begin
for (int unsigned lvl = 0; lvl < $clog2(TLB_ENTRIES); lvl++) begin
automatic int unsigned idx_base = $unsigned((2**lvl)-1);
// lvl0 <=> MSB, lvl1 <=> MSB-1, ...
automatic int unsigned shift = $clog2(TLB_ENTRIES) - lvl;
@ -179,7 +179,7 @@ module tlb #(
end
// Decode tree to write enable signals
// Next for-loop basically creates the following logic for e.g. an 8 entry
// TLB (note: pseudocode obviously):
// TLB (note: pseudo-code obviously):
// replace_en[7] = &plru_tree_q[ 6, 2, 0]; //plru_tree_q[0,2,6]=={1,1,1}
// replace_en[6] = &plru_tree_q[~6, 2, 0]; //plru_tree_q[0,2,6]=={1,1,0}
// replace_en[5] = &plru_tree_q[ 5,~2, 0]; //plru_tree_q[0,2,5]=={1,0,1}
@ -192,21 +192,21 @@ module tlb #(
// the corresponding bit of the entry's index, this is
// the next entry to replace.
for (int unsigned i = 0; i < TLB_ENTRIES; i += 1) begin
automatic logic en = 1'b1;
for (int unsigned lvl = 0; lvl < $clog2(TLB_ENTRIES); lvl += 1) begin
automatic int unsigned idx_base = $unsigned((2**lvl)-1);
// lvl0 <=> MSB, lvl1 <=> MSB-1, ...
automatic int unsigned shift = $clog2(TLB_ENTRIES) - lvl;
automatic logic en = 1'b1;
for (int unsigned lvl = 0; lvl < $clog2(TLB_ENTRIES); lvl++) begin
automatic int unsigned idx_base = $unsigned((2**lvl)-1);
// lvl0 <=> MSB, lvl1 <=> MSB-1, ...
automatic int unsigned shift = $clog2(TLB_ENTRIES) - lvl;
// en &= plru_tree_q[idx_base + (i>>shift)] == ((i >> (shift-1)) & 1'b1);
automatic int unsigned new_index = (i >> (shift-1)) & 32'b1;
if(new_index[0]) begin
en &= plru_tree_q[idx_base + (i>>shift)];
end else begin
en &= ~plru_tree_q[idx_base + (i>>shift)];
// en &= plru_tree_q[idx_base + (i>>shift)] == ((i >> (shift-1)) & 1'b1);
automatic int unsigned new_index = (i >> (shift-1)) & 32'b1;
if(new_index[0]) begin
en &= plru_tree_q[idx_base + (i>>shift)];
end else begin
en &= ~plru_tree_q[idx_base + (i>>shift)];
end
end
end
replace_en[i] = en;
replace_en[i] = en;
end
end

View file

@ -38,24 +38,39 @@ module core_tb;
assign irq_sec_i = 1'b0;
ariane dut (
.clk_i ( clk_i ),
.rst_n ( rst_ni ),
.clock_en_i ( clock_en_i ),
.test_en_i ( test_en_i ),
.fetch_enable_i ( fetch_enable_i ),
.core_busy_o ( core_busy_o ),
.ext_perf_counters_i ( ),
.boot_addr_i ( boot_addr_i ),
.core_id_i ( core_id_i ),
.cluster_id_i ( cluster_id_i ),
.instr_if ( instr_if ),
.data_if ( data_if ),
.irq_i ( irq_i ),
.irq_id_i ( irq_id_i ),
.irq_ack_o ( irq_ack_o ),
.irq_sec_i ( irq_sec_i ),
.sec_lvl_o ( sec_lvl_o ),
.debug_if ( debug_if )
.clk_i ( clk_i ),
.rst_n ( rst_ni ),
.clock_en_i ( clock_en_i ),
.test_en_i ( test_en_i ),
.fetch_enable_i ( fetch_enable_i ),
.core_busy_o ( core_busy_o ),
.ext_perf_counters_i ( ),
.boot_addr_i ( boot_addr_i ),
.core_id_i ( core_id_i ),
.cluster_id_i ( cluster_id_i ),
.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_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 ( irq_i ),
.irq_id_i ( irq_id_i ),
.irq_ack_o ( irq_ack_o ),
.irq_sec_i ( irq_sec_i ),
.sec_lvl_o ( sec_lvl_o ),
.debug_if ( debug_if )
);
// clock process

View file

@ -47,7 +47,7 @@ module lsu_tb;
.lsu_valid_o ( lsu.result_valid ),
.commit_i ( lsu.commit ),
// we are currently no testing the PTW and MMU
.enable_translation_i ( 1'b0 ),
.enable_translation_i ( 1'b1 ),
.fetch_req_i ( 1'b0 ),
.fetch_gnt_o ( ),
.fetch_valid_o ( ),
@ -61,8 +61,22 @@ module lsu_tb;
.asid_i ( 1'b0 ),
.flush_tlb_i ( 1'b0 ),
.instr_if ( instr_if ),
.data_if ( slave ),
.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_req ),
.instr_if_data_rvalid_i ( instr_if.data_rvalid ),
.instr_if_data_rdata_i ( instr_if.data_rdata ),
.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_data_gnt_i ( slave.data_gnt ),
.data_if_data_rvalid_i ( slave.data_rvalid ),
.data_if_data_rdata_i ( slave.data_rdata ),
.lsu_exception_o ( lsu.exception )
);