/* jtag.c -- JTAG modeling
|
/* jtag.c -- JTAG modeling
|
|
|
Copyright (C) 2008 Embecosm Limited
|
Copyright (C) 2008 Embecosm Limited
|
|
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify it
|
This program is free software; you can redistribute it and/or modify it
|
under the terms of the GNU General Public License as published by the Free
|
under the terms of the GNU General Public License as published by the Free
|
Software Foundation; either version 3 of the License, or (at your option)
|
Software Foundation; either version 3 of the License, or (at your option)
|
any later version.
|
any later version.
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
more details.
|
more details.
|
|
|
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
/* This program is commented throughout in a fashion suitable for processing
|
/* This program is commented throughout in a fashion suitable for processing
|
with Doxygen. */
|
with Doxygen. */
|
|
|
|
|
/* Autoconf and/or portability configuration */
|
/* Autoconf and/or portability configuration */
|
#include "config.h"
|
#include "config.h"
|
#include "port.h"
|
#include "port.h"
|
|
|
/* System includes */
|
/* System includes */
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <stddef.h>
|
#include <stddef.h>
|
#include <stdint.h>
|
#include <stdint.h>
|
#include <string.h>
|
#include <string.h>
|
|
|
/* Package includes */
|
/* Package includes */
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
#include "debug-unit.h"
|
#include "debug-unit.h"
|
#include "spr-defs.h"
|
#include "spr-defs.h"
|
#include "jtag.h"
|
#include "jtag.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "toplevel-support.h"
|
#include "toplevel-support.h"
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Calculate an ongoing 32-bit CRC for a value
|
/*!Calculate an ongoing 32-bit CRC for a value
|
|
|
Utility function. This is for a CRC, where the value is presented in normal
|
Utility function. This is for a CRC, where the value is presented in normal
|
order (i.e its most significant bit is at the most significant positions,
|
order (i.e its most significant bit is at the most significant positions,
|
it has not been reversed for incorporating ina JTAG register).
|
it has not been reversed for incorporating ina JTAG register).
|
|
|
The function can be used for values with more than 64 bits, but will treat
|
The function can be used for values with more than 64 bits, but will treat
|
the supplied value as the most-significant 64 bits, with all other bits
|
the supplied value as the most-significant 64 bits, with all other bits
|
zero. In practice this is only of use when shifting in a large number of
|
zero. In practice this is only of use when shifting in a large number of
|
zeros.
|
zeros.
|
|
|
The CRC used is the IEEE 802.3 32-bit CRC using the polynomial:
|
The CRC used is the IEEE 802.3 32-bit CRC using the polynomial:
|
|
|
x^32 + x^26 + x^23 +x^22 +x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 +
|
x^32 + x^26 + x^23 +x^22 +x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 +
|
x^4 + x^2 + x^1 + 1
|
x^4 + x^2 + x^1 + 1
|
|
|
In this implementation, the CRC is initialized to all ones (outside this
|
In this implementation, the CRC is initialized to all ones (outside this
|
function), to catch leading zeros.
|
function), to catch leading zeros.
|
|
|
The function is designed to be used in a continuing calculation if
|
The function is designed to be used in a continuing calculation if
|
desired. It takes a partially computed CRC and shifts in the appropriate
|
desired. It takes a partially computed CRC and shifts in the appropriate
|
new bits for the value supplied. For a new calculation, this value should
|
new bits for the value supplied. For a new calculation, this value should
|
be 0xffffffff.
|
be 0xffffffff.
|
|
|
@param[in] value The number whose CRC is wanted (MSB first)
|
@param[in] value The number whose CRC is wanted (MSB first)
|
@param[in] num_bits The number of bits to use from value
|
@param[in] num_bits The number of bits to use from value
|
@param[in] crc_in The value of the CRC computed so far
|
@param[in] crc_in The value of the CRC computed so far
|
|
|
@return The updated CRC value */
|
@return The updated CRC value */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static uint32_t
|
static uint32_t
|
crc32 (uint64_t value,
|
crc32 (uint64_t value,
|
int num_bits,
|
int num_bits,
|
uint32_t crc_in)
|
uint32_t crc_in)
|
{
|
{
|
static const uint32_t CRC32_POLY = 0x04c11db7;
|
static const uint32_t CRC32_POLY = 0x04c11db7;
|
|
|
/* Incorporate the bits, MS bit first. */
|
/* Incorporate the bits, MS bit first. */
|
int i;
|
int i;
|
|
|
for (i = num_bits - 1; i >= 0; i--)
|
for (i = num_bits - 1; i >= 0; i--)
|
{
|
{
|
uint32_t d = (1 == ((value >> i) & 1)) ? 0xfffffff : 0x0000000;
|
uint32_t d = (1 == ((value >> i) & 1)) ? 0xfffffff : 0x0000000;
|
uint32_t t = (1 == ((crc_in >> 31) & 1)) ? 0xfffffff : 0x0000000;
|
uint32_t t = (1 == ((crc_in >> 31) & 1)) ? 0xfffffff : 0x0000000;
|
|
|
crc_in <<= 1;
|
crc_in <<= 1;
|
crc_in ^= (d ^ t) & CRC32_POLY;
|
crc_in ^= (d ^ t) & CRC32_POLY;
|
}
|
}
|
|
|
return crc_in;
|
return crc_in;
|
|
|
} /* crc32 () */
|
} /* crc32 () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Reverse up to 64 bits in a word
|
/*!Reverse up to 64 bits in a word
|
|
|
Utility function. Uses the "reverse" algorithm from the University of
|
Utility function. Uses the "reverse" algorithm from the University of
|
Kentucky Aggregate Magic Algorithms.
|
Kentucky Aggregate Magic Algorithms.
|
|
|
@param[in] val The long word to reverse
|
@param[in] val The long word to reverse
|
@param[in] numBits Number of bits to reverse
|
@param[in] numBits Number of bits to reverse
|
|
|
@return The reversed word. */
|
@return The reversed word. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static uint64_t
|
static uint64_t
|
reverse_bits (uint64_t val,
|
reverse_bits (uint64_t val,
|
int numBits)
|
int numBits)
|
{
|
{
|
val = (((val & 0xaaaaaaaaaaaaaaaaULL) >> 1) |
|
val = (((val & 0xaaaaaaaaaaaaaaaaULL) >> 1) |
|
((val & 0x5555555555555555ULL) << 1));
|
((val & 0x5555555555555555ULL) << 1));
|
val = (((val & 0xccccccccccccccccULL) >> 2) |
|
val = (((val & 0xccccccccccccccccULL) >> 2) |
|
((val & 0x3333333333333333ULL) << 2));
|
((val & 0x3333333333333333ULL) << 2));
|
val = (((val & 0xf0f0f0f0f0f0f0f0ULL) >> 4) |
|
val = (((val & 0xf0f0f0f0f0f0f0f0ULL) >> 4) |
|
((val & 0x0f0f0f0f0f0f0f0fULL) << 4));
|
((val & 0x0f0f0f0f0f0f0f0fULL) << 4));
|
val = (((val & 0xff00ff00ff00ff00ULL) >> 8) |
|
val = (((val & 0xff00ff00ff00ff00ULL) >> 8) |
|
((val & 0x00ff00ff00ff00ffULL) << 8));
|
((val & 0x00ff00ff00ff00ffULL) << 8));
|
val = (((val & 0xffff0000ffff0000ULL) >> 16) |
|
val = (((val & 0xffff0000ffff0000ULL) >> 16) |
|
((val & 0x0000ffff0000ffffULL) << 16));
|
((val & 0x0000ffff0000ffffULL) << 16));
|
val = ((val >> 32) | (val << 32));
|
val = ((val >> 32) | (val << 32));
|
|
|
return val >> (64 - numBits); /* Only the bits we want */
|
return val >> (64 - numBits); /* Only the bits we want */
|
|
|
} /* reverse_bits () */
|
} /* reverse_bits () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Reverse a byte
|
/*!Reverse a byte
|
|
|
Utility function. Uses the "reverse" algorithm from the University of
|
Utility function. Uses the "reverse" algorithm from the University of
|
Kentucky Aggregate Magic Algorithms.
|
Kentucky Aggregate Magic Algorithms.
|
|
|
@param[in] byte The byte to reverse
|
@param[in] byte The byte to reverse
|
|
|
@return The reversed byte. */
|
@return The reversed byte. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static uint8_t
|
static uint8_t
|
reverse_byte (uint8_t byte)
|
reverse_byte (uint8_t byte)
|
{
|
{
|
byte = (((byte & 0xaa) >> 1) | ((byte & 0x55) << 1));
|
byte = (((byte & 0xaa) >> 1) | ((byte & 0x55) << 1));
|
byte = (((byte & 0xcc) >> 2) | ((byte & 0x33) << 2));
|
byte = (((byte & 0xcc) >> 2) | ((byte & 0x33) << 2));
|
|
|
return ((byte >> 4) | (byte << 4));
|
return ((byte >> 4) | (byte << 4));
|
|
|
} /* reverse_byte () */
|
} /* reverse_byte () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Construct a response register to shift out.
|
/*!Construct a response register to shift out.
|
|
|
The generic format is:
|
The generic format is:
|
|
|
+-------+--------+---------+---------+
|
+-------+--------+---------+---------+
|
| | | | |
|
| | | | |
|
TDI -> | CRC | Status | XX..XX | 00..00 | -> TDO
|
TDI -> | CRC | Status | XX..XX | 00..00 | -> TDO
|
| | | | |
|
| | | | |
|
+-------+--------+---------+---------+
|
+-------+--------+---------+---------+
|
32 4 "ignored" "zero"
|
32 4 "ignored" "zero"
|
bits bits bits bits
|
bits bits bits bits
|
|
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC is
|
Fields are always shifted in MS bit first, so must be reversed. The CRC is
|
on the 4 status bits. Only the "zero" bits are zeroed. This allows for
|
on the 4 status bits. Only the "zero" bits are zeroed. This allows for
|
other fields to be specified in the "ignored" bits region, which are
|
other fields to be specified in the "ignored" bits region, which are
|
guaranteed to be left untouched.
|
guaranteed to be left untouched.
|
|
|
@param[out] jreg The buffer for the constructed register
|
@param[out] jreg The buffer for the constructed register
|
@param[in] status The status bits
|
@param[in] status The status bits
|
@param[in] crc_in CRC computed so far (set to 0xffffffff if none)
|
@param[in] crc_in CRC computed so far (set to 0xffffffff if none)
|
@param[in] ign_bits The number of bits to ignore
|
@param[in] ign_bits The number of bits to ignore
|
@param[in] zero_bits The number of bits to zero */
|
@param[in] zero_bits The number of bits to zero */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
construct_response (unsigned char *jreg,
|
construct_response (unsigned char *jreg,
|
uint8_t status,
|
uint8_t status,
|
uint32_t crc_in,
|
uint32_t crc_in,
|
unsigned int ign_bits,
|
unsigned int ign_bits,
|
unsigned int zero_bits)
|
unsigned int zero_bits)
|
{
|
{
|
/* Construct the outgoing CRC */
|
/* Construct the outgoing CRC */
|
uint32_t crc_out = crc32 (status, 4, crc_in);
|
uint32_t crc_out = crc32 (status, 4, crc_in);
|
|
|
/* Reversed versions of fields ready for insertion */
|
/* Reversed versions of fields ready for insertion */
|
uint8_t status_r = reverse_bits (status, 4);
|
uint8_t status_r = reverse_bits (status, 4);
|
uint32_t crc_out_r = reverse_bits (crc_out, 32);
|
uint32_t crc_out_r = reverse_bits (crc_out, 32);
|
|
|
/* Construct the response register */
|
/* Construct the response register */
|
unsigned int zero_bytes = zero_bits / 8;
|
unsigned int zero_bytes = zero_bits / 8;
|
unsigned int zero_off = zero_bits % 8;
|
unsigned int zero_off = zero_bits % 8;
|
|
|
/* Clear the zero bits */
|
/* Clear the zero bits */
|
if (zero_bytes > 0)
|
if (zero_bytes > 0)
|
{
|
{
|
memset (jreg, 0, zero_bytes);
|
memset (jreg, 0, zero_bytes);
|
}
|
}
|
|
|
jreg[zero_bytes] >>= zero_off;
|
jreg[zero_bytes] >>= zero_off;
|
jreg[zero_bytes] <<= zero_off;
|
jreg[zero_bytes] <<= zero_off;
|
|
|
/* Determine how much to skip in total */
|
/* Determine how much to skip in total */
|
unsigned int skip_bytes = (ign_bits + zero_bits) / 8;
|
unsigned int skip_bytes = (ign_bits + zero_bits) / 8;
|
unsigned int bit_off = (ign_bits + zero_bits) % 8;
|
unsigned int bit_off = (ign_bits + zero_bits) % 8;
|
|
|
/* Simplify by dealing separately with two cases:
|
/* Simplify by dealing separately with two cases:
|
- the bit offset is less than or equal to 4, so the status goes in the
|
- the bit offset is less than or equal to 4, so the status goes in the
|
first free byte, with some CRC.
|
first free byte, with some CRC.
|
- the bit offset is greater than 4 but less than 8, so the status goes in
|
- the bit offset is greater than 4 but less than 8, so the status goes in
|
the first and second free bytes.
|
the first and second free bytes.
|
|
|
For completeness we deal with what should be the impossible case of
|
For completeness we deal with what should be the impossible case of
|
bit_off > 7. */
|
bit_off > 7. */
|
if (bit_off <= 4)
|
if (bit_off <= 4)
|
{
|
{
|
/* Note that this works even if bit_off == 4, since there will be no CRC
|
/* Note that this works even if bit_off == 4, since there will be no CRC
|
remaining to OR into the first byte. */
|
remaining to OR into the first byte. */
|
jreg[skip_bytes] |= ((status_r & 0xf) << bit_off) |
|
jreg[skip_bytes] |= ((status_r & 0xf) << bit_off) |
|
((crc_out_r << (4 + bit_off)) & 0xff);
|
((crc_out_r << (4 + bit_off)) & 0xff);
|
jreg[skip_bytes + 1] = (crc_out_r >> ( 4 - bit_off)) & 0xff;
|
jreg[skip_bytes + 1] = (crc_out_r >> ( 4 - bit_off)) & 0xff;
|
jreg[skip_bytes + 2] = (crc_out_r >> (12 - bit_off)) & 0xff;
|
jreg[skip_bytes + 2] = (crc_out_r >> (12 - bit_off)) & 0xff;
|
jreg[skip_bytes + 3] = (crc_out_r >> (20 - bit_off)) & 0xff;
|
jreg[skip_bytes + 3] = (crc_out_r >> (20 - bit_off)) & 0xff;
|
jreg[skip_bytes + 4] = (crc_out_r >> (28 - bit_off)) & 0xff;
|
jreg[skip_bytes + 4] = (crc_out_r >> (28 - bit_off)) & 0xff;
|
}
|
}
|
else if (bit_off < 8)
|
else if (bit_off < 8)
|
{
|
{
|
jreg[skip_bytes] |= status_r << bit_off;
|
jreg[skip_bytes] |= status_r << bit_off;
|
jreg[skip_bytes + 1] = (status_r >> (8 - bit_off)) |
|
jreg[skip_bytes + 1] = (status_r >> (8 - bit_off)) |
|
((crc_out_r << (bit_off - 4)) & 0xff);
|
((crc_out_r << (bit_off - 4)) & 0xff);
|
jreg[skip_bytes + 2] = (crc_out_r >> (12 - bit_off)) & 0xff;
|
jreg[skip_bytes + 2] = (crc_out_r >> (12 - bit_off)) & 0xff;
|
jreg[skip_bytes + 3] = (crc_out_r >> (20 - bit_off)) & 0xff;
|
jreg[skip_bytes + 3] = (crc_out_r >> (20 - bit_off)) & 0xff;
|
jreg[skip_bytes + 4] = (crc_out_r >> (28 - bit_off)) & 0xff;
|
jreg[skip_bytes + 4] = (crc_out_r >> (28 - bit_off)) & 0xff;
|
jreg[skip_bytes + 5] = (crc_out_r >> (36 - bit_off)) & 0xff;
|
jreg[skip_bytes + 5] = (crc_out_r >> (36 - bit_off)) & 0xff;
|
}
|
}
|
else
|
else
|
{
|
{
|
fprintf (stderr, "*** ABORT ***: construct_response: impossible bit "
|
fprintf (stderr, "*** ABORT ***: construct_response: impossible bit "
|
"offset: %u.\n", bit_off);
|
"offset: %u.\n", bit_off);
|
abort ();
|
abort ();
|
}
|
}
|
} /* construct_response () */
|
} /* construct_response () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Select a module for debug
|
/*!Select a module for debug
|
|
|
Process a module selection register. The format is:
|
Process a module selection register. The format is:
|
|
|
+---------+-------+--------+---+
|
+---------+-------+--------+---+
|
| | | | |
|
| | | | |
|
TDI -> | Ignored | CRC | Module | 1 | -> TDO
|
TDI -> | Ignored | CRC | Module | 1 | -> TDO
|
| | | ID | |
|
| | | ID | |
|
+---------+-------+--------+---+
|
+---------+-------+--------+---+
|
36 32 4
|
36 32 4
|
bits bits bits
|
bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+---------+
|
+-------+--------+---------+
|
| | | |
|
| | | |
|
TDI -> | CRC | Status | 00..00 | -> TDO
|
TDI -> | CRC | Status | 00..00 | -> TDO
|
| | | |
|
| | | |
|
+-------+--------+---------+
|
+-------+--------+---------+
|
32 4 37
|
32 4 37
|
bits bits bits
|
bits bits bits
|
|
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 5 bits, the CRC out on the 4 status bits.
|
is computed on the first 5 bits, the CRC out on the 4 status bits.
|
|
|
This is a register of a fixed size, which we verify initially.
|
This is a register of a fixed size, which we verify initially.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied.
|
@param[in] num_bits The number of bits supplied.
|
|
|
@return The number of cycles the shift took, which in turn is the number
|
@return The number of cycles the shift took, which in turn is the number
|
of bits in the register */
|
of bits in the register */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
select_module (unsigned char *jreg,
|
select_module (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Validate register size, which is fixed */
|
/* Validate register size, which is fixed */
|
const int REG_BITS = 36 + 32 + 4 + 1;
|
const int REG_BITS = 36 + 32 + 4 + 1;
|
|
|
if (REG_BITS != num_bits)
|
if (REG_BITS != num_bits)
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG module select %d bits, when %d bits expected.\n",
|
"ERROR: JTAG module select %d bits, when %d bits expected.\n",
|
num_bits, REG_BITS);
|
num_bits, REG_BITS);
|
return;
|
return;
|
}
|
}
|
|
|
/* Break out the fields */
|
/* Break out the fields */
|
uint8_t mod_id = reverse_bits ((jreg[0] >> 1) & 0xf, 4);
|
uint8_t mod_id = reverse_bits ((jreg[0] >> 1) & 0xf, 4);
|
uint32_t crc_in = reverse_bits (((uint32_t ) (jreg[0] & 0xe0) >> 5) |
|
uint32_t crc_in = reverse_bits (((uint32_t ) (jreg[0] & 0xe0) >> 5) |
|
((uint32_t ) jreg[1] << 3) |
|
((uint32_t ) jreg[1] << 3) |
|
((uint32_t ) jreg[2] << 11) |
|
((uint32_t ) jreg[2] << 11) |
|
((uint32_t ) jreg[3] << 19) |
|
((uint32_t ) jreg[3] << 19) |
|
((uint32_t ) (jreg[4] & 0x1f) << 27), 32);
|
((uint32_t ) (jreg[4] & 0x1f) << 27), 32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (1, 1, 0xffffffff);
|
crc_computed = crc32 (1, 1, 0xffffffff);
|
crc_computed = crc32 (mod_id, 4, crc_computed);
|
crc_computed = crc32 (mod_id, 4, crc_computed);
|
|
|
/* Status flags */
|
/* Status flags */
|
enum jtag_status status = JS_OK;
|
enum jtag_status status = JS_OK;
|
|
|
/* Validate the CRC */
|
/* Validate the CRC */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
/* Is it a valid module? */
|
/* Is it a valid module? */
|
switch (mod_id)
|
switch (mod_id)
|
{
|
{
|
case JM_WISHBONE:
|
case JM_WISHBONE:
|
case JM_CPU0:
|
case JM_CPU0:
|
case JM_CPU1:
|
case JM_CPU1:
|
/* All valid. Record the module */
|
/* All valid. Record the module */
|
runtime.debug.mod_id = mod_id;
|
runtime.debug.mod_id = mod_id;
|
|
|
break;
|
break;
|
|
|
default:
|
default:
|
/* Bad module: record the error. Set the module to JM_UNDEFINED,
|
/* Bad module: record the error. Set the module to JM_UNDEFINED,
|
which will trigger more errors in the future, rather than
|
which will trigger more errors in the future, rather than
|
leaving the module unchanged, which might allow such errors to
|
leaving the module unchanged, which might allow such errors to
|
slip by undetected. */
|
slip by undetected. */
|
status |= JS_MODULE_MISSING;
|
status |= JS_MODULE_MISSING;
|
runtime.debug.mod_id = JM_UNDEFINED;
|
runtime.debug.mod_id = JM_UNDEFINED;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* CRC Mismatch: record the error */
|
/* CRC Mismatch: record the error */
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
/* Construct the outgoing register and return the JTAG cycles taken (the
|
/* Construct the outgoing register and return the JTAG cycles taken (the
|
register length) */
|
register length) */
|
return construct_response (jreg, status, 0xffffffff, 0, 37);
|
return construct_response (jreg, status, 0xffffffff, 0, 37);
|
|
|
} /* select_module */
|
} /* select_module */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Read WishBone data
|
/*!Read WishBone data
|
|
|
Read memory from WishBone. The WRITE_COMMAND address is updated to reflect
|
Read memory from WishBone. The WRITE_COMMAND address is updated to reflect
|
the completed read if successful.
|
the completed read if successful.
|
|
|
The data follows an initial 37 bits corresponding to the incoming command
|
The data follows an initial 37 bits corresponding to the incoming command
|
and CRC. We use the smaller of the data size in the original WRITE_COMMAND
|
and CRC. We use the smaller of the data size in the original WRITE_COMMAND
|
and the size of the data in the GO_COMMAND_WRITE packet, so we can handle
|
and the size of the data in the GO_COMMAND_WRITE packet, so we can handle
|
over/under-run.
|
over/under-run.
|
|
|
The result is the CRC of the data read. The status flag is supplied as a
|
The result is the CRC of the data read. The status flag is supplied as a
|
pointer, since this can also be updated if there is a problem reading the
|
pointer, since this can also be updated if there is a problem reading the
|
data.
|
data.
|
|
|
@note The size of the data is one greater than the length specified in the
|
@note The size of the data is one greater than the length specified in the
|
original WRITE_COMMAND.
|
original WRITE_COMMAND.
|
|
|
@todo For now we always read a byte a time. In the future, we ought to use
|
@todo For now we always read a byte a time. In the future, we ought to use
|
16 and 32-bit accesses for greater efficiency.
|
16 and 32-bit accesses for greater efficiency.
|
|
|
@todo The algorithm for ensuring we only set the bits of interest in the
|
@todo The algorithm for ensuring we only set the bits of interest in the
|
register is inefficient. We should instead clear the whole area
|
register is inefficient. We should instead clear the whole area
|
before starting.
|
before starting.
|
|
|
@param[out] jreg The JTAG register buffer where data is to be
|
@param[out] jreg The JTAG register buffer where data is to be
|
stored.
|
stored.
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
(may be different to that in the prior READ/WRITE
|
(may be different to that in the prior READ/WRITE
|
if we have over- or under-run).
|
if we have over- or under-run).
|
@param[in] status_ptr Pointer to the status register.
|
@param[in] status_ptr Pointer to the status register.
|
|
|
@return The CRC of the data read */
|
@return The CRC of the data read */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static uint32_t
|
static uint32_t
|
wishbone_read (unsigned char *jreg,
|
wishbone_read (unsigned char *jreg,
|
unsigned long int jreg_bytes,
|
unsigned long int jreg_bytes,
|
enum jtag_status *status_ptr)
|
enum jtag_status *status_ptr)
|
{
|
{
|
const unsigned int BIT_OFF = 37 % 8; /* Skip initial fields */
|
const unsigned int BIT_OFF = 37 % 8; /* Skip initial fields */
|
const unsigned int BYTE_OFF = 37 / 8;
|
const unsigned int BYTE_OFF = 37 / 8;
|
|
|
/* Transfer each byte in turn, computing the CRC as we go. We must supply
|
/* Transfer each byte in turn, computing the CRC as we go. We must supply
|
jreg_bytes. If there is overrun, we use zero for the remaining bytes. */
|
jreg_bytes. If there is overrun, we use zero for the remaining bytes. */
|
uint32_t crc_out = 0xffffffff;
|
uint32_t crc_out = 0xffffffff;
|
unsigned long int i;
|
unsigned long int i;
|
|
|
for (i = 0; i < jreg_bytes; i++)
|
for (i = 0; i < jreg_bytes; i++)
|
{
|
{
|
unsigned char byte = 0;
|
unsigned char byte = 0;
|
|
|
/* Get a byte if available */
|
/* Get a byte if available */
|
if (i < runtime.debug.size)
|
if (i < runtime.debug.size)
|
{
|
{
|
/* Error if we can't access this byte */
|
/* Error if we can't access this byte */
|
if (NULL == verify_memoryarea (runtime.debug.addr + i))
|
if (NULL == verify_memoryarea (runtime.debug.addr + i))
|
{
|
{
|
*status_ptr |= JS_WISHBONE_ERROR;
|
*status_ptr |= JS_WISHBONE_ERROR;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Get the data with no cache or VM translation */
|
/* Get the data with no cache or VM translation */
|
byte = eval_direct8 (runtime.debug.addr + i, 0, 0);
|
byte = eval_direct8 (runtime.debug.addr + i, 0, 0);
|
}
|
}
|
}
|
}
|
|
|
/* Update the CRC, reverse, then store the byte in the register, without
|
/* Update the CRC, reverse, then store the byte in the register, without
|
trampling adjacent bits. Simplified version when the bit offset is
|
trampling adjacent bits. Simplified version when the bit offset is
|
zero. */
|
zero. */
|
crc_out = crc32 (byte, 8, crc_out);
|
crc_out = crc32 (byte, 8, crc_out);
|
byte = reverse_byte (byte);
|
byte = reverse_byte (byte);
|
|
|
/* Clear the bits (only) we are setting */
|
/* Clear the bits (only) we are setting */
|
jreg[BYTE_OFF + i] <<= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] <<= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] >>= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] >>= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i + 1] >>= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] >>= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] <<= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] <<= BIT_OFF;
|
|
|
/* OR in the bits */
|
/* OR in the bits */
|
jreg[BYTE_OFF + i] |= (byte << BIT_OFF) & 0xff;
|
jreg[BYTE_OFF + i] |= (byte << BIT_OFF) & 0xff;
|
jreg[BYTE_OFF + i + 1] |= (byte >> (8 - BIT_OFF)) & 0xff;
|
jreg[BYTE_OFF + i + 1] |= (byte >> (8 - BIT_OFF)) & 0xff;
|
}
|
}
|
|
|
/* Only advance if there we no errors (including over/under-run. */
|
/* Only advance if there we no errors (including over/under-run. */
|
if (JS_OK == *status_ptr)
|
if (JS_OK == *status_ptr)
|
{
|
{
|
runtime.debug.addr += runtime.debug.size;
|
runtime.debug.addr += runtime.debug.size;
|
}
|
}
|
|
|
return crc_out;
|
return crc_out;
|
|
|
} /* wishbone_read () */
|
} /* wishbone_read () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Read SPR data
|
/*!Read SPR data
|
|
|
Read memory from a SPR. The WRITE_COMMAND address is updated to reflect the
|
Read memory from a SPR. The WRITE_COMMAND address is updated to reflect the
|
completed read if successful.
|
completed read if successful.
|
|
|
The data follows an initial 37 bits corresponding to the incoming command
|
The data follows an initial 37 bits corresponding to the incoming command
|
and CRC. We use the smaller of the data size in the original WRITE_COMMAND
|
and CRC. We use the smaller of the data size in the original WRITE_COMMAND
|
and the size of the data in the GO_COMMAND_WRITE packet, so we can handle
|
and the size of the data in the GO_COMMAND_WRITE packet, so we can handle
|
over/under-run.
|
over/under-run.
|
|
|
The result is the CRC of the data read.
|
The result is the CRC of the data read.
|
|
|
Unlike with Wishbone, there is no concept of any errors possible when
|
Unlike with Wishbone, there is no concept of any errors possible when
|
reading an SPR.
|
reading an SPR.
|
|
|
@todo The algorithm for ensuring we only set the bits of interest in the
|
@todo The algorithm for ensuring we only set the bits of interest in the
|
register is inefficient. We should instead clear the whole area
|
register is inefficient. We should instead clear the whole area
|
before starting.
|
before starting.
|
|
|
@note The address is treated as a word address of the SPR.
|
@note The address is treated as a word address of the SPR.
|
|
|
@note The debug unit is documented as being explicitly Big Endian. However
|
@note The debug unit is documented as being explicitly Big Endian. However
|
that seems to be a poor basis for modeling, and more to do with the
|
that seems to be a poor basis for modeling, and more to do with the
|
debug unit only ever being used with big-endian architectures. We
|
debug unit only ever being used with big-endian architectures. We
|
transfer the bytes in the endianness of the OR1K.
|
transfer the bytes in the endianness of the OR1K.
|
|
|
@param[out] jreg The JTAG register buffer where data is to be stored.
|
@param[out] jreg The JTAG register buffer where data is to be stored.
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
(may be different to that in the prior READ/WRITE
|
(may be different to that in the prior READ/WRITE
|
if we have over- or under-run).
|
if we have over- or under-run).
|
@param[in] status_ptr Pointer to the status register.
|
@param[in] status_ptr Pointer to the status register.
|
|
|
@return The CRC of the data read */
|
@return The CRC of the data read */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static uint32_t
|
static uint32_t
|
spr_read (unsigned char *jreg,
|
spr_read (unsigned char *jreg,
|
unsigned long int jreg_bytes,
|
unsigned long int jreg_bytes,
|
enum jtag_status *status_ptr)
|
enum jtag_status *status_ptr)
|
{
|
{
|
const unsigned int BIT_OFF = 37 % 8; /* Skip initial fields */
|
const unsigned int BIT_OFF = 37 % 8; /* Skip initial fields */
|
const unsigned int BYTE_OFF = 37 / 8;
|
const unsigned int BYTE_OFF = 37 / 8;
|
|
|
/* Store the SPR in the register, without trampling adjacent bits, computing
|
/* Store the SPR in the register, without trampling adjacent bits, computing
|
the CRC as we go. We have to fill all the JTAG register bytes. If there
|
the CRC as we go. We have to fill all the JTAG register bytes. If there
|
is overrun, we pack in zeros. */
|
is overrun, we pack in zeros. */
|
uint32_t spr = mfspr (runtime.debug.addr);
|
uint32_t spr = mfspr (runtime.debug.addr);
|
uint32_t crc_out = 0xffffffff;
|
uint32_t crc_out = 0xffffffff;
|
unsigned long int i;
|
unsigned long int i;
|
|
|
for (i = 0; i < jreg_bytes; i++)
|
for (i = 0; i < jreg_bytes; i++)
|
{
|
{
|
unsigned char byte = 0;
|
unsigned char byte = 0;
|
|
|
/* Get the byte from the SPR if available, otherwise use zero */
|
/* Get the byte from the SPR if available, otherwise use zero */
|
if (i < 4)
|
if (i < 4)
|
{
|
{
|
#ifdef OR32_BIG_ENDIAN
|
#ifdef OR32_BIG_ENDIAN
|
byte = (spr >> 8 * i) & 0xff;
|
byte = (spr >> 8 * i) & 0xff;
|
#else /* !OR32_BIG_ENDIAN */
|
#else /* !OR32_BIG_ENDIAN */
|
byte = (spr >> (24 - (8 * i))) & 0xff;
|
byte = (spr >> (24 - (8 * i))) & 0xff;
|
#endif /* OR32_BIG_ENDIAN */
|
#endif /* OR32_BIG_ENDIAN */
|
}
|
}
|
|
|
/* Update the CRC */
|
/* Update the CRC */
|
crc_out = crc32 (byte, 8, crc_out);
|
crc_out = crc32 (byte, 8, crc_out);
|
|
|
/* Reverse, then store the byte in the register, without trampling
|
/* Reverse, then store the byte in the register, without trampling
|
adjacent bits. */
|
adjacent bits. */
|
byte = reverse_byte (byte);
|
byte = reverse_byte (byte);
|
|
|
/* Clear the bits (only) we are setting */
|
/* Clear the bits (only) we are setting */
|
jreg[BYTE_OFF + i] <<= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] <<= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] >>= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] >>= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i + 1] >>= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] >>= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] <<= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] <<= BIT_OFF;
|
|
|
/* OR in the bits */
|
/* OR in the bits */
|
jreg[BYTE_OFF + i] |= (byte << BIT_OFF) & 0xff;
|
jreg[BYTE_OFF + i] |= (byte << BIT_OFF) & 0xff;
|
jreg[BYTE_OFF + i + 1] |= (byte >> (8 - BIT_OFF)) & 0xff;
|
jreg[BYTE_OFF + i + 1] |= (byte >> (8 - BIT_OFF)) & 0xff;
|
}
|
}
|
|
|
/* Only advance if there we no errors (including over/under-run). */
|
/* Only advance if there we no errors (including over/under-run). */
|
if (JS_OK == *status_ptr)
|
if (JS_OK == *status_ptr)
|
{
|
{
|
runtime.debug.addr++;
|
runtime.debug.addr++;
|
}
|
}
|
|
|
return crc_out;
|
return crc_out;
|
|
|
} /* spr_read () */
|
} /* spr_read () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Set up null data.
|
/*!Set up null data.
|
|
|
When there is an error in GO_COMMAND_READ, the data fields must be
|
When there is an error in GO_COMMAND_READ, the data fields must be
|
populated and the CRC set up, to ensure a correct return.
|
populated and the CRC set up, to ensure a correct return.
|
|
|
The data follows an initial 37 bits corresponding to the incoming command
|
The data follows an initial 37 bits corresponding to the incoming command
|
and CRC. We use the smaller of the data size in the original WRITE_COMMAND
|
and CRC. We use the smaller of the data size in the original WRITE_COMMAND
|
and the size of the data in the GO_COMMAND_WRITE packet, so we can handle
|
and the size of the data in the GO_COMMAND_WRITE packet, so we can handle
|
over/under-run.
|
over/under-run.
|
|
|
@param[out] jreg The JTAG register buffer where data is to be stored.
|
@param[out] jreg The JTAG register buffer where data is to be stored.
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
(may be different to that in the prior READ/WRITE
|
(may be different to that in the prior READ/WRITE
|
if we have over- or under-run).
|
if we have over- or under-run).
|
|
|
@return The CRC of the data read */
|
@return The CRC of the data read */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static uint32_t
|
static uint32_t
|
null_read (unsigned char *jreg,
|
null_read (unsigned char *jreg,
|
unsigned long int jreg_bytes)
|
unsigned long int jreg_bytes)
|
{
|
{
|
const unsigned int BIT_OFF = 37 % 8; /* Skip initial fields */
|
const unsigned int BIT_OFF = 37 % 8; /* Skip initial fields */
|
const unsigned int BYTE_OFF = 37 / 8;
|
const unsigned int BYTE_OFF = 37 / 8;
|
|
|
/* Store each null byte in turn, computing the CRC as we go */
|
/* Store each null byte in turn, computing the CRC as we go */
|
uint32_t crc_out = 0xffffffff;
|
uint32_t crc_out = 0xffffffff;
|
unsigned long int i;
|
unsigned long int i;
|
|
|
for (i = 0; i < jreg_bytes; i++)
|
for (i = 0; i < jreg_bytes; i++)
|
{
|
{
|
crc_out = crc32 (0, 8, crc_out); /* Compute the CRC for null byte */
|
crc_out = crc32 (0, 8, crc_out); /* Compute the CRC for null byte */
|
|
|
/* Store null byte in the register, without trampling adjacent
|
/* Store null byte in the register, without trampling adjacent
|
bits. */
|
bits. */
|
jreg[BYTE_OFF + i] <<= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] <<= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] >>= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i] >>= 8 - BIT_OFF;
|
jreg[BYTE_OFF + i + 1] >>= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] >>= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] <<= BIT_OFF;
|
jreg[BYTE_OFF + i + 1] <<= BIT_OFF;
|
}
|
}
|
|
|
return crc_out;
|
return crc_out;
|
|
|
} /* null_read () */
|
} /* null_read () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Carry out a read from WishBone or SPR
|
/*!Carry out a read from WishBone or SPR
|
|
|
Process a GO_COMMAND register for read. The format is:
|
Process a GO_COMMAND register for read. The format is:
|
|
|
+-------------+-------+---------+---+
|
+-------------+-------+---------+---+
|
| | | GO | |
|
| | | GO | |
|
TDI -> | Ignored | CRC | COMMAND | 0 | -> TDO
|
TDI -> | Ignored | CRC | COMMAND | 0 | -> TDO
|
| | | (0x0) | |
|
| | | (0x0) | |
|
+-------------+-------+---------+---+
|
+-------------+-------+---------+---+
|
36 + 8 * size 32 4
|
36 + 8 * size 32 4
|
bits bits bits
|
bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+------------+---------+
|
+-------+--------+------------+---------+
|
| | | | |
|
| | | | |
|
TDI -> | CRC | Status | Data | 00..00 | -> TDO
|
TDI -> | CRC | Status | Data | 00..00 | -> TDO
|
| | | | |
|
| | | | |
|
+-------+--------+------------+---------+
|
+-------+--------+------------+---------+
|
32 4 8 * size 37
|
32 4 8 * size 37
|
bits bits bits bits
|
bits bits bits bits
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 5 bits, the CRC out on the 4 + 8 * size status and
|
is computed on the first 5 bits, the CRC out on the 4 + 8 * size status and
|
data bits.
|
data bits.
|
|
|
@note The size of the data is one greater than the length specified in the
|
@note The size of the data is one greater than the length specified in the
|
original WRITE_COMMAND.
|
original WRITE_COMMAND.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
go_command_read (unsigned char *jreg,
|
go_command_read (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Check the length is consistent with the prior WRITE_COMMAND. If not we
|
/* Check the length is consistent with the prior WRITE_COMMAND. If not we
|
have overrun or underrun and flag accordingly. */
|
have overrun or underrun and flag accordingly. */
|
const int REG_BITS = 36 + 8 * runtime.debug.size + 32 + 4 + 1;
|
const int REG_BITS = 36 + 8 * runtime.debug.size + 32 + 4 + 1;
|
unsigned long int jreg_bytes;
|
unsigned long int jreg_bytes;
|
enum jtag_status status;
|
enum jtag_status status;
|
|
|
if (REG_BITS == num_bits)
|
if (REG_BITS == num_bits)
|
{
|
{
|
jreg_bytes = runtime.debug.size;
|
jreg_bytes = runtime.debug.size;
|
status = JS_OK;
|
status = JS_OK;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Size will round down for safety */
|
/* Size will round down for safety */
|
jreg_bytes = (runtime.debug.size * 8 + num_bits - REG_BITS) / 8;
|
jreg_bytes = (runtime.debug.size * 8 + num_bits - REG_BITS) / 8;
|
status = JS_OVER_UNDERRUN;
|
status = JS_OVER_UNDERRUN;
|
}
|
}
|
|
|
/* Break out the fields */
|
/* Break out the fields */
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[0] & 0xe0) >> 5) |
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[0] & 0xe0) >> 5) |
|
((uint32_t) jreg[1] << 3) |
|
((uint32_t) jreg[1] << 3) |
|
((uint32_t) jreg[2] << 11) |
|
((uint32_t) jreg[2] << 11) |
|
((uint32_t) jreg[3] << 19) |
|
((uint32_t) jreg[3] << 19) |
|
((uint32_t) (jreg[4] & 0x1f) << 27), 32);
|
((uint32_t) (jreg[4] & 0x1f) << 27), 32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (JCMD_GO_COMMAND, 4, crc_computed);
|
crc_computed = crc32 (JCMD_GO_COMMAND, 4, crc_computed);
|
|
|
/* CRC to go out */
|
/* CRC to go out */
|
uint32_t crc_out = 0;
|
uint32_t crc_out = 0;
|
|
|
/* Validate the CRC */
|
/* Validate the CRC */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
/* Read the data. Module errors will have been detected earlier, so we
|
/* Read the data. Module errors will have been detected earlier, so we
|
do nothing more here. */
|
do nothing more here. */
|
switch (runtime.debug.mod_id)
|
switch (runtime.debug.mod_id)
|
{
|
{
|
case JM_WISHBONE:
|
case JM_WISHBONE:
|
crc_out = wishbone_read (jreg, jreg_bytes, &status);
|
crc_out = wishbone_read (jreg, jreg_bytes, &status);
|
break;
|
break;
|
|
|
case JM_CPU0:
|
case JM_CPU0:
|
crc_out = spr_read (jreg, jreg_bytes, &status);
|
crc_out = spr_read (jreg, jreg_bytes, &status);
|
break;
|
break;
|
|
|
default:
|
default:
|
crc_out = null_read (jreg, jreg_bytes);
|
crc_out = null_read (jreg, jreg_bytes);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Mismatch: record the error */
|
/* Mismatch: record the error */
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
/* Construct the outgoing register, skipping the data read and returning the
|
/* Construct the outgoing register, skipping the data read and returning the
|
number of JTAG cycles taken (the register length). */
|
number of JTAG cycles taken (the register length). */
|
construct_response (jreg, status, crc_out, 8UL * jreg_bytes, 37);
|
construct_response (jreg, status, crc_out, 8UL * jreg_bytes, 37);
|
|
|
} /* go_command_read () */
|
} /* go_command_read () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Write WishBone data
|
/*!Write WishBone data
|
|
|
Write memory to WishBone. The WRITE_COMMAND address is updated to reflect
|
Write memory to WishBone. The WRITE_COMMAND address is updated to reflect
|
the completed write if successful.
|
the completed write if successful.
|
|
|
The data follows an initial 5 bits specifying the command. We use the
|
The data follows an initial 5 bits specifying the command. We use the
|
smaller of the data size in the original WRITE_COMMAND and the size of the
|
smaller of the data size in the original WRITE_COMMAND and the size of the
|
data in the GO_COMMAND_WRITE packet, so we can handle over/under-run.
|
data in the GO_COMMAND_WRITE packet, so we can handle over/under-run.
|
|
|
@note The size of the data is one greater than the length specified in the
|
@note The size of the data is one greater than the length specified in the
|
original WRITE_COMMAND.
|
original WRITE_COMMAND.
|
|
|
@todo For now we always write a byte a time. In the future, we ought to use
|
@todo For now we always write a byte a time. In the future, we ought to use
|
16 and 32-bit accesses for greater efficiency and to correctly model
|
16 and 32-bit accesses for greater efficiency and to correctly model
|
the use of different access types.
|
the use of different access types.
|
|
|
@param[in] jreg The JTAG register buffer where data is found.
|
@param[in] jreg The JTAG register buffer where data is found.
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
(may be different to that in the prior READ/WRITE
|
(may be different to that in the prior READ/WRITE
|
if we have over- or under-run).
|
if we have over- or under-run).
|
@param[out] status_ptr Pointer to the status register. */
|
@param[out] status_ptr Pointer to the status register. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
wishbone_write (unsigned char *jreg,
|
wishbone_write (unsigned char *jreg,
|
unsigned long int jreg_bytes,
|
unsigned long int jreg_bytes,
|
enum jtag_status *status_ptr)
|
enum jtag_status *status_ptr)
|
{
|
{
|
const unsigned int BIT_OFF = 5; /* Skip initial command */
|
const unsigned int BIT_OFF = 5; /* Skip initial command */
|
|
|
/* Transfer each byte in turn, computing the CRC as we go. We must supply
|
/* Transfer each byte in turn, computing the CRC as we go. We must supply
|
jreg_bytes. If there is overrun, we ignore the remaining bytes. */
|
jreg_bytes. If there is overrun, we ignore the remaining bytes. */
|
unsigned long int i;
|
unsigned long int i;
|
|
|
for (i = 0; i < jreg_bytes; i++)
|
for (i = 0; i < jreg_bytes; i++)
|
{
|
{
|
/* Set a byte if available */
|
/* Set a byte if available */
|
if (i < runtime.debug.size)
|
if (i < runtime.debug.size)
|
{
|
{
|
/* Error if we can't access this byte */
|
/* Error if we can't access this byte */
|
if (NULL == verify_memoryarea (runtime.debug.addr + i))
|
if (NULL == verify_memoryarea (runtime.debug.addr + i))
|
{
|
{
|
*status_ptr |= JS_WISHBONE_ERROR;
|
*status_ptr |= JS_WISHBONE_ERROR;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Extract the byte from the register, reverse it and write it,
|
/* Extract the byte from the register, reverse it and write it,
|
circumventing the usual checks by pretending this is program
|
circumventing the usual checks by pretending this is program
|
memory. */
|
memory. */
|
unsigned char byte;
|
unsigned char byte;
|
|
|
byte = (jreg[i] >> BIT_OFF) | (jreg[i + 1] << (8 - BIT_OFF));
|
byte = (jreg[i] >> BIT_OFF) | (jreg[i + 1] << (8 - BIT_OFF));
|
byte = reverse_byte (byte);
|
byte = reverse_byte (byte);
|
|
|
set_program8 (runtime.debug.addr + i, byte);
|
set_program8 (runtime.debug.addr + i, byte);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
if (JS_OK == *status_ptr)
|
if (JS_OK == *status_ptr)
|
{
|
{
|
runtime.debug.addr += runtime.debug.size;
|
runtime.debug.addr += runtime.debug.size;
|
}
|
}
|
} /* wishbone_write () */
|
} /* wishbone_write () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Write SPR data
|
/*!Write SPR data
|
|
|
Write memory to WishBone. The WRITE_COMMAND address is updated to reflect
|
Write memory to WishBone. The WRITE_COMMAND address is updated to reflect
|
the completed write if successful.
|
the completed write if successful.
|
|
|
The data follows an initial 5 bits specifying the command. We use the
|
The data follows an initial 5 bits specifying the command. We use the
|
smaller of the data size in the original WRITE_COMMAND and the size of the
|
smaller of the data size in the original WRITE_COMMAND and the size of the
|
data in the GO_COMMAND_WRITE packet, so we can handle over/under-run.
|
data in the GO_COMMAND_WRITE packet, so we can handle over/under-run.
|
|
|
Unlike with Wishbone, there is no concept of any errors possible when
|
Unlike with Wishbone, there is no concept of any errors possible when
|
writing an SPR.
|
writing an SPR.
|
|
|
@todo The algorithm for ensuring we only set the bits of interest in the
|
@todo The algorithm for ensuring we only set the bits of interest in the
|
register is inefficient. We should instead clear the whole area
|
register is inefficient. We should instead clear the whole area
|
before starting.
|
before starting.
|
|
|
@note The address is treated as a word address of the SPR.
|
@note The address is treated as a word address of the SPR.
|
|
|
@note The debug unit is documented as being explicitly Big Endian. However
|
@note The debug unit is documented as being explicitly Big Endian. However
|
that seems to be a poor basis for modeling, and more to do with the
|
that seems to be a poor basis for modeling, and more to do with the
|
debug unit only ever being used with big-endian architectures. We
|
debug unit only ever being used with big-endian architectures. We
|
transfer the bytes in the endianness of the OR1K.
|
transfer the bytes in the endianness of the OR1K.
|
|
|
@param[out] jreg The JTAG register buffer where data is to be stored.
|
@param[out] jreg The JTAG register buffer where data is to be stored.
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
@param[in] jreg_bytes The number of bytes expected in the JTAG register
|
(may be different to that in the prior READ/WRITE
|
(may be different to that in the prior READ/WRITE
|
if we have over- or under-run).
|
if we have over- or under-run).
|
@param[out] status_ptr Pointer to the status register. */
|
@param[out] status_ptr Pointer to the status register. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
spr_write (unsigned char *jreg,
|
spr_write (unsigned char *jreg,
|
unsigned long int jreg_bytes,
|
unsigned long int jreg_bytes,
|
enum jtag_status *status_ptr)
|
enum jtag_status *status_ptr)
|
{
|
{
|
const unsigned int BIT_OFF = 5; /* Skip initial command */
|
const unsigned int BIT_OFF = 5; /* Skip initial command */
|
|
|
/* Construct the SPR value one byte at a time. If there is overrun, ignore
|
/* Construct the SPR value one byte at a time. If there is overrun, ignore
|
the excess bytes. */
|
the excess bytes. */
|
uint32_t spr = 0;
|
uint32_t spr = 0;
|
unsigned long int i;
|
unsigned long int i;
|
|
|
for (i = 0; i < jreg_bytes; i++)
|
for (i = 0; i < jreg_bytes; i++)
|
{
|
{
|
if (i < 4)
|
if (i < 4)
|
{
|
{
|
uint8_t byte;
|
uint8_t byte;
|
|
|
byte = (jreg[i] >> BIT_OFF) | (jreg[i + 1] << (8 - BIT_OFF));
|
byte = (jreg[i] >> BIT_OFF) | (jreg[i + 1] << (8 - BIT_OFF));
|
byte = reverse_byte (byte);
|
byte = reverse_byte (byte);
|
|
|
#ifdef OR32_BIG_ENDIAN
|
#ifdef OR32_BIG_ENDIAN
|
spr |= ((uint32_t) (byte)) << (8 * i);
|
spr |= ((uint32_t) (byte)) << (8 * i);
|
#else /* !OR32_BIG_ENDIAN */
|
#else /* !OR32_BIG_ENDIAN */
|
spr |= ((uint32_t) (byte)) << (24 - (8 * i));
|
spr |= ((uint32_t) (byte)) << (24 - (8 * i));
|
#endif /* OR32_BIG_ENDIAN */
|
#endif /* OR32_BIG_ENDIAN */
|
}
|
}
|
}
|
}
|
|
|
/* Transfer the SPR */
|
/* Transfer the SPR */
|
mtspr (runtime.debug.addr, spr);
|
mtspr (runtime.debug.addr, spr);
|
|
|
/* Only advance if there we no errors (including over/under-run). */
|
/* Only advance if there we no errors (including over/under-run). */
|
if (JS_OK == *status_ptr)
|
if (JS_OK == *status_ptr)
|
{
|
{
|
runtime.debug.addr++;
|
runtime.debug.addr++;
|
}
|
}
|
} /* spr_write () */
|
} /* spr_write () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Carry out a write to WishBone or SPR
|
/*!Carry out a write to WishBone or SPR
|
|
|
Process a GO_COMMAND register for write. The format is:
|
Process a GO_COMMAND register for write. The format is:
|
|
|
+-------------+-------+------------+---------+---+
|
+-------------+-------+------------+---------+---+
|
| | | | GO | |
|
| | | | GO | |
|
TDI -> | Ignored | CRC | Data | COMMAND | 0 | -> TDO
|
TDI -> | Ignored | CRC | Data | COMMAND | 0 | -> TDO
|
| | | | (0x0) | |
|
| | | | (0x0) | |
|
+-------------+-------+------------+---------+---+
|
+-------------+-------+------------+---------+---+
|
36 32 8 * size 4
|
36 32 8 * size 4
|
bits bits bits bits
|
bits bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+-------------+
|
+-------+--------+-------------+
|
| | | |
|
| | | |
|
TDI -> | CRC | Status | 00......00 | -> TDO
|
TDI -> | CRC | Status | 00......00 | -> TDO
|
| | | |
|
| | | |
|
+-------+--------+-------------+
|
+-------+--------+-------------+
|
32 4 8 * size + 37
|
32 4 8 * size + 37
|
bits bits bits
|
bits bits bits
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 5 + 8 * size bits, the CRC out on the 4 status
|
is computed on the first 5 + 8 * size bits, the CRC out on the 4 status
|
bits.
|
bits.
|
|
|
@note The size of the data is one greater than the length specified in the
|
@note The size of the data is one greater than the length specified in the
|
original WRITE_COMMAND.
|
original WRITE_COMMAND.
|
|
|
@todo The rules say we look for errors in the WRITE_COMMAND spec
|
@todo The rules say we look for errors in the WRITE_COMMAND spec
|
here. However it would be better to do that at WRITE_COMMAND time and
|
here. However it would be better to do that at WRITE_COMMAND time and
|
save the result for here, to avoid using duff data.
|
save the result for here, to avoid using duff data.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
go_command_write (unsigned char *jreg,
|
go_command_write (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Check the length is consistent with the prior WRITE_COMMAND. If not we
|
/* Check the length is consistent with the prior WRITE_COMMAND. If not we
|
have overrun or underrun and flag accordingly. */
|
have overrun or underrun and flag accordingly. */
|
const int REG_BITS = 36 + 32 + 8 * runtime.debug.size + 4 + 1;
|
const int REG_BITS = 36 + 32 + 8 * runtime.debug.size + 4 + 1;
|
unsigned long int real_size;
|
unsigned long int real_size;
|
enum jtag_status status;
|
enum jtag_status status;
|
|
|
if (REG_BITS == num_bits)
|
if (REG_BITS == num_bits)
|
{
|
{
|
real_size = runtime.debug.size;
|
real_size = runtime.debug.size;
|
status = JS_OK;
|
status = JS_OK;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Size will round down for safety */
|
/* Size will round down for safety */
|
real_size = (runtime.debug.size * 8UL + num_bits - REG_BITS) / 8UL;
|
real_size = (runtime.debug.size * 8UL + num_bits - REG_BITS) / 8UL;
|
status = JS_OVER_UNDERRUN;
|
status = JS_OVER_UNDERRUN;
|
}
|
}
|
|
|
/* Break out the fields */
|
/* Break out the fields */
|
uint32_t crc_in =
|
uint32_t crc_in =
|
reverse_bits (((uint32_t) (jreg[real_size + 0] & 0xe0) >> 5) |
|
reverse_bits (((uint32_t) (jreg[real_size + 0] & 0xe0) >> 5) |
|
((uint32_t) jreg[real_size + 1] << 3) |
|
((uint32_t) jreg[real_size + 1] << 3) |
|
((uint32_t) jreg[real_size + 2] << 11) |
|
((uint32_t) jreg[real_size + 2] << 11) |
|
((uint32_t) jreg[real_size + 3] << 19) |
|
((uint32_t) jreg[real_size + 3] << 19) |
|
((uint32_t) (jreg[real_size + 4] & 0x1f) << 27),
|
((uint32_t) (jreg[real_size + 4] & 0x1f) << 27),
|
32);
|
32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (JCMD_GO_COMMAND, 4, crc_computed);
|
crc_computed = crc32 (JCMD_GO_COMMAND, 4, crc_computed);
|
|
|
unsigned long int i;
|
unsigned long int i;
|
|
|
for (i = 0; i < real_size; i++)
|
for (i = 0; i < real_size; i++)
|
{
|
{
|
uint8_t byte = reverse_bits (((jreg[i] & 0xe0) >> 5) |
|
uint8_t byte = reverse_bits (((jreg[i] & 0xe0) >> 5) |
|
((jreg[i + 1] & 0x1f) << 3), 8);
|
((jreg[i + 1] & 0x1f) << 3), 8);
|
crc_computed = crc32 (byte, 8, crc_computed);
|
crc_computed = crc32 (byte, 8, crc_computed);
|
}
|
}
|
|
|
/* Validate the CRC */
|
/* Validate the CRC */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
/* Write the data. Module errors will have been detected earlier, so we
|
/* Write the data. Module errors will have been detected earlier, so we
|
do nothing more here. */
|
do nothing more here. */
|
switch (runtime.debug.mod_id)
|
switch (runtime.debug.mod_id)
|
{
|
{
|
case JM_WISHBONE:
|
case JM_WISHBONE:
|
wishbone_write (jreg, real_size, &status);
|
wishbone_write (jreg, real_size, &status);
|
break;
|
break;
|
|
|
case JM_CPU0:
|
case JM_CPU0:
|
spr_write (jreg, real_size, &status);
|
spr_write (jreg, real_size, &status);
|
break;
|
break;
|
|
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Mismatch: record the error */
|
/* Mismatch: record the error */
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
/* Construct the outgoing register, skipping the data read and returning the
|
/* Construct the outgoing register, skipping the data read and returning the
|
number of JTAG cycles taken (the register length). */
|
number of JTAG cycles taken (the register length). */
|
construct_response (jreg, status, 0xffffffff, 0, 37UL + 8UL * real_size);
|
construct_response (jreg, status, 0xffffffff, 0, 37UL + 8UL * real_size);
|
|
|
} /* go_command_write () */
|
} /* go_command_write () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Invoke the action specified by a prior WRITE_COMMAND register
|
/*!Invoke the action specified by a prior WRITE_COMMAND register
|
|
|
Process a GO_COMMAND register.
|
Process a GO_COMMAND register.
|
|
|
How this is handled depends on whether a previous WRITE_COMMAND has
|
How this is handled depends on whether a previous WRITE_COMMAND has
|
selected a read access type or a write access type has been selected.
|
selected a read access type or a write access type has been selected.
|
|
|
This function breaks this out.
|
This function breaks this out.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
go_command (unsigned char *jreg,
|
go_command (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Have we even had a WRITE_COMMAND? */
|
/* Have we even had a WRITE_COMMAND? */
|
if (!runtime.debug.write_defined_p)
|
if (!runtime.debug.write_defined_p)
|
{
|
{
|
memset (jreg, 0, (num_bits + 7) / 8);
|
memset (jreg, 0, (num_bits + 7) / 8);
|
fprintf (stderr, "ERROR: JTAG GO_COMMAND with no prior WRITE_COMMAND.\n");
|
fprintf (stderr, "ERROR: JTAG GO_COMMAND with no prior WRITE_COMMAND.\n");
|
return;
|
return;
|
}
|
}
|
|
|
/* Whether to read or write depends on the access type. We don't put an
|
/* Whether to read or write depends on the access type. We don't put an
|
error message if it's invalid here - we rely on the prior WRITE_COMMAND
|
error message if it's invalid here - we rely on the prior WRITE_COMMAND
|
to do that. We just silently ignore. */
|
to do that. We just silently ignore. */
|
switch (runtime.debug.acc_type)
|
switch (runtime.debug.acc_type)
|
{
|
{
|
case JAT_WRITE8:
|
case JAT_WRITE8:
|
case JAT_WRITE16:
|
case JAT_WRITE16:
|
case JAT_WRITE32:
|
case JAT_WRITE32:
|
go_command_write (jreg, num_bits);
|
go_command_write (jreg, num_bits);
|
break;
|
break;
|
|
|
case JAT_READ8:
|
case JAT_READ8:
|
case JAT_READ16:
|
case JAT_READ16:
|
case JAT_READ32:
|
case JAT_READ32:
|
go_command_read (jreg, num_bits);
|
go_command_read (jreg, num_bits);
|
break;
|
break;
|
|
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
} /* go_command () */
|
} /* go_command () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Read a previouse WRITE_COMMAND register
|
/*!Read a previouse WRITE_COMMAND register
|
|
|
Process a READ_COMMAND register. The format is:
|
Process a READ_COMMAND register. The format is:
|
|
|
+---------+-------+---------+---+
|
+---------+-------+---------+---+
|
| | | READ | |
|
| | | READ | |
|
TDI -> | Ignored | CRC | COMMAND | 0 | -> TDO
|
TDI -> | Ignored | CRC | COMMAND | 0 | -> TDO
|
| | | (0x1) | |
|
| | | (0x1) | |
|
+---------+-------+---------+---+
|
+---------+-------+---------+---+
|
88 32 4
|
88 32 4
|
bits bits bits
|
bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+--------+---------+--------+---------+
|
+-------+--------+--------+---------+--------+---------+
|
| | | | | | |
|
| | | | | | |
|
TDI -> | CRC | Status | Length | Address | Access | 00..00 | -> TDO
|
TDI -> | CRC | Status | Length | Address | Access | 00..00 | -> TDO
|
| | | | | Type | |
|
| | | | | Type | |
|
+-------+--------+--------+---------+--------+---------+
|
+-------+--------+--------+---------+--------+---------+
|
32 4 16 32 4 37
|
32 4 16 32 4 37
|
bits bits bits bits bits bits
|
bits bits bits bits bits bits
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 5 bits, the CRC out on the 56 status, length,
|
is computed on the first 5 bits, the CRC out on the 56 status, length,
|
address and access type bits.
|
address and access type bits.
|
|
|
This is a register of a fixed size, which we verify initially.
|
This is a register of a fixed size, which we verify initially.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
read_command (unsigned char *jreg,
|
read_command (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Validate register size, which is fixed */
|
/* Validate register size, which is fixed */
|
const int REG_BITS = 88 + 32 + 4 + 1;
|
const int REG_BITS = 88 + 32 + 4 + 1;
|
|
|
if (REG_BITS != num_bits)
|
if (REG_BITS != num_bits)
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG READ_COMMAND %d bits, when %d bits expected.\n",
|
"ERROR: JTAG READ_COMMAND %d bits, when %d bits expected.\n",
|
num_bits, REG_BITS);
|
num_bits, REG_BITS);
|
return;
|
return;
|
}
|
}
|
|
|
/* Break out the fields */
|
/* Break out the fields */
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[0] & 0xe0) >> 5) |
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[0] & 0xe0) >> 5) |
|
((uint32_t) jreg[1] << 3) |
|
((uint32_t) jreg[1] << 3) |
|
((uint32_t) jreg[2] << 11) |
|
((uint32_t) jreg[2] << 11) |
|
((uint32_t) jreg[3] << 19) |
|
((uint32_t) jreg[3] << 19) |
|
((uint32_t) (jreg[4] & 0x1f) << 27), 32);
|
((uint32_t) (jreg[4] & 0x1f) << 27), 32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (JCMD_READ_COMMAND, 4, crc_computed);
|
crc_computed = crc32 (JCMD_READ_COMMAND, 4, crc_computed);
|
|
|
/* CRC to go out */
|
/* CRC to go out */
|
uint32_t crc_out = 0xffffffff;
|
uint32_t crc_out = 0xffffffff;
|
|
|
/* Status flags */
|
/* Status flags */
|
enum jtag_status status = JS_OK;
|
enum jtag_status status = JS_OK;
|
|
|
/* Only do anything with this if the CRC's match */
|
/* Only do anything with this if the CRC's match */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
/* If we haven't had a previous WRITE_COMMAND, then we return empty
|
/* If we haven't had a previous WRITE_COMMAND, then we return empty
|
data. There is no valid status flag we can use, but we print a rude
|
data. There is no valid status flag we can use, but we print a rude
|
message. */
|
message. */
|
uint8_t acc_type;
|
uint8_t acc_type;
|
uint32_t addr;
|
uint32_t addr;
|
uint16_t len;
|
uint16_t len;
|
|
|
if (runtime.debug.write_defined_p)
|
if (runtime.debug.write_defined_p)
|
{
|
{
|
acc_type = runtime.debug.acc_type;
|
acc_type = runtime.debug.acc_type;
|
addr = runtime.debug.addr;
|
addr = runtime.debug.addr;
|
len = runtime.debug.size - 1;
|
len = runtime.debug.size - 1;
|
}
|
}
|
else
|
else
|
{
|
{
|
fprintf (stderr, "ERROR: JTAG READ_COMMAND finds no data.\n");
|
fprintf (stderr, "ERROR: JTAG READ_COMMAND finds no data.\n");
|
|
|
acc_type = 0;
|
acc_type = 0;
|
addr = 0;
|
addr = 0;
|
len = 0;
|
len = 0;
|
}
|
}
|
|
|
/* Compute the CRC */
|
/* Compute the CRC */
|
crc_out = crc32 (acc_type, 4, crc_out);
|
crc_out = crc32 (acc_type, 4, crc_out);
|
crc_out = crc32 (addr, 32, crc_out);
|
crc_out = crc32 (addr, 32, crc_out);
|
crc_out = crc32 (len, 16, crc_out);
|
crc_out = crc32 (len, 16, crc_out);
|
|
|
/* Reverse the bit fields */
|
/* Reverse the bit fields */
|
acc_type = reverse_bits (acc_type, 4);
|
acc_type = reverse_bits (acc_type, 4);
|
addr = reverse_bits (addr, 32);
|
addr = reverse_bits (addr, 32);
|
len = reverse_bits (len, 16);
|
len = reverse_bits (len, 16);
|
|
|
/* Construct the outgoing register. */
|
/* Construct the outgoing register. */
|
jreg[ 4] |= (acc_type << 5) & 0xe0;
|
jreg[ 4] |= (acc_type << 5) & 0xe0;
|
jreg[ 5] |= (acc_type >> 3) & 0x01;
|
jreg[ 5] |= (acc_type >> 3) & 0x01;
|
jreg[ 5] |= (addr << 1) & 0xfe;
|
jreg[ 5] |= (addr << 1) & 0xfe;
|
jreg[ 6] |= (addr >> 7) & 0xff;
|
jreg[ 6] |= (addr >> 7) & 0xff;
|
jreg[ 7] |= (addr >> 15) & 0xff;
|
jreg[ 7] |= (addr >> 15) & 0xff;
|
jreg[ 8] |= (addr >> 23) & 0xff;
|
jreg[ 8] |= (addr >> 23) & 0xff;
|
jreg[ 9] |= (addr >> 31) & 0x01;
|
jreg[ 9] |= (addr >> 31) & 0x01;
|
jreg[ 9] |= (len << 1) & 0xfe;
|
jreg[ 9] |= (len << 1) & 0xfe;
|
jreg[10] |= (len >> 7) & 0xff;
|
jreg[10] |= (len >> 7) & 0xff;
|
jreg[11] |= (len >> 15) & 0x01;
|
jreg[11] |= (len >> 15) & 0x01;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* CRC Mismatch: record the error */
|
/* CRC Mismatch: record the error */
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
/* Construct the final response with the status, skipping the fields we've
|
/* Construct the final response with the status, skipping the fields we've
|
just written. */
|
just written. */
|
return construct_response (jreg, status, crc_out, 52, 37);
|
return construct_response (jreg, status, crc_out, 52, 37);
|
|
|
} /* read_command () */
|
} /* read_command () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Validate WRITE_COMMAND fields for WishBone
|
/*!Validate WRITE_COMMAND fields for WishBone
|
|
|
Check that a WRITE_COMMAND's fields are valid for WishBone access.
|
Check that a WRITE_COMMAND's fields are valid for WishBone access.
|
|
|
- 16 and 32-bit access must be correctly aligned.
|
- 16 and 32-bit access must be correctly aligned.
|
|
|
- size must be a multiple of 2 for 16-bit access, and a multiple of 4 for
|
- size must be a multiple of 2 for 16-bit access, and a multiple of 4 for
|
32-bit access.
|
32-bit access.
|
|
|
Error messages are printed to explain any validation problems.
|
Error messages are printed to explain any validation problems.
|
|
|
@todo Should multiple SPR accesses be allowed in a single access?
|
@todo Should multiple SPR accesses be allowed in a single access?
|
|
|
@note The size of the data is one greater than the length specified in the
|
@note The size of the data is one greater than the length specified in the
|
original WRITE_COMMAND.
|
original WRITE_COMMAND.
|
|
|
@param[in] acc_type The access type field
|
@param[in] acc_type The access type field
|
@param[in] addr The address field
|
@param[in] addr The address field
|
@param[in] size The number of bytes to transfer (field is 1 less than
|
@param[in] size The number of bytes to transfer (field is 1 less than
|
this).
|
this).
|
|
|
@return 1 (TRUE) if validation is OK, 0 (FALSE) if validation fails. */
|
@return 1 (TRUE) if validation is OK, 0 (FALSE) if validation fails. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static int
|
static int
|
validate_wb_fields (unsigned char acc_type,
|
validate_wb_fields (unsigned char acc_type,
|
unsigned long int addr,
|
unsigned long int addr,
|
unsigned long int size)
|
unsigned long int size)
|
{
|
{
|
int res_p = 1; /* Result */
|
int res_p = 1; /* Result */
|
|
|
/* Determine the size of the access */
|
/* Determine the size of the access */
|
uint32_t access_bytes = 1;
|
uint32_t access_bytes = 1;
|
|
|
switch (acc_type)
|
switch (acc_type)
|
{
|
{
|
case JAT_WRITE8:
|
case JAT_WRITE8:
|
case JAT_READ8:
|
case JAT_READ8:
|
access_bytes = 1;
|
access_bytes = 1;
|
break;
|
break;
|
|
|
case JAT_WRITE16:
|
case JAT_WRITE16:
|
case JAT_READ16:
|
case JAT_READ16:
|
access_bytes = 2;
|
access_bytes = 2;
|
break;
|
break;
|
|
|
case JAT_WRITE32:
|
case JAT_WRITE32:
|
case JAT_READ32:
|
case JAT_READ32:
|
access_bytes = 4;
|
access_bytes = 4;
|
break;
|
break;
|
|
|
default:
|
default:
|
fprintf (stderr, "ERROR: JTAG WRITE_COMMAND unknown access type %u.\n",
|
fprintf (stderr, "ERROR: JTAG WRITE_COMMAND unknown access type %u.\n",
|
acc_type);
|
acc_type);
|
res_p = 0;
|
res_p = 0;
|
break;
|
break;
|
}
|
}
|
|
|
/* Check for alignment. This works for 8-bit and undefined access type,
|
/* Check for alignment. This works for 8-bit and undefined access type,
|
although the tests will always pass. */
|
although the tests will always pass. */
|
|
|
if (0 != (addr % access_bytes))
|
if (0 != (addr % access_bytes))
|
{
|
{
|
fprintf (stderr, "ERROR: JTAG WishBone %d-bit access must be %d-byte "
|
fprintf (stderr, "ERROR: JTAG WishBone %d-bit access must be %d-byte "
|
"aligned.\n", access_bytes * 8, access_bytes);
|
"aligned.\n", access_bytes * 8, access_bytes);
|
res_p = 0;
|
res_p = 0;
|
}
|
}
|
|
|
/* Check byte length is multiple of access width */
|
/* Check byte length is multiple of access width */
|
if (0 != (size % access_bytes))
|
if (0 != (size % access_bytes))
|
{
|
{
|
fprintf (stderr, "ERROR: JTAG %d-bit WishBone access must be multiple "
|
fprintf (stderr, "ERROR: JTAG %d-bit WishBone access must be multiple "
|
"of %d bytes in length.\n", access_bytes * 8, access_bytes);
|
"of %d bytes in length.\n", access_bytes * 8, access_bytes);
|
res_p = 0;
|
res_p = 0;
|
}
|
}
|
|
|
return res_p;
|
return res_p;
|
|
|
} /* validate_wb_fields () */
|
} /* validate_wb_fields () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Validate WRITE_COMMAND fields for SPR
|
/*!Validate WRITE_COMMAND fields for SPR
|
|
|
Check that a WRITE_COMMAND's fields are valid for SPR access. Only prints
|
Check that a WRITE_COMMAND's fields are valid for SPR access. Only prints
|
messages, since the protocol does not allow for any errors.
|
messages, since the protocol does not allow for any errors.
|
|
|
- 8 and 16-bit access is not permitted.
|
- 8 and 16-bit access is not permitted.
|
|
|
- size must be 4 bytes (1 word). Any other value is an error.
|
- size must be 4 bytes (1 word). Any other value is an error.
|
|
|
- address must be less than MAX_SPRS. If a larger value is specified, it
|
- address must be less than MAX_SPRS. If a larger value is specified, it
|
will be reduced module MAX_SPRS (which is hopefully a power of 2). This
|
will be reduced module MAX_SPRS (which is hopefully a power of 2). This
|
is only a warning, not an error.
|
is only a warning, not an error.
|
|
|
Error/warning messages are printed to explain any validation problems.
|
Error/warning messages are printed to explain any validation problems.
|
|
|
@todo Should multiple SPR accesses be allowed in a single access?
|
@todo Should multiple SPR accesses be allowed in a single access?
|
|
|
@note The size of the data is one greater than the length specified in the
|
@note The size of the data is one greater than the length specified in the
|
original WRITE_COMMAND.
|
original WRITE_COMMAND.
|
|
|
@param[in] acc_type The access type field
|
@param[in] acc_type The access type field
|
@param[in] addr The address field
|
@param[in] addr The address field
|
@param[in] size The number of bytes to transfer (field is 1 less than
|
@param[in] size The number of bytes to transfer (field is 1 less than
|
this).
|
this).
|
|
|
@return 1 (TRUE) if we could validate (even if addr needs truncating),
|
@return 1 (TRUE) if we could validate (even if addr needs truncating),
|
0 (FALSE) otherwise. */
|
0 (FALSE) otherwise. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static int
|
static int
|
validate_spr_fields (unsigned char acc_type,
|
validate_spr_fields (unsigned char acc_type,
|
unsigned long int addr,
|
unsigned long int addr,
|
unsigned long int size)
|
unsigned long int size)
|
{
|
{
|
int res_p = 1; /* Result */
|
int res_p = 1; /* Result */
|
|
|
/* Determine the size and direction of the access */
|
/* Determine the size and direction of the access */
|
switch (acc_type)
|
switch (acc_type)
|
{
|
{
|
case JAT_WRITE8:
|
case JAT_WRITE8:
|
case JAT_READ8:
|
case JAT_READ8:
|
fprintf (stderr, "ERROR: JTAG 8-bit access for SPR not supported.\n");
|
fprintf (stderr, "ERROR: JTAG 8-bit access for SPR not supported.\n");
|
res_p = 0;
|
res_p = 0;
|
break;
|
break;
|
|
|
case JAT_WRITE16:
|
case JAT_WRITE16:
|
case JAT_READ16:
|
case JAT_READ16:
|
fprintf (stderr, "ERROR: JTAG 16-bit access for SPR not supported.\n");
|
fprintf (stderr, "ERROR: JTAG 16-bit access for SPR not supported.\n");
|
res_p = 0;
|
res_p = 0;
|
break;
|
break;
|
|
|
case JAT_WRITE32:
|
case JAT_WRITE32:
|
case JAT_READ32:
|
case JAT_READ32:
|
break;
|
break;
|
|
|
default:
|
default:
|
fprintf (stderr, "ERROR: unknown JTAG SPR access type %u.\n",
|
fprintf (stderr, "ERROR: unknown JTAG SPR access type %u.\n",
|
acc_type);
|
acc_type);
|
res_p = 0;
|
res_p = 0;
|
break;
|
break;
|
}
|
}
|
|
|
/* Validate access size */
|
/* Validate access size */
|
if (4 != size)
|
if (4 != size)
|
{
|
{
|
fprintf (stderr, "ERROR: JTAG SPR access 0x%lx bytes not supported.\n",
|
fprintf (stderr, "ERROR: JTAG SPR access 0x%lx bytes not supported.\n",
|
size);
|
size);
|
res_p = 0;
|
res_p = 0;
|
}
|
}
|
|
|
/* Validate address. This will be truncated if wrong, so not an error. */
|
/* Validate address. This will be truncated if wrong, so not an error. */
|
if (addr >= MAX_SPRS)
|
if (addr >= MAX_SPRS)
|
{
|
{
|
fprintf (stderr, "Warning: truncated JTAG SPR address 0x%08lx.\n",
|
fprintf (stderr, "Warning: truncated JTAG SPR address 0x%08lx.\n",
|
addr);
|
addr);
|
}
|
}
|
|
|
return res_p; /* Success */
|
return res_p; /* Success */
|
|
|
} /* validate_spr_fields () */
|
} /* validate_spr_fields () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Specify details for a subsequent GO_COMMAND
|
/*!Specify details for a subsequent GO_COMMAND
|
|
|
Process a WRITE_COMMAND register. The format is:
|
Process a WRITE_COMMAND register. The format is:
|
|
|
+---------+-------+--------+---------+--------+---------+---+
|
+---------+-------+--------+---------+--------+---------+---+
|
| | | | | | WRITE | |
|
| | | | | | WRITE | |
|
TDI -> | Ignored | CRC | Length | Address | Access | COMMAND | 0 | -> TDO
|
TDI -> | Ignored | CRC | Length | Address | Access | COMMAND | 0 | -> TDO
|
| | | | | Type | (0x2) | |
|
| | | | | Type | (0x2) | |
|
+---------+-------+--------+---------+--------+---------+---+
|
+---------+-------+--------+---------+--------+---------+---+
|
36 32 16 32 4 4
|
36 32 16 32 4 4
|
bits bits bits bits bits bits
|
bits bits bits bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+---------+
|
+-------+--------+---------+
|
| | | |
|
| | | |
|
TDI -> | CRC | Status | 00..00 | -> TDO
|
TDI -> | CRC | Status | 00..00 | -> TDO
|
| | | |
|
| | | |
|
+-------+--------+---------+
|
+-------+--------+---------+
|
32 4 89
|
32 4 89
|
bits bits bits
|
bits bits bits
|
|
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 57 bits, the CRC out on the 4 status bits.
|
is computed on the first 57 bits, the CRC out on the 4 status bits.
|
|
|
There are no bits for reporting bit specification errors other than CRC
|
There are no bits for reporting bit specification errors other than CRC
|
mismatch. The subsequent GO_COMMAND will report an error in reading from
|
mismatch. The subsequent GO_COMMAND will report an error in reading from
|
Wishbone or over/under-run. We report any inconsistencies here with warning
|
Wishbone or over/under-run. We report any inconsistencies here with warning
|
messages, correcting them if possible.
|
messages, correcting them if possible.
|
|
|
All errors invalidate any prior data. This will ensure any subsequent usage
|
All errors invalidate any prior data. This will ensure any subsequent usage
|
continues to trigger faults, rather than a failed WRITE_COMMAND being
|
continues to trigger faults, rather than a failed WRITE_COMMAND being
|
missed.
|
missed.
|
|
|
This is a register of a fixed size, which we verify initially.
|
This is a register of a fixed size, which we verify initially.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
write_command (unsigned char *jreg,
|
write_command (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Validate register size, which is fixed */
|
/* Validate register size, which is fixed */
|
const int REG_BITS = 36 + 32 +16 + 32 + 4 + 4 + 1;
|
const int REG_BITS = 36 + 32 +16 + 32 + 4 + 4 + 1;
|
|
|
if (REG_BITS != num_bits)
|
if (REG_BITS != num_bits)
|
{
|
{
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_COMMAND %d bits, when %d bits expected.\n",
|
"ERROR: JTAG WRITE_COMMAND %d bits, when %d bits expected.\n",
|
num_bits, REG_BITS);
|
num_bits, REG_BITS);
|
return;
|
return;
|
}
|
}
|
|
|
/* Break out the fields */
|
/* Break out the fields */
|
uint8_t acc_type = reverse_bits (((jreg[0] & 0xe0) >> 5) |
|
uint8_t acc_type = reverse_bits (((jreg[0] & 0xe0) >> 5) |
|
((jreg[1] & 0x01) << 3) , 4);
|
((jreg[1] & 0x01) << 3) , 4);
|
uint32_t addr = reverse_bits (((uint32_t) (jreg[ 1] & 0xfe) >> 1) |
|
uint32_t addr = reverse_bits (((uint32_t) (jreg[ 1] & 0xfe) >> 1) |
|
((uint32_t) jreg[ 2] << 7) |
|
((uint32_t) jreg[ 2] << 7) |
|
((uint32_t) jreg[ 3] << 15) |
|
((uint32_t) jreg[ 3] << 15) |
|
((uint32_t) jreg[ 4] << 23) |
|
((uint32_t) jreg[ 4] << 23) |
|
((uint32_t) (jreg[ 5] & 0x01) << 31), 32);
|
((uint32_t) (jreg[ 5] & 0x01) << 31), 32);
|
uint16_t len = reverse_bits (((uint32_t) (jreg[ 5] & 0xfe) >> 1) |
|
uint16_t len = reverse_bits (((uint32_t) (jreg[ 5] & 0xfe) >> 1) |
|
((uint32_t) jreg[ 6] << 7) |
|
((uint32_t) jreg[ 6] << 7) |
|
((uint32_t) (jreg[ 7] & 0x01) << 15), 16);
|
((uint32_t) (jreg[ 7] & 0x01) << 15), 16);
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[ 7] & 0xfe) >> 1) |
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[ 7] & 0xfe) >> 1) |
|
((uint32_t) jreg[ 8] << 7) |
|
((uint32_t) jreg[ 8] << 7) |
|
((uint32_t) jreg[ 9] << 15) |
|
((uint32_t) jreg[ 9] << 15) |
|
((uint32_t) jreg[10] << 23) |
|
((uint32_t) jreg[10] << 23) |
|
((uint32_t) (jreg[11] & 0x01) << 31), 32);
|
((uint32_t) (jreg[11] & 0x01) << 31), 32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (JCMD_WRITE_COMMAND, 4, crc_computed);
|
crc_computed = crc32 (JCMD_WRITE_COMMAND, 4, crc_computed);
|
crc_computed = crc32 (acc_type, 4, crc_computed);
|
crc_computed = crc32 (acc_type, 4, crc_computed);
|
crc_computed = crc32 (addr, 32, crc_computed);
|
crc_computed = crc32 (addr, 32, crc_computed);
|
crc_computed = crc32 (len, 16, crc_computed);
|
crc_computed = crc32 (len, 16, crc_computed);
|
|
|
/* Status flags */
|
/* Status flags */
|
enum jtag_status status = JS_OK;
|
enum jtag_status status = JS_OK;
|
|
|
/* We only do anything with this packet if the CRC's match */
|
/* We only do anything with this packet if the CRC's match */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
unsigned long int data_size = (unsigned long int) len + 1UL;
|
unsigned long int data_size = (unsigned long int) len + 1UL;
|
|
|
switch (runtime.debug.mod_id)
|
switch (runtime.debug.mod_id)
|
{
|
{
|
case JM_WISHBONE:
|
case JM_WISHBONE:
|
|
|
if (validate_wb_fields (acc_type, addr, data_size))
|
if (validate_wb_fields (acc_type, addr, data_size))
|
{
|
{
|
runtime.debug.write_defined_p = 1;
|
runtime.debug.write_defined_p = 1;
|
runtime.debug.acc_type = acc_type;
|
runtime.debug.acc_type = acc_type;
|
runtime.debug.addr = addr;
|
runtime.debug.addr = addr;
|
runtime.debug.size = data_size;
|
runtime.debug.size = data_size;
|
}
|
}
|
else
|
else
|
{
|
{
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
}
|
}
|
|
|
break;
|
break;
|
|
|
case JM_CPU0:
|
case JM_CPU0:
|
|
|
/* Oversize addresses are permitted, but cause a validation warning
|
/* Oversize addresses are permitted, but cause a validation warning
|
and are truncated here. */
|
and are truncated here. */
|
if (validate_spr_fields (acc_type, addr, data_size))
|
if (validate_spr_fields (acc_type, addr, data_size))
|
{
|
{
|
runtime.debug.write_defined_p = 1;
|
runtime.debug.write_defined_p = 1;
|
runtime.debug.acc_type = acc_type;
|
runtime.debug.acc_type = acc_type;
|
runtime.debug.addr = addr % MAX_SPRS;
|
runtime.debug.addr = addr % MAX_SPRS;
|
runtime.debug.size = data_size;
|
runtime.debug.size = data_size;
|
}
|
}
|
else
|
else
|
{
|
{
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
}
|
}
|
|
|
break;
|
break;
|
|
|
case JM_CPU1:
|
case JM_CPU1:
|
|
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_COMMAND for CPU1 not supported.\n");
|
"ERROR: JTAG WRITE_COMMAND for CPU1 not supported.\n");
|
break;
|
break;
|
|
|
case JM_UNDEFINED:
|
case JM_UNDEFINED:
|
|
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_COMMAND with no module selected.\n");
|
"ERROR: JTAG WRITE_COMMAND with no module selected.\n");
|
break;
|
break;
|
|
|
default:
|
default:
|
|
|
/* All other modules will have triggered an error on selection. */
|
/* All other modules will have triggered an error on selection. */
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* CRC Mismatch: record the error */
|
/* CRC Mismatch: record the error */
|
runtime.debug.write_defined_p = 0;
|
runtime.debug.write_defined_p = 0;
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
|
|
/* Construct the outgoing register */
|
/* Construct the outgoing register */
|
construct_response (jreg, status, 0xffffffff, 0, 89);
|
construct_response (jreg, status, 0xffffffff, 0, 89);
|
|
|
} /* write_command () */
|
} /* write_command () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Read the control bits from a CPU.
|
/*!Read the control bits from a CPU.
|
|
|
Process a READ_CONTROL register. The format is:
|
Process a READ_CONTROL register. The format is:
|
|
|
+---------+-------+---------+---+
|
+---------+-------+---------+---+
|
| | | READ | |
|
| | | READ | |
|
TDI -> | Ignored | CRC | CONTROL | 0 | -> TDO
|
TDI -> | Ignored | CRC | CONTROL | 0 | -> TDO
|
| | | (0x3) | |
|
| | | (0x3) | |
|
+---------+-------+---------+---+
|
+---------+-------+---------+---+
|
88 32 4
|
88 32 4
|
bits bits bits
|
bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+--------+---------+
|
+-------+--------+--------+---------+
|
| | | | |
|
| | | | |
|
TDI -> | CRC | Status | Data | 00..00 | -> TDO
|
TDI -> | CRC | Status | Data | 00..00 | -> TDO
|
| | | | |
|
| | | | |
|
+-------+--------+--------+---------+
|
+-------+--------+--------+---------+
|
32 4 52 37
|
32 4 52 37
|
bits bits bits bits
|
bits bits bits bits
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 57 bits, the CRC out on the 4 status bits.
|
is computed on the first 57 bits, the CRC out on the 4 status bits.
|
|
|
This is a register of a fixed size, which we verify initially.
|
This is a register of a fixed size, which we verify initially.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
read_control (unsigned char *jreg,
|
read_control (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Validate register size, which is fixed */
|
/* Validate register size, which is fixed */
|
const int REG_BITS = 88 + 32 + 4 + 1;
|
const int REG_BITS = 88 + 32 + 4 + 1;
|
|
|
if (REG_BITS != num_bits)
|
if (REG_BITS != num_bits)
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG READ_CONTROL %d bits, when %d bits expected.\n",
|
"ERROR: JTAG READ_CONTROL %d bits, when %d bits expected.\n",
|
num_bits, REG_BITS);
|
num_bits, REG_BITS);
|
return;
|
return;
|
}
|
}
|
|
|
/* Break out the fields. */
|
/* Break out the fields. */
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[0] & 0xe0) >> 5) |
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[0] & 0xe0) >> 5) |
|
((uint32_t) jreg[1] << 3) |
|
((uint32_t) jreg[1] << 3) |
|
((uint32_t) jreg[2] << 11) |
|
((uint32_t) jreg[2] << 11) |
|
((uint32_t) jreg[3] << 19) |
|
((uint32_t) jreg[3] << 19) |
|
((uint32_t) (jreg[4] & 0x1f) << 27), 32);
|
((uint32_t) (jreg[4] & 0x1f) << 27), 32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (JCMD_READ_CONTROL, 4, crc_computed);
|
crc_computed = crc32 (JCMD_READ_CONTROL, 4, crc_computed);
|
|
|
/* CRC to go out */
|
/* CRC to go out */
|
uint32_t crc_out = 0xffffffff;
|
uint32_t crc_out = 0xffffffff;
|
|
|
/* Status flags */
|
/* Status flags */
|
enum jtag_status status = JS_OK;
|
enum jtag_status status = JS_OK;
|
|
|
/* Only do anything if the CRC's match */
|
/* Only do anything if the CRC's match */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
uint64_t data = 0;
|
uint64_t data = 0;
|
|
|
switch (runtime.debug.mod_id)
|
switch (runtime.debug.mod_id)
|
{
|
{
|
case JM_CPU0:
|
case JM_CPU0:
|
|
|
/* Valid module. Only bit we can sensibly read is the stall
|
/* Valid module. Only bit we can sensibly read is the stall
|
bit. Compute the CRC, reverse the data and construct the
|
bit. Compute the CRC, reverse the data and construct the
|
outgoing register. */
|
outgoing register. */
|
data = (uint64_t) runtime.cpu.stalled << JCB_STALL;
|
data = (uint64_t) runtime.cpu.stalled << JCB_STALL;
|
break;
|
break;
|
|
|
case JM_UNDEFINED:
|
case JM_UNDEFINED:
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG READ_CONTROL with no module selected.\n");
|
"ERROR: JTAG READ_CONTROL with no module selected.\n");
|
break;
|
break;
|
|
|
case JM_WISHBONE:
|
case JM_WISHBONE:
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG READ_CONTROL of WishBone not supported.\n");
|
"ERROR: JTAG READ_CONTROL of WishBone not supported.\n");
|
break;
|
break;
|
|
|
case JM_CPU1:
|
case JM_CPU1:
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG READ_CONTROL of CPU1 not supported.\n");
|
"ERROR: JTAG READ_CONTROL of CPU1 not supported.\n");
|
break;
|
break;
|
|
|
default:
|
default:
|
/* All other modules will have triggered an error on selection. */
|
/* All other modules will have triggered an error on selection. */
|
break;
|
break;
|
}
|
}
|
|
|
/* Compute the CRC, reverse and store the data, and construct the
|
/* Compute the CRC, reverse and store the data, and construct the
|
response with the status. */
|
response with the status. */
|
crc_out = crc32 (data, 52, crc_out);
|
crc_out = crc32 (data, 52, crc_out);
|
data = reverse_bits (data, 52);
|
data = reverse_bits (data, 52);
|
|
|
jreg[ 4] |= (data << 5) & 0xf8;
|
jreg[ 4] |= (data << 5) & 0xf8;
|
jreg[ 5] |= (data >> 3) & 0x07;
|
jreg[ 5] |= (data >> 3) & 0x07;
|
jreg[ 6] |= (data >> 11) & 0xff;
|
jreg[ 6] |= (data >> 11) & 0xff;
|
jreg[ 7] |= (data >> 19) & 0xff;
|
jreg[ 7] |= (data >> 19) & 0xff;
|
jreg[ 8] |= (data >> 27) & 0xff;
|
jreg[ 8] |= (data >> 27) & 0xff;
|
jreg[ 9] |= (data >> 35) & 0xff;
|
jreg[ 9] |= (data >> 35) & 0xff;
|
jreg[10] |= (data >> 43) & 0xff;
|
jreg[10] |= (data >> 43) & 0xff;
|
jreg[11] |= (data >> 51) & 0x01;
|
jreg[11] |= (data >> 51) & 0x01;
|
}
|
}
|
else
|
else
|
{
|
{
|
/* CRC Mismatch: record the error */
|
/* CRC Mismatch: record the error */
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
|
|
/* Construct the response with the status */
|
/* Construct the response with the status */
|
return construct_response (jreg, status, crc_out, 52, 37);
|
return construct_response (jreg, status, crc_out, 52, 37);
|
|
|
} /* read_control () */
|
} /* read_control () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Write the control bits to a CPU.
|
/*!Write the control bits to a CPU.
|
|
|
Process a WRITE_CONTROL register. The format is:
|
Process a WRITE_CONTROL register. The format is:
|
|
|
+---------+-------+--------+---------+---+
|
+---------+-------+--------+---------+---+
|
| | | | WRITE | |
|
| | | | WRITE | |
|
TDI -> | Ignored | CRC | Data | CONTROL | 0 | -> TDO
|
TDI -> | Ignored | CRC | Data | CONTROL | 0 | -> TDO
|
| | | | (0x4) | |
|
| | | | (0x4) | |
|
+---------+-------+--------+---------+---+
|
+---------+-------+--------+---------+---+
|
36 32 52 4
|
36 32 52 4
|
bits bits bits bits
|
bits bits bits bits
|
|
|
The returned register has the format:
|
The returned register has the format:
|
|
|
+-------+--------+---------+
|
+-------+--------+---------+
|
| | | |
|
| | | |
|
TDI -> | CRC | Status | 00..00 | -> TDO
|
TDI -> | CRC | Status | 00..00 | -> TDO
|
| | | |
|
| | | |
|
+-------+--------+---------+
|
+-------+--------+---------+
|
32 4 89
|
32 4 89
|
bits bits bits
|
bits bits bits
|
|
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
Fields are always shifted in MS bit first, so must be reversed. The CRC in
|
is computed on the first 57 bits, the CRC out on the 4 status bits.
|
is computed on the first 57 bits, the CRC out on the 4 status bits.
|
|
|
This is a register of a fixed size, which we verify initially.
|
This is a register of a fixed size, which we verify initially.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
write_control (unsigned char *jreg,
|
write_control (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
/* Validate register size, which is fixed */
|
/* Validate register size, which is fixed */
|
const int REG_BITS = 36 + 32 + 52 + 4 + 1;
|
const int REG_BITS = 36 + 32 + 52 + 4 + 1;
|
|
|
if (REG_BITS != num_bits)
|
if (REG_BITS != num_bits)
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_CONTROL %d bits, when %d bits expected.\n",
|
"ERROR: JTAG WRITE_CONTROL %d bits, when %d bits expected.\n",
|
num_bits, REG_BITS);
|
num_bits, REG_BITS);
|
return;
|
return;
|
}
|
}
|
|
|
/* Break out the fields. */
|
/* Break out the fields. */
|
uint64_t data = reverse_bits (((uint64_t) (jreg[ 0] & 0xe0) >> 5) |
|
uint64_t data = reverse_bits (((uint64_t) (jreg[ 0] & 0xe0) >> 5) |
|
((uint64_t) jreg[ 1] << 3) |
|
((uint64_t) jreg[ 1] << 3) |
|
((uint64_t) jreg[ 2] << 11) |
|
((uint64_t) jreg[ 2] << 11) |
|
((uint64_t) jreg[ 3] << 19) |
|
((uint64_t) jreg[ 3] << 19) |
|
((uint64_t) jreg[ 4] << 27) |
|
((uint64_t) jreg[ 4] << 27) |
|
((uint64_t) jreg[ 5] << 35) |
|
((uint64_t) jreg[ 5] << 35) |
|
((uint64_t) jreg[ 6] << 43) |
|
((uint64_t) jreg[ 6] << 43) |
|
((uint64_t) (jreg[ 7] & 0x01) << 51), 52);
|
((uint64_t) (jreg[ 7] & 0x01) << 51), 52);
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[ 7] & 0xfe) >> 1) |
|
uint32_t crc_in = reverse_bits (((uint32_t) (jreg[ 7] & 0xfe) >> 1) |
|
((uint32_t) jreg[ 8] << 7) |
|
((uint32_t) jreg[ 8] << 7) |
|
((uint32_t) jreg[ 9] << 15) |
|
((uint32_t) jreg[ 9] << 15) |
|
((uint32_t) jreg[10] << 23) |
|
((uint32_t) jreg[10] << 23) |
|
((uint32_t) (jreg[11] & 0x01) << 31), 32);
|
((uint32_t) (jreg[11] & 0x01) << 31), 32);
|
|
|
/* Compute the expected CRC */
|
/* Compute the expected CRC */
|
uint32_t crc_computed;
|
uint32_t crc_computed;
|
|
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (0, 1, 0xffffffff);
|
crc_computed = crc32 (JCMD_WRITE_CONTROL, 4, crc_computed);
|
crc_computed = crc32 (JCMD_WRITE_CONTROL, 4, crc_computed);
|
crc_computed = crc32 (data, 52, crc_computed);
|
crc_computed = crc32 (data, 52, crc_computed);
|
|
|
/* Status flags */
|
/* Status flags */
|
enum jtag_status status = JS_OK;
|
enum jtag_status status = JS_OK;
|
|
|
/* Only use the data if CRC's match */
|
/* Only use the data if CRC's match */
|
if (crc_computed == crc_in)
|
if (crc_computed == crc_in)
|
{
|
{
|
int reset_bit;
|
int reset_bit;
|
int stall_bit;
|
int stall_bit;
|
|
|
switch (runtime.debug.mod_id)
|
switch (runtime.debug.mod_id)
|
{
|
{
|
case JM_CPU0:
|
case JM_CPU0:
|
|
|
/* Good data and valid module. Reset, stall or unstall the register
|
/* Good data and valid module. Reset, stall or unstall the register
|
as required. If reset is requested, there is no point considering
|
as required. If reset is requested, there is no point considering
|
stalling! */
|
stalling! */
|
reset_bit = (0x1 == ((data >> JCB_RESET) & 0x1));
|
reset_bit = (0x1 == ((data >> JCB_RESET) & 0x1));
|
stall_bit = (0x1 == ((data >> JCB_STALL) & 0x1));
|
stall_bit = (0x1 == ((data >> JCB_STALL) & 0x1));
|
|
|
if (reset_bit)
|
if (reset_bit)
|
{
|
{
|
sim_reset ();
|
sim_reset ();
|
}
|
}
|
else
|
else
|
{
|
{
|
set_stall_state (stall_bit);
|
set_stall_state (stall_bit);
|
}
|
}
|
|
|
break;
|
break;
|
|
|
case JM_UNDEFINED:
|
case JM_UNDEFINED:
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_CONTROL with no module selected.\n");
|
"ERROR: JTAG WRITE_CONTROL with no module selected.\n");
|
break;
|
break;
|
|
|
case JM_WISHBONE:
|
case JM_WISHBONE:
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_CONTROL of WishBone not supported.\n");
|
"ERROR: JTAG WRITE_CONTROL of WishBone not supported.\n");
|
break;
|
break;
|
|
|
case JM_CPU1:
|
case JM_CPU1:
|
fprintf (stderr,
|
fprintf (stderr,
|
"ERROR: JTAG WRITE_CONTROL of CPU1 not supported.\n");
|
"ERROR: JTAG WRITE_CONTROL of CPU1 not supported.\n");
|
break;
|
break;
|
|
|
default:
|
default:
|
/* All other modules will have triggered an error on selection. */
|
/* All other modules will have triggered an error on selection. */
|
break;
|
break;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* CRC Mismatch: record the error */
|
/* CRC Mismatch: record the error */
|
status |= JS_CRC_IN_ERROR;
|
status |= JS_CRC_IN_ERROR;
|
}
|
}
|
|
|
/* Construct the response with the status */
|
/* Construct the response with the status */
|
return construct_response (jreg, status, 0xffffffff, 0, 89);
|
return construct_response (jreg, status, 0xffffffff, 0, 89);
|
|
|
} /* write_control () */
|
} /* write_control () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Initialize the JTAG system
|
/*!Initialize the JTAG system
|
|
|
For now just reset the JTAG interface */
|
For now just reset the JTAG interface */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
jtag_init ()
|
jtag_init ()
|
{
|
{
|
(void) jtag_reset ();
|
(void) jtag_reset ();
|
|
|
} /* jtag_init () */
|
} /* jtag_init () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Reset the JTAG interface
|
/*!Reset the JTAG interface
|
|
|
Mark the current JTAG instruction as undefined. */
|
Mark the current JTAG instruction as undefined. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
jtag_reset ()
|
jtag_reset ()
|
{
|
{
|
runtime.debug.instr = JI_UNDEFINED;
|
runtime.debug.instr = JI_UNDEFINED;
|
|
|
} /* jtag_reset () */
|
} /* jtag_reset () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Shift a JTAG instruction register
|
/*!Shift a JTAG instruction register
|
|
|
@note Like all the JTAG interface functions, this must not be called
|
@note Like all the JTAG interface functions, this must not be called
|
re-entrantly while a call to any other function (e.g. or1kim_run ())
|
re-entrantly while a call to any other function (e.g. or1kim_run ())
|
is in progress. It is the responsibility of the caller to ensure this
|
is in progress. It is the responsibility of the caller to ensure this
|
constraint is met, for example by use of a SystemC mutex.
|
constraint is met, for example by use of a SystemC mutex.
|
|
|
The register is represented as a vector of bytes, with the byte at offset
|
The register is represented as a vector of bytes, with the byte at offset
|
zero being shifted first, and the least significant bit in each byte being
|
zero being shifted first, and the least significant bit in each byte being
|
shifted first. Where the register will not fit in an exact number of bytes,
|
shifted first. Where the register will not fit in an exact number of bytes,
|
the odd bits are in the highest numbered byte, shifted to the low end.
|
the odd bits are in the highest numbered byte, shifted to the low end.
|
|
|
The format is:
|
The format is:
|
|
|
+-------------+
|
+-------------+
|
| |
|
| |
|
TDI -> | Instruction | -> TDO
|
TDI -> | Instruction | -> TDO
|
| |
|
| |
|
+-------------+
|
+-------------+
|
4
|
4
|
bits
|
bits
|
|
|
We first verify that we have received the correct number of bits. If not we
|
We first verify that we have received the correct number of bits. If not we
|
put out a warning, and for consistency return the number of bits supplied
|
put out a warning, and for consistency return the number of bits supplied
|
as the number of cycles the shift took.
|
as the number of cycles the shift took.
|
|
|
With this debug interface, registers are shifted MS bit first, so we must
|
With this debug interface, registers are shifted MS bit first, so we must
|
reverse the bits to get the actual value.
|
reverse the bits to get the actual value.
|
|
|
We record the selected instruction. For completeness the register is parsed
|
We record the selected instruction. For completeness the register is parsed
|
and a warning given if any register other than DEBUG is shifted.
|
and a warning given if any register other than DEBUG is shifted.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
jtag_shift_ir (unsigned char *jreg,
|
jtag_shift_ir (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
if (4 != num_bits)
|
if (4 != num_bits)
|
{
|
{
|
fprintf (stderr, "ERROR: Invalid JTAG instruction length %d bits.\n",
|
fprintf (stderr, "ERROR: Invalid JTAG instruction length %d bits.\n",
|
num_bits);
|
num_bits);
|
return;
|
return;
|
}
|
}
|
|
|
runtime.debug.instr = reverse_bits (jreg[0] & 0xf, 4);
|
runtime.debug.instr = reverse_bits (jreg[0] & 0xf, 4);
|
|
|
switch (runtime.debug.instr)
|
switch (runtime.debug.instr)
|
{
|
{
|
case JI_EXTEST:
|
case JI_EXTEST:
|
fprintf (stderr, "Warning: JTAG EXTEST shifted.\n");
|
fprintf (stderr, "Warning: JTAG EXTEST shifted.\n");
|
break;
|
break;
|
|
|
case JI_SAMPLE_PRELOAD:
|
case JI_SAMPLE_PRELOAD:
|
fprintf (stderr, "Warning: JTAG SAMPLE/PRELOAD shifted.\n");
|
fprintf (stderr, "Warning: JTAG SAMPLE/PRELOAD shifted.\n");
|
break;
|
break;
|
|
|
case JI_IDCODE:
|
case JI_IDCODE:
|
fprintf (stderr, "Warning: JTAG IDCODE shifted.\n");
|
fprintf (stderr, "Warning: JTAG IDCODE shifted.\n");
|
break;
|
break;
|
|
|
case JI_DEBUG:
|
case JI_DEBUG:
|
/* Do nothing for this one */
|
/* Do nothing for this one */
|
break;
|
break;
|
|
|
case JI_MBIST:
|
case JI_MBIST:
|
fprintf (stderr, "Warning: JTAG MBIST shifted.\n");
|
fprintf (stderr, "Warning: JTAG MBIST shifted.\n");
|
break;
|
break;
|
|
|
case JI_BYPASS:
|
case JI_BYPASS:
|
fprintf (stderr, "Warning: JTAG BYPASS shifted.\n");
|
fprintf (stderr, "Warning: JTAG BYPASS shifted.\n");
|
break;
|
break;
|
|
|
default:
|
default:
|
fprintf (stderr, "ERROR: Unknown JTAG instruction 0x%1x shifted.\n",
|
fprintf (stderr, "ERROR: Unknown JTAG instruction 0x%1x shifted.\n",
|
runtime.debug.instr);
|
runtime.debug.instr);
|
break;
|
break;
|
}
|
}
|
} /* jtag_shift_ir () */
|
} /* jtag_shift_ir () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Shift a JTAG data register
|
/*!Shift a JTAG data register
|
|
|
@note Like all the JTAG interface functions, this must not be called
|
@note Like all the JTAG interface functions, this must not be called
|
re-entrantly while a call to any other function (e.g. or1kim_run ())
|
re-entrantly while a call to any other function (e.g. or1kim_run ())
|
is in progress. It is the responsibility of the caller to ensure this
|
is in progress. It is the responsibility of the caller to ensure this
|
constraint is met, for example by use of a SystemC mutex.
|
constraint is met, for example by use of a SystemC mutex.
|
|
|
The register is represented as a vector of bytes, with the byte at offset
|
The register is represented as a vector of bytes, with the byte at offset
|
zero being shifted first, and the least significant bit in each byte being
|
zero being shifted first, and the least significant bit in each byte being
|
shifted first. Where the register will not fit in an exact number of bytes,
|
shifted first. Where the register will not fit in an exact number of bytes,
|
the odd bits are in the highest numbered byte, shifted to the low end.
|
the odd bits are in the highest numbered byte, shifted to the low end.
|
|
|
This is only meaningful if the DEBUG register instruction is already
|
This is only meaningful if the DEBUG register instruction is already
|
selected. If not, the data register is rejected.
|
selected. If not, the data register is rejected.
|
|
|
The register is parsed to determine which of the six possible register
|
The register is parsed to determine which of the six possible register
|
types it could be.
|
types it could be.
|
- SELECT_MODULE
|
- SELECT_MODULE
|
- WRITE_COMMNAND
|
- WRITE_COMMNAND
|
- READ_COMMAND
|
- READ_COMMAND
|
- GO_COMMAND
|
- GO_COMMAND
|
- WRITE_CONTROL
|
- WRITE_CONTROL
|
- READ_CONTROL
|
- READ_CONTROL
|
|
|
@note In practice READ_COMMAND is not used. However the functionality is
|
@note In practice READ_COMMAND is not used. However the functionality is
|
provided for future compatibility.
|
provided for future compatibility.
|
|
|
The parsing is hierarchical. The first bit determines if we have
|
The parsing is hierarchical. The first bit determines if we have
|
SELECT_MODULE, if not, the next 4 bits determine the command.
|
SELECT_MODULE, if not, the next 4 bits determine the command.
|
|
|
@param[in,out] jreg The register to shift in, and the register shifted
|
@param[in,out] jreg The register to shift in, and the register shifted
|
back out.
|
back out.
|
@param[in] num_bits The number of bits supplied. */
|
@param[in] num_bits The number of bits supplied. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
jtag_shift_dr (unsigned char *jreg,
|
jtag_shift_dr (unsigned char *jreg,
|
int num_bits)
|
int num_bits)
|
{
|
{
|
if (JI_DEBUG != runtime.debug.instr)
|
if (JI_DEBUG != runtime.debug.instr)
|
{
|
{
|
fprintf (stderr, "ERROR: Attempt to shift JTAG data register when "
|
fprintf (stderr, "ERROR: Attempt to shift JTAG data register when "
|
"DEBUG not instruction.\n");
|
"DEBUG not instruction.\n");
|
return;
|
return;
|
}
|
}
|
|
|
int select_module_p = (1 == (jreg[0] & 0x1));
|
int select_module_p = (1 == (jreg[0] & 0x1));
|
|
|
if (select_module_p)
|
if (select_module_p)
|
{
|
{
|
select_module (jreg, num_bits);
|
select_module (jreg, num_bits);
|
}
|
}
|
else
|
else
|
{
|
{
|
switch (reverse_bits ((jreg[0] >> 1) & 0xf, 4))
|
switch (reverse_bits ((jreg[0] >> 1) & 0xf, 4))
|
{
|
{
|
case JCMD_GO_COMMAND: go_command (jreg, num_bits); break;
|
case JCMD_GO_COMMAND: go_command (jreg, num_bits); break;
|
case JCMD_READ_COMMAND: read_command (jreg, num_bits); break;
|
case JCMD_READ_COMMAND: read_command (jreg, num_bits); break;
|
case JCMD_WRITE_COMMAND: write_command (jreg, num_bits); break;
|
case JCMD_WRITE_COMMAND: write_command (jreg, num_bits); break;
|
case JCMD_READ_CONTROL: read_control (jreg, num_bits); break;
|
case JCMD_READ_CONTROL: read_control (jreg, num_bits); break;
|
case JCMD_WRITE_CONTROL: write_control (jreg, num_bits); break;
|
case JCMD_WRITE_CONTROL: write_control (jreg, num_bits); break;
|
|
|
default:
|
default:
|
/* Not a command we recognize. */
|
/* Not a command we recognize. */
|
fprintf (stderr, "ERROR: DEBUG command not recognized.\n");
|
fprintf (stderr, "ERROR: DEBUG command not recognized.\n");
|
break;
|
break;
|
}
|
}
|
}
|
}
|
} /* jtag_shift_dr () */
|
} /* jtag_shift_dr () */
|
|
|