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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [tick/] [tick.c] - Blame information for rev 1779

Go to most recent revision | 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 91 lampret
 
50 1408 nogj
 
51 1748 jeremybenn
/*! When did the timer start to count */
52
static long long cycles_start = 0;
53
 
54
/*! Indicates if the timer is actually counting.  Needed to simulate one-shot
55
    mode correctly */
56 1540 nogj
int tick_count;
57 728 markom
 
58 1748 jeremybenn
/*! Reset. It initializes TTCR register. */
59
void
60
tick_reset (void)
61 91 lampret
{
62 728 markom
  if (config.sim.verbose)
63 1748 jeremybenn
    {
64
      PRINTF ("Resetting Tick Timer.\n");
65
    }
66
 
67 1540 nogj
  cpu_state.sprs[SPR_TTCR] = 0;
68
  cpu_state.sprs[SPR_TTMR] = 0;
69
  tick_count = 0;
70 91 lampret
}
71
 
72 1748 jeremybenn
/*! Raises a timer exception */
73
static void
74
tick_raise_except (void *dat)
75 91 lampret
{
76 1540 nogj
  cpu_state.sprs[SPR_TTMR] |= SPR_TTMR_IP;
77
 
78
  /* Reschedule unconditionally, since we have to raise the exception until
79
   * TTMR_IP has been cleared */
80 1748 jeremybenn
  sched_next_insn (tick_raise_except, NULL);
81 1559 nogj
 
82
  /* be sure not to issue a timer exception if an exception occured before it */
83 1748 jeremybenn
  if (cpu_state.sprs[SPR_SR] & SPR_SR_TEE)
84
    {
85
      except_handle (EXCEPT_TICK, cpu_state.sprs[SPR_EEAR_BASE]);
86
    }
87 1540 nogj
}
88
 
89 1748 jeremybenn
/*! Restarts the tick timer */
90
static void
91
tick_restart (void *dat)
92 1540 nogj
{
93
  cpu_state.sprs[SPR_TTCR] = 0;
94
  cycles_start = runtime.sim.cycles;
95 1748 jeremybenn
  SCHED_ADD (tick_restart, NULL, cpu_state.sprs[SPR_TTMR] & SPR_TTMR_PERIOD);
96 1540 nogj
}
97
 
98 1748 jeremybenn
/*! Stops the timer */
99
static void
100
tick_one_shot (void *dat)
101 1540 nogj
{
102
  cpu_state.sprs[SPR_TTCR] = cpu_state.sprs[SPR_TTMR] & SPR_TTMR_PERIOD;
103
  tick_count = 0;
104
}
105
 
106 1748 jeremybenn
/*! Schedules the timer jobs */
107
static void
108
sched_timer_job (uorreg_t prev_ttmr)
109 1540 nogj
{
110
  uorreg_t ttmr = cpu_state.sprs[SPR_TTMR];
111
  uint32_t match_time = ttmr & SPR_TTMR_PERIOD;
112 1748 jeremybenn
  uint32_t ttcr_period = spr_read_ttcr () & SPR_TTCR_PERIOD;
113 1540 nogj
 
114
  /* Remove previous jobs if they exists */
115 1748 jeremybenn
  if ((prev_ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
116
    {
117
      SCHED_FIND_REMOVE (tick_raise_except, NULL);
118
    }
119 1540 nogj
 
120 1748 jeremybenn
  switch (prev_ttmr & SPR_TTMR_M)
121
    {
122
    case SPR_TTMR_RT:
123
      SCHED_FIND_REMOVE (tick_restart, NULL);
124
      break;
125 1540 nogj
 
126 1748 jeremybenn
    case SPR_TTMR_SR:
127
      SCHED_FIND_REMOVE (tick_one_shot, NULL);
128
      break;
129
    }
130
 
131
  if (match_time >= ttcr_period)
132
    {
133
      match_time -= ttcr_period;
134
    }
135 1540 nogj
  else
136 1748 jeremybenn
    {
137
      match_time += (0xfffffffu - ttcr_period) + 1;
138
    }
139 1540 nogj
 
140 1748 jeremybenn
  switch (ttmr & SPR_TTMR_M)
141
    {
142
    case 0:                      /* Disabled timer */
143
      if (!match_time && (ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
144
        SCHED_ADD (tick_raise_except, NULL, 0);
145
      break;
146
 
147
    case SPR_TTMR_RT:           /* Auto-restart timer */
148
      SCHED_ADD (tick_restart, NULL, match_time);
149
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
150
        SCHED_ADD (tick_raise_except, NULL, match_time);
151
      break;
152
 
153
    case SPR_TTMR_SR:           /* One-shot timer */
154
      if (tick_count)
155
        {
156
          SCHED_ADD (tick_one_shot, NULL, match_time);
157
          if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
158
            SCHED_ADD (tick_raise_except, NULL, match_time);
159
        }
160
      break;
161
 
162
    case SPR_TTMR_CR:           /* Continuos timer */
163
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
164
        SCHED_ADD (tick_raise_except, NULL, match_time);
165 802 simons
    }
166 728 markom
}
167 189 chris
 
168 1748 jeremybenn
 
169
/*! Handles a write to the ttcr spr */
170
void
171
spr_write_ttcr (uorreg_t value)
172 728 markom
{
173 1540 nogj
  cycles_start = runtime.sim.cycles - value;
174
 
175 1748 jeremybenn
  sched_timer_job (cpu_state.sprs[SPR_TTMR]);
176 728 markom
}
177 611 simons
 
178 1748 jeremybenn
/*! Value is the *previous* value of SPR_TTMR.  The new one can be found in
179
    cpu_state.sprs[SPR_TTMR] */
180
void
181
spr_write_ttmr (uorreg_t prev_val)
182 728 markom
{
183 1540 nogj
  uorreg_t value = cpu_state.sprs[SPR_TTMR];
184
 
185 1560 nogj
  /* Code running on or1k can't set SPR_TTMR_IP so make sure it isn't */
186
  cpu_state.sprs[SPR_TTMR] &= ~SPR_TTMR_IP;
187 1540 nogj
 
188
  /* If the timer was already disabled, ttcr should not be updated */
189 1748 jeremybenn
  if (tick_count)
190
    {
191
      cpu_state.sprs[SPR_TTCR] = runtime.sim.cycles - cycles_start;
192
    }
193 1540 nogj
 
194
  cycles_start = runtime.sim.cycles - cpu_state.sprs[SPR_TTCR];
195
 
196
  tick_count = value & SPR_TTMR_M;
197
 
198 1748 jeremybenn
  if ((tick_count == 0xc0000000) &&
199
      (cpu_state.sprs[SPR_TTCR] == (value & SPR_TTMR_PERIOD)))
200
    {
201
      tick_count = 0;
202
    }
203 1540 nogj
 
204 1748 jeremybenn
  sched_timer_job (prev_val);
205 728 markom
}
206 611 simons
 
207 1748 jeremybenn
uorreg_t
208
spr_read_ttcr ()
209 728 markom
{
210 1540 nogj
  uorreg_t ret;
211
 
212 1748 jeremybenn
  if (!tick_count)
213
    {
214
      /* Report the time when the counter stoped (and don't carry on
215
         counting) */
216
      ret = cpu_state.sprs[SPR_TTCR];
217
    }
218 1540 nogj
  else
219 1748 jeremybenn
    {
220
      ret = runtime.sim.cycles - cycles_start;
221
    }
222 1540 nogj
 
223 1748 jeremybenn
  return  ret;
224 91 lampret
}

powered by: WebSVN 2.1.0

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