@aswaterman explains:
Rather than requiring each MMIO device to support arbitrary sizes and
alignments, decompose MMIO misaligned loads and stores in such a way
as to guarantee their constituent parts are always aligned.
(Specifically, they now always decompose to a sequence of one-byte
accesses.)
This is not a semantic change for main-memory accesses, but it is a
semantic change for I/O devices. It makes them more realistic, in that
most bus standards don't support non-power-of-2-sized accesses.
Since mtime and mtimecmp both initialize to 0, and "a machine timer
interrupt becomes pending whenever mtime contains a value greater than
or equal to mtimecmp," MTIP should be 1.
Before this change, MTIP would be 0 until the first increment, or
until reading/writing from CLINT regs (since clint_t::load() and
clint_t::store() call increment(0)).
std::min takes its arguments by reference, so the arguments need to be
defined. An alternative would have been to force the problematic argument
into being an rvalue (e.g., by adding 0), but this approach seems to me
to be more robust.
This fixes compilation under -O0; see https://github.com/riscv-software-src/riscv-isa-sim/pull/1264#issuecomment-1451114717@scottj97 I posit that this situation is unusual enough that it shouldn't
motivate us to test -O0 in CI.
This is a large delta because the old implementation baked in multiple
assumptions about the contiguity of hart IDs.
As a side effect, fix implementation for big-endian hosts.
This commit started as an attempt to make the PLIC tolerant of
discontiguous hart IDs, but it turns out it was already most of
the way there: PLIC contexts can still be dense even if the hart
IDs are not.
Nevertheless, I wanted to avoid passing the procs vector directly to
the plic_t constructor. In removing it, I realized I could also get
rid of the smode parameter by querying whether each hart has S-mode.
This is also more correct; previously, we were instantiating the PLIC
as though all harts had S-mode, regardless of whether they actually did.
Debug spec says:
Because chain affects the next trigger, hardware
must zero it in writes to mcontrol that set dmode
to 0 if the next trigger has dmode of 1. In addition
hardware should ignore writes to mcontrol that
set dmode to 1 if the previous trigger has both
dmode of 0 and chain of 1. Debuggers must avoid
the latter case by checking chain on the previous
trigger if they’re writing mcontrol.
Previously, this was ignoring the write even if it was coming from
M-mode and therefore would have had dmode forced to 0. That should not
count as a "write to mcontrol that sets dmode to 1".