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

Subversion Repositories openrisc

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

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
static long long cycles_start = 0;
53
 
54
/*! Indicates if the timer is actually counting.  Needed to simulate one-shot
55
    mode correctly */
56
int tick_count;
57
 
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
  tick_count = 0;
70
}
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
  cycles_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 19 jeremybenn
  tick_count = 0;
104
}
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 538 julius
  uint32_t match_time = ttmr & SPR_TTMR_TP;
112
  uint32_t ttcr_period = spr_read_ttcr () & SPR_TTCR_CNT;
113 19 jeremybenn
 
114
  /* Remove previous jobs if they exists */
115
  if ((prev_ttmr & SPR_TTMR_IE) && !(ttmr & SPR_TTMR_IP))
116
    {
117
      SCHED_FIND_REMOVE (tick_raise_except, NULL);
118
    }
119
 
120
  switch (prev_ttmr & SPR_TTMR_M)
121
    {
122
    case SPR_TTMR_RT:
123
      SCHED_FIND_REMOVE (tick_restart, NULL);
124
      break;
125
 
126
    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
  else
136
    {
137
      match_time += (0xfffffffu - ttcr_period) + 1;
138
    }
139
 
140
  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
    }
166
}
167
 
168
 
169
/*! Handles a write to the ttcr spr */
170
void
171
spr_write_ttcr (uorreg_t value)
172
{
173
  cycles_start = runtime.sim.cycles - value;
174
 
175
  sched_timer_job (cpu_state.sprs[SPR_TTMR]);
176
}
177
 
178
/*! 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
{
183
  uorreg_t value = cpu_state.sprs[SPR_TTMR];
184
 
185
  /* 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
 
188
  /* If the timer was already disabled, ttcr should not be updated */
189
  if (tick_count)
190
    {
191
      cpu_state.sprs[SPR_TTCR] = runtime.sim.cycles - cycles_start;
192
    }
193
 
194
  cycles_start = runtime.sim.cycles - cpu_state.sprs[SPR_TTCR];
195
 
196
  tick_count = value & SPR_TTMR_M;
197
 
198
  if ((tick_count == 0xc0000000) &&
199 538 julius
      (cpu_state.sprs[SPR_TTCR] == (value & SPR_TTMR_TP)))
200 19 jeremybenn
    {
201
      tick_count = 0;
202
    }
203
 
204
  sched_timer_job (prev_val);
205
}
206
 
207
uorreg_t
208
spr_read_ttcr ()
209
{
210
  uorreg_t ret;
211
 
212
  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
  else
219
    {
220
      ret = runtime.sim.cycles - cycles_start;
221
    }
222
 
223
  return  ret;
224
}

powered by: WebSVN 2.1.0

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