Moved IO unit memory map into the IO memory segments

This commit is contained in:
Niclas Finne 2012-05-25 20:14:44 +02:00
parent 231714ecdc
commit fcae849403
6 changed files with 170 additions and 285 deletions

View File

@ -72,36 +72,23 @@ public class MSP430f1611Config extends MSP430Config {
USART usart0 = new USART(cpu, 0, cpu.memory, 0x70);
USART usart1 = new USART(cpu, 1, cpu.memory, 0x78);
for (int i = 0, n = 8; i < n; i++) {
cpu.memOut[0x70 + i] = usart0;
cpu.memIn[0x70 + i] = usart0;
cpu.setIORange(0x70, 8, usart0);
cpu.setIORange(0x78, 8, usart1);
cpu.memOut[0x78 + i] = usart1;
cpu.memIn[0x78 + i] = usart1;
}
Multiplier mp = new Multiplier(cpu, cpu.memory, 0);
// Only cares of writes!
for (int i = 0x130, n = 0x13f; i < n; i++) {
cpu.memOut[i] = mp;
cpu.memIn[i] = mp;
}
cpu.setIORange(0x130, 0x0f, mp);
// Usarts
ioUnits.add(usart0);
ioUnits.add(usart1);
DMA dma = new DMA("dma", cpu, cpu.memory, 0);
for (int i = 0, n = 24; i < n; i++) {
cpu.memOut[0x1E0 + i] = dma;
cpu.memIn[0x1E0 + i] = dma;
}
cpu.setIORange(0x1e0, 24, dma);
/* DMA Ctl */
cpu.memOut[0x122] = dma;
cpu.memIn[0x124] = dma;
cpu.setIORange(0x122, 1, dma);
cpu.setIORange(0x124, 1, dma);
/* configure the DMA */
dma.setDMATrigger(DMA.URXIFG0, usart0, 0);
dma.setDMATrigger(DMA.UTXIFG0, usart0, 1);
@ -112,60 +99,23 @@ public class MSP430f1611Config extends MSP430Config {
ioUnits.add(dma);
// Add port 1,2 with interrupt capability!
IOPort io1;
IOPort io2;
ioUnits.add(io1 = new IOPort(cpu, 1, 4, cpu.memory, 0x20));
ioUnits.add(io2 = new IOPort(cpu, 2, 1, cpu.memory, 0x28));
for (int i = 0, n = 8; i < n; i++) {
cpu.memOut[0x20 + i] = io1;
cpu.memOut[0x28 + i] = io2;
cpu.memIn[0x20 + i] = io1;
cpu.memIn[0x28 + i] = io2;
}
// IOPorts will add themselves to the CPU
ioUnits.add(new IOPort(cpu, 1, 4, cpu.memory, 0x20));
ioUnits.add(new IOPort(cpu, 2, 1, cpu.memory, 0x28));
// Add port 3,4 & 5,6
for (int i = 0, n = 2; i < n; i++) {
IOPort p = new IOPort(cpu, (3 + i), 0, cpu.memory, 0x18 + i * 4);
ioUnits.add(p);
cpu.memOut[0x18 + i * 4] = p;
cpu.memOut[0x19 + i * 4] = p;
cpu.memOut[0x1a + i * 4] = p;
cpu.memOut[0x1b + i * 4] = p;
cpu.memIn[0x18 + i * 4] = p;
cpu.memIn[0x19 + i * 4] = p;
cpu.memIn[0x1a + i * 4] = p;
cpu.memIn[0x1b + i * 4] = p;
ioUnits.add(new IOPort(cpu, (3 + i), 0, cpu.memory, 0x18 + i * 4));
ioUnits.add(new IOPort(cpu, (5 + i), 0, cpu.memory, 0x30 + i * 4));
}
for (int i = 0, n = 2; i < n; i++) {
IOPort p = new IOPort(cpu, (5 + i), 0, cpu.memory, 0x30 + i * 4);
ioUnits.add(p);
cpu.memOut[0x30 + i * 4] = p;
cpu.memOut[0x31 + i * 4] = p;
cpu.memOut[0x32 + i * 4] = p;
cpu.memOut[0x33 + i * 4] = p;
cpu.memIn[0x30 + i * 4] = p;
cpu.memIn[0x31 + i * 4] = p;
cpu.memIn[0x32 + i * 4] = p;
cpu.memIn[0x33 + i * 4] = p;
}
ADC12 adc12 = new ADC12(cpu);
ioUnits.add(adc12);
cpu.setIORange(0x080, 16, adc12);
cpu.setIORange(0x140, 16, adc12);
cpu.setIORange(0x150, 16, adc12);
cpu.setIORange(0x1a0, 8, adc12);
for (int i = 0, n = 16; i < n; i++) {
cpu.memOut[0x80 + i] = adc12;
cpu.memIn[0x80 + i] = adc12;
cpu.memOut[0x140 + i] = adc12;
cpu.memIn[0x140 + i] = adc12;
cpu.memOut[0x150 + i] = adc12;
cpu.memIn[0x150 + i] = adc12;
}
for (int i = 0, n = 8; i < n; i++) {
cpu.memOut[0x1A0 + i] = adc12;
cpu.memIn[0x1A0 + i] = adc12;
}
return 3 + 6;
}
}

