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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code/] [lib-jtag/] [lib-jtag.c] - Diff between revs 98 and 220

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

Rev 98 Rev 220
/* lib-jtag.c. Basic test of Or1ksim library JTAG interface.
/* lib-jtag.c. Basic test of Or1ksim library JTAG interface.
 
 
   Copyright (C) 1999-2006 OpenCores
   Copyright (C) 1999-2006 OpenCores
   Copyright (C) 2010 Embecosm Limited
   Copyright (C) 2010 Embecosm Limited
 
 
   Contributors various OpenCores participants
   Contributors various OpenCores participants
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
   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 it
   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
   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)
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.
   any later version.
 
 
   This program is distributed in the hope that it will be useful, but WITHOUT
   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
   more details.
 
 
   You should have received a copy of the GNU General Public License along
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
 
 
/* ----------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
   This code is commented throughout for use with Doxygen.
   This code is commented throughout for use with Doxygen.
   --------------------------------------------------------------------------*/
   --------------------------------------------------------------------------*/
 
 
#include <errno.h>
#include <errno.h>
#include <stddef.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
 
 
#include "or1ksim.h"
#include "or1ksim.h"
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Dump a JTAG register
/*!Dump a JTAG register
 
 
   Prefix with the supplied string and add a newline afterwards.
   Prefix with the supplied string and add a newline afterwards.
 
 
   @param[in] prefix     Prefix string to print out
   @param[in] prefix     Prefix string to print out
   @param[in] jreg       The JTAG register
   @param[in] jreg       The JTAG register
   @param[in] num_bytes  The number of bytes in the register                 */
   @param[in] num_bytes  The number of bytes in the register                 */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
dump_jreg (const char    *prefix,
dump_jreg (const char    *prefix,
           unsigned char *jreg,
           unsigned char *jreg,
           int            num_bytes)
           int            num_bytes)
{
{
  int  i;
  int  i;
 
 
  printf ("%s: ", prefix);
  printf ("%s: ", prefix);
 
 
  /* Dump each byte in turn */
  /* Dump each byte in turn */
  for (i = num_bytes - 1; i >=0; i--)
  for (i = num_bytes - 1; i >=0; i--)
    {
    {
      printf ("%02x", jreg[i]);
      printf ("%02x", jreg[i]);
    }
    }
 
 
  printf ("\n");
  printf ("\n");
 
 
}       /* dump_jreg () */
}       /* dump_jreg () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Convert a hex char into its value.
/*!Convert a hex char into its value.
 
 
   @param[in] c  The char to convert
   @param[in] c  The char to convert
 
 
   @return  The value represented by the char, or -1 if it's not a valid
   @return  The value represented by the char, or -1 if it's not a valid
            char.                                                            */
            char.                                                            */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
hexch2val (char  c)
hexch2val (char  c)
{
{
  switch (c)
  switch (c)
    {
    {
    case '0': return  0;
    case '0': return  0;
    case '1': return  1;
    case '1': return  1;
    case '2': return  2;
    case '2': return  2;
    case '3': return  3;
    case '3': return  3;
    case '4': return  4;
    case '4': return  4;
    case '5': return  5;
    case '5': return  5;
    case '6': return  6;
    case '6': return  6;
    case '7': return  7;
    case '7': return  7;
    case '8': return  8;
    case '8': return  8;
    case '9': return  9;
    case '9': return  9;
 
 
    case 'a': case 'A': return 10;
    case 'a': case 'A': return 10;
    case 'b': case 'B': return 11;
    case 'b': case 'B': return 11;
    case 'c': case 'C': return 12;
    case 'c': case 'C': return 12;
    case 'd': case 'D': return 13;
    case 'd': case 'D': return 13;
    case 'e': case 'E': return 14;
    case 'e': case 'E': return 14;
    case 'f': case 'F': return 15;
    case 'f': case 'F': return 15;
 
 
    default:
    default:
      return  -1;
      return  -1;
    }
    }
}       /* hexch2val () */
}       /* hexch2val () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Shift a JTAG register.
/*!Shift a JTAG register.
 
 
   Almost all this code is common between the instruction and data
   Almost all this code is common between the instruction and data
   registers. All that varies is the library function called and the error
   registers. All that varies is the library function called and the error
   message if anything goes wrong. So we common things up here.
   message if anything goes wrong. So we common things up here.
 
 
   @param[in] type       'D' if this is a data register, 'I' if an instruction
   @param[in] type       'D' if this is a data register, 'I' if an instruction
                         register.
                         register.
   @param[in] next_jreg  Offset into argv of the next JTAG register length
   @param[in] next_jreg  Offset into argv of the next JTAG register length
                         field.
                         field.
   @param[in] argc       argc from the main program (for checking next_jref).
   @param[in] argc       argc from the main program (for checking next_jref).
   @param[in] argv       argv from the main program.
   @param[in] argv       argv from the main program.
 
 
   @return  1 (TRUE) on success, 0 (FALSE) on failure.                       */
   @return  1 (TRUE) on success, 0 (FALSE) on failure.                       */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
