Skip to content

Commit

Permalink
Make DTLB generate exception uppon TLB miss
Browse files Browse the repository at this point in the history
fallen committed May 30, 2012
1 parent 8e87083 commit 43f6245
Showing 4 changed files with 193 additions and 97 deletions.
21 changes: 12 additions & 9 deletions boards/milkymist-one/rtl/lm32_include.v
Original file line number Diff line number Diff line change
@@ -96,6 +96,8 @@
`define CFG_WATCHPOINTS 32'h4
`define CFG_EXTERNAL_BREAK_ENABLED
`define CFG_GDBSTUB_ENABLED
//`define CFG_RANDOM_WISHBONE_LATENCY
//`define CFG_VERBOSE_DISPLAY_ENABLED

// Enable MMU
`define CFG_MMU_ENABLED
@@ -304,16 +306,17 @@
`define LM32_WPC_C_READ_WRITE 2'b11

// Exception IDs
`define LM32_EID_WIDTH 3
`define LM32_EID_WIDTH 4
`define LM32_EID_RNG (`LM32_EID_WIDTH-1):0
`define LM32_EID_RESET 3'h0
`define LM32_EID_BREAKPOINT 3'd1
`define LM32_EID_INST_BUS_ERROR 3'h2
`define LM32_EID_WATCHPOINT 3'd3
`define LM32_EID_DATA_BUS_ERROR 3'h4
`define LM32_EID_DIVIDE_BY_ZERO 3'h5
`define LM32_EID_INTERRUPT 3'h6
`define LM32_EID_SCALL 3'h7
`define LM32_EID_RESET `LM32_EID_WIDTH'h0
`define LM32_EID_BREAKPOINT `LM32_EID_WIDTH'd1
`define LM32_EID_INST_BUS_ERROR `LM32_EID_WIDTH'h2
`define LM32_EID_WATCHPOINT `LM32_EID_WIDTH'd3
`define LM32_EID_DATA_BUS_ERROR `LM32_EID_WIDTH'h4
`define LM32_EID_DIVIDE_BY_ZERO `LM32_EID_WIDTH'h5
`define LM32_EID_INTERRUPT `LM32_EID_WIDTH'h6
`define LM32_EID_SCALL `LM32_EID_WIDTH'h7
`define LM32_EID_DTLB_MISS `LM32_EID_WIDTH'h8

// Pipeline result selection mux controls

25 changes: 20 additions & 5 deletions cores/lm32/rtl/lm32_cpu.v
Original file line number Diff line number Diff line change
@@ -967,6 +967,8 @@ lm32_decoder decoder (
.csr_write_enable (csr_write_enable_d)
);

wire dtlb_miss_exception;

// Load/store unit
lm32_load_store_unit #(
.associativity (dcache_associativity),
@@ -985,6 +987,7 @@ lm32_load_store_unit #(
.kill_x (kill_x),
.kill_m (kill_m),
.exception_m (exception_m),
.exception_x (exception_x),
.store_operand_x (store_operand_x),
.load_store_address_x (adder_result_x),
.load_store_address_m (operand_m),
@@ -1006,6 +1009,7 @@ lm32_load_store_unit #(
.csr (csr_x),
.csr_write_data (operand_1_x),
.csr_write_enable (csr_write_enable_q_x),
.eret_q_x (eret_q_x),
// From Wishbone
.d_dat_i (D_DAT_I),
.d_ack_i (D_ACK_I),
@@ -1027,7 +1031,7 @@ lm32_load_store_unit #(
`endif
.load_data_w (load_data_w),
.stall_wb_load (stall_wb_load),
.dtlb_miss (dtlb_miss),
.dtlb_miss (dtlb_miss_exception),
.csr_read_data (load_store_csr_read_data_x),
// To Wishbone
.d_dat_o (D_DAT_O),
@@ -1765,6 +1769,9 @@ assign non_debug_exception_x = (system_call_exception == `TRUE)
&& (D_CYC_O == `FALSE)
`endif
)
`endif
`ifdef CFG_MMU_ENABLED
|| (dtlb_miss_exception == `TRUE)
`endif
;

@@ -1788,6 +1795,9 @@ assign exception_x = (system_call_exception == `TRUE)
&& (D_CYC_O == `FALSE)
`endif
)
`endif
`ifdef CFG_MMU_ENABLED
|| (dtlb_miss_exception == `TRUE)
`endif
;
`endif
@@ -1837,7 +1847,10 @@ begin
eid_x = `LM32_EID_INTERRUPT;
else
`endif
eid_x = `LM32_EID_SCALL;
if (dtlb_miss_exception == `TRUE )
eid_x = `LM32_EID_DTLB_MISS;
else
eid_x = `LM32_EID_SCALL;
end

