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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 63 julius
// ----------------------------------------------------------------------------
2
 
3
// TAP DR-Scan action: implementation
4
 
5
// Copyright (C) 2009  Embecosm Limited <info@embecosm.com>
6
 
7
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
// This file is part of the Embecosm cycle accurate SystemC JTAG library.
10
 
11
// This program is free software: you can redistribute it and/or modify it
12
// under the terms of the GNU Lesser General Public License as published by
13
// the Free Software Foundation, either version 3 of the License, or (at your
14
// option) 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 Lesser General Public
19
// License for more details.
20
 
21
// You should have received a copy of the GNU Lesser General Public License
22
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 
24
// The C/C++ parts of this program are commented throughout in a fashion
25
// suitable for processing with Doxygen.
26
 
27
// ----------------------------------------------------------------------------
28
 
29
// $Id$
30
 
31
#include <iostream>
32
#include <stdio.h>
33
#include "TapActionDRScan.h"
34
#include "TapStateMachine.h"
35
 
36
 
37
//! Constructor for "large" DR registers
38
 
39
//! Sets up the superclass with the SystemC completion event and initializes
40
//! our state as appropriate.
41
 
42
//! This constructor represents large registers as an array of uint64_t, with
43
//! least significant bits in the lowest numbered element, and any odd bits in
44
//! the highest numbered element.
45
 
46
//! However if we are presented with an array that represents a "small"
47
//! (i.e. up to 64-bit) register, we will store it efficiently.
48
 
49
//! @param[in] doneEvent     SystemC event to be signalled when this action is
50
//!                          complete.
51
//! @param[in] _dRegInArray  The register to shift in.
52
//! @param[in] _dRegSize     Size in bits of the register to shift in.
53
 
54
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
55
                                  uint64_t          *_dRegInArray,
56
                                  int                _dRegSize
57
                                  ) :
58
  TapAction (_doneEvent),
59
  dRegBitSize (_dRegSize),
60
  dRegWordSize ((_dRegSize + 63) / 64),
61
  goToPauseState(0),
62
  bitsBeforePause(0),
63
  bitsShifted (0),
64
  dRScanState (SHIFT_DR_PREPARING)
65
{
66
  // Small registers are represented simply. Large registers are copied to a
67
  // local instance (since we destroy dRegIn when shifting it)
68
 
69
  if (1 == dRegWordSize)
70
    {
71
      dRegIn  = _dRegInArray[0];
72
      dRegOut = 0;
73
    }
74
  else
75
    {
76
      dRegInArray  = new uint64_t [dRegWordSize];
77
      dRegOutArray = new uint64_t [dRegWordSize];
78
 
79
      // Copy in the in array and zero the out array
80
      for (int i = 0; i < dRegWordSize; i++)
81
        {
82
          dRegInArray[i]  = _dRegInArray[i];
83
          dRegOutArray[i] = 0;
84
        }
85
 
86
      // Create a mask for the top word
87
      int maskBits = ((dRegBitSize - 1) % 64) + 1;
88
      topMask = (1ULL << maskBits) - 1ULL;
89
    }
90
}       // TapActionDRScan ()
91
 
92
 
93
//! Constructor for small DR registers
94
 
95
//! Sets up the superclass with the SystemC completion event and initializes
96
//! our state as appropriate.
97
 
98
//! This constructor represents small registers in a single uint64_t
99
 
100
//! @param[in] doneEvent  SystemC event to be signalled when this action is
101
//!                       complete.
102
//! @param[in] _dRegIn    The register to shift in.
103
//! @param[in] _dRegSize  Size in bits of the register to shift in. Must be no
104
//!                       greater than 64, or we give a rude message and set
105
//!                       the value to 64 anyway.
106
 
107
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
108
                                  uint64_t           _dRegIn,
109
                                  int                _dRegSize) :
110
  TapAction (_doneEvent),
111
  dRegBitSize (_dRegSize),
112
  dRegWordSize (1),
113
  goToPauseState(0),
