From 848cf2bf87be8d97df2e44b499b5506a39feeaab Mon Sep 17 00:00:00 2001 From: joxe Date: Tue, 18 Mar 2008 13:37:58 +0000 Subject: [PATCH] Rewrote scheduling of timer system to be eventbased instead of "tick" based. git-svn-id: https://mspsim.svn.sourceforge.net/svnroot/mspsim/mspsim@195 23d1a52b-0c3c-0410-b72d-8f29ab48fe35 --- se/sics/mspsim/core/EventQueue.java | 3 + se/sics/mspsim/core/MSP430Core.java | 44 +++++---- se/sics/mspsim/core/Timer.java | 141 ++++++++++++++++++---------- tests/cputest.c | 4 +- 4 files changed, 120 insertions(+), 72 deletions(-) diff --git a/se/sics/mspsim/core/EventQueue.java b/se/sics/mspsim/core/EventQueue.java index a69b1f8..40ed967 100644 --- a/se/sics/mspsim/core/EventQueue.java +++ b/se/sics/mspsim/core/EventQueue.java @@ -45,6 +45,7 @@ public class EventQueue { private TimeEvent first; public long nextTime; + public int eventCount = 0; public EventQueue() { } @@ -58,6 +59,7 @@ public class EventQueue { if (event.scheduled) { removeEvent(event); } + eventCount++; if (first == null) { first = event; } else { @@ -116,6 +118,7 @@ public class EventQueue { // System.out.println("Removed =>"); // print(); event.scheduled = false; + eventCount--; return true; } diff --git a/se/sics/mspsim/core/MSP430Core.java b/se/sics/mspsim/core/MSP430Core.java index 901715a..bfc8b2f 100644 --- a/se/sics/mspsim/core/MSP430Core.java +++ b/se/sics/mspsim/core/MSP430Core.java @@ -52,7 +52,7 @@ public class MSP430Core extends Chip implements MSP430Constants { // Try it out with 64 k memory public static final int MAX_MEM = 64*1024; - public static final int INTERNAL_IO_SIZE = 5; + public static final int INTERNAL_IO_SIZE = 3; public static final int PORTS = 6; public static final int MODE_ACTIVE = 0; @@ -131,12 +131,14 @@ public class MSP430Core extends Chip implements MSP430Constants { // Ignore type for now... // Internal Active IOUnits + int passIO = 0; + int actIO = 0; ioUnits = new IOUnit[INTERNAL_IO_SIZE + 10]; ioCycles = new long[INTERNAL_IO_SIZE + 10]; // Passive IOUnits (no tick) - do we need to remember them??? // Maybe for debugging purposes... - passiveIOUnits = new IOUnit[PORTS]; + passiveIOUnits = new IOUnit[PORTS + 2]; Timer ta = new Timer(this, Timer.TIMER_Ax149, memory, 0x160); Timer tb = new Timer(this, Timer.TIMER_Bx149, memory, 0x180); @@ -168,15 +170,15 @@ public class MSP430Core extends Chip implements MSP430Constants { memIn[i] = mp; } - ioUnits[0] = ta; - ioUnits[1] = tb; - ioUnits[2] = bcs; +// ioUnits[0] = ta; +// ioUnits[1] = tb; + ioUnits[actIO++] = bcs; USART usart0 = new USART(this, memory, 0x70); USART usart1 = new USART(this, memory, 0x78); - ioUnits[3] = usart0; - ioUnits[4] = usart1; + ioUnits[actIO++] = usart0; + ioUnits[actIO++] = usart1; for (int i = 0, n = 8; i < n; i++) { memOut[0x70 + i] = usart0; @@ -187,7 +189,7 @@ public class MSP430Core extends Chip implements MSP430Constants { } ADC12 adc12 = new ADC12(this); - ioUnits[5] = adc12; + ioUnits[actIO++] = adc12; for (int i = 0, n = 16; i < n; i++) { memOut[0x80 + i] = adc12; @@ -228,6 +230,11 @@ public class MSP430Core extends Chip implements MSP430Constants { memOut[0x32 + i * 4] = passiveIOUnits[i + 4]; memOut[0x33 + i * 4] = passiveIOUnits[i + 4]; } + passIO = 6; + + // Add the timers + passiveIOUnits[passIO++] = ta; + passiveIOUnits[passIO++] = tb; initIOUnit(); } @@ -378,30 +385,30 @@ public class MSP430Core extends Chip implements MSP430Constants { private void executeEvents() { if (cycles >= nextVTimeEventCycles) { - if (vTimeEventQueue.nextTime == 0) { - nextVTimeEventCycles = cycles + 1000; + if (vTimeEventQueue.eventCount == 0) { + nextVTimeEventCycles = cycles + 10000; } else { TimeEvent te = vTimeEventQueue.popFirst(); long now = getTime(); te.execute(now); - if (vTimeEventQueue.nextTime > 0) { + if (vTimeEventQueue.eventCount > 0) { nextVTimeEventCycles = convertVTime(vTimeEventQueue.nextTime); } else { - nextVTimeEventCycles = cycles + 1000; + nextVTimeEventCycles = cycles + 10000; } } } if (cycles >= nextCycleEventCycles) { - if (cycleEventQueue.nextTime == 0) { - nextCycleEventCycles = cycles + 1000; + if (cycleEventQueue.eventCount == 0) { + nextCycleEventCycles = cycles + 10000; } else { TimeEvent te = cycleEventQueue.popFirst(); te.execute(cycles); - if (cycleEventQueue.nextTime > 0) { - nextEventCycles = cycleEventQueue.nextTime; + if (cycleEventQueue.eventCount > 0) { + nextCycleEventCycles = cycleEventQueue.nextTime; } else { - nextCycleEventCycles = cycles + 1000; + nextCycleEventCycles = cycles + 10000; } } } @@ -417,7 +424,7 @@ public class MSP430Core extends Chip implements MSP430Constants { * @param time */ public void scheduleCycleEvent(TimeEvent event, long cycles) { - long currentNext = vTimeEventQueue.nextTime; + long currentNext = cycleEventQueue.nextTime; cycleEventQueue.addEvent(event, cycles); if (currentNext != cycleEventQueue.nextTime) { nextCycleEventCycles = cycleEventQueue.nextTime; @@ -425,7 +432,6 @@ public class MSP430Core extends Chip implements MSP430Constants { nextEventCycles = nextCycleEventCycles; } } - } diff --git a/se/sics/mspsim/core/Timer.java b/se/sics/mspsim/core/Timer.java index 4e84f89..5a014ef 100644 --- a/se/sics/mspsim/core/Timer.java +++ b/se/sics/mspsim/core/Timer.java @@ -197,7 +197,13 @@ public class Timer extends IOUnit { private boolean interruptEnable = false; private boolean interruptPending = false; - + private TimeEvent timerTrigger = new TimeEvent(0) { + public void execute(long t) { +// System.out.println(getName() + " executing update timers at " + t); + updateTimers(t); + } + }; + private MSP430Core core; private int lastTIV; @@ -389,6 +395,7 @@ public class Timer extends IOUnit { } updateCaptures(-1, cycles); + break; case TCCTL0: case TCCTL1: @@ -448,8 +455,10 @@ public class Timer extends IOUnit { if (DEBUG) { System.out.println(getName() + " Cycles: " + cycles + " expCap[" + index + "]: " + expCaptureTime[index] + " ctr:" + counter + " data: " + data + " ~" + - (100 * (cyclesMultiplicator * diff * 1L) / 2500000) / 100.0 + " sec"); + (100 * (cyclesMultiplicator * diff * 1L) / 2500000) / 100.0 + " sec" + + "at cycles: " + expCaptureTime[index]); } + calculateNextEventTime(cycles); } } @@ -459,10 +468,8 @@ public class Timer extends IOUnit { } private void updateCaptures(int index, long cycles) { - int low = 0; int hi = noCompare; if (index != -1) { - low = index; hi = index + 1; } @@ -476,12 +483,12 @@ public class Timer extends IOUnit { } else if (clockSource == SRC_ACLK) { frqClk = core.aclkFrq / inputDivider; } - + // Handle the captures... if (captureOn[i]) { - if (inputSrc[i] == SRC_ACLK) { - divisor = core.aclkFrq; - } + if (inputSrc[i] == SRC_ACLK) { + divisor = core.aclkFrq; + } if (DEBUG) { System.out.println(getName() + " expCapInterval[" + i + "] frq = " + @@ -506,6 +513,7 @@ public class Timer extends IOUnit { } } } + calculateNextEventTime(cycles); } private int updateCounter(long cycles) { @@ -539,10 +547,15 @@ public class Timer extends IOUnit { return counter; } - // Simplest possible - just a call each 1000 cycles (which is wrong...) + // Simplest possible - just a call each 1000 cycles (which is wrong...) public long ioTick(long cycles) { + System.out.println(getName() + " UNEXPECTED CALL TO IOTICK ****"); + return 100000 + cycles; + } - if (cycles > nextTimerTrigger) { + private void updateTimers(long cycles) { + + if (cycles >= nextTimerTrigger) { interruptPending = true; // This should be updated whenever clockspeed changes... nextTimerTrigger = (long) (nextTimerTrigger + 0x10000 * cyclesMultiplicator); @@ -551,57 +564,83 @@ public class Timer extends IOUnit { // This will not work very good... // But the timer does not need to be updated this often... // Do we need to update the counter here??? - // System.out.println("Checking capture register [ioTick]: " + cycles); + // System.out.println("Checking capture register [ioTick]: " + cycles); for (int i = 0, n = noCompare; i < n; i++) { // System.out.println("Checking: " + i); - if (expCaptureTime[i] != -1 && cycles > expCaptureTime[i]) { - if (DEBUG) { - System.out.println(getName() + " CAPTURE: " + i + - " Cycles: " + cycles + " expCap: " + - expCaptureTime[i] + - " => ExpCR: " + Utils.hex16(expCompare[i]) + - " TR: " + Utils.hex16(updateCounter(cycles))); - } - // Set the interrupt flag... - tcctl[i] |= CC_IFG; + if (expCaptureTime[i] != -1 && cycles >= expCaptureTime[i]) { + if (DEBUG) { + System.out.println(getName() + " CAPTURE: " + i + + " Cycles: " + cycles + " expCap: " + + expCaptureTime[i] + + " => ExpCR: " + Utils.hex16(expCompare[i]) + + " TR: " + Utils.hex16(updateCounter(cycles))); + } + // Set the interrupt flag... + tcctl[i] |= CC_IFG; - if (captureOn[i]) { - // Write the expected capture time to the register (counter could - // differ slightly) - tccr[i] = expCompare[i]; - // Update capture times... for next capture - expCompare[i] = (expCompare[i] + expCapInterval[i]) & 0xffff; - expCaptureTime[i] += expCapInterval[i] * cyclesMultiplicator; - if (DEBUG) { - System.out.println(getName() + - " setting expCaptureTime to next capture: " + - expCaptureTime[i]); - } - } else { - // Update expected compare time for this compare/cap reg. - // 0x10000 cycles... e.g. a full 16 bits wrap of the timer - expCaptureTime[i] = expCaptureTime[i] + - (long) (0x10000 * cyclesMultiplicator); - if (DEBUG) { - System.out.println(getName() + - " setting expCaptureTime to full wrap: " + - expCaptureTime[i]); - } - } + if (captureOn[i]) { + // Write the expected capture time to the register (counter could + // differ slightly) + tccr[i] = expCompare[i]; + // Update capture times... for next capture + expCompare[i] = (expCompare[i] + expCapInterval[i]) & 0xffff; + expCaptureTime[i] += expCapInterval[i] * cyclesMultiplicator; + if (DEBUG) { + System.out.println(getName() + + " setting expCaptureTime to next capture: " + + expCaptureTime[i]); + } + } else { + // Update expected compare time for this compare/cap reg. + // 0x10000 cycles... e.g. a full 16 bits wrap of the timer + expCaptureTime[i] = expCaptureTime[i] + + (long) (0x10000 * cyclesMultiplicator); + if (DEBUG) { + System.out.println(getName() + + " setting expCaptureTime to full wrap: " + + expCaptureTime[i]); + } + } - if (DEBUG) { - System.out.println("Wrote to: " + - Utils.hex16(offset + TCCTL0 + i * 2 + 1)); - } + if (DEBUG) { + System.out.println("Wrote to: " + + Utils.hex16(offset + TCCTL0 + i * 2 + 1)); + } } } + // Trigger interrupts that are up for triggering! triggerInterrupts(); - - return 1000 + cycles; + calculateNextEventTime(cycles); } - + + private void calculateNextEventTime(long cycles) { + long time = nextTimerTrigger; +// int smallest = -1; + for (int i = 0; i < expCaptureTime.length; i++) { + long ct = expCaptureTime[i]; + if (ct > 0 && ct < time) { + time = ct; +// smallest = i; + } + } + + if (time == 0) { + time = cycles + 1000; + } + + if (!timerTrigger.scheduled) { +// System.out.println(getName() + " new trigger (nothing sch) ..." + time + " re:" + +// smallest + " => " + (smallest > 0 ? expCaptureTime[smallest] + " > " + expCompare[smallest]: +// nextTimerTrigger) + " C:"+ cycles); + core.scheduleCycleEvent(timerTrigger, time); + } else if (timerTrigger.time > time) { +// System.out.println(getName() + " new trigger (new time)..." + time + " C:"+ cycles); + core.scheduleCycleEvent(timerTrigger, time); + } + } + // Can be called to generate any interrupt... public void triggerInterrupts() { // First check if any capture register is generating an interrupt... diff --git a/tests/cputest.c b/tests/cputest.c index 78e9c13..ceb092e 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -73,7 +73,7 @@ static int caseID = 0; static int pos = 0; static unsigned int times[10]; interrupt(TIMERB1_VECTOR) timerb1 (void) { - if(TBIV == 2) { + if (TBIV == 2) { if (pos < 10) { times[pos] = TBR; pos++; @@ -309,7 +309,7 @@ static void testTimer() { } for (i = 0; i < pos; i++) { - printf("Trigg time %d => %d\n", i + 1, times[i]); + printf("Trigg time %d => %ud\n", i + 1, times[i]); } }