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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [generic.c] - Diff between revs 1751 and 1756

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1751 Rev 1756
Line 20... Line 20...
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 
/* This program is commented throughout in a fashion suitable for processing
/* This program is commented throughout in a fashion suitable for processing
   with Doxygen. */
   with Doxygen. */
 
 
 
 
/* This is functional simulation of any external peripheral. It's job is to
/* This is functional simulation of any external peripheral. It's job is to
 * trap accesses in a specific range, so that the simulator can drive an
 * trap accesses in a specific range, so that the simulator can drive an
 * external device.
 * external device.
 
 *
 
 * A note on endianess. All external communication is done using HOST
 
 * endianess. A set of functions are provided to convert between host and
 
 * model endianess (htoml, htoms, mtohl, mtohs).
 */
 */
 
 
/* Autoconf and/or portability configuration */
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
 
 
Line 74... Line 79...
  uint32_t size;                /* Address space size (bytes) */
  uint32_t size;                /* Address space size (bytes) */
 
 
};
};
 
 
 
 
 
/* Convert a 32-bit value from host to model endianess */
 
static unsigned long int
 
htoml (unsigned long int  host_val)
 
{
 
  unsigned char  model_array[4];
 
 
 
#ifdef OR32_BIG_ENDIAN
 
  model_array[0] = (host_val >> 24) & 0xff;
 
  model_array[1] = (host_val >> 16) & 0xff;
 
  model_array[2] = (host_val >>  8) & 0xff;
 
  model_array[3] = (host_val      ) & 0xff;
 
#else
 
  model_array[0] = (host_val      ) & 0xff;
 
  model_array[1] = (host_val >>  8) & 0xff;
 
  model_array[2] = (host_val >> 16) & 0xff;
 
  model_array[3] = (host_val >> 24) & 0xff;
 
#endif
 
 
 
  return *((unsigned long int *)model_array);
 
 
 
}       /* htoml () */
 
 
 
 
 
/* Convert a 16-bit value from host to model endianess */
 
static unsigned short int
 
htoms (unsigned short int  host_val)
 
{
 
  unsigned char  model_array[2];
 
 
 
#ifdef OR32_BIG_ENDIAN
 
  model_array[0] = (host_val >>  8) & 0xff;
 
  model_array[1] = (host_val      ) & 0xff;
 
#else
 
  model_array[0] = (host_val      ) & 0xff;
 
  model_array[1] = (host_val >>  8) & 0xff;
 
#endif
 
 
 
  return *((unsigned short int *)model_array);
 
 
 
}       /* htoms () */
 
 
 
 
 
/* Convert a 32-bit value from model to host endianess */
 
static unsigned long int
 
mtohl (unsigned long int  model_val)
 
{
 
  unsigned char     *model_array = (unsigned char *)(&model_val);
 
  unsigned long int  host_val;
 
 
 
#ifdef OR32_BIG_ENDIAN
 
  host_val =                   model_array[0];
 
  host_val = (host_val << 8) | model_array[1];
 
  host_val = (host_val << 8) | model_array[2];
 
  host_val = (host_val << 8) | model_array[3];
 
#else
 
  host_val =                   model_array[3];
 
  host_val = (host_val << 8) | model_array[2];
 
  host_val = (host_val << 8) | model_array[1];
 
  host_val = (host_val << 8) | model_array[0];
 
#endif
 
 
 
  return  host_val;
 
 
 
}       /* mtohl () */
 
 
 
 
 
/* Convert a 32-bit value from model to host endianess */
 
static unsigned short int
 
mtohs (unsigned short int  model_val)
 
{
 
  unsigned char      *model_array = (unsigned char *)(&model_val);
 
  unsigned short int  host_val;
 
 
 
#ifdef OR32_BIG_ENDIAN
 
  host_val =                   model_array[0];
 
  host_val = (host_val << 8) | model_array[1];
 
#else
 
  host_val =                   model_array[1];
 
  host_val = (host_val << 8) | model_array[0];
 
#endif
 
 
 
  return  host_val;
 
 
 
}       /* mtohs () */
 
 
 
 
/* Generic read and write upcall routines. Note the address here is absolute,
/* Generic read and write upcall routines. Note the address here is absolute,
   not relative to the device. */
   not relative to the device. The mask uses host endianess, not Or1ksim
 
   endianess. */
 
 
