Skip to content

Commit

Permalink
fix(intr, aia): update xtopi and use xtopi to update intr deleg
Browse files Browse the repository at this point in the history
* NEMU could get xtopei csr register to update xtopi by difftest
* add m/s/vsiprio struct and add init iprio method
* add update xtopi method to update interrupt deleg when intr raise
* add xtopei, xtopi, xireg csr registers read/write
  • Loading branch information
sinceforYy committed Nov 19, 2024
1 parent b9507fb commit f7a7a85
Show file tree
Hide file tree
Showing 11 changed files with 585 additions and 2 deletions.
5 changes: 5 additions & 0 deletions include/isa.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,10 @@ void isa_difftest_set_mhartid(int n);
#endif
void isa_update_mip(unsigned lcofip);
void isa_update_mhpmcounter_overflow(uint64_t mhpmeventOverflowVec);
#ifdef CONFIG_RV_IMSIC
void isa_update_mtopi();
void isa_update_stopi();
void isa_update_vstopi();
#endif

#endif
1 change: 1 addition & 0 deletions src/cpu/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <generated/autoconf.h>
#include <profiling/profiling_control.h>
#include "../local-include/trigger.h"
#include "../local-include/aia.h"

/* The assembly code of instructions executed is only output to the screen
* when the number of instructions executed is less than this value.
Expand Down
12 changes: 12 additions & 0 deletions src/cpu/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ void difftest_raise_mhpmevent_overflow(uint64_t mhpmeventOverflowVec) {
void difftest_non_reg_interrupt_pending(void *nonRegInterruptPending) {
memcpy(&cpu.non_reg_interrupt_pending, nonRegInterruptPending, sizeof(struct NonRegInterruptPending));
isa_update_mip(cpu.non_reg_interrupt_pending.lcofi_req);
#ifdef CONFIG_RV_IMSIC
isa_update_mtopi();
isa_update_stopi();
isa_update_vstopi();
#endif
}

#ifdef CONFIG_DIFFTEST_STORE_COMMIT
Expand All @@ -268,6 +273,13 @@ void difftest_get_store_event_other_info(void *info) {



void difftest_aia_xtopei(void *xtopei) {
#ifdef CONFIG_RV_IMSIC
memcpy(&cpu.xtopei, xtopei, sizeof(struct Xtopei));
isa_update_vstopi();
#endif
}

void difftest_enable_debug() {
#ifdef CONFIG_SHARE
dynamic_config.debug_difftest = true;
Expand Down
14 changes: 14 additions & 0 deletions src/isa/riscv64/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,3 +435,17 @@ void isa_update_mhpmcounter_overflow(uint64_t mhpmeventOverflowVec) {
}
#endif
}

#ifdef CONFIG_RV_IMSIC
void isa_update_mtopi() {
update_mtopi();
}

void isa_update_stopi() {
update_stopi();
}

void isa_update_vstopi() {
update_vstopi();
}
#endif
20 changes: 20 additions & 0 deletions src/isa/riscv64/include/isa-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ struct NonRegInterruptPending {
bool lcofi_req;
};

struct Xtopei {
uint64_t mtopei;
uint64_t stopei;
uint64_t vstopei;
};

struct DebugInfo {
uint64_t current_pc;
};
Expand All @@ -73,6 +79,9 @@ struct MemEventQueryResult {
#endif

typedef struct TriggerModule TriggerModule;
typedef struct IpriosModule IpriosModule;
typedef struct IpriosSort IpriosSort;
typedef struct HighestPrioIntr HighestPrioIntr;

typedef struct {
// Below will be synced by regcpy when run difftest, DO NOT TOUCH
Expand Down Expand Up @@ -174,6 +183,17 @@ typedef struct {

trap_info_t trapInfo;

#ifdef CONFIG_RV_IMSIC
struct Xtopei xtopei;
IpriosModule* MIprios;
IpriosModule* SIprios;
IpriosModule* VSIprios;
IpriosSort* MIpriosSort;
IpriosSort* SIpriosSort;
IpriosSort* VSIpriosSort;
HighestPrioIntr* HighestPrioIntr;
#endif

} riscv64_CPU_state;

// decode
Expand Down
7 changes: 7 additions & 0 deletions src/isa/riscv64/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ void init_csr();
#ifdef CONFIG_RV_SDTRIG
void init_trigger();
#endif // CONFIG_RV_SDTRIG
#ifdef CONFIG_RV_IMSIC
void init_iprio();
#endif

#if !defined(CONFIG_SHARE) || defined(CONFIG_LIGHTQS)
void init_clint();
Expand Down Expand Up @@ -202,6 +205,10 @@ void init_isa() {
init_trigger();
#endif // CONFIG_RV_SDTRIG

#ifdef CONFIG_RV_IMSIC
init_iprio();
#endif

#define MSTATEEN0_RESET 0xdc00000000000001ULL
#define HSTATEEN0_RESET 0xdc00000000000001ULL
#define SSTATEEN0_RESET 0x0000000000000001ULL
Expand Down
53 changes: 53 additions & 0 deletions src/isa/riscv64/local-include/aia.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#ifdef CONFIG_RV_IMSIC

#ifndef __AIA_H__
#define __AIA_H__

#include "common.h"
#include "csr.h"
#include "intr.h"

// 0,4,8 is reserved
#define IPRIO_ENABLE_NUM 61
#define IPRIO_NUM 8

typedef struct {
word_t val;
} Iprio;

typedef struct IpriosModule {
Iprio iprios[IPRIO_NUM];
} IpriosModule;

typedef struct {
bool enable;
uint8_t priority;
} IpriosEnable;

typedef struct HighestPrioIntr {
uint8_t idx;
uint8_t priority;
} HighestPrioIntr;

typedef struct IpriosSort {
IpriosEnable ipriosEnable[IPRIO_ENABLE_NUM];
} IpriosSort;

typedef struct {
uint8_t hviprios[24];
} Hviprios;

bool iprio_is_zero(IpriosModule* iprios);
void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios);
void set_viprios_sort(uint64_t topi_gather);
uint8_t high_iprio(IpriosSort* ipriosSort, uint8_t xei);
uint8_t get_prio_idx_in_group(uint8_t irq);

extern int interrupt_default_prio[IPRIO_ENABLE_NUM];

bool no_mtopi();
bool no_stopi();
bool no_vstopi();

#endif // __AIA_H__
#endif // CONFIG_RV_IMSIC
13 changes: 13 additions & 0 deletions src/isa/riscv64/local-include/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,14 @@ CSR_STRUCT_START(hvictl)
CSR_STRUCT_END(hvictl)

CSR_STRUCT_START(hviprio1)
uint64_t intr0 : 8; // [7 : 0] reserved
uint64_t ssi : 8; // [16: 8]
uint64_t intr4 : 8; // [23:16] reserved
uint64_t sti : 8; // [31:24]
uint64_t intr8 : 8; // [39:32] reserved
uint64_t coi : 8; // [47:40]
uint64_t intr14 : 8; // [55:48]
uint64_t intr15 : 8; // [63:56]
CSR_STRUCT_END(hviprio1)

CSR_STRUCT_START(hviprio2)
Expand Down Expand Up @@ -1524,6 +1532,11 @@ void csr_prepare();

word_t gen_status_sd(word_t status);
word_t get_mip();
#ifdef CONFIG_RV_IMSIC
void update_mtopi();
void update_stopi();
void update_vstopi();
#endif

/** PMP **/
uint8_t pmpcfg_from_index(int idx);
Expand Down
165 changes: 165 additions & 0 deletions src/isa/riscv64/system/aia.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include "isa.h"
#include "cpu/cpu.h"
#include "../local-include/aia.h"