// Stall generation
@@ -2557,13 +2570,15 @@ begin

|| ((debug_exception_x == `TRUE)
&& (non_debug_exception_x == `FALSE)))
branch_target_m <= {deba, eid_x, {3{1'b0}}};
branch_target_m <= {deba[31:9], eid_x, {3{1'b0}}};
else
branch_target_m <= {eba, eid_x, {3{1'b0}}};
branch_target_m <= {eba[31:9], eid_x, {3{1'b0}}};
else
branch_target_m <= branch_target_x;
`else
branch_target_m <= exception_x == `TRUE ? {eba, eid_x, {3{1'b0}}} : branch_target_x;
//if (exception_x == `TRUE)
// $display("branch_target_m <= 0x%08X", branch_target_m);
branch_target_m <= exception_x == `TRUE ? {eba[31:9], eid_x, {3{1'b0}}} : branch_target_x;
`endif
`ifdef CFG_TRACE_ENABLED
eid_m <= eid_x;
216 changes: 135 additions & 81 deletions cores/lm32/rtl/lm32_dcache.v
Original file line number Diff line number Diff line change
@@ -76,10 +76,11 @@
`define LM32_DC_STATE_CHECK 3'b010
`define LM32_DC_STATE_REFILL 3'b100

`define LM32_DTLB_CTRL_FLUSH 4'h1
`define LM32_DTLB_CTRL_UPDATE 4'h2
`define LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE 4'h4
`define LM32_TLB_CTRL_SWITCH_TO_USER_MODE 4'h8
`define LM32_DTLB_CTRL_FLUSH 5'h1
`define LM32_DTLB_CTRL_UPDATE 5'h2
`define LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE 5'h4
`define LM32_TLB_CTRL_SWITCH_TO_USER_MODE 5'h8
`define LM32_TLB_CTRL_INVALIDATE_ENTRY 5'h10

`define LM32_TLB_STATE_CHECK 2'b01
`define LM32_TLB_STATE_FLUSH 2'b10
@@ -107,6 +108,8 @@ module lm32_dcache (
csr,
csr_write_data,
csr_write_enable,
exception_x,
eret_q_x,
// ----- Outputs -----
stall_request,
restart_request,
@@ -115,7 +118,7 @@ module lm32_dcache (
refilling,
load_data,
// To pipeline
dtlb_miss,
dtlb_miss_q,
kernel_mode,
pa,
csr_read_data
@@ -135,7 +138,7 @@ parameter dtlb_sets = 1024; // Number of lines of DTLB
parameter page_size = 4096; // System page size

`define LM32_DTLB_IDX_RNG addr_dtlb_index_msb:addr_dtlb_index_lsb
`define LM32_DTLB_INVALID_TAG { {9{1'b1}}, `FALSE}
//`define LM32_DTLB_INVALID_TAG { {9{1'b1}}, `FALSE}
`define LM32_DTLB_ADDRESS_PFN_RNG addr_pfn_msb:addr_pfn_lsb
`define LM32_PAGE_OFFSET_RNG addr_page_offset_msb:addr_page_offset_lsb
`define LM32_DTLB_INVALID_ADDRESS { vpfn_width{1'b1} }
@@ -153,6 +156,17 @@ localparam addr_dtlb_tag_lsb = addr_dtlb_index_msb + 1;
localparam addr_dtlb_tag_msb = addr_dtlb_tag_lsb + addr_dtlb_tag_width - 1;

`define LM32_DTLB_TAG_INVALID { addr_dtlb_tag_width{ 1'b0 } }
`define LM32_DTLB_LOOKUP_RANGE vpfn_width-1:0

/* The following define is the range containing the TAG inside the dtlb_read_data wire which contains the DTLB value from BlockRAM
* Indeed dtlb_read_data contains { VALID_BIT, TAG_VALUE, LOOKUP_VALUE }
* LM32_DTLB_TAG_RANGE is the range to extract the TAG_VALUE */
`define LM32_DTLB_TAG_RANGE vpfn_width+addr_dtlb_tag_width-1:vpfn_width

/* The following define is the range containing the TAG inside a memory address like dtlb_update_vaddr_csr_reg for instance. */
`define LM32_DTLB_ADDR_TAG_RNG addr_dtlb_tag_msb:addr_dtlb_tag_lsb
`define LM32_DTLB_VALID_BIT vpfn_width+addr_dtlb_tag_width


localparam addr_offset_width = clogb2(bytes_per_line)-1-2;
localparam addr_set_width = clogb2(sets)-1;
@@ -191,13 +205,15 @@ input dflush; // Indicates cache shoul
input [`LM32_CSR_RNG] csr; // CSR read/write index
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
input csr_write_enable; // CSR write enable
input exception_x; // An exception occured in the X stage
input eret_q_x;

/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////

output csr_read_data;
reg [`LM32_WORD_RNG] csr_read_data;
wire [`LM32_WORD_RNG] csr_read_data;

output stall_request; // Request pipeline be stalled because cache is busy
wire stall_request;
@@ -215,7 +231,9 @@ wire [`LM32_WORD_RNG] load_data;
output kernel_mode;
wire kernel_mode;

output dtlb_miss;
output dtlb_miss_q;
//output dtlb_miss;
//output dtlb_miss_int;

/////////////////////////////////////////////////////
// Internal nets and registers
@@ -253,14 +271,9 @@ wire [addr_dtlb_index_width-1:0] dtlb_data_read_address;
wire [addr_dtlb_index_width-1:0] dtlb_data_write_address;
wire dtlb_data_read_port_enable;
wire dtlb_write_port_enable;
wire [vpfn_width-1:0] dtlb_write_data;
wire [vpfn_width-1:0] dtlb_read_data;

wire [addr_dtlb_index_width-1:0] dtlb_tag_read_address;
wire dtlb_tag_read_port_enable;
wire [addr_dtlb_index_width-1:0] dtlb_tag_write_address;
wire [9:0] dtlb_write_tag;
wire [9:0] dtlb_read_tag;
wire [vpfn_width + addr_dtlb_tag_width + 1 - 1:0] dtlb_write_data; // +1 is for valid_bit
wire [vpfn_width + addr_dtlb_tag_width + 1 - 1:0] dtlb_read_data; // +1 is for valid_bit

wire [`LM32_WORD_RNG] physical_address;

wire [`LM32_WORD_RNG] pa;
@@ -270,6 +283,8 @@ reg [`LM32_WORD_RNG] latest_store_tlb_lookup;
assign pa = physical_address;

reg kernel_mode_reg = `LM32_KERNEL_MODE;
wire switch_to_kernel_mode;
wire switch_to_user_mode;
reg [`LM32_WORD_RNG] dtlb_update_vaddr_csr_reg = `LM32_WORD_WIDTH'd0;
reg [`LM32_WORD_RNG] dtlb_update_paddr_csr_reg = `LM32_WORD_WIDTH'd0;
reg [1:0] dtlb_state = `LM32_TLB_STATE_CHECK;
@@ -278,8 +293,12 @@ reg dtlb_updating;
reg [addr_dtlb_index_width-1:0] dtlb_update_set;
reg dtlb_flushing;
reg [addr_dtlb_index_width-1:0] dtlb_flush_set;
reg dtlb_miss;
wire dtlb_miss;
reg dtlb_miss_q = 0;
reg dtlb_miss_int = 0;
reg [`LM32_WORD_RNG] dtlb_miss_addr;
wire dtlb_data_valid;
wire [`LM32_DTLB_LOOKUP_RANGE] dtlb_lookup;

genvar i, j;

@@ -300,7 +319,7 @@ assign kernel_mode = kernel_mode_reg;
lm32_ram
#(
// ----- Parameters -------
.data_width (vpfn_width),
.data_width (vpfn_width + addr_dtlb_tag_width + 1),
.address_width (addr_dtlb_index_width)
// Modified for Milkymist: removed non-portable RAM parameters
) dtlb_data_ram
@@ -319,37 +338,16 @@ lm32_ram
.read_data (dtlb_read_data)
);

`ifdef CFG_VERBOSE_DISPLAY_ENABLED
always @(posedge clk_i)
begin
if (dtlb_write_port_enable)
begin
$display("[DTLB data : %d] Writing 0x%08X to 0x%08X", $time, dtlb_write_data, dtlb_data_write_address);
$display("[DTLB tag : %d] Writing 0x%08X to 0x%08X", $time, dtlb_write_tag, dtlb_tag_write_address);
end
end
`endif

lm32_ram
#(
// ----- Parameters -------
.data_width (addr_dtlb_tag_width),
.address_width (addr_dtlb_index_width)
// Modified for Milkymist: removed non-portable RAM parameters
) dtlb_tag_ram
(
// ----- Inputs -------
.read_clk (clk_i),
.write_clk (clk_i),
.reset (rst_i),
.read_address (dtlb_tag_read_address),
.enable_read (dtlb_tag_read_port_enable),
.write_address (dtlb_tag_write_address),
.enable_write (`TRUE),
.write_enable (dtlb_write_port_enable),
.write_data (dtlb_write_tag),
// ----- Outputs -------
.read_data (dtlb_read_tag)
);

generate
for (i = 0; i < associativity; i = i + 1)
begin : memories
@@ -437,33 +435,47 @@ lm32_ram
/////////////////////////////////////////////////////

// CSR Write
always @(posedge clk_i)
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (csr_write_enable)
if (rst_i == `TRUE)
begin
case (csr)
`LM32_CSR_TLB_CTRL: if (csr_write_data[0]) dtlb_ctrl_csr_reg[31:1] <= csr_write_data[31:1];
`LM32_CSR_TLB_VADDRESS: if (csr_write_data[0]) dtlb_update_vaddr_csr_reg[31:1] <= csr_write_data[31:1];
`LM32_CSR_TLB_PADDRESS: if (csr_write_data[0]) dtlb_update_paddr_csr_reg[31:1] <= csr_write_data[31:1];
endcase
dtlb_ctrl_csr_reg <= `LM32_WORD_WIDTH'd0;
dtlb_update_vaddr_csr_reg <= `LM32_WORD_WIDTH'd0;
dtlb_update_paddr_csr_reg <= `LM32_WORD_WIDTH'd0;
end
else
begin
if (csr_write_enable)
begin
case (csr)
`LM32_CSR_TLB_CTRL: if (csr_write_data[0]) dtlb_ctrl_csr_reg[31:1] <= csr_write_data[31:1];
`LM32_CSR_TLB_VADDRESS: if (csr_write_data[0]) dtlb_update_vaddr_csr_reg[31:1] <= csr_write_data[31:1];
`LM32_CSR_TLB_PADDRESS: if (csr_write_data[0]) dtlb_update_paddr_csr_reg[31:1] <= csr_write_data[31:1];
endcase
end
dtlb_ctrl_csr_reg[0] <= 0;
dtlb_update_vaddr_csr_reg[0] <= 0;
dtlb_update_paddr_csr_reg[0] <= 0;
end
dtlb_ctrl_csr_reg[0] <= 0;
dtlb_update_vaddr_csr_reg[0] <= 0;
dtlb_update_paddr_csr_reg[0] <= 0;
end



// Compute which ways in the cache match the address being read
generate
for (i = 0; i < associativity; i = i + 1)
begin : match
// FIXME : We need to put physical address coming out from MMU instead of address_m[]
//assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});

assign dtlb_read_tag = dtlb_read_data[`LM32_DTLB_TAG_RANGE];
assign dtlb_data_valid = dtlb_read_data[`LM32_DTLB_VALID_BIT];
assign dtlb_lookup = dtlb_read_data[`LM32_DTLB_LOOKUP_RANGE];

assign way_match[i] = (kernel_mode_reg == `LM32_KERNEL_MODE) ?
({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE})
: (dtlb_read_tag == `LM32_DTLB_TAG_INVALID) ?
`FALSE
: ({way_tag[i], way_valid[i]} == {dtlb_read_data, `TRUE});
: /*dtlb_data_valid && (dtlb_read_tag == address_m[`LM32_DC_ADDR_TAG_RNG]) &&
*/ ({way_tag[i], way_valid[i]} == {dtlb_lookup, `TRUE});

/*always @(*)
begin
@@ -552,19 +564,15 @@ assign dtlb_tag_write_address = (dtlb_flushing == `TRUE)
: dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];

assign dtlb_data_read_port_enable = (stall_x == `FALSE) || !stall_m;
assign dtlb_tag_read_port_enable = (stall_x == `FALSE) || !stall_m;
assign dtlb_write_port_enable = dtlb_updating || dtlb_flushing;
assign dtlb_write_tag = (dtlb_flushing == `TRUE)
? `LM32_DTLB_INVALID_TAG
: {dtlb_update_vaddr_csr_reg[30:22], `TRUE}; // 10-1 top VA bits

assign physical_address = (kernel_mode_reg == `LM32_KERNEL_MODE)
? address_m
: { dtlb_read_data , address_m[`LM32_PAGE_OFFSET_RNG] };
: {dtlb_lookup, address_m[`LM32_PAGE_OFFSET_RNG]};

assign dtlb_write_data = (dtlb_flushing == `TRUE)
? `LM32_DTLB_INVALID_ADDRESS
: dtlb_update_paddr_csr_reg[`LM32_DTLB_ADDRESS_PFN_RNG];
? {`FALSE, {addr_dtlb_tag_width{1'b0}}, {vpfn_width{1'b0}}}
: {`TRUE, {dtlb_update_vaddr_csr_reg[`LM32_DTLB_ADDR_TAG_RNG]}, dtlb_update_paddr_csr_reg[`LM32_DTLB_ADDRESS_PFN_RNG]};

// Compute signal to indicate when we are on the last refill accesses
generate
@@ -602,11 +610,11 @@ assign tmem_write_data[`LM32_DC_TAGS_VALID_RNG] = ((last_refill == `TRUE) || (va
assign tmem_write_data[`LM32_DC_TAGS_TAG_RNG] = refill_address[`LM32_DC_ADDR_TAG_RNG];

// Signals that indicate which state we are in
assign flushing = state[0];
assign flushing = state[0]; //|| dtlb_miss;
assign check = state[1];
assign refill = state[2];

assign miss = (~(|way_match)) && (load_q_m == `TRUE) && (stall_m == `FALSE);
assign miss = (~(|way_match)) && (load_q_m == `TRUE) && (stall_m == `FALSE) && (~dtlb_miss);
assign stall_request = (check == `FALSE) || (dtlb_state == `LM32_TLB_STATE_FLUSH && kernel_mode_reg != `LM32_KERNEL_MODE);

/////////////////////////////////////////////////////
@@ -675,6 +683,8 @@ begin
end
else if (dflush == `TRUE)
state <= `LM32_DC_STATE_FLUSH;
// else if (dtlb_miss == `TRUE)
// refill_address <= physical_address;
end

// Refill a cache line
@@ -697,15 +707,45 @@ end

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (write_port_enable && (|way_dmem_we))
if (rst_i == `TRUE)
latest_store_tlb_lookup <= `LM32_WORD_WIDTH'd0;
else
begin
latest_store_tlb_lookup <= { dtlb_read_data , address_m[`LM32_PAGE_OFFSET_RNG] };
if (write_port_enable && (|way_dmem_we))
begin
latest_store_tlb_lookup <= {dtlb_lookup, address_m[`LM32_PAGE_OFFSET_RNG]};
end
end
end

always @(*)
assign csr_read_data = latest_store_tlb_lookup;

assign dtlb_miss = (kernel_mode_reg == `LM32_USER_MODE) && (load_q_m || store_q_m) && ~(dtlb_data_valid);

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
dtlb_miss_int <= 0;
else
begin
if (dtlb_miss)
dtlb_miss_int <= 1;
else
dtlb_miss_int <= 0;
end
end

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
csr_read_data <= latest_store_tlb_lookup;
if (rst_i == `TRUE)
dtlb_miss_q <= 0;
else
begin
if (dtlb_miss_int)
dtlb_miss_q <= 1;
else
dtlb_miss_q <= 0;
end
end

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
@@ -716,6 +756,7 @@ begin
dtlb_flush_set <= {addr_dtlb_index_width{1'b1}};
dtlb_state <= `LM32_TLB_STATE_FLUSH;
dtlb_updating <= 0;
dtlb_miss_addr <= `LM32_WORD_WIDTH'd0;
end
else
begin
@@ -725,19 +766,19 @@ begin
begin
dtlb_updating <= 0;
dtlb_flushing <= 0;
if ((dtlb_miss == `TRUE) && (kernel_mode_reg == `LM32_KERNEL_MODE))
if (dtlb_miss == `TRUE)
begin
// FIXME : We need to generate an exception
// dtlb_flushing <= 0;
// dtlb_flush_set <= address_m[addr_dtlb_index_width-1:0];
dtlb_miss_addr <= address_m;
dtlb_updating <= 0;
$display("ERROR : DTLB MISS on addr 0x%08X", address_m);
$display("ERROR : DTLB MISS on addr 0x%08X at time %t", address_m, $time);
end
else if (csr_write_enable && csr_write_data[0])
if (csr_write_enable && csr_write_data[0])
begin
// FIXME : test for kernel mode is removed for testing purposes ONLY
if (csr == `LM32_CSR_TLB_CTRL /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
begin
case (csr_write_data[4:1])
case (csr_write_data[5:1])
`LM32_DTLB_CTRL_FLUSH:
begin
dtlb_flushing <= 1;
@@ -750,17 +791,13 @@ begin
begin
dtlb_updating <= 1;
end
// FIXME : This is for testing purposes ONLY
`LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE:
begin
kernel_mode_reg <= `LM32_KERNEL_MODE;
dtlb_updating <= 0;
end

`LM32_TLB_CTRL_SWITCH_TO_USER_MODE:
`LM32_TLB_CTRL_INVALIDATE_ENTRY:
begin
kernel_mode_reg <= `LM32_USER_MODE;
dtlb_flushing <= 1;
dtlb_flush_set <= dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
dtlb_updating <= 0;
dtlb_state <= `LM32_TLB_STATE_CHECK;
end

endcase
@@ -780,6 +817,23 @@ begin
end
end

assign switch_to_kernel_mode = (/*(kernel_mode_reg == `LM32_KERNEL_MODE) && */csr_write_enable && (csr == `LM32_CSR_TLB_CTRL) && csr_write_data[5:0] == {`LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE, 1'b1});
assign switch_to_user_mode = (/*(kernel_mode_reg == `LM32_KERNEL_MODE) && */csr_write_enable && (csr == `LM32_CSR_TLB_CTRL) && csr_write_data[5:0] == {`LM32_TLB_CTRL_SWITCH_TO_USER_MODE, 1'b1});


always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
kernel_mode_reg <= `LM32_KERNEL_MODE;
else
begin
if (/*exception_x || */switch_to_kernel_mode)
kernel_mode_reg <= `LM32_KERNEL_MODE;
else if (/*eret_q_x || */switch_to_user_mode)
kernel_mode_reg <= `LM32_USER_MODE;
end
end

generate
if (bytes_per_line > 4)
begin
28 changes: 26 additions & 2 deletions cores/lm32/rtl/lm32_load_store_unit.v
Original file line number Diff line number Diff line change
@@ -80,6 +80,7 @@ module lm32_load_store_unit (
kill_x,
kill_m,
exception_m,
exception_x,
store_operand_x,
load_store_address_x,
load_store_address_m,
@@ -101,6 +102,7 @@ module lm32_load_store_unit (
csr,
csr_write_data,
csr_write_enable,
eret_q_x,
// From Wishbone
d_dat_i,
d_ack_i,
@@ -164,6 +166,9 @@ input stall_m; // M stage stall
input kill_x; // Kill instruction in X stage
input kill_m; // Kill instruction in M stage
input exception_m; // An exception occured in the M stage
input exception_x; // An exception occured in the X stage
input eret_q_x;


input [`LM32_CSR_RNG] csr; // CSR read/write index
input [`LM32_WORD_RNG] csr_write_data; // Data to write to specified CSR
@@ -191,7 +196,8 @@ input dflush; // Flush the data cache
input [`LM32_WORD_RNG] irom_data_m; // Data from Instruction-ROM
`endif

input dtlb_miss;
wire dtlb_miss;
output dtlb_miss;

input [`LM32_WORD_RNG] d_dat_i; // Data Wishbone interface read data
input d_ack_i; // Data Wishbone interface acknowledgement
@@ -273,6 +279,7 @@ reg dcache_select_m;
wire [`LM32_WORD_RNG] dcache_data_m; // Data read from cache
wire [`LM32_WORD_RNG] dcache_refill_address; // Address to refill data cache from
reg dcache_refill_ready; // Indicates the next word of refill data is ready
reg d_adr_o_sampling;
wire [`LM32_CTYPE_RNG] first_cycle_type; // First Wishbone cycle type
wire [`LM32_CTYPE_RNG] next_cycle_type; // Next Wishbone cycle type
wire last_word; // Indicates if this is the last word in the cache line
@@ -420,14 +427,17 @@ lm32_dcache #(
.csr (csr),
.csr_write_data (csr_write_data),
.csr_write_enable (csr_write_enable),
.exception_x (exception_x),
.eret_q_x (eret_q_x),
// ----- Outputs -----
.stall_request (dcache_stall_request),
.restart_request (dcache_restart_request),
.refill_request (dcache_refill_request),
.refill_address (dcache_refill_address),
.refilling (dcache_refilling),
.load_data (dcache_data_m),
.dtlb_miss (dtlb_miss),
// .dtlb_miss (dtlb_miss),
.dtlb_miss_q (dtlb_miss),
.kernel_mode (kernel_mode),
.pa (physical_address),
.csr_read_data (csr_read_data)
@@ -654,6 +664,7 @@ always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
d_adr_o_sampling <= `FALSE;
d_cyc_o <= `FALSE;
d_stb_o <= `FALSE;
d_dat_o <= {`LM32_WORD_WIDTH{1'b0}};
@@ -690,6 +701,7 @@ begin
else
`endif
begin
d_adr_o_sampling <= 0;
// Refill/access complete
d_cyc_o <= `FALSE;
d_stb_o <= `FALSE;
@@ -716,6 +728,10 @@ begin
if (dcache_refill_request == `TRUE)
begin
// Start cache refill
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("Sampling address to refill 0x%08X\n", first_address);
`endif
d_adr_o_sampling <= 1;
d_adr_o <= first_address;
d_cyc_o <= `TRUE;
d_sel_o <= {`LM32_WORD_WIDTH/8{`TRUE}};
@@ -737,6 +753,10 @@ begin
)
begin
// Data cache is write through, so all stores go to memory
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("Sampling address to write through 0x%08X\n", store_data_m);
`endif
d_adr_o_sampling <= 1;
d_dat_o <= store_data_m;
d_adr_o <= (kernel_mode == `LM32_KERNEL_MODE) ? load_store_address_m : physical_address;
d_cyc_o <= `TRUE;
@@ -752,6 +772,10 @@ begin
)
begin
// Read requested address
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("Sampling address to read 0x%08X\n", (kernel_mode == `LM32_KERNEL_MODE) ? load_store_address_m : physical_address);
`endif
d_adr_o_sampling <= 1;
stall_wb_load <= `FALSE;
d_adr_o <= (kernel_mode == `LM32_KERNEL_MODE) ? load_store_address_m : physical_address;
d_cyc_o <= `TRUE;

0 comments on commit 43f6245

Please sign in to comment.