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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code/] [lib-jtag/] [lib-jtag.c] - Blame information for rev 97

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 97 jeremybenn
/* lib-jtag.c. Basic test of Or1ksim library JTAG interface.
2
 
3
   Copyright (C) 1999-2006 OpenCores
4
   Copyright (C) 2010 Embecosm Limited
5
 
6
   Contributors various OpenCores participants
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
23
 
24
/* ----------------------------------------------------------------------------
25
   This code is commented throughout for use with Doxygen.
26
   --------------------------------------------------------------------------*/
27
 
28
#include <errno.h>
29
#include <stddef.h>
30
#include <stdlib.h>
31
#include <stdio.h>
32
#include <string.h>
33
 
34
#include "or1ksim.h"
35
 
36
 
37
/* --------------------------------------------------------------------------*/
38
/*!Dump a JTAG register
39
 
40
   Prefix with the supplied string and add a newline afterwards.
41
 
42
   @param[in] prefix     Prefix string to print out
43
   @param[in] jreg       The JTAG register
44
   @param[in] num_bytes  The number of bytes in the register                 */
45
/* --------------------------------------------------------------------------*/
46
static void
47
dump_jreg (const char    *prefix,
48
           unsigned char *jreg,
49
           int            num_bytes)
50
{
51
  int  i;
52
 
53
  printf ("%s: ", prefix);
54
 
55
  /* Dump each byte in turn */
56
  for (i = num_bytes - 1; i >=0; i--)
57
    {
58
      printf ("%02x", jreg[i]);
59
    }
60
 
61
  printf ("\n");
62
 
63
}       /* dump_jreg () */
64
 
65
 
66
/* --------------------------------------------------------------------------*/
67
/*!Convert a hex char into its value.
68
 
69
   @param[in] c  The char to convert
70
 
71
   @return  The value represented by the char, or -1 if it's not a valid
72
            char.                                                            */
73
/* --------------------------------------------------------------------------*/
74
static int
75
hexch2val (char  c)
76
{
77
  switch (c)
78
    {
79
    case '0': return  0;
80
    case '1': return  1;
81
    case '2': return  2;
82
    case '3': return  3;
83
    case '4': return  4;
84
    case '5': return  5;
85
    case '6': return  6;
86
    case '7': return  7;
87
    case '8': return  8;
88
    case '9': return  9;
89
 
90
    case 'a': case 'A': return 10;
91
    case 'b': case 'B': return 11;
92
    case 'c': case 'C': return 12;
93
    case 'd': case 'D': return 13;
94
    case 'e': case 'E': return 14;
95
    case 'f': case 'F': return 15;
96
 
97
    default:
98
      return  -1;
99
    }
100
}       /* hexch2val () */
101
 
102
 
103
/* --------------------------------------------------------------------------*/
104
/*!Shift a JTAG register.
105
 
106
   Almost all this code is common between the instruction and data
107
   registers. All that varies is the library function called and the error
108
   message if anything goes wrong. So we common things up here.
109
 
110
   @param[in] type       'D' if this is a data register, 'I' if an instruction
111
                         register.
112
   @param[in] next_jreg  Offset into argv of the next JTAG register hex
113
                         string.
114
   @param[in] argc       argc from the main program (for checking next_jref).
115
   @param[in] argv       argv from the main program.
116
 
117
   @return  1 (TRUE) on success, 0 (FALSE) on failure.                       */
118
/* --------------------------------------------------------------------------*/
119
static int
120
process_jreg (const char  type,
121
              int         next_jreg,
122
              int         argc,
123
              char       *argv[])
124
{
125
  const char *long_name = ('D' == type) ? "data" : "instruction";
126
 
127
  /* Do we have the arg? */
128
  if (next_jreg > argc)
129
    {
130
      printf ("ERROR: no %s register found.\n", long_name);
131
      return  0;
132
    }
133
 
134
  /* Is the reg an exact number of bytes? */
135
  char *hex_str   = argv[next_jreg];
136
  int   num_chars = strlen (hex_str);
137
 
138
  if (0 != (num_chars % 2))
139
    {
140
      printf ("ERROR: %s register not exact number of bytes.\n", long_name);
141
      return  0;
142
    }
143
 
144
  /* Allocate space */
145
  int            num_bytes = num_chars / 2;
146
  unsigned char *jreg      = malloc (num_bytes);
147
 
148
  if (NULL == jreg)
149
    {
150
      printf ("ERROR: malloc for %s register failed.\n", long_name);
151
      return  0;
152
    }
153
 
154
  /* Initialize the register. The hex presentation is MS byte of the string on
155
     the left (i.e. at offset 0), but the internal representation is LS byte
156
     at the lowest address. */
157
  int  i;
158
 
159
  for (i = 0; i < num_bytes; i++)
160
    {
161
      int  byte_off = num_bytes - i - 1;
162
      int  ch_off   = i * 2;
163
      int  j;
164
 
165
      /* Each nybble in turn */
166
      for (j = 0; j < 2; j++)
167
        {
168
          char  c     = hex_str[ch_off + j];
169
          int   c_val = hexch2val (c);
170
 
171
          if (c_val < 0)
172
            {
173
              printf ("ERROR: %c not valid hex digit.\n", c);
174
              free (jreg);
175
              return  0;
176
            }
177
 
178
          jreg[byte_off] <<= 4;
179
          jreg[byte_off]  |= c_val;
180
        }
181
    }
182
 
183
  /* Note what we are doing */
184
  dump_jreg ("  shifting in", jreg, num_bytes);
185
 
186
  double  t;
187
 
188
  if ('D' == type)
189
    {
190
      t = or1ksim_jtag_shift_dr (jreg);
191
    }
192
  else
193
    {
194
      t = or1ksim_jtag_shift_ir (jreg);
195
    }
196
 
197
  dump_jreg ("  shifted out", jreg, num_bytes);
198
  printf ("  time taken %.12fs\n", t);
199
 
200
  free (jreg);
201
  return  1;                    /* Completed successfully */
202
 
203
}       /* process_jreg () */
204
 