#ifdef CONFIG_RV_IMSIC

int interrupt_default_prio[IPRIO_ENABLE_NUM] = {
// custom highest group
63, 31, 62,
61, 30, 60,
// local high group
47, 23, 46,
45, 22, 44,
43, 21, 42,
41, 20, 40,
// custom middle high group
59, 29, 58,
57, 28, 56,
// priv arch group
IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
IRQ_SGEI,
IRQ_VSEIP, IRQ_VSSIP, IRQ_VSTIP,
IRQ_LCOFI, 14, 15,
// custom middle low group
55, 27, 54,
53, 26, 52,
// local low group
39, 19, 38,
37, 18, 36,
35, 17, 34,
33, 16, 32,
// custom lowest group
51, 25, 50,
49, 24, 48
};

bool iprio_is_zero(IpriosModule* iprios) {
bool is_zero = true;
for (int i = 0; i < IPRIO_NUM; i++) {
is_zero &= iprios->iprios[i].val == 0;
}
return is_zero;
}

uint8_t get_prio_idx_in_group(uint8_t irq) {
uint8_t idx = 0;
for (int i = 0; i < IPRIO_ENABLE_NUM; i++) {
if (irq == interrupt_default_prio[i]) {
idx = i;
}
}
return idx;
}

bool intr_enable(uint64_t topi_gather, uint64_t idx) {
return (topi_gather >> interrupt_default_prio[idx]) & 0x1;
}

