Skip to content

Commit

Permalink
fix(aia): external interrupt priority from PLIC or IMSIC
Browse files Browse the repository at this point in the history
  • Loading branch information
sinceforYy committed Jan 17, 2025
1 parent 68c3db2 commit 1d64532
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 66 deletions.
1 change: 1 addition & 0 deletions include/isa.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ void isa_update_mtopi();
void isa_update_stopi();
void isa_update_vstopi();
void isa_update_hgeip();
void isa_update_external_interrupt_select();
#endif
void isa_sync_custom_mflushpwr(bool l2FlushDone);

Expand Down
4 changes: 4 additions & 0 deletions src/cpu/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ 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
if (cpu.non_reg_interrupt_pending.platform_irp_meip || cpu.non_reg_interrupt_pending.from_aia_meip ||
cpu.non_reg_interrupt_pending.platform_irp_seip || cpu.non_reg_interrupt_pending.from_aia_seip) {
isa_update_external_interrupt_select();
}
isa_update_mtopi();
isa_update_stopi();
isa_update_vstopi();
Expand Down
8 changes: 8 additions & 0 deletions src/isa/riscv64/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,14 @@ void isa_update_mhpmcounter_overflow(uint64_t mhpmeventOverflowVec) {
}

#ifdef CONFIG_RV_IMSIC
void isa_update_external_interrupt_select() {
if (cpu.non_reg_interrupt_pending.platform_irp_meip || cpu.non_reg_interrupt_pending.platform_irp_seip) {
cpu.external_interrupt_select = true;
} else {
cpu.external_interrupt_select = false;
}
}

void isa_update_mtopi() {
update_mtopi();
}
Expand Down
7 changes: 5 additions & 2 deletions src/isa/riscv64/include/isa-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct NonRegInterruptPending {
bool platform_irp_stip;
bool platform_irp_vseip;
bool platform_irp_vstip;
bool from_aia_meip;
bool from_aia_seip;
bool lcofi_req;
};

Expand Down Expand Up @@ -82,7 +84,6 @@ struct MemEventQueryResult {
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 @@ -187,12 +188,14 @@ typedef struct {
#ifdef CONFIG_RV_IMSIC
struct FromAIA fromaia;
IpriosModule* MIprios;
IpriosModule* MIprios_rdata;
IpriosModule* SIprios;
IpriosModule* SIprios_rdata;
IpriosModule* VSIprios;
IpriosSort* MIpriosSort;
IpriosSort* SIpriosSort;
IpriosSort* VSIpriosSort;
HighestPrioIntr* HighestPrioIntr;
bool external_interrupt_select;
#endif

} riscv64_CPU_state;
Expand Down
9 changes: 3 additions & 6 deletions src/isa/riscv64/local-include/aia.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,11 @@ typedef struct IpriosModule {

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

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

typedef struct IpriosSort {
IpriosEnable ipriosEnable[IPRIO_ENABLE_NUM];
} IpriosSort;
Expand All @@ -38,7 +35,7 @@ typedef struct {
} Hviprios;

bool iprio_is_zero(IpriosModule* iprios);
void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios);
void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios, uint8_t xei, uint64_t xtopei);
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);
Expand Down
102 changes: 66 additions & 36 deletions src/isa/riscv64/system/aia.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,24 @@ 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) {
void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios, uint8_t xei, uint64_t xtopei) {
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;
if (interrupt_default_prio[i] == xei) {
mtopei_t* topei_tmp = (mtopei_t*)xtopei;
iprios_sort->ipriosEnable[i].isZero = cpu.external_interrupt_select;
iprios_sort->ipriosEnable[i].greaterThan255 = topei_tmp->iprio > 255;
iprios_sort->ipriosEnable[i].priority = topei_tmp->iprio & 0xff;
} else {
iprios_sort->ipriosEnable[i].isZero = ((iprios->iprios[interrupt_default_prio[i]/8].val >> (8 * (interrupt_default_prio[i]%8))) & 0xff) == 0;
iprios_sort->ipriosEnable[i].greaterThan255 = false;
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].isZero = false;
iprios_sort->ipriosEnable[i].greaterThan255 = false;
iprios_sort->ipriosEnable[i].priority = 0;
}
}
Expand All @@ -72,7 +83,7 @@ void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule
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].isZero = priority == 0;
cpu.VSIpriosSort->ipriosEnable[idx].priority = priority;
}
}
Expand All @@ -93,6 +104,15 @@ void set_hviprios(Hviprios hprios) {
}

void set_viprios_sort(uint64_t topi_gather) {
for (int i = 0; i < IPRIO_ENABLE_NUM; i++) {
if (intr_enable(topi_gather, i)) {
cpu.VSIpriosSort->ipriosEnable[i].enable = true;
cpu.VSIpriosSort->ipriosEnable[i].isZero = true;
} else {
cpu.VSIpriosSort->ipriosEnable[i].enable = false;
}
}

Hviprios hviprios;
for (int i = 0; i < 24; i++) {
hviprios.hviprios[i] = 0;
Expand All @@ -105,47 +125,57 @@ void set_viprios_sort(uint64_t topi_gather) {
}

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

for (int i = 1; i < IPRIO_ENABLE_NUM; i ++) {
// enable
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) {
// zero
bool left_prio_is_zero = ipriosSort->ipriosEnable[high_prio_idx].isZero;
bool right_prio_is_zero = ipriosSort->ipriosEnable[i].isZero;

bool left_prio_is_not_zero = !left_prio_is_zero;
bool right_prio_is_not_zero = !right_prio_is_zero;

// idx
bool left_idx_leq_xei = high_prio_idx <= get_prio_idx_in_group(xei);
bool right_idx_leq_xei = i <= get_prio_idx_in_group(xei);

bool left_idx_greater_xei = !left_idx_leq_xei;

// greater than 255
bool left_prio_greater_255 = ipriosSort->ipriosEnable[high_prio_idx].greaterThan255;
bool right_prio_greater_255 = ipriosSort->ipriosEnable[i].greaterThan255;

bool left_prio_leq_255 = !left_prio_greater_255;
bool right_prio_leq_255 = !right_prio_greater_255;

// priority
uint8_t left_prio = ipriosSort->ipriosEnable[high_prio_idx].priority;
uint8_t right_prio = ipriosSort->ipriosEnable[i].priority;

bool left_prio_leq_right_prio = left_prio <= right_prio;
bool left_prio_greater_right_prio = !left_prio_leq_right_prio;

if ((left_disenable && right_enable) ||
(left_enable && right_enable &&
(
(left_prio_is_zero && right_prio_is_not_zero && left_idx_greater_xei) ||
(left_prio_is_not_zero && right_prio_is_zero && right_idx_leq_xei) ||
(left_prio_is_not_zero && right_prio_is_not_zero &&
(
(left_prio_greater_255 && right_prio_leq_255) ||
(left_prio_leq_255 && right_prio_leq_255 && left_prio_greater_right_prio)
)
)
)
)
) {
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;
}
}
}
}

Expand Down
Loading

0 comments on commit 1d64532

Please sign in to comment.