Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add a draft of ITLB to Milkymist MMU

  • Loading branch information...
commit 3f098597855711ceade3356723c90f41e1d0d80e 1 parent 188ce66
Yann Sionneau authored June 11, 2012
12  lm32_cpu.v
@@ -616,7 +616,8 @@ wire mc_stall_request_x;                        // Multi-cycle arithmetic unit s
616 616
 wire [`LM32_WORD_RNG] mc_result_x;
617 617
 `endif
618 618
 
619  
-wire [`LM32_WORD_RNG] load_store_csr_read_data_x;// Data read from load store CSRs
  619
+wire [`LM32_WORD_RNG] load_store_csr_read_data_x;// Data read from load store unit CSRs
  620
+wire [`LM32_WORD_RNG] instruction_csr_read_data_x;// Data read from instruction unit CSRs
620 621
 // From CSRs
621 622
 `ifdef CFG_INTERRUPTS_ENABLED
622 623
 wire [`LM32_WORD_RNG] interrupt_csr_read_data_x;// Data read from interrupt CSRs
@@ -819,6 +820,7 @@ lm32_instruction_unit #(
819 820
     .branch_target_x        (branch_target_x),
820 821
 `endif
821 822
     .exception_m            (exception_m),
  823
+    .exception_x            (exception_x),
822 824
     .branch_taken_m         (branch_taken_m),
823 825
     .branch_mispredict_taken_m (branch_mispredict_taken_m),
824 826
     .branch_target_m        (branch_target_m),
@@ -834,7 +836,11 @@ lm32_instruction_unit #(
834 836
     .dcache_restart_request (dcache_restart_request),
835 837
     .dcache_refill_request  (dcache_refill_request),
836 838
     .dcache_refilling       (dcache_refilling),
837  
-`endif        
  839
+`endif
  840
+    .csr		    (csr_x),
  841
+    .csr_write_data	    (operand_1_x),
  842
+    .csr_write_enable	    (csr_write_enable_q_x),
  843
+    .eret_q_x		    (eret_q_x),
838 844
 `ifdef CFG_IWB_ENABLED
839 845
     // From Wishbone
840 846
     .i_dat_i                (I_DAT_I),
@@ -863,6 +869,8 @@ lm32_instruction_unit #(
863 869
 `ifdef CFG_IROM_ENABLED
864 870
     .irom_data_m            (irom_data_m),
865 871
 `endif
  872
+    .itlb_miss		    (itlb_miss_exception),
  873
+    .csr_read_data	    (instruction_csr_read_data_x),
866 874
 `ifdef CFG_IWB_ENABLED
867 875
     // To Wishbone
868 876
     .i_dat_o                (I_DAT_O),
335  lm32_icache.v
@@ -57,6 +57,8 @@
57 57
 `include "lm32_include.v"
58 58
 
59 59
 `ifdef CFG_ICACHE_ENABLED
  60
+`define LM32_KERNEL_MODE		 1
  61
+`define LM32_USER_MODE			 0
60 62
 
61 63
 `define LM32_IC_ADDR_OFFSET_RNG          addr_offset_msb:addr_offset_lsb
62 64
 `define LM32_IC_ADDR_SET_RNG             addr_set_msb:addr_set_lsb
@@ -79,6 +81,15 @@
79 81
 `define LM32_IC_STATE_CHECK              4'b0100
80 82
 `define LM32_IC_STATE_REFILL             4'b1000
81 83
 
  84
+`define LM32_ITLB_CTRL_FLUSH		 	5'h1
  85
+`define LM32_ITLB_CTRL_UPDATE		 	5'h2
  86
+`define LM32_TLB_CTRL_SWITCH_TO_KERNEL_MODE	5'h4
  87
+`define LM32_TLB_CTRL_SWITCH_TO_USER_MODE	5'h8
  88
+`define LM32_TLB_CTRL_INVALIDATE_ENTRY		5'h10
  89
+
  90
+`define LM32_TLB_STATE_CHECK		 2'b01
  91
+`define LM32_TLB_STATE_FLUSH		 2'b10
  92
+
82 93
 /////////////////////////////////////////////////////
83 94
 // Module interface
84 95
 /////////////////////////////////////////////////////
@@ -100,13 +111,24 @@ module lm32_icache (
100 111
 `endif
101 112
     valid_d,
102 113
     branch_predict_taken_d,
  114
+    csr,
  115
+    csr_write_data,
  116
+    csr_write_enable,
  117
+    exception_x,
  118
+    eret_q_x,
  119
+    exception_m,
103 120
     // ----- Outputs -----
104 121
     stall_request,
105 122
     restart_request,
106 123
     refill_request,
107 124
     refill_address,
  125
+    physical_refill_address,
108 126
     refilling,
109  
-    inst
  127
+    inst,
  128
+    itlb_miss_int,
  129
+    kernel_mode,
  130
+    pa,
  131
+    csr_read_data
110 132
     );
111 133
 
112 134
 /////////////////////////////////////////////////////
@@ -119,6 +141,39 @@ parameter bytes_per_line = 16;                          // Number of bytes per c
119 141
 parameter base_address = 0;                             // Base address of cachable memory
120 142
 parameter limit = 0;                                    // Limit (highest address) of cachable memory
121 143
 
  144
+parameter itlb_sets = 1024;				// Number of lines of ITLB
  145
+parameter page_size = 4096;				// System page size
  146
+
  147
+`define LM32_ITLB_IDX_RNG		addr_itlb_index_msb:addr_itlb_index_lsb
  148
+`define LM32_ITLB_ADDRESS_PFN_RNG	addr_pfn_msb:addr_pfn_lsb
  149
+`define LM32_PAGE_OFFSET_RNG		addr_page_offset_msb:addr_page_offset_lsb
  150
+`define LM32_ITLB_INVALID_ADDRESS	{ vpfn_width{1'b1} }
  151
+
  152
+localparam addr_page_offset_lsb = 0;
  153
+localparam addr_page_offset_msb = addr_page_offset_lsb + clogb2(page_size) - 2;
  154
+localparam addr_itlb_index_width = clogb2(itlb_sets) - 1;
  155
+localparam addr_itlb_index_lsb = addr_page_offset_msb + 1;
  156
+localparam addr_itlb_index_msb = addr_itlb_index_lsb + addr_itlb_index_width - 1;
  157
+localparam addr_pfn_lsb = addr_page_offset_msb + 1;
  158
+localparam addr_pfn_msb = `LM32_WORD_WIDTH - 1;
  159
+localparam vpfn_width = `LM32_WORD_WIDTH - (clogb2(page_size) - 1);
  160
+localparam addr_itlb_tag_width = vpfn_width - addr_itlb_index_width;
  161
+localparam addr_itlb_tag_lsb = addr_itlb_index_msb + 1;
  162
+localparam addr_itlb_tag_msb = addr_itlb_tag_lsb + addr_itlb_tag_width - 1;
  163
+
  164
+`define LM32_ITLB_TAG_INVALID		{ addr_itlb_tag_width{ 1'b0 } }
  165
+`define LM32_ITLB_LOOKUP_RANGE		vpfn_width-1:0
  166
+
  167
+/* The following define is the range containing the TAG inside the itlb_read_data wire which contains the ITLB value from BlockRAM
  168
+ * Indeed itlb_read_data contains { VALID_BIT, TAG_VALUE, LOOKUP_VALUE }
  169
+ * LM32_ITLB_TAG_RANGE is the range to extract the TAG_VALUE */
  170
+`define LM32_ITLB_TAG_RANGE		vpfn_width+addr_itlb_tag_width-1:vpfn_width
  171
+
  172
+/* The following define is the range containing the TAG inside a memory address like itlb_update_vaddr_csr_reg for instance. */
  173
+`define LM32_ITLB_ADDR_TAG_RNG		addr_itlb_tag_msb:addr_itlb_tag_lsb
  174
+`define LM32_ITLB_VALID_BIT		vpfn_width+addr_itlb_tag_width
  175
+
  176
+
122 177
 localparam addr_offset_width = clogb2(bytes_per_line)-1-2;
123 178
 localparam addr_set_width = clogb2(sets)-1;
124 179
 localparam addr_offset_lsb = 2;
@@ -154,10 +209,20 @@ input iflush;                                       // Flush the cache
154 209
 input select_f;                                     // Instruction in F stage is mapped through instruction cache
155 210
 `endif
156 211
    
  212
+input [`LM32_CSR_RNG] csr;				// CSR read/write index
  213
+input [`LM32_WORD_RNG] csr_write_data;			// Data to write to specified CSR
  214
+input csr_write_enable;					// CSR write enable
  215
+input exception_x;					// An exception occured in the X stage
  216
+input exception_m;
  217
+input eret_q_x;
  218
+
157 219
 /////////////////////////////////////////////////////
158 220
 // Outputs
159 221
 /////////////////////////////////////////////////////
160 222
 
  223
+output csr_read_data;
  224
+wire [`LM32_WORD_RNG] csr_read_data;
  225
+
161 226
 output stall_request;                               // Request to stall the pipeline
162 227
 wire   stall_request;
163 228
 output restart_request;                             // Request to restart instruction that caused the cache miss
@@ -166,11 +231,18 @@ output refill_request;                              // Request to refill a cache
166 231
 wire   refill_request;
167 232
 output [`LM32_PC_RNG] refill_address;               // Base address of cache refill
168 233
 reg    [`LM32_PC_RNG] refill_address;               
  234
+output [`LM32_PC_RNG] physical_refill_address;
  235
+reg    [`LM32_PC_RNG] physical_refill_address;
169 236
 output refilling;                                   // Indicates the instruction cache is currently refilling
170 237
 reg    refilling;
171 238
 output [`LM32_INSTRUCTION_RNG] inst;                // Instruction read from cache
172 239
 wire   [`LM32_INSTRUCTION_RNG] inst;
173 240
 
  241
+output kernel_mode;
  242
+wire kernel_mode;
  243
+
  244
+output itlb_miss_int;
  245
+
174 246
 /////////////////////////////////////////////////////
175 247
 // Internal nets and registers 
176 248
 /////////////////////////////////////////////////////
@@ -199,7 +271,41 @@ reg [`LM32_IC_ADDR_OFFSET_RNG] refill_offset;
199 271
 wire last_refill;
200 272
 reg [`LM32_IC_TMEM_ADDR_RNG] flush_set;
201 273
 
202  
-genvar i;
  274
+wire [addr_itlb_index_width-1:0] itlb_data_read_address;
  275
+wire [addr_itlb_index_width-1:0] itlb_data_write_address;
  276
+wire itlb_data_read_port_enable;
  277
+wire itlb_write_port_enable;
  278
+wire [vpfn_width + addr_itlb_tag_width + 1 - 1:0] itlb_write_data; // +1 is for valid_bit
  279
+wire [vpfn_width + addr_itlb_tag_width + 1 - 1:0] itlb_read_data; // +1 is for valid_bit
  280
+
  281
+wire [`LM32_WORD_RNG] physical_address;
  282
+
  283
+wire [`LM32_WORD_RNG] pa;
  284
+output [`LM32_WORD_RNG] pa;
  285
+
  286
+assign pa = physical_address;
  287
+
  288
+reg kernel_mode_reg = `LM32_KERNEL_MODE;
  289
+wire switch_to_kernel_mode;
  290
+wire switch_to_user_mode;
  291
+reg [`LM32_WORD_RNG] itlb_update_vaddr_csr_reg = `LM32_WORD_WIDTH'd0;
  292
+reg [`LM32_WORD_RNG] itlb_update_paddr_csr_reg = `LM32_WORD_WIDTH'd0;
  293
+reg [1:0] itlb_state = `LM32_TLB_STATE_CHECK;
  294
+reg [`LM32_WORD_RNG] itlb_ctrl_csr_reg = `LM32_WORD_WIDTH'd0;
  295
+reg itlb_updating;
  296
+reg [addr_itlb_index_width-1:0] itlb_update_set;
  297
+reg itlb_flushing;
  298
+reg [addr_itlb_index_width-1:0] itlb_flush_set;
  299
+wire itlb_miss;
  300
+reg itlb_miss_q = `FALSE;
  301
+wire itlb_miss_int;
  302
+reg [`LM32_WORD_RNG] itlb_miss_addr;
  303
+wire itlb_data_valid;
  304
+wire [`LM32_ITLB_LOOKUP_RANGE] itlb_lookup;
  305
+
  306
+genvar i, j;
  307
+
  308
+assign kernel_mode = kernel_mode_reg;
203 309
 
204 310
 /////////////////////////////////////////////////////
205 311
 // Functions
@@ -211,6 +317,39 @@ genvar i;
211 317
 // Instantiations
212 318
 /////////////////////////////////////////////////////
213 319
 
  320
+// ITLB instantiation
  321
+lm32_ram
  322
+  #(
  323
+    // ----- Parameters -------
  324
+    .data_width (vpfn_width + addr_itlb_tag_width + 1),
  325
+    .address_width (addr_itlb_index_width)
  326
+// Modified for Milkymist: removed non-portable RAM parameters
  327
+    ) itlb_data_ram
  328
+    (
  329
+     // ----- Inputs -------
  330
+     .read_clk (clk_i),
  331
+     .write_clk (clk_i),
  332
+     .reset (rst_i),
  333
+     .read_address (itlb_data_read_address),
  334
+     .enable_read (itlb_data_read_port_enable),
  335
+     .write_address (itlb_data_write_address),
  336
+     .enable_write (`TRUE),
  337
+     .write_enable (itlb_write_port_enable),
  338
+     .write_data (itlb_write_data),
  339
+     // ----- Outputs -------
  340
+     .read_data (itlb_read_data)
  341
+     );
  342
+
  343
+`ifdef CFG_VERBOSE_DISPLAY_ENABLED
  344
+always @(posedge clk_i)
  345
+begin
  346
+	if (itlb_write_port_enable)
  347
+	begin
  348
+		$display("[ITLB data : %d] Writing 0x%08X to 0x%08X", $time, itlb_write_data, itlb_data_write_address);
  349
+	end
  350
+end
  351
+`endif
  352
+
214 353
    generate
215 354
       for (i = 0; i < associativity; i = i + 1)
216 355
 	begin : memories
@@ -268,11 +407,45 @@ endgenerate
268 407
 // Combinational logic
269 408
 /////////////////////////////////////////////////////
270 409
 
  410
+// CSR Write
  411
+always @(posedge clk_i `CFG_RESET_SENSITIVITY)
  412
+begin
  413
+	if (rst_i == `TRUE)
  414
+	begin
  415
+		itlb_ctrl_csr_reg <= `LM32_WORD_WIDTH'd0;
  416
+		itlb_update_vaddr_csr_reg <= `LM32_WORD_WIDTH'd0;
  417
+		itlb_update_paddr_csr_reg <= `LM32_WORD_WIDTH'd0;
  418
+	end
  419
+	else
  420
+	begin
  421
+		if (csr_write_enable)
  422
+		begin
  423
+			case (csr)
  424
+			`LM32_CSR_TLB_CTRL:	if (~csr_write_data[0]) itlb_ctrl_csr_reg[31:1] <= csr_write_data[31:1];
  425
+			`LM32_CSR_TLB_VADDRESS: if (~csr_write_data[0]) itlb_update_vaddr_csr_reg[31:1] <= csr_write_data[31:1];
  426
+			`LM32_CSR_TLB_PADDRESS: if (~csr_write_data[0]) itlb_update_paddr_csr_reg[31:1] <= csr_write_data[31:1];
  427
+			endcase
  428
+		end
  429
+		itlb_ctrl_csr_reg[0] <= 0;
  430
+		itlb_update_vaddr_csr_reg[0] <= 0;
  431
+		itlb_update_paddr_csr_reg[0] <= 0;
  432
+	end
  433
+end
  434
+
271 435
 // Compute which ways in the cache match the address address being read
272 436
 generate
273 437
     for (i = 0; i < associativity; i = i + 1)
274 438
     begin : match
275  
-assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[`LM32_IC_ADDR_TAG_RNG], `TRUE});
  439
