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
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
0 commit comments