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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [sysc/] [src/] [JtagDriverSC.cpp] - Blame information for rev 63

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

Line No. Rev Author Line
1 63 julius
// ----------------------------------------------------------------------------
2
 
3
// SystemC JTAG driver
4
 
5
// Copyright (C) 2008  Embecosm Limited <info@embecosm.com>
6
 
7
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
// This file is part of the cycle accurate model of the OpenRISC 1000 based
10
// system-on-chip, ORPSoC, built using Verilator.
11
 
12
// This program is free software: you can redistribute it and/or modify it
13
// under the terms of the GNU Lesser General Public License as published by
14
// the Free Software Foundation, either version 3 of the License, or (at your
15
// option) any later version.
16
 
17
// This program is distributed in the hope that it will be useful, but WITHOUT
18
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
20
// License for more details.
21
 
22
// You should have received a copy of the GNU Lesser General Public License
23
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 
25
// ----------------------------------------------------------------------------
26
 
27
// $Id: JtagDriverSC.cpp 317 2009-02-22 19:52:12Z jeremy $
28
 
29
#include <iostream>
30
#include <iomanip>
31
 
32
#include "JtagDriverSC.h"
33
 
34
 
35
SC_HAS_PROCESS (JtagDriverSC);
36
 
37
//! Constructor for the JTAG driver.
38
 
39
//! We create a SC_THREAD in which we can spit out some actions. Must be a
40
//! thread, since we need to wait for the actions to complete.
41
 
42
//! @param[in] name             Name of this module, passed to the parent
43
//!                             constructor. 
44
//! @param[in] _tapActionQueue  Pointer to fifo of actions to perform
45
 
46
JtagDriverSC::JtagDriverSC (sc_core::sc_module_name        name,
47
                            sc_core::sc_fifo<TapAction *> *_tapActionQueue) :
48
  sc_module (name),
49
  tapActionQueue (_tapActionQueue),
50
  currentScanChain (OR1K_SC_UNDEF)
51
{
52
  SC_THREAD (queueActions);
53
 
54
}       // JtagDriverSC ()
55
 
56
 
57
//! SystemC thread to queue some actions
58
 
59
//! Have to use a thread, since we will end up waiting for actions to
60
//! complete.
61
 
62
void
63
JtagDriverSC::queueActions ()
64
{
65
  uint32_t res;                 // General result variable
66
 
67
  // Reset the JTAG
68
  reset ();
69
 
70
  // Select the register scan chain to stall the processor, stall the
71
  // processor and check it has stalled
72
  selectChain (OR1K_SC_REGISTER);
73
  writeReg (OR1K_RSC_RISCOP, RISCOP_STALL);
74
 
75
  do
76
    {
77
      res = readReg (OR1K_RSC_RISCOP);
78
      std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000
79
                << "us: RISCOP = " << std::hex << res << std::endl;
80
    }
81
  while ((res & RISCOP_STALL) != RISCOP_STALL);
82
 
83
  // Write the NPC SPR. Select the RISC_DEBUG scan chain, read the
84
  // register, write the register and read it back.
85
  selectChain (OR1K_SC_RISC_DEBUG);
86
 
87
  res = readReg (0x10);                         // NPC
88
  std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000
89
            << "us: Old NPC = " << std::hex << res << std::endl;
90
 
91
  writeReg (0x10, 0x4000100);
92
 
93
  res = readReg (0x10);                         // NPC
94
  std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000
95
            << "us: New NPC = " << std::hex << res << std::endl;
96
 
97
  // Unstall and check it has unstalled
98
  selectChain (OR1K_SC_REGISTER);
99
  writeReg (OR1K_RSC_RISCOP, 0);
100
 
101
  do
102
    {
103
      res = readReg (OR1K_RSC_RISCOP);
104
      std::cout << sc_core::sc_time_stamp ().to_seconds () * 1000000
105
                << "us: RISCOP = " << std::hex << res << std::endl;
106
    }
107
  while ((res & RISCOP_STALL) == RISCOP_STALL);
108
 
109
}       // queueActions ()
110
 
