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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [tick/] [tick.c] - Blame information for rev 588

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

Line No. Rev Author Line
1 19 jeremybenn
/* tick.c -- Simulation of OpenRISC 1000 tick timer
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
5
   Copyright (C) 2008 Embecosm Limited
6
 
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10
 
11
   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
 
16
   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
 
21
   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
 
24
/* This program is commented throughout in a fashion suitable for processing
25
   with Doxygen. */
26
 
27
/* This is functional simulation of OpenRISC 1000 architectural tick timer */
28
 
29
/* Autoconf and/or portability configuration */
30
#include "config.h"
31
#include "port.h"
32
 
33
/* System includes */
34
#include <stdlib.h>
35
#include <stdio.h>
36
 
37
/* Package includes */
38
#include "arch.h"
39
#include "abstract.h"
40
#include "except.h"
41
#include "tick.h"
42
#include "opcode/or32.h"
43
#include "spr-defs.h"
44
#include "execute.h"
45
#include "pic.h"
46
#include "sprs.h"
47
#include "sim-config.h"
48
#include "sched.h"
49
 
50
 
51
/*! When did the timer start to count */
52 561 julius
static long long cycle_count_at_tick_start = 0;
53 19 jeremybenn
 
54
/*! Indicates if the timer is actually counting.  Needed to simulate one-shot
55
    mode correctly */
56 561 julius
int tick_counting;
57 19 jeremybenn
 
58
/*! Reset. It initializes TTCR register. */
59
void
60
tick_reset (void)
61
{
62
  if (config.sim.verbose)
63
    {
64
      PRINTF ("Resetting Tick Timer.\n");
65
    }
66
 
67
  cpu_state.sprs[SPR_TTCR] = 0;
68
  cpu_state.sprs[SPR_TTMR] = 0;
69 561 julius
  tick_counting = 0;
70 19 jeremybenn
}
71
 
72
/*! Raises a timer exception */
73
static void
74
tick_raise_except (void *dat)
75
{
76
  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
  sched_next_insn (tick_raise_except, NULL);
81
 
82
  /* be sure not to issue a timer exception if an exception occured before it */
83
  if (cpu_state.sprs[SPR_SR] & SPR_SR_TEE)
84
    {
85
      except_handle (EXCEPT_TICK, cpu_state.sprs[SPR_EEAR_BASE]);
86
    }
87
}
88
 
89
/*! Restarts the tick timer */
90
static void
91
tick_restart (void *dat)
92
{
93
  cpu_state.sprs[SPR_TTCR] = 0;
94 561 julius
  cycle_count_at_tick_start = runtime.sim.cycles;
95 538 julius
  SCHED_ADD (tick_restart, NULL, cpu_state.sprs[SPR_TTMR] & SPR_TTMR_TP);
96 19 jeremybenn
}
97
 
98
/*! Stops the timer */
99
static void
100
tick_one_shot (void *dat)
101
{
102 538 julius
  cpu_state.sprs[SPR_TTCR] = cpu_state.sprs[SPR_TTMR] & SPR_TTMR_TP;
103 561 julius
  tick_counting = 0;
104 19 jeremybenn
}
105
 