+
  440
+assign itlb_read_tag = itlb_read_data[`LM32_ITLB_TAG_RANGE];
  441
+assign itlb_data_valid = itlb_read_data[`LM32_ITLB_VALID_BIT];
  442
+assign itlb_lookup = itlb_read_data[`LM32_ITLB_LOOKUP_RANGE];
  443
+
  444
+//assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[`LM32_IC_ADDR_TAG_RNG], `TRUE});
  445
+assign way_match[i] = (kernel_mode_reg == `LM32_KERNEL_MODE) ?
  446
+		      ({way_tag[i], way_valid[i]} == {address_f[`LM32_IC_ADDR_TAG_RNG], `TRUE}) : 
  447
+
  448
+		      ({way_tag[i], way_valid[i]} == {itlb_lookup, `TRUE });
276 449
     end
277 450
 endgenerate
278 451
 
@@ -304,6 +477,25 @@ assign tmem_write_address = flushing
304 477
                                 ? flush_set
305 478
                                 : refill_address[`LM32_IC_ADDR_SET_RNG];
306 479
 
  480
+// Compute address to use to index into the ITLB data memory
  481
+
  482
+assign itlb_data_read_address = address_a[`LM32_ITLB_IDX_RNG];
  483
+
  484
+// tlb_update_address will receive data from a CSR register
  485
+assign itlb_data_write_address = itlb_update_vaddr_csr_reg[`LM32_ITLB_IDX_RNG];
  486
+
  487
+assign itlb_data_read_port_enable = (stall_a == `FALSE) || !stall_f;
  488
+assign itlb_write_port_enable = itlb_updating || itlb_flushing;
  489
+
  490
+assign physical_address = (kernel_mode_reg == `LM32_KERNEL_MODE)
  491
+			    ? {address_f, 2'b0}
  492
+			    : {itlb_lookup, address_f[`LM32_PAGE_OFFSET_RNG+2], 2'b0};
  493
+
  494
+assign itlb_write_data = (itlb_flushing == `TRUE)
  495
+			 ? {`FALSE, {addr_itlb_tag_width{1'b0}}, {vpfn_width{1'b0}}}
  496
+			 : {`TRUE, {itlb_update_vaddr_csr_reg[`LM32_ITLB_ADDR_TAG_RNG]}, itlb_update_paddr_csr_reg[`LM32_ITLB_ADDRESS_PFN_RNG]};
  497
+
  498
+
307 499
 // Compute signal to indicate when we are on the last refill accesses
308 500
 generate 
309 501
     if (bytes_per_line > 4)                            
@@ -330,7 +522,7 @@ endgenerate
330 522
 
331 523
 // On the last refill cycle set the valid bit, for all other writes it should be cleared
332 524
 assign tmem_write_data[`LM32_IC_TAGS_VALID_RNG] = last_refill & !flushing;
333  
-assign tmem_write_data[`LM32_IC_TAGS_TAG_RNG] = refill_address[`LM32_IC_ADDR_TAG_RNG];
  525
+assign tmem_write_data[`LM32_IC_TAGS_TAG_RNG] = physical_refill_address[`LM32_IC_ADDR_TAG_RNG];
334 526
 
335 527
 // Signals that indicate which state we are in
336 528
 assign flushing = |state[1:0];
@@ -414,11 +606,13 @@ begin
414 606
                 restart_request <= `FALSE;
415 607
             if (iflush == `TRUE)
416 608
             begin
  609
+                physical_refill_address <= physical_address[`LM32_PC_RNG];
417 610
                 refill_address <= address_f;
418 611
                 state <= `LM32_IC_STATE_FLUSH;
419 612
             end
420 613
             else if (miss == `TRUE)
421 614
             begin
  615
+                physical_refill_address <= physical_address[`LM32_PC_RNG];
422 616
                 refill_address <= address_f;
423 617
                 state <= `LM32_IC_STATE_REFILL;
424 618
             end
@@ -441,6 +635,139 @@ begin
441 635
     end
442 636
 end
443 637
 
  638
+assign csr_read_data = itlb_miss_addr;
  639
+
  640
+assign itlb_miss = (kernel_mode_reg == `LM32_USER_MODE) && (read_enable_f) && ~(itlb_data_valid);
  641
+
  642
+always @(posedge clk_i `CFG_RESET_SENSITIVITY)
  643
+begin
  644
+	if (rst_i == `TRUE)
  645
+		itlb_miss_q <= `FALSE;
  646
+	else
  647
+	begin
  648
+		if (itlb_miss && ~itlb_miss_q)
  649
+			itlb_miss_q <= `TRUE;
  650
+		else if (itlb_miss_q && exception_m)
  651
+			itlb_miss_q <= `FALSE;
  652
+	end
  653
+end
  654
+
  655
+assign itlb_miss_int = (itlb_miss || itlb_miss_q);
  656
+
  657
+always @(posedge clk_i `CFG_RESET_SENSITIVITY)
  658
+begin
  659
+	if (rst_i == `TRUE)
  660
+	begin
  661
+		itlb_flushing <= 1;
  662
+		itlb_flush_set <= {addr_itlb_index_width{1'b1}};
  663
+		itlb_state <= `LM32_TLB_STATE_FLUSH;
  664
+		itlb_updating <= 0;
  665
+		itlb_miss_addr <= `LM32_WORD_WIDTH'd0;
  666
+	end
  667
+	else
  668
+	begin
  669
+		case (itlb_state)
  670
+
  671
+		`LM32_TLB_STATE_CHECK:
  672
+		begin
  673
+			itlb_updating <= 0;
  674
+			itlb_flushing <= 0;
  675
+			if (itlb_miss == `TRUE)
  676
+			begin
  677
+				itlb_miss_addr <= address_f;
  678
+				$display("WARNING : ITLB MISS on addr 0x%08X at time %t", address_f, $time);
  679
+			end
  680
+			if (csr_write_enable && ~csr_write_data[0])
  681
+			begin
  682
+				// FIXME : test for kernel mode is removed for testing purposes ONLY
  683
+				if (csr == `LM32_CSR_TLB_CTRL /*&& (kernel_mode_reg == `LM32_KERNEL_MODE)*/)
  684
+				begin
  685
+`ifdef CFG_VERBOSE_DISPLAY_ENABLED
  686
+					$display("ITLB WCSR at %t with csr_write_data == 0x%08X", $time, csr_write_data);
  687
+`endif
  688
+					case (csr_write_data[5:1])
  689
+					`LM32_ITLB_CTRL_FLUSH:
  690
+					begin
  691
+`ifdef CFG_VERBOSE_DISPLAY_ENABLED
  692
+						$display("it's a FLUSH at %t", $time);
  693
+`endif
  694
+						itlb_flushing <= 1;
  695
+						itlb_flush_set <= {addr_itlb_index_width{1'b1}};
  696
+						itlb_state <= `LM32_TLB_STATE_FLUSH;
  697
+						itlb_updating <= 0;
  698
+					end
  699
+
  700
+					`LM32_ITLB_CTRL_UPDATE:
  701
+					begin
  702
+`ifdef CFG_VERBOSE_DISPLAY_ENABLED
  703
+						$display("it's an UPDATE at %t", $time);
  704
+`endif
  705
+						itlb_updating <= 1;
  706
+					end
  707
+
  708
+					`LM32_TLB_CTRL_INVALIDATE_ENTRY:
  709
+					begin
  710
+`ifdef CFG_VERBOSE_DISPLAY_ENABLED
  711
+						$display("it's an INVALIDATE ENTRY at %t", $time);
  712
+`endif
  713
+						itlb_flushing <= 1;
  714
+						itlb_flush_set <= itlb_update_vaddr_csr_reg[`LM32_ITLB_IDX_RNG];
  715
+						itlb_updating <= 0;
  716
+						itlb_state <= `LM32_TLB_STATE_CHECK;
  717
+					end
  718
+
  719
+					endcase
  720
+				end
  721
+			end
  722
+		end
  723
+
  724
+		`LM32_TLB_STATE_FLUSH:
  725
+		begin
  726
+			itlb_updating <= 0;
  727
+			if (itlb_flush_set == {addr_itlb_index_width{1'b0}})
  728
+				itlb_state <= `LM32_TLB_STATE_CHECK;
  729
+			itlb_flush_set <= itlb_flush_set - 1'b1;
  730
+		end
  731
+
  732
+		endcase
  733
+	end
  734
+end
  735
+
  736
+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'b0});
  737
+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'b0});
  738
+
  739
+reg go_to_user_mode;
  740
+reg go_to_user_mode_2;
  741
+
  742
+always @(posedge clk_i `CFG_RESET_SENSITIVITY)
  743
+begin
  744
+	if (rst_i == `TRUE)
  745
+		go_to_user_mode <= `FALSE;
  746
+	else
  747
+		go_to_user_mode <= (eret_q_x || switch_to_user_mode);
  748
+end
  749
+
  750
+always @(posedge clk_i `CFG_RESET_SENSITIVITY)
  751
+begin
  752
+	if (rst_i == `TRUE)
  753
+		go_to_user_mode_2 <= `FALSE;
  754
+	else
  755
+		go_to_user_mode_2 <= go_to_user_mode;
  756
+end
  757
+
  758
+always @(posedge clk_i `CFG_RESET_SENSITIVITY)
  759
+begin
  760
+	if (rst_i == `TRUE)
  761
+		kernel_mode_reg <= `LM32_KERNEL_MODE;
  762
+	else
  763
+	begin
  764
+		if (exception_x || switch_to_kernel_mode)
  765
+			kernel_mode_reg <= `LM32_KERNEL_MODE;
  766
+		else if (go_to_user_mode_2)
  767
+			kernel_mode_reg <= `LM32_USER_MODE;
  768
+	end
  769
+end
  770
+
444 771
 generate 
445 772
     if (bytes_per_line > 4)
446 773
     begin
43  lm32_instruction_unit.v
@@ -99,6 +99,7 @@ module lm32_instruction_unit (
99 99
     branch_target_x,
100 100
 `endif
101 101
     exception_m,
  102
+    exception_x,
102 103
     branch_taken_m,
103 104
     branch_mispredict_taken_m,
104 105
     branch_target_m,
@@ -115,6 +116,10 @@ module lm32_instruction_unit (
115 116
     irom_address_xm,
116 117
     irom_we_xm,
117 118
 `endif
  119
+    csr,
  120
+    csr_write_data,
  121
+    csr_write_enable,
  122
+    eret_q_x,
118 123
 `ifdef CFG_IWB_ENABLED
119 124
     // From Wishbone
120 125
     i_dat_i,
@@ -143,6 +148,8 @@ module lm32_instruction_unit (
143 148
 `ifdef CFG_IROM_ENABLED
144 149
     irom_data_m,
145 150
 `endif
  151
+    itlb_miss,
  152
+    csr_read_data,
146 153
 `ifdef CFG_IWB_ENABLED
147 154
     // To Wishbone
148 155
     i_dat_o,
@@ -245,6 +252,13 @@ input [`LM32_BYTE_RNG] jtag_write_data;                 // JTAG wrirte data
245 252
 input [`LM32_WORD_RNG] jtag_address;                    // JTAG read/write address
246 253
 `endif
247 254
 
  255
+input exception_x;                                      // An exception occured in the X stage
  256
+input eret_q_x;
  257
+
  258
+input [`LM32_CSR_RNG] csr;				// CSR read/write index
  259
+input [`LM32_WORD_RNG] csr_write_data;			// Data to write to specified CSR
  260
+input csr_write_enable;					// CSR write enable
  261
+
248 262
 /////////////////////////////////////////////////////
249 263
 // Outputs
250 264
 /////////////////////////////////////////////////////
@@ -327,6 +341,12 @@ wire   [`LM32_INSTRUCTION_RNG] instruction_f;
327 341
 output [`LM32_INSTRUCTION_RNG] instruction_d;           // D stage instruction to be decoded
328 342
 reg    [`LM32_INSTRUCTION_RNG] instruction_d;
329 343
 
  344
+output csr_read_data;
  345
+wire [`LM32_WORD_RNG] csr_read_data;
  346
+
  347
+output itlb_miss;
  348
+wire itlb_miss;
  349
+
330 350
 /////////////////////////////////////////////////////
331 351
 // Internal nets and registers 
332 352
 /////////////////////////////////////////////////////
@@ -340,6 +360,7 @@ reg [`LM32_PC_RNG] restart_address;                     // Address to restart fr
340 360
 `ifdef CFG_ICACHE_ENABLED
341 361
 wire icache_read_enable_f;                              // Indicates if instruction cache miss is valid
342 362
 wire [`LM32_PC_RNG] icache_refill_address;              // Address that caused cache miss
  363
+wire [`LM32_PC_RNG] icache_physical_refill_address;     // Physical address that caused cache miss
343 364
 reg icache_refill_ready;                                // Indicates when next word of refill data is ready to be written to cache
344 365
 reg [`LM32_INSTRUCTION_RNG] icache_refill_data;         // Next word of refill data, fetched from Wishbone
345 366
 wire [`LM32_INSTRUCTION_RNG] icache_data_f;             // Instruction fetched from instruction cache
@@ -373,6 +394,9 @@ reg jtag_access;                                        // Indicates if a JTAG W
373 394
 reg alternate_eba_taken;
374 395
 `endif
375 396
 
  397
+wire [`LM32_WORD_RNG] physical_address;
  398
+wire kernel_mode;
  399
+
376 400
 /////////////////////////////////////////////////////
377 401
 // Functions
378 402
 /////////////////////////////////////////////////////
@@ -454,13 +478,24 @@ lm32_icache #(
454 478
     .refill_ready           (icache_refill_ready),
455 479
     .refill_data            (icache_refill_data),
456 480
     .iflush                 (iflush),
  481
+    .csr		    (csr),
  482
+    .csr_write_data	    (csr_write_data),
  483
+    .csr_write_enable	    (csr_write_enable),
  484
+    .exception_x	    (exception_x),
  485
+    .eret_q_x		    (eret_q_x),
  486
+    .exception_m	    (exception_m),
457 487
     // ----- Outputs -----
458 488
     .stall_request          (icache_stall_request),
459 489
     .restart_request        (icache_restart_request),
460 490
     .refill_request         (icache_refill_request),
461 491
     .refill_address         (icache_refill_address),
  492
+    .physical_refill_address (icache_physical_refill_address),
462 493
     .refilling              (icache_refilling),
463  
-    .inst                   (icache_data_f)
  494
+    .inst                   (icache_data_f),
  495
+    .itlb_miss_int	    (itlb_miss),
  496
+    .kernel_mode	    (kernel_mode),
  497
+    .pa			    (physical_address),
  498
+    .csr_read_data	    (csr_read_data)
464 499
     );
465 500
 `endif
466 501
 
@@ -555,21 +590,21 @@ generate
555 590
 assign first_cycle_type = `LM32_CTYPE_END;
556 591
 assign next_cycle_type = `LM32_CTYPE_END;
557 592
 assign last_word = `TRUE;
558  
-assign first_address = icache_refill_address;
  593
+assign first_address = icache_physical_refill_address;
559 594
     end
560 595
     8:
561 596
     begin
562 597
 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
563 598
 assign next_cycle_type = `LM32_CTYPE_END;
564 599
 assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1;
565  
-assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
  600
+assign first_address = {icache_physical_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
566 601
     end
567 602
     16:
568 603
     begin
569 604
 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
570 605
 assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? `LM32_CTYPE_END : `LM32_CTYPE_INCREMENTING;
571 606
 assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11;
572  
-assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
  607
+assign first_address = {icache_physical_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
573 608
     end
574 609
     endcase
575 610
 endgenerate

0 notes on commit 3f09859

Please sign in to comment.
Something went wrong with that request. Please try again.