begin working on linux verilator simulation
[microwatt.git] / mmu.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.common.all;
7
8 -- Radix MMU
9 -- Supports 4-level trees as in arch 3.0B, but not the two-step translation for
10 -- guests under a hypervisor (i.e. there is no gRA -> hRA translation).
11
12 entity mmu is
13 port (
14 clk : in std_ulogic;
15 rst : in std_ulogic;
16
17 l_in : in Loadstore1ToMmuType;
18 l_out : out MmuToLoadstore1Type;
19
20 d_out : out MmuToDcacheType;
21 d_in : in DcacheToMmuType;
22
23 i_out : out MmuToIcacheType
24 );
25 end mmu;
26
27 architecture behave of mmu is
28
29 type state_t is (IDLE,
30 DO_TLBIE,
31 TLB_WAIT,
32 PART_TBL_READ,
33 PART_TBL_WAIT,
34 PART_TBL_DONE,
35 PROC_TBL_READ,
36 PROC_TBL_WAIT,
37 SEGMENT_CHECK,
38 RADIX_LOOKUP,
39 RADIX_READ_WAIT,
40 RADIX_LOAD_TLB,
41 RADIX_FINISH
42 );
43
44 type reg_stage_t is record
45 -- latched request from loadstore1
46 valid : std_ulogic;
47 iside : std_ulogic;
48 store : std_ulogic;
49 priv : std_ulogic;
50 addr : std_ulogic_vector(63 downto 0);
51 inval_all : std_ulogic;
52 -- config SPRs
53 ptcr : std_ulogic_vector(63 downto 0);
54 pid : std_ulogic_vector(31 downto 0);
55 -- internal state
56 state : state_t;
57 done : std_ulogic;
58 err : std_ulogic;
59 prtbl : std_ulogic_vector(63 downto 0);
60 ptb_valid : std_ulogic;
61 pgtbl0 : std_ulogic_vector(63 downto 0);
62 pt0_valid : std_ulogic;
63 pgtbl3 : std_ulogic_vector(63 downto 0);
64 pt3_valid : std_ulogic;
65 shift : unsigned(5 downto 0);
66 mask_size : unsigned(4 downto 0);
67 pgbase : std_ulogic_vector(55 downto 0);
68 pde : std_ulogic_vector(63 downto 0);
69 invalid : std_ulogic;
70 badtree : std_ulogic;
71 segerror : std_ulogic;
72 perm_err : std_ulogic;
73 rc_error : std_ulogic;
74 end record;
75
76 signal r, rin : reg_stage_t;
77
78 signal addrsh : std_ulogic_vector(15 downto 0);
79 signal mask : std_ulogic_vector(15 downto 0);
80 signal finalmask : std_ulogic_vector(43 downto 0);
81
82 begin
83 -- Multiplex internal SPR values back to loadstore1, selected
84 -- by l_in.sprn.
85 l_out.sprval <= r.ptcr when l_in.sprn(8) = '1' else x"00000000" & r.pid;
86
87 mmu_0: process(clk)
88 begin
89 if rising_edge(clk) then
90 if rst = '1' then
91 r.state <= IDLE;
92 r.valid <= '0';
93 r.ptb_valid <= '0';
94 r.pt0_valid <= '0';
95 r.pt3_valid <= '0';
96 r.ptcr <= (others => '0');
97 r.pid <= (others => '0');
98 else
99 if rin.valid = '1' then
100 report "MMU got tlb miss for " & to_hstring(rin.addr);
101 end if;
102 if l_out.done = '1' then
103 report "MMU completing op without error";
104 end if;
105 if l_out.err = '1' then
106 report "MMU completing op with err invalid=" & std_ulogic'image(l_out.invalid) &
107 " badtree=" & std_ulogic'image(l_out.badtree);
108 end if;
109 if rin.state = RADIX_LOOKUP then
110 report "radix lookup shift=" & integer'image(to_integer(rin.shift)) &
111 " msize=" & integer'image(to_integer(rin.mask_size));
112 end if;
113 if r.state = RADIX_LOOKUP then
114 report "send load addr=" & to_hstring(d_out.addr) &
115 " addrsh=" & to_hstring(addrsh) & " mask=" & to_hstring(mask);
116 end if;
117 r <= rin;
118 end if;
119 end if;
120 end process;
121
122 -- Shift address bits 61--12 right by 0--47 bits and
123 -- supply the least significant 16 bits of the result.
124 addrshifter: process(all)
125 variable sh1 : std_ulogic_vector(30 downto 0);
126 variable sh2 : std_ulogic_vector(18 downto 0);
127 variable result : std_ulogic_vector(15 downto 0);
128 begin
129 case r.shift(5 downto 4) is
130 when "00" =>
131 sh1 := r.addr(42 downto 12);
132 when "01" =>
133 sh1 := r.addr(58 downto 28);
134 when others =>
135 sh1 := "0000000000000" & r.addr(61 downto 44);
136 end case;
137 case r.shift(3 downto 2) is
138 when "00" =>
139 sh2 := sh1(18 downto 0);
140 when "01" =>
141 sh2 := sh1(22 downto 4);
142 when "10" =>
143 sh2 := sh1(26 downto 8);
144 when others =>
145 sh2 := sh1(30 downto 12);
146 end case;
147 case r.shift(1 downto 0) is
148 when "00" =>
149 result := sh2(15 downto 0);
150 when "01" =>
151 result := sh2(16 downto 1);
152 when "10" =>
153 result := sh2(17 downto 2);
154 when others =>
155 result := sh2(18 downto 3);
156 end case;
157 addrsh <= result;
158 end process;
159
160 -- generate mask for extracting address fields for PTE address generation
161 addrmaskgen: process(all)
162 variable m : std_ulogic_vector(15 downto 0);
163 begin
164 -- mask_count has to be >= 5
165 m := x"001f";
166 for i in 5 to 15 loop
167 if i < to_integer(r.mask_size) then
168 m(i) := '1';
169 end if;
170 end loop;
171 mask <= m;
172 end process;
173
174 -- generate mask for extracting address bits to go in TLB entry
175 -- in order to support pages > 4kB
176 finalmaskgen: process(all)
177 variable m : std_ulogic_vector(43 downto 0);
178 begin
179 m := (others => '0');
180 for i in 0 to 43 loop
181 if i < to_integer(r.shift) then
182 m(i) := '1';
183 end if;
184 end loop;
185 finalmask <= m;
186 end process;
187
188 mmu_1: process(all)
189 variable v : reg_stage_t;
190 variable dcreq : std_ulogic;
191 variable tlb_load : std_ulogic;
192 variable itlb_load : std_ulogic;
193 variable tlbie_req : std_ulogic;
194 variable ptbl_rd : std_ulogic;
195 variable prtbl_rd : std_ulogic;
196 variable pt_valid : std_ulogic;
197 variable effpid : std_ulogic_vector(31 downto 0);
198 variable prtable_addr : std_ulogic_vector(63 downto 0);
199 variable rts : unsigned(5 downto 0);
200 variable mbits : unsigned(5 downto 0);
201 variable pgtable_addr : std_ulogic_vector(63 downto 0);
202 variable pte : std_ulogic_vector(63 downto 0);
203 variable tlb_data : std_ulogic_vector(63 downto 0);
204 variable nonzero : std_ulogic;
205 variable pgtbl : std_ulogic_vector(63 downto 0);
206 variable perm_ok : std_ulogic;
207 variable rc_ok : std_ulogic;
208 variable addr : std_ulogic_vector(63 downto 0);
209 variable data : std_ulogic_vector(63 downto 0);
210 begin
211 v := r;
212 v.valid := '0';
213 dcreq := '0';
214 v.done := '0';
215 v.err := '0';
216 v.invalid := '0';
217 v.badtree := '0';
218 v.segerror := '0';
219 v.perm_err := '0';
220 v.rc_error := '0';
221 tlb_load := '0';
222 itlb_load := '0';
223 tlbie_req := '0';
224 v.inval_all := '0';
225 ptbl_rd := '0';
226 prtbl_rd := '0';
227
228 -- Radix tree data structures in memory are big-endian,
229 -- so we need to byte-swap them
230 for i in 0 to 7 loop
231 data(i * 8 + 7 downto i * 8) := d_in.data((7 - i) * 8 + 7 downto (7 - i) * 8);
232 end loop;
233
234 case r.state is
235 when IDLE =>
236 if l_in.addr(63) = '0' then
237 pgtbl := r.pgtbl0;
238 pt_valid := r.pt0_valid;
239 else
240 pgtbl := r.pgtbl3;
241 pt_valid := r.pt3_valid;
242 end if;
243 -- rts == radix tree size, # address bits being translated
244 rts := unsigned('0' & pgtbl(62 downto 61) & pgtbl(7 downto 5));
245 -- mbits == # address bits to index top level of tree
246 mbits := unsigned('0' & pgtbl(4 downto 0));
247 -- set v.shift to rts so that we can use finalmask for the segment check
248 v.shift := rts;
249 v.mask_size := mbits(4 downto 0);
250 v.pgbase := pgtbl(55 downto 8) & x"00";
251
252 if l_in.valid = '1' then
253 v.addr := l_in.addr;
254 v.iside := l_in.iside;
255 v.store := not (l_in.load or l_in.iside);
256 v.priv := l_in.priv;
257 if l_in.tlbie = '1' then
258 -- Invalidate all iTLB/dTLB entries for tlbie with
259 -- RB[IS] != 0 or RB[AP] != 0, or for slbia
260 v.inval_all := l_in.slbia or l_in.addr(11) or l_in.addr(10) or
261 l_in.addr(7) or l_in.addr(6) or l_in.addr(5);
262 -- The RIC field of the tlbie instruction comes across on the
263 -- sprn bus as bits 2--3. RIC=2 flushes process table caches.
264 if l_in.sprn(3) = '1' then
265 v.pt0_valid := '0';
266 v.pt3_valid := '0';
267 v.ptb_valid := '0';
268 end if;
269 v.state := DO_TLBIE;
270 else
271 v.valid := '1';
272 if r.ptb_valid = '0' then
273 -- need to fetch process table base from partition table
274 v.state := PART_TBL_READ;
275 elsif pt_valid = '0' then
276 -- need to fetch process table entry
277 -- set v.shift so we can use finalmask for generating
278 -- the process table entry address
279 v.shift := unsigned('0' & r.prtbl(4 downto 0));
280 v.state := PROC_TBL_READ;
281 elsif mbits = 0 then
282 -- Use RPDS = 0 to disable radix tree walks
283 v.state := RADIX_FINISH;
284 v.invalid := '1';
285 else
286 v.state := SEGMENT_CHECK;
287 end if;
288 end if;
289 end if;
290 if l_in.mtspr = '1' then
291 -- Move to PID needs to invalidate L1 TLBs and cached
292 -- pgtbl0 value. Move to PTCR does that plus
293 -- invalidating the cached pgtbl3 and prtbl values as well.
294 if l_in.sprn(8) = '0' then
295 v.pid := l_in.rs(31 downto 0);
296 else
297 v.ptcr := l_in.rs;
298 v.pt3_valid := '0';
299 v.ptb_valid := '0';
300 end if;
301 v.pt0_valid := '0';
302 v.inval_all := '1';
303 v.state := DO_TLBIE;
304 end if;
305
306 when DO_TLBIE =>
307 dcreq := '1';
308 tlbie_req := '1';
309 v.state := TLB_WAIT;
310
311 when TLB_WAIT =>
312 if d_in.done = '1' then
313 v.state := RADIX_FINISH;
314 end if;
315
316 when PART_TBL_READ =>
317 dcreq := '1';
318 ptbl_rd := '1';
319 v.state := PART_TBL_WAIT;
320
321 when PART_TBL_WAIT =>
322 if d_in.done = '1' then
323 v.prtbl := data;
324 v.ptb_valid := '1';
325 v.state := PART_TBL_DONE;
326 end if;
327
328 when PART_TBL_DONE =>
329 v.shift := unsigned('0' & r.prtbl(4 downto 0));
330 v.state := PROC_TBL_READ;
331
332 when PROC_TBL_READ =>
333 dcreq := '1';
334 prtbl_rd := '1';
335 v.state := PROC_TBL_WAIT;
336
337 when PROC_TBL_WAIT =>
338 if d_in.done = '1' then
339 if r.addr(63) = '1' then
340 v.pgtbl3 := data;
341 v.pt3_valid := '1';
342 else
343 v.pgtbl0 := data;
344 v.pt0_valid := '1';
345 end if;
346 -- rts == radix tree size, # address bits being translated
347 rts := unsigned('0' & data(62 downto 61) & data(7 downto 5));
348 -- mbits == # address bits to index top level of tree
349 mbits := unsigned('0' & data(4 downto 0));
350 -- set v.shift to rts so that we can use finalmask for the segment check
351 v.shift := rts;
352 v.mask_size := mbits(4 downto 0);
353 v.pgbase := data(55 downto 8) & x"00";
354 if mbits = 0 then
355 v.state := RADIX_FINISH;
356 v.invalid := '1';
357 else
358 v.state := SEGMENT_CHECK;
359 end if;
360 end if;
361 if d_in.err = '1' then
362 v.state := RADIX_FINISH;
363 v.badtree := '1';
364 end if;
365
366 when SEGMENT_CHECK =>
367 mbits := '0' & r.mask_size;
368 v.shift := r.shift + (31 - 12) - mbits;
369 nonzero := or(r.addr(61 downto 31) and not finalmask(30 downto 0));
370 if r.addr(63) /= r.addr(62) or nonzero = '1' then
371 v.state := RADIX_FINISH;
372 v.segerror := '1';
373 elsif mbits < 5 or mbits > 16 or mbits > (r.shift + (31 - 12)) then
374 v.state := RADIX_FINISH;
375 v.badtree := '1';
376 else
377 v.state := RADIX_LOOKUP;
378 end if;
379
380 when RADIX_LOOKUP =>
381 dcreq := '1';
382 v.state := RADIX_READ_WAIT;
383
384 when RADIX_READ_WAIT =>
385 if d_in.done = '1' then
386 v.pde := data;
387 -- test valid bit
388 if data(63) = '1' then
389 -- test leaf bit
390 if data(62) = '1' then
391 -- check permissions and RC bits
392 perm_ok := '0';
393 if r.priv = '1' or data(3) = '0' then
394 if r.iside = '0' then
395 perm_ok := data(1) or (data(2) and not r.store);
396 else
397 -- no IAMR, so no KUEP support for now
398 -- deny execute permission if cache inhibited
399 perm_ok := data(0) and not data(5);
400 end if;
401 end if;
402 rc_ok := data(8) and (data(7) or not r.store);
403 if perm_ok = '1' and rc_ok = '1' then
404 v.state := RADIX_LOAD_TLB;
405 else
406 v.state := RADIX_FINISH;
407 v.perm_err := not perm_ok;
408 -- permission error takes precedence over RC error
409 v.rc_error := perm_ok;
410 end if;
411 else
412 mbits := unsigned('0' & data(4 downto 0));
413 if mbits < 5 or mbits > 16 or mbits > r.shift then
414 v.state := RADIX_FINISH;
415 v.badtree := '1';
416 else
417 v.shift := v.shift - mbits;
418 v.mask_size := mbits(4 downto 0);
419 v.pgbase := data(55 downto 8) & x"00";
420 v.state := RADIX_LOOKUP;
421 end if;
422 end if;
423 else
424 -- non-present PTE, generate a DSI
425 v.state := RADIX_FINISH;
426 v.invalid := '1';
427 end if;
428 end if;
429 if d_in.err = '1' then
430 v.state := RADIX_FINISH;
431 v.badtree := '1';
432 end if;
433
434 when RADIX_LOAD_TLB =>
435 tlb_load := '1';
436 if r.iside = '0' then
437 dcreq := '1';
438 v.state := TLB_WAIT;
439 else
440 itlb_load := '1';
441 v.state := IDLE;
442 end if;
443
444 when RADIX_FINISH =>
445 v.state := IDLE;
446
447 end case;
448
449 if v.state = RADIX_FINISH or (v.state = RADIX_LOAD_TLB and r.iside = '1') then
450 v.err := v.invalid or v.badtree or v.segerror or v.perm_err or v.rc_error;
451 v.done := not v.err;
452 end if;
453
454 if r.addr(63) = '1' then
455 effpid := x"00000000";
456 else
457 effpid := r.pid;
458 end if;
459 prtable_addr := x"00" & r.prtbl(55 downto 36) &
460 ((r.prtbl(35 downto 12) and not finalmask(23 downto 0)) or
461 (effpid(31 downto 8) and finalmask(23 downto 0))) &
462 effpid(7 downto 0) & "0000";
463
464 pgtable_addr := x"00" & r.pgbase(55 downto 19) &
465 ((r.pgbase(18 downto 3) and not mask) or (addrsh and mask)) &
466 "000";
467 pte := x"00" &
468 ((r.pde(55 downto 12) and not finalmask) or (r.addr(55 downto 12) and finalmask))
469 & r.pde(11 downto 0);
470
471 -- update registers
472 rin <= v;
473
474 -- drive outputs
475 if tlbie_req = '1' then
476 addr := r.addr;
477 tlb_data := (others => '0');
478 elsif tlb_load = '1' then
479 addr := r.addr(63 downto 12) & x"000";
480 tlb_data := pte;
481 elsif ptbl_rd = '1' then
482 addr := x"00" & r.ptcr(55 downto 12) & x"008";
483 tlb_data := (others => '0');
484 elsif prtbl_rd = '1' then
485 addr := prtable_addr;
486 tlb_data := (others => '0');
487 else
488 addr := pgtable_addr;
489 tlb_data := (others => '0');
490 end if;
491
492 l_out.done <= r.done;
493 l_out.err <= r.err;
494 l_out.invalid <= r.invalid;
495 l_out.badtree <= r.badtree;
496 l_out.segerr <= r.segerror;
497 l_out.perm_error <= r.perm_err;
498 l_out.rc_error <= r.rc_error;
499
500 d_out.valid <= dcreq;
501 d_out.tlbie <= tlbie_req;
502 d_out.doall <= r.inval_all;
503 d_out.tlbld <= tlb_load;
504 d_out.addr <= addr;
505 d_out.pte <= tlb_data;
506
507 i_out.tlbld <= itlb_load;
508 i_out.tlbie <= tlbie_req;
509 i_out.doall <= r.inval_all;
510 i_out.addr <= addr;
511 i_out.pte <= tlb_data;
512
513 end process;
514 end;