Skip to content

Commit dc8aa6c

Browse files
committed
refactor(paddr.c, macro.h): update store_commit_queue_push logic and add new macro
* if a committed store crosses a 8 byte boundary, the function store_commit_queue_push() will split the store commit into two parts, and push them into the commit queue separately. * add macro SAFE_BITMASK for generating bitmask safely. * add macro SAFE_BITMASKRANGE for generating range-based bitmask safely. * add macro IS_POW_OF_2 for check if a number is a power of 2. BREAKING CHANGE: store_queue diff is not backward compatible!
1 parent d046c0e commit dc8aa6c

File tree

2 files changed

+48
-130
lines changed

2 files changed

+48
-130
lines changed

include/macro.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,18 @@
8484
#define MAP(c, f) c(f)
8585

8686
#define BITMASK(bits) ((1UL << (bits)) - 1UL)
87+
// safe bitmask function to avoid overflow
88+
#define SAFE_BITMASK(bits) (((bits) >= 64ULL) ? (~0ULL) : (BITMASK(bits)))
89+
#define SAFE_BITMASKRANGE(hi, lo) ((SAFE_BITMASK(hi)) & (~SAFE_BITMASK(lo)))
90+
8791
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
8892
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = (int64_t)x }; (uint64_t)__x.n; })
8993

9094
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1))
9195
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz) - 1))
9296

97+
#define IS_POW_OF_2(x) ((x) && !(x & (x - 1UL)))
98+
9399
#define MAX_OF(x, y) ((x) > (y) ? (x) : (y))
94100
#define MIN_OF(x, y) ((x) < (y) ? (x) : (y))
95101

src/memory/paddr.c

Lines changed: 42 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <cpu/cpu.h>
2626
#include "../local-include/csr.h"
2727
#include "../local-include/intr.h"
28+
#include "macro.h"
2829

2930
unsigned long MEMORY_SIZE = CONFIG_MSIZE;
3031

