diff options
author | Tim Newsome <tim@sifive.com> | 2022-03-16 10:51:27 -0700 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2022-04-05 10:10:03 -0700 |
commit | 354f977848c17ba80681de60c05d46966e1ffc1a (patch) | |
tree | b9630d0a16fde153ac1b595248b8bf86940b88f0 /riscv/triggers.cc | |
parent | 894f77677d2d6bb84cf57ddec68e87857df357a1 (diff) | |
download | spike-354f977848c17ba80681de60c05d46966e1ffc1a.zip spike-354f977848c17ba80681de60c05d46966e1ffc1a.tar.gz spike-354f977848c17ba80681de60c05d46966e1ffc1a.tar.bz2 |
Move trigger_match() into triggers.
Diffstat (limited to 'riscv/triggers.cc')
-rw-r--r-- | riscv/triggers.cc | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/riscv/triggers.cc b/riscv/triggers.cc index f6b6e7d..fc7736a 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -87,4 +87,88 @@ module_t::module_t(unsigned count) : triggers(count) { } } +// Return the index of a trigger that matched, or -1. +int module_t::trigger_match(processor_t *proc, triggers::operation_t operation, reg_t address, reg_t data) +{ + state_t *state = proc->get_state(); + if (state->debug_mode) + return -1; + + bool chain_ok = true; + auto xlen = proc->get_xlen(); + + for (unsigned int i = 0; i < triggers.size(); i++) { + if (!chain_ok) { + chain_ok |= !triggers[i]->chain; + continue; + } + + if ((operation == triggers::OPERATION_EXECUTE && !triggers[i]->execute) || + (operation == triggers::OPERATION_STORE && !triggers[i]->store) || + (operation == triggers::OPERATION_LOAD && !triggers[i]->load) || + (state->prv == PRV_M && !triggers[i]->m) || + (state->prv == PRV_S && !triggers[i]->s) || + (state->prv == PRV_U && !triggers[i]->u)) { + continue; + } + + reg_t value; + if (triggers[i]->select) { + value = data; + } else { + value = address; + } + + // We need this because in 32-bit mode sometimes the PC bits get sign + // extended. + if (xlen == 32) { + value &= 0xffffffff; + } + + auto tdata2 = triggers[i]->tdata2; + switch (triggers[i]->match) { + case triggers::mcontrol_t::MATCH_EQUAL: + if (value != tdata2) + continue; + break; + case triggers::mcontrol_t::MATCH_NAPOT: + { + reg_t mask = ~((1 << (cto(tdata2)+1)) - 1); + if ((value & mask) != (tdata2 & mask)) + continue; + } + break; + case triggers::mcontrol_t::MATCH_GE: + if (value < tdata2) + continue; + break; + case triggers::mcontrol_t::MATCH_LT: + if (value >= tdata2) + continue; + break; + case triggers::mcontrol_t::MATCH_MASK_LOW: + { + reg_t mask = tdata2 >> (xlen/2); + if ((value & mask) != (tdata2 & mask)) + continue; + } + break; + case triggers::mcontrol_t::MATCH_MASK_HIGH: + { + reg_t mask = tdata2 >> (xlen/2); + if (((value >> (xlen/2)) & mask) != (tdata2 & mask)) + continue; + } + break; + } + + if (!triggers[i]->chain) { + return i; + } + chain_ok = true; + } + return -1; +} + + }; |