Skip to content

Commit ffe67c7

Browse files
authored
Merge pull request #2117 from riscv-software-src/ziccid
Implement Ziccid (I$ coherence)
2 parents 0d0863c + c58413e commit ffe67c7

File tree

5 files changed

+124
-30
lines changed

5 files changed

+124
-30
lines changed

riscv/bloom_filter.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// See LICENSE for license details.
2+
3+
#ifndef _RISCV_BLOOM_FILTER_H
4+
#define _RISCV_BLOOM_FILTER_H
5+
6+
#include <bitset>
7+
#include <cstdint>
8+
9+
struct simple_hash1 {
10+
uint64_t operator()(uint64_t x) const
11+
{
12+
x = (x ^ (x >> 33)) * 0xff51afd7ed558ccd;
13+
x = (x ^ (x >> 33)) * 0xc4ceb9fe1a85ec53;
14+
return x ^ (x >> 33);
15+
}
16+
};
17+
18+
struct simple_hash2 {
19+
uint64_t operator()(uint64_t x) const
20+
{
21+
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
22+
x = (x ^ (x >> 27)) * 0x94d049b13c66a8ed;
23+
return x ^ (x >> 31);
24+
}
25+
};
26+
27+
template <typename T, typename H1, typename H2, size_t M, size_t K> // M: bit array size, K: number of hash functions
28+
class bloom_filter_t {
29+
public:
30+
void clear()
31+
{
32+
bits.reset();
33+
}
34+
35+
void insert(T value)
36+
{
37+
uint64_t h1 = H1()(value);
38+
uint64_t h2 = H2()(value);
39+
40+
for (size_t i = 0; i < K; i++) {
41+
size_t idx = (h1 + i * h2) % M;
42+
bits[idx] = true;
43+
}
44+
}
45+
46+
bool contains(T value) const
47+
{
48+
uint64_t h1 = H1()(value);
49+
uint64_t h2 = H2()(value);
50+
51+
for (size_t i = 0; i < K; i++) {
52+
size_t idx = (h1 + i * h2) % M;
53+
if (!bits[idx])
54+
return false;
55+
}
56+
57+
return true;
58+
}
59+
60+
private:
61+
std::bitset<M> bits;
62+
};
63+
64+
#endif

riscv/execute.cc

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,6 @@ void processor_t::step(size_t n)
223223
}
224224
}
225225

226-
if (extension_enabled(EXT_ZICCID)) {
227-
// Ziccid requires stores eventually become visible to instruction fetch,
228-
// so periodically flush the I$
229-
if (ziccid_flush_count-- == 0) {
230-
ziccid_flush_count += ZICCID_FLUSH_PERIOD;
231-
_mmu->flush_icache();
232-
}
233-
}
234-
235226
while (n > 0) {
236227
size_t instret = 0;
237228
reg_t pc = state.pc;
@@ -314,7 +305,7 @@ void processor_t::step(size_t n)
314305
for (auto ic_entry = _mmu->access_icache(pc); ; ) {
315306
auto fetch = ic_entry->data;
316307
pc = execute_insn_fast(this, pc, fetch);
317-
ic_entry = ic_entry->next;
308+
ic_entry = &_mmu->icache[_mmu->icache_index(pc)];
318309
if (unlikely(ic_entry->tag != pc))
319310
break;
320311
if (unlikely(instret + 1 == n))

riscv/mmu.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ mmu_t::insn_parcel_t mmu_t::fetch_slow_path(reg_t vaddr)
112112
paddr = translate(access_info, sizeof(insn_parcel_t));
113113
host_addr = (uintptr_t)sim->addr_to_mem(paddr);
114114

115+
if (proc->extension_enabled(EXT_ZICCID)) {
116+
// Maintain exclusion with all store TLBs
117+
for (auto [_, p2] : sim->get_harts())
118+
p2->mmu->flush_stlb_ppn(paddr >> PGSHIFT);
119+
120+
tlb_insn_reverse_tags.insert(paddr >> PGSHIFT);
121+
}
122+
115123
refill_tlb(vaddr, paddr, (char*)host_addr, FETCH);
116124
}
117125

@@ -326,6 +334,14 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces
326334
paddr = translate(access_info, len);
327335
host_addr = (uintptr_t)sim->addr_to_mem(paddr);
328336

337+
if (proc && proc->extension_enabled(EXT_ZICCID)) {
338+
// Maintain exclusion with all instruction TLBs
339+
for (auto [_, p2] : sim->get_harts())
340+
p2->mmu->flush_itlb_ppn(paddr >> PGSHIFT);
341+
342+
tlb_store_reverse_tags.insert(paddr >> PGSHIFT);
343+
}
344+
329345
if (!access_info.flags.is_special_access())
330346
refill_tlb(vaddr, paddr, (char*)host_addr, STORE);
331347
}
@@ -394,6 +410,35 @@ void mmu_t::store_slow_path(reg_t original_addr, reg_t len, const uint8_t* bytes
394410
}
395411
}
396412

