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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/or1ksim/testsuite
    from Rev 432 to Rev 433
    Reverse comparison

Rev 432 → Rev 433

/test-code-or1k/int-logger/int-logger.c
0,0 → 1,185
/* int-logger.c. Test of Or1ksim handling of interrupts
 
Copyright (C) 2010 Embecosm Limited
 
Contributors various OpenCores participants
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
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 3 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, see <http: www.gnu.org/licenses/>. */
 
/* ----------------------------------------------------------------------------
This code is commented throughout for use with Doxygen.
--------------------------------------------------------------------------*/
 
#include "support.h"
#include "spr-defs.h"
#include "board.h"
 
 
/* --------------------------------------------------------------------------*/
/*!Write a memory mapped register
 
@param[in] addr Memory mapped address
@param[in] value Value to set */
/* --------------------------------------------------------------------------*/
static void
setreg (unsigned long addr,
unsigned char value)
{
*((volatile unsigned char *) addr) = value;
 
} /* setreg () */
 
 
/* --------------------------------------------------------------------------*/
/*!Read a memory mapped register
 
@param[in] addr Memory mapped address
 
@return Value read */
/* --------------------------------------------------------------------------*/
unsigned long
getreg (unsigned long addr)
{
return *((volatile unsigned char *) addr);
 
} /* getreg () */
 
 
/* --------------------------------------------------------------------------*/
/*!Count the number of ones in a register
 
SIMD Within A Register (SWAR) algorithm from Aggregate Magic Algorithms
(http://aggregate.org/MAGIC/) from the University of Kentucky.
 
32-bit recursive reduction using SWAR. First step is mapping 2-bit
values into sum of 2 1-bit values in sneaky way.
 
@param[in] x The 32-bit register whose bits are to be counted.
 
@return The number of bits that are set to 1. */
/* --------------------------------------------------------------------------*/
static int
ones32 (unsigned long int x)
{
x -= ((x >> 1) & 0x55555555);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0f0f0f0f);
x += (x >> 8);
x += (x >> 16);
 
return (x & 0x0000003f);
 
} /* ones32 () */
 