111
 
112
//! Reset the JTAG
113
 
114
//! @note Must be called from a SystemC thread, because of the use of wait()
115
 
116
void
117
JtagDriverSC::reset ()
118
{
119
  sc_core::sc_event *actionDone = new sc_core::sc_event();
120
  TapActionReset    *resetAction;
121
 
122
  // Create and queue the reset action and wait for it to complete
123
  resetAction = new TapActionReset (actionDone);
124
  tapActionQueue->write (resetAction);
125
  wait (*actionDone);
126
 
127
  delete resetAction;
128
  delete actionDone;
129
 
130
}       // reset ()
131
 
132
 
133
//! Select an OpenRISC 1000 scan chain
134
 
135
//! Built on top of the JTAG commands to shift registers
136
//! We only do something if the scan chain needs to be changed.
137
//! - Shift-IR the CHAIN_SELECT instruction
138
//! - Shift-DR the specified chain
139
//! - Shift-IR the DEBUG instruction
140
 
141
//! @note Must be called from a SystemC thread, because of the use of wait()
142
 
143
//! @param[in] chain  The desired scan chain
144
 
145
 
146
void
147
JtagDriverSC::selectChain (int chain)
148
{
149
  if (chain == currentScanChain)
150
    {
151
      return;
152
    }
153
  else
154
    {
155
      currentScanChain = chain;
156
    }
157
 
158
  sc_core::sc_event *actionDone = new sc_core::sc_event();
159
  TapActionIRScan   *iRScan;
160
  TapActionDRScan   *dRScan;
161
 
162
  // Create and queue the IR-Scan action for CHAIN_SELECT (no CRC)
163
  iRScan = new TapActionIRScan (actionDone, CHAIN_SELECT_IR, JTAG_IR_LEN);
164
  tapActionQueue->write (iRScan);
165
  wait (*actionDone);
166
 
167
  delete iRScan;
168
 
169
  // Create and queue the DR-Scan action for the specified chain (which we
170
  // know will fit into 64 bits)
171
  uint64_t  chainReg = crc8 (chain, CHAIN_DR_LEN) << (CHAIN_DR_LEN) | chain;
172
  dRScan = new TapActionDRScan (actionDone, chainReg, CHAIN_DR_LEN + CRC_LEN);
173
  tapActionQueue->write (dRScan);
174
  wait (*actionDone);
175
 
176
  delete dRScan;
177
 
178
  // Create and queue the IR-Scan action for DEBUG (no CRC)
179
  iRScan      = new TapActionIRScan (actionDone, DEBUG_IR, JTAG_IR_LEN);
180
  tapActionQueue->write (iRScan);
181
  wait (*actionDone);
182
 
183
  delete iRScan;
184
  delete actionDone;
185
 
186
}       // selectChain()
187
 
188
 
189
//! Read an OpenRISC 1000 JTAG register
190
 
191
//! Built on top of the JTAG commands to shift registers
192
//! - Shift-DR the specified address with R/W field unset
193
//! - read out the data shifted out.
194
 
195
//! DR register fields depend on the scan chain in use. For SC_REGISTER:
196
//! -   [4:0] Address to read from
197
//! -     [5] 0 indicating read
198
//! -  [37:6] Unused
199
//! - [45:38] CRC (CRC-8-ATM)
200
 
201
//! For SC_RISC_DEBUG (i.e. SPRs) and SC_WISHBONE:
202
//! -  [31:0] Address to read from
203
//! -    [32] 0 indicating read
204
//! - [64:33] unused
205
//! - [72:65] CRC (CRC-8-ATM)
206
 
207
//! In general two Scan-DR loops are needed. The first will cause the value
208
//! associated with the address to be loaded into the shift register, the
209
//! second will actually shift that value out. So we use a subsidiary call to
210
//! do the read (::readReg1()). This allows a future extension, where a block
211
//! of registers are read efficiently by overlapping ScanDR actions.
212
 
