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

Subversion Repositories eco32

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

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 25 hellwig
/*
23
 * data structure for simulation timer
24
 */
25 8 hellwig
typedef struct timer {
26
  struct timer *next;
27
  int alarm;
28
  void (*callback)(int param);
29
  int param;
30
} Timer;
31
 
32
 
33 25 hellwig
/*
34
 * data structure for timer/counter device
35
 */
36
typedef struct {
37
  Word ctrl;
38
  Word divisor;
39
  Word counter;
40
  int irq;
41
} TimerCounter;
42
 
43
 
44 8 hellwig
static Bool debug = false;
45
 
46
static Timer *activeTimers = NULL;
47
static Timer *freeTimers = NULL;
48 25 hellwig
static int currentTime = 0;              /* measured in clock cycles */
49 8 hellwig
 
50 25 hellwig
static TimerCounter timerCounters[NUMBER_TMRCNT];
51 8 hellwig
 
52
 
53
Word timerRead(Word addr) {
54 25 hellwig
  int dev, reg;
55 8 hellwig
  Word data;
56
 
57
  if (debug) {
58
    cPrintf("\n**** TIMER READ from 0x%08X", addr);
59
  }
60 25 hellwig
  dev = addr >> 12;
61
  if (dev >= NUMBER_TMRCNT) {
62
    /* illegal device */
63
    throwException(EXC_BUS_TIMEOUT);
64
  }
65
  reg = addr & 0x0FFF;
66
  if (reg == TIMER_CTRL) {
67
    data = timerCounters[dev].ctrl;
68 8 hellwig
  } else
69 25 hellwig
  if (reg == TIMER_DIVISOR) {
70
    data = timerCounters[dev].divisor;
71
  } else
72
  if (reg == TIMER_COUNTER) {
73
    data = timerCounters[dev].counter;
74 8 hellwig
  } else {
75
    /* illegal register */
76
    throwException(EXC_BUS_TIMEOUT);
77
  }
78
  if (debug) {
79
    cPrintf(", data = 0x%08X ****\n", data);
80
  }
81
  return data;
82
}
83
 
84
 
85
void timerWrite(Word addr, Word data) {
86 25 hellwig
  int dev, reg;
87
 
88 8 hellwig
  if (debug) {
89
    cPrintf("\n**** TIMER WRITE to 0x%08X, data = 0x%08X ****\n",
90
            addr, data);
91
  }
92 25 hellwig
  dev = addr >> 12;
93
  if (dev >= NUMBER_TMRCNT) {
94
    /* illegal device */
95
    throwException(EXC_BUS_TIMEOUT);
96
  }
97
  reg = addr & 0x0FFF;
98
  if (reg == TIMER_CTRL) {
99 8 hellwig
    if (data & TIMER_IEN) {
100 25 hellwig
      timerCounters[dev].ctrl |= TIMER_IEN;
101 8 hellwig
    } else {
102 25 hellwig
      timerCounters[dev].ctrl &= ~TIMER_IEN;
103 8 hellwig
    }
104
    if (data & TIMER_EXP) {
105 25 hellwig
      timerCounters[dev].ctrl |= TIMER_EXP;
106 8 hellwig
    } else {
107 25 hellwig
      timerCounters[dev].ctrl &= ~TIMER_EXP;
108 8 hellwig
    }
109 25 hellwig
    if ((timerCounters[dev].ctrl & TIMER_IEN) != 0 &&
110
        (timerCounters[dev].ctrl & TIMER_EXP) != 0) {
111 8 hellwig
      /* raise timer interrupt */
112 25 hellwig
      cpuSetInterrupt(timerCounters[dev].irq);
113 8 hellwig
    } else {
114
      /* lower timer interrupt */
115 25 hellwig
      cpuResetInterrupt(timerCounters[dev].irq);
116 8 hellwig
    }
117
  } else
118 25 hellwig
  if (reg == TIMER_DIVISOR) {
119
    timerCounters[dev].divisor = data;
120
    timerCounters[dev].counter = data;
121 8 hellwig
  } else {
122
    /* illegal register */
123
    throwException(EXC_BUS_TIMEOUT);
124
  }
125
}
126
 
127
 