/* --------------------------------------------------------------------------*/
/*!Count the number of ones in a register
 
SIMD Within A Register (SWAR) algorithm from Aggregate Magic Algorithms
(http://aggregate.org/MAGIC/) from the University of Kentucky.
 
Compute the log to base 2 of a supplied numger. In this case we know it will
be an exact power of 2. We return -1 if asked for log (0).
 
@param[in] x The 32-bit register whose log to base 2 we want.
 
@return The log to base 2 of the argument, or -1 if the argument was
zero. */
/* --------------------------------------------------------------------------*/
static int
int_log2 (unsigned int x)
{
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
 
return ones32 (x) - 1;
 
} /* int_log2 () */
 
 
/* --------------------------------------------------------------------------*/
/*!Generic interrupt handler
 
This should receive the interrupt exception. Report the value in PICSR.
 
Potentially PICSR has multiple bits set, so we report the least significant
bit. This is consistent with an approach which gives highest priority to
any NMI lines (0 or 1).
 
It is up to the external agent to clear the interrupt. We prompt it by
writing the number of the interrupt we have just received. */
/* --------------------------------------------------------------------------*/
static void
interrupt_handler ()
{
unsigned long int picsr = mfspr (SPR_PICSR);
 
printf ("PICSR = 0x%08lx\n", picsr);
setreg (GENERIC_BASE, int_log2 (picsr & -picsr));
 
} /* interrupt_handler () */
 
 
/* --------------------------------------------------------------------------*/
/*!Main program to set up interrupt handler
 
We make a series of read upcalls, after 500 us and then every 1000us, which
prompt some interrupts being set and cleared. By doing this, our upcalls
should always be well clear of any calling function interrupt generation,
which is on millisecond boundaries.
 
A read upcall is a request to trigger an interrupt. We will subsequently
use a write upcall in the interrupt handler to request clearing of the
interrupt.
 
@return The return code from the program (always zero). */
/* --------------------------------------------------------------------------*/
int
main ()
{
printf ("Starting interrupt handler\n");
excpt_int = (unsigned long)interrupt_handler;
/* Enable interrupts */
printf ("Enabling interrupts.\n");
mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
mtspr (SPR_PICMR, 0xffffffff);
 
/* Loop forever, upcalling at the desired intervals. */
unsigned long int start = read_timer ();
 
while (1)
{
static long int end_time = 500;
 
while ((read_timer () - start) < end_time)
{
}
 
/* Read to request an interrupt */
(void)getreg (GENERIC_BASE);
 
/* Wait 1000us before next upcall. */
end_time += 1000;
}
 
/* We don't actually ever return */
return 0;
 
} /* main () */
test-code-or1k/int-logger/int-logger.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Index: test-code/lib-inttest/lib-inttest.c =================================================================== --- test-code/lib-inttest/lib-inttest.c (nonexistent) +++ test-code/lib-inttest/lib-inttest.c (revision 433) @@ -0,0 +1,285 @@ +/* lib-inttest.c. Test of Or1ksim library interrupt funcs. + + Copyright (C) 1999-2006 OpenCores + Copyright (C) 2010 Embecosm Limited + + Contributors various OpenCores participants + Contributor Jeremy Bennett + + 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 3 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, see . */ + +/* ---------------------------------------------------------------------------- + This code is commented throughout for use with Doxygen. + --------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "or1ksim.h" + + +/*! Number of interrupts in PIC */ +#define NUM_INTS 32 + +/*! Number of the PICSR SPR. */ +#define SPR_PICSR 0x4802 + +/*! Flag indicating if we are using level sensitive interrupts */ +static int level_sensitive_p; + +/*! Vector of interrupt numbers. */ +static int *intv; + +/*! Count of interrupts. */ +static int intc = 0; + +/*! Next interrupt */ +static int next_int = 0; + + +/* --------------------------------------------------------------------------*/ +/*!Read upcall + + Upcall from Or1ksim to read a word from an external peripheral. If called + this will trigger an interrupt. + + We may get an end case where we are asked for an interrupt, but have no + more to give. We silently ignore this - it is just due to allowing the + target program enough time to finish. + + @param[in] class_ptr A handle pass back from the initalization. Intended + for C++ callers, not used here. + @param[in] addr Address to read from. Ignored here. + @param[in] mask Byte mask for the read. Ignored here. + @param[out] rdata Buffer for the data read. Ignored here. + @param[in] data_len Number of bytes in mask and rdata. + + @return Zero on success, non-zero on failure. Always zero here. */ +/* --------------------------------------------------------------------------*/ +static int +read_upcall (void *class_ptr, + unsigned long int addr, + unsigned char mask[], + unsigned char rdata[], + int data_len) +{ + if (next_int < intc) + { + int inum = intv[next_int++]; + + printf ("Triggering interrupt %d\n", inum); + + if (level_sensitive_p) + { + or1ksim_interrupt_set (inum); + } + else + { + or1ksim_interrupt (inum); + } + } + + return 0; /* Success */ + +} /* read_upcall () */ + + +/* --------------------------------------------------------------------------*/ +/*!Write upcall + + Upcall from Or1ksim to write a word to an external peripheral. If called + this will clear an interrupt. The data is the number of the interrupt to + clear. + + @param[in] class_ptr A handle pass back from the initalization. Intended + for C++ callers, not used here. + @param[in] addr Address to write to. Ignored here. + @param[in] mask Byte mask for the write. Ignored here. + @param[in] wdata The data to write. Ignored here. + @param[in] data_len Number of bytes in mask and rdata. + + @return Zero on success, non-zero on failure. Always zero here. */ +/* --------------------------------------------------------------------------*/ +static int +write_upcall (void *class_ptr, + unsigned long int addr, + unsigned char mask[], + unsigned char wdata[], + int data_len) +{ + /* Extract the inum */ + int inum = wdata[0]; + + printf ("Clearing interrupt %d\n", inum); + + if (level_sensitive_p) + { + or1ksim_interrupt_clear (inum); + } + else + { + unsigned long int picsr; + + if (!or1ksim_read_spr (SPR_PICSR, &picsr)) + { + fprintf (stderr, "ERROR failed to read PICSR: Exiting.\n"); + exit (1); + } + + picsr &= ~(1UL << inum); + printf ("Cleared PICSR is 0x%08lx\n", picsr); + + if (!or1ksim_write_spr (SPR_PICSR, picsr)) + { + fprintf (stderr, "ERROR failed to write PICSR: Exiting.\n"); + exit (1); + } + } + + return 0; /* Success */ + +} /* write_upcall () */ + + +/* --------------------------------------------------------------------------*/ +/*!Main program + + Build an or1ksim program using the library which loads a program and config + from the command line, and then drives interrupts. Usage: + + lib-inttest -l|-e ... + + is run continuously. It requests that the next interrupt event be + triggered by a read upcall. Clearing an interrupt occurs when a write + upcall is received. + + The third argument specifies whether the level senstive (-l) or edge + triggered (-e) mechanism should be used for setting and clearing + interrupts. + + @param[in] argc Number of elements in argv + @param[in] argv Vector of program name and arguments + + @return Return code for the program. */ +/* --------------------------------------------------------------------------*/ +int +main (int argc, + char *argv[]) +{ + const int INT_OFF = 4; /* Offset in argv of interrupts */ + int i; /* General counter */ + + /* Parse args */ + if (argc < (INT_OFF + 1)) + { + fprintf (stderr, + "usage: lib-inttest-level -l|-e " + " ...\n"); + return 1; + } + + /* What type of interrupt? */ + if (0 == strcmp ("-l", argv[3])) + { + level_sensitive_p = 1; + } + else if (0 == strcmp ("-e", argv[3])) + { + level_sensitive_p = 0; + } + else + { + fprintf (stderr, "ERROR: Must specify -l or -e: exiting\n"); + exit (1); + } + + /* Get all the interrupts sorted out into the vector. We hold them with one + greater than absolute value, so we can distinguish between +0 and -0. */ + intv = malloc ((argc - INT_OFF) * sizeof (int)); + + for (i = INT_OFF; i < argc; i++) + { + int inum = atoi (argv[i]); + + if ((inum <= 0) || (NUM_INTS <= inum)) + { + printf ("Warning: Invalid interrupt # %d to raise: Exiting.\n", inum); + exit (1); + } + + intv[i - INT_OFF] = inum; + } + + /* Global counters */ + intc = argc - INT_OFF; + next_int = 0; + + /* Dummy argv array to pass arguments to or1ksim_init. Varies depending on + whether an image file is specified. */ + int dummy_argc; + char *dummy_argv[5]; + + dummy_argv[0] = "libsim"; + dummy_argv[1] = "-q"; + dummy_argv[2] = "-f"; + dummy_argv[3] = argv[1]; + dummy_argv[4] = argv[2]; + + dummy_argc = 5; + + /* Initialize the program. Put the initialization message afterwards, or it + will get swamped by the Or1ksim header. */ + if (0 == or1ksim_init (dummy_argc, dummy_argv, NULL, &read_upcall, + &write_upcall)) + { + printf ("Initalization succeeded.\n"); + } + else + { + printf ("ERROR: Initalization failed.\n"); + free (intv); + exit (1); + } + + /* Run in bursts of 1ms until all interrupts have been set and cleared. */ + do + { + if (OR1KSIM_RC_OK != or1ksim_run (1.0e-3)) + { + printf ("ERROR: run failed\n"); + free (intv); + exit (1); + } + } + while (next_int < intc); + + /* One more burst to allow the device driver time to complete. */ + if (OR1KSIM_RC_OK != or1ksim_run (1.0e-3)) + { + printf ("ERROR: run failed\n"); + free (intv); + exit (1); + } + + /* All interrupts should have been handled. */ + free (intv); + + printf ("Test completed successfully.\n"); + return 0; + +} /* main () */
test-code/lib-inttest/lib-inttest.c Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property

powered by: WebSVN 2.1.0

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