213
//! We can also provide a variant of ::readReg1 () that is optimized for
214
//! "small" value.
215
 
216
//! @note Must be called from a SystemC thread, because of the use of wait()
217
 
218
//! @param[in] addr  The address of the register
219
 
220
//! @return  The register value read
221
 
222
uint32_t
223
JtagDriverSC::readReg (uint32_t  addr)
224
{
225
  bool  firstTime = true;
226
  int   bitSizeNoCrc;           // Size of reg w/o its CRC field
227
 
228
  // Determine the size of register to read.
229
  switch (currentScanChain)
230
    {
231
    case OR1K_SC_RISC_DEBUG:
232
      bitSizeNoCrc  = RISC_DEBUG_DR_LEN;
233
      break;
234
 
235
    case OR1K_SC_REGISTER:
236
      bitSizeNoCrc  = REGISTER_DR_LEN;
237
      break;
238
 
239
    case OR1K_SC_WISHBONE:
240
      bitSizeNoCrc  = WISHBONE_DR_LEN;
241
      break;
242
    }
243
 
244
  // Read the register twice. Use an optimized version if the register is
245
  // "small".
246
  if ((bitSizeNoCrc + CRC_LEN) < 64)
247
    {
248
      (void)readReg1 (addr, bitSizeNoCrc);
249
      return  readReg1 (addr, bitSizeNoCrc);
250
    }
251
  else
252
    {
253
      uint64_t *dReg = new uint64_t [(bitSizeNoCrc + CRC_LEN + 63) / 64];
254
      (void)readReg1 (dReg, addr, bitSizeNoCrc);
255
      uint32_t  res = readReg1 (dReg, addr, bitSizeNoCrc);
256
      delete [] dReg;
257
 
258
      return  res;
259
    }
260
}       // readReg ()
261
 
262
 
263
//! Single read of an OpenRISC 1000 JTAG register
264
 
265
//! Built on top of the JTAG commands to shift registers
266
//! - Shift-DR the specified address with R/W field unset
267
//! - read out the data shifted out.
268
 
269
//! This version is for "small" values represented as a uint64_t.
270
 
271
//! @note Must be called from a SystemC thread, because of the use of wait()
272
 
273
//! @param[in]     addr          The address to read
274
//! @param[in]     bitSizeNoCrc  Size of the register excluding its CRC field
275
 
276
//! @return  The register value read
277
 
278
uint32_t
279
JtagDriverSC::readReg1 (uint32_t   addr,
280
                        int        bitSizeNoCrc)
281
{
282
  // Useful fields and sizes and the register itself
283
  int                fullBitSize = bitSizeNoCrc + CRC_LEN;
284
  int                dataOffset  = bitSizeNoCrc - DR_DATA_LEN;
285
  uint64_t           dReg;
286
 
287
  // Allocate space for the shifted reg and a SystemC completion event
288
  sc_core::sc_event *actionDone  = new sc_core::sc_event();
289
 
290
  // Loop until CRCs match
291
  while (true)
292
    {
293
      // Create the data to shift in
294
      dReg  = 0ULL;
295
      dReg |= addr;
296
      uint8_t crc_in = crc8 (dReg, bitSizeNoCrc);
297
      dReg |= (uint64_t)crc_in << bitSizeNoCrc;
298
 
299
      // Prepare the action, queue it and wait for it to complete
300
      TapActionDRScan *dRScan = new TapActionDRScan (actionDone, dReg,
301
                                                     fullBitSize);
302
      tapActionQueue->write (dRScan);
303
      wait (*actionDone);
304
      dReg = dRScan->getDRegOut ();
305
      delete dRScan;
306
 
307
      // Check CRCs
308
      uint8_t  crc_out  = dReg >> bitSizeNoCrc;
309
      uint8_t  crc_calc = crc8 (dReg, bitSizeNoCrc);
310
 
311
      // All done if CRC matches
312
      if (crc_out == crc_calc)
313
        {
314
          delete    actionDone;
315
          return  (dReg >> dataOffset) & ((1ULL << DR_DATA_LEN) - 1);
316
        }
317
    }
318
}       // readReg1 ()
319
 