114
  bitsBeforePause(0),
115
  bitsShifted (0),
116
  dRScanState (SHIFT_DR_PREPARING)
117
{
118
  // Print a rude message if we are not small
119
  if (dRegBitSize > 64)
120
    {
121
      std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
122
      dRegBitSize = 64;
123
    }
124
 
125
  // Simple representation
126
  dRegIn  = _dRegIn;
127
  dRegOut = 0;
128
 
129
}       // TapActionDRScan ()
130
 
131
//! Constructor for "large" DR registers using special PAUSE state
132
 
133
//! Sets up the superclass with the SystemC completion event and initializes
134
//! our state as appropriate.
135
 
136
//! This constructor represents large registers as an array of uint64_t, with
137
//! least significant bits in the lowest numbered element, and any odd bits in
138
//! the highest numbered element.
139
 
140
//! However if we are presented with an array that represents a "small"
141
//! (i.e. up to 64-bit) register, we will store it efficiently.
142
 
143
//! @param[in] doneEvent     SystemC event to be signalled when this action is
144
//!                          complete.
145
//! @param[in] _dRegInArray  The register to shift in.
146
//! @param[in] _dRegSize     Size in bits of the register to shift in.
147
//! @param[in] _goToPauseState     Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0
148
//! @param[in] _bitsBeforePauseState     Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed
149
 
150
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
151
                                  uint64_t          *_dRegInArray,
152
                                  int                _dRegSize,
153
                                  int                _goToPauseState,
154
                                  int                _bitsBeforePauseState
155
                                  ) :
156
  TapAction (_doneEvent),
157
  dRegBitSize (_dRegSize),
158
  dRegWordSize ((_dRegSize + 63) / 64),
159
  goToPauseState(_goToPauseState),
160
  bitsBeforePause(_bitsBeforePauseState),
161
  pauseStateCount(0),
162
  bitsShifted (0),
163
  dRScanState (SHIFT_DR_PREPARING)
164
{
165
  // Small registers are represented simply. Large registers are copied to a
166
  // local instance (since we destroy dRegIn when shifting it)
167
 
168
  if (1 == dRegWordSize)
169
    {
170
      dRegIn  = _dRegInArray[0];
171
      dRegOut = 0;
172
    }
173
  else
174
    {
175
      dRegInArray  = new uint64_t [dRegWordSize];
176
      dRegOutArray = new uint64_t [dRegWordSize];
177
 
178
      // Copy in the in array and zero the out array
179
      for (int i = 0; i < dRegWordSize; i++)
180
        {
181
          dRegInArray[i]  = _dRegInArray[i];
182
          dRegOutArray[i] = 0;
183
        }
184
 
185
      // Create a mask for the top word
186
      int maskBits = ((dRegBitSize - 1) % 64) + 1;
187
      topMask = (1ULL << maskBits) - 1ULL;
188
    }
189
}       // TapActionDRScan ()
190
 
191
 
192
//! Constructor for small DR registers using special PAUSE state
193
 
194
//! Sets up the superclass with the SystemC completion event and initializes
195
//! our state as appropriate.
196
 
197
//! This constructor represents small registers in a single uint64_t
198
 
199
//! @param[in] doneEvent  SystemC event to be signalled when this action is
200
//!                       complete.
201
//! @param[in] _dRegIn    The register to shift in.
202
//! @param[in] _dRegSize  Size in bits of the register to shift in. Must be no
203
//!                       greater than 64, or we give a rude message and set
204
//!                       the value to 64 anyway.
205
//! @param[in] _goToPauseState     Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0
206
//! @param[in] _bitsBeforePauseState     Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed
207
 
208
 
209
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
210
                                  uint64_t           _dRegIn,
211
                                  int                _dRegSize,
212
                                  int                _goToPauseState,
213
                                  int                _bitsBeforePauseState
214
                                  ) :
215
  TapAction (_doneEvent),
216
  dRegBitSize (_dRegSize),
217
  dRegWordSize (1),