static unsigned long int
static unsigned long int
ext_read (unsigned long int addr, unsigned long int mask)
ext_read (unsigned long int  addr,
 
          unsigned long int  mask)
{
{
  return config.ext.read_up (config.ext.class_ptr, addr, mask);
  return config.ext.read_up (config.ext.class_ptr, addr, mask);
 
 
}                               /* ext_callback() */
}                               /* ext_callback() */
 
 
 
 
/* Generic read and write upcall routines. Note the address here is absolute,
/* Generic read and write upcall routines. Note the address here is absolute,
   not relative to the device. */
   not relative to the device. The mask and value use host endianess, not
 
   Or1ksim endianess. */
 
 
static void
static void
ext_write (unsigned long int addr,
ext_write (unsigned long int addr,
           unsigned long int mask, unsigned long int value)
           unsigned long int  mask,
 
           unsigned long int  value)
{
{
  config.ext.write_up (config.ext.class_ptr, addr, mask, value);
  config.ext.write_up (config.ext.class_ptr, addr, mask, value);
 
 
}                               /* ext_callback() */
}                               /* ext_callback() */
 
 
Line 119... Line 214...
    }
    }
  else
  else
    {
    {
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long bitoff = (fulladdr & 0x00000003) << 3;
      unsigned long  bytenum  = fulladdr & 0x00000003;
 
 
#ifdef OR32_BIG_ENDIAN
      uint8_t        mask_array[4];
      unsigned long mask = 0x000000ff << (24 - bitoff);
      unsigned long  res;
      unsigned long res = ext_read (wordaddr, mask);
      uint8_t       *res_array;
 
 
      return (uint8_t) ((res >> (24 - bitoff)) & 0x000000ff);
      /* This works whatever the host endianess */
#else
      memset (mask_array, 0, 4);
      unsigned long mask = 0x000000ff << bitoff;
      mask_array[bytenum] = 0xff;
      unsigned long res = ext_read (wordaddr, mask);
 
 
 
      return (uint8_t) ((res >> bitoff) & 0x00000ff);
      res       = ext_read (wordaddr, *((unsigned int *)mask_array));
#endif
      res_array = (uint8_t *)(&res);
 
 
 
      return  res_array[bytenum];
    }
    }
}                               /* generic_read_byte() */
}                               /* generic_read_byte() */
 
 
 
 
static void
static void
Line 154... Line 250...
    }
    }
  else
  else
    {
    {
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long bitoff = (fulladdr & 0x00000003) << 3;
 
 
 
#ifdef OR32_BIG_ENDIAN
      unsigned long  bytenum  = fulladdr & 0x00000003;
      unsigned long mask = 0x000000ff << (24 - bitoff);
      uint8_t        mask_array[4];
      unsigned long wordval = ((unsigned long int) value) << (24 - bitoff);
      uint8_t        value_array[4];
#else
 
      unsigned long mask = 0x000000ff << bitoff;
      /* This works whatever the host endianess */
      unsigned long wordval = ((unsigned long int) value) << bitoff;
      memset (mask_array, 0, 4);
#endif
      mask_array[bytenum] = 0xff;
 
      memset (value_array, 0, 4);
 
      value_array[bytenum] = value;
 
 
      ext_write (wordaddr, mask, wordval);
      ext_write (wordaddr, *((unsigned long int *)mask_array),
 
                 *((unsigned long int *)value_array));
    }
    }
}                               /* generic_write_byte() */
}                               /* generic_write_byte() */
 
 
 
 
 