View File

@ -76,33 +76,22 @@ public class MSP430f2617Config extends MSP430Config {
public int setup(MSP430Core cpu, ArrayList<IOUnit> ioUnits) {
Multiplier mp = new Multiplier(cpu, cpu.memory, 0);
// Only cares of writes!
for (int i = 0x130, n = 0x13f; i < n; i++) {
cpu.memOut[i] = mp;
cpu.memIn[i] = mp;
}
cpu.setIORange(0x130, 0x0f, mp);
USCI usciA0 = new USCI(cpu, 0, cpu.memory, this);
USCI usciB0 = new USCI(cpu, 1, cpu.memory, this);
USCI usciA1 = new USCI(cpu, 2, cpu.memory, this);
USCI usciB1 = new USCI(cpu, 3, cpu.memory, this);
for (int i = 0, n = 8; i < n; i++) {
cpu.memOut[0x60 + i] = usciA0;
cpu.memIn[0x60 + i] = usciA0;
cpu.memOut[0x68 + i] = usciB0;
cpu.memIn[0x68 + i] = usciB0;
cpu.setIORange(0x60, 8, usciA0);
cpu.setIORange(0x68, 8, usciB0);
cpu.setIORange(0xd0, 8, usciA1);
cpu.setIORange(0xd8, 8, usciB1);
cpu.memOut[0xd0 + i] = usciA1;
cpu.memIn[0xd0 + i] = usciA1;
cpu.memOut[0xd8 + i] = usciB1;
cpu.memIn[0xd8 + i] = usciB1;
}
/* usciBx for i2c mode */
cpu.setIO(0x118, usciB0, true);
cpu.setIO(0x11a, usciB0, true);
cpu.setIO(0x17c, usciB1, true);
cpu.setIO(0x17e, usciB1, true);
cpu.setIORange(0x118, 2, usciB0);
cpu.setIORange(0x11a, 2, usciB0);
cpu.setIORange(0x17c, 2, usciB1);
cpu.setIORange(0x17e, 2, usciB1);
ioUnits.add(usciA0);
ioUnits.add(usciB0);
@ -110,66 +99,26 @@ public class MSP430f2617Config extends MSP430Config {
ioUnits.add(usciB1);
/* usciA1 handles interrupts for both usciA1 and B1 */
cpu.memOut[6] = usciA1;
cpu.memIn[6] = usciA1;
cpu.memOut[7] = usciA1;
cpu.memIn[7] = usciA1;
cpu.setIORange(0x06, 2, usciA1);
// Add port 1,2 with interrupt capability!
IOPort io1;
IOPort io2;
ioUnits.add(io1 = new IOPort(cpu, 1, 4, cpu.memory, 0x20));
ioUnits.add(io2 = new IOPort(cpu, 2, 1, cpu.memory, 0x28));
for (int i = 0, n = 8; i < n; i++) {
cpu.memOut[0x20 + i] = io1;
cpu.memOut[0x28 + i] = io2;
cpu.memIn[0x20 + i] = io1;
cpu.memIn[0x28 + i] = io2;
}
// IOPorts will add themselves to the CPU
ioUnits.add(new IOPort(cpu, 1, 4, cpu.memory, 0x20));
ioUnits.add(new IOPort(cpu, 2, 1, cpu.memory, 0x28));
// Add port 3,4 & 5,6
for (int i = 0, n = 2; i < n; i++) {
IOPort p = new IOPort(cpu, (3 + i), 0, cpu.memory, 0x18 + i * 4);
ioUnits.add(p);
cpu.memOut[0x18 + i * 4] = p;
cpu.memOut[0x19 + i * 4] = p;
cpu.memOut[0x1a + i * 4] = p;
cpu.memOut[0x1b + i * 4] = p;
cpu.memIn[0x18 + i * 4] = p;
cpu.memIn[0x19 + i * 4] = p;
cpu.memIn[0x1a + i * 4] = p;
cpu.memIn[0x1b + i * 4] = p;
ioUnits.add(new IOPort(cpu, (3 + i), 0, cpu.memory, 0x18 + i * 4));
ioUnits.add(new IOPort(cpu, (5 + i), 0, cpu.memory, 0x30 + i * 4));
}
for (int i = 0, n = 2; i < n; i++) {
IOPort p = new IOPort(cpu, (5 + i), 0, cpu.memory, 0x30 + i * 4);
ioUnits.add(p);
cpu.memOut[0x30 + i * 4] = p;
cpu.memOut[0x31 + i * 4] = p;
cpu.memOut[0x32 + i * 4] = p;
cpu.memOut[0x33 + i * 4] = p;
cpu.memIn[0x30 + i * 4] = p;
cpu.memIn[0x31 + i * 4] = p;
cpu.memIn[0x32 + i * 4] = p;
cpu.memIn[0x33 + i * 4] = p;
}
ADC12 adc12 = new ADC12(cpu);
ioUnits.add(adc12);
cpu.setIORange(0x080, 16, adc12);
cpu.setIORange(0x140, 16, adc12);
cpu.setIORange(0x150, 16, adc12);
cpu.setIORange(0x1a0, 8, adc12);
for (int i = 0, n = 16; i < n; i++) {
cpu.memOut[0x80 + i] = adc12;
cpu.memIn[0x80 + i] = adc12;
cpu.memOut[0x140 + i] = adc12;
cpu.memIn[0x140 + i] = adc12;
cpu.memOut[0x150 + i] = adc12;
cpu.memIn[0x150 + i] = adc12;
}
for (int i = 0, n = 8; i < n; i++) {
cpu.memOut[0x1A0 + i] = adc12;
cpu.memIn[0x1A0 + i] = adc12;
}
/* 4 usci units + 6 io port*/
return 4 + 6;
}

View File

@ -103,18 +103,13 @@ public class MSP430f5437Config extends MSP430Config {
public int setup(MSP430Core cpu, ArrayList<IOUnit> ioUnits) {
Multiplier32 mp = new Multiplier32(cpu, cpu.memory, 0x4c0);
for (int i = 0x4c0, n = 0x4c0 + 0x2e; i < n; i++) {
cpu.memOut[i] = mp;
cpu.memIn[i] = mp;
}
cpu.setIORange(0x4c0, 0x2e, mp);
/* this code should be slightly more generic... and be somewhere else... */
for (int i = 0, n = uartConfig.length; i < n; i++) {
GenericUSCI usci = new GenericUSCI(cpu, i, cpu.memory, this);
/* setup 0 - 1f as IO addresses */
for (int a = 0; a < 0x20; a++) {
cpu.setIO(a + uartConfig[i].offset, usci, false);
}
cpu.setIORange(uartConfig[i].offset, 0x20, usci);
// System.out.println("Adding IOUnit USCI: " + usci.getName());
ioUnits.add(usci);
}

View File

@ -84,7 +84,7 @@ public class IOPort extends IOUnit {
private static final PortReg[] PORTMAP_NO_INTERRUPT =
{PortReg.IN, PortReg.OUT, PortReg.DIR, PortReg.SEL};
private PortReg[] portMap;
private final PortReg[] portMap;
private PortListener portListener = null;
// represents the direction register
@ -111,33 +111,27 @@ public class IOPort extends IOUnit {
* Creates a new <code>IOPort</code> instance.
*
*/
public IOPort(MSP430Core cpu, int port,
int interrupt, int[] memory, int offset) {
super("P" + port, "Port " + port, cpu, memory, offset);
this.port = port;
this.interrupt = interrupt;
this.ie = 0;
this.ifg = 0;
if (interrupt == 0) {
portMap = PORTMAP_NO_INTERRUPT;
} else {
portMap = PORTMAP_INTERRUPT;
}
public IOPort(MSP430Core cpu, int port, int interrupt, int[] memory, int offset) {
this(cpu, port, interrupt, memory, offset,
interrupt == 0 ? PORTMAP_NO_INTERRUPT : PORTMAP_INTERRUPT);
}
/* Create an IOPort with a special PortMap */
public IOPort(MSP430Core cpu, int port,
int interrupt, int[] memory, int offset, PortReg[] portMap) {
this(cpu, port, interrupt, memory, offset);
super("P" + port, "Port " + port, cpu, memory, offset);
this.port = port;
this.interrupt = interrupt;
this.ie = 0;
this.ifg = 0;
this.portMap = portMap;
// System.out.println("Port " + port + " interrupt vector: " + interrupt);
/* register all the registers from the port-map */
for (int i = 0; i < portMap.length; i++) {
if (portMap[i] != null) {
// System.out.println(" P" + port + portMap[i] + " at " + Utils.hex16(offset + i));
cpu.setIO(offset + i, this, false);
cpu.setIORange(offset + i, 1, this);
}
}
}

View File

@ -1,20 +1,41 @@
package se.sics.mspsim.core;
import java.util.Arrays;
import se.sics.mspsim.util.Utils;
public class IOSegment implements Memory {
private final MSP430Core core;
private final IOUnit[] mem;
private final IOUnit voidIO;
IOSegment(MSP430Core core) {
IOSegment(MSP430Core core, int maxMemIO, IOUnit voidIO) {
this.core = core;
this.voidIO = voidIO;
this.mem = new IOUnit[maxMemIO];
Arrays.fill(mem, voidIO);
}
void setIORange(int address, int range, IOUnit io) {
System.out.println("IO: 0x" + Utils.hex(address, 4) + "-"
+ Utils.hex(address + range, 4) + ": " + io.id);
for (int i = 0; i < range; i++) {
if (mem[address + i] != voidIO) {
throw new IllegalStateException("IO unit already set: 0x"
+ Utils.hex(address + i, 4)
+ " (" + io.id + " => " + mem[address + i].id + ')');
}
mem[address + i] = io;
}
}
@Override
public int read(int address, AccessMode mode, AccessType type) throws EmulationException {
boolean word = mode != AccessMode.BYTE;
// Only word reads at 0x1fe which is highest address...
int val = core.memIn[address].read(address, word, core.cycles);
int val = mem[address].read(address, word, core.cycles);
if (mode == AccessMode.WORD20) {
val |= core.memIn[address + 2].read(address, word, core.cycles) << 16;
val |= mem[address + 2].read(address, word, core.cycles) << 16;
}
return val;
}
@ -24,9 +45,9 @@ public class IOSegment implements Memory {
boolean word = mode != AccessMode.BYTE;
if (!word) data &= 0xff;
core.memOut[dstAddress].write(dstAddress, data & 0xffff, word, core.cycles);
mem[dstAddress].write(dstAddress, data & 0xffff, word, core.cycles);
if (mode == AccessMode.WORD20) {
core.memOut[dstAddress].write(dstAddress + 2, data >> 16, word, core.cycles);
mem[dstAddress].write(dstAddress + 2, data >> 16, word, core.cycles);
}
}
@ -40,4 +61,20 @@ public class IOSegment implements Memory {
write(address, data, mode);
}
public String info() {
StringBuilder sb = new StringBuilder();
sb.append("IOSegment[0x0000-").append(Utils.hex(mem.length, 4)).append("]\n");
int start = 0;
for (int i = 1; i < mem.length; i++) {
if (mem[i] != mem[i - 1]) {
sb.append(" 0x").append(Utils.hex(start, 4))
.append("-").append(Utils.hex(i - 1, 4))
.append(": ").append(mem[i - 1].id).append(" (")
.append(mem[i - 1].name).append(")\n");
start = i;
}
}
return sb.toString();
}
}

View File

@ -70,6 +70,9 @@ public class MSP430Core extends Chip implements MSP430Constants {
boolean breakpointActive = true;
public final int memory[];
private final Flash flash;
boolean isFlashBusy;
boolean isStopping = false;
private final Memory memorySegments[];
Memory currentSegment;
@ -80,15 +83,10 @@ public class MSP430Core extends Chip implements MSP430Constants {
public final boolean MSP430XArch;
public final MSP430Config config;
// Most HW needs only notify write and clocking, others need also read...
// For notify write...
public final IOUnit[] memOut;
// For notify read... -> which will happen before actual read!
public final IOUnit[] memIn;
private ArrayList<IOUnit> ioUnits;
private SFR sfr;
private Watchdog watchdog;
private final ArrayList<IOUnit> ioUnits;
private final SFR sfr;
private final Watchdog watchdog;
private final ClockSystem bcs;
// From the possible interrupt sources - to be able to indicate is serviced.
// NOTE: 64 since more modern MSP430's have more than 16 vectors (5xxx has 64).
@ -129,43 +127,24 @@ public class MSP430Core extends Chip implements MSP430Constants {
private ArrayList<Chip> chips = new ArrayList<Chip>();
ComponentRegistry registry;
final ComponentRegistry registry;
Profiler profiler;
private Flash flash;
boolean isFlashBusy;
boolean isStopping = false;
ClockSystem bcs;
public void setIO(int adr, IOUnit io, boolean word) {
memOut[adr] = io;
memIn[adr] = io;
if (word) {
memOut[adr + 1] = io;
memIn[adr + 1] = io;
}
}
public void setIORange(int adr, int size, IOUnit io) {
for (int i = 0; i < size; i++) {
memOut[adr + i] = io;
memIn[adr + i] = io;
}
}
public MSP430Core(int type, ComponentRegistry registry, MSP430Config config) {
super("MSP430", "MSP430 Core", null);
MAX_INTERRUPT = config.maxInterruptVector;
MAX_MEM_IO = config.maxMemIO;
MAX_MEM = config.maxMem;
memOut = new IOUnit[MAX_MEM_IO];
memIn = new IOUnit[MAX_MEM_IO];
MSP430XArch = config.MSP430XArch;
memory = new int[MAX_MEM];
memorySegments = new Memory[MAX_MEM >> 8];
flash = new Flash(this, memory,
new FlashRange(config.mainFlashStart, config.mainFlashStart + config.mainFlashSize, 512, 64),
new FlashRange(config.infoMemStart, config.infoMemStart + config.infoMemSize, 128, 64),
config.flashControllerOffset);
currentSegment = new Memory() {
@Override
public int read(int address, AccessMode mode, AccessType type) throws EmulationException {
@ -197,10 +176,10 @@ public class MSP430Core extends Chip implements MSP430Constants {
}
};
System.out.println("Set up MSP430 Core with " + MAX_MEM + " bytes memory");
// System.out.println("Set up MSP430 Core with " + MAX_MEM + " bytes memory");
/* this is for detecting writes/read to/from non-existing IO */
IOUnit voidIO = new IOUnit(id, cpu, memory, 0) {
IOUnit voidIO = new IOUnit("void", cpu, memory, 0) {
public void interruptServiced(int vector) {
}
public void write(int address, int value, boolean word, long cycles) {
@ -212,89 +191,11 @@ public class MSP430Core extends Chip implements MSP430Constants {
}
};
/* fill with void IO */
for (int i = 0; i < MAX_MEM_IO; i++) {
memOut[i] = voidIO;
memIn[i] = voidIO;
}
this.registry = registry;
this.config = config;
// The CPU need to register itself as chip
addChip(this);
// Ignore type for now...
setModeNames(MODE_NAMES);
// IOUnits should likely be placed in a hashtable?
// Maybe for debugging purposes...
ioUnits = new ArrayList<IOUnit>();
flash = new Flash(this, memory,
new FlashRange(config.mainFlashStart, config.mainFlashStart + config.mainFlashSize, 512, 64),
new FlashRange(config.infoMemStart, config.infoMemStart + config.infoMemSize, 128, 64),
config.flashControllerOffset);
for (int i = 0; i < 8; i++) {
memOut[i + config.flashControllerOffset] = flash;
memIn[i + config.flashControllerOffset] = flash;
}
/* Setup special function registers */
sfr = new SFR(this, memory);
for (int i = 0, n = 0x10; i < n; i++) {
memOut[i + config.sfrOffset] = sfr;
memIn[i + config.sfrOffset] = sfr;
}
// first step towards making core configurable
Timer[] timers = new Timer[config.timerConfig.length];
for (int i = 0; i < config.timerConfig.length; i++) {
Timer t = new Timer(this, memory, config.timerConfig[i]);
for (int a = 0, n = 0x20; a < n; a++) {
memOut[config.timerConfig[i].offset + a] = t;
memIn[config.timerConfig[i].offset + a] = t;
}
memIn[config.timerConfig[i].timerIVAddr] = t;
memOut[config.timerConfig[i].timerIVAddr] = t;
timers[i] = t;
}
// XXX this should be handled by the config, but we do it here to
// avoid changing too much of the mspsim architecture for now
if (MSP430XArch) {
bcs = new UnifiedClockSystem(this, memory, 0, timers);
} else {
bcs = new BasicClockModule(this, memory, 0, timers);
}
for (int i = bcs.getAddressRangeMin(), n = bcs.getAddressRangeMax();
i <= n; i++) {
memOut[i] = bcs;
memIn[i] = bcs;
}
// SFR and Basic clock system.
ioUnits.add(sfr);
ioUnits.add(bcs);
config.setup(this, ioUnits);
/* timers after ports ? */
for (int i = 0; i < timers.length; i++) {
ioUnits.add(timers[i]);
}
watchdog = new Watchdog(this);
memOut[config.watchdogOffset] = watchdog;
memIn[config.watchdogOffset] = watchdog;
ioUnits.add(watchdog);
/* setup memory segments */
int maxSeg = MAX_MEM >> 8;
Memory ramSegment = new RAMSegment(this);
Memory flashSegment = new FlashSegment(this, flash);
Memory ioSegment = new IOSegment(this);
IOSegment ioSegment = new IOSegment(this, MAX_MEM_IO, voidIO);
Memory noMemorySegment = new NoMemSegment(this);
for (int i = 0; i < maxSeg; i++) {
if (config.isRAM(i << 8)) {
@ -312,9 +213,68 @@ public class MSP430Core extends Chip implements MSP430Constants {
}
}
this.registry = registry;
this.config = config;
// The CPU need to register itself as chip
addChip(this);
// Ignore type for now...
setModeNames(MODE_NAMES);
// IOUnits should likely be placed in a hashtable?
// Maybe for debugging purposes...
ioUnits = new ArrayList<IOUnit>();
ioSegment.setIORange(config.flashControllerOffset, 6, flash);
/* Setup special function registers */
sfr = new SFR(this, memory);
ioSegment.setIORange(config.sfrOffset, 0x10, sfr);
// first step towards making core configurable
Timer[] timers = new Timer[config.timerConfig.length];
for (int i = 0; i < config.timerConfig.length; i++) {
Timer t = new Timer(this, memory, config.timerConfig[i]);
ioSegment.setIORange(config.timerConfig[i].offset, 0x20, t);
ioSegment.setIORange(config.timerConfig[i].timerIVAddr, 1, t);
timers[i] = t;
}
// XXX this should be handled by the config, but we do it here to
// avoid changing too much of the mspsim architecture for now
if (MSP430XArch) {
bcs = new UnifiedClockSystem(this, memory, 0, timers);
} else {
bcs = new BasicClockModule(this, memory, 0, timers);
}
ioSegment.setIORange(bcs.getAddressRangeMin(), bcs.getAddressRangeMax() - bcs.getAddressRangeMin() + 1, bcs);
// SFR and Basic clock system.
ioUnits.add(sfr);
ioUnits.add(bcs);
config.setup(this, ioUnits);
/* timers after ports ? */
for (int i = 0; i < timers.length; i++) {
ioUnits.add(timers[i]);
}
watchdog = new Watchdog(this);
ioSegment.setIORange(config.watchdogOffset, 1, watchdog);
ioUnits.add(watchdog);
bcs.reset(0);
}
public void setIORange(int address, int range, IOUnit io) {
if (address + range > MAX_MEM_IO) {
throw new IllegalStateException("Outside IO memory: 0x" + Utils.hex(address, 4));
}
IOSegment ioSegment = (IOSegment) memorySegments[address >> 8];
ioSegment.setIORange(address, range, io);
}
public Profiler getProfiler() {
return profiler;
}