Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: fallen/milkymist-mmu-simulation
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a4b3489cbfb9
Choose a base ref
...
head repository: fallen/milkymist-mmu-simulation
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0b3710bcc710
Choose a head ref
  • 2 commits
  • 7 files changed
  • 1 contributor

Commits on Aug 4, 2012

  1. fixes in ITLB

    fallen committed Aug 4, 2012
    Copy the full SHA
    d98eb9a View commit details

Commits on Oct 21, 2012

  1. Copy the full SHA
    0b3710b View commit details
Showing with 401 additions and 78 deletions.
  1. +59 −10 lm32_cpu.v
  2. +13 −11 lm32_dcache.v
  3. +75 −23 lm32_icache.v
  4. +15 −0 lm32_include.v
  5. +9 −0 lm32_instruction_unit.v
  6. +1 −1 soc.v
  7. +229 −33 soc.wcfg
69 changes: 59 additions & 10 deletions lm32_cpu.v
Original file line number Diff line number Diff line change
@@ -646,12 +646,12 @@ begin
begin
if (~stall_a)
$display("[%t] Addressing inst @ 0x%08X", $time, pc_a);
if (~stall_f)
/* if (~stall_f)
$display("[%t] Fetching inst @ 0x%08X", $time, pc_f);
if (~stall_d)
$display("[%t] Decoding inst @ 0x%08X", $time, pc_d);
if (~stall_x)
$display("[%t] Executing inst @ 0x%08X", $time, pc_x);
$display("[%t] Executing inst @ 0x%08X", $time, pc_x);*/
end
end
`endif
@@ -872,6 +872,7 @@ lm32_instruction_unit #(
.csr_write_enable (csr_write_enable_q_x),
.eret_q_x (eret_q_x),
.csr_psw (lm32_csr_psw_reg),
.q_x (q_x),
`endif
`ifdef CFG_IWB_ENABLED
// From Wishbone
@@ -2197,6 +2198,7 @@ begin
`LM32_CSR_CFG2: csr_read_data_x = cfg2;
`LM32_CSR_TLB_VADDRESS: csr_read_data_x = load_store_csr_read_data_x;
`LM32_CSR_TLB_PADDRESS: csr_read_data_x = instruction_csr_read_data_x;
`LM32_CSR_PSW: csr_read_data_x = lm32_csr_psw_reg;
default: csr_read_data_x = {`LM32_WORD_WIDTH{1'bx}};
endcase
end
@@ -2210,15 +2212,62 @@ begin
lm32_csr_psw_reg <= `LM32_WORD_WIDTH'h0;
end
else
if (csr_write_enable_q_x)
begin
case (csr_x)
// operand_1_x is csr_write_data
`LM32_CSR_PSW:
lm32_csr_psw_reg <= operand_1_x;
`LM32_CSR_IE:
lm32_csr_psw_reg[2:0] <= operand_1_x[2:0];
endcase
`ifdef CFG_DEBUG_ENABLED
if (non_debug_exception_q_w == `TRUE)
begin
// Save and then clear ITLB and DTLB enable
lm32_csr_psw_reg[`LM32_CSR_PSW_EITLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_EDTLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE] <= `FALSE;
lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE] <= `FALSE;
end
else if (debug_exception_q_w == `TRUE)
begin
// Save and then clear TLB enable
lm32_csr_psw_reg[`LM32_CSR_PSW_BITLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE] <= `FALSE;
lm32_csr_psw_reg[`LM32_CSR_PSW_BDTLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE] <= `FALSE;
end
`else
if (exception_q_w == `TRUE)
begin
// Save and then clear ITLB and DTLB enable
lm32_csr_psw_reg[`LM32_CSR_PSW_EITLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE] <= `FALSE;
lm32_csr_psw_reg[`LM32_CSR_PSW_EDTLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE] <= `FALSE;
end
`endif
else if (stall_x == `FALSE)
begin
if (eret_q_x == `TRUE)
begin
// Restore ITLB and DTLB enable
lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_EITLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_EDTLBE];
end
`ifdef CFG_DEBUG_ENABLED
else if (bret_q_x == `TRUE)
begin
// Restore ITLB and DTLB enable
lm32_csr_psw_reg[`LM32_CSR_PSW_ITLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_BITLBE];
lm32_csr_psw_reg[`LM32_CSR_PSW_DTLBE] <= lm32_csr_psw_reg[`LM32_CSR_PSW_BDTLBE];
end
`endif
else if (csr_write_enable_q_x == `TRUE)
begin
// Handle wcsr write
case (csr_x)
// operand_1_x is csr_write_data
`LM32_CSR_PSW:
lm32_csr_psw_reg <= operand_1_x;
`LM32_CSR_IE:
lm32_csr_psw_reg[2:0] <= operand_1_x[2:0];
endcase
end
end
end
end
`endif
24 changes: 13 additions & 11 deletions lm32_dcache.v
Original file line number Diff line number Diff line change
@@ -80,9 +80,6 @@
`define LM32_TLB_CTRL_SWITCH_TO_USER_MODE 5'h8
`define LM32_TLB_CTRL_INVALIDATE_ENTRY 5'h10

// FIXME: update the value
`define LM32_CSR_PSW_DTLBE `LM32_WORD_WIDTH'h01

`define LM32_TLB_STATE_CHECK 2'b01
`define LM32_TLB_STATE_FLUSH 2'b10

@@ -783,33 +780,38 @@ begin
end
if (csr_write_enable && csr_write_data[0])
begin
if (csr == `LM32_CSR_TLB_PADDRESS)
begin
$display("[ %t ] Updating a DTLB mapping 0x%08X -> 0x%08X", $time, dtlb_update_vaddr_csr_reg, dtlb_update_paddr_csr_reg);
dtlb_updating <= 1;
end
// FIXME : test for kernel mode is removed for testing purposes ONLY
if (csr == `LM32_CSR_TLB_CTRL /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
else if (csr == `LM32_CSR_TLB_VADDRESS /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
begin
dtlb_updating <= 0;
case (csr_write_data[5:1])
`LM32_DTLB_CTRL_FLUSH:
begin
$display("[ %t ] Flushing DTLB", $time);
dtlb_flushing <= 1;
dtlb_flush_set <= {addr_dtlb_index_width{1'b1}};
dtlb_state <= `LM32_TLB_STATE_FLUSH;
dtlb_updating <= 0;
end

`LM32_DTLB_CTRL_UPDATE:
begin
dtlb_updating <= 1;
end

`LM32_TLB_CTRL_INVALIDATE_ENTRY:
begin
$display("[ %t ] Invalidating DTLB entry 0x%08X", $time, dtlb_update_vaddr_csr_reg);
dtlb_flushing <= 1;
dtlb_flush_set <= dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
// dtlb_flush_set <= dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
dtlb_flush_set <= csr_write_data[`LM32_DTLB_IDX_RNG];
dtlb_updating <= 0;
dtlb_state <= `LM32_TLB_STATE_CHECK;
end

endcase
end
else
dtlb_updating <= 0;
end
end

98 changes: 75 additions & 23 deletions lm32_icache.v
Original file line number Diff line number Diff line change
@@ -80,9 +80,6 @@

`ifdef CFG_MMU_ENABLED

// FIXME: update the value
`define LM32_CSR_PSW_ITLBE `LM32_WORD_WIDTH'h02

`define LM32_ITLB_CTRL_FLUSH 5'h1
`define LM32_ITLB_CTRL_UPDATE 5'h2
`define LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE 5'h4
@@ -109,9 +106,15 @@ module lm32_icache (
stall_f,
`ifdef CFG_MMU_ENABLED
stall_x,
stall_m,
`endif
address_a,
address_f,
`ifdef CFG_MMU_ENABLED
pc_x,
pc_m,
pc_w,
`endif
read_enable_f,
refill_ready,
refill_data,
@@ -129,6 +132,7 @@ module lm32_icache (
exception_x,
eret_q_x,
exception_m,
q_x,
`endif
// ----- Outputs -----
stall_request,
@@ -213,13 +217,19 @@ input rst_i; // Reset

input stall_a; // Stall instruction in A stage
input stall_f; // Stall instruction in F stage
`ifdef CFG_MMU_ENABLED
input stall_x; // Stall instruction in X stage
input stall_m; // Stall instruction in X stage
`endif

input valid_d; // Valid instruction in D stage
input branch_predict_taken_d; // Instruction in D stage is a branch and is predicted taken

input [`LM32_PC_RNG] address_a; // Address of instruction in A stage
input [`LM32_PC_RNG] address_f; // Address of instruction in F stage
input [`LM32_PC_RNG] pc_x; // Address of instruction in X stage
input [`LM32_PC_RNG] pc_m; // Address of instruction in M stage
input [`LM32_PC_RNG] pc_w; // Address of instruction in W stage
input read_enable_f; // Indicates if cache access is valid

input refill_ready; // Next word of refill data is ready
@@ -238,6 +248,7 @@ input [`LM32_WORD_RNG] csr_psw;
input exception_x; // An exception occured in the X stage
input exception_m;
input eret_q_x;
input q_x;
`endif

/////////////////////////////////////////////////////
@@ -681,7 +692,7 @@ assign pa = physical_address;
assign kernel_mode = kernel_mode_reg;

assign csr_read_data = {itlb_miss_addr, 2'b0};
assign itlb_miss = (itlb_enabled == `TRUE) && (read_enable_f) && ~(itlb_data_valid);
assign itlb_miss = (itlb_enabled == `TRUE) && (read_enable_f) && ~(itlb_data_valid) && (~itlb_miss_q);
assign itlb_miss_int = (itlb_miss || itlb_miss_q);
assign itlb_read_tag = itlb_read_data[`LM32_ITLB_TAG_RANGE];
assign itlb_data_valid = itlb_read_data[`LM32_ITLB_VALID_BIT];
@@ -732,9 +743,9 @@ begin
itlb_miss_q <= `FALSE;
else
begin
if (itlb_miss && ~itlb_miss_q)
if (itlb_miss && ~itlb_miss_q && ~(exception_x == `TRUE && stall_m == `FALSE && stall_x == `FALSE && q_x == `TRUE))
itlb_miss_q <= `TRUE;
else if (itlb_miss_q && exception_m)
else if (itlb_miss_q && exception_x == `TRUE && stall_m == `FALSE && stall_x == `FALSE && q_x == `TRUE)
itlb_miss_q <= `FALSE;
end
end
@@ -764,17 +775,57 @@ begin
end
end

reg [`LM32_PC_RNG] pc_exception;
reg in_exception;

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (rst_i == `TRUE)
begin
itlb_enabled <= `FALSE;
in_exception <= `FALSE;
pc_exception <= {`LM32_PC_WIDTH{1'b0}};
end
else
begin
if (~stall_x)
begin
itlb_enabled <= csr_psw[`LM32_CSR_PSW_ITLBE];
if (eret_q_x)
begin
// $display("[%t] itlb_enabled <= 0x%08X upon eret", $time, csr_psw[`LM32_CSR_PSW_EITLBE]);
itlb_enabled <= csr_psw[`LM32_CSR_PSW_EITLBE];
end
else if (exception_x || in_exception)
begin
if (~in_exception)
begin
if (~exception_m)
in_exception <= 1;
else
in_exception <= 0;
end
else
begin
if (exception_m)
begin
$display("[%t] pc_exception <= 0x%08X", $time, pc_m);
pc_exception <= pc_m;
end
if (pc_exception == pc_w)
begin
in_exception <= 0;
end
end
$display("[%t] itlb_enabled <= 0x%08X upon exception", $time, 0);
itlb_enabled <= 0;
end
else
begin
if (itlb_enabled != csr_psw[`LM32_CSR_PSW_ITLBE])
$display("[%t] itlb_enabled <= 0x%08X", $time, csr_psw[`LM32_CSR_PSW_ITLBE]);

itlb_enabled <= csr_psw[`LM32_CSR_PSW_ITLBE];
end
end
end
end
@@ -805,39 +856,40 @@ begin
end
if (csr_write_enable && ~csr_write_data[0])
begin
if (csr == `LM32_CSR_TLB_PADDRESS /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
begin
$display("[%t] ITLB WCSR to PADDR with csr_write_data == 0x%08X", $time, csr_write_data);
//`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("it's an UPDATE at %t", $time);
//`endif
itlb_updating <= 1;
end
// FIXME : test for kernel mode is removed for testing purposes ONLY
if (csr == `LM32_CSR_TLB_CTRL /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
else if (csr == `LM32_CSR_TLB_VADDRESS /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
begin
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
//`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("ITLB WCSR at %t with csr_write_data == 0x%08X", $time, csr_write_data);
`endif
//`endif
case (csr_write_data[5:1])
`LM32_ITLB_CTRL_FLUSH:
begin
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
//`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("it's a FLUSH at %t", $time);
`endif
//`endif
itlb_flushing <= 1;
itlb_flush_set <= {addr_itlb_index_width{1'b1}};
itlb_state <= `LM32_TLB_STATE_FLUSH;
itlb_updating <= 0;
end

`LM32_ITLB_CTRL_UPDATE:
begin
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("it's an UPDATE at %t", $time);
`endif
itlb_updating <= 1;
end

`LM32_TLB_CTRL_INVALIDATE_ENTRY:
begin
`ifdef CFG_VERBOSE_DISPLAY_ENABLED
//`ifdef CFG_VERBOSE_DISPLAY_ENABLED
$display("it's an INVALIDATE ENTRY at %t", $time);
`endif
//`endif
itlb_flushing <= 1;
itlb_flush_set <= itlb_update_vaddr_csr_reg[`LM32_ITLB_IDX_RNG];
// itlb_flush_set <= itlb_update_vaddr_csr_reg[`LM32_ITLB_IDX_RNG];
itlb_flush_set <= csr_write_data[`LM32_ITLB_IDX_RNG];
itlb_updating <= 0;
itlb_state <= `LM32_TLB_STATE_CHECK;
end
15 changes: 15 additions & 0 deletions lm32_include.v
Original file line number Diff line number Diff line change
@@ -301,6 +301,21 @@
`define LM32_CSR_TLB_DBG `LM32_CSR_WIDTH'h1f
`endif

`ifdef CFG_MMU_ENABLED
`define LM32_CSR_PSW_IE `LM32_WORD_WIDTH'h0
`define LM32_CSR_PSW_EIE `LM32_WORD_WIDTH'h1
`define LM32_CSR_PSW_BIE `LM32_WORD_WIDTH'h2
`define LM32_CSR_PSW_ITLBE `LM32_WORD_WIDTH'h3
`define LM32_CSR_PSW_EITLBE `LM32_WORD_WIDTH'h4
`define LM32_CSR_PSW_BITLBE `LM32_WORD_WIDTH'h5
`define LM32_CSR_PSW_DTLBE `LM32_WORD_WIDTH'h6
`define LM32_CSR_PSW_EDTLBE `LM32_WORD_WIDTH'h7
`define LM32_CSR_PSW_BDTLBE `LM32_WORD_WIDTH'h8
`define LM32_CSR_PSW_USR `LM32_WORD_WIDTH'h9
`define LM32_CSR_PSW_EUSR `LM32_WORD_WIDTH'ha
`define LM32_CSR_PSW_BUSR `LM32_WORD_WIDTH'hb
`endif

// Values for WPC CSR
`define LM32_WPC_C_RNG 1:0
`define LM32_WPC_C_DISABLED 2'b00
Loading