OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [timer.c] - Blame information for rev 8

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 hellwig
/*
2
 * timer.c -- timer simulation
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <setjmp.h>
10
 
11
#include "common.h"
12
#include "console.h"
13
#include "error.h"
14
#include "except.h"
15
#include "cpu.h"
16
#include "timer.h"
17
 
18
 
19
#define TIME_WRAP       1000000         /* avoid overflow of current time */
20
 
21
 
22
typedef struct timer {
23
  struct timer *next;
24
  int alarm;
25
  void (*callback)(int param);
26
  int param;
27
} Timer;
28
 
29
 
30
static Bool debug = false;
31
 
32
static Timer *activeTimers = NULL;
33
static Timer *freeTimers = NULL;
34
 
35
static int currentTime = 0;
36
 
37
static Word timerCtrl = 0x00000000;
38
static Word timerDivisor = 0xFFFFFFFF;
39
static Word timerCounter = 0xFFFFFFFF;
40
 
41
 
42
Word timerRead(Word addr) {
43
  Word data;
44
 
45
  if (debug) {
46
    cPrintf("\n**** TIMER READ from 0x%08X", addr);
47
  }
48
  if (addr == TIMER_CTRL) {
49
    data = timerCtrl;
50
  } else
51
  if (addr == TIMER_DIVISOR) {
52
    data = timerDivisor;
53
  } else {
54
    /* illegal register */
55
    throwException(EXC_BUS_TIMEOUT);
56
  }
57
  if (debug) {
58
    cPrintf(", data = 0x%08X ****\n", data);
59
  }
60
  return data;
61
}
62
 
63
 
64
void timerWrite(Word addr, Word data) {
65
  if (debug) {
66
    cPrintf("\n**** TIMER WRITE to 0x%08X, data = 0x%08X ****\n",
67
            addr, data);
68
  }
69
  if (addr == TIMER_CTRL) {
70
    if (data & TIMER_IEN) {
71
      timerCtrl |= TIMER_IEN;
72
    } else {
73
      timerCtrl &= ~TIMER_IEN;
74
    }
75
    if (data & TIMER_EXP) {
76
      timerCtrl |= TIMER_EXP;
77
    } else {
78
      timerCtrl &= ~TIMER_EXP;
79
    }
80
    if ((timerCtrl & TIMER_IEN) != 0 &&
81
        (timerCtrl & TIMER_EXP) != 0) {
82
      /* raise timer interrupt */
83
      cpuSetInterrupt(IRQ_TIMER);
84
    } else {
85
      /* lower timer interrupt */
86
      cpuResetInterrupt(IRQ_TIMER);
87
    }
88
  } else
89
  if (addr == TIMER_DIVISOR) {
90
    timerDivisor = data;
91
    timerCounter = data;
92
  } else {
93
    /* illegal register */
94
    throwException(EXC_BUS_TIMEOUT);
95
  }
96
}
97
 
98
 
99
void timerTick(void) {
100
  Timer *timer;
101
  void (*callback)(int param);
102
  int param;
103
 
104
  /* increment current time, avoid overflow */
105
  if (++currentTime == TIME_WRAP) {
106
    currentTime -= TIME_WRAP;
107
    timer = activeTimers;
108
    while (timer != NULL) {
109
      timer->alarm -= TIME_WRAP;
110
      timer = timer->next;
111
    }
112
  }
113
  /* check whether any simulation timer expired */
114
  while (activeTimers != NULL &&
115
         currentTime >= activeTimers->alarm) {
116
    timer = activeTimers;
117
    activeTimers = timer->next;
118
    callback = timer->callback;
119
    param = timer->param;
120
    timer->next = freeTimers;
121
    freeTimers = timer;
122
    (*callback)(param);
123
  }
124
  /* decrement counter and check if an interrupt must be raised */
125
  if (--timerCounter == 0) {
126
    timerCounter = timerDivisor;
127
    timerCtrl |= TIMER_EXP;
128
    if (timerCtrl & TIMER_IEN) {
129
      /* raise timer interrupt */
130
      cpuSetInterrupt(IRQ_TIMER);
131
    }
132
  }
133
}
134
 
135
 
136
void timerStart(int msec, void (*callback)(int param), int param) {
137
  Timer *timer;
138
  Timer *p;
139
 
140
  if (freeTimers == NULL) {
141
    error("out of timers");
142
  }
143
  timer = freeTimers;
144
  freeTimers = timer->next;
145
  timer->alarm = currentTime + msec;
146
  timer->callback = callback;
147
  timer->param = param;
148
  if (activeTimers == NULL ||
149
      timer->alarm < activeTimers->alarm) {
150
    /* link into front of active timers queue */
151
    timer->next = activeTimers;
152
    activeTimers = timer;
153
  } else {
154
    /* link elsewhere into active timers queue */
155
    p = activeTimers;
156
    while (p->next != NULL &&
157
           p->next->alarm <= timer->alarm) {
158
      p = p->next;
159
    }
160
    timer->next = p->next;
161
    p->next = timer;
162
  }
163
}
164
 
165
 
166
void timerReset(void) {
167
  Timer *timer;
168
 
169
  cPrintf("Resetting Timer...\n");
170
  while (activeTimers != NULL) {
171
    timer = activeTimers;
172
    activeTimers = timer->next;
173
    timer->next = freeTimers;
174
    freeTimers = timer;
175
  }
176
}
177
 
178
 
179
void timerInit(void) {
180
  Timer *timer;
181
  int i;
182
 
183
  for (i = 0; i < NUMBER_TIMERS; i++) {
184
    timer = malloc(sizeof(Timer));
185
    if (timer == NULL) {
186
      error("cannot allocate simulation timers");
187
    }
188
    timer->next = freeTimers;
189
    freeTimers = timer;
190
  }
191
  timerReset();
192
}
193
 
194
 
195
void timerExit(void) {
196
  Timer *timer;
197
 
198
  timerReset();
199
  while (freeTimers != NULL) {
200
    timer = freeTimers;
201
    freeTimers = timer->next;
202
    free(timer);
203
  }
204
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.