218
  goToPauseState(_goToPauseState),
219
  bitsBeforePause(_bitsBeforePauseState),
220
  pauseStateCount(0),
221
  bitsShifted (0),
222
  dRScanState (SHIFT_DR_PREPARING)
223
{
224
  // Print a rude message if we are not small
225
  if (dRegBitSize > 64)
226
    {
227
      std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
228
      dRegBitSize = 64;
229
    }
230
 
231
  // Simple representation
232
  dRegIn  = _dRegIn;
233
  dRegOut = 0;
234
 
235
}       // TapActionDRScan ()
236
 
237
 
238
 
239
 
240
//! Destructor.
241
 
242
//! If we allocated them, free the large registers
243
 
244
TapActionDRScan::~TapActionDRScan ()
245
{
246
  if (dRegWordSize > 1)
247
    {
248
      delete [] dRegInArray;
249
      delete [] dRegOutArray;
250
    }
251
}       // ~TapActionDRScan ()
252
 
253
 
254
//! Process the Shift-DR action
255
 
256
//! This drives the DR-Scan state. We can only do this if we have the TAP
257
//! state machine in a consistent state, which in turn is only possible if we
258
//! have been through a reset cycle.
259
 
260
//! If the state machine shows it has yet to be through a reset cycle, we
261
//! drive that cycle, after issuing a warning. This functionality is provided
262
//! by the parent class, TapAction::.
263
 
264
//! @param[in]  tapStateMachine  The TAP state machine with which this action
265
//!                              is associated. 
266
//! @param[out] tdi              The value to drive on TDI
267
//! @param[in]  tdo              The value currently on TDO
268
//! @param[out] tms              The value to drive on TMS
269
 
270
//! @return  True if the action is complete
271
 
272
bool
273
TapActionDRScan::process (TapStateMachine *tapStateMachine,
274
                          bool            &tdi,
275
                          bool             tdo,
276
                          bool            &tms)
