Skip to content

Commit ca16987

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 BITRANGEMASK for generate bitmask of a range of bits. * 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 ca16987

File tree

2 files changed

+41
-128
lines changed

2 files changed

+41
-128
lines changed

include/macro.h

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

8686
#define BITMASK(bits) ((1UL << (bits)) - 1UL)
87+
// [hi:lo] is 1 and others are 0
88+
#define BITRANGEMASK(hi, lo) ((((hi) >= 63) ? (~0UL) : (1UL << ((hi) + 1UL))) - (1UL << (lo)))
8789
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
8890
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = (int64_t)x }; (uint64_t)__x.n; })
8991

9092
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1))
9193
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz) - 1))
9294

95+
#define IS_POW_OF_2(x) ((x) && !(x & (x - 1UL)))
96+
9397
#define MAX_OF(x, y) ((x) > (y) ? (x) : (y))
9498
#define MIN_OF(x, y) ((x) < (y) ? (x) : (y))
9599

src/memory/paddr.c

Lines changed: 37 additions & 128 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,145 +538,53 @@ 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;
567-
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-
}
580-
581-
#define GEN_BYTE_MASK(len) ((1ULL << (len)) - 1)
582-
#define GEN_BIT_MASK(len) ((len) >= 8 ? (~0ULL) : ((1ULL << ((len) * 8)) - 1))
583541

584542
void store_commit_queue_push(uint64_t addr, uint64_t data, int len, int cross_page_store) {
543+
585544
#ifndef CONFIG_DIFFTEST_STORE_COMMIT_AMO
586545
if (cpu.amo) {
587546
return;
588547
}
589548
#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);
620549

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;
550+
Logm("push store addr = " FMT_PADDR ", data = " FMT_WORD ", len = %d", addr,
551+
data, len);
552+
553+
// check if len is 1, 2, 4, 8 or cross page store
554+
Assert(len > 0 && len <= 8 && (IS_POW_OF_2(len) || cross_page_store || cpu.isVecUnitStore),
555+
"Invalid len %d", len);
556+
557+
// align to 8B boundary, because max len is 64b
558+
uint8_t offset = addr & 0x7ULL;
559+
uint8_t low_len = MIN_OF(len, 8 - offset);
560+
uint8_t low_mask = BITRANGEMASK(low_len + offset - 1UL, offset);
561+
uint64_t low_data =
562+
(data << (offset << 3)) & BITRANGEMASK((low_len + offset) * 8UL - 1UL, offset * 8);
563+
uint64_t low_addr = addr & ~0x7ULL;
564+
store_commit_t low_store_commit = {
565+
.addr = low_addr,
566+
.data = low_data,
567+
.mask = low_mask,
568+
.pc = prev_s->pc
569+
};
570+
store_queue_push(low_store_commit);
634571

635-
store_queue_push(store_commit);
572+
if (low_len == len) {
636573
return;
637574
}
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);
575+
576+
uint8_t high_len = len - low_len;
577+
uint64_t high_addr = low_addr + 8;
578+
uint8_t high_mask = BITRANGEMASK(high_len - 1UL, 0);
579+
uint64_t high_data = (data >> (low_len << 3)) & BITRANGEMASK(high_len * 8UL - 1UL, 0);
580+
store_commit_t high_store_commit = {
581+
.addr = high_addr,
582+
.data = high_data,
583+
.mask = high_mask,
584+
.pc = prev_s->pc
585+
};
586+
587+
store_queue_push(high_store_commit);
679588
}
680589

681590
store_commit_t store_commit_queue_pop(int *flag) {

0 commit comments

Comments
 (0)