/* Result is in model endianess */
static uint16_t
static uint16_t
generic_read_hw (oraddr_t addr, void *dat)
generic_read_hw (oraddr_t addr, void *dat)
{
{
  struct dev_generic *dev = (struct dev_generic *) dat;
  struct dev_generic *dev = (struct dev_generic *) dat;
 
 
Line 196... Line 295...
    }
    }
  else
  else
    {
    {
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long bitoff = (fulladdr & 0x00000003) << 3;
      unsigned long   bytenum  = fulladdr & 0x00000002;
 
 
#ifdef OR32_BIG_ENDIAN
      uint8_t         mask_array[4];
      unsigned long mask = 0x0000ffff << (16 - bitoff);
      unsigned long   res;
      unsigned long res = ext_read (wordaddr, mask);
      uint8_t        *res_array;
 
      uint8_t         hwres_array[2];
 
 
      return (uint16_t) ((res >> (16 - bitoff)) & 0x0000ffff);
      /* This works whatever the host endianess */
#else
      memset (mask_array, 0, 4);
      unsigned long mask = 0x0000ffff << bitoff;
      mask_array[bytenum]     = 0xff;
      unsigned long res = ext_read (wordaddr, mask);
      mask_array[bytenum + 1] = 0xff;
 
 
      return (uint16_t) ((res >> bitoff) & 0x0000ffff);
      res       = ext_read (wordaddr, *((unsigned int *)mask_array));
#endif
      res_array = (uint8_t *)(&res);
 
 
 
      hwres_array[0] = res_array[bytenum];
 
      hwres_array[1] = res_array[bytenum + 1];
 
 
 
      return htoms (*((uint16_t *)hwres_array));
    }
    }
}                               /* generic_read_hw() */
}                               /* generic_read_hw() */
 
 
 
 
 
/* Value is in model endianness */
static void
static void
generic_write_hw (oraddr_t addr, uint16_t value, void *dat)
generic_write_hw (oraddr_t addr, uint16_t value, void *dat)
{
{
  struct dev_generic *dev = (struct dev_generic *) dat;
  struct dev_generic *dev = (struct dev_generic *) dat;
 
 
Line 234... Line 340...
      fprintf (stderr,
      fprintf (stderr,
               "Unaligned half word write to 0x%" PRIxADDR " ignored\n", addr);
               "Unaligned half word write to 0x%" PRIxADDR " ignored\n", addr);
    }
    }
  else
  else
    {
    {
 
      uint16_t       host_value = mtohs (value);
 
 
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long wordaddr = fulladdr & 0xfffffffc;
      unsigned long bitoff = (fulladdr & 0x00000003) << 3;
      unsigned long  bytenum  = fulladdr & 0x00000002;
 
 
#ifdef OR32_BIG_ENDIAN
      uint8_t        mask_array[4];
      unsigned long mask = 0x0000ffff << (16 - bitoff);
      uint8_t        value_array[4];
      unsigned long wordval = ((unsigned long int) value) << (16 - bitoff);
      uint8_t       *hw_value_array;
#else
 
      unsigned long mask = 0x0000ffff << bitoff;
      /* This works whatever the host endianess */
      unsigned long wordval = ((unsigned long int) value) << bitoff;
      memset (mask_array, 0, 4);
#endif
      mask_array[bytenum]     = 0xff;
 
      mask_array[bytenum + 1] = 0xff;
 
 
 
      memset (value_array, 0, 4);
 
      hw_value_array           = (uint8_t *)(&host_value);
 
      value_array[bytenum]     = hw_value_array[0];
 
      value_array[bytenum + 1] = hw_value_array[1];
 
 
      ext_write (wordaddr, mask, wordval);
      ext_write (wordaddr, *((unsigned long int *)mask_array),
 
                 *((unsigned long int *)value_array));
    }
    }
}                               /* generic_write_hw() */
}                               /* generic_write_hw() */
 
 
 
 
static uint32_t
static uint32_t
Line 278... Line 393...
    }
    }
  else
  else
    {
    {
      unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
 
 
      return (uint32_t) ext_read (wordaddr, 0xffffffff);
      return (uint32_t) htoml (ext_read (wordaddr, 0xffffffff));
    }
    }
}                               /* generic_read_word() */
}                               /* generic_read_word() */
 
 
 
 
static void
static void
Line 304... Line 419...
      fprintf (stderr,
      fprintf (stderr,
               "Unaligned full word write to 0x%" PRIxADDR " ignored\n", addr);
               "Unaligned full word write to 0x%" PRIxADDR " ignored\n", addr);
    }
    }
  else
  else
    {
    {
 
      unsigned long host_value = mtohl (value);
      unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
      unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
 
 
      ext_write (wordaddr, 0xffffffff, value);
      ext_write (wordaddr, 0xffffffff, host_value);
    }
    }
}                               /* generic_write_word() */
}                               /* generic_write_word() */
 
 
 
 
/* Reset is a null operation */
/* Reset is a null operation */

powered by: WebSVN 2.1.0

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