-- Signals to complete (possibly with error)
ls_valid : std_ulogic;
+ ls_error : std_ulogic;
mmu_done : std_ulogic;
- error_done : std_ulogic;
+ mmu_error : std_ulogic;
cache_paradox : std_ulogic;
-- Signal to complete a failed stcx.
req_row <= get_row(r0.req.addr);
req_tag <= get_tag(ra);
- go := r0_valid and not (r0.tlbie or r0.tlbld) and not r1.error_done;
+ go := r0_valid and not (r0.tlbie or r0.tlbld) and not r1.ls_error;
-- Test if pending request is a hit on any way
-- In order to make timing in virtual mode, when we are using the TLB,
d_out.valid <= r1.ls_valid;
d_out.data <= data_out;
d_out.store_done <= not r1.stcx_fail;
- d_out.error <= r1.error_done;
+ d_out.error <= r1.ls_error;
d_out.cache_paradox <= r1.cache_paradox;
-- Outputs to MMU
m_out.done <= r1.mmu_done;
- m_out.err <= r1.error_done;
+ m_out.err <= r1.mmu_error;
m_out.data <= data_out;
-- We have a valid load or store hit or we just completed a slow
end if;
-- error cases complete without stalling
- if r1.error_done = '1' then
+ if r1.ls_error = '1' then
report "completing ld/st with error";
end if;
end if;
-- error cases complete without stalling
- if r1.error_done = '1' then
+ if r1.mmu_error = '1' then
report "completing MMU ld with error";
end if;
if req_op = OP_BAD then
report "Signalling ld/st error valid_ra=" & std_ulogic'image(valid_ra) &
" rc_ok=" & std_ulogic'image(rc_ok) & " perm_ok=" & std_ulogic'image(perm_ok);
- r1.error_done <= '1';
+ r1.ls_error <= not r0.mmu_req;
+ r1.mmu_error <= r0.mmu_req;
r1.cache_paradox <= access_ok;
else
- r1.error_done <= '0';
+ r1.ls_error <= '0';
+ r1.mmu_error <= '0';
r1.cache_paradox <= '0';
end if;
r1.ls_valid <= '0';
-- complete tlbies and TLB loads in the third cycle
r1.mmu_done <= r0_valid and (r0.tlbie or r0.tlbld);
- if req_op = OP_LOAD_HIT or req_op = OP_BAD or req_op = OP_STCX_FAIL then
+ if req_op = OP_LOAD_HIT or req_op = OP_STCX_FAIL then
if r0.mmu_req = '0' then
r1.ls_valid <= '1';
else
v.last_dword := '0';
when ACK_WAIT =>
+ if d_in.error = '1' then
+ -- dcache will discard the second request if it
+ -- gets an error on the 1st of two requests
+ if r.dwords_done = '1' then
+ addr := next_addr;
+ else
+ addr := r.addr;
+ end if;
+ if d_in.cache_paradox = '1' then
+ -- signal an interrupt straight away
+ exception := '1';
+ dsisr(63 - 38) := not r.load;
+ -- XXX there is no architected bit for this
+ dsisr(63 - 35) := d_in.cache_paradox;
+ v.state := IDLE;
+ else
+ -- Look up the translation for TLB miss
+ -- and also for permission error and RC error
+ -- in case the PTE has been updated.
+ mmureq := '1';
+ v.state := MMU_LOOKUP;
+ end if;
+ end if;
if d_in.valid = '1' then
- if d_in.error = '1' then
- -- dcache will discard the second request if it
- -- gets an error on the 1st of two requests
- if r.dwords_done = '1' then
- addr := next_addr;
- else
- addr := r.addr;
- end if;
- if d_in.cache_paradox = '1' then
- -- signal an interrupt straight away
- exception := '1';
- dsisr(63 - 38) := not r.load;
- -- XXX there is no architected bit for this
- dsisr(63 - 35) := d_in.cache_paradox;
- v.state := IDLE;
- else
- -- Look up the translation for TLB miss
- -- and also for permission error and RC error
- -- in case the PTE has been updated.
- mmureq := '1';
- v.state := MMU_LOOKUP;
+ if r.last_dword = '0' then
+ v.dwords_done := '1';
+ v.last_dword := '1';
+ if r.load = '1' then
+ v.load_data := data_permuted;
end if;
else
- if r.last_dword = '0' then
- v.dwords_done := '1';
- v.last_dword := '1';
- if r.load = '1' then
- v.load_data := data_permuted;
- end if;
+ write_enable := r.load;
+ if r.load = '1' and r.update = '1' then
+ -- loads with rA update need an extra cycle
+ v.state := LD_UPDATE;
else
- write_enable := r.load;
- if r.load = '1' and r.update = '1' then
- -- loads with rA update need an extra cycle
- v.state := LD_UPDATE;
- else
- -- stores write back rA update in this cycle
- do_update := r.update;
- done := '1';
- v.state := IDLE;
- end if;
+ -- stores write back rA update in this cycle
+ do_update := r.update;
+ done := '1';
+ v.state := IDLE;
end if;
end if;
end if;
when PROC_TBL_WAIT =>
if d_in.done = '1' then
- if d_in.err = '0' then
- if r.addr(63) = '1' then
- v.pgtbl3 := data;
- v.pt3_valid := '1';
- else
- v.pgtbl0 := data;
- v.pt0_valid := '1';
- end if;
- -- rts == radix tree size, # address bits being translated
- rts := unsigned('0' & data(62 downto 61) & data(7 downto 5));
- -- mbits == # address bits to index top level of tree
- mbits := unsigned('0' & data(4 downto 0));
- -- set v.shift to rts so that we can use finalmask for the segment check
- v.shift := rts;
- v.mask_size := mbits(4 downto 0);
- v.pgbase := data(55 downto 8) & x"00";
- if mbits = 0 then
- v.state := RADIX_FINISH;
- v.invalid := '1';
- else
- v.state := SEGMENT_CHECK;
- end if;
+ if r.addr(63) = '1' then
+ v.pgtbl3 := data;
+ v.pt3_valid := '1';
else
+ v.pgtbl0 := data;
+ v.pt0_valid := '1';
+ end if;
+ -- rts == radix tree size, # address bits being translated
+ rts := unsigned('0' & data(62 downto 61) & data(7 downto 5));
+ -- mbits == # address bits to index top level of tree
+ mbits := unsigned('0' & data(4 downto 0));
+ -- set v.shift to rts so that we can use finalmask for the segment check
+ v.shift := rts;
+ v.mask_size := mbits(4 downto 0);
+ v.pgbase := data(55 downto 8) & x"00";
+ if mbits = 0 then
v.state := RADIX_FINISH;
- v.badtree := '1';
+ v.invalid := '1';
+ else
+ v.state := SEGMENT_CHECK;
end if;
end if;
+ if d_in.err = '1' then
+ v.state := RADIX_FINISH;
+ v.badtree := '1';
+ end if;
when SEGMENT_CHECK =>
mbits := '0' & r.mask_size;
when RADIX_READ_WAIT =>
if d_in.done = '1' then
- if d_in.err = '0' then
- v.pde := data;
- -- test valid bit
- if data(63) = '1' then
- -- test leaf bit
- if data(62) = '1' then
- -- check permissions and RC bits
- perm_ok := '0';
- if r.priv = '1' or data(3) = '0' then
- if r.iside = '0' then
- perm_ok := data(1) or (data(2) and not r.store);
- else
- -- no IAMR, so no KUEP support for now
- -- deny execute permission if cache inhibited
- perm_ok := data(0) and not data(5);
- end if;
- end if;
- rc_ok := data(8) and (data(7) or not r.store);
- if perm_ok = '1' and rc_ok = '1' then
- v.state := RADIX_LOAD_TLB;
+ v.pde := data;
+ -- test valid bit
+ if data(63) = '1' then
+ -- test leaf bit
+ if data(62) = '1' then
+ -- check permissions and RC bits
+ perm_ok := '0';
+ if r.priv = '1' or data(3) = '0' then
+ if r.iside = '0' then
+ perm_ok := data(1) or (data(2) and not r.store);
else
- v.state := RADIX_FINISH;
- v.perm_err := not perm_ok;
- -- permission error takes precedence over RC error
- v.rc_error := perm_ok;
+ -- no IAMR, so no KUEP support for now
+ -- deny execute permission if cache inhibited
+ perm_ok := data(0) and not data(5);
end if;
+ end if;
+ rc_ok := data(8) and (data(7) or not r.store);
+ if perm_ok = '1' and rc_ok = '1' then
+ v.state := RADIX_LOAD_TLB;
else
- mbits := unsigned('0' & data(4 downto 0));
- if mbits < 5 or mbits > 16 or mbits > r.shift then
- v.state := RADIX_FINISH;
- v.badtree := '1';
- else
- v.shift := v.shift - mbits;
- v.mask_size := mbits(4 downto 0);
- v.pgbase := data(55 downto 8) & x"00";
- v.state := RADIX_LOOKUP;
- end if;
+ v.state := RADIX_FINISH;
+ v.perm_err := not perm_ok;
+ -- permission error takes precedence over RC error
+ v.rc_error := perm_ok;
end if;
else
- -- non-present PTE, generate a DSI
- v.state := RADIX_FINISH;
- v.invalid := '1';
+ mbits := unsigned('0' & data(4 downto 0));
+ if mbits < 5 or mbits > 16 or mbits > r.shift then
+ v.state := RADIX_FINISH;
+ v.badtree := '1';
+ else
+ v.shift := v.shift - mbits;
+ v.mask_size := mbits(4 downto 0);
+ v.pgbase := data(55 downto 8) & x"00";
+ v.state := RADIX_LOOKUP;
+ end if;
end if;
else
+ -- non-present PTE, generate a DSI
v.state := RADIX_FINISH;
- v.badtree := '1';
+ v.invalid := '1';
end if;
end if;
+ if d_in.err = '1' then
+ v.state := RADIX_FINISH;
+ v.badtree := '1';
+ end if;
when RADIX_LOAD_TLB =>
tlb_load := '1';