Line 31... |
Line 31... |
#include <iostream>
|
#include <iostream>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include "TapActionDRScan.h"
|
#include "TapActionDRScan.h"
|
#include "TapStateMachine.h"
|
#include "TapStateMachine.h"
|
|
|
|
|
//! Constructor for "large" DR registers
|
//! Constructor for "large" DR registers
|
|
|
//! Sets up the superclass with the SystemC completion event and initializes
|
//! Sets up the superclass with the SystemC completion event and initializes
|
//! our state as appropriate.
|
//! our state as appropriate.
|
|
|
Line 49... |
Line 48... |
//! @param[in] doneEvent SystemC event to be signalled when this action is
|
//! @param[in] doneEvent SystemC event to be signalled when this action is
|
//! complete.
|
//! complete.
|
//! @param[in] _dRegInArray The register to shift in.
|
//! @param[in] _dRegInArray The register to shift in.
|
//! @param[in] _dRegSize Size in bits of the register to shift in.
|
//! @param[in] _dRegSize Size in bits of the register to shift in.
|
|
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
TapActionDRScan::TapActionDRScan(sc_core::sc_event * _doneEvent, uint64_t * _dRegInArray, int _dRegSize):
|
uint64_t *_dRegInArray,
|
|
int _dRegSize
|
|
) :
|
|
TapAction (_doneEvent),
|
TapAction (_doneEvent),
|
dRegBitSize (_dRegSize),
|
dRegBitSize (_dRegSize),
|
dRegWordSize ((_dRegSize + 63) / 64),
|
dRegWordSize ((_dRegSize + 63) / 64),
|
goToPauseState(0),
|
goToPauseState(0),
|
bitsBeforePause(0),
|
bitsBeforePause(0), bitsShifted(0), dRScanState(SHIFT_DR_PREPARING)
|
bitsShifted (0),
|
|
dRScanState (SHIFT_DR_PREPARING)
|
|
{
|
{
|
// Small registers are represented simply. Large registers are copied to a
|
// Small registers are represented simply. Large registers are copied to a
|
// local instance (since we destroy dRegIn when shifting it)
|
// local instance (since we destroy dRegIn when shifting it)
|
|
|
if (1 == dRegWordSize)
|
if (1 == dRegWordSize) {
|
{
|
|
dRegIn = _dRegInArray[0];
|
dRegIn = _dRegInArray[0];
|
dRegOut = 0;
|
dRegOut = 0;
|
}
|
} else {
|
else
|
|
{
|
|
dRegInArray = new uint64_t [dRegWordSize];
|
dRegInArray = new uint64_t [dRegWordSize];
|
dRegOutArray = new uint64_t [dRegWordSize];
|
dRegOutArray = new uint64_t [dRegWordSize];
|
|
|
// Copy in the in array and zero the out array
|
// Copy in the in array and zero the out array
|
for (int i = 0; i < dRegWordSize; i++)
|
for (int i = 0; i < dRegWordSize; i++) {
|
{
|
|
dRegInArray[i] = _dRegInArray[i];
|
dRegInArray[i] = _dRegInArray[i];
|
dRegOutArray[i] = 0;
|
dRegOutArray[i] = 0;
|
}
|
}
|
|
|
// Create a mask for the top word
|
// Create a mask for the top word
|
int maskBits = ((dRegBitSize - 1) % 64) + 1;
|
int maskBits = ((dRegBitSize - 1) % 64) + 1;
|
topMask = (1ULL << maskBits) - 1ULL;
|
topMask = (1ULL << maskBits) - 1ULL;
|
}
|
}
|
} // TapActionDRScan ()
|
} // TapActionDRScan ()
|
|
|
|
|
//! Constructor for small DR registers
|
//! Constructor for small DR registers
|
|
|
//! Sets up the superclass with the SystemC completion event and initializes
|
//! Sets up the superclass with the SystemC completion event and initializes
|
//! our state as appropriate.
|
//! our state as appropriate.
|
|
|
Line 104... |
Line 93... |
//! greater than 64, or we give a rude message and set
|
//! greater than 64, or we give a rude message and set
|
//! the value to 64 anyway.
|
//! the value to 64 anyway.
|
|
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
uint64_t _dRegIn,
|
uint64_t _dRegIn,
|
int _dRegSize) :
|
int _dRegSize):TapAction(_doneEvent),
|
TapAction (_doneEvent),
|
|
dRegBitSize (_dRegSize),
|
dRegBitSize (_dRegSize),
|
dRegWordSize (1),
|
dRegWordSize (1),
|
goToPauseState(0),
|
goToPauseState(0),
|
bitsBeforePause(0),
|
bitsBeforePause(0), bitsShifted(0), dRScanState(SHIFT_DR_PREPARING)
|
bitsShifted (0),
|
|
dRScanState (SHIFT_DR_PREPARING)
|
|
{
|
{
|
// Print a rude message if we are not small
|
// Print a rude message if we are not small
|
if (dRegBitSize > 64)
|
if (dRegBitSize > 64) {
|
{
|
|
std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
|
std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
|
dRegBitSize = 64;
|
dRegBitSize = 64;
|
}
|
}
|
|
|
// Simple representation
|
// Simple representation
|
dRegIn = _dRegIn;
|
dRegIn = _dRegIn;
|
dRegOut = 0;
|
dRegOut = 0;
|
|
|
} // TapActionDRScan ()
|
} // TapActionDRScan ()
|
Line 149... |
Line 133... |
|
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
uint64_t *_dRegInArray,
|
uint64_t *_dRegInArray,
|
int _dRegSize,
|
int _dRegSize,
|
int _goToPauseState,
|
int _goToPauseState,
|
int _bitsBeforePauseState
|
int
|
) :
|
_bitsBeforePauseState):TapAction(_doneEvent),
|
TapAction (_doneEvent),
|
dRegBitSize(_dRegSize), dRegWordSize((_dRegSize + 63) / 64),
|
dRegBitSize (_dRegSize),
|
goToPauseState(_goToPauseState), bitsBeforePause(_bitsBeforePauseState),
|
dRegWordSize ((_dRegSize + 63) / 64),
|
pauseStateCount(0), bitsShifted(0), dRScanState(SHIFT_DR_PREPARING)
|
goToPauseState(_goToPauseState),
|
|
bitsBeforePause(_bitsBeforePauseState),
|
|
pauseStateCount(0),
|
|
bitsShifted (0),
|
|
dRScanState (SHIFT_DR_PREPARING)
|
|
{
|
{
|
// Small registers are represented simply. Large registers are copied to a
|
// Small registers are represented simply. Large registers are copied to a
|
// local instance (since we destroy dRegIn when shifting it)
|
// local instance (since we destroy dRegIn when shifting it)
|
|
|
if (1 == dRegWordSize)
|
if (1 == dRegWordSize) {
|
{
|
|
dRegIn = _dRegInArray[0];
|
dRegIn = _dRegInArray[0];
|
dRegOut = 0;
|
dRegOut = 0;
|
}
|
} else {
|
else
|
|
{
|
|
dRegInArray = new uint64_t [dRegWordSize];
|
dRegInArray = new uint64_t [dRegWordSize];
|
dRegOutArray = new uint64_t [dRegWordSize];
|
dRegOutArray = new uint64_t [dRegWordSize];
|
|
|
// Copy in the in array and zero the out array
|
// Copy in the in array and zero the out array
|
for (int i = 0; i < dRegWordSize; i++)
|
for (int i = 0; i < dRegWordSize; i++) {
|
{
|
|
dRegInArray[i] = _dRegInArray[i];
|
dRegInArray[i] = _dRegInArray[i];
|
dRegOutArray[i] = 0;
|
dRegOutArray[i] = 0;
|
}
|
}
|
|
|
// Create a mask for the top word
|
// Create a mask for the top word
|
int maskBits = ((dRegBitSize - 1) % 64) + 1;
|
int maskBits = ((dRegBitSize - 1) % 64) + 1;
|
topMask = (1ULL << maskBits) - 1ULL;
|
topMask = (1ULL << maskBits) - 1ULL;
|
}
|
}
|
} // TapActionDRScan ()
|
} // TapActionDRScan ()
|
|
|
|
|
//! Constructor for small DR registers using special PAUSE state
|
//! Constructor for small DR registers using special PAUSE state
|
|
|
//! Sets up the superclass with the SystemC completion event and initializes
|
//! Sets up the superclass with the SystemC completion event and initializes
|
//! our state as appropriate.
|
//! our state as appropriate.
|
|
|
Line 203... |
Line 177... |
//! greater than 64, or we give a rude message and set
|
//! greater than 64, or we give a rude message and set
|
//! the value to 64 anyway.
|
//! the value to 64 anyway.
|
//! @param[in] _goToPauseState Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0
|
//! @param[in] _goToPauseState Switch determining if we go to PAUSE state after _bitsBeforePauseState and poll for TDO=0
|
//! @param[in] _bitsBeforePauseState Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed
|
//! @param[in] _bitsBeforePauseState Number of bits to shift in before going to shift pause state and polling TDO, indicating transaction has completed
|
|
|
|
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
TapActionDRScan::TapActionDRScan (sc_core::sc_event *_doneEvent,
|
uint64_t _dRegIn,
|
uint64_t _dRegIn,
|
int _dRegSize,
|
int _dRegSize,
|
int _goToPauseState,
|
int _goToPauseState,
|
int _bitsBeforePauseState
|
int
|
) :
|
_bitsBeforePauseState):TapAction(_doneEvent),
|
TapAction (_doneEvent),
|
dRegBitSize(_dRegSize), dRegWordSize(1), goToPauseState(_goToPauseState),
|
dRegBitSize (_dRegSize),
|
bitsBeforePause(_bitsBeforePauseState), pauseStateCount(0), bitsShifted(0),
|
dRegWordSize (1),
|
|
goToPauseState(_goToPauseState),
|
|
bitsBeforePause(_bitsBeforePauseState),
|
|
pauseStateCount(0),
|
|
bitsShifted (0),
|
|
dRScanState (SHIFT_DR_PREPARING)
|
dRScanState (SHIFT_DR_PREPARING)
|
{
|
{
|
// Print a rude message if we are not small
|
// Print a rude message if we are not small
|
if (dRegBitSize > 64)
|
if (dRegBitSize > 64) {
|
{
|
|
std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
|
std::cerr << "Simple DR size reduced to 64 bits" << std::endl;
|
dRegBitSize = 64;
|
dRegBitSize = 64;
|
}
|
}
|
|
|
// Simple representation
|
// Simple representation
|
dRegIn = _dRegIn;
|
dRegIn = _dRegIn;
|
dRegOut = 0;
|
dRegOut = 0;
|
|
|
} // TapActionDRScan ()
|
} // TapActionDRScan ()
|
|
|
|
|
|
|
|
|
//! Destructor.
|
//! Destructor.
|
|
|
//! If we allocated them, free the large registers
|
//! If we allocated them, free the large registers
|
|
|
TapActionDRScan::~TapActionDRScan ()
|
TapActionDRScan::~TapActionDRScan ()
|
{
|
{
|
if (dRegWordSize > 1)
|
if (dRegWordSize > 1) {
|
{
|
|
delete [] dRegInArray;
|
delete [] dRegInArray;
|
delete [] dRegOutArray;
|
delete [] dRegOutArray;
|
}
|
}
|
} // ~TapActionDRScan ()
|
} // ~TapActionDRScan ()
|
|
|
|
|
//! Process the Shift-DR action
|
//! Process the Shift-DR action
|
|
|
//! This drives the DR-Scan state. We can only do this if we have the TAP
|
//! This drives the DR-Scan state. We can only do this if we have the TAP
|
//! state machine in a consistent state, which in turn is only possible if we
|
//! state machine in a consistent state, which in turn is only possible if we
|
//! have been through a reset cycle.
|
//! have been through a reset cycle.
|
Line 267... |
Line 228... |
//! @param[in] tdo The value currently on TDO
|
//! @param[in] tdo The value currently on TDO
|
//! @param[out] tms The value to drive on TMS
|
//! @param[out] tms The value to drive on TMS
|
|
|
//! @return True if the action is complete
|
//! @return True if the action is complete
|
|
|
bool
|
bool TapActionDRScan::process(TapStateMachine * tapStateMachine,
|
TapActionDRScan::process (TapStateMachine *tapStateMachine,
|
bool & tdi, bool tdo, bool & tms)
|
bool &tdi,
|
|
bool tdo,
|
|
bool &tms)
|
|
{
|
{
|
// Ensure we are in a consistent state. If not then we'll have moved towards
|
// Ensure we are in a consistent state. If not then we'll have moved towards
|
// it and can return with the given tms
|
// it and can return with the given tms
|
if (!checkResetDone (tapStateMachine, tms, true))
|
if (!checkResetDone(tapStateMachine, tms, true)) {
|
{
|
|
return false;
|
return false;
|
}
|
}
|
|
|
if (goToPauseState)
|
if (goToPauseState) {
|
{
|
switch (dRScanState) {
|
switch (dRScanState)
|
|
{
|
|
case SHIFT_DR_PREPARING:
|
case SHIFT_DR_PREPARING:
|
|
|
// Are we in the Shift-DR state yet?
|
// Are we in the Shift-DR state yet?
|
if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms))
|
if (!tapStateMachine->targetState(TAP_SHIFT_DR, tms)) {
|
{
|
|
return false; // Not there. Accept the TMS value
|
return false; // Not there. Accept the TMS value
|
}
|
} else {
|
else
|
|
{
|
|
dRScanState = SHIFT_DR_SHIFTING_BEFORE_PAUSE; // Drop through
|
dRScanState = SHIFT_DR_SHIFTING_BEFORE_PAUSE; // Drop through
|
}
|
}
|
|
|
case SHIFT_DR_SHIFTING_BEFORE_PAUSE:
|
case SHIFT_DR_SHIFTING_BEFORE_PAUSE:
|
|
|
// Are we still shifting stuff?
|
// Are we still shifting stuff?
|
if (bitsShifted < bitsBeforePause)
|
if (bitsShifted < bitsBeforePause) {
|
{
|
|
// We are in the Shift-DR state. Another bit about to be done, so
|
// We are in the Shift-DR state. Another bit about to be done, so
|
// increment the count
|
// increment the count
|
bitsShifted++;
|
bitsShifted++;
|
|
|
// Set the TDI value. In a routine to keep this tidy.
|
// Set the TDI value. In a routine to keep this tidy.
|
tdi = shiftDRegOut ();
|
tdi = shiftDRegOut ();
|
|
|
// Record the TDO value. This is always a cycle late, so we ignore
|
// Record the TDO value. This is always a cycle late, so we ignore
|
// it the first time. The value shifts in from the top.
|
// it the first time. The value shifts in from the top.
|
if (bitsShifted > 1)
|
if (bitsShifted > 1) {
|
{
|
|
shiftDRegIn (tdo);
|
shiftDRegIn (tdo);
|
}
|
}
|
|
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case
|
// it is 1 to move us into Exit1-DR.
|
// it is 1 to move us into Exit1-DR.
|
tms = (bitsShifted == bitsBeforePause);
|
tms = (bitsShifted == bitsBeforePause);
|
|
|
// Not done until we've updated
|
// Not done until we've updated
|
return false;
|
return false;
|
}
|
} else {
|
else
|
|
{
|
|
// Capture the last TDO bit
|
// Capture the last TDO bit
|
shiftDRegIn (tdo);
|
shiftDRegIn (tdo);
|
|
|
// Now lower TMS to go to PAUSE_DR
|
// Now lower TMS to go to PAUSE_DR
|
tms = false;
|
tms = false;
|
Line 336... |
Line 283... |
|
|
}
|
}
|
|
|
case SHIFT_DR_SHIFTING_PAUSE:
|
case SHIFT_DR_SHIFTING_PAUSE:
|
{
|
{
|
if (!tapStateMachine->targetState (TAP_PAUSE_DR, tms))
|
if (!tapStateMachine->targetState
|
{
|
(TAP_PAUSE_DR, tms)) {
|
return false; // Not there. Accept the TMS value
|
return false; // Not there. Accept the TMS value
|
}
|
}
|
|
|
if ( pauseStateCount++ < 3)
|
if ( pauseStateCount++ < 3)
|
return false;
|
return false;
|
// Sit in DR_PAUSE state and cycle until TDO is low
|
// Sit in DR_PAUSE state and cycle until TDO is low
|
// tms starts false, should get set to true on the cycle
|
// tms starts false, should get set to true on the cycle
|
// tdo goes low, then the next cycle we go back to SHIFT_DR
|
// tdo goes low, then the next cycle we go back to SHIFT_DR
|
// and we return so tms isn't set again.
|
// and we return so tms isn't set again.
|
if (!tdo)
|
if (!tdo) {
|
{
|
|
tms = true;
|
tms = true;
|
dRScanState = SHIFT_DR_EXIT2;
|
dRScanState = SHIFT_DR_EXIT2;
|
return false;
|
return false;
|
}
|
}
|
}
|
}
|
Line 366... |
Line 312... |
|
|
}
|
}
|
|
|
case SHIFT_DR_SHIFTING_AFTER_PAUSE:
|
case SHIFT_DR_SHIFTING_AFTER_PAUSE:
|
{
|
{
|
if (bitsShifted < dRegBitSize)
|
if (bitsShifted < dRegBitSize) {
|
{
|
|
// We are in the Shift-DR state. Another bit about to be done, so
|
// We are in the Shift-DR state. Another bit about to be done, so
|
// increment the count
|
// increment the count
|
bitsShifted++;
|
bitsShifted++;
|
|
|
// Set the TDI value. In a routine to keep this tidy.
|
// Set the TDI value. In a routine to keep this tidy.
|
Line 384... |
Line 329... |
// it is 1 to move us into Exit1-DR.
|
// it is 1 to move us into Exit1-DR.
|
tms = (bitsShifted == dRegBitSize);
|
tms = (bitsShifted == dRegBitSize);
|
|
|
// Not done until we've updated
|
// Not done until we've updated
|
return false;
|
return false;
|
}
|
} else {
|
else
|
|
{
|
|
// Capture the last TDO bit
|
// Capture the last TDO bit
|
shiftDRegIn (tdo);
|
shiftDRegIn (tdo);
|
|
|
dRScanState = SHIFT_DR_UPDATING; // Drop through
|
dRScanState = SHIFT_DR_UPDATING; // Drop through
|
}
|
}
|
}
|
}
|
|
|
|
|
case SHIFT_DR_UPDATING:
|
case SHIFT_DR_UPDATING:
|
|
|
// Are we still trying to update?
|
// Are we still trying to update?
|
if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms))
|
if (!tapStateMachine->targetState(TAP_UPDATE_DR, tms)) {
|
{
|
|
return false; // Not there. Accept the TMS value
|
return false; // Not there. Accept the TMS value
|
}
|
} else {
|
else
|
|
{
|
|
return true; // All done
|
return true; // All done
|
}
|
}
|
}
|
}
|
}
|
} else {
|
else
|
switch (dRScanState) {
|
{
|
|
switch (dRScanState)
|
|
{
|
|
case SHIFT_DR_PREPARING:
|
case SHIFT_DR_PREPARING:
|
|
|
// Are we in the Shift-DR state yet?
|
// Are we in the Shift-DR state yet?
|
if (!tapStateMachine->targetState (TAP_SHIFT_DR, tms))
|
if (!tapStateMachine->targetState(TAP_SHIFT_DR, tms)) {
|
{
|
|
return false; // Not there. Accept the TMS value
|
return false; // Not there. Accept the TMS value
|
}
|
} else {
|
else
|
|
{
|
|
dRScanState = SHIFT_DR_SHIFTING; // Drop through
|
dRScanState = SHIFT_DR_SHIFTING; // Drop through
|
}
|
}
|
|
|
case SHIFT_DR_SHIFTING:
|
case SHIFT_DR_SHIFTING:
|
|
|
// Are we still shifting stuff?
|
// Are we still shifting stuff?
|
if (bitsShifted < dRegBitSize)
|
if (bitsShifted < dRegBitSize) {
|
{
|
|
// We are in the Shift-DR state. Another bit about to be done, so
|
// We are in the Shift-DR state. Another bit about to be done, so
|
// increment the count
|
// increment the count
|
bitsShifted++;
|
bitsShifted++;
|
|
|
// Set the TDI value. In a routine to keep this tidy.
|
// Set the TDI value. In a routine to keep this tidy.
|
tdi = shiftDRegOut ();
|
tdi = shiftDRegOut ();
|
|
|
// Record the TDO value. This is always a cycle late, so we ignore
|
// Record the TDO value. This is always a cycle late, so we ignore
|
// it the first time. The value shifts in from the top.
|
// it the first time. The value shifts in from the top.
|
if (bitsShifted > 1)
|
if (bitsShifted > 1) {
|
{
|
|
shiftDRegIn (tdo);
|
shiftDRegIn (tdo);
|
}
|
}
|
|
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case
|
// TMS is 0 to keep us here UNLESS this is the last bit, in which case
|
// it is 1 to move us into Exit1-DR.
|
// it is 1 to move us into Exit1-DR.
|
tms = (bitsShifted == dRegBitSize);
|
tms = (bitsShifted == dRegBitSize);
|
|
|
// Not done until we've updated
|
// Not done until we've updated
|
return false;
|
return false;
|
}
|
} else {
|
else
|
|
{
|
|
// Capture the last TDO bit
|
// Capture the last TDO bit
|
shiftDRegIn (tdo);
|
shiftDRegIn (tdo);
|
|
|
dRScanState = SHIFT_DR_UPDATING; // Drop through
|
dRScanState = SHIFT_DR_UPDATING; // Drop through
|
|
|
}
|
}
|
|
|
case SHIFT_DR_UPDATING:
|
case SHIFT_DR_UPDATING:
|
|
|
// Are we still trying to update?
|
// Are we still trying to update?
|
if (!tapStateMachine->targetState (TAP_UPDATE_DR, tms))
|
if (!tapStateMachine->targetState(TAP_UPDATE_DR, tms)) {
|
{
|
|
return false; // Not there. Accept the TMS value
|
return false; // Not there. Accept the TMS value
|
}
|
} else {
|
else
|
|
{
|
|
return true; // All done
|
return true; // All done
|
}
|
}
|
}
|
}
|
}
|
}
|
} // process ()
|
} // process ()
|
|
|
|
|
//! Get the shifted out value.
|
//! Get the shifted out value.
|
|
|
//! This version works with large values.
|
//! This version works with large values.
|
|
|
//! @param[out] dRegArray Array for the result
|
//! @param[out] dRegArray Array for the result
|
void
|
void TapActionDRScan::getDRegOut(uint64_t dRegArray[])
|
TapActionDRScan::getDRegOut (uint64_t dRegArray[])
|
|
{
|
|
if (1 == dRegWordSize)
|
|
{
|
{
|
|
if (1 == dRegWordSize) {
|
dRegArray[0] = dRegOut;
|
dRegArray[0] = dRegOut;
|
}
|
} else {
|
else
|
for (int i = 0; i < dRegWordSize; i++) {
|
{
|
|
for (int i = 0 ; i < dRegWordSize; i++)
|
|
{
|
|
dRegArray[i] = dRegOutArray[i];
|
dRegArray[i] = dRegOutArray[i];
|
}
|
}
|
}
|
}
|
} // getDRegOut ()
|
} // getDRegOut ()
|
|
|
|
|
//! Get the shifted out value.
|
//! Get the shifted out value.
|
|
|
//! This version is for small values. For large values it silently returns the
|
//! This version is for small values. For large values it silently returns the
|
//! bottom 64 bits only.
|
//! bottom 64 bits only.
|
|
|
//! @todo Should we give an error. Or is it useful to allow efficient access
|
//! @todo Should we give an error. Or is it useful to allow efficient access
|
//! to the bottom 64 bits?
|
//! to the bottom 64 bits?
|
|
|
//! @return The value shifted out (or the bottom 64 bits thereof if the
|
//! @return The value shifted out (or the bottom 64 bits thereof if the
|
//! register is "large").
|
//! register is "large").
|
uint64_t
|
uint64_t TapActionDRScan::getDRegOut()
|
TapActionDRScan::getDRegOut ()
|
|
{
|
|
if (1 == dRegWordSize)
|
|
{
|
{
|
|
if (1 == dRegWordSize) {
|
return dRegOut;
|
return dRegOut;
|
}
|
} else {
|
else
|
|
{
|
|
return dRegOutArray[0];
|
return dRegOutArray[0];
|
}
|
}
|
} // getDRegOut ()
|
} // getDRegOut ()
|
|
|
|
|
//! Utility to shift the bottom bit out of the dReg.
|
//! Utility to shift the bottom bit out of the dReg.
|
|
|
//! Two flavours depending on whether we have a "small" register
|
//! Two flavours depending on whether we have a "small" register
|
|
|
//! @return The bit shifted out.
|
//! @return The bit shifted out.
|
bool
|
bool TapActionDRScan::shiftDRegOut()
|
TapActionDRScan::shiftDRegOut ()
|
|
{
|
{
|
if (1 == dRegWordSize) // "Small" register
|
if (1 == dRegWordSize) // "Small" register
|
{
|
{
|
bool res = dRegIn & 1;
|
bool res = dRegIn & 1;
|
dRegIn >>= 1;
|
dRegIn >>= 1;
|
return res;
|
return res;
|
}
|
} else // "Large" register
|
else // "Large" register
|
|
{
|
{
|
bool res = (dRegInArray[0] & 1) == 1;
|
bool res = (dRegInArray[0] & 1) == 1;
|
|
|
// Shift all but the first word along
|
// Shift all but the first word along
|
for (int i = 0; i < (dRegWordSize - 1); i++)
|
for (int i = 0; i < (dRegWordSize - 1); i++) {
|
{
|
dRegInArray[i] =
|
dRegInArray[i] = (dRegInArray[i] >> 1) | (dRegInArray[i+1] << 63);
|
(dRegInArray[i] >> 1) | (dRegInArray[i + 1] << 63);
|
}
|
}
|
|
|
// Shift the first word
|
// Shift the first word
|
dRegInArray[dRegWordSize - 1] >>= 1;
|
dRegInArray[dRegWordSize - 1] >>= 1;
|
|
|
return res;
|
return res;
|
}
|
}
|
} // shiftDRegOut ()
|
} // shiftDRegOut ()
|
|
|
|
|
//! Utility to shift the top bit into the dReg.
|
//! Utility to shift the top bit into the dReg.
|
|
|
//! Two flavours depending on whether we have a "small" register
|
//! Two flavours depending on whether we have a "small" register
|
|
|
//! @param bitIn The bit to shift in the top
|
//! @param bitIn The bit to shift in the top
|
void
|
void TapActionDRScan::shiftDRegIn(bool bitIn)
|
TapActionDRScan::shiftDRegIn (bool bitIn)
|
|
{
|
{
|
if (1 == dRegWordSize) // "Small" register
|
if (1 == dRegWordSize) // "Small" register
|
{
|
{
|
dRegOut >>= 1; // Move all the existing bits right
|
dRegOut >>= 1; // Move all the existing bits right
|
|
|
if (bitIn) // OR any new bit in
|
if (bitIn) // OR any new bit in
|
{
|
{
|
uint64_t tmpBit = 1ULL << (dRegBitSize - 1);
|
uint64_t tmpBit = 1ULL << (dRegBitSize - 1);
|
dRegOut |= tmpBit;
|
dRegOut |= tmpBit;
|
}
|
}
|
}
|
} else // "Large" register
|
else // "Large" register
|
|
{
|
{
|
// Shift all but the first word along
|
// Shift all but the first word along
|
for (int i = 0; i < (dRegWordSize - 1); i++)
|
for (int i = 0; i < (dRegWordSize - 1); i++) {
|
{
|
|
dRegOutArray[i] >>= 1;
|
dRegOutArray[i] >>= 1;
|
dRegOutArray[i] |= dRegOutArray[i+1] << 63;
|
dRegOutArray[i] |= dRegOutArray[i+1] << 63;
|
}
|
}
|
|
|
// The first word is shifted and the new bit masked in
|
// The first word is shifted and the new bit masked in
|
dRegOutArray[dRegWordSize - 1] >>= 1;
|
dRegOutArray[dRegWordSize - 1] >>= 1;
|
dRegOutArray[dRegWordSize - 1] |= bitIn ? (topMask + 1) >> 1 : 0;
|
dRegOutArray[dRegWordSize - 1] |=
|
|
bitIn ? (topMask + 1) >> 1 : 0;
|
}
|
}
|
} // shiftDRegIn ()
|
} // shiftDRegIn ()
|
|
|
No newline at end of file
|
No newline at end of file
|