320
 
321
//! Single read of an OpenRISC 1000 JTAG register
322
 
323
//! Built on top of the JTAG commands to shift registers
324
//! - Shift-DR the specified address with R/W field unset
325
//! - read out the data shifted out.
326
 
327
//! This version is for "large" values represented as an array of uint64_t.
328
 
329
//! @note Must be called from a SystemC thread, because of the use of wait()
330
 
331
//! @param[in,out] dRegArray     The shift register to use
332
//! @param[in]     addr          The address to read
333
//! @param[in]     bitSizeNoCrc  Size of the register excluding its CRC field
334
 
335
//! @return  The register value read
336
 
337
uint32_t
338
JtagDriverSC::readReg1 (uint64_t  *dRegArray,
339
                        uint32_t   addr,
340
                        int        bitSizeNoCrc)
341
{
342
  // Useful fields and sizes
343
  int                fullBitSize = bitSizeNoCrc + CRC_LEN;
344
  int                dataOffset  = bitSizeNoCrc - DR_DATA_LEN;
345
 
346
  // Allocate a SystemC completion event
347
  sc_core::sc_event *actionDone  = new sc_core::sc_event();
348
 
349
  // Loop until CRCs match
350
  while (true)
351
    {
352
      // Create the data to shift in
353
      memset (dRegArray, 0, fullBitSize / 8);
354
      dRegArray[0] |= addr;
355
      uint8_t crc_in = crc8 (dRegArray, bitSizeNoCrc);
356
      insertBits (crc_in, CRC_LEN, dRegArray, bitSizeNoCrc);
357
 
358
      // Prepare the action, queue it and wait for it to complete
359
      TapActionDRScan *dRScan = new TapActionDRScan (actionDone, dRegArray,
360
                                                     fullBitSize);
361
      tapActionQueue->write (dRScan);
362
      wait (*actionDone);
363
      dRScan->getDRegOut (dRegArray);
364
      delete dRScan;
365
 
366
      // Check CRCs
367
      uint8_t  crc_out  = extractBits (dRegArray, bitSizeNoCrc, CRC_LEN);
368
      uint8_t  crc_calc = crc8 (dRegArray, bitSizeNoCrc);
369
 
370
      // All done if CRC matches
371
      if (crc_out == crc_calc)
372
        {
373
          delete  actionDone;
374
          return  extractBits (dRegArray, dataOffset, DR_DATA_LEN);
375
        }
376
    }
377
}       // readReg1 ()
378
 
379
 
380
//! Write an OpenRISC 1000 JTAG register
381
 
382
//! Built on top of the JTAG commands to shift registers
383
//! - Shift-DR the specified address with R/W field set and data to write
384
 
385
//! DR register fields depend on the scan chain in use. For SC_REGISTER:
386
//! -   [4:0] Address to write to
387
//! -     [5] 1 indicating write
388
//! -  [37:6] Value to write
389
//! - [45:38] CRC (CRC-8-ATM)
390
 
391
//! For SC_RISC_DEBUG (i.e. SPRs) and SC_WISHBONE:
392
//! -  [31:0] Address to write to
393
//! -    [32] 1 indicating write
394
//! - [64:33] Value to write
395
//! - [72:65] CRC (CRC-8-ATM)
396
 
397
//! @note Must be called from a SystemC thread, because of the use of wait()
398
 
399
//! @param[in] addr  The address of the register
400
//! @param[in] data  The register data to write
401
 
402
void
403
JtagDriverSC::writeReg (uint32_t  addr,
404
                        uint32_t  data)
