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: 9ce4f23
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: 4e83927
Choose a head ref
  • 4 commits
  • 4 files changed
  • 1 contributor

Commits on Jun 1, 2012

  1. Copy the full SHA
    229d711 View commit details
  2. Indent fix

    fallen committed Jun 1, 2012
    Copy the full SHA
    94fc320 View commit details
  3. Cleaning code

    fallen committed Jun 1, 2012
    Copy the full SHA
    1805080 View commit details
  4. Improve DTLB exceptions, add CSR to retrieve virtual addr causing a p…

    …age fault
    
    - Add a wcsr TLBCTRL bit to ask the TLB to invalidate a TLB entry
    - Add a rcsr DTLBMA (DTLB Miss Address) using the same CSR id as DTLBVADDR
      allowing to retrieve the virtual address which caused a DTLB miss
    - Improve DTLB exceptions to generate exceptions more reliably.
      exception_x is now asserted until exception_m is asserted as well
      preventing pipeline stalls to cancel exception propagation from
      stage X to stage M.
    fallen committed Jun 1, 2012
    Copy the full SHA
    4e83927 View commit details
Showing with 43 additions and 96 deletions.
  1. +2 −2 lm32_cpu.v
  2. +34 −63 lm32_dcache.v
  3. +2 −2 lm32_load_store_unit.v
  4. +5 −29 soc.wcfg