205
 
206
/* --------------------------------------------------------------------------*/
207
/*!Main program
208
 
209
   Build an or1ksim program using the library which loads a program and config
210
   from the command line which will drive JTAG.
211
 
212
   lib-jtag <config-file> <image> <jtype> [<reg>] [<jtype> [<reg>]] ...
213
 
214
   - config-file  An Or1ksim configuration file.
215
   - image        A OpenRISC binary image to load into Or1ksim
216
   - jtype        One of 'R' (JTAG reset), 'I' (JTAG instruction register) or
217
                  'D' (JTAG data register).
218
   - reg          If jtype is 'D' or 'I', a JTAG register specified in
219
                  hex. Must be an even number of digits (i.e. exact number of
220
                  bytes), and use leading zeros if null bytes are needed at
221
                  the MS end.
222
 
223
   The target program is run in bursts of 1ms execution, and the type of
224
   return (OK, hit breakpoint) noted. Between each burst of execution, the
225
   next register is submitted to the corresponding Or1ksim JTAG interface
226
   function, and the resulting register (for 'I' and 'D') noted.
227
 
228
   @param[in] argc  Number of elements in argv
229
   @param[in] argv  Vector of program name and arguments
230
 
231
   @return  Return code for the program.                                     */
232
/* --------------------------------------------------------------------------*/
233
int
234
main (int   argc,
235
      char *argv[])
236
{
237
  /* Check we have minimum number of args. */
238
  if (argc < 4)
239
    {
240
      printf ("usage: lib-jtag <config-file> <image> <jtype> <reg> [<jtype> "
241
              "<reg>] ...\n");
242
      return  1;
243
    }
244
 
245
  /* Initialize the program. Put the initialization message afterwards, or it
246
     will get swamped by the Or1ksim header. */
247
  if (0 == or1ksim_init (argv[1], argv[2], NULL, NULL, NULL))
248
    {
249
      printf ("Initalization succeeded.\n");
250
    }
251
  else
252
    {
253
      printf ("Initalization failed.\n");
254
      return  1;
255
    }
256
 
257
  /* Run repeatedly for 1 millisecond until we have processed all JTAG
258
     registers */
259
  int  next_jreg = 3;                   /* Offset to next JTAG register */
260
 
261
  do
262
    {
263
      switch (or1ksim_run (1.0e-3))
264
        {
265
        case OR1KSIM_RC_OK:
266
          printf ("Execution step completed OK.\n");
267
          break;
268
 
269
        case OR1KSIM_RC_BRKPT:
270
          printf ("Execution step completed with breakpoint.\n");
271
          break;
272
 
273
        default:
274
          printf ("ERROR: run failed.\n");
275
          return  1;
276
        }
277
 
278
      /* Process the next arg appropriately. */
279
      switch (argv[next_jreg++][0])
280
        {
281
        case 'R':
282
          printf ("Resetting JTAG.\n");
283
          or1ksim_jtag_reset ();
284
          break;
285
 
286
        case 'I':
287
          printf ("Shifting instruction register.\n");
288
 
289
          if (!process_jreg ('I', next_jreg++, argc, argv))
290
            {
291
              return  1;                /* Something went wrong */
292
            }
293
 
294
          break;
295
 
296
        case 'D':
297
          printf ("Shifting data register.\n");
298
 
299
          if (!process_jreg ('D', next_jreg++, argc, argv))
300
            {
301
              return  1;                /* Something went wrong */
302
            }
303
 
304
          break;
305
 
306
        default:
307
          printf ("ERROR: unknown JTAG request type.\n");
308
          return  1;
309
        }
310
    }
311
  while (next_jreg < argc);
312
 
313
  /* A little longer to allow response to last upcall to be handled. */
314
  switch (or1ksim_run (1.0e-3))
315
    {
316
    case OR1KSIM_RC_OK:
317
      printf ("Execution step completed OK.\n");
318
      break;
319
 
320
    case OR1KSIM_RC_BRKPT:
321
      printf ("Execution step completed with breakpoint.\n");
322
      break;
323
 
324
    default:
325
      printf ("ERROR: run failed.\n");
326
      return  1;
327
    }
328
 
329
  printf ("Test completed successfully.\n");
330
  return  0;
331
 
332
}       /* main () */

powered by: WebSVN 2.1.0

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