1
0
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:
Seth J. Morabito 2008-12-11 16:38:39 -08:00
parent 6f678af3df
commit a54dbc323d
10 changed files with 222 additions and 59 deletions

View File

@ -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);
}
}

View File

@ -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);
}

View 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());
}
}
}

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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 {