This class implements capture, shift and update of a value through a
data register. Functionally it is very similar to
TapActionIRScan
. However complexity is added,
because data registers may be too large for a single C++ variable,
so must be represented in
arrays. TapActionDRScan
has a number of
private instance variables.
int dRegBitSize
This is the number of bits to be shifted in through TDI
and out
through TDO
.
int dRegWordSize
If dRegBitSize
is more than 64, this is the
number of elements in the uint64_t array used to
represent the input and output registers, with the least
significant bits in element 0.
uint64_t topMask
If register values are held in an array
(i.e. dRegBitSize
is more than 64), any odd
number of bits (if dRegBitSize
is not an
exact multiple of 64) are held in the most significant element
of the array. This is a mask for those bits.
uint64_t *dRegInArray
When the registers are held in an array
(i.e. dRegBitSize
is more than 64), this is a
pointer to the array representing the value being shifted in
through TDI
. It holds the remaining bits to be shifted.
Since the original value is destroyed during processing, this is a copy of the array supplying the original value to the constructor.
uint64_t dRegIn
If the number of bits in a register (held in
dRegBitSize
) is 64 or less, the value to be
shifted through TDI
can be held in this simple variable for
efficiency.
uint64_t *dRegOutArray
When the registers are held in an array
(i.e. dRegBitSize
is more than 64), this is a
pointer to the array representing the value being shifted out
through TDO
. It holds the bits shifted out so far.
uint64_t dRegOut
If the number of bits in a register (held in
dRegBitSize
) is 64 or less, the value being
shifted out through TDO
can be held in this simple variable for
efficiency.
int bitsShifted
The number of bits shifted in so far.
enum { SHIFT_DR_PREPARING, SHIFT_DR_SHIFTING, SHIFT_DR_UPDATING } dRScanState
This enumeration records where the action is in its process. The
process
method follows a state machine (see
below) whose state is recorded here.
As with the instruction register, the primary responsibility of
the constructor is to initialize all
the instance variables. The register size is taken from
the arguments, the count of bits shifted is
zeroed and the DR-Scan process state machine is set to
SHIFT_DR_PREPARING
.
There are two variants depending on whether the value to be
shifted in through TDO
is small enough to fit in a single 64-bit
variable.
In either case, if the number of bits in the register size is greater than 64, the registers will be represented as an array of uint64_t. Otherwise they will be represented as simple uint64_t variables for efficiency.
Where registers are represented as vectors, new vectors of the
correct size are allocated and the supplied input value copied
to the input register. The output register is zeroed. The size of
the vectors is recorded in dRegWordSize
.
Otherwise the input value is copied to the local instance variable
(dRegIn
) and the output value
(dRegOut
) is zeroed.
The destructor is used to delete the local copies of registers where they have been represented as arrays to free the memory.
As with TapActionIRScan
, this method
generates the appropriate values of TDI
and TMS
to process the
action and capture TDI
. It is controlled by its own state machine,
whose state is recorded in iRScanState
as shown
in Figure 3.3
The operations on the registers vary depending on whether the
register is more than 64 bits long. These operations (to shift
bits out for TDI
and in from TDO
) are placed in separate
utility functions, shiftDRegOut
and
shiftDRegIn
(see below).
This function is part of the public API, allowing the user to
access the value shifted through TDO
on completion.
It is provided in two versions. In the first, the result is copied to an array of uint64_t provided as an argument. This version may be used even if the register is 64 bits or smaller. The value will be copied into element 0 of the array.
The second version returns the value as a uint64_t. This version may be used, even if the register is more than 64 bits long. The least significant 64 bits will be returned.
These functions are used to shift the least significant bit out of
dRegInArray
(for use as TDI
) and the shift in
the most significant bit (from TDO
) of
dRegOutArray
. However if the data register is
represented as a scalar uint64_t variable they will
perform the equivalent operation on DRegIn
and
DRegOut
instead.