@@ -537,150 +538,61 @@ bool analysis_memory_isuse(uint64_t page) {
537538
#endif
538539

539540
#ifdef CONFIG_DIFFTEST_STORE_COMMIT
540-
#define LIMITING_SHIFT(x) (((uint64_t)(x)) < ((uint64_t)63ULL) ? ((uint64_t)(x)) : ((uint64_t)63ULL))
541-
void miss_align_store_commit_queue_push(uint64_t addr, uint64_t data, int len) {
542-
// align with dut
543-
uint8_t inside_16bytes_bound = ((addr >> 4) & 1ULL) == (((addr + len - 1) >> 4) & 1ULL);
544-
uint64_t st_mask = (len == 1) ? 0x1ULL : (len == 2) ? 0x3ULL : (len == 4) ? 0xfULL : (len == 8) ? 0xffULL : 0xdeadbeefULL;
545-
uint64_t st_data_mask = (len == 1) ? 0xffULL : (len == 2) ? 0xffffULL : (len == 4) ? 0xffffffffULL : (len == 8) ? 0xffffffffffffffffULL : 0xdeadbeefULL;
546-
store_commit_t low_addr_st;
547-
store_commit_t high_addr_st;
548-
549-
if (inside_16bytes_bound) {
550-
low_addr_st.addr = addr - (addr % 16ULL);
551-
if ((addr % 16ULL) > 8) {
552-
low_addr_st.data = 0;
553-
} else {
554-
low_addr_st.data = (data & st_data_mask) << LIMITING_SHIFT((addr % 16ULL) << 3);
555-
}
556-
low_addr_st.mask = (st_mask << (addr % 16ULL)) & 0xffULL;
557-
low_addr_st.pc = prev_s->pc;
558-
559-
store_queue_push(low_addr_st);
560-
561-
// printf("[DEBUG] inside 16 bytes region addr: %lx, data: %lx, mask: %lx\n", low_addr_st->addr, low_addr_st->data, (uint64_t)(low_addr_st->mask));
562-
} else {
563-
low_addr_st.addr = addr - (addr % 8ULL);
564-
low_addr_st.data = (data & (st_data_mask >> ((addr % len) << 3))) << LIMITING_SHIFT((8 - len + (addr % len)) << 3);
565-
low_addr_st.mask = (st_mask >> (addr % len)) << (8 - len + (addr % len));
566-
low_addr_st.pc = prev_s->pc;
567541

568-
high_addr_st.addr = addr - (addr % 16ULL) + 16ULL;
569-
high_addr_st.data = (data >> LIMITING_SHIFT((len - (addr % len)) << 3)) & (st_data_mask >> LIMITING_SHIFT((len - (addr % len)) << 3));
570-
high_addr_st.mask = st_mask >> (len - (addr % len));
571-
high_addr_st.pc = prev_s->pc;
572-
573-
store_queue_push(low_addr_st);
574-
store_queue_push(high_addr_st);
575-
576-
// printf("[DEBUG] split low addr store addr: %lx, data: %lx, mask: %lx\n", low_addr_st->addr, low_addr_st->data, (uint64_t)(low_addr_st->mask));
577-
// printf("[DEBUG] split high addr store addr: %lx, data: %lx, mask: %lx\n", high_addr_st->addr, high_addr_st->data, (uint64_t)(high_addr_st->mask));
578-
}
579-
}
542+
void store_commit_queue_push(uint64_t addr, uint64_t data, int len,
543+
int cross_page_store) {
580544

581-
#define GEN_BYTE_MASK(len) ((1ULL << (len)) - 1)
582-
#define GEN_BIT_MASK(len) ((len) >= 8 ? (~0ULL) : ((1ULL << ((len) * 8)) - 1))
583-
584-
void store_commit_queue_push(uint64_t addr, uint64_t data, int len, int cross_page_store) {
585545
#ifndef CONFIG_DIFFTEST_STORE_COMMIT_AMO
586546
if (cpu.amo) {
587547
return;
588548
}
589549
#endif // CONFIG_DIFFTEST_STORE_COMMIT_AMO
590-
#ifdef CONFIG_AC_NONE
591-
uint8_t store_miss_align = (addr & (len - 1)) != 0;
592-
if (unlikely(store_miss_align)) {
593-
if (!cross_page_store && !cpu.isVecUnitStore) {
594-
miss_align_store_commit_queue_push(addr, data, len);
595-
return;
596-
}
597-
}
598-
#endif // CONFIG_AC_NONE
599-
Logm("push store addr = " FMT_PADDR ", data = " FMT_WORD ", len = %d", addr, data, len);
600-
store_commit_t store_commit;
601-
602-
if (cpu.isVecUnitStore)
603-
{
604-
bool isCross128Bit = (addr & 0xF) + len > 16;
605-
606-
if (isCross128Bit)
607-
{
608-
paddr_t offset_in_block = addr & 0xF;
609-
paddr_t space_left = 16 - offset_in_block;
610-
611-
paddr_t low_addr = addr;
612-
uint8_t low_len = space_left;
613-
uint16_t low_mask = (1U << low_len) - 1;
614-
word_t low_data = data & ((1ULL << low_len * 8) - 1);
615-
616-
paddr_t high_addr = addr + space_left;
617-
uint8_t high_len = len - space_left;
618-
uint16_t high_mask = (1U << high_len) - 1;
619-
word_t high_data = data >> (low_len * 8);
620550

621-
store_commit_t low_store_commit = {low_addr, low_data, low_mask, prev_s->pc};
622-
store_commit_t high_store_commit = {high_addr, high_data, high_mask, prev_s->pc};
623-
624-
store_queue_push(low_store_commit);
625-
store_queue_push(high_store_commit);
626-
627-
return;
628-
}
629-
store_commit.data = data & GEN_BIT_MASK(len);
630-
store_commit.mask = GEN_BYTE_MASK(len);
631-
assert(len <= 8);
632-
store_commit.addr = addr;
633-
store_commit.pc = prev_s->pc;
634-
635-
store_queue_push(store_commit);
551+
Logm("push store addr = " FMT_PADDR ", data = " FMT_WORD ", len = %d", addr,
552+
data, len);
553+
554+
// check if len is 1, 2, 4, 8 or cross page store or isVecUnitStore
555+
// maybe isVecUnitStore check is useless there
556+
Assert(len > 0 && len <= 8 &&
557+
(IS_POW_OF_2(len) || cross_page_store || cpu.isVecUnitStore),
558+
"Invalid len %d", len);
559+
560+
// align to 8B boundary, because max len is 64b
561+
uint8_t offset = addr & 0x7ULL;
562+
uint8_t low_len = MIN_OF(len, 8 - offset);
563+
uint8_t low_mask = SAFE_BITMASKRANGE(low_len + offset, offset);
564+
uint64_t low_addr = addr & ~0x7ULL;
565+
uint64_t low_data = (data << (offset << 3)) &
566+
SAFE_BITMASKRANGE((low_len + offset) * 8, offset * 8);
567+
store_commit_t low_store_commit = {
568+
.addr = low_addr, .data = low_data, .mask = low_mask, .pc = prev_s->pc};
569+
ref_log_cpu(
570+
"Queue low store addr = " FMT_PADDR ", data = " FMT_WORD ", mask = %08x",
571+
low_store_commit.addr, low_store_commit.data, low_store_commit.mask);
572+
store_queue_push(low_store_commit);
573+
574+
if (low_len == len) {
636575
return;
637576
}
638-
uint64_t offset = addr % 8ULL;
639-
store_commit.addr = addr - offset;
640-
switch (len) {
641-
case 1:
642-
store_commit.data = (data & 0xffULL) << (offset << 3);
643-
store_commit.mask = 0x1 << offset;
644-
break;
645-
case 2:
646-
store_commit.data = (data & 0xffffULL) << (offset << 3);
647-
store_commit.mask = 0x3 << offset;
648-
break;
649-
case 4:
650-
store_commit.data = (data & 0xffffffffULL) << (offset << 3);
651-
store_commit.mask = 0xf << offset;
652-
break;
653-
case 8:
654-
store_commit.data = data;
655-
store_commit.mask = 0xff;
656-
break;
657-
default:
658-
#ifdef CONFIG_AC_NONE
659-
// strange length, only valid from cross page write
660-
if (cross_page_store) {
661-
int i = 0;
662-
uint64_t _data_mask = 0;
663-
uint64_t _mask = 0;
664-
for (; i < len; i++) {
665-
_data_mask = (_data_mask << 8) | 0xffUL;
666-
_mask = (_mask << 1) | 0x1UL;
667-
}
668-
store_commit.data = (data & _data_mask) << (offset << 3);
669-
store_commit.mask = _mask << offset;
670-
} else {
671-
assert(0);
672-
}
673-
#else
674-
assert(0);
675-
#endif // CONFIG_AC_NONE
676-
}
677-
store_commit.pc = prev_s->pc;
678-
store_queue_push(store_commit);
577+
578+
uint8_t high_len = len - low_len;
579+
uint8_t high_mask = SAFE_BITMASKRANGE(high_len, 0);
580+
uint64_t high_addr = low_addr + 8;
581+
uint64_t high_data =
582+
(data >> (low_len << 3)) & SAFE_BITMASKRANGE(high_len * 8, 0);
583+
store_commit_t high_store_commit = {.addr = high_addr,
584+
.data = high_data,
585+
.mask = high_mask,
586+
.pc = prev_s->pc};
587+
ref_log_cpu(
588+
"Queue high store addr = " FMT_PADDR ", data = " FMT_WORD ", mask = %08x",
589+
high_store_commit.addr, high_store_commit.data, high_store_commit.mask);
590+
store_queue_push(high_store_commit);
679591
}
680592

681593
store_commit_t store_commit_queue_pop(int *flag) {
682594
*flag = 1;
683-
store_commit_t result = {.addr=0, .data=0, .mask=0};
595+
store_commit_t result = {.addr = 0, .data = 0, .mask = 0};
684596
if (store_queue_empty()) {
685597
*flag = 0;
686598
return result;

0 commit comments

Comments
 (0)