- icache_areq_o.fetch_valid = 1'b0;
-
- # 4K page
- icache_areq_o.fetch_paddr = {itlb_content.ppn, icache_areq_i.fetch_vaddr[11:0]};
- # Mega page
- if (itlb_is_2M) begin
- icache_areq_o.fetch_paddr[20:12] = icache_areq_i.fetch_vaddr[20:12];
- end
- # Giga page
- if (itlb_is_1G) begin
- icache_areq_o.fetch_paddr[29:12] = icache_areq_i.fetch_vaddr[29:12];
- end
-
- # ---------
- # ITLB Hit
- # --------
- # if we hit the ITLB output the request signal immediately
- if (itlb_lu_hit) begin
- icache_areq_o.fetch_valid = icache_areq_i.fetch_req;
- # we got an access error
- if (iaccess_err) begin
- # throw a page fault
- icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, icache_areq_i.fetch_vaddr, 1'b1};
- end
- end else
- # ---------
- # ITLB Miss
- # ---------
- # watch out for exceptions happening during walking the page table
- if (ptw_active && walking_instr) begin
- icache_areq_o.fetch_valid = ptw_error;
- icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
- end
+ # MMU disabled: just pass through
+ m.d.comb += [icache_areq_o.fetch_valid.eq(icache_areq_i.fetch_req),
+ # play through in case we disabled address translation
+ icache_areq_o.fetch_paddr.eq(icache_areq_i.fetch_vaddr)
+ ]
+ # two potential exception sources:
+ # 1. HPTW threw an exception -> signal with a page fault exception
+ # 2. We got an access error because of insufficient permissions ->
+ # throw an access exception
+ m.d.comb += icache_areq_o.fetch_exception.eq(0)
+ # Check whether we are allowed to access this memory region
+ # from a fetch perspective
+ m.d.comb += iaccess_err.eq(icache_areq_i.fetch_req & \
+ (((priv_lvl_i == PRIV_LVL_U) & \
+ ~itlb_content.u) | \
+ ((priv_lvl_i == :PRIV_LVL_S) & \
+ itlb_content.u)))
+
+ # MMU enabled: address from TLB, request delayed until hit.
+ # Error when TLB hit and no access right or TLB hit and
+ # translated address not valid (e.g. AXI decode error),
+ # or when PTW performs walk due to ITLB miss and raises
+ # an error.
+ with m.If (self.enable_translation_i):
+ # we work with SV39, so if VM is enabled, check that
+ # all bits [63:38] are equal
+ with m.If (icache_areq_i.fetch_req & \
+ ~(((~icache_areq_i.fetch_vaddr[38:64]) == 0) | \
+ (icache_areq_i.fetch_vaddr[38:64]) == 0)):
+ fe = icache_areq_o.fetch_exception
+ m.d.comb += [fe.cause.eq(INSTR_ACCESS_FAULT),
+ fe.tval.eq(icache_areq_i.fetch_vaddr),
+ fe.valid.eq(1)
+ ]
+
+ m.d.comb += icache_areq_o.fetch_valid.eq(0)
+
+ # 4K page
+ paddr = Signal.like(icache_areq_o.fetch_paddr)
+ paddr4k = Cat(icache_areq_i.fetch_vaddr[0:12], itlb_content.ppn)
+ m.d.comb += paddr.eq(paddr4k)
+ # Mega page
+ with m.If(itlb_is_2M):
+ m.d.comb += paddr[12:21].eq(icache_areq_i.fetch_vaddr[12:21])