@@ -43,6 +43,7 @@ struct insn_fetch_t
4343
4444struct icache_entry_t {
4545 reg_t tag;
46+ icache_entry_t * next;
4647 insn_fetch_t data;
4748};
4849
@@ -56,6 +57,11 @@ struct dtlb_entry_t {
5657 reg_t tag;
5758};
5859
60+ struct pte_cache_entry_t {
61+ reg_t paddr;
62+ reg_t pte;
63+ };
64+
5965struct xlate_flags_t {
6066 const bool forced_virt : 1 {false };
6167 const bool hlvx : 1 {false };
@@ -129,7 +135,7 @@ class mmu_t
129135 T ss_load (reg_t addr) {
130136 if ((addr & (sizeof (T) - 1 )) != 0 )
131137 throw trap_store_access_fault ((proc) ? proc->state .v : false , addr, 0 , 0 );
132- return load<T>(addr, {.forced_virt = false , . hlvx = false , . lr = false , . ss_access =true });
138+ return load<T>(addr, {.ss_access =true });
133139 }
134140
135141 template <typename T>
@@ -156,7 +162,7 @@ class mmu_t
156162 void ss_store (reg_t addr, T val) {
157163 if ((addr & (sizeof (T) - 1 )) != 0 )
158164 throw trap_store_access_fault ((proc) ? proc->state .v : false , addr, 0 , 0 );
159- store<T>(addr, val, {.forced_virt = false , . hlvx = false , . lr = false , . ss_access =true });
165+ store<T>(addr, val, {.ss_access =true });
160166 }
161167
162168 // AMO/Zicbom faults should be reported as store faults
@@ -188,13 +194,9 @@ class mmu_t
188194 // for shadow stack amoswap
189195 template <typename T>
190196 T ssamoswap (reg_t addr, reg_t value) {
191- bool forced_virt = false ;
192- bool hlvx = false ;
193- bool lr = false ;
194- bool ss_access = true ;
195- store_slow_path (addr, sizeof (T), nullptr , {forced_virt, hlvx, lr, ss_access}, false , true );
196- auto data = load<T>(addr, {forced_virt, hlvx, lr, ss_access});
197- store<T>(addr, value, {forced_virt, hlvx, lr, ss_access});
197+ store_slow_path (addr, sizeof (T), nullptr , {.ss_access =true }, false , true );
198+ auto data = load<T>(addr, {.ss_access =true });
199+ store<T>(addr, value, {.ss_access =true });
198200 return data;
199201 }
200202
@@ -272,7 +274,10 @@ class mmu_t
272274 store_slow_path (vaddr, size, nullptr , {}, false , true );
273275 }
274276
275- reg_t paddr = translate (generate_access_info (vaddr, STORE, {}), 1 );
277+ auto [tlb_hit, host_addr, paddr] = access_tlb (tlb_store, vaddr);
278+ if (!tlb_hit)
279+ paddr = translate (generate_access_info (vaddr, STORE, {}), 1 );
280+
276281 if (sim->reservable (paddr))
277282 return load_reservation_address == paddr;
278283 else
@@ -321,6 +326,7 @@ class mmu_t
321326
322327 insn_fetch_t fetch = {proc->decode_insn (insn), insn};
323328 entry->tag = addr;
329+ entry->next = &icache[icache_index (addr + length)];
324330 entry->data = fetch;
325331
326332 auto [check_tracer, _, paddr] = access_tlb (tlb_insn, addr, TLB_FLAGS, TLB_CHECK_TRACER);
@@ -407,6 +413,9 @@ class mmu_t
407413 dtlb_entry_t tlb_store[TLB_ENTRIES];
408414 dtlb_entry_t tlb_insn[TLB_ENTRIES];
409415
416+ static const reg_t PTE_CACHE_ENTRIES = 251 ;
417+ pte_cache_entry_t pte_cache[PTE_CACHE_ENTRIES];
418+
410419 typedef bloom_filter_t <reg_t , simple_hash1, simple_hash2, TLB_ENTRIES * 16 , 3 > reverse_tags_t ;
411420 reverse_tags_t tlb_store_reverse_tags;
412421 reverse_tags_t tlb_insn_reverse_tags;
@@ -463,6 +472,9 @@ class mmu_t
463472
464473 template <typename T> inline reg_t pte_load (reg_t pte_paddr, reg_t addr, bool virt, access_type trap_type)
465474 {
475+ if (auto [hit, pte] = pte_cache_access (pte_paddr); hit)
476+ return pte;
477+
466478 const size_t ptesize = sizeof (T);
467479
468480 if (!pmp_ok (pte_paddr, ptesize, LOAD, PRV_S, false ))
@@ -475,7 +487,10 @@ class mmu_t
475487 } else if (!mmio_load (pte_paddr, ptesize, (uint8_t *)&target_pte)) {
476488 throw_access_exception (virt, addr, trap_type);
477489 }
478- return from_target (target_pte);
490+
491+ auto res = from_target (target_pte);
492+ pte_cache_insert (pte_paddr, res);
493+ return res;
479494 }
480495
481496 template <typename T> inline void pte_store (reg_t pte_paddr, reg_t new_pte, reg_t addr, bool virt, access_type trap_type)
@@ -492,6 +507,20 @@ class mmu_t
492507 } else if (!mmio_store (pte_paddr, ptesize, (uint8_t *)&target_pte)) {
493508 throw_access_exception (virt, addr, trap_type);
494509 }
510+
511+ pte_cache_insert (pte_paddr, new_pte);
512+ }
513+
514+ std::tuple<bool , reg_t > pte_cache_access (reg_t key)
515+ {
516+ auto e = pte_cache[key % PTE_CACHE_ENTRIES];
517+ return std::make_tuple (e.paddr == key, e.pte );
518+ }
519+
520+ void pte_cache_insert (reg_t key, reg_t value)
521+ {
522+ if (value & PTE_V)
523+ pte_cache[key % PTE_CACHE_ENTRIES] = {key, value};
495524 }
496525
497526 inline insn_parcel_t fetch_insn_parcel (reg_t addr) {
0 commit comments