diff --git a/src/main/scala/lsu/el2_lsu_addrcheck.scala b/src/main/scala/lsu/el2_lsu_addrcheck.scala new file mode 100644 index 00000000..ee15d89b --- /dev/null +++ b/src/main/scala/lsu/el2_lsu_addrcheck.scala @@ -0,0 +1,188 @@ +class el2_lsu_addrcheck extends MultiIOModule +{ + val lsu_c2_m_clk = IO(Input(Clock())) + //val rst_l = IO(Input(1.W)) //implicit + val start_addr_d = IO(Input(UInt(32.W))) + val end_addr_d = IO(Input(UInt(32.W))) + val lsu_pkt_d = IO(Input(new el2_lsu_pkt_t)) + val dec_tlu_mrac_ff = IO(Input(UInt(32.W))) + val rs1_region_d = IO(Input(UInt(4.W))) + val rs1_d = IO(Input(UInt(32.W))) + val is_sideeffects_m = IO(Output(UInt(1.W))) + val addr_in_dccm_d = IO(Output(UInt(1.W))) + val addr_in_pic_d = IO(Output(UInt(1.W))) + val addr_external_d = IO(Output(UInt(1.W))) + val access_fault_d = IO(Output(UInt(1.W))) + val misaligned_fault_d = IO(Output(UInt(1.W))) + val exc_mscause_d = IO(Output(UInt(4.W))) + val fir_dccm_access_error_d = IO(Output(UInt(1.W))) + val fir_nondccm_access_error_d = IO(Output(UInt(1.W))) + val scan_mode = IO(Input(UInt(1.W))) + + val start_addr_in_dccm_d = WireInit(0.U(1.W)) + val start_addr_in_dccm_region_d = WireInit(0.U(1.W)) + val end_addr_in_dccm_d = WireInit(0.U(1.W)) + val end_addr_in_dccm_region_d = WireInit(0.U(1.W)) + + //DCCM check + // Start address check + if(pt1.DCCM_ENABLE==1){ // Gen_dccm_enable + val start_addr_dccm_rangecheck = Module(new rvrangecheck(pt1.DCCM_SADR,pt1.DCCM_SIZE)) + start_addr_dccm_rangecheck.io.addr := start_addr_d + start_addr_in_dccm_d := start_addr_dccm_rangecheck.io.in_range + start_addr_in_dccm_region_d := start_addr_dccm_rangecheck.io.in_region + + // End address check + val end_addr_dccm_rangecheck = Module(new rvrangecheck(pt1.DCCM_SADR,pt1.DCCM_SIZE)) + end_addr_dccm_rangecheck.io.addr := end_addr_d + end_addr_in_dccm_d := end_addr_dccm_rangecheck.io.in_range + end_addr_in_dccm_region_d := end_addr_dccm_rangecheck.io.in_region + } + else{ //Gen_dccm_disable + start_addr_in_dccm_d := 0.U + start_addr_in_dccm_region_d := 0.U + end_addr_in_dccm_d := 0.U + end_addr_in_dccm_region_d := 0.U + } + + val addr_in_iccm = WireInit(0.U(1.W)) + if(pt1.ICCM_ENABLE == 1){ //check_iccm + addr_in_iccm := (start_addr_d(31,28) === pt.ICCM_REGION) + } + else{ + addr_in_iccm := 1.U + } + + + //PIC memory check + //start address check + val start_addr_pic_rangecheck = Module(new rvrangecheck(pt1.PIC_BASE_ADDR,pt1.PIC_SIZE)) + start_addr_pic_rangecheck.io.addr := start_addr_d(31,0) + val start_addr_in_pic_d = start_addr_pic_rangecheck.io.in_range + val start_addr_in_pic_region_d = start_addr_pic_rangecheck.io.in_region + + //End address check + val end_addr_pic_rangecheck = Module(new rvrangecheck(pt1.PIC_BASE_ADDR,pt1.PIC_SIZE)) + end_addr_pic_rangecheck.io.addr := end_addr_d(31,0) + val end_addr_in_pic_d = end_addr_pic_rangecheck.io.in_range + val end_addr_in_pic_region_d = end_addr_pic_rangecheck.io.in_region + + val start_addr_dccm_or_pic = start_addr_in_dccm_region_d | start_addr_in_pic_region_d + val base_reg_dccm_or_pic = (rs1_region_d(3,0) === pt.DCCM_REGION) | (rs1_region_d(3,0) === pt.PIC_REGION) //base region + addr_in_dccm_d := (start_addr_in_dccm_d & end_addr_in_dccm_d) + addr_in_pic_d := (start_addr_in_pic_d & end_addr_in_pic_d) + + addr_external_d := ~(start_addr_in_dccm_region_d | start_addr_in_pic_region_d); //if start address does not belong to dccm/pic + val csr_idx = Cat(start_addr_d(31,28),"b1".U) + val is_sideeffects_d = dec_tlu_mrac_ff(csr_idx) & ~(start_addr_in_dccm_region_d | start_addr_in_pic_region_d | addr_in_iccm) & lsu_pkt_d.valid & (lsu_pkt_d.store | lsu_pkt_d.load) //every region has the 2 LSB indicating ( 1: sideeffects/no_side effects, and 0: cacheable ). Ignored in internal regions + val is_aligned_d = (lsu_pkt_d.word & (start_addr_d(1,0) === "b00".U)) | (lsu_pkt_d.half & (start_addr_d(0) === "b0".U)) | lsu_pkt_d.by + + + val non_dccm_access_ok = (~(Cat(pt.DATA_ACCESS_ENABLE0,pt.DATA_ACCESS_ENABLE1,pt.DATA_ACCESS_ENABLE2,pt.DATA_ACCESS_ENABLE3, + pt.DATA_ACCESS_ENABLE4,pt.DATA_ACCESS_ENABLE5,pt.DATA_ACCESS_ENABLE6,pt.DATA_ACCESS_ENABLE7)).orR) | +(((pt.DATA_ACCESS_ENABLE0 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK0)) === (pt.DATA_ACCESS_ADDR0 | pt.DATA_ACCESS_MASK0)) | //0111 + (pt.DATA_ACCESS_ENABLE1 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK1)) === (pt.DATA_ACCESS_ADDR1 | pt.DATA_ACCESS_MASK1)) | //1111 + (pt.DATA_ACCESS_ENABLE2 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK2)) === (pt.DATA_ACCESS_ADDR2 | pt.DATA_ACCESS_MASK2)) | //1011 + (pt.DATA_ACCESS_ENABLE3 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK3)) === (pt.DATA_ACCESS_ADDR3 | pt.DATA_ACCESS_MASK3)) | //1000 + (pt.DATA_ACCESS_ENABLE4 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK4)) === (pt.DATA_ACCESS_ADDR4 | pt.DATA_ACCESS_MASK4)) | + (pt.DATA_ACCESS_ENABLE5 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK5)) === (pt.DATA_ACCESS_ADDR5 | pt.DATA_ACCESS_MASK5)) | + (pt.DATA_ACCESS_ENABLE6 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK6)) === (pt.DATA_ACCESS_ADDR6 | pt.DATA_ACCESS_MASK6)) | + (pt.DATA_ACCESS_ENABLE7 & ((start_addr_d(31,0) | pt.DATA_ACCESS_MASK7)) === (pt.DATA_ACCESS_ADDR7 | pt.DATA_ACCESS_MASK7))) + & + ((pt.DATA_ACCESS_ENABLE0 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK0)) === (pt.DATA_ACCESS_ADDR0 | pt.DATA_ACCESS_MASK0)) | + (pt.DATA_ACCESS_ENABLE1 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK1)) === (pt.DATA_ACCESS_ADDR1 | pt.DATA_ACCESS_MASK1)) | + (pt.DATA_ACCESS_ENABLE2 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK2)) === (pt.DATA_ACCESS_ADDR2 | pt.DATA_ACCESS_MASK2)) | + (pt.DATA_ACCESS_ENABLE3 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK3)) === (pt.DATA_ACCESS_ADDR3 | pt.DATA_ACCESS_MASK3)) | + (pt.DATA_ACCESS_ENABLE4 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK4)) === (pt.DATA_ACCESS_ADDR4 | pt.DATA_ACCESS_MASK4)) | + (pt.DATA_ACCESS_ENABLE5 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK5)) === (pt.DATA_ACCESS_ADDR5 | pt.DATA_ACCESS_MASK5)) | + (pt.DATA_ACCESS_ENABLE6 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK6)) === (pt.DATA_ACCESS_ADDR6 | pt.DATA_ACCESS_MASK6)) | + (pt.DATA_ACCESS_ENABLE7 & ((end_addr_d(31,0) | pt.DATA_ACCESS_MASK7)) === (pt.DATA_ACCESS_ADDR7 | pt.DATA_ACCESS_MASK7)))) + + val regpred_access_fault_d = (start_addr_dccm_or_pic ^ base_reg_dccm_or_pic) + val picm_access_fault_d = (addr_in_pic_d & ((start_addr_d(1,0) != "b00".U) | ~lsu_pkt_d.word)) + + + val unmapped_access_fault_d = WireInit(1.U(1.W)) + val mpu_access_fault_d = WireInit(1.U(1.W)) + + + if(pt1.DCCM_REGION == pt1.PIC_REGION){ + unmapped_access_fault_d := ((start_addr_in_dccm_region_d & ~(start_addr_in_dccm_d | start_addr_in_pic_d)) | + // 0. Addr in dccm/pic region but not in dccm/pic offset + (end_addr_in_dccm_region_d & ~(end_addr_in_dccm_d | end_addr_in_pic_d)) | + // 0. Addr in dccm/pic region but not in dccm/pic offset + (start_addr_in_dccm_d & end_addr_in_pic_d) | + // 0. DCCM -> PIC cross when DCCM/PIC in same region + (start_addr_in_pic_d & end_addr_in_dccm_d)) + // 0. DCCM -> PIC cross when DCCM/PIC in same region + + + + mpu_access_fault_d := (~start_addr_in_dccm_region_d & ~non_dccm_access_ok) + // 3. Address is not in a populated non-dccm region + } + + else{ + + unmapped_access_fault_d := ((start_addr_in_dccm_region_d & ~start_addr_in_dccm_d) | + // 0. Addr in dccm region but not in dccm offset + (end_addr_in_dccm_region_d & ~end_addr_in_dccm_d) | + // 0. Addr in dccm region but not in dccm offset + (start_addr_in_pic_region_d & ~start_addr_in_pic_d) | + // 0. Addr in picm region but not in picm offset + (end_addr_in_pic_region_d & ~end_addr_in_pic_d)) + + // 0. Addr in picm region but not in picm offset + + + mpu_access_fault_d := (~start_addr_in_pic_region_d & ~start_addr_in_dccm_region_d & ~non_dccm_access_ok); + // 3. Address is not in a populated non-dccm region + } + + //check width of access_fault_mscause_d + + access_fault_d := (unmapped_access_fault_d | mpu_access_fault_d | picm_access_fault_d | regpred_access_fault_d) & lsu_pkt_d.valid & ~lsu_pkt_d.dma + val access_fault_mscause_d = WireInit(0.U(4.W)) + access_fault_mscause_d := Mux(unmapped_access_fault_d.asBool, "b0010".U, Mux(mpu_access_fault_d.asBool, "b0011".U, Mux(regpred_access_fault_d.asBool, "b0101".U, Mux(picm_access_fault_d.asBool, "b0110".U, "b0000".U)))) + + + + val regcross_misaligned_fault_d = (start_addr_d(31,28) =/= end_addr_d(31,28)) + val sideeffect_misaligned_fault_d = (is_sideeffects_d & ~ is_aligned_d) + + + misaligned_fault_d := (regcross_misaligned_fault_d | (sideeffect_misaligned_fault_d & addr_external_d)) & lsu_pkt_d.valid & ~lsu_pkt_d.dma + + + val misaligned_fault_mscause_d = WireInit(0.U(4.W)) + misaligned_fault_mscause_d := Mux(regcross_misaligned_fault_d, "b0010".U, Mux(sideeffect_misaligned_fault_d.asBool, "b0001".U, "b0000".U)) + + + exc_mscause_d := Mux(misaligned_fault_d.asBool, misaligned_fault_mscause_d(3,0), access_fault_mscause_d(3,0)) + + // Fast interrupt error logic + fir_dccm_access_error_d := ((start_addr_in_dccm_region_d & ~start_addr_in_dccm_d) | + (end_addr_in_dccm_region_d & ~end_addr_in_dccm_d)) & lsu_pkt_d.valid & lsu_pkt_d.fast_int + fir_nondccm_access_error_d := ~(start_addr_in_dccm_region_d & end_addr_in_dccm_region_d) & lsu_pkt_d.valid & lsu_pkt_d.fast_int + + + + //rvdff #(.WIDTH(1)) is_sideeffects_mff (.din(is_sideeffects_d), .dout(is_sideeffects_m), .clk(lsu_c2_m_clk), .*); + + + val is_sideeffects_mff = Module(new rvdff(1,0)) //TBD for clock and reset + is_sideeffects_mff.io.din := is_sideeffects_d + is_sideeffects_m := is_sideeffects_mff.io.dout + + + + //is_sideeffects_m :=0.U + // addr_in_dccm_d :=0.U + // addr_in_pic_d :=0.U + // addr_external_d :=0.U + // access_fault_d :=0.U + // misaligned_fault_d :=0.U + // exc_mscause_d :=0.U + // fir_dccm_access_error_d :=0.U + // fir_nondccm_access_error_d :=0.U +} diff --git a/src/main/scala/lsu/el2_lsu_lsc_ctl.scala b/src/main/scala/lsu/el2_lsu_lsc_ctl.scala new file mode 100644 index 00000000..d698b2eb --- /dev/null +++ b/src/main/scala/lsu/el2_lsu_lsc_ctl.scala @@ -0,0 +1,108 @@ +class el2_lsu_lsc_ctl extends MultiIOModule +{ + //val rst_l = IO(Input(1.W)) //implicit + val lsu_c1_m_clk = IO(Input(Clock())) + val lsu_c1_r_clk = IO(Input(Clock())) + val lsu_c2_m_clk = IO(Input(Clock())) + val lsu_c2_r_clk = IO(Input(Clock())) + val lsu_store_c1_m_clk = IO(Input(Clock())) + + val lsu_ld_data_r = IO(Input(UInt(32.W))) //DCCM data + val lsu_ld_data_corr_r = IO(Input(UInt(32.W))) // ECC corrected data + val lsu_single_ecc_error_r = IO(Input(UInt(1.W))) + val lsu_double_ecc_error_r = IO(Input(UInt(1.W))) + + val lsu_ld_data_m = IO(Input(UInt(32.W))) + val lsu_single_ecc_error_m = IO(Input(UInt(1.W))) + val lsu_double_ecc_error_m = IO(Input(UInt(1.W))) + + val flush_m_up = IO(Input(UInt(1.W))) + val flush_r = IO(Input(UInt(1.W))) + + val exu_lsu_rs1_d = IO(Input(UInt(32.W))) // address + val exu_lsu_rs2_d = IO(Input(UInt(32.W))) // store data + + val lsu_p = IO(Input(new el2_lsu_pkt_t())) // lsu control packet //coming from decode + val dec_lsu_valid_raw_d = IO(Input(UInt(1.W))) // Raw valid for address computation + val dec_lsu_offset_d = IO(Input(UInt(12.W))) + + val picm_mask_data_m = IO(Input(UInt(32.W))) + val bus_read_data_m = IO(Input(UInt(32.W))) //coming from bus interface + + val lsu_result_m = IO(Output(UInt(32.W)) ) + val lsu_result_corr_r = IO(Output(UInt(32.W))) // This is the ECC corrected data going to RF + + // lsu address down the pipe + val lsu_addr_d = IO(Output(UInt(32.W))) + val lsu_addr_m = IO(Output(UInt(32.W))) + val lsu_addr_r = IO(Output(UInt(32.W))) + + // lsu address down the pipe - needed to check unaligned + val end_addr_d = IO(Output(UInt(32.W))) + val end_addr_m = IO(Output(UInt(32.W))) + val end_addr_r = IO(Output(UInt(32.W))) + + // store data down the pipe + val store_data_m = IO(Output(UInt(32.W))) + + val dec_tlu_mrac_ff = IO(Output(UInt(32.W))) // CSR read + + val lsu_exc_m = IO(Output(UInt(1.W))) + val is_sideeffects_m = IO(Output(UInt(1.W))) + val lsu_commit_r = IO(Output(UInt(1.W))) + val lsu_single_ecc_error_incr = IO(Output(UInt(1.W))) + val lsu_error_pkt_r = IO(Output(new el2_lsu_error_pkt_t())) + + val lsu_fir_addr = IO(Output(UInt(32.W))) //(31:1) in sv // fast interrupt address TBD + val lsu_fir_error = IO(Output(UInt(2.W))) // Error during fast interrupt lookup TBD + + // address in dccm/pic/external per pipe stage + val addr_in_dccm_d = IO(Output(UInt(1.W))) + val addr_in_dccm_m = IO(Output(UInt(1.W))) + val addr_in_dccm_r = IO(Output(UInt(1.W))) + + val addr_in_pic_d = IO(Output(UInt(1.W))) + val addr_in_pic_m = IO(Output(UInt(1.W))) + val addr_in_pic_r = IO(Output(UInt(1.W))) + + val addr_external_m = IO(Output(UInt(1.W))) + + // DMA slave + val dma_dccm_req = IO(Input(UInt(1.W))) + val dma_mem_addr = IO(Input(UInt(32.W))) + val dma_mem_sz = IO(Input(UInt(3.W))) + val dma_mem_write = IO(Input(UInt(1.W))) + val dma_mem_wdata = IO(Input(UInt(64.W))) + + + + + // Store buffer related signals + val lsu_pkt_d = new el2_lsu_pkt_t() + val lsu_pkt_m = new el2_lsu_pkt_t() + val lsu_pkt_r = new el2_lsu_pkt_t() + + val scan_mode = IO(Input(UInt(1.W))) + val dma_pkt_d = new el2_lsu_pkt_t() + val lsu_pkt_m_in = new el2_lsu_pkt_t() + val lsu_pkt_r_in = new el2_lsu_pkt_t() + val lsu_error_pkt_m = new el2_lsu_error_pkt_t() + + val lsu_rs1_d = Mux(dec_lsu_valid_raw_d.asBool,dec_lsu_valid_raw_d, dec_lsu_valid_raw_d) + val lsu_offset_d = dec_lsu_offset_d(11,0) & Fill(12,dec_lsu_valid_raw_d) + + val rs1_d_raw = lsu_rs1_d + val offset_d = lsu_offset_d + + val rs1_d = Mux(lsu_pkt_d.load_ldst_bypass_d.asBool,lsu_result_m,rs1_d_raw) + + val lsadder = new rvlsadder() + lsadder.io.rs1 := rs1_d + lsadder.io.offset := offset_d + val full_addr_d = lsadder.io.dout + + + + + +}