process_jreg (const char  type,
process_jreg (const char  type,
              int         next_jreg,
              int         next_jreg,
              int         argc,
              int         argc,
              char       *argv[])
              char       *argv[])
{
{
  const char *long_name = ('D' == type) ? "data" : "instruction";
  const char *long_name = ('D' == type) ? "data" : "instruction";
 
 
  /* Do we have the arg (length and value)? */
  /* Do we have the arg (length and value)? */
  if ((next_jreg + 1) > argc)
  if ((next_jreg + 1) > argc)
    {
    {
      printf ("ERROR: no %s register found.\n", long_name);
      printf ("ERROR: no %s register found.\n", long_name);
      return  0;
      return  0;
    }
    }
 
 
  /* Get the length field */
  /* Get the length field */
  int  bit_len = strtol (argv[next_jreg++], NULL, 0);
  int  bit_len = strtol (argv[next_jreg++], NULL, 0);
 
 
  if (0 == bit_len)
  if (0 == bit_len)
    {
    {
      printf ("ERROR: invalid register length\n");
      printf ("ERROR: invalid register length\n");
      return  0;
      return  0;
    }
    }
 
 
  /* Is the reg an exact number of bytes? */
  /* Is the reg an exact number of bytes? */
  char *hex_str   = argv[next_jreg];
  char *hex_str   = argv[next_jreg];
  int   num_chars = strlen (hex_str);
  int   num_chars = strlen (hex_str);
  int   num_bytes = (bit_len + 7) / 8;
  int   num_bytes = (bit_len + 7) / 8;
 
 
  if (num_chars > (2 * num_bytes))
  if (num_chars > (2 * num_bytes))
    {
    {
      printf ("Warning: Too many digits for register: truncated.\n");
      printf ("Warning: Too many digits for register: truncated.\n");
    }
    }
 
 
  /* Allocate and clear space */
  /* Allocate and clear space */
  unsigned char *jreg = malloc (num_bytes);
  unsigned char *jreg = malloc (num_bytes);
 
 
  if (NULL == jreg)
  if (NULL == jreg)
    {
    {
      printf ("ERROR: malloc for %s register failed.\n", long_name);
      printf ("ERROR: malloc for %s register failed.\n", long_name);
      return  0;
      return  0;
    }
    }
 
 
  memset (jreg, 0, num_bytes);
  memset (jreg, 0, num_bytes);
 
 
  /* Initialize the register. The hex presentation is MS byte of the string on
  /* Initialize the register. The hex presentation is MS byte of the string on
     the left (i.e. at offset 0), but the internal representation is LS byte
     the left (i.e. at offset 0), but the internal representation is LS byte
     at the lowest address. */
     at the lowest address. */
  int  i;
  int  i;
 
 
  for (i = num_chars - 1; i >= 0; i--)
  for (i = num_chars - 1; i >= 0; i--)
    {
    {
      int  dig_num  = num_chars - 1 - i;        /* Which digit */
      int  dig_num  = num_chars - 1 - i;        /* Which digit */
      int  dig_val  = hexch2val (hex_str[i]);
      int  dig_val  = hexch2val (hex_str[i]);
 
 
      if (dig_val < 0)
      if (dig_val < 0)
        {
        {
          printf ("ERROR: %c not valid hex digit.\n", hex_str[i]);
          printf ("ERROR: %c not valid hex digit.\n", hex_str[i]);
          free (jreg);
          free (jreg);
          return  0;
          return  0;
        }
        }
 
 
      /* MS digits are the odd numbered ones */
      /* MS digits are the odd numbered ones */
      jreg[dig_num / 2] |= (0 == (dig_num % 2)) ? dig_val : dig_val << 4;
      jreg[dig_num / 2] |= (0 == (dig_num % 2)) ? dig_val : dig_val << 4;
    }
    }
 
 
  /* Note what we are doing */
  /* Note what we are doing */
  dump_jreg ("  shifting in", jreg, num_bytes);
  dump_jreg ("  shifting in", jreg, num_bytes);
 
 
  double  t;
  double  t;
 
 
  if ('D' == type)
  if ('D' == type)
    {
    {
      t = or1ksim_jtag_shift_dr (jreg, bit_len);
      t = or1ksim_jtag_shift_dr (jreg, bit_len);
    }
    }
  else
  else
    {
    {
      t = or1ksim_jtag_shift_ir (jreg, bit_len);
      t = or1ksim_jtag_shift_ir (jreg, bit_len);
    }
    }
 
 
  dump_jreg ("  shifted out", jreg, num_bytes);
  dump_jreg ("  shifted out", jreg, num_bytes);
  printf ("  time taken %.12fs\n", t);
  printf ("  time taken %.12fs\n", t);
 
 
  free (jreg);
  free (jreg);
  return  1;                    /* Completed successfully */
  return  1;                    /* Completed successfully */
 
 
}       /* process_jreg () */
}       /* process_jreg () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Main program
/*!Main program
 
 
   Build an or1ksim program using the library which loads a program and config
   Build an or1ksim program using the library which loads a program and config
   from the command line which will drive JTAG.
   from the command line which will drive JTAG.
 
 
   lib-jtag <config-file> <image> <jtype> [<bitlen> <reg>]
   lib-jtag <config-file> <image> <jtype> [<bitlen> <reg>]
            [<jtype> [<bitlen> <reg>]] ...
            [<jtype> [<bitlen> <reg>]] ...
 
 
   - config-file  An Or1ksim configuration file.
   - config-file  An Or1ksim configuration file.
   - image        A OpenRISC binary image to load into Or1ksim
   - image        A OpenRISC binary image to load into Or1ksim
   - jtype        One of 'R' (JTAG reset), 'I' (JTAG instruction register) or
   - jtype        One of 'R' (JTAG reset), 'I' (JTAG instruction register) or
                  'D' (JTAG data register).
                  'D' (JTAG data register).
   - bitlen       If jtype is 'D' or 'I', the number of bits in the JTAG
   - bitlen       If jtype is 'D' or 'I', the number of bits in the JTAG
                  register.
                  register.
   - reg          If jtype is 'D' or 'I', a JTAG register specified in
   - reg          If jtype is 'D' or 'I', a JTAG register specified in
                  hex. Specified LS digit on the right, and leading zeros may
                  hex. Specified LS digit on the right, and leading zeros may
                  be omitted.
                  be omitted.
 
 
   The target program is run in bursts of 1ms execution, and the type of
   The target program is run in bursts of 1ms execution, and the type of
   return (OK, hit breakpoint) noted. Between each burst of execution, the
   return (OK, hit breakpoint) noted. Between each burst of execution, the
   next register is submitted to the corresponding Or1ksim JTAG interface
   next register is submitted to the corresponding Or1ksim JTAG interface
   function, and the resulting register (for 'I' and 'D') noted.
   function, and the resulting register (for 'I' and 'D') noted.
 
 
   @param[in] argc  Number of elements in argv
   @param[in] argc  Number of elements in argv
   @param[in] argv  Vector of program name and arguments
   @param[in] argv  Vector of program name and arguments
 
 
   @return  Return code for the program.                                     */
   @return  Return code for the program.                                     */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
