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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [tick/] [tick.c] - Diff between revs 1429 and 1765

Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

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