106
/*! Schedules the timer jobs */
107
static void
108
sched_timer_job (uorreg_t prev_ttmr)
109
{
110
  uorreg_t ttmr = cpu_state.sprs[SPR_TTMR];
111 561 julius
  uint32_t match_ttmr = ttmr & SPR_TTMR_TP;
112
  /* TTCR register, only concerned with part of TTCR which will trigger int */
113
  uint32_t match_ttcr = spr_read_ttcr () & SPR_TTMR_TP;
114
  uint32_t cycles_until_except;
115 19 jeremybenn
 
116 561 julius
  /* On clearing TTMR interrupt signal bit remove previous jobs if they
117
     exist */
118 19 jeremybenn
  if ((prev_ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
119
    {
120
      SCHED_FIND_REMOVE (tick_raise_except, NULL);
121
    }
122
 
123
  switch (prev_ttmr & SPR_TTMR_M)
124
    {
125
    case SPR_TTMR_RT:
126
      SCHED_FIND_REMOVE (tick_restart, NULL);
127
      break;
128
 
129
    case SPR_TTMR_SR:
130
      SCHED_FIND_REMOVE (tick_one_shot, NULL);
131
      break;
132
    }
133
 
134 561 julius
  /* Calculate cycles until next tick exception, based on current TTCR value */
135
  if (match_ttmr >= match_ttcr)
136 19 jeremybenn
    {
137 561 julius
      cycles_until_except = match_ttmr - match_ttcr;
138 19 jeremybenn
    }
139
  else
140
    {
141 561 julius
      /* Cycles after "wrap" of section of TTCR which will cause a match and,
142
         potentially, an exception */
143
      cycles_until_except = match_ttmr + (0x0fffffffu - match_ttcr) + 1;
144 19 jeremybenn
    }
145
 
146
  switch (ttmr & SPR_TTMR_M)
147
    {
148
    case 0:                      /* Disabled timer */
149 561 julius
      if (!cycles_until_except && (ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
150 19 jeremybenn
        SCHED_ADD (tick_raise_except, NULL, 0);
151
      break;
152
 
153
    case SPR_TTMR_RT:           /* Auto-restart timer */
154 561 julius
      SCHED_ADD (tick_restart, NULL, cycles_until_except);
155 19 jeremybenn
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
156 561 julius
        SCHED_ADD (tick_raise_except, NULL, cycles_until_except);
157 19 jeremybenn
      break;
158
 
159
    case SPR_TTMR_SR:           /* One-shot timer */
160 561 julius
      if (tick_counting)
161 19 jeremybenn
        {
162 561 julius
          SCHED_ADD (tick_one_shot, NULL, cycles_until_except);
163 19 jeremybenn
          if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
164 561 julius
            SCHED_ADD (tick_raise_except, NULL, cycles_until_except);
165 19 jeremybenn
        }
166
      break;
167
 
168
    case SPR_TTMR_CR:           /* Continuos timer */
169
      if ((ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
170 561 julius
        SCHED_ADD (tick_raise_except, NULL, cycles_until_except);
171 19 jeremybenn
    }
172
}
173
 
174
 
175
/*! Handles a write to the ttcr spr */
176
void
177
spr_write_ttcr (uorreg_t value)
178
{
179 561 julius
  cycle_count_at_tick_start = runtime.sim.cycles - value;
180 19 jeremybenn
 
181
  sched_timer_job (cpu_state.sprs[SPR_TTMR]);
182
}
183
 
184 561 julius
/*! prev_val is the *previous* value of SPR_TTMR.  The new one can be found in
185 19 jeremybenn
    cpu_state.sprs[SPR_TTMR] */
186
void
187
spr_write_ttmr (uorreg_t prev_val)
188
{
189
  uorreg_t value = cpu_state.sprs[SPR_TTMR];
190
 
191
  /* Code running on or1k can't set SPR_TTMR_IP so make sure it isn't */
192
  cpu_state.sprs[SPR_TTMR] &= ~SPR_TTMR_IP;
193
 
194
  /* If the timer was already disabled, ttcr should not be updated */
195 561 julius
  if (tick_counting)
196 19 jeremybenn
    {
197 561 julius
      cpu_state.sprs[SPR_TTCR] = runtime.sim.cycles - cycle_count_at_tick_start;
198 19 jeremybenn
    }
199
 
200 561 julius
  cycle_count_at_tick_start = runtime.sim.cycles - cpu_state.sprs[SPR_TTCR];
201 19 jeremybenn
 
202 561 julius
  tick_counting = value & SPR_TTMR_M;
203 19 jeremybenn
 
204 561 julius
  /* If TTCR==TTMR_TP when setting MR, we disable counting??
205
     I think this should be looked at - Julius */
206
  if ((tick_counting == SPR_TTMR_CR) &&
207 538 julius
      (cpu_state.sprs[SPR_TTCR] == (value & SPR_TTMR_TP)))
208 19 jeremybenn
    {
209 561 julius
      tick_counting = 0;
210 19 jeremybenn
    }
211
 
212
  sched_timer_job (prev_val);
213
}
214
 
215
uorreg_t
216
spr_read_ttcr ()
217
{
218
  uorreg_t ret;
219
 
220 561 julius
  if (!tick_counting)
221 19 jeremybenn
    {
222 561 julius
      /* Report the time when the counter stopped (and don't carry on
223 19 jeremybenn
         counting) */
224
      ret = cpu_state.sprs[SPR_TTCR];
225
    }
226
  else
227
    {
228 561 julius
      ret = runtime.sim.cycles - cycle_count_at_tick_start;
229 19 jeremybenn
    }
230
 
231
  return  ret;
232
}

powered by: WebSVN 2.1.0

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