277
{
278
  // Ensure we are in a consistent state. If not then we'll have moved towards
279
  // it and can return with the given tms
280
  if (!checkResetDone (tapStateMachine, tms, true))
281
    {
282
      return false;
283
    }
284
 
285
  if (goToPauseState)
286
    {
287
      switch (dRScanState)
288
        {
289
        case SHIFT_DR_PREPARING:
290
 
291
          // Are we in the Shift-DR state yet?
292
          if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms))
293
            {
294
              return  false;            // Not there. Accept the TMS value
295
            }
296
          else
297
            {
298
              dRScanState = SHIFT_DR_SHIFTING_BEFORE_PAUSE;     // Drop through
299
            }
300
 
301
        case SHIFT_DR_SHIFTING_BEFORE_PAUSE:
302
 
303
          // Are we still shifting stuff?
304
          if (bitsShifted < bitsBeforePause)
305
            {
306
              // We are in the Shift-DR state. Another bit about to be done, so
307
              // increment the count
308
              bitsShifted++;
309
 
310
              // Set the TDI value. In a routine to keep this tidy.
311
              tdi = shiftDRegOut ();
312
 
313
              // Record the TDO value. This is always a cycle late, so we ignore
314
              // it the first time. The value shifts in from the top.
315
              if (bitsShifted > 1)
316
                {
317
                  shiftDRegIn (tdo);
318
                }
319
 
320
              // TMS is 0 to keep us here UNLESS this is the last bit, in which case
321
              // it is 1 to move us into Exit1-DR.
322
              tms = (bitsShifted == bitsBeforePause);
323
 
324
              // Not done until we've updated
325
              return false;
326
            }
327
          else
328
            {
329
              // Capture the last TDO bit
330
              shiftDRegIn (tdo);
331
 
332
              // Now lower TMS to go to PAUSE_DR
333
              tms = false;
334
 
335
              dRScanState = SHIFT_DR_SHIFTING_PAUSE;
336
 
337
            }
338
 
339
        case SHIFT_DR_SHIFTING_PAUSE:
340
          {
341
            if (!tapStateMachine->targetState (TAP_PAUSE_DR, tms))
342
              {
343
                return  false;          // Not there. Accept the TMS value
344
              }
345
 
346
            if ( pauseStateCount++ < 3)
347
              return false;
348
            // Sit in DR_PAUSE state and cycle until TDO is low
349
            // tms starts false, should get set to true on the cycle
350
            // tdo goes low, then the next cycle we go back to SHIFT_DR
351
            // and we return so tms isn't set again.
352
            if (!tdo)
353
              {
354
                tms = true;
355
                dRScanState = SHIFT_DR_EXIT2;
356
                return false;
357
              }
358
          }
359
 
360
        case SHIFT_DR_EXIT2:
361
          {
362
            tms = false;
363
            shiftDRegIn (0);
364
            dRScanState = SHIFT_DR_SHIFTING_AFTER_PAUSE;
365
            return false;
366
 
367
          }
368
 
369
        case SHIFT_DR_SHIFTING_AFTER_PAUSE:
370
          {
371
            if (bitsShifted < dRegBitSize)
372
              {
373
                // We are in the Shift-DR state. Another bit about to be done, so
374
                // increment the count
375
                bitsShifted++;
376
 
377
                // Set the TDI value. In a routine to keep this tidy.
378
                tdi = shiftDRegOut ();
379
 
380
                //printf("shifting after pause (%d+32=%d) %d of %d tdo=%d\n",bitsBeforePause,bitsBeforePause+32, bitsShifted, dRegBitSize,(tdo) ? 1 : 0);
381
                shiftDRegIn (tdo);
382
 
383
                // TMS is 0 to keep us here UNLESS this is the last bit, in which case
384
                // it is 1 to move us into Exit1-DR.
385
                tms = (bitsShifted == dRegBitSize);
386
 
387
                // Not done until we've updated
388
                return false;
389
              }
390
            else
391
              {
392
                // Capture the last TDO bit
393
                shiftDRegIn (tdo);
394
 
395
                dRScanState = SHIFT_DR_UPDATING;        // Drop through
396
              }
397
          }
398
 
399
 
400
        case SHIFT_DR_UPDATING:
401
 
402
          // Are we still trying to update?
403
          if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms))
404
            {
405
              return  false;            // Not there. Accept the TMS value
406
            }
407
          else
408
            {
409
              return  true;                     // All done
410
            }
411
        }
412
    }
413
  else
414
    {
415
      switch (dRScanState)
416
        {
417
        case SHIFT_DR_PREPARING:
418
 
419
          // Are we in the Shift-DR state yet?
420
          if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms))
421
            {
422
              return  false;            // Not there. Accept the TMS value
423
            }
424
          else
425
            {
426
              dRScanState = SHIFT_DR_SHIFTING;  // Drop through
427
            }
428
 
429
        case SHIFT_DR_SHIFTING:
430
 
431
          // Are we still shifting stuff?
432
          if (bitsShifted < dRegBitSize)
433
            {
434
              // We are in the Shift-DR state. Another bit about to be done, so
435
              // increment the count
436
              bitsShifted++;
437
 
438
              // Set the TDI value. In a routine to keep this tidy.
439
              tdi = shiftDRegOut ();
440
 
441
              // Record the TDO value. This is always a cycle late, so we ignore
442
              // it the first time. The value shifts in from the top.
443
              if (bitsShifted > 1)
444
                {
445
                  shiftDRegIn (tdo);
446
                }
447
 
448
              // TMS is 0 to keep us here UNLESS this is the last bit, in which case
449
              // it is 1 to move us into Exit1-DR.
450
              tms = (bitsShifted == dRegBitSize);
451
 
452
              // Not done until we've updated
453
              return false;
454
            }
455
          else
456
            {
457
              // Capture the last TDO bit
458
              shiftDRegIn (tdo);
459
 
460
              dRScanState = SHIFT_DR_UPDATING;  // Drop through
461
 
462
            }
