+ def elaborate(self, platform):
+ iaccess_err = Signal() # insufficient priv to access instr page
+ daccess_err = Signal() # insufficient priv to access data page
+ ptw_active = Signal() # PTW is currently walking a page table
+ walking_instr = Signal() # PTW is walking because of an ITLB miss
+ ptw_error = Signal() # PTW threw an exception
+
+ update_vaddr = Signal(39)
+ update_ptw_itlb = TLBUpdate()
+ update_ptw_dtlb = TLBUpdate()
+
+ itlb_lu_access = Signal()
+ itlb_content = PTE()
+ itlb_is_2M = Signal()
+ itlb_is_1G = Signal()
+ itlb_lu_hit = Signal()
+
+ dtlb_lu_access = Signal()
+ dtlb_content = PTE()
+ dtlb_is_2M = Signal()
+ dtlb_is_1G = Signal()
+ dtlb_lu_hit = Signal()
+
+ # Assignments
+ m.d.comb += [itlb_lu_access.eq(icache_areq_i.fetch_req),
+ dtlb_lu_access.eq(lsu_req_i)
+ ]
+
+
+ # ITLB
+ m.submodules.i_tlb = i_tlb = TLB(INSTR_TLB_ENTRIES, ASID_WIDTH)
+ m.d.comb += [i_tlb.flush_i.eq(flush_tlb_i),
+ i_tlb.update_i.eq(update_ptw_itlb),
+ i_tlb.lu_access_i.eq(itlb_lu_access),
+ i_tlb.lu_asid_i.eq(asid_i),
+ i_tlb.lu_vaddr_i.eq(icache_areq_i.fetch_vaddr),
+ itlb_content.eq(i_tlb.lu_content_o),
+ itlb_is_2M.eq(i_tlb.lu_is_2M_o),
+ itlb_is_1G.eq(i_tlb.lu_is_1G_o),
+ itlb_lu_hit.eq(i_tlb.lu_hit_o),
+ ]
+
+ # DTLB
+ m.submodules.d_tlb = d_tlb = TLB(DATA_TLB_ENTRIES, ASID_WIDTH)
+ m.d.comb += [d_tlb.flush_i.eq(flush_tlb_i),
+ d_tlb.update_i.eq(update_ptw_dtlb),
+ d_tlb.lu_access_i.eq(dtlb_lu_access),
+ d_tlb.lu_asid_i.eq(asid_i),
+ d_tlb.lu_vaddr_i.eq(lsu_vaddr_i),
+ dtlb_content.eq(d_tlb.lu_content_o),
+ dtlb_is_2M.eq(d_tlb.lu_is_2M_o),
+ dtlb_is_1G.eq(d_tlb.lu_is_1G_o),
+ dtlb_lu_hit.eq(d_tlb.lu_hit_o),
+ ]
+
+ ptw #(
+ .ASID_WIDTH ( ASID_WIDTH )
+ ) i_ptw (
+ .clk_i ( clk_i ),
+ .rst_ni ( rst_ni ),
+ .ptw_active_o ( ptw_active ),
+ .walking_instr_o ( walking_instr ),
+ .ptw_error_o ( ptw_error ),
+ .enable_translation_i ( enable_translation_i ),
+
+ .update_vaddr_o ( update_vaddr ),
+ .itlb_update_o ( update_ptw_itlb ),
+ .dtlb_update_o ( update_ptw_dtlb ),
+
+ .itlb_access_i ( itlb_lu_access ),
+ .itlb_hit_i ( itlb_lu_hit ),
+ .itlb_vaddr_i ( icache_areq_i.fetch_vaddr ),
+
+ .dtlb_access_i ( dtlb_lu_access ),
+ .dtlb_hit_i ( dtlb_lu_hit ),
+ .dtlb_vaddr_i ( lsu_vaddr_i ),
+
+ .req_port_i ( req_port_i ),
+ .req_port_o ( req_port_o ),
+
+ .*
+ );
+
+ # ila_1 i_ila_1 (
+ # .clk(clk_i), # input wire clk
+ # .probe0({req_port_o.address_tag, req_port_o.address_index}),
+ # .probe1(req_port_o.data_req), # input wire [63:0] probe1
+ # .probe2(req_port_i.data_gnt), # input wire [0:0] probe2
+ # .probe3(req_port_i.data_rdata), # input wire [0:0] probe3
+ # .probe4(req_port_i.data_rvalid), # input wire [0:0] probe4
+ # .probe5(ptw_error), # input wire [1:0] probe5
+ # .probe6(update_vaddr), # input wire [0:0] probe6
+ # .probe7(update_ptw_itlb.valid), # input wire [0:0] probe7
+ # .probe8(update_ptw_dtlb.valid), # input wire [0:0] probe8
+ # .probe9(dtlb_lu_access), # input wire [0:0] probe9
+ # .probe10(lsu_vaddr_i), # input wire [0:0] probe10
+ # .probe11(dtlb_lu_hit), # input wire [0:0] probe11
+ # .probe12(itlb_lu_access), # input wire [0:0] probe12
+ # .probe13(icache_areq_i.fetch_vaddr), # input wire [0:0] probe13
+ # .probe14(itlb_lu_hit) # input wire [0:0] probe13
+ # );
+
+ #-----------------------
+ # Instruction Interface
+ #-----------------------
+ # The instruction interface is a simple request response interface
+ always_comb begin : instr_interface
+ # MMU disabled: just pass through
+ icache_areq_o.fetch_valid = icache_areq_i.fetch_req;
+ icache_areq_o.fetch_paddr = icache_areq_i.fetch_vaddr; # play through in case we disabled address translation
+ # 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
+ icache_areq_o.fetch_exception = '0;
+ # Check whether we are allowed to access this memory region from a fetch perspective
+ iaccess_err = icache_areq_i.fetch_req && (((priv_lvl_i == riscv::PRIV_LVL_U) && ~itlb_content.u)
+ || ((priv_lvl_i == riscv::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.
+ if (enable_translation_i) begin
+ # we work with SV39, so if VM is enabled, check that all bits [63:38] are equal
+ if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[63:38]) == 1'b1 || (|icache_areq_i.fetch_vaddr[63:38]) == 1'b0)) begin
+ icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, icache_areq_i.fetch_vaddr, 1'b1};
+ end