4 changes: 2 additions & 2 deletions lm32_cpu.v
Original file line number Diff line number Diff line change
@@ -1850,7 +1850,7 @@ begin
if (dtlb_miss_exception == `TRUE )
eid_x = `LM32_EID_DTLB_MISS;
else
eid_x = `LM32_EID_SCALL;
eid_x = `LM32_EID_SCALL;
end

// Stall generation
@@ -2143,7 +2143,7 @@ begin
`LM32_CSR_JRX: csr_read_data_x = jrx_csr_read_data;
`endif
`LM32_CSR_CFG2: csr_read_data_x = cfg2;
`LM32_CSR_TLB_DBG: csr_read_data_x = load_store_csr_read_data_x;
`LM32_CSR_TLB_VADDRESS: csr_read_data_x = load_store_csr_read_data_x;

default: csr_read_data_x = {`LM32_WORD_WIDTH{1'bx}};
endcase
97 changes: 34 additions & 63 deletions 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
@@ -109,6 +110,7 @@ module lm32_dcache (
csr_write_enable,
exception_x,
eret_q_x,
exception_m,
// ----- Outputs -----
stall_request,
restart_request,
@@ -117,7 +119,7 @@ module lm32_dcache (
refilling,
load_data,
// To pipeline
dtlb_miss_q,
dtlb_miss_int,
kernel_mode,
pa,
csr_read_data
@@ -137,7 +139,6 @@ 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_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} }
@@ -205,6 +206,7 @@ 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 exception_m;
input eret_q_x;

/////////////////////////////////////////////////////
@@ -230,9 +232,7 @@ wire [`LM32_WORD_RNG] load_data;
output kernel_mode;
wire kernel_mode;

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

/////////////////////////////////////////////////////
// Internal nets and registers
@@ -293,8 +293,8 @@ reg [addr_dtlb_index_width-1:0] dtlb_update_set;
reg dtlb_flushing;
reg [addr_dtlb_index_width-1:0] dtlb_flush_set;
wire dtlb_miss;
reg dtlb_miss_q = 0;
reg dtlb_miss_int = 0;
reg dtlb_miss_q = `FALSE;
wire dtlb_miss_int;
reg [`LM32_WORD_RNG] dtlb_miss_addr;
wire dtlb_data_valid;
wire [`LM32_DTLB_LOOKUP_RANGE] dtlb_lookup;
@@ -464,27 +464,14 @@ end
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_data_valid && (dtlb_read_tag == address_m[`LM32_DC_ADDR_TAG_RNG]) &&
*/ ({way_tag[i], way_valid[i]} == {dtlb_lookup, `TRUE});

/*always @(*)
begin
if (kernel_mode_reg == `LM32_KERNEL_MODE)
way_match[i] <= ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});
else if (dtlb_read_tag == `LM32_DTLB_TAG_INVALID) // DTLB tag is invalid
way_match[i] <= `FALSE;
else
way_match[i] <= ({way_tag[i], way_valid[i]} == {dtlb_read_data, `TRUE});
end*/
: ({way_tag[i], way_valid[i]} == {dtlb_lookup, `TRUE});
end
endgenerate

@@ -554,20 +541,10 @@ assign dtlb_data_read_address = address_x[`LM32_DTLB_IDX_RNG];
assign dtlb_tag_read_address = address_x[`LM32_DTLB_IDX_RNG];

// tlb_update_address will receive data from a CSR register
assign dtlb_data_write_address = /*(dtlb_flushing == `TRUE)
? dtlb_flush_set
: */dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];

assign dtlb_tag_write_address = (dtlb_flushing == `TRUE)
? dtlb_flush_set
: dtlb_update_vaddr_csr_reg[`LM32_DTLB_IDX_RNG];
assign dtlb_data_write_address = 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_TAG_INVALID
: {dtlb_update_vaddr_csr_reg[30:22], `TRUE}; // 10-1 top VA bits

assign physical_address = (kernel_mode_reg == `LM32_KERNEL_MODE)
? address_m
@@ -613,7 +590,7 @@ 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]; //|| dtlb_miss;
assign flushing = state[0];
assign check = state[1];
assign refill = state[2];

@@ -686,8 +663,6 @@ 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
@@ -721,35 +696,24 @@ begin
end
end

assign csr_read_data = latest_store_tlb_lookup;
assign csr_read_data = dtlb_miss_addr;

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;
dtlb_miss_q <= `FALSE;
else
begin
if (dtlb_miss)
dtlb_miss_int <= 1;
else
dtlb_miss_int <= 0;
if (dtlb_miss && ~dtlb_miss_q)
dtlb_miss_q <= `TRUE;
else if (dtlb_miss_q && exception_m)
dtlb_miss_q <= `FALSE;
end
end

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
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
assign dtlb_miss_int = (dtlb_miss || dtlb_miss_q);

always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
@@ -771,17 +735,15 @@ begin
dtlb_flushing <= 0;
if (dtlb_miss == `TRUE)
begin
// dtlb_flushing <= 0;
// dtlb_flush_set <= address_m[addr_dtlb_index_width-1:0];
dtlb_miss_addr <= address_m;
$display("ERROR : DTLB MISS on addr 0x%08X at time %t", address_m, $time);
$display("WARNING : DTLB MISS on addr 0x%08X at time %t", address_m, $time);
end
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;
@@ -794,6 +756,15 @@ begin
begin
dtlb_updating <= 1;
end

`LM32_TLB_CTRL_INVALIDATE_ENTRY:
begin
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
end
end
@@ -811,8 +782,8 @@ begin
end
end

assign switch_to_kernel_mode = (csr_write_enable && (csr == `LM32_CSR_TLB_CTRL) && csr_write_data[4:0] == {`LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE, 1'b1});
assign switch_to_user_mode = (csr_write_enable && (csr == `LM32_CSR_TLB_CTRL) && csr_write_data[4:0] == {`LM32_TLB_CTRL_SWITCH_TO_USER_MODE, 1'b1});
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)
4 changes: 2 additions & 2 deletions lm32_load_store_unit.v
Original file line number Diff line number Diff line change
@@ -429,15 +429,15 @@ lm32_dcache #(
.csr_write_enable (csr_write_enable),
.exception_x (exception_x),
.eret_q_x (eret_q_x),
.exception_m (exception_m),
// ----- 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_q (dtlb_miss),
.dtlb_miss_int (dtlb_miss),
.kernel_mode (kernel_mode),
.pa (physical_address),
.csr_read_data (csr_read_data)
34 changes: 5 additions & 29 deletions soc.wcfg
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
</top_modules>
</db_ref>
</db_ref_list>
<WVObjectSize size="149" />
<WVObjectSize size="144" />
<wvobject fp_name="/soc/memadr" type="array" db_ref_id="1">
<obj_property name="ElementShortName">memadr[31:0]</obj_property>
<obj_property name="ObjectShortName">memadr[31:0]</obj_property>
@@ -413,13 +413,8 @@
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_read_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_read_data[19:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_read_data[19:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_read_tag" type="array" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_read_tag[9:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_read_tag[9:0]</obj_property>
<obj_property name="ElementShortName">dtlb_read_data[30:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_read_data[30:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_sets" type="array" db_ref_id="1">
@@ -431,38 +426,19 @@
<obj_property name="ElementShortName">dtlb_state[1:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_state[1:0]</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_tag_read_address" type="array" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_tag_read_address[9:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_tag_read_address[9:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_tag_read_port_enable" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_tag_read_port_enable</obj_property>
<obj_property name="ObjectShortName">dtlb_tag_read_port_enable</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_tag_write_address" type="array" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_tag_write_address[9:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_tag_write_address[9:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_updating" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_updating</obj_property>
<obj_property name="ObjectShortName">dtlb_updating</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_write_data" type="array" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_write_data[19:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_write_data[19:0]</obj_property>
<obj_property name="ElementShortName">dtlb_write_data[30:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_write_data[30:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_write_port_enable" type="logic" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_write_port_enable</obj_property>
<obj_property name="ObjectShortName">dtlb_write_port_enable</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/dtlb_write_tag" type="array" db_ref_id="1">
<obj_property name="ElementShortName">dtlb_write_tag[9:0]</obj_property>
<obj_property name="ObjectShortName">dtlb_write_tag[9:0]</obj_property>
<obj_property name="Radix">HEXRADIX</obj_property>
</wvobject>
<wvobject fp_name="/soc/lm32/cpu/load_store_unit/dcache/flush_set" type="array" db_ref_id="1">
<obj_property name="ElementShortName">flush_set[7:0]</obj_property>
<obj_property name="ObjectShortName">flush_set[7:0]</obj_property>