diff --git a/ut_frontend/itlb/classical_version/test_tlb_receive_ptw_resp.py b/ut_frontend/itlb/classical_version/_test_tlb_receive_ptw_resp.py similarity index 100% rename from ut_frontend/itlb/classical_version/test_tlb_receive_ptw_resp.py rename to ut_frontend/itlb/classical_version/_test_tlb_receive_ptw_resp.py diff --git a/ut_frontend/itlb/classical_version/test_tlb_receive_request.py b/ut_frontend/itlb/classical_version/_test_tlb_receive_request.py similarity index 100% rename from ut_frontend/itlb/classical_version/test_tlb_receive_request.py rename to ut_frontend/itlb/classical_version/_test_tlb_receive_request.py diff --git a/ut_frontend/itlb/classical_version/test_tlb_reset.py b/ut_frontend/itlb/classical_version/_test_tlb_reset.py similarity index 100% rename from ut_frontend/itlb/classical_version/test_tlb_reset.py rename to ut_frontend/itlb/classical_version/_test_tlb_reset.py diff --git a/ut_frontend/itlb/classical_version/base_components.py b/ut_frontend/itlb/classical_version/base_components.py new file mode 100644 index 00000000..ab7cf807 --- /dev/null +++ b/ut_frontend/itlb/classical_version/base_components.py @@ -0,0 +1,334 @@ +################################################################################ +# hit +################################################################################ + +def hit_nonStage_requestor_0(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_nostage_hit(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 1 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_0.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_0.resp.paddr_0.value == ((signals["ppn"] << 12) | signals["offset"])) + assert (tlb.requestor_0.resp.miss.value == 0) + # return signals + return signals + + +def hit_nonStage_requestor_1(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_nostage_hit(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 1 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_1.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_1.resp.paddr_0.value == ((signals["ppn"] << 12) | signals["offset"])) + assert (tlb.requestor_1.resp.miss.value == 0) + # return signals + return signals + + +def hit_nonStage_requestor_2(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_nostage_hit(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 1 + tlb.ctrl.io_requestor_2_resp_ready.value = 1 + tlb.requestor_2.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_2.resp.paddr_0.value == ((signals["ppn"] << 12) | signals["offset"])) + assert (tlb.requestor_2.resp.miss.value == 0) + # return signals + return signals + + +################################################################################ +# miss +################################################################################ + +# no stage +def miss_nonStage_requestor_0(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + print(f'generate signals: {signals}') + # initialize dut with signals + tlb.init_dut_for_nostage_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 1 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_0.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_0.resp.miss.value == 1) + # return signals + return signals + + +def miss_nonStage_requestor_1(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_nostage_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 1 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_1.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_1.resp.miss.value == 1) + # return signals + return signals + + +def miss_nonStage_requestor_2(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_nostage_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 1 + tlb.ctrl.io_requestor_2_resp_ready.value = 1 + tlb.requestor_2.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_2.resp.miss.value == 1) + # return signals + return signals + + +# only stage 1 +def miss_onlyStage1_requestor_0(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_onlyStage1_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 1 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_0.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_0.resp.miss.value == 1) + # return signals + return signals + + +def miss_onlyStage1_requestor_1(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_onlyStage1_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 1 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_1.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_1.resp.miss.value == 1) + # return signals + return signals + + +def miss_onlyStage1_requestor_2(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_onlyStage1_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 1 + tlb.ctrl.io_requestor_2_resp_ready.value = 1 + tlb.requestor_2.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_2.resp.miss.value == 1) + # return signals + return signals + + +# only stage 2 +def miss_onlyStage2_requestor_0(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_onlyStage2_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 1 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_0.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_0.resp.miss.value == 1) + # return signals + return signals + + +def miss_onlyStage2_requestor_1(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_onlyStage2_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 1 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_1.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_1.resp.miss.value == 1) + # return signals + return signals + + +def miss_onlyStage2_requestor_2(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_onlyStage2_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 1 + tlb.ctrl.io_requestor_2_resp_ready.value = 1 + tlb.requestor_2.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_2.resp.miss.value == 1) + # return signals + return signals + + +# all stage +def miss_allStage_requestor_0(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_allStage_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 1 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_0.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_0.resp.miss.value == 1) + # return signals + return signals + + +def miss_allStage_requestor_1(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_allStage_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 1 + tlb.requestor_2.req.valid.value = 0 + tlb.requestor_1.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_1.resp.miss.value == 1) + # return signals + return signals + + +def miss_allStage_requestor_2(tlb) -> dict: + # generate signals + signals = tlb.gene_rand_TLBsignal_batch() + # initialize dut with signals + tlb.init_dut_for_allStage_miss(signals["vpn"], signals["asid"], signals["ppn"], signals["ppn_low"]) + tlb.csr.satp.asid.value = signals["asid"] + # step to next cycle + tlb.dut.Step() + # switch requestor + tlb.requestor_0.req.valid.value = 0 + tlb.requestor_1.req.valid.value = 0 + tlb.requestor_2.req.valid.value = 1 + tlb.ctrl.io_requestor_2_resp_ready.value = 1 + tlb.requestor_2.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + # step to next cycle + tlb.dut.Step(2) + # assert result + assert (tlb.requestor_2.resp.miss.value == 1) + # return signals + return signals diff --git a/ut_frontend/itlb/classical_version/env/itlb_utils.py b/ut_frontend/itlb/classical_version/env/itlb_utils.py new file mode 100644 index 00000000..f7c8844a --- /dev/null +++ b/ut_frontend/itlb/classical_version/env/itlb_utils.py @@ -0,0 +1,2 @@ +def other_than(value): + return value ^ 1 diff --git a/ut_frontend/itlb/classical_version/env/itlb_wrapper.py b/ut_frontend/itlb/classical_version/env/itlb_wrapper.py index a833cb23..f192123c 100644 --- a/ut_frontend/itlb/classical_version/env/itlb_wrapper.py +++ b/ut_frontend/itlb/classical_version/env/itlb_wrapper.py @@ -20,6 +20,7 @@ import toffee.funcov as fc from dut.TLB import * +from ut_frontend.itlb.classical_version.env.itlb_utils import other_than from .itlb_consts import * from queue import Queue from comm import get_version_checker, get_out_dir, UT_FCOV @@ -280,6 +281,14 @@ def reset(self): self.dut.reset.value = 0 # print(">>> RESET FINISHED !") + def cleanup_requestor(self, requestor: int): + self.reset() + self.flushPipe[requestor].value = 1 + self.dut.Step() + self.flushPipe[requestor].value = 0 + self.dut.Step(2) + # print(f">>> CLEANUP requestor_{i} FINISHED !") + def gene_rand_TLBreq(self): """ generate random TLB request @@ -288,6 +297,27 @@ def gene_rand_TLBreq(self): req_vaddr = random.randint(0, 2 ** 50 - 1) return req_valid, req_vaddr + def gene_rand_TLBsignal_batch(self) -> dict: + vpn, offset = self.gene_rand_addr() + asid = random.randint(0, 2 ** 16 - 1) + ppn = random.randint(0, 2 ** 36 - 1) + ppn_low = [random.randint(0, 2 ** 3 - 1) for _ in range(8)] + valid_idx = [random.choice([0, 1]) for _ in range(8)] + return { + "asid": asid, + "vpn": vpn, + "offset": offset, + "ppn": ppn, + "ppn_low": ppn_low, + "valid_idx": valid_idx, + } + + def gene_rand_addr(self) -> tuple[int, int]: + addr = random.randint(0, 2 ** 50 - 1) + pn = addr >> 12 + offset = addr & 0xfff + return pn, offset + def rand_req0(self): """ send random TLB request from requestor0 @@ -414,6 +444,328 @@ def rand_ptw_resp(self, vpn, asid, s2xlate): # TODO return randPPN + def init_dut_for_nostage_hit(self, vpn, asid, ppn, ppn_low): + # prepare data + addr_low = vpn & 0b111 + ## ctrl signals + self.ctrl.io_ptw_resp_valid.value = 1 + self.ctrl.io_ptw_resp_bits_s2xlate.value = 0b00 + # initialize conditions + self.ptw_resp_s1.entry_tag.value = vpn >> 3 + self.ptw_resp_s1.entry_asid.value = asid + self.ptw_resp_s1.entry_vmid.value = DONTCARE + self.ptw_resp_s1.entry_n.value = UNUSED0 + self.ptw_resp_s1.entry_pbmt.value = UNUSED0 + self.ptw_resp_s1.entry_perm_d.value = UNUSED0 + self.ptw_resp_s1.entry_perm_a.value = UNUSED0 + self.ptw_resp_s1.entry_perm_g.value = UNUSED0 + self.ptw_resp_s1.entry_perm_u.value = UNUSED0 + self.ptw_resp_s1.entry_perm_x.value = UNUSED1 + self.ptw_resp_s1.entry_perm_w.value = UNUSED0 + self.ptw_resp_s1.entry_perm_r.value = UNUSED0 + self.ptw_resp_s1.entry_level.value = UNUSED0 + self.ptw_resp_s1.entry_v.value = 1 + self.ptw_resp_s1.entry_ppn.value = ppn >> 3 + self.ptw_resp_s1.addr_low.value = addr_low + ppn_low_dict = { + 0: self.ptw_resp_s1.ppn_low_0, + 1: self.ptw_resp_s1.ppn_low_1, + 2: self.ptw_resp_s1.ppn_low_2, + 3: self.ptw_resp_s1.ppn_low_3, + 4: self.ptw_resp_s1.ppn_low_4, + 5: self.ptw_resp_s1.ppn_low_5, + 6: self.ptw_resp_s1.ppn_low_6, + 7: self.ptw_resp_s1.ppn_low_7 + } + valididx_dict = { + 0: self.ptw_resp_s1.valididx_0, + 1: self.ptw_resp_s1.valididx_1, + 2: self.ptw_resp_s1.valididx_2, + 3: self.ptw_resp_s1.valididx_3, + 4: self.ptw_resp_s1.valididx_4, + 5: self.ptw_resp_s1.valididx_5, + 6: self.ptw_resp_s1.valididx_6, + 7: self.ptw_resp_s1.valididx_7 + } + pteidx_dict = { + 0: self.ptw_resp_s1.pteidx_0, + 1: self.ptw_resp_s1.pteidx_1, + 2: self.ptw_resp_s1.pteidx_2, + 3: self.ptw_resp_s1.pteidx_3, + 4: self.ptw_resp_s1.pteidx_4, + 5: self.ptw_resp_s1.pteidx_5, + 6: self.ptw_resp_s1.pteidx_6, + 7: self.ptw_resp_s1.pteidx_7 + } + for i in range(8): + if i == addr_low: + ppn_low_dict[i].value = ppn & 0b111 + valididx_dict[i].value = 1 + else: + ppn_low_dict[i].value = ppn_low[i] + valididx_dict[i].value = 0 + pteidx_dict[addr_low].value = 1 + self.ptw_resp_s1.pf.value = UNUSED0 + self.ptw_resp_s1.af.value = UNUSED0 + + + def init_dut_for_nostage_miss(self, vpn, asid, ppn, ppn_low): + # prepare data + addr_low = vpn & 0b111 + ## ctrl signals + self.ctrl.io_ptw_resp_valid.value = 1 + self.ctrl.io_ptw_resp_bits_s2xlate.value = 0b00 + # initialize conditions + self.ptw_resp_s1.entry_tag.value = other_than(vpn >> 3) + self.ptw_resp_s1.entry_asid.value = asid + self.ptw_resp_s1.entry_vmid.value = DONTCARE + self.ptw_resp_s1.entry_n.value = UNUSED0 + self.ptw_resp_s1.entry_pbmt.value = UNUSED0 + self.ptw_resp_s1.entry_perm_d.value = UNUSED0 + self.ptw_resp_s1.entry_perm_a.value = UNUSED0 + self.ptw_resp_s1.entry_perm_g.value = UNUSED0 + self.ptw_resp_s1.entry_perm_u.value = UNUSED0 + self.ptw_resp_s1.entry_perm_x.value = UNUSED1 + self.ptw_resp_s1.entry_perm_w.value = UNUSED0 + self.ptw_resp_s1.entry_perm_r.value = UNUSED0 + self.ptw_resp_s1.entry_level.value = UNUSED0 + self.ptw_resp_s1.entry_v.value = 1 + self.ptw_resp_s1.entry_ppn.value = ppn >> 3 + self.ptw_resp_s1.addr_low.value = addr_low + ppn_low_dict = { + 0: self.ptw_resp_s1.ppn_low_0, + 1: self.ptw_resp_s1.ppn_low_1, + 2: self.ptw_resp_s1.ppn_low_2, + 3: self.ptw_resp_s1.ppn_low_3, + 4: self.ptw_resp_s1.ppn_low_4, + 5: self.ptw_resp_s1.ppn_low_5, + 6: self.ptw_resp_s1.ppn_low_6, + 7: self.ptw_resp_s1.ppn_low_7 + } + valididx_dict = { + 0: self.ptw_resp_s1.valididx_0, + 1: self.ptw_resp_s1.valididx_1, + 2: self.ptw_resp_s1.valididx_2, + 3: self.ptw_resp_s1.valididx_3, + 4: self.ptw_resp_s1.valididx_4, + 5: self.ptw_resp_s1.valididx_5, + 6: self.ptw_resp_s1.valididx_6, + 7: self.ptw_resp_s1.valididx_7 + } + pteidx_dict = { + 0: self.ptw_resp_s1.pteidx_0, + 1: self.ptw_resp_s1.pteidx_1, + 2: self.ptw_resp_s1.pteidx_2, + 3: self.ptw_resp_s1.pteidx_3, + 4: self.ptw_resp_s1.pteidx_4, + 5: self.ptw_resp_s1.pteidx_5, + 6: self.ptw_resp_s1.pteidx_6, + 7: self.ptw_resp_s1.pteidx_7 + } + for i in range(8): + if i == addr_low: + ppn_low_dict[i].value = ppn & 0b111 + valididx_dict[i].value = 1 + else: + ppn_low_dict[i].value = ppn_low[i] + valididx_dict[i].value = 0 + pteidx_dict[addr_low].value = 1 + self.ptw_resp_s1.pf.value = UNUSED0 + self.ptw_resp_s1.af.value = UNUSED0 + + def init_dut_for_onlyStage1_miss(self, vpn, asid, ppn, ppn_low): + # prepare data + addr_low = vpn & 0b111 + ## ctrl signals + self.ctrl.io_ptw_resp_valid.value = 1 + self.ctrl.io_ptw_resp_bits_s2xlate.value = 0b01 + # initialize conditions + self.ptw_resp_s1.entry_tag.value = other_than(vpn >> 3) + self.ptw_resp_s1.entry_asid.value = asid + self.ptw_resp_s1.entry_vmid.value = DONTCARE + self.ptw_resp_s1.entry_n.value = UNUSED0 + self.ptw_resp_s1.entry_pbmt.value = UNUSED0 + self.ptw_resp_s1.entry_perm_d.value = UNUSED0 + self.ptw_resp_s1.entry_perm_a.value = UNUSED0 + self.ptw_resp_s1.entry_perm_g.value = UNUSED0 + self.ptw_resp_s1.entry_perm_u.value = UNUSED0 + self.ptw_resp_s1.entry_perm_x.value = UNUSED1 + self.ptw_resp_s1.entry_perm_w.value = UNUSED0 + self.ptw_resp_s1.entry_perm_r.value = UNUSED0 + self.ptw_resp_s1.entry_level.value = UNUSED0 + self.ptw_resp_s1.entry_v.value = 1 + self.ptw_resp_s1.entry_ppn.value = ppn >> 3 + self.ptw_resp_s1.addr_low.value = addr_low + ppn_low_dict = { + 0: self.ptw_resp_s1.ppn_low_0, + 1: self.ptw_resp_s1.ppn_low_1, + 2: self.ptw_resp_s1.ppn_low_2, + 3: self.ptw_resp_s1.ppn_low_3, + 4: self.ptw_resp_s1.ppn_low_4, + 5: self.ptw_resp_s1.ppn_low_5, + 6: self.ptw_resp_s1.ppn_low_6, + 7: self.ptw_resp_s1.ppn_low_7 + } + valididx_dict = { + 0: self.ptw_resp_s1.valididx_0, + 1: self.ptw_resp_s1.valididx_1, + 2: self.ptw_resp_s1.valididx_2, + 3: self.ptw_resp_s1.valididx_3, + 4: self.ptw_resp_s1.valididx_4, + 5: self.ptw_resp_s1.valididx_5, + 6: self.ptw_resp_s1.valididx_6, + 7: self.ptw_resp_s1.valididx_7 + } + pteidx_dict = { + 0: self.ptw_resp_s1.pteidx_0, + 1: self.ptw_resp_s1.pteidx_1, + 2: self.ptw_resp_s1.pteidx_2, + 3: self.ptw_resp_s1.pteidx_3, + 4: self.ptw_resp_s1.pteidx_4, + 5: self.ptw_resp_s1.pteidx_5, + 6: self.ptw_resp_s1.pteidx_6, + 7: self.ptw_resp_s1.pteidx_7 + } + for i in range(8): + if i == addr_low: + ppn_low_dict[i].value = ppn & 0b111 + valididx_dict[i].value = 1 + else: + ppn_low_dict[i].value = ppn_low[i] + valididx_dict[i].value = 0 + pteidx_dict[addr_low].value = 1 + self.ptw_resp_s1.pf.value = UNUSED0 + self.ptw_resp_s1.af.value = UNUSED0 + + def init_dut_for_onlyStage2_miss(self, vpn, asid, ppn, ppn_low): + # prepare data + addr_low = vpn & 0b111 + ## ctrl signals + self.ctrl.io_ptw_resp_valid.value = 1 + self.ctrl.io_ptw_resp_bits_s2xlate.value = 0b10 + # initialize conditions + self.ptw_resp_s1.entry_tag.value = other_than(vpn >> 3) + self.ptw_resp_s1.entry_asid.value = asid + self.ptw_resp_s1.entry_vmid.value = DONTCARE + self.ptw_resp_s1.entry_n.value = UNUSED0 + self.ptw_resp_s1.entry_pbmt.value = UNUSED0 + self.ptw_resp_s1.entry_perm_d.value = UNUSED0 + self.ptw_resp_s1.entry_perm_a.value = UNUSED0 + self.ptw_resp_s1.entry_perm_g.value = UNUSED0 + self.ptw_resp_s1.entry_perm_u.value = UNUSED0 + self.ptw_resp_s1.entry_perm_x.value = UNUSED1 + self.ptw_resp_s1.entry_perm_w.value = UNUSED0 + self.ptw_resp_s1.entry_perm_r.value = UNUSED0 + self.ptw_resp_s1.entry_level.value = UNUSED0 + self.ptw_resp_s1.entry_v.value = 1 + self.ptw_resp_s1.entry_ppn.value = ppn >> 3 + self.ptw_resp_s1.addr_low.value = addr_low + ppn_low_dict = { + 0: self.ptw_resp_s1.ppn_low_0, + 1: self.ptw_resp_s1.ppn_low_1, + 2: self.ptw_resp_s1.ppn_low_2, + 3: self.ptw_resp_s1.ppn_low_3, + 4: self.ptw_resp_s1.ppn_low_4, + 5: self.ptw_resp_s1.ppn_low_5, + 6: self.ptw_resp_s1.ppn_low_6, + 7: self.ptw_resp_s1.ppn_low_7 + } + valididx_dict = { + 0: self.ptw_resp_s1.valididx_0, + 1: self.ptw_resp_s1.valididx_1, + 2: self.ptw_resp_s1.valididx_2, + 3: self.ptw_resp_s1.valididx_3, + 4: self.ptw_resp_s1.valididx_4, + 5: self.ptw_resp_s1.valididx_5, + 6: self.ptw_resp_s1.valididx_6, + 7: self.ptw_resp_s1.valididx_7 + } + pteidx_dict = { + 0: self.ptw_resp_s1.pteidx_0, + 1: self.ptw_resp_s1.pteidx_1, + 2: self.ptw_resp_s1.pteidx_2, + 3: self.ptw_resp_s1.pteidx_3, + 4: self.ptw_resp_s1.pteidx_4, + 5: self.ptw_resp_s1.pteidx_5, + 6: self.ptw_resp_s1.pteidx_6, + 7: self.ptw_resp_s1.pteidx_7 + } + for i in range(8): + if i == addr_low: + ppn_low_dict[i].value = ppn & 0b111 + valididx_dict[i].value = 1 + else: + ppn_low_dict[i].value = ppn_low[i] + valididx_dict[i].value = 0 + pteidx_dict[addr_low].value = 1 + self.ptw_resp_s1.pf.value = UNUSED0 + self.ptw_resp_s1.af.value = UNUSED0 + + def init_dut_for_allStage_miss(self, vpn, asid, ppn, ppn_low): + # prepare data + addr_low = vpn & 0b111 + ## ctrl signals + self.ctrl.io_ptw_resp_valid.value = 1 + self.ctrl.io_ptw_resp_bits_s2xlate.value = 0b11 + # initialize conditions + self.ptw_resp_s1.entry_tag.value = other_than(vpn >> 3) + self.ptw_resp_s1.entry_asid.value = asid + self.ptw_resp_s1.entry_vmid.value = DONTCARE + self.ptw_resp_s1.entry_n.value = UNUSED0 + self.ptw_resp_s1.entry_pbmt.value = UNUSED0 + self.ptw_resp_s1.entry_perm_d.value = UNUSED0 + self.ptw_resp_s1.entry_perm_a.value = UNUSED0 + self.ptw_resp_s1.entry_perm_g.value = UNUSED0 + self.ptw_resp_s1.entry_perm_u.value = UNUSED0 + self.ptw_resp_s1.entry_perm_x.value = UNUSED1 + self.ptw_resp_s1.entry_perm_w.value = UNUSED0 + self.ptw_resp_s1.entry_perm_r.value = UNUSED0 + self.ptw_resp_s1.entry_level.value = UNUSED0 + self.ptw_resp_s1.entry_v.value = 1 + self.ptw_resp_s1.entry_ppn.value = ppn >> 3 + self.ptw_resp_s1.addr_low.value = addr_low + ppn_low_dict = { + 0: self.ptw_resp_s1.ppn_low_0, + 1: self.ptw_resp_s1.ppn_low_1, + 2: self.ptw_resp_s1.ppn_low_2, + 3: self.ptw_resp_s1.ppn_low_3, + 4: self.ptw_resp_s1.ppn_low_4, + 5: self.ptw_resp_s1.ppn_low_5, + 6: self.ptw_resp_s1.ppn_low_6, + 7: self.ptw_resp_s1.ppn_low_7 + } + valididx_dict = { + 0: self.ptw_resp_s1.valididx_0, + 1: self.ptw_resp_s1.valididx_1, + 2: self.ptw_resp_s1.valididx_2, + 3: self.ptw_resp_s1.valididx_3, + 4: self.ptw_resp_s1.valididx_4, + 5: self.ptw_resp_s1.valididx_5, + 6: self.ptw_resp_s1.valididx_6, + 7: self.ptw_resp_s1.valididx_7 + } + pteidx_dict = { + 0: self.ptw_resp_s1.pteidx_0, + 1: self.ptw_resp_s1.pteidx_1, + 2: self.ptw_resp_s1.pteidx_2, + 3: self.ptw_resp_s1.pteidx_3, + 4: self.ptw_resp_s1.pteidx_4, + 5: self.ptw_resp_s1.pteidx_5, + 6: self.ptw_resp_s1.pteidx_6, + 7: self.ptw_resp_s1.pteidx_7 + } + for i in range(8): + if i == addr_low: + ppn_low_dict[i].value = ppn & 0b111 + valididx_dict[i].value = 1 + else: + ppn_low_dict[i].value = ppn_low[i] + valididx_dict[i].value = 0 + pteidx_dict[addr_low].value = 1 + self.ptw_resp_s1.pf.value = UNUSED0 + self.ptw_resp_s1.af.value = UNUSED0 + + class TLBrwWrapper(toffee.Bundle): """ Support TLB read/write only. diff --git a/ut_frontend/itlb/classical_version/test_tlb_handle_miss_cond.py b/ut_frontend/itlb/classical_version/test_tlb_handle_miss_cond.py new file mode 100644 index 00000000..ae70c644 --- /dev/null +++ b/ut_frontend/itlb/classical_version/test_tlb_handle_miss_cond.py @@ -0,0 +1,124 @@ +#coding=utf8 +#*************************************************************************************** +# This project is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# +# See the Mulan PSL v2 for more details. +#**************************************************************************************/ +from .base_components import miss_nonStage_requestor_0, miss_nonStage_requestor_1, miss_nonStage_requestor_2, \ + miss_onlyStage1_requestor_0, miss_onlyStage1_requestor_1, miss_onlyStage1_requestor_2, miss_onlyStage2_requestor_0, \ + miss_onlyStage2_requestor_1, miss_onlyStage2_requestor_2, miss_allStage_requestor_0, miss_allStage_requestor_1, \ + miss_allStage_requestor_2 +from .env import * +import inspect + +ROUND_NUM = 2 +ROUND_SIZE = 2 + + +def test_handle_miss_cond_miss(tlb_fixture): + """ + no stage,miss + """ + # connect to fixture + tlb = tlb_fixture + tlb.set_default_value() + # reset + tlb.reset() + + # add clock + tlb.dut.xclock.StepRis(lambda _: g.sample()) + + # no stage + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_nonStage_requestor_0(tlb) + tlb.cleanup_requestor(0) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_nonStage_requestor_1(tlb) + tlb.cleanup_requestor(1) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_nonStage_requestor_2(tlb) + tlb.cleanup_requestor(2) # cleanup requestor 2 after each missing + + # only stage 1 + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_onlyStage1_requestor_0(tlb) + tlb.cleanup_requestor(0) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_onlyStage1_requestor_1(tlb) + tlb.cleanup_requestor(1) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_onlyStage1_requestor_2(tlb) + tlb.cleanup_requestor(2) # cleanup requestor 2 after each missing + + # only stage 2 + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_onlyStage2_requestor_0(tlb) + tlb.cleanup_requestor(0) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_onlyStage2_requestor_1(tlb) + tlb.cleanup_requestor(1) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_onlyStage2_requestor_2(tlb) + tlb.cleanup_requestor(2) # cleanup requestor 2 after each missing + + # all stage + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_allStage_requestor_0(tlb) + tlb.cleanup_requestor(0) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_allStage_requestor_1(tlb) + tlb.cleanup_requestor(1) + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + miss_allStage_requestor_2(tlb) + tlb.cleanup_requestor(2) # cleanup requestor 2 after each missing + + +def test_handle_miss_cond_ptw_req(tlb_fixture): + """ + no stage,miss + """ + # connect to fixture + tlb = tlb_fixture + tlb.set_default_value() + # reset + tlb.reset() + + # add clock + tlb.dut.xclock.StepRis(lambda _: g.sample()) + + # no stage + for _ in range(ROUND_NUM): + for _ in range(ROUND_SIZE): + signals = miss_nonStage_requestor_0(tlb) + assert(tlb.ctrl.io_ptw_req_0_valid.value == 1) + assert(tlb.ptw_req_0.vpn.value == signals["vpn"]) + # simulate PTW invalid + ppn, _ = tlb.gene_rand_addr() + tlb.ctrl.io_ptw_resp_valid.value = 0 + tlb.ptw_resp_s1.entry_ppn.value = ppn + tlb.ptw_resp_s1.entry_tag.value = signals["vpn"] + tlb.dut.Step() + # should miss when reading second time + tlb.requestor_0.req.bits_vaddr.value = (signals["vpn"] << 12) | signals["offset"] + tlb.dut.Step(2) + assert (tlb.requestor_0.resp.miss.value == 1) + tlb.cleanup_requestor(0)