463
 
464
        case SHIFT_DR_UPDATING:
465
 
466
          // Are we still trying to update?
467
          if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms))
468
            {
469
              return  false;            // Not there. Accept the TMS value
470
            }
471
          else
472
            {
473
              return  true;                     // All done
474
            }
475
        }
476
    }
477
}       // process ()
478
 
479
 
480
//! Get the shifted out value.
481
 
482
//! This version works with large values.
483
 
484
//! @param[out] dRegArray  Array for the result
485
void
486
TapActionDRScan::getDRegOut (uint64_t  dRegArray[])
487
{
488
  if (1 == dRegWordSize)
489
    {
490
      dRegArray[0] = dRegOut;
491
    }
492
  else
493
    {
494
      for (int i = 0 ; i < dRegWordSize; i++)
495
        {
496
          dRegArray[i] = dRegOutArray[i];
497
        }
498
    }
499
}       // getDRegOut ()
500
 
501
 
502
//! Get the shifted out value.
503
 
504
//! This version is for small values. For large values it silently returns the
505
//! bottom 64 bits only.
506
 
507
//! @todo  Should we give an error. Or is it useful to allow efficient access
508
//!        to the bottom 64 bits?
509
 
510
//! @return  The value shifted out (or the bottom 64 bits thereof if the
511
//!          register is "large").
512
uint64_t
513
TapActionDRScan::getDRegOut ()
514
{
515
  if (1 == dRegWordSize)
516
    {
517
      return dRegOut;
518
    }
519
  else
520
    {
521
      return dRegOutArray[0];
522
    }
523
}       // getDRegOut ()
524
 
525
 
526
//! Utility to shift the bottom bit out of the dReg.
527
 
528
//! Two flavours depending on whether we have a "small" register
529
 
530
//! @return  The bit shifted out.
531
bool
532
TapActionDRScan::shiftDRegOut ()
533
{
534
  if (1 == dRegWordSize)                // "Small" register
535
    {
536
      bool  res = dRegIn & 1;
537
      dRegIn >>= 1;
538
      return  res;
539
    }
540
  else                                  // "Large" register
541
    {
542
      bool  res = (dRegInArray[0] & 1) == 1;
543
 
544
      // Shift all but the first word along
545
      for (int  i = 0; i < (dRegWordSize - 1); i++)
546
        {
547
          dRegInArray[i] = (dRegInArray[i] >> 1) | (dRegInArray[i+1] << 63);
548
        }
549
 
550
      // Shift the first word
551
      dRegInArray[dRegWordSize - 1] >>= 1;
552
 
553
      return  res;
554
    }
555
}       // shiftDRegOut ()
556
 
557
 
558
//! Utility to shift the top bit into the dReg.
559
 
560
//! Two flavours depending on whether we have a "small" register
561
 
562
//! @param bitIn  The bit to shift in the top
563
void
564
TapActionDRScan::shiftDRegIn (bool  bitIn)
565
{
566
  if (1 == dRegWordSize)                // "Small" register
567
    {
568
      dRegOut >>= 1;                    // Move all the existing bits right
569
 
570
      if (bitIn)                        // OR any new bit in
571
        {
572
          uint64_t tmpBit = 1ULL << (dRegBitSize - 1);
573
          dRegOut |= tmpBit;
574
        }
575
    }
576
  else                                  // "Large" register
577
    {
578
      // Shift all but the first word along
579
      for (int  i = 0; i < (dRegWordSize - 1); i++)
580
        {
581
          dRegOutArray[i] >>= 1;
582
          dRegOutArray[i]  |= dRegOutArray[i+1] << 63;
583
        }
584
 
585
      // The first word is shifted and the new bit masked in
586
      dRegOutArray[dRegWordSize - 1] >>= 1;
587
      dRegOutArray[dRegWordSize - 1]  |= bitIn ? (topMask + 1) >> 1 : 0;
588
    }
589
}       // shiftDRegIn ()

powered by: WebSVN 2.1.0

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