From 0f1d0ff978fb464db07e5871cacabd1ca53002e0 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 29 May 2012 11:41:33 +0200 Subject: [PATCH] Improved support for emulation of msp430f2xxx series --- se/sics/mspsim/config/MSP430f2617Config.java | 27 +++-- se/sics/mspsim/config/MSP430f5437Config.java | 15 ++- se/sics/mspsim/core/IOPort.java | 121 +++++++++++-------- se/sics/mspsim/core/MSP430Config.java | 3 + se/sics/mspsim/core/MSP430Core.java | 8 +- se/sics/mspsim/core/Multiplier32.java | 4 +- 6 files changed, 105 insertions(+), 73 deletions(-) diff --git a/se/sics/mspsim/config/MSP430f2617Config.java b/se/sics/mspsim/config/MSP430f2617Config.java index bbf1fc3..5d4670c 100644 --- a/se/sics/mspsim/config/MSP430f2617Config.java +++ b/se/sics/mspsim/config/MSP430f2617Config.java @@ -49,7 +49,17 @@ import se.sics.mspsim.util.Utils; public class MSP430f2617Config extends MSP430Config { - + private static final String portConfig[] = { + "P1=0,IN 20,OUT 21,DIR 22,IFG 23,IES 24,IE 25,SEL 26,SEL2 41,REN 27", + "P2=0,IN 28,OUT 29,DIR 2A,IFG 2B,IES 2C,IE 2D,SEL 2E,SEL2 42,REN 2F", + "P3=0,IN 18,OUT 19,DIR 1A,SEL 1B,SEL2 43,REN 10", + "P4=0,IN 1C,OUT 1D,DIR 1E,SEL 1F,SEL2 44,REN 11", + "P5=0,IN 30,OUT 31,DIR 32,SEL 33,SEL2 45,REN 12", + "P6=0,IN 34,OUT 35,DIR 36,SEL 37,SEL2 46,REN 13", + "P7=0,IN 38,OUT 3A,DIR 3C,SEL 3E,SEL2 47,REN 14", + "P8=0,IN 39,OUT 3B,DIR 3D,SEL 3F,SEL2 48,REN 15" + }; + public MSP430f2617Config() { /* 32 vectors for the MSP430X series */ maxInterruptVector = 31; @@ -62,9 +72,9 @@ public class MSP430f2617Config extends MSP430Config { /* TX Vec, RX Vec, TX Bit, RX Bit, SFR-reg, Offset, Name, A?*/ UARTConfig uA0 = new UARTConfig(22, 23, 1, 0, 1, 0x60, "USCI A0", true); - UARTConfig uB0 = new UARTConfig(22, 23, 3, 2, 1, 0x60, "USCI B0", false); + UARTConfig uB0 = new UARTConfig(22, 23, 3, 2, 1, 0x68, "USCI B0", false); UARTConfig uA1 = new UARTConfig(16, 17, 1, 0, 6, 0xD0, "USCI A1", true); - UARTConfig uB1 = new UARTConfig(16, 17, 3, 2, 6, 0xD0, "USCI B1", false); + UARTConfig uB1 = new UARTConfig(16, 17, 3, 2, 6, 0xD8, "USCI B1", false); uartConfig = new UARTConfig[] {uA0, uB0, uA1, uB1}; /* configure memory */ @@ -103,13 +113,12 @@ public class MSP430f2617Config extends MSP430Config { // Add port 1,2 with interrupt capability! // 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)); + IOPort last = null; + ioUnits.add(last = IOPort.parseIOPort(cpu, 18, portConfig[0], last)); + ioUnits.add(last = IOPort.parseIOPort(cpu, 19, portConfig[1], last)); - // Add port 3,4 & 5,6 - for (int i = 0, n = 2; i < n; i++) { - 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 = 2; i < portConfig.length; i++) { + ioUnits.add(last = IOPort.parseIOPort(cpu, 0, portConfig[i], last)); } ADC12 adc12 = new ADC12(cpu); diff --git a/se/sics/mspsim/config/MSP430f5437Config.java b/se/sics/mspsim/config/MSP430f5437Config.java index 4b849b6..15570ee 100644 --- a/se/sics/mspsim/config/MSP430f5437Config.java +++ b/se/sics/mspsim/config/MSP430f5437Config.java @@ -36,6 +36,7 @@ package se.sics.mspsim.config; import java.util.ArrayList; +import se.sics.mspsim.core.ClockSystem; import se.sics.mspsim.core.GenericUSCI; import se.sics.mspsim.core.IOPort; import se.sics.mspsim.core.IOUnit; @@ -43,6 +44,7 @@ import se.sics.mspsim.core.MSP430Config; import se.sics.mspsim.core.MSP430Core; import se.sics.mspsim.core.Multiplier32; import se.sics.mspsim.core.Timer; +import se.sics.mspsim.core.UnifiedClockSystem; import se.sics.mspsim.util.Utils; public class MSP430f5437Config extends MSP430Config { @@ -113,12 +115,12 @@ public class MSP430f5437Config extends MSP430Config { // System.out.println("Adding IOUnit USCI: " + usci.getName()); ioUnits.add(usci); } - - ioUnits.add(IOPort.parseIOPort(cpu, 47, portConfig[0])); - ioUnits.add(IOPort.parseIOPort(cpu, 42, portConfig[1])); + IOPort last = null; + ioUnits.add(last = IOPort.parseIOPort(cpu, 47, portConfig[0], last)); + ioUnits.add(last = IOPort.parseIOPort(cpu, 42, portConfig[1], last)); for (int i = 2; i < portConfig.length; i++) { - ioUnits.add(IOPort.parseIOPort(cpu, 0, portConfig[i])); + ioUnits.add(last = IOPort.parseIOPort(cpu, 0, portConfig[i], last)); } return portConfig.length + uartConfig.length; @@ -129,4 +131,9 @@ public class MSP430f5437Config extends MSP430Config { return Utils.hex20(addr); } + @Override + public ClockSystem createClockSystem(MSP430Core cpu, int[] memory, Timer[] timers) { + return new UnifiedClockSystem(cpu, memory, 0, timers); + } + } diff --git a/se/sics/mspsim/core/IOPort.java b/se/sics/mspsim/core/IOPort.java index f5331e1..7db6a7b 100644 --- a/se/sics/mspsim/core/IOPort.java +++ b/se/sics/mspsim/core/IOPort.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2007-2012, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,47 +36,14 @@ */ package se.sics.mspsim.core; +import java.util.Arrays; import se.sics.mspsim.util.Utils; public class IOPort extends IOUnit { public enum PinState { LOW, HI }; - private final int port; - private final int interrupt; - - // External pin state! - private PinState pinState[] = new PinState[8]; - - /* NOTE: The offset needs to be configurable since the new IOPorts on - * the 5xxx series are located at other addresses. - * Maybe create another IOPort that just convert IOAddress to this 'old' mode? - * - will be slightly slower on IOWrite/read but very easy to implement. - * - * - * - * - * - * - */ - - enum PortReg {IN, OUT, DIR, SEL, IFG, IES, IE, REN, DS, IV_L, IV_H}; - - public static final int IN = 0; - public static final int OUT = 1; - public static final int DIR = 2; - public static final int SEL = 4; /* what about SEL2? */ - public static final int IFG = 5; - public static final int IES = 6; - public static final int IE = 7; - public static final int REN = 8; - public static final int DS = 9; - public static final int IV_L = 10; - public static final int IV_H = 11; - - private static final String[] names = { - "IN", "OUT", "DIR", "SEL", "IFG", "IES", "IE", "REN", "DS" }; - + public enum PortReg {IN, OUT, DIR, SEL, SEL2, IFG, IES, IE, REN, DS, IV_L, IV_H}; /* portmaps for 1611 */ private static final PortReg[] PORTMAP_INTERRUPT = @@ -84,10 +51,15 @@ public class IOPort extends IOUnit { private static final PortReg[] PORTMAP_NO_INTERRUPT = {PortReg.IN, PortReg.OUT, PortReg.DIR, PortReg.SEL}; + private final int port; + private final int interrupt; + + // External pin state! + private final PinState pinState[] = new PinState[8]; + private final PortReg[] portMap; private PortListener portListener = null; - // represents the direction register /* Registers for Digital I/O */ @@ -95,11 +67,12 @@ public class IOPort extends IOUnit { private int out; private int dir; private int sel; + private int sel2; private int ie; private int ifg; private int ies; /* edge select */ private int ren; -// private int ds; + private int ds; private int iv; /* low / high */ @@ -136,7 +109,7 @@ public class IOPort extends IOUnit { } } - public static IOPort parseIOPort(MSP430Core cpu, int interrupt, String specification) { + public static IOPort parseIOPort(MSP430Core cpu, int interrupt, String specification, IOPort last) { /* Specification = Px=Offset,REG Off, ... */ String[] specs = specification.split(","); int port = specs[0].charAt(1) - '0'; @@ -148,10 +121,17 @@ public class IOPort extends IOUnit { String[] preg = specs[i].split(" "); PortReg pr = PortReg.valueOf(preg[0]); int offs = Integer.parseInt(preg[1], 16); + if (offs >= portMap.length) { + portMap = Arrays.copyOf(portMap, offs + 1); + } portMap[offs] = pr; } - - return new IOPort(cpu, port, interrupt, cpu.memory, offset, portMap); + IOPort newPort = new IOPort(cpu, port, interrupt, cpu.memory, offset, portMap); + if (last != null && offset == last.offset && offset > 0) { + // This port is a pair with previous port to allow 16 bits writes + last.ioPair = newPort; + } + return newPort; } public int getPort() { @@ -202,7 +182,37 @@ public class IOPort extends IOUnit { } //System.out.println("*** Setting IV to: " + iv + " ifg: " + ifg); } - + + public int getRegister(PortReg register) { + switch(register) { + case DIR: + return dir; + case IE: + return ie; + case IES: + return ies; + case IFG: + return ifg; + case IN: + return in; + case IV_H: + return (iv >> 8) & 0xff; + case IV_L: + return iv & 0xff; + case OUT: + return out; + case REN: + return ren; + case DS: + return ds; + case SEL: + return sel; + case SEL2: + return sel2; + } + return 0; + } + /* only byte access!!! */ int read_port(PortReg function, long cycles) { switch(function) { @@ -222,6 +232,10 @@ public class IOPort extends IOUnit { return ies; case SEL: return sel; + case SEL2: + return sel2; + case DS: + return ds; case IV_L: return iv & 0xff; case IV_H: @@ -282,7 +296,13 @@ public class IOPort extends IOUnit { case SEL: sel = data; break; + case SEL2: + sel2 = data; + break; /* Can IV be written ? */ + case DS: + ds = data; + break; case IV_L: iv = (iv & 0xff00) | data; break; @@ -381,9 +401,7 @@ public class IOPort extends IOUnit { public void reset(int type) { int oldValue = out | (~dir) & 0xff; - for (int i = 0, n = 8; i < n; i++) { - pinState[i] = PinState.LOW; - } + Arrays.fill(pinState, PinState.LOW); in = 0; dir = 0; ren = 0; @@ -401,12 +419,13 @@ public class IOPort extends IOUnit { public String info() { StringBuilder sb = new StringBuilder(); - /* TODO: USE PORTMAP FOR THIS!!! */ - String[] regs = names; - sb.append('$').append(Utils.hex16(offset)).append(':'); - for (int i = 0, n = regs.length; i < n; i++) { - sb.append(' ').append(regs[i]).append(":$") - .append(Utils.hex8(0)); + sb.append(" $").append(Utils.hex(offset, 2)).append(':'); + for (int i = 0, n = portMap.length; i < n; i++) { + PortReg reg = portMap[i]; + if (reg != null) { + sb.append(' ').append(reg).append("($").append(Utils.hex(i, 2)).append("):$") + .append(Utils.hex(0, 2)); + } } return sb.toString(); } diff --git a/se/sics/mspsim/core/MSP430Config.java b/se/sics/mspsim/core/MSP430Config.java index fae8440..3cb67d1 100644 --- a/se/sics/mspsim/core/MSP430Config.java +++ b/se/sics/mspsim/core/MSP430Config.java @@ -143,5 +143,8 @@ public abstract class MSP430Config { maxMemIO = size; } + public ClockSystem createClockSystem(MSP430Core cpu, int[] memory, Timer[] timers) { + return new BasicClockModule(cpu, memory, 0, timers); + } } diff --git a/se/sics/mspsim/core/MSP430Core.java b/se/sics/mspsim/core/MSP430Core.java index db3fde5..76a03ef 100644 --- a/se/sics/mspsim/core/MSP430Core.java +++ b/se/sics/mspsim/core/MSP430Core.java @@ -239,13 +239,7 @@ public class MSP430Core extends Chip implements MSP430Constants { 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); - } + bcs = config.createClockSystem(this, memory, timers); ioSegment.setIORange(bcs.getAddressRangeMin(), bcs.getAddressRangeMax() - bcs.getAddressRangeMin() + 1, bcs); // SFR and Basic clock system. diff --git a/se/sics/mspsim/core/Multiplier32.java b/se/sics/mspsim/core/Multiplier32.java index e5024b2..141f752 100644 --- a/se/sics/mspsim/core/Multiplier32.java +++ b/se/sics/mspsim/core/Multiplier32.java @@ -168,12 +168,12 @@ public class Multiplier32 extends IOUnit { public void write(int address, int data, boolean word, long cycles) { address = address - offset; if (DEBUG) { - log("write to: " + Utils.hex(address, 4) + " data = " + data + " word = " + word); + log("write to: $" + Utils.hex(address, 4) + " data=" + data + " word=" + word); } switch(address) { case MPY: - op1 = mpy = data; if (DEBUG) log("Write to MPY: " + data); + op1 = mpy = data; signed = false; accumulating = false; break;