int
int
main (int   argc,
main (int   argc,
      char *argv[])
      char *argv[])
{
{
  /* Check we have minimum number of args. */
  /* Check we have minimum number of args. */
  if (argc < 4)
  if (argc < 4)
    {
    {
      printf ("usage: lib-jtag <config-file> <image> <jtype> [<bitlen> <reg>] "
      printf ("usage: lib-jtag <config-file> <image> <jtype> [<bitlen> <reg>] "
              "[<jtype> [<bitlen> <reg>]] ...\n");
              "[<jtype> [<bitlen> <reg>]] ...\n");
      return  1;
      return  1;
    }
    }
 
 
 
  /* 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
  /* Initialize the program. Put the initialization message afterwards, or it
     will get swamped by the Or1ksim header. */
     will get swamped by the Or1ksim header. */
  if (0 == or1ksim_init (argv[1], argv[2], NULL, NULL, NULL))
  if (0 == or1ksim_init (dummy_argc, dummy_argv, NULL, NULL, NULL))
    {
    {
      printf ("Initalization succeeded.\n");
      printf ("Initalization succeeded.\n");
    }
    }
  else
  else
    {
    {
      printf ("Initalization failed.\n");
      printf ("Initalization failed.\n");
      return  1;
      return  1;
    }
    }
 
 
  /* Run repeatedly for 1 millisecond until we have processed all JTAG
  /* Run repeatedly for 1 millisecond until we have processed all JTAG
     registers */
     registers */
  int  next_jreg = 3;                   /* Offset to next JTAG register */
  int  next_jreg = 3;                   /* Offset to next JTAG register */
 
 
  do
  do
    {
    {
      switch (or1ksim_run (1.0e-3))
      switch (or1ksim_run (1.0e-3))
        {
        {
        case OR1KSIM_RC_OK:
        case OR1KSIM_RC_OK:
          printf ("Execution step completed OK.\n");
          printf ("Execution step completed OK.\n");
          break;
          break;
 
 
        case OR1KSIM_RC_BRKPT:
        case OR1KSIM_RC_BRKPT:
          printf ("Execution step completed with breakpoint.\n");
          printf ("Execution step completed with breakpoint.\n");
          break;
          break;
 
 
        default:
        default:
          printf ("ERROR: run failed.\n");
          printf ("ERROR: run failed.\n");
          return  1;
          return  1;
        }
        }
 
 
      /* Process the next arg appropriately. */
      /* Process the next arg appropriately. */
      switch (argv[next_jreg++][0])
      switch (argv[next_jreg++][0])
        {
        {
        case 'R':
        case 'R':
          printf ("Resetting JTAG.\n");
          printf ("Resetting JTAG.\n");
          or1ksim_jtag_reset ();
          or1ksim_jtag_reset ();
          break;
          break;
 
 
        case 'I':
        case 'I':
          printf ("Shifting instruction register.\n");
          printf ("Shifting instruction register.\n");
 
 
          if (process_jreg ('I', next_jreg, argc, argv))
          if (process_jreg ('I', next_jreg, argc, argv))
            {
            {
              next_jreg += 2;
              next_jreg += 2;
            }
            }
          else
          else
            {
            {
              return  1;                /* Something went wrong */
              return  1;                /* Something went wrong */
            }
            }
 
 
          break;
          break;
 
 
        case 'D':
        case 'D':
          printf ("Shifting data register.\n");
          printf ("Shifting data register.\n");
 
 
          if (process_jreg ('D', next_jreg, argc, argv))
          if (process_jreg ('D', next_jreg, argc, argv))
            {
            {
              next_jreg += 2;
              next_jreg += 2;
            }
            }
          else
          else
            {
            {
              return  1;                /* Something went wrong */
              return  1;                /* Something went wrong */
            }
            }
 
 
          break;
          break;
 
 
        default:
        default:
          printf ("ERROR: unknown JTAG request type.\n");
          printf ("ERROR: unknown JTAG request type.\n");
          return  1;
          return  1;
        }
        }
    }
    }
  while (next_jreg < argc);
  while (next_jreg < argc);
 
 
  /* A little longer to allow response to last upcall to be handled. */
  /* A little longer to allow response to last upcall to be handled. */
  switch (or1ksim_run (1.0e-3))
  switch (or1ksim_run (1.0e-3))
    {
    {
    case OR1KSIM_RC_OK:
    case OR1KSIM_RC_OK:
      printf ("Execution step completed OK.\n");
      printf ("Execution step completed OK.\n");
      break;
      break;
 
 
    case OR1KSIM_RC_BRKPT:
    case OR1KSIM_RC_BRKPT:
      printf ("Execution step completed with breakpoint.\n");
      printf ("Execution step completed with breakpoint.\n");
      break;
      break;
 
 
    default:
    default:
      printf ("ERROR: run failed.\n");
      printf ("ERROR: run failed.\n");
      return  1;
      return  1;
    }
    }
 
 
  printf ("Test completed successfully.\n");
  printf ("Test completed successfully.\n");
  return  0;
  return  0;
 
 
}       /* main () */
}       /* main () */
 
 

powered by: WebSVN 2.1.0

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