413+
bool mmu_t::flush_tlb_ppn(reg_t ppn, dtlb_entry_t* tlb, reverse_tags_t& filter)
414+
{
415+
if (!filter.contains(ppn))
416+
return false;
417+
418+
filter.clear();
419+
420+
for (size_t i = 0; i < TLB_ENTRIES; i++) {
421+
auto entry_ppn = tlb[i].data.target_addr >> PGSHIFT;
422+
if (entry_ppn == ppn)
423+
tlb[i].tag = -1;
424+
else if (tlb[i].tag != (reg_t)-1)
425+
filter.insert(entry_ppn);
426+
}
427+
428+
return true;
429+
}
430+
431+
void mmu_t::flush_stlb_ppn(reg_t ppn)
432+
{
433+
flush_tlb_ppn(ppn, tlb_store, tlb_store_reverse_tags);
434+
}
435+
436+
void mmu_t::flush_itlb_ppn(reg_t ppn)
437+
{
438+
if (flush_tlb_ppn(ppn, tlb_insn, tlb_insn_reverse_tags))
439+
flush_icache();
440+
}
441+
397442
tlb_entry_t mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type)
398443
{
399444
reg_t idx = (vaddr >> PGSHIFT) % TLB_ENTRIES;

riscv/mmu.h

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifndef _RISCV_MMU_H
44
#define _RISCV_MMU_H
55

6+
#include "bloom_filter.h"
67
#include "decode.h"
78
#include "trap.h"
89
#include "common.h"
@@ -42,7 +43,6 @@ struct insn_fetch_t
4243

4344
struct icache_entry_t {
4445
reg_t tag;
45-
struct icache_entry_t* next;
4646
insn_fetch_t data;
4747
};
4848

@@ -292,7 +292,7 @@ class mmu_t
292292
return have_reservation;
293293
}
294294

295-
static const reg_t ICACHE_ENTRIES = 1024;
295+
static const reg_t ICACHE_ENTRIES = 4096;
296296

297297
inline size_t icache_index(reg_t addr)
298298
{
@@ -312,26 +312,15 @@ class mmu_t
312312
inline icache_entry_t* refill_icache(reg_t addr, icache_entry_t* entry)
313313
{
314314
insn_bits_t insn = fetch_insn_parcel(addr);
315+
unsigned length = insn_length(insn);
315316

316-
int length = insn_length(insn);
317-
318-
if (likely(length == 4)) {
319-
insn |= (insn_bits_t)fetch_insn_parcel(addr + 2) << 16;
320-
} else if (length == 2) {
321-
// entire instruction already fetched
322-
} else if (length == 6) {
323-
insn |= (insn_bits_t)fetch_insn_parcel(addr + 2) << 16;
324-
insn |= (insn_bits_t)fetch_insn_parcel(addr + 4) << 32;
325-
} else {
326-
static_assert(sizeof(insn_bits_t) == 8, "insn_bits_t must be uint64_t");
327-
insn |= (insn_bits_t)fetch_insn_parcel(addr + 2) << 16;
328-
insn |= (insn_bits_t)fetch_insn_parcel(addr + 4) << 32;
329-
insn |= (insn_bits_t)fetch_insn_parcel(addr + 6) << 48;
317+
for (unsigned pos = sizeof(insn_parcel_t); pos < length; pos += sizeof(insn_parcel_t)) {
318+
insn |= fetch_insn_parcel(addr + pos) << (8 * pos);
319+
length = insn_length(insn);
330320
}
331321

332322
insn_fetch_t fetch = {proc->decode_insn(insn), insn};
333323
entry->tag = addr;
334-
entry->next = &icache[icache_index(addr + length)];
335324
entry->data = fetch;
336325

337326
auto [check_tracer, _, paddr] = access_tlb(tlb_insn, addr, TLB_FLAGS, TLB_CHECK_TRACER);
@@ -419,6 +408,14 @@ class mmu_t
419408
dtlb_entry_t tlb_store[TLB_ENTRIES];
420409
dtlb_entry_t tlb_insn[TLB_ENTRIES];
421410

411+
typedef bloom_filter_t<reg_t, simple_hash1, simple_hash2, TLB_ENTRIES * 16, 3> reverse_tags_t;
412+
reverse_tags_t tlb_store_reverse_tags;
413+
reverse_tags_t tlb_insn_reverse_tags;
414+
415+
bool flush_tlb_ppn(reg_t ppn, dtlb_entry_t* tlb, reverse_tags_t& filter);
416+
void flush_itlb_ppn(reg_t ppn);
417+
void flush_stlb_ppn(reg_t ppn);
418+
422419
// finish translation on a TLB miss and update the TLB
423420
tlb_entry_t refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type);
424421
const char* fill_from_mmio(reg_t vaddr, reg_t paddr);

riscv/processor.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,6 @@ class processor_t : public abstract_device_t
414414
static const size_t OPCODE_CACHE_SIZE = 4095;
415415
opcode_cache_entry_t opcode_cache[OPCODE_CACHE_SIZE];
416416

417-
unsigned ziccid_flush_count = 0;
418-
static const unsigned ZICCID_FLUSH_PERIOD = 10;
419-
420417
void take_pending_interrupt() { take_interrupt(state.mip->read() & state.mie->read()); }
421418
void take_interrupt(reg_t mask); // take first enabled interrupt in mask
422419
void take_trap(trap_t& t, reg_t epc); // take an exception

0 commit comments

Comments
 (0)