405
{
406
  int       bitSizeNoCrc;               // Size of reg w/o its CRC field
407
  uint64_t  writeBit;                   // Mask for the write enable bit
408
 
409
  // Determine the size of register to write.
410
  switch (currentScanChain)
411
    {
412
    case OR1K_SC_RISC_DEBUG:
413
      bitSizeNoCrc  = RISC_DEBUG_DR_LEN;
414
      writeBit      = RISC_DEBUG_RW;
415
      break;
416
 
417
    case OR1K_SC_REGISTER:
418
      bitSizeNoCrc  = REGISTER_DR_LEN;
419
      writeBit      = REGISTER_RW;
420
      break;
421
 
422
    case OR1K_SC_WISHBONE:
423
      bitSizeNoCrc  = WISHBONE_DR_LEN;
424
      writeBit      = WISHBONE_RW;
425
      break;
426
    }
427
 
428
  // Create the register in an array
429
  int       wordSize = (bitSizeNoCrc + CRC_LEN + 63) / 64;
430
  uint64_t *dReg   = new uint64_t [wordSize];
431
 
432
  // Create the data to shift in
433
  memset (dReg, 0, wordSize * 8);
434
  dReg[0] |= writeBit | addr;
435
  insertBits (data, DR_DATA_LEN, dReg, bitSizeNoCrc - DR_DATA_LEN);
436
  insertBits (crc8 (dReg, bitSizeNoCrc), CRC_LEN, dReg, bitSizeNoCrc);
437
 
438
  // Prepare the action, queue it and wait for it to complete
439
  sc_core::sc_event *actionDone = new sc_core::sc_event();
440
  TapActionDRScan   *dRScan     = new TapActionDRScan (actionDone, dReg,
441
                                                       bitSizeNoCrc + CRC_LEN);
442
 
443
  tapActionQueue->write (dRScan);
444
  wait (*actionDone);
445
 
446
  delete [] dReg;
447
  delete dRScan;
448
  delete actionDone;
449
 
450
}       // writeReg ()
451
 
452
 
453
//! Compute CRC-8-ATM
454
 
455
//! The data is in a uint64_t, for which we use the first size bits to compute
456
//! the CRC.
457
 
458
//! @Note I am using the same algorithm as the ORPSoC debug unit, but I
459
//!       believe its function is broken! I don't believe the data bit should
460
//!       feature in the computation of bits 2 & 1 of the new CRC.
461
 
462
//! @Note I've realized that this is an algorithm for LSB first, so maybe it
463
//!       is correct!
464
 
465
//! @param data  The data whose CRC is desired
466
//! @param size  The number of bits in the data
467
 
468
uint8_t
469
JtagDriverSC::crc8 (uint64_t  data,
470
                    int       size)
471
{
472
  uint8_t    crc = 0;
473
 
474
  for (int  i = 0; i < size; i++)
475
    {
476
      uint8_t  d         = data & 1;            // Latest data bit
477
      data             >>= 1;
478
 
479
      uint8_t  oldCrc7    = (crc >> 7) & 1;
480
      uint8_t  oldCrc1    = (crc >> 1) & 1;
481
      uint8_t  oldCrc0    = (crc >> 0) & 1;
482
      uint8_t  newCrc2    = d ^ oldCrc1 ^ oldCrc7;              // Why d?
483
      uint8_t  newCrc1    = d ^ oldCrc0 ^ oldCrc7;              // Why d?
484
      uint8_t  newCrc0    = d ^ oldCrc7;
485
 
486
      crc = ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | newCrc0;
487
    }
488
 
489
  return crc;
490
 
491
}       // crc8 ()
492
 
493
 
494
//! Compute CRC-8-ATM
495
 
496
//! The data is in an array of uint64_t, for which we use the first size bits
497
//! to compute the CRC.
498
 
499
//! @Note I am using the same algorithm as the ORPSoC debug unit, but I
500
//!       believe its function is broken! I don't believe the data bit should
501
//!       feature in the computation of bits 2 & 1 of the new CRC.
502
 
503
//! @Note I've realized that this is an algorithm for LSB first, so maybe it
504
//!       is correct!
505
 
506
//! @param dataArray  The array of data whose CRC is desired
507
//! @param size       The number of bits in the data
508
 
