Browse Source

Merge pull request #1207 from YenHaoChen/pr-trap-trigger-common

triggers: refactor: add trap_common_t
pull/1211/head
Scott Johnson 3 years ago
committed by GitHub
parent
commit
b3946f8500
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      riscv/triggers.cc
  2. 31
      riscv/triggers.h

36
riscv/triggers.cc

@ -54,6 +54,10 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) <= SSELECT_MAXVAL) ? get_field(val, CSR_TEXTRA_SSELECT(xlen)) : SSELECT_IGNORE);
}
bool trigger_t::common_match(processor_t * const proc) const noexcept {
return mode_match(proc->get_state()) && textra_match(proc);
}
bool trigger_t::mode_match(state_t * const state) const noexcept
{
switch (state->prv) {
@ -190,7 +194,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
if ((operation == triggers::OPERATION_EXECUTE && !execute) ||
(operation == triggers::OPERATION_STORE && !store) ||
(operation == triggers::OPERATION_LOAD && !load) ||
!mode_match(proc->get_state())) {
!common_match(proc)) {
return std::nullopt;
}
@ -310,22 +314,27 @@ void itrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b
action = legalize_action(get_field(val, CSR_ITRIGGER_ACTION));
}
std::optional<match_result_t> itrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
{
if (!mode_match(proc->get_state()))
if (!common_match(proc))
return std::nullopt;
auto xlen = proc->get_xlen();
bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0;
reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1));
assert(bit < xlen);
if (interrupt && ((bit == 0 && nmi) || ((tdata2 >> bit) & 1))) { // Assume NMI's exception code is 0
if (simple_match(interrupt, bit)) {
hit = true;
return match_result_t(TIMING_AFTER, action);
}
return std::nullopt;
}
bool itrigger_t::simple_match(bool interrupt, reg_t bit) const
{
return interrupt && ((bit == 0 && nmi) || ((tdata2 >> bit) & 1)); // Assume NMI's exception code is 0
}
reg_t etrigger_t::tdata1_read(const processor_t * const proc) const noexcept
{
auto xlen = proc->get_xlen();
@ -356,20 +365,9 @@ void etrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b
action = legalize_action(get_field(val, CSR_ETRIGGER_ACTION));
}
std::optional<match_result_t> etrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
bool etrigger_t::simple_match(bool interrupt, reg_t bit) const
{
if (!mode_match(proc->get_state()))
return std::nullopt;
auto xlen = proc->get_xlen();
bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0;
reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1));
assert(bit < xlen);
if (!interrupt && ((tdata2 >> bit) & 1)) {
hit = true;
return match_result_t(TIMING_AFTER, action);
}
return std::nullopt;
return !interrupt && ((tdata2 >> bit) & 1);
}
module_t::module_t(unsigned count) : triggers(count) {
@ -483,7 +481,7 @@ std::optional<match_result_t> module_t::detect_memory_access_match(operation_t o
* entire chain did not match. This is allowed by the spec, because the final
* trigger in the chain will never get `hit` set unless the entire chain
* matches. */
auto result = trigger->textra_match(proc) ? trigger->detect_memory_access_match(proc, operation, address, data) : std::nullopt;
auto result = trigger->detect_memory_access_match(proc, operation, address, data);
if (result.has_value() && !trigger->get_chain())
return result;
@ -499,7 +497,7 @@ std::optional<match_result_t> module_t::detect_trap_match(const trap_t& t) noexc
return std::nullopt;
for (auto trigger: triggers) {
auto result = trigger->textra_match(proc) ? trigger->detect_trap_match(proc, t) : std::nullopt;
auto result = trigger->detect_trap_match(proc, t);
if (result.has_value())
return result;
}

31
riscv/triggers.h

@ -83,11 +83,10 @@ public:
virtual std::optional<match_result_t> detect_memory_access_match(processor_t UNUSED * const proc,
operation_t UNUSED operation, reg_t UNUSED address, std::optional<reg_t> UNUSED data) noexcept { return std::nullopt; }
virtual std::optional<match_result_t> detect_trap_match(processor_t UNUSED * const proc, const trap_t UNUSED & t) noexcept { return std::nullopt; }
bool textra_match(processor_t * const proc) const noexcept;
protected:
action_t legalize_action(reg_t val) const noexcept;
bool mode_match(state_t * const state) const noexcept;
bool common_match(processor_t * const proc) const noexcept;
reg_t tdata2;
bool vs = false;
@ -98,6 +97,8 @@ protected:
private:
unsigned legalize_mhselect(bool h_enabled) const noexcept;
bool mode_match(state_t * const state) const noexcept;
bool textra_match(processor_t * const proc) const noexcept;
struct mhselect_interpretation {
const unsigned mhselect;
@ -145,37 +146,39 @@ private:
bool dmode;
};
class itrigger_t : public trigger_t {
class trap_common_t : public trigger_t {
public:
virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override;
virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override;
bool get_dmode() const override { return dmode; }
virtual action_t get_action() const override { return action; }
virtual std::optional<match_result_t> detect_trap_match(processor_t * const proc, const trap_t& t) noexcept override;
private:
virtual bool simple_match(bool interrupt, reg_t bit) const = 0;
protected:
bool dmode;
bool hit;
bool nmi;
action_t action;
};
class etrigger_t : public trigger_t {
class itrigger_t : public trap_common_t {
public:
virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override;
virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override;
bool get_dmode() const override { return dmode; }
virtual action_t get_action() const override { return action; }
private:
virtual bool simple_match(bool interrupt, reg_t bit) const override;
bool nmi;
};
virtual std::optional<match_result_t> detect_trap_match(processor_t * const proc, const trap_t& t) noexcept override;
class etrigger_t : public trap_common_t {
public:
virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override;
virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override;
private:
bool dmode;
bool hit;
action_t action;
virtual bool simple_match(bool interrupt, reg_t bit) const override;
};
class mcontrol_common_t : public trigger_t {

Loading…
Cancel
Save