1
0
mirror of https://github.com/sethm/symon.git synced 2024-06-15 08:29:27 +00:00

Add interrupt flag to CPU

This commit is contained in:
Seth Morabito 2014-01-25 19:53:53 -08:00
parent 3d36cd5460
commit 0c5035fc56
3 changed files with 151 additions and 102 deletions

View File

@ -151,6 +151,18 @@ public class Bus {
throw new MemoryAccessException("Bus write failed. No device at address " + String.format("$%04X", address));
}
public void assertInterrupt() {
if (cpu != null) {
cpu.assertInterrupt();
}
}
public void clearInterrupt() {
if (cpu != null) {
cpu.clearInterrupt();
}
}
public SortedSet<Device> getDevices() {
// Expose a copy of the device list, not the original
return new TreeSet<Device>(devices);

View File

@ -113,7 +113,9 @@ public class Cpu implements InstructionTable {
* Reset the CPU to known initial values.
*/
public void reset() throws MemoryAccessException {
// Registers
/* TODO: In reality, the stack pointer could be anywhere
on the stack after reset. This non-deterministic behavior might be
worth while to simulate. */
state.sp = 0xff;
// Set the PC to the address stored in the reset vector
@ -131,6 +133,8 @@ public class Cpu implements InstructionTable {
state.overflowFlag = false;
state.negativeFlag = false;
state.interruptAsserted = false;
// Clear illegal opcode trap.
state.opTrap = false;
@ -1161,6 +1165,20 @@ public class Cpu implements InstructionTable {
return state.getStatusFlag();
}
/**
* Simulate transition from logic-high to logic-low on the INT line.
*/
public void assertInterrupt() {
state.interruptAsserted = true;
}
/**
* Simulate transition from logic-low to logic-high of the INT line.
*/
public void clearInterrupt() {
state.interruptAsserted = false;
}
/**
* Push an item onto the stack, and decrement the stack counter.
* Will wrap-around if already at the bottom of the stack (This
@ -1305,6 +1323,8 @@ public class Cpu implements InstructionTable {
public int[] args = new int[2];
public int instSize;
public boolean opTrap;
/* True if the INT line was held low */
public boolean interruptAsserted;
/* Status Flag Register bits */
public boolean carryFlag;
@ -1341,6 +1361,7 @@ public class Cpu implements InstructionTable {
this.args[1] = s.args[1];
this.instSize = s.instSize;
this.opTrap = s.opTrap;
this.interruptAsserted = s.interruptAsserted;
this.carryFlag = s.carryFlag;
this.negativeFlag = s.negativeFlag;
this.zeroFlag = s.zeroFlag;
@ -1349,7 +1370,7 @@ public class Cpu implements InstructionTable {
this.breakFlag = s.breakFlag;
this.overflowFlag = s.overflowFlag;
this.stepCounter = s.stepCounter;
}
}
/**
* Returns a string formatted for the trace log.

View File

@ -10,113 +10,129 @@ import com.loomcom.symon.exceptions.*;
*/
public class BusTest extends TestCase {
public BusTest(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(BusTest.class);
}
public void testCreatingWithStartAndEndAddresses() {
Bus b = null;
b = new Bus(0x00, 0xff);
assertEquals(0x00, b.startAddress());
assertEquals(0xff, b.endAddress());
b = new Bus(0x20, 0xea);
assertEquals(0x20, b.startAddress());
assertEquals(0xea, b.endAddress());
}
public void testCreatingWithSize() {
Bus b = null;
b = new Bus(256);
assertEquals(0x00, b.startAddress());
assertEquals(0xff, b.endAddress());
b = new Bus(4096);
assertEquals(0x000, b.startAddress());
assertEquals(0xfff, b.endAddress());
b = new Bus(65536);
assertEquals(0x0000, b.startAddress());
assertEquals(0xffff, b.endAddress());
}
public void testAddDevice() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x00ff, true);
Device rom = new Memory(0x0100, 0x02ff, false);
Bus b = new Bus(0x0000, 0xffff);
assertEquals(0, b.getDevices().size());
b.addDevice(memory);
assertEquals(1, b.getDevices().size());
b.addDevice(rom);
assertEquals(2, b.getDevices().size());
}
public void testOverlappingDevicesShouldFail() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x0100, true);
Device rom = new Memory(0x00ff, 0x0200, false);
Bus b = new Bus(0x0000, 0xffff);
b.addDevice(memory);
try {
b.addDevice(rom);
fail("Should have thrown a MemoryRangeException.");
} catch (MemoryRangeException ex) {
// expected
public BusTest(String testName) {
super(testName);
}
}
public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException {
Device memory = new Memory(0x00ff, 0xff00, true);
public static Test suite() {
return new TestSuite(BusTest.class);
}
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
}
public void testCreatingWithStartAndEndAddresses() {
Bus b = null;
public void testIsCompleteWithOneDevice() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0xffff, true);
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertTrue("Address space should have been complete!", b.isComplete());
}
b = new Bus(0x00, 0xff);
assertEquals(0x00, b.startAddress());
assertEquals(0xff, b.endAddress());
public void testIsCompleteWithTwoDevices() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x7fff, true);
Device rom = new Memory(0x8000, 0xffff, false);
b = new Bus(0x20, 0xea);
assertEquals(0x20, b.startAddress());
assertEquals(0xea, b.endAddress());
}
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(rom);
assertTrue("Address space should have been complete!", b.isComplete());
}
public void testCreatingWithSize() {
Bus b = null;
public void testIsCompleteWithThreeDevices() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x7fff, true);
Device rom1 = new Memory(0x8000, 0xBfff, false);
Device rom2 = new Memory(0xC000, 0xffff, false);
b = new Bus(256);
assertEquals(0x00, b.startAddress());
assertEquals(0xff, b.endAddress());
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(rom1);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(rom2);
assertTrue("Address space should have been complete!", b.isComplete());
}
b = new Bus(4096);
assertEquals(0x000, b.startAddress());
assertEquals(0xfff, b.endAddress());
b = new Bus(65536);
assertEquals(0x0000, b.startAddress());
assertEquals(0xffff, b.endAddress());
}
public void testAddDevice() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x00ff, true);
Device rom = new Memory(0x0100, 0x02ff, false);
Bus b = new Bus(0x0000, 0xffff);
assertEquals(0, b.getDevices().size());
b.addDevice(memory);
assertEquals(1, b.getDevices().size());
b.addDevice(rom);
assertEquals(2, b.getDevices().size());
}
public void testOverlappingDevicesShouldFail() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x0100, true);
Device rom = new Memory(0x00ff, 0x0200, false);
Bus b = new Bus(0x0000, 0xffff);
b.addDevice(memory);
try {
b.addDevice(rom);
fail("Should have thrown a MemoryRangeException.");
} catch (MemoryRangeException ex) {
// expected
}
}
public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException {
Device memory = new Memory(0x00ff, 0xff00, true);
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
}
public void testIsCompleteWithOneDevice() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0xffff, true);
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertTrue("Address space should have been complete!", b.isComplete());
}
public void testIsCompleteWithTwoDevices() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x7fff, true);
Device rom = new Memory(0x8000, 0xffff, false);
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(rom);
assertTrue("Address space should have been complete!", b.isComplete());
}
public void testIsCompleteWithThreeDevices() throws MemoryRangeException {
Device memory = new Memory(0x0000, 0x7fff, true);
Device rom1 = new Memory(0x8000, 0xBfff, false);
Device rom2 = new Memory(0xC000, 0xffff, false);
Bus b = new Bus(0x0000, 0xffff);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(memory);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(rom1);
assertFalse("Address space was unexpectedly complete!", b.isComplete());
b.addDevice(rom2);
assertTrue("Address space should have been complete!", b.isComplete());
}
public void testSetAndClearInterrupt() throws Exception {
Bus b = new Bus(0x0000, 0xffff);
Cpu c = new Cpu();
b.addCpu(c);
assertFalse(c.getCpuState().interruptAsserted);
b.assertInterrupt();
assertTrue(c.getCpuState().interruptAsserted);
b.clearInterrupt();
assertFalse(c.getCpuState().interruptAsserted);
}
}