509
uint8_t
510
JtagDriverSC::crc8 (uint64_t  dataArray[],
511
                    int       size)
512
{
513
  uint8_t    crc = 0;
514
 
515
  for (int  i = 0; i < size; i++)
516
    {
517
      uint8_t  d       = (dataArray[i / 64] >> (i % 64)) & 1;
518
      uint8_t  oldCrc7 = (crc >> 7) & 1;
519
      uint8_t  oldCrc1 = (crc >> 1) & 1;
520
      uint8_t  oldCrc0 = (crc >> 0) & 1;
521
      uint8_t  newCrc2 = d ^ oldCrc1 ^ oldCrc7;         // Why d?
522
      uint8_t  newCrc1 = d ^ oldCrc0 ^ oldCrc7;         // Why d?
523
      uint8_t  newCrc0 = d ^ oldCrc7;
524
 
525
      crc = ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) | newCrc0;
526
    }
527
 
528
  return crc;
529
 
530
}       // crc8 ()
531
 
532
 
533
//! Utility to insert a string of bits into array
534
 
535
//! This is a simple overwriting
536
 
537
//! @param  str       Bits to insert
538
//! @param  strLen    Number of bits to insert
539
//! @param  array     Array into which to insert
540
//! @param  startBit  Offset at which to insert bits
541
 
542
void
543
JtagDriverSC::insertBits (uint64_t  str,
544
                          int       strLen,
545
                          uint64_t *array,
546
                          int       startBit)
547
{
548
  int  startWord = startBit / 64;
549
  int  endWord   = (startBit + strLen - 1) / 64;
550
 
551
  startBit       = startBit % 64;
552
 
553
  // Deal with the startWord. Get enough bits for the mask and put them in the
554
  // right place
555
  uint64_t startMask   = ((1ULL << strLen) - 1ULL) << startBit;
556
 
557
  array[startWord] &= ~startMask;
558
  array[startWord] |= str << startBit;
559
 
560
  // If we were all in one word, we can give up now.
561
  if (startWord == endWord)
562
    {
563
      return;
564
    }
565
 
566
  // Deal with the endWord. Get enough bits for the mask. No need to shift
567
  // these up - they're always at the bottom of the word
568
  int  bitsToDo = (startBit + strLen) % 64;
569
 
570
  uint64_t  endMask = (1ULL << bitsToDo) - 1ULL;
571
 
572
  array[endWord] &= ~endMask;
573
  array[endWord] |= str >> (strLen - bitsToDo);
574
 
575
}       // insertBits()
576
 
577
 
578
//! Utility to extract a string of bits from an array
579
 
580
//! @param  array     Array from which to extract
581
//! @param  startBit  Offset at which to extract bits
582
//! @param  strLen    Number of bits to extract
583
 
584
//! @return  Extracted bits
585
 
586
uint64_t
587
JtagDriverSC::extractBits (uint64_t *array,
588
                           int       startBit,
589
                           int       strLen)
590
{
591
  int  startWord = startBit / 64;
592
  int  endWord   = (startBit + strLen - 1) / 64;
593
 
594
  startBit       = startBit % 64;
595
 
596
  // Deal with the startWord. Get enough bits for the mask and put them in the
597
  // right place
598
  uint64_t  startMask = ((1ULL << strLen) - 1ULL) << startBit;
599
  uint64_t  res       = (array[startWord] & startMask) >> startBit;
600
 
601
  // If we were all in one word, we can give up now.
602
  if (startWord == endWord)
603
    {
604
      return  res;
605
    }
606
 
607
  // Deal with the endWord. Get enough bits for the mask. No need to shift
608
  // these up - they're always at the bottom of the word
609
  int       bitsToDo = (startBit + strLen) % 64;
610
  uint64_t  endMask  = (1ULL << bitsToDo) - 1ULL;
611
 
612
  return  res | ((array[endWord] & endMask) << (strLen - bitsToDo));
613
 
614
}       // extractBits ()

powered by: WebSVN 2.1.0

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