mips: m4k alternate pracc code. Patch 1

This patch and the following patches define another way of doing processor access without the need to read back
the pracc address as needed in current pracc code.
Current pracc code is executed linearly and unconditionally. The processor starts execution at 0xff200200
and the fetch address is ever incremented by 4, including the last instruction in the delay slot of the branch to start.
Most of the processor accesses are fetch and some are store accesses.
After a previous patch regarding the way of restoring registers (reg8 and reg9), there are no load processor accesses.
The pracc address for a store depends only on the store instruction given before.
m4k core has a 5 stage pipeline and the memory access is done in the 3rth stage. This means that the store access
will not arrive immediately after a store instruction, it appears after another instruction enters the pipeline.
For reference: MD00249 mips32 m4k manual.
A new struct pracc_queue_info is defined to help each function in generating the code. The field pracc_list holds in the
lower half the list of instructions and in the upper half the store addressess, if any. In this way the list can be used by
current code or by the new one to generate the sequence of pracc accesses.
For every pracc access only one scan to register "all" is used by calling the new function mips_ejtag_add_scan_96().
This function does not call jtag_execute_queue(), all the scans needed can be queued before calling for execution.
The pracc bit is not checked before execution, is checked after the queue has been executed.
Without calling the wait function the code works much faster, but the scan frequency must be limited. For pic32mx
with core clock at 4Mhz works  up to 600Khz and with 8Mhz up to 1200. To increase the scan frequency a delay
between scans is added by calling jtag_add_cloks().
A time delay in nano seconds is stored in scan_delay, a new field in ejtag_info, and a handler is provided for it.
A mode field is added to ejtag_info to hold the working mode. If a time delay of 2ms (2000000 ns) or higher is set,
current code is executed, if lower, new code is executed.
Initial default values are set in function mips32_init_arch_info. A reset does not change this settings.

Change-Id: I266bdb386b24744435b6e29d8489a68c0c15ff65
Signed-off-by: Salvador Arroyo <sarroyofdez@yahoo.es>
Reviewed-on: http://openocd.zylin.com/1193
Tested-by: jenkins
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
__archive__
Salvador Arroyo 2013-03-03 10:50:42 +01:00 committed by Freddie Chopin
parent 1936646fc2
commit 109f37c161
5 changed files with 98 additions and 1 deletions

View File

@ -300,6 +300,9 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s
mips32->read_core_reg = mips32_read_core_reg; mips32->read_core_reg = mips32_read_core_reg;
mips32->write_core_reg = mips32_write_core_reg; mips32->write_core_reg = mips32_write_core_reg;
mips32->ejtag_info.scan_delay = 2000000; /* Initial default value */
mips32->ejtag_info.mode = 0; /* Initial default value */
return ERROR_OK; return ERROR_OK;
} }
@ -779,6 +782,29 @@ COMMAND_HANDLER(mips32_handle_cp0_command)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(mips32_handle_scan_delay_command)
{
struct target *target = get_current_target(CMD_CTX);
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ejtag_info->scan_delay);
else if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
if (ejtag_info->scan_delay >= 2000000) {
ejtag_info->mode = 0;
command_print(CMD_CTX, "running in legacy mode");
} else {
ejtag_info->mode = 1;
command_print(CMD_CTX, "running in fast queued mode");
}
return ERROR_OK;
}
static const struct command_registration mips32_exec_command_handlers[] = { static const struct command_registration mips32_exec_command_handlers[] = {
{ {
.name = "cp0", .name = "cp0",
@ -786,6 +812,13 @@ static const struct command_registration mips32_exec_command_handlers[] = {
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "regnum select [value]", .usage = "regnum select [value]",
.help = "display/modify cp0 register", .help = "display/modify cp0 register",
},
{
.name = "scan_delay",
.handler = mips32_handle_scan_delay_command,
.mode = COMMAND_ANY,
.help = "display/set scan delay in nano seconds",
.usage = "[value]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -51,6 +51,14 @@
#define NEG16(v) (((~(v)) + 1) & 0xFFFF) #define NEG16(v) (((~(v)) + 1) & 0xFFFF)
/*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/
struct pracc_queue_info {
int retval;
const int max_code;
int code_count;
int store_count;
uint32_t *pracc_list; /* Code and store addresses */
};
int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info,
uint32_t addr, int size, int count, void *buf); uint32_t addr, int size, int count, void *buf);
int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info,

View File

@ -99,6 +99,29 @@ static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impco
return ERROR_OK; return ERROR_OK;
} }
void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf)
{
assert(ejtag_info->tap != NULL);
struct jtag_tap *tap = ejtag_info->tap;
struct scan_field field;
uint8_t out_scan[12];
/* processor access "all" register 96 bit */
field.num_bits = 96;
field.out_value = out_scan;
buf_set_u32(out_scan, 0, 32, ctrl);
buf_set_u32(out_scan + 4, 0, 32, data);
buf_set_u32(out_scan + 8, 0, 32, 0);
field.in_value = in_scan_buf;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
keep_alive();
}
int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data) int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data)
{ {
struct jtag_tap *tap; struct jtag_tap *tap;

View File

@ -130,6 +130,8 @@ struct mips_ejtag {
int fast_access_save; int fast_access_save;
uint32_t reg8; uint32_t reg8;
uint32_t reg9; uint32_t reg9;
unsigned scan_delay;
int mode;
}; };
void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info,
@ -137,6 +139,8 @@ void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info,
int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info);
int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info);
int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode); int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode);
void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info,
uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf);
void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data); void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data);
int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data); int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data);
void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data); void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data);

View File

@ -1186,7 +1186,6 @@ COMMAND_HANDLER(mips_m4k_handle_cp0_command)
if (CMD_ARGC == 2) { if (CMD_ARGC == 2) {
uint32_t value; uint32_t value;
retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel); retval = mips32_cp0_read(ejtag_info, &value, cp0_reg, cp0_sel);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
command_print(CMD_CTX, command_print(CMD_CTX,
@ -1273,6 +1272,29 @@ COMMAND_HANDLER(mips_m4k_handle_smp_gdb_command)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(mips_m4k_handle_scan_delay_command)
{
struct target *target = get_current_target(CMD_CTX);
struct mips_m4k_common *mips_m4k = target_to_m4k(target);
struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ejtag_info->scan_delay);
else if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay);
if (ejtag_info->scan_delay >= 20000000) {
ejtag_info->mode = 0;
command_print(CMD_CTX, "running in legacy mode");
} else {
ejtag_info->mode = 1;
command_print(CMD_CTX, "running in fast queued mode");
}
return ERROR_OK;
}
static const struct command_registration mips_m4k_exec_command_handlers[] = { static const struct command_registration mips_m4k_exec_command_handlers[] = {
{ {
.name = "cp0", .name = "cp0",
@ -1302,6 +1324,13 @@ static const struct command_registration mips_m4k_exec_command_handlers[] = {
.help = "display/fix current core played to gdb", .help = "display/fix current core played to gdb",
.usage = "", .usage = "",
}, },
{
.name = "scan_delay",
.handler = mips_m4k_handle_scan_delay_command,
.mode = COMMAND_ANY,
.help = "display/set scan delay in nano seconds",
.usage = "[value]",
},
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };