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

Verified

This commit was signed with the committer’s verified signature.
lukekarrys Luke Karrys
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.