void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios) {
for (int i = 0; i < IPRIO_ENABLE_NUM; i++) {
if (intr_enable(topi_gather, i)) {
iprios_sort->ipriosEnable[i].enable = true;
iprios_sort->ipriosEnable[i].priority = (iprios->iprios[interrupt_default_prio[i]/8].val >> (8 * (interrupt_default_prio[i]%8))) & 0xff;
} else {
iprios_sort->ipriosEnable[i].enable = false;
iprios_sort->ipriosEnable[i].priority = 0;
}
}
}

void handle_irq_hviprio(uint8_t irq, uint64_t topi, uint8_t priority) {
word_t idx = get_prio_idx_in_group(irq);
if (intr_enable(topi, idx)) {
cpu.VSIpriosSort->ipriosEnable[idx].enable = true;
cpu.VSIpriosSort->ipriosEnable[idx].priority = priority;
}
}

word_t get_hviprio2(uint8_t idx) {
return (hviprio2->val >> 8 * idx) & 0xf;
}

void set_hviprios(Hviprios hprios) {
hprios.hviprios[1] = hviprio1->ssi;
hprios.hviprios[5] = hviprio1->sti;
hprios.hviprios[13] = hviprio1->coi;
hprios.hviprios[14] = hviprio1->intr14;
hprios.hviprios[15] = hviprio1->intr15;
for (int i = 0; i < 8; i++) {
hprios.hviprios[i+16] = get_hviprio2(i);
}
}

void set_viprios_sort(uint64_t topi_gather) {
Hviprios hviprios;
for (int i = 0; i < 24; i++) {
hviprios.hviprios[i] = 0;
}

set_hviprios(hviprios);
for (int i = 0; i < 24; i++) {
handle_irq_hviprio(i, topi_gather, hviprios.hviprios[i]);
}
}

uint8_t high_iprio(IpriosSort* ipriosSort, uint8_t xei) {
uint8_t high_prio_idx = cpu.HighestPrioIntr->idx;

for (int i = 1; i < IPRIO_ENABLE_NUM; i ++) {
bool left_enable = ipriosSort->ipriosEnable[high_prio_idx].enable;
bool right_enable = ipriosSort->ipriosEnable[i].enable;

bool left_disenable = !left_enable;

uint8_t left_priority = ipriosSort->ipriosEnable[high_prio_idx].priority;
uint8_t right_priority = ipriosSort->ipriosEnable[i].priority;

bool left_priority_is_zero = left_priority == 0;
bool right_priority_is_zero = right_priority == 0;

bool left_priority_is_not_zero = !left_priority_is_zero;
bool right_priority_is_not_zero = !right_priority_is_zero;

bool left_leq_xei = high_prio_idx <= get_prio_idx_in_group(xei);
bool right_leq_xei = i <= get_prio_idx_in_group(xei);

bool left_great_xei = !left_leq_xei;

bool left_leq_right = left_priority <= right_priority;
bool left_great_right = !left_leq_right;

if (left_disenable && right_enable) {
high_prio_idx = i;
} else if (left_enable && right_enable) {
if (left_priority_is_zero && right_priority_is_not_zero) {
if (left_great_xei || right_leq_xei) {
high_prio_idx = i;
}
} else if (left_priority_is_not_zero && right_priority_is_zero) {
if (left_great_xei && right_leq_xei) {
high_prio_idx = i;
}
} else if (left_priority_is_not_zero && right_priority_is_not_zero) {
if (left_great_right) {
high_prio_idx = i;
}
}
}
}

return high_prio_idx;
}

bool no_mtopi() {
return mtopi->iid == 0;
}
bool no_stopi() {
return stopi->iid == 0;
}
bool no_vstopi() {
return vstopi->iid == 0;
}

#endif
Loading

0 comments on commit f7a7a85

Please sign in to comment.