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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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