URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [stable_0_1_x/] [or1ksim/] [tick/] [tick.c] - Rev 1771
Go to most recent revision | Compare with Previous | Blame | View Log
/* tick.c -- Simulation of OpenRISC 1000 tick timer Copyright (C) 1999 Damjan Lampret, lampret@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This is functional simulation of OpenRISC 1000 architectural tick timer. */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "config.h" #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #include "port.h" #include "arch.h" #include "abstract.h" #include "except.h" #include "tick.h" #include "spr_defs.h" #include "pic.h" #include "sprs.h" #include "sim-config.h" #include "sched.h" /* When did the timer start to count */ int cycles_start = 0; /* TT Count Register */ unsigned long ttcr; /* TT Mode Register */ unsigned long ttmr; /* Reset. It initializes TTCR register. */ void tick_reset() { if (config.sim.verbose) PRINTF("Resetting Tick Timer.\n"); mtspr(SPR_TTCR, 0); mtspr(SPR_TTMR, 0); } /* Job handler for tick timer */ void tick_job (int param) { int mode = (ttmr & SPR_TTMR_M) >> 30; /*debug (7, "tick_job%i, param %i\n", param, mode);*/ switch (mode) { case 1: if (!param) { sprs[SPR_TTCR] = ttcr = 0; cycles_start = runtime.sim.cycles - ttcr; SCHED_ADD(tick_job, 0, runtime.sim.cycles + (ttmr & SPR_TTMR_PERIOD) - ttcr); } case 2: if (ttmr & SPR_TTMR_IE) { setsprbits(SPR_TTMR, SPR_TTMR_IP, 1); /* be sure not to issue timer exception if an exception occured before it */ if (((mfspr(SPR_SR) & SPR_SR_TEE) == SPR_SR_TEE) && (!pending.valid)) except_handle(EXCEPT_TICK, mfspr(SPR_EEAR_BASE)); else /* If TEE is currently not set we have to pend tick exception by rescheduling. */ SCHED_ADD(tick_job, 1, runtime.sim.cycles + 1); } break; } } /* Starts the tick timer. This function is called by a write to ttcr spr register */ void spr_write_ttcr (unsigned long value) { unsigned mode = (ttmr & SPR_TTMR_M) >> 30; /*debug (7, "ttcr = %08x\n", value);*/ ttcr = value; /* Remove previous if it exists */ SCHED_FIND_REMOVE(tick_job, 0); SCHED_FIND_REMOVE(tick_job, 1); if (mode == 1 || mode == 2) { SCHED_ADD(tick_job, 0, runtime.sim.cycles + (ttmr & SPR_TTMR_PERIOD) - ttcr); cycles_start = runtime.sim.cycles - ttcr; } } void spr_write_ttmr (unsigned long value) { /*debug (7, "ttmr = %08x\n", value);*/ ttmr = value; /* Handle the modes properly. */ switch((ttmr & SPR_TTMR_M) >> 30) { case 0: /* Timer is disabled */ SCHED_FIND_REMOVE(tick_job, 0); SCHED_FIND_REMOVE(tick_job, 1); break; case 1: /* Timer should auto restart */ sprs[SPR_TTCR] = ttcr = 0; cycles_start = runtime.sim.cycles; SCHED_FIND_REMOVE(tick_job, 0); SCHED_FIND_REMOVE(tick_job, 1); SCHED_ADD(tick_job, 0, runtime.sim.cycles + (ttmr & SPR_TTMR_PERIOD) - ttcr); break; case 2: /* Stop the timer when match */ SCHED_FIND_REMOVE(tick_job, 0); SCHED_FIND_REMOVE(tick_job, 1); break; case 3: /* Timer keeps running -- do nothing*/ break; } } unsigned long spr_read_ttcr () { /*debug (7, "ttcr ---- %08x\n", runtime.sim.cycles - cycles_start);*/ return runtime.sim.cycles - cycles_start; }
Go to most recent revision | Compare with Previous | Blame | View Log