128
void timerTick(void) {
129
  Timer *timer;
130
  void (*callback)(int param);
131
  int param;
132 25 hellwig
  int i;
133 8 hellwig
 
134 25 hellwig
  /* increment current time */
135
  currentTime += CC_PER_INSTR;
136
  /* avoid overflow */
137
  if (currentTime >= TIME_WRAP) {
138 8 hellwig
    currentTime -= TIME_WRAP;
139
    timer = activeTimers;
140
    while (timer != NULL) {
141
      timer->alarm -= TIME_WRAP;
142
      timer = timer->next;
143
    }
144
  }
145
  /* check whether any simulation timer expired */
146
  while (activeTimers != NULL &&
147
         currentTime >= activeTimers->alarm) {
148
    timer = activeTimers;
149
    activeTimers = timer->next;
150
    callback = timer->callback;
151
    param = timer->param;
152
    timer->next = freeTimers;
153
    freeTimers = timer;
154
    (*callback)(param);
155
  }
156 25 hellwig
  /* decrement counters and check if an interrupt must be raised */
157
  for (i = 0; i < NUMBER_TMRCNT; i++) {
158
    if (timerCounters[i].counter <= CC_PER_INSTR) {
159
      timerCounters[i].counter += timerCounters[i].divisor - CC_PER_INSTR;
160
      timerCounters[i].ctrl |= TIMER_EXP;
161
      if (timerCounters[i].ctrl & TIMER_IEN) {
162
        /* raise timer interrupt */
163
        cpuSetInterrupt(timerCounters[i].irq);
164
      }
165
    } else {
166
      timerCounters[i].counter -= CC_PER_INSTR;
167 8 hellwig
    }
168
  }
169
}
170
 
171
 
172 25 hellwig
void timerStart(int usec, void (*callback)(int param), int param) {
173 8 hellwig
  Timer *timer;
174
  Timer *p;
175
 
176
  if (freeTimers == NULL) {
177
    error("out of timers");
178
  }
179
  timer = freeTimers;
180
  freeTimers = timer->next;
181 25 hellwig
  timer->alarm = currentTime + usec * CC_PER_USEC;
182 8 hellwig
  timer->callback = callback;
183
  timer->param = param;
184
  if (activeTimers == NULL ||
185
      timer->alarm < activeTimers->alarm) {
186
    /* link into front of active timers queue */
187
    timer->next = activeTimers;
188
    activeTimers = timer;
189
  } else {
190
    /* link elsewhere into active timers queue */
191
    p = activeTimers;
192
    while (p->next != NULL &&
193
           p->next->alarm <= timer->alarm) {
194
      p = p->next;
195
    }
196
    timer->next = p->next;
197
    p->next = timer;
198
  }
199
}
200
 
201
 
202
void timerReset(void) {
203
  Timer *timer;
204 25 hellwig
  int i;
205 8 hellwig
 
206
  cPrintf("Resetting Timer...\n");
207
  while (activeTimers != NULL) {
208
    timer = activeTimers;
209
    activeTimers = timer->next;
210
    timer->next = freeTimers;
211
    freeTimers = timer;
212
  }
213 25 hellwig
  for (i = 0; i < NUMBER_TMRCNT; i++) {
214
    timerCounters[i].ctrl = 0x00000000;
215
    timerCounters[i].divisor = 0xFFFFFFFF;
216
    timerCounters[i].counter = 0xFFFFFFFF;
217
    timerCounters[i].irq = IRQ_TIMER_0 + i;
218
  }
219 8 hellwig
}
220
 
221
 
222
void timerInit(void) {
223
  Timer *timer;
224
  int i;
225
 
226
  for (i = 0; i < NUMBER_TIMERS; i++) {
227
    timer = malloc(sizeof(Timer));
228
    if (timer == NULL) {
229
      error("cannot allocate simulation timers");
230
    }
231
    timer->next = freeTimers;
232
    freeTimers = timer;
233
  }
234
  timerReset();
235
}
236
 
237
 
238
void timerExit(void) {
239
  Timer *timer;
240
 
241 25 hellwig
  while (activeTimers != NULL) {
242
    timer = activeTimers;
243
    activeTimers = timer->next;
244
    timer->next = freeTimers;
245
    freeTimers = timer;
246
  }
247 8 hellwig
  while (freeTimers != NULL) {
248
    timer = freeTimers;
249
    freeTimers = timer->next;
250
    free(timer);
251
  }
252
}

powered by: WebSVN 2.1.0

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