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