Make the interrupt lines belong to a bus rather than to the machine
The second piece of the peripheral core, and like the first it changes nothing: one array of bits became a struct, and the machine's own devices reach it through wrappers because every one of them really is on this bus. IT WAS ONE ARRAY INDEXED BY PORT FOR THE WHOLE MACHINE. With two processors that is not a tidiness problem, it is each of them seeing the other's lines: a disk finishing would interrupt a sound core, a sound core's tick would interrupt the shell, and both would arrive at a handler installed for something else entirely. Hardware vectors are per port, so the numbers would even look plausible on the way in. Unlike the shift register, which was harmless until there was a second core to share it with, this one was always going to be wrong the moment there was one. Still to come on this rung: a controller each, since it holds the source, the destination, the length and five guard registers, and two cores setting those between each other's instructions would interleave into nonsense. Then the interleaving rule, which belongs in the manual as machine behaviour rather than as something the emulator happens to do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
4e3258e3f7
commit
5be5bea994
+23
-10
@@ -622,11 +622,9 @@ static uint8_t consoleStatus(void) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// One bit per port, so a device can ask for attention without anything having to poll
|
||||
// it. Eight ports to the byte, low bit first.
|
||||
#define INTERRUPT_LINE_BYTES 32
|
||||
|
||||
static uint8_t pendingInterrupts[INTERRUPT_LINE_BYTES];
|
||||
// The machine's own lines. A peripheral core's device keeps its own set, which is the
|
||||
// entire reason these are a struct rather than an array sitting here.
|
||||
static InterruptLines machineLines;
|
||||
|
||||
// Whether somebody has asked the machine to start over, and taking that request away.
|
||||
static int resetWanted = 0;
|
||||
@@ -671,24 +669,35 @@ const Bus *machineBus(void) {
|
||||
return &theMachinesBus;
|
||||
}
|
||||
|
||||
void linesRaise(InterruptLines *lines, uint8_t port) {
|
||||
lines->bits[port >> 3] |= (uint8_t)(1u << (port & 7));
|
||||
}
|
||||
|
||||
void linesClear(InterruptLines *lines, uint8_t port) {
|
||||
lines->bits[port >> 3] &= (uint8_t)~(1u << (port & 7));
|
||||
}
|
||||
|
||||
// The machine's own, which is what every device in this file means when it asks for
|
||||
// attention. Wrappers rather than a change at every call site, because every one of those
|
||||
// devices really is on this bus and saying so twenty times would not make it truer.
|
||||
void raiseInterrupt(uint8_t port) {
|
||||
pendingInterrupts[port >> 3] |= (uint8_t)(1u << (port & 7));
|
||||
linesRaise(&machineLines, port);
|
||||
}
|
||||
|
||||
void clearInterrupt(uint8_t port) {
|
||||
pendingInterrupts[port >> 3] &= (uint8_t)~(1u << (port & 7));
|
||||
linesClear(&machineLines, port);
|
||||
}
|
||||
|
||||
int nextPendingInterrupt(void) {
|
||||
int linesNext(const InterruptLines *lines) {
|
||||
// Lowest numbered port wins. This is a scan rather than a priority encoder, which
|
||||
// means there is no arbitration to explain and a programmer can work out what
|
||||
// happens next by reading the port numbers.
|
||||
for (int group = 0; group < INTERRUPT_LINE_BYTES; group++) {
|
||||
if (pendingInterrupts[group] == 0) {
|
||||
if (lines->bits[group] == 0) {
|
||||
continue;
|
||||
}
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
if (pendingInterrupts[group] & (1u << bit)) {
|
||||
if (lines->bits[group] & (1u << bit)) {
|
||||
return group * 8 + bit;
|
||||
}
|
||||
}
|
||||
@@ -696,6 +705,10 @@ int nextPendingInterrupt(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nextPendingInterrupt(void) {
|
||||
return linesNext(&machineLines);
|
||||
}
|
||||
|
||||
// ---- Refusing ----
|
||||
//
|
||||
// Set when a device will not do what it was asked, and read by the CPU immediately
|
||||
|
||||
Reference in New Issue
Block a user