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
This commit is contained in:
joxe 2008-03-18 13:37:58 +00:00
parent bc89b1c17e
commit 848cf2bf87
4 changed files with 120 additions and 72 deletions

View File

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

View File

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

View File

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

View File

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