Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(intr, aia): update xtopi and use xtopi update intr deleg #651

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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