mirror of
https://github.com/sethm/symon.git
synced 2024-06-03 07:29:30 +00:00
Profiling. Made a new directory for exceptions.
This commit is contained in:
parent
6f678af3df
commit
a54dbc323d
|
@ -2,33 +2,35 @@ package com.loomcom.lm6502;
|
|||
|
||||
import java.util.*;
|
||||
import com.loomcom.lm6502.devices.*;
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
public class Bus {
|
||||
|
||||
private int bottom = 0x0000;
|
||||
private int top = 0xffff;
|
||||
/* By default, our bus starts at 0, and goes up to 64K */
|
||||
private int startAddress = 0x0000;
|
||||
private int endAddress = 0xffff;
|
||||
|
||||
/**
|
||||
* Ordered list of IO devices.
|
||||
*/
|
||||
private List<Device> devices;
|
||||
private SortedSet<Device> devices;
|
||||
|
||||
public Bus(int size) {
|
||||
this(0, size - 1);
|
||||
}
|
||||
|
||||
public Bus(int bottom, int top) {
|
||||
this.devices = new ArrayList(8);
|
||||
this.bottom = bottom;
|
||||
this.top = top;
|
||||
public Bus(int startAddress, int endAddress) {
|
||||
this.devices = new TreeSet();
|
||||
this.startAddress = startAddress;
|
||||
this.endAddress = endAddress;
|
||||
}
|
||||
|
||||
public int bottom() {
|
||||
return bottom;
|
||||
public int startAddress() {
|
||||
return startAddress;
|
||||
}
|
||||
|
||||
public int top() {
|
||||
return top;
|
||||
public int endAddress() {
|
||||
return endAddress;
|
||||
}
|
||||
|
||||
public void addDevice(Device device)
|
||||
|
@ -62,21 +64,21 @@ public class Bus {
|
|||
for (Device d : devices) {
|
||||
MemoryRange cur = d.getMemoryRange();
|
||||
if (i == 0) {
|
||||
// If the first entry doesn't start at 'bottom', return false.
|
||||
if (cur.getStartAddress() != bottom) { return false; }
|
||||
// If the first entry doesn't start at 'startAddress', return false.
|
||||
if (cur.startAddress() != startAddress) { return false; }
|
||||
}
|
||||
|
||||
if (prev != null && i < length - 1) {
|
||||
// Otherwise, compare previous map's end against this map's
|
||||
// top. They must be adjacent!
|
||||
if (cur.getStartAddress() - 1 != prev.getEndAddress()) {
|
||||
// endAddress. They must be adjacent!
|
||||
if (cur.startAddress() - 1 != prev.endAddress()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == length - 1) {
|
||||
// If the last entry doesn't end at top, return false;
|
||||
if (cur.getEndAddress() != top) { return false; }
|
||||
// If the last entry doesn't end at endAddress, return false;
|
||||
if (cur.endAddress() != endAddress) { return false; }
|
||||
}
|
||||
|
||||
i++;
|
||||
|
@ -87,8 +89,35 @@ public class Bus {
|
|||
return true;
|
||||
}
|
||||
|
||||
public List getDevices() {
|
||||
public int read(int address) {
|
||||
for (Device d : devices) {
|
||||
MemoryRange range = d.getMemoryRange();
|
||||
if (range.includes(address)) {
|
||||
// Compute offset into this device's address space.
|
||||
int devAddr = address - range.startAddress();
|
||||
return d.read(devAddr);
|
||||
}
|
||||
}
|
||||
// TODO: Raise access error.
|
||||
throw new RuntimeException("Read failed! Device not found.");
|
||||
}
|
||||
|
||||
public void write(int address, int value) {
|
||||
for (Device d : devices) {
|
||||
MemoryRange range = d.getMemoryRange();
|
||||
if (range.includes(address)) {
|
||||
// Compute offset into this device's address space.
|
||||
int devAddr = address - range.startAddress();
|
||||
d.write(devAddr, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// TODO: Raise access error.
|
||||
throw new RuntimeException("Write failed! Device not found.");
|
||||
}
|
||||
|
||||
public SortedSet getDevices() {
|
||||
// Expose a copy of the device list, not the original
|
||||
return new ArrayList(devices);
|
||||
return new TreeSet(devices);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
package com.loomcom.lm6502;
|
||||
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
/**
|
||||
* MemoryRange is a simple container class representing a literal
|
||||
* range of memory, with a staraddress, and an end address. It has
|
||||
* guards against creating impossible memory ranges, and implements
|
||||
* some useful methods for checking address inclusion and range
|
||||
* overlaps.
|
||||
*/
|
||||
public class MemoryRange implements Comparable<MemoryRange> {
|
||||
|
||||
/** The starting address of the memory range. */
|
||||
public int startAddress;
|
||||
/** The ending address of the memory range. */
|
||||
public int endAddress;
|
||||
|
||||
public MemoryRange(int startAddress, int endAddress)
|
||||
|
@ -17,11 +29,17 @@ public class MemoryRange implements Comparable<MemoryRange> {
|
|||
this.endAddress = endAddress;
|
||||
}
|
||||
|
||||
public int getStartAddress() {
|
||||
/**
|
||||
* @returns the starting address.
|
||||
*/
|
||||
public int startAddress() {
|
||||
return startAddress;
|
||||
}
|
||||
|
||||
public int getEndAddress() {
|
||||
/**
|
||||
* @returns the ending address.
|
||||
*/
|
||||
public int endAddress() {
|
||||
return endAddress;
|
||||
}
|
||||
|
||||
|
@ -42,8 +60,8 @@ public class MemoryRange implements Comparable<MemoryRange> {
|
|||
* @returns true if this range overlaps in any way with the other.
|
||||
*/
|
||||
public boolean overlaps(MemoryRange other) {
|
||||
return (this.includes(other.getStartAddress()) ||
|
||||
other.includes(this.getStartAddress()));
|
||||
return (this.includes(other.startAddress()) ||
|
||||
other.includes(this.startAddress()));
|
||||
}
|
||||
|
||||
// Implementation of Comparable interface
|
||||
|
@ -54,8 +72,8 @@ public class MemoryRange implements Comparable<MemoryRange> {
|
|||
if (this == other) {
|
||||
return 0;
|
||||
}
|
||||
Integer thisStartAddr = new Integer(this.getStartAddress());
|
||||
Integer thatStartAddr = new Integer(other.getStartAddress());
|
||||
Integer thisStartAddr = new Integer(this.startAddress());
|
||||
Integer thatStartAddr = new Integer(other.startAddress());
|
||||
return thisStartAddr.compareTo(thatStartAddr);
|
||||
}
|
||||
|
||||
|
|
66
src/main/java/com/loomcom/lm6502/Profiler.java
Normal file
66
src/main/java/com/loomcom/lm6502/Profiler.java
Normal file
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* A simple profiler, for debugging the simulator.
|
||||
* It is safe to ignore me.
|
||||
*/
|
||||
|
||||
package com.loomcom.lm6502;
|
||||
|
||||
import java.util.*;
|
||||
import com.loomcom.lm6502.devices.*;
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
public class Profiler {
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
// Create a bus.
|
||||
Bus b = new Bus(0, 65535);
|
||||
|
||||
// Create eight devices, each 8KB, to fill the bus.
|
||||
b.addDevice(new Memory(0x0000, 0x2000, null)); // 8KB @ $0000-$1fff
|
||||
b.addDevice(new Memory(0x2000, 0x2000, null)); // 8KB @ $2000-$3fff
|
||||
b.addDevice(new Memory(0x4000, 0x2000, null)); // 8KB @ $4000-$5fff
|
||||
b.addDevice(new Memory(0x6000, 0x2000, null)); // 8KB @ $6000-$7fff
|
||||
b.addDevice(new Memory(0x8000, 0x2000, null)); // 8KB @ $8000-$9fff
|
||||
b.addDevice(new Memory(0xa000, 0x2000, null)); // 8KB @ $a000-$bfff
|
||||
b.addDevice(new Memory(0xc000, 0x2000, null)); // 8KB @ $c000-$dfff
|
||||
b.addDevice(new Memory(0xe000, 0x2000, null)); // 8KB @ $e000-$ffff
|
||||
|
||||
// Read memory
|
||||
long sum = 0;
|
||||
long average = 0;
|
||||
|
||||
long iters = 500;
|
||||
|
||||
for (int i = 0; i < iters; i++) {
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
|
||||
// Read and assign to a buffer
|
||||
int buf = 0;
|
||||
for (int j = 0; j < 0xffff; j++) {
|
||||
buf = b.read(j);
|
||||
if (buf != 0xff) {
|
||||
System.out.println("WARNING! MEMORY SHOULD HAVE BEEN $FF, WAS: " + buf);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
long endTime = System.nanoTime();
|
||||
long diff = endTime - startTime;
|
||||
|
||||
// System.out.println("Read of 64KB took: " + diff + " ns (" + (diff / 1000) + " us)");
|
||||
|
||||
sum += diff;
|
||||
average = sum / (i + 1);
|
||||
}
|
||||
|
||||
System.out.println("Average time to read 64KB: " + average + " ns (" + (average / 1000) + " us)");
|
||||
System.out.println("Average time to read one byte: " + sum / (64 * 1024 * iters) + " ns");
|
||||
|
||||
} catch (MemoryRangeException ex) {
|
||||
System.out.println("Memory Access Exception! " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,30 +10,26 @@ public class Simulator {
|
|||
/**
|
||||
* Command-line parser used by this simulator.
|
||||
*/
|
||||
CommandParser m_parser;
|
||||
CommandParser parser;
|
||||
|
||||
/**
|
||||
* The CPU itself.
|
||||
*/
|
||||
Cpu m_cpu;
|
||||
Cpu cpu;
|
||||
|
||||
/**
|
||||
* The Bus responsible for routing memory read/write requests to the
|
||||
* correct IO devices.
|
||||
*/
|
||||
Bus m_bus;
|
||||
Bus bus;
|
||||
|
||||
public Simulator() {
|
||||
m_cpu = new Cpu(this);
|
||||
m_parser = new CommandParser(System.in, System.out, this);
|
||||
cpu = new Cpu(this);
|
||||
parser = new CommandParser(System.in, System.out, this);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
m_parser.run();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Simulator().run();
|
||||
parser.run();
|
||||
}
|
||||
|
||||
public void step() {
|
||||
|
@ -45,4 +41,12 @@ public class Simulator {
|
|||
|
||||
public void write(int address, int value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main simulator routine.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
new Simulator().run();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package com.loomcom.lm6502.devices;
|
||||
|
||||
import com.loomcom.lm6502.*;
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
/**
|
||||
* A memory-mapped IO Device.
|
||||
*/
|
||||
|
||||
public abstract class Device {
|
||||
public abstract class Device implements Comparable<Device> {
|
||||
|
||||
/** The memory range for this device. */
|
||||
private MemoryRange memoryRange;
|
||||
|
@ -23,20 +24,21 @@ public abstract class Device {
|
|||
this.cpu = cpu;
|
||||
}
|
||||
|
||||
/* Methods required to be implemented by inheriting classes. */
|
||||
public abstract void write(int address, int data);
|
||||
|
||||
public abstract int read(int address);
|
||||
public abstract String toString();
|
||||
|
||||
public MemoryRange getMemoryRange() {
|
||||
return memoryRange;
|
||||
}
|
||||
|
||||
public int getEndAddress() {
|
||||
return memoryRange.getEndAddress();
|
||||
public int endAddress() {
|
||||
return memoryRange.endAddress();
|
||||
}
|
||||
|
||||
public int getStartAddress() {
|
||||
return memoryRange.getStartAddress();
|
||||
public int startAddress() {
|
||||
return memoryRange.startAddress();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -47,4 +49,17 @@ public abstract class Device {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two devices. The sort order is defined by the sort
|
||||
* order of the device's memory ranges.
|
||||
*/
|
||||
public int compareTo(Device other) {
|
||||
if (other == null) {
|
||||
throw new NullPointerException("Cannot compare to null.");
|
||||
}
|
||||
if (this == other) {
|
||||
return 0;
|
||||
}
|
||||
return getMemoryRange().compareTo(other.getMemoryRange());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
package com.loomcom.lm6502.devices;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.loomcom.lm6502.*;
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
public class Memory extends Device {
|
||||
|
||||
private boolean readOnly;
|
||||
|
||||
private int[] mem;
|
||||
|
||||
public Memory(int address, int size, Cpu cpu, boolean readOnly)
|
||||
throws MemoryRangeException {
|
||||
super(address, size, "RW Memory", cpu);
|
||||
|
||||
this.readOnly = readOnly;
|
||||
this.mem = new int[size];
|
||||
|
||||
// Init the mem to all 0xff
|
||||
Arrays.fill(this.mem, 0xff);
|
||||
}
|
||||
|
||||
public Memory(int address, int size, Cpu cpu)
|
||||
|
@ -18,10 +28,17 @@ public class Memory extends Device {
|
|||
}
|
||||
|
||||
public void write(int address, int data) {
|
||||
System.out.println(String.format("[write] Before write: $%04x=$%04x", address, this.mem[address]));
|
||||
this.mem[address] = data;
|
||||
System.out.println(String.format("[write] After write: $%04x=$%04x", address, this.mem[address]));
|
||||
}
|
||||
|
||||
public int read(int address) {
|
||||
return 0;
|
||||
return this.mem[address];
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Memory: " + getMemoryRange().toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.loomcom.lm6502.exceptions;
|
||||
|
||||
/**
|
||||
* Exception that will be thrown if access to memory or IO cannot be
|
||||
* accessed.
|
||||
*/
|
||||
public class MemoryAccessException extends Exception {
|
||||
public MemoryAccessException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.loomcom.lm6502;
|
||||
package com.loomcom.lm6502.exceptions;
|
||||
|
||||
/**
|
||||
* Exception that will be thrown if devices conflict in the IO map.
|
|
@ -3,6 +3,7 @@ package com.loomcom.lm6502;
|
|||
import junit.framework.*;
|
||||
|
||||
import com.loomcom.lm6502.devices.*;
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -19,32 +20,32 @@ public class BusTest extends TestCase {
|
|||
return new TestSuite(BusTest.class);
|
||||
}
|
||||
|
||||
public void testCreatingWithTopAndBottom() {
|
||||
public void testCreatingWithStartAndEndAddresses() {
|
||||
Bus b = null;
|
||||
|
||||
b = new Bus(0x00, 0xff);
|
||||
assertEquals(0x00, b.bottom());
|
||||
assertEquals(0xff, b.top());
|
||||
assertEquals(0x00, b.startAddress());
|
||||
assertEquals(0xff, b.endAddress());
|
||||
|
||||
b = new Bus(0x20, 0xea);
|
||||
assertEquals(0x20, b.bottom());
|
||||
assertEquals(0xea, b.top());
|
||||
assertEquals(0x20, b.startAddress());
|
||||
assertEquals(0xea, b.endAddress());
|
||||
}
|
||||
|
||||
public void testCreatingWithSize() {
|
||||
Bus b = null;
|
||||
|
||||
b = new Bus(256);
|
||||
assertEquals(0x00, b.bottom());
|
||||
assertEquals(0xff, b.top());
|
||||
assertEquals(0x00, b.startAddress());
|
||||
assertEquals(0xff, b.endAddress());
|
||||
|
||||
b = new Bus(4096);
|
||||
assertEquals(0x000, b.bottom());
|
||||
assertEquals(0xfff, b.top());
|
||||
assertEquals(0x000, b.startAddress());
|
||||
assertEquals(0xfff, b.endAddress());
|
||||
|
||||
b = new Bus(65536);
|
||||
assertEquals(0x0000, b.bottom());
|
||||
assertEquals(0xffff, b.top());
|
||||
assertEquals(0x0000, b.startAddress());
|
||||
assertEquals(0xffff, b.endAddress());
|
||||
}
|
||||
|
||||
public void testAddDevice() throws MemoryRangeException {
|
||||
|
@ -76,7 +77,7 @@ public class BusTest extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testIsCompleteWithFirstDeviceNotStartingAtBottom() throws MemoryRangeException {
|
||||
public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException {
|
||||
Device memory = new Memory(0x00ff, 0xff00, null, true);
|
||||
|
||||
Bus b = new Bus(0x0000, 0xffff);
|
||||
|
|
|
@ -5,6 +5,8 @@ import junit.framework.*;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.loomcom.lm6502.exceptions.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -36,14 +38,14 @@ public class MemoryRangeTest extends TestCase {
|
|||
new MemoryRange(2, 10);
|
||||
}
|
||||
|
||||
public void testGetStartAddress() throws MemoryRangeException {
|
||||
public void testStartAddress() throws MemoryRangeException {
|
||||
MemoryRange r = new MemoryRange(0x101, 0x202);
|
||||
assertEquals(0x101, r.getStartAddress());
|
||||
assertEquals(0x101, r.startAddress());
|
||||
}
|
||||
|
||||
public void testGetEndAddress() throws MemoryRangeException {
|
||||
public void testEndAddress() throws MemoryRangeException {
|
||||
MemoryRange r = new MemoryRange(0x101, 0x202);
|
||||
assertEquals(0x202, r.getEndAddress());
|
||||
assertEquals(0x202, r.endAddress());
|
||||
}
|
||||
|
||||
public void testOverlaps() throws MemoryRangeException {
|
||||
|
|
Loading…
Reference in New Issue
Block a user