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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc1/] [or1ksim/] [tick/] [tick.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 91 lampret
/* tick.c -- Simulation of OpenRISC 1000 tick timer
2 1748 jeremybenn
 
3 91 lampret
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4 1540 nogj
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
5 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
6 91 lampret
 
7 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8 91 lampret
 
9 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10 91 lampret
 
11 1748 jeremybenn
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15 91 lampret
 
16 1748 jeremybenn
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20 91 lampret
 
21 1748 jeremybenn
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
23 91 lampret
 
24 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26 91 lampret
 
27 1748 jeremybenn
/* This is functional simulation of OpenRISC 1000 architectural tick timer */
28
 
29
/* Autoconf and/or portability configuration */
30 1350 nogj
#include "config.h"
31 1748 jeremybenn
#include "port.h"
32 1350 nogj
 
33 1748 jeremybenn
/* System includes */
34
#include <stdlib.h>
35
#include <stdio.h>
36 1350 nogj
 
37 1748 jeremybenn
/* Package includes */
38 1350 nogj
#include "arch.h"
39
#include "abstract.h"
40 561 simons
#include "except.h"
41 91 lampret
#include "tick.h"
42 1432 nogj
#include "opcode/or32.h"
43 1748 jeremybenn
#include "spr-defs.h"
44 1432 nogj
#include "execute.h"
45 102 lampret
#include "pic.h"
46 189 chris
#include "sprs.h"
47 333 markom
#include "sim-config.h"
48 728 markom
#include "sched.h"
49 1408 nogj
#include "debug.h"
50 91 lampret
 
51 1408 nogj
 
52 1748 jeremybenn
DEFAULT_DEBUG_CHANNEL (tick);
53 133 markom
 
54 1748 jeremybenn
/*! When did the timer start to count */
55
static long long cycles_start = 0;
56
 
57
/*! Indicates if the timer is actually counting.  Needed to simulate one-shot
58
    mode correctly */
59 1540 nogj
int tick_count;
60 728 markom
 
61 1748 jeremybenn
/*! Reset. It initializes TTCR register. */
62
void
63
tick_reset (void)
64 91 lampret
{
65 728 markom
  if (config.sim.verbose)
66 1748 jeremybenn
    {
67
      PRINTF ("Resetting Tick Timer.\n");
68
    }
69
 
70 1540 nogj
  cpu_state.sprs[SPR_TTCR] = 0;
71
  cpu_state.sprs[SPR_TTMR] = 0;
72
  tick_count = 0;
73 91 lampret
}
74
 
75 1748 jeremybenn
/*! Raises a timer exception */
76
static void
77
tick_raise_except (void *dat)
78 91 lampret
{
79 1540 nogj
  cpu_state.sprs[SPR_TTMR] |= SPR_TTMR_IP;
80
 
81
  /* Reschedule unconditionally, since we have to raise the exception until
82
   * TTMR_IP has been cleared */
83 1748 jeremybenn
  sched_next_insn (tick_raise_except, NULL);
84 1559 nogj
 
85
  /* be sure not to issue a timer exception if an exception occured before it */
86 1748 jeremybenn
  if (cpu_state.sprs[SPR_SR] & SPR_SR_TEE)
87
    {
88
      except_handle (EXCEPT_TICK, cpu_state.sprs[SPR_EEAR_BASE]);
89
    }
90 1540 nogj
}
91
 
92 1748 jeremybenn
/*! Restarts the tick timer */
93
static void
94
tick_restart (void *dat)
95 1540 nogj
{
96
  cpu_state.sprs[SPR_TTCR] = 0;
97
  cycles_start = runtime.sim.cycles;
98 1748 jeremybenn
  TRACE ("Scheduleing timer restart job for %" PRIdREG "\n",
99
         cpu_state.sprs[SPR_TTMR] & SPR_TTMR_PERIOD);
100
  SCHED_ADD (tick_restart, NULL, cpu_state.sprs[SPR_TTMR] & SPR_TTMR_PERIOD);
101 1540 nogj
}
102
 
103 1748 jeremybenn
/*! Stops the timer */
104
static void
105
tick_one_shot (void *dat)
106 1540 nogj
{
107 1748 jeremybenn
  TRACE ("Stopping one-shot timer\n");
108 1540 nogj
  cpu_state.sprs[SPR_TTCR] = cpu_state.sprs[SPR_TTMR] & SPR_TTMR_PERIOD;
109
  tick_count = 0;
110
}
111
 
112 1748 jeremybenn
/*! Schedules the timer jobs */
113
static void
114
sched_timer_job (uorreg_t prev_ttmr)
115 1540 nogj
{
116
  uorreg_t ttmr = cpu_state.sprs[SPR_TTMR];
117
  uint32_t match_time = ttmr & SPR_TTMR_PERIOD;
118 1748 jeremybenn
  uint32_t ttcr_period = spr_read_ttcr () & SPR_TTCR_PERIOD;
119 1540 nogj
 
120
  /* Remove previous jobs if they exists */
121 1748 jeremybenn
  if ((prev_ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
122
    {
123
      SCHED_FIND_REMOVE (tick_raise_except, NULL);
124
    }
125 1540 nogj
 
126 1748 jeremybenn
  switch (prev_ttmr & SPR_TTMR_M)
127
    {
128
    case SPR_TTMR_RT:
129
      SCHED_FIND_REMOVE (tick_restart, NULL);
130
      break;
131 1540 nogj
 
132 1748 jeremybenn
    case SPR_TTMR_SR:
133
      SCHED_FIND_REMOVE (tick_one_shot, NULL);
134
      break;
135
    }
136
 
137
  if (match_time >= ttcr_period)
138
    {
139
      match_time -= ttcr_period;
140
    }
141 1540 nogj
  else
142 1748 jeremybenn
    {
143
      match_time += (0xfffffffu - ttcr_period) + 1;
144
    }
145 1540 nogj
 
146 1748 jeremybenn
  TRACE ("Cycles to go until match: %" PRIu32 " (0x%" PRIx32 ")\n",
147
         match_time, match_time);
148 1540 nogj
 
149 1748 jeremybenn
  switch (ttmr & SPR_TTMR_M)
150
    {
151
    case 0:                      /* Disabled timer */
152
      TRACE ("Scheduleing exception when timer match (in disabled mode).\n");
153
      if (!match_time && (ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
154
        SCHED_ADD (tick_raise_except, NULL, 0);
155
      break;
156
 
157
    case SPR_TTMR_RT:           /* Auto-restart timer */
158
      TRACE ("Scheduleing auto-restarting timer.\n");
159
      SCHED_ADD (tick_restart, NULL, match_time);
160
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
161
        SCHED_ADD (tick_raise_except, NULL, match_time);
162
      break;
163
 
164
    case SPR_TTMR_SR:           /* One-shot timer */
165
      TRACE ("Scheduleing one-shot timer.\n");
166
      if (tick_count)
167
        {
168
          SCHED_ADD (tick_one_shot, NULL, match_time);
169
          if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
170
            SCHED_ADD (tick_raise_except, NULL, match_time);
171
        }
172
      break;
173
 
174
    case SPR_TTMR_CR:           /* Continuos timer */
175
      TRACE ("Scheduleing exception when timer match (in cont. mode).\n");
176
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
177
        SCHED_ADD (tick_raise_except, NULL, match_time);
178 802 simons
    }
179 728 markom
}
180 189 chris
 
181 1748 jeremybenn
 
182
/*! Handles a write to the ttcr spr */
183
void
184
spr_write_ttcr (uorreg_t value)
185 728 markom
{
186 1748 jeremybenn
  TRACE ("set ttcr = %" PRIxREG "\n", value);
187 1540 nogj
  cycles_start = runtime.sim.cycles - value;
188
 
189 1748 jeremybenn
  sched_timer_job (cpu_state.sprs[SPR_TTMR]);
190 728 markom
}
191 611 simons
 
192 1748 jeremybenn
/*! Value is the *previous* value of SPR_TTMR.  The new one can be found in
193
    cpu_state.sprs[SPR_TTMR] */
194
void
195
spr_write_ttmr (uorreg_t prev_val)
196 728 markom
{
197 1540 nogj
  uorreg_t value = cpu_state.sprs[SPR_TTMR];
198
 
199 1748 jeremybenn
  TRACE ("set ttmr = %" PRIxREG " (previous: %" PRIxREG ")\n", value,
200
         prev_val);
201 1540 nogj
 
202 1560 nogj
  /* Code running on or1k can't set SPR_TTMR_IP so make sure it isn't */
203
  cpu_state.sprs[SPR_TTMR] &= ~SPR_TTMR_IP;
204 1540 nogj
 
205
  /* If the timer was already disabled, ttcr should not be updated */
206 1748 jeremybenn
  if (tick_count)
207
    {
208
      cpu_state.sprs[SPR_TTCR] = runtime.sim.cycles - cycles_start;
209
    }
210 1540 nogj
 
211
  cycles_start = runtime.sim.cycles - cpu_state.sprs[SPR_TTCR];
212
 
213
  tick_count = value & SPR_TTMR_M;
214
 
215 1748 jeremybenn
  if ((tick_count == 0xc0000000) &&
216
      (cpu_state.sprs[SPR_TTCR] == (value & SPR_TTMR_PERIOD)))
217
    {
218
      tick_count = 0;
219
    }
220 1540 nogj
 
221 1748 jeremybenn
  sched_timer_job (prev_val);
222 728 markom
}
223 611 simons
 
224 1748 jeremybenn
uorreg_t
225
spr_read_ttcr ()
226 728 markom
{
227 1540 nogj
  uorreg_t ret;
228
 
229 1748 jeremybenn
  if (!tick_count)
230
    {
231
      /* Report the time when the counter stoped (and don't carry on
232
         counting) */
233
      ret = cpu_state.sprs[SPR_TTCR];
234
    }
235 1540 nogj
  else
236 1748 jeremybenn
    {
237
      ret = runtime.sim.cycles - cycles_start;
238
    }
239 1540 nogj
 
240 1748 jeremybenn
  TRACE ("read ttcr %" PRIdREG " (0x%" PRIxREG ")\n", ret, ret);
241
  return  ret;
242 91 lampret
}

powered by: WebSVN 2.1.0

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