Add Blackfin commands.

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1733 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Jie Zhang 15 years ago
parent 8abd3a255d
commit 4aa24728f9

@ -1,3 +1,40 @@
2010-01-26 Jie Zhang <jie.zhang@analog.com>
Mike Frysinger <vapier@gentoo.org>
* configure.ac (AC_CONFIG_FILES): Add src/bfin/Makefile.
* include/urjtag/Makefile.am (pkginclude_HEADERS): Add bfin.h.
* include/urjtag/bfin.h: New file.
* include/urjtag/chain.h (struct URJ_CHAIN): Add main_part.
* include/urjtag/error.h (enum URJ_ERROR): Add URJ_ERROR_BFIN.
* include/urjtag/part.h (struct URJ_PART_PARAMS): Define.
(struct URJ_PART): Add params.
(urj_part_init_func_t): Typedef.
(struct URJ_PART_INIT): Define.
(urj_part_inits): Declare.
(urj_part_init_register): Declare.
(urj_part_find_init): Declare.
* include/urjtag/types.h (urj_part_params_t): Typedef.
(urj_part_init_t): Typedef.
* src/Makefile.am (SUBDIRS): Add bfin.
(liburjtag_la_LIBADD): Add bfin/libbfin.la.
* src/bfin/Makefile.am: New file.
* src/bfin/bfin-part-bfin.c: New file.
* src/bfin/bfin-part.c: New file.
* src/bfin/bfin-part.h: New file.
* src/bfin/bfin.c: New file.
* src/bfin/insn-gen.c: New file.
* src/cmd/Makefile.am (libcmd_la_SOURCES): Add cmd_bfin.c.
* src/cmd/cmd_bfin.c: New file.
* src/cmd/cmd_list.h: Add _URJ_CMD(bfin).
* src/global/log-error.c (urj_error_string): Handle URJ_ERROR_BFIN.
* src/part/part.c (urj_part_inits): Define.
(urj_part_alloc): Initialize params.
(urj_part_free): Free params.
(urj_part_init_register): New.
(urj_part_find_init): New.
* src/tap/detect.c (urj_tap_detect_parts): Do part initialization.
Initialize main_part.
2010-01-24 Arnim Laeuger <arniml>
* src/tap/usbconn/libftdi.c, src/tap/usbconn/libftd2xx.c:

@ -76,6 +76,7 @@ AC_CONFIG_FILES(
src/global/Makefile
src/apps/jtag/Makefile
src/apps/bsdl2jtag/Makefile
src/bfin/Makefile
po/Makefile.in
)

@ -24,6 +24,7 @@
include $(top_srcdir)/Makefile.rules
pkginclude_HEADERS = \
bfin.h \
bitmask.h \
bsbit.h \
bsdl.h \

@ -0,0 +1,367 @@
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
*
* 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 Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef BFIN_H
#define BFIN_H
#include <stdint.h>
#include "types.h"
#include "tap.h"
#include "part.h"
/* High-Nibble: group code, low nibble: register code. */
#define T_REG_R 0x00
#define T_REG_P 0x10
#define T_REG_I 0x20
#define T_REG_B 0x30
#define T_REG_L 0x34
#define T_REG_M 0x24
#define T_REG_A 0x40
enum core_regnum
{
REG_R0 = T_REG_R, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
REG_P0 = T_REG_P, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
REG_I0 = T_REG_I, REG_I1, REG_I2, REG_I3,
REG_M0 = T_REG_M, REG_M1, REG_M2, REG_M3,
REG_B0 = T_REG_B, REG_B1, REG_B2, REG_B3,
REG_L0 = T_REG_L, REG_L1, REG_L2, REG_L3,
REG_A0x = T_REG_A, REG_A0w, REG_A1x, REG_A1w,
REG_ASTAT = 0x46,
REG_RETS = 0x47,
REG_LC0 = 0x60, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1,
REG_CYCLES, REG_CYCLES2,
REG_USP = 0x70, REG_SEQSTAT, REG_SYSCFG,
REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT,
};
#define CLASS_MASK 0xf0
#define GROUP(x) (((x) & CLASS_MASK) >> 4)
#define DREG_P(x) (((x) & CLASS_MASK) == T_REG_R)
#define PREG_P(x) (((x) & CLASS_MASK) == T_REG_P)
#define DTEST_COMMAND 0xffe00300
#define DTEST_DATA0 0xffe00400
#define DTEST_DATA1 0xffe00404
#define ITEST_COMMAND 0xffe01300
#define ITEST_DATA0 0xffe01400
#define ITEST_DATA1 0xffe01404
/* OAB stands for Operations and Bits. */
struct emu_oab
{
/* Operations */
void (*dbgctl_init) (urj_part_t *part, uint16_t value);
uint16_t (*dbgstat_value) (urj_part_t *part);
/* Generate TEST_COMMAND from ADDR and W(rite). */
uint32_t (*test_command) (uint32_t addr, int w);
/* For existing Blackfin processors, it's actually DTEST_COMMAND
address. */
uint32_t test_command_addr;
/* For existing Blackfin processors, they are actually DTEST_DATA
addresses. */
uint32_t test_data0_addr;
uint32_t test_data1_addr;
/* No existing Blackfin processors use this. It should be 0. */
int dbgctl_dbgstat_in_one_chain;
/* No existing Blackfin processors use this. It should be 0. */
int sticky_in_reset;
/* Bits */
uint16_t dbgctl_sram_init;
uint16_t dbgctl_wakeup;
uint16_t dbgctl_sysrst;
uint16_t dbgctl_esstep;
uint16_t dbgctl_emudatsz_32;
uint16_t dbgctl_emudatsz_40;
uint16_t dbgctl_emudatsz_48;
uint16_t dbgctl_emudatsz_mask;
uint16_t dbgctl_emuirlpsz_2;
uint16_t dbgctl_emuirsz_64;
uint16_t dbgctl_emuirsz_48;
uint16_t dbgctl_emuirsz_32;
uint16_t dbgctl_emuirsz_mask;
uint16_t dbgctl_empen;
uint16_t dbgctl_emeen;
uint16_t dbgctl_emfen;
uint16_t dbgctl_empwr;
uint16_t dbgstat_lpdec1;
uint16_t dbgstat_in_powrgate;
uint16_t dbgstat_core_fault;
uint16_t dbgstat_idle;
uint16_t dbgstat_in_reset;
uint16_t dbgstat_lpdec0;
uint16_t dbgstat_bist_done;
uint16_t dbgstat_emucause_mask;
uint16_t dbgstat_emuack;
uint16_t dbgstat_emuready;
uint16_t dbgstat_emudiovf;
uint16_t dbgstat_emudoovf;
uint16_t dbgstat_emudif;
uint16_t dbgstat_emudof;
};
struct bfin_part_data
{
int bypass;
struct emu_oab *emu_oab;
int scan;
uint16_t dbgctl;
uint16_t dbgstat;
uint64_t emuir_a;
uint64_t emuir_b;
uint64_t emudat_out;
uint64_t emudat_in;
uint32_t emupc;
uint32_t emupc_orig;
};
#define BFIN_PART_BYPASS(part) (((struct bfin_part_data *)((part)->params->data))->bypass)
#define EMU_OAB(part) (((struct bfin_part_data *)((part)->params->data))->emu_oab)
#define BFIN_PART_SCAN(part) (((struct bfin_part_data *)((part)->params->data))->scan)
#define BFIN_PART_WPSTAT(part) (((struct bfin_part_data *)((part)->params->data))->wpstat)
#define BFIN_PART_DBGCTL(part) (((struct bfin_part_data *)((part)->params->data))->dbgctl)
#define BFIN_PART_DBGSTAT(part) (((struct bfin_part_data *)((part)->params->data))->dbgstat)
#define BFIN_PART_EMUIR_A(part) (((struct bfin_part_data *)((part)->params->data))->emuir_a)
#define BFIN_PART_EMUIR_B(part) (((struct bfin_part_data *)((part)->params->data))->emuir_b)
#define BFIN_PART_EMUDAT_OUT(part) (((struct bfin_part_data *)((part)->params->data))->emudat_out)
#define BFIN_PART_EMUDAT_IN(part) (((struct bfin_part_data *)((part)->params->data))->emudat_in)
#define BFIN_PART_EMUPC(part) (((struct bfin_part_data *)((part)->params->data))->emupc)
#define BFIN_PART_EMUPC_ORIG(part) (((struct bfin_part_data *)((part)->params->data))->emupc_orig)
extern struct emu_oab bfin_emu_oab;
#define IDCODE_SCAN 0
#define DBGSTAT_SCAN 1
#define DBGCTL_SCAN 2
#define EMUIR_SCAN 3
#define EMUDAT_SCAN 4
#define EMUPC_SCAN 5
#define BYPASS 6
#define EMUIR64_SCAN 7
#define NUM_SCANS 8
extern const char *scans[];
#define INSN_NOP 0x0000
#define INSN_RTE 0x0014
#define INSN_CSYNC 0x0023
#define INSN_SSYNC 0x0024
#define INSN_ILLEGAL 0xffffffff
#define INSN_BIT_MULTI 0x08
#define INSN_IS_MULTI(insn) \
(((insn) & 0xc0) == 0xc0 && ((insn) & INSN_BIT_MULTI) \
&& ((insn) & 0xe8) != 0xe8 /* not linkage */)
enum bfin_insn_type
{
/* Instruction is a normal instruction. */
BFIN_INSN_NORMAL,
/* Instruction is a value which should be set to EMUDAT. */
BFIN_INSN_SET_EMUDAT
};
struct bfin_insn
{
/* The instruction or the value to be set to EMUDAT. */
uint64_t i;
/* The type of this instruction. */
enum bfin_insn_type type;
/* Instructions to be executed are kept on a linked list.
This is the link. */
struct bfin_insn *next;
};
enum {
LEAVE_NOP_DEFAULT,
LEAVE_NOP_YES,
LEAVE_NOP_NO
};
extern int bfin_check_emuready;
/* From src/bfin/bfin.c */
int part_is_bfin (urj_chain_t *, int);
void part_bypass (urj_chain_t *, int);
urj_tap_register_t *register_init_value (urj_tap_register_t *, uint64_t);
uint64_t register_value (urj_tap_register_t *);
int part_scan_select (urj_chain_t *, int, int);
int chain_scan_select (urj_chain_t *, int);
#define DECLARE_PART_DBGCTL_SET_BIT(name) \
void part_dbgctl_bit_set_##name (urj_chain_t *chain, int n);
#define DECLARE_PART_DBGCTL_CLEAR_BIT(name) \
void part_dbgctl_bit_clear_##name (urj_chain_t *chain, int n);
#define DECLARE_PART_DBGCTL_IS(name) \
int part_dbgctl_is_##name (urj_chain_t *chain, int n);
#define DECLARE_CHAIN_DBGCTL_SET_BIT(name) \
void chain_dbgctl_bit_set_##name (urj_chain_t *chain);
#define DECLARE_CHAIN_DBGCTL_CLEAR_BIT(name) \
void chain_dbgctl_bit_clear_##name (urj_chain_t *chain);
#define DECLARE_DBGCTL_BIT_OP(name) \
DECLARE_PART_DBGCTL_SET_BIT(name) \
DECLARE_PART_DBGCTL_CLEAR_BIT(name) \
DECLARE_PART_DBGCTL_IS(name) \
DECLARE_CHAIN_DBGCTL_SET_BIT(name) \
DECLARE_CHAIN_DBGCTL_CLEAR_BIT(name)
/* These functions check cached DBGSTAT. So before calling them,
chain_dbgstat_get or part_dbgstat_get has to be called to update cached
DBGSTAT value. */
#define DECLARE_PART_DBGSTAT_BIT_IS(name) \
int part_dbgstat_is_##name (urj_chain_t *chain, int n);
DECLARE_DBGCTL_BIT_OP (sram_init)
DECLARE_DBGCTL_BIT_OP (wakeup)
DECLARE_DBGCTL_BIT_OP (sysrst)
DECLARE_DBGCTL_BIT_OP (esstep)
DECLARE_DBGCTL_BIT_OP (emudatsz_32)
DECLARE_DBGCTL_BIT_OP (emudatsz_40)
DECLARE_DBGCTL_BIT_OP (emudatsz_48)
DECLARE_DBGCTL_BIT_OP (emuirlpsz_2)
DECLARE_DBGCTL_BIT_OP (emuirsz_64)
DECLARE_DBGCTL_BIT_OP (emuirsz_48)
DECLARE_DBGCTL_BIT_OP (emuirsz_32)
DECLARE_DBGCTL_BIT_OP (empen)
DECLARE_DBGCTL_BIT_OP (emeen)
DECLARE_DBGCTL_BIT_OP (emfen)
DECLARE_DBGCTL_BIT_OP (empwr)
DECLARE_PART_DBGSTAT_BIT_IS (lpdec1)
DECLARE_PART_DBGSTAT_BIT_IS (in_powrgate)
DECLARE_PART_DBGSTAT_BIT_IS (core_fault)
DECLARE_PART_DBGSTAT_BIT_IS (idle)
DECLARE_PART_DBGSTAT_BIT_IS (in_reset)
DECLARE_PART_DBGSTAT_BIT_IS (lpdec0)
DECLARE_PART_DBGSTAT_BIT_IS (bist_done)
DECLARE_PART_DBGSTAT_BIT_IS (emuack)
DECLARE_PART_DBGSTAT_BIT_IS (emuready)
DECLARE_PART_DBGSTAT_BIT_IS (emudiovf)
DECLARE_PART_DBGSTAT_BIT_IS (emudoovf)
DECLARE_PART_DBGSTAT_BIT_IS (emudif)
DECLARE_PART_DBGSTAT_BIT_IS (emudof)
uint16_t part_dbgstat_emucause (urj_chain_t *, int);
void chain_dbgstat_get (urj_chain_t *);
void part_dbgstat_get (urj_chain_t *, int);
void chain_emupc_get (urj_chain_t *, int);
uint32_t part_emupc_get (urj_chain_t *, int, int);
void chain_dbgstat_clear_ovfs (urj_chain_t *);
void part_dbgstat_clear_ovfs (urj_chain_t *, int);
void chain_check_emuready (urj_chain_t *);
int part_sticky_in_reset (urj_chain_t *, int);
void chain_wait_in_reset (urj_chain_t *);
void part_wait_in_reset (urj_chain_t *, int);
void chain_wait_reset (urj_chain_t *);
void part_wait_reset (urj_chain_t *, int);
void part_check_emuready (urj_chain_t *, int);
void part_emudat_set (urj_chain_t *, int, uint32_t, int);
uint32_t part_emudat_get (urj_chain_t *, int, int);
void part_emudat_defer_get (urj_chain_t *, int, int);
uint32_t part_emudat_get_done (urj_chain_t *, int, int);
uint64_t emudat_value (urj_tap_register_t *);
void emudat_init_value (urj_tap_register_t *, uint32_t);
void chain_register_get (urj_chain_t *, enum core_regnum, uint32_t *);
uint32_t part_register_get (urj_chain_t *, int, enum core_regnum);
void chain_register_set (urj_chain_t *, enum core_regnum, uint32_t *);
void chain_register_set_same (urj_chain_t *, enum core_regnum, uint32_t);
void part_register_set (urj_chain_t *, int, enum core_regnum, uint32_t);
void chain_emuir_set_same (urj_chain_t *, uint64_t, int);
void part_emuir_set (urj_chain_t *, int, uint64_t, int);
void chain_emuir_set_same_2 (urj_chain_t *, uint64_t, uint64_t, int);
void part_emuir_set_2 (urj_chain_t *, int, uint64_t, uint64_t, int);
uint32_t part_get_r0 (urj_chain_t *, int);
uint32_t part_get_p0 (urj_chain_t *, int);
void part_set_r0 (urj_chain_t *, int, uint32_t);
void part_set_p0 (urj_chain_t *, int, uint32_t);
void chain_emulation_enable (urj_chain_t *);
void part_emulation_enable (urj_chain_t *, int);
void chain_emulation_disable (urj_chain_t *);
void part_emulation_disable (urj_chain_t *, int);
void chain_emulation_trigger (urj_chain_t *);
void part_emulation_trigger (urj_chain_t *, int);
void chain_emulation_return (urj_chain_t *);
void part_emulation_return (urj_chain_t *, int);
void part_execute_instructions (urj_chain_t *, int n, struct bfin_insn *);
void chain_system_reset (urj_chain_t *);
void bfin_core_reset (urj_chain_t *);
void software_reset (urj_chain_t *);
void chain_emupc_reset (urj_chain_t *, uint32_t *);
uint32_t part_mmr_read_clobber_r0 (urj_chain_t *, int, int32_t, int);
void part_mmr_write_clobber_r0 (urj_chain_t *, int, int32_t, uint32_t, int);
uint32_t part_mmr_read (urj_chain_t *, int, uint32_t, int);
void part_mmr_write (urj_chain_t *, int, uint32_t, uint32_t, int);
/* From src/bfin/insn-gen.c */
uint32_t gen_move (enum core_regnum dest, enum core_regnum src);
uint32_t gen_load32_offset (enum core_regnum dest, enum core_regnum base, int32_t offset);
uint32_t gen_store32_offset (enum core_regnum base, int32_t offset, enum core_regnum src);
uint32_t gen_load16z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset);
uint32_t gen_store16_offset (enum core_regnum base, int32_t offset, enum core_regnum src);
uint32_t gen_load8z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset);
uint32_t gen_store8_offset (enum core_regnum base, int32_t offset, enum core_regnum src);
uint32_t gen_load32pi (enum core_regnum dest, enum core_regnum base);
uint32_t gen_store32pi (enum core_regnum base, enum core_regnum src);
uint32_t gen_load16zpi (enum core_regnum dest, enum core_regnum base);
uint32_t gen_store16pi (enum core_regnum base, enum core_regnum src);
uint32_t gen_load8zpi (enum core_regnum dest, enum core_regnum base);
uint32_t gen_store8pi (enum core_regnum base, enum core_regnum src);
uint32_t gen_load32 (enum core_regnum dest, enum core_regnum base);
uint32_t gen_store32 (enum core_regnum base, enum core_regnum src);
uint32_t gen_load16z (enum core_regnum dest, enum core_regnum base);
uint32_t gen_store16 (enum core_regnum base, enum core_regnum src);
uint32_t gen_load8z (enum core_regnum dest, enum core_regnum base);
uint32_t gen_store8 (enum core_regnum base, enum core_regnum src);
uint32_t gen_iflush (enum core_regnum addr);
uint32_t gen_iflush_pm (enum core_regnum addr);
uint32_t gen_flush (enum core_regnum addr);
uint32_t gen_flush_pm (enum core_regnum addr);
uint32_t gen_flushinv (enum core_regnum addr);
uint32_t gen_flushinv_pm (enum core_regnum addr);
uint32_t gen_prefetch (enum core_regnum addr);
uint32_t gen_prefetch_pm (enum core_regnum addr);
uint32_t gen_jump_reg (enum core_regnum addr);
#endif /* BFIN_H */

@ -44,6 +44,7 @@ struct URJ_CHAIN
int active_part;
urj_cable_t *cable;
urj_bsdl_globs_t bsdl;
int main_part;
};
urj_chain_t *urj_tap_chain_alloc (void);

@ -68,6 +68,8 @@ typedef enum URJ_ERROR
URJ_ERROR_BSDL_VHDL,
URJ_ERROR_BSDL_BSDL,
URJ_ERROR_BFIN,
URJ_ERROR_UNIMPLEMENTED,
}
urj_error_t;

@ -31,6 +31,12 @@
#define URJ_PART_PART_MAXLEN 20
#define URJ_PART_STEPPING_MAXLEN 8
struct URJ_PART_PARAMS
{
void (*free) (void *);
void *data;
};
struct URJ_PART
{
urj_tap_register_t *id;
@ -46,6 +52,7 @@ struct URJ_PART
urj_data_register_t *data_registers;
int boundary_length;
urj_bsbit_t **bsbits;
urj_part_params_t *params;
};
urj_part_t *urj_part_alloc (const urj_tap_register_t *id);
@ -86,6 +93,20 @@ urj_part_instruction_t *urj_part_instruction_define (urj_part_t *part,
const char *code,
const char *data_register);
typedef void (*urj_part_init_func_t) (urj_part_t *);
struct URJ_PART_INIT
{
char part[URJ_PART_PART_MAXLEN + 1];
urj_part_init_func_t init;
urj_part_init_t *next;
};
/* List of registered part initializers. */
extern urj_part_init_t *urj_part_inits;
void urj_part_init_register (char *part, urj_part_init_func_t init);
urj_part_init_func_t urj_part_find_init (char *part);
/**
* parts

@ -37,6 +37,8 @@ typedef struct URJ_PARTS urj_parts_t;
typedef struct URJ_PART_SIGNAL urj_part_signal_t;
typedef struct URJ_PART_SALIAS urj_part_salias_t;
typedef struct URJ_PART_INSTRUCTION urj_part_instruction_t;
typedef struct URJ_PART_PARAMS urj_part_params_t;
typedef struct URJ_PART_INIT urj_part_init_t;
typedef struct URJ_DATA_REGISTER urj_data_register_t;
typedef struct URJ_BSBIT urj_bsbit_t;
typedef struct URJ_TAP_REGISTER urj_tap_register_t;

@ -28,6 +28,7 @@ SUBDIRS = \
lib \
tap \
part \
bfin \
bus \
cmd \
global
@ -54,6 +55,7 @@ liburjtag_la_LIBADD = \
part/libpart.la \
lib/libjtaglib.la \
flash/libflash.la \
bfin/libbfin.la \
bus/libbus.la \
cmd/libcmd.la \
global/libglobal.la \

@ -0,0 +1,34 @@
#
# $Id: Makefile.am 506 2003-08-13 10:05:15Z telka $
#
# Copyright (C) 2002 ETC s.r.o.
#
# 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 Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# Written by Marcel Telka <marcel@telka.sk>, 2002.
#
include $(top_srcdir)/Makefile.rules
noinst_LTLIBRARIES = libbfin.la
libbfin_la_SOURCES = \
insn-gen.c \
bfin.c \
bfin-part.c \
bfin-part-bfin.c
AM_CFLAGS = $(WARNINGCFLAGS)

@ -0,0 +1,159 @@
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
*
* This file is subject to the terms and conditions of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later
* version. See the file COPYING for more details.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Non-GPL License is also available. Please contact
* <david.babicz@analog.com> for more information.
*
* Implementation of `Blackfin' target for the GDB proxy server.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <urjtag/part.h>
#include <urjtag/data_register.h>
#include <urjtag/part_instruction.h>
#include <urjtag/bfin.h>
/* The helper functions for Blackfin DBGCTL and DBGSTAT operations. */
static void
bfin_dbgctl_init (urj_part_t *part, uint16_t v)
{
register_init_value (part->active_instruction->data_register->in, v);
}
static uint16_t
bfin_dbgstat_value (urj_part_t *part)
{
return register_value (part->active_instruction->data_register->out);
}
static uint32_t
bfin_test_command (uint32_t addr, int w)
{
uint32_t test_command;
/* We can only access [15:0] range. */
if ((addr & 0xf0000) != 0)
return 0;
test_command =
(addr & 0x0800) << 15 /* Address bit 11 */
| (addr & 0x8000) << 8 /* Address bit 15 */
| (addr & 0x3000) << 4 /* Address bits [13:12] */
| (addr & 0x47f8) /* Address bits 14 and [10:3] */
| 0x1000000 /* Access instruction */
| 0x4; /* Access data array */
if (w)
test_command |= 0x2; /* Write */
return test_command;
}
struct emu_oab bfin_emu_oab =
{
bfin_dbgctl_init,
bfin_dbgstat_value,
bfin_test_command,
DTEST_COMMAND,
DTEST_DATA0,
DTEST_DATA1,
0, /* dbgctl_dbgstat_in_one_chain */
0, /* sticky_in_reset */
0x1000, /* DBGCTL_SRAM_INIT */
0x0800, /* DBGCTL_WAKEUP */
0x0400, /* DBGCTL_SYSRST */
0x0200, /* DBGCTL_ESSTEP */
0x0000, /* DBGCTL_EMUDATSZ_32 */
0x0080, /* DBGCTL_EMUDATSZ_40 */
0x0100, /* DBGCTL_EMUDATSZ_48 */
0x0180, /* DBGCTL_EMUDATSZ_MASK */
0x0040, /* DBGCTL_EMUIRLPSZ_2 */
0x0000, /* DBGCTL_EMUIRSZ_64 */
0x0010, /* DBGCTL_EMUIRSZ_48 */
0x0020, /* DBGCTL_EMUIRSZ_32 */
0x0030, /* DBGCTL_EMUIRSZ_MASK */
0x0008, /* DBGCTL_EMPEN */
0x0004, /* DBGCTL_EMEEN */
0x0002, /* DBGCTL_EMFEN */
0x0001, /* DBGCTL_EMPWR */
0x8000, /* DBGSTAT_LPDEC1 */
0x0000, /* No DBGSTAT_IN_POWRGATE for bfin */
0x4000, /* DBGSTAT_CORE_FAULT */
0x2000, /* DBGSTAT_IDLE */
0x1000, /* DBGSTAT_IN_RESET */
0x0800, /* DBGSTAT_LPDEC0 */
0x0400, /* DBGSTAT_BIST_DONE */
0x03c0, /* DBGSTAT_EMUCAUSE_MASK */
0x0020, /* DBGSTAT_EMUACK */
0x0010, /* DBGSTAT_EMUREADY */
0x0008, /* DBGSTAT_EMUDIOVF */
0x0004, /* DBGSTAT_EMUDOOVF */
0x0002, /* DBGSTAT_EMUDIF */
0x0001, /* DBGSTAT_EMUDOF */
};
static void
bfin_part_init (urj_part_t *part)
{
int i;
assert (part && part->params);
part->params->free = free;
part->params->data = malloc (sizeof (struct bfin_part_data));
EMU_OAB (part) = &bfin_emu_oab;
BFIN_PART_BYPASS (part) = 0;
for (i = 0; i < NUM_SCANS; i++)
if (strcmp (part->active_instruction->name, scans[i]) == 0)
break;
assert (i < NUM_SCANS);
BFIN_PART_SCAN (part) = i;
BFIN_PART_DBGCTL (part) = 0;
BFIN_PART_DBGSTAT (part) = 0;
BFIN_PART_EMUIR_A (part) = INSN_ILLEGAL;
BFIN_PART_EMUIR_B (part) = INSN_ILLEGAL;
BFIN_PART_EMUDAT_OUT (part) = 0;
BFIN_PART_EMUDAT_IN (part) = 0;
BFIN_PART_EMUPC (part) = -1;
}
extern void bfin_init (void);
void
bfin_init ()
{
urj_part_init_register ("BF506", bfin_part_init);
urj_part_init_register ("BF518", bfin_part_init);
urj_part_init_register ("BF526", bfin_part_init);
urj_part_init_register ("BF527", bfin_part_init);
urj_part_init_register ("BF533", bfin_part_init);
urj_part_init_register ("BF534", bfin_part_init);
urj_part_init_register ("BF537", bfin_part_init);
urj_part_init_register ("BF538", bfin_part_init);
urj_part_init_register ("BF548", bfin_part_init);
urj_part_init_register ("BF561", bfin_part_init);
}

@ -0,0 +1,169 @@
/*
* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
*
* 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 Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <urjtag/part.h>
#include <urjtag/bfin.h>
#include "bfin-part.h"
/* Wrappers of the helper functions. */
void
_part_dbgctl_init (urj_part_t *part, uint16_t value)
{
EMU_OAB (part)->dbgctl_init (part, value);
}
uint16_t
_part_dbgstat_value (urj_part_t *part)
{
return EMU_OAB (part)->dbgstat_value (part);
}
/* Routines to access DBGCTL and DBGSTAT bits. */
#define _PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
uint16_t \
_part_dbgctl_bit_clear_or_set_##name (urj_part_t *part, uint16_t dbgctl, int set) \
{ \
if (set) \
return dbgctl | EMU_OAB (part)->dbgctl_##name; \
else \
return dbgctl & ~EMU_OAB (part)->dbgctl_##name; \
}
#define _PART_DBGCTL_BIT_IS(name) \
int \
_part_dbgctl_is_##name (urj_part_t *part, uint16_t dbgctl) \
{ \
if (dbgctl & EMU_OAB (part)->dbgctl_##name) \
return 1; \
else \
return 0; \
}
#define _PART_DBGCTL(name) \
_PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
_PART_DBGCTL_BIT_IS(name)
#define _PART_DBGCTL_BIT_IS_MASK(base, sfx) \
int \
_part_dbgctl_is_##base##_##sfx (urj_part_t *part, uint16_t dbgctl) \
{ \
if ((dbgctl & EMU_OAB (part)->dbgctl_##base##_mask) == \
EMU_OAB (part)->dbgctl_##base##_##sfx) \
return 1; \
else \
return 0; \
}
#define _PART_DBGCTL_MASK(base, sfx) \
_PART_DBGCTL_CLEAR_OR_SET_BIT(base##_##sfx) \
_PART_DBGCTL_BIT_IS_MASK(base, sfx)
_PART_DBGCTL (sram_init)
_PART_DBGCTL (wakeup)
_PART_DBGCTL (sysrst)
_PART_DBGCTL (esstep)
_PART_DBGCTL_MASK (emudatsz, 32)
_PART_DBGCTL_MASK (emudatsz, 40)
_PART_DBGCTL_MASK (emudatsz, 48)
_PART_DBGCTL (emuirlpsz_2)
_PART_DBGCTL_MASK (emuirsz, 64)
_PART_DBGCTL_MASK (emuirsz, 48)
_PART_DBGCTL_MASK (emuirsz, 32)
_PART_DBGCTL (empen)
_PART_DBGCTL (emeen)
_PART_DBGCTL (emfen)
_PART_DBGCTL (empwr)
#define _PART_DBGSTAT_BIT_IS(name) \
int \
_part_dbgstat_is_##name (urj_part_t *part, uint16_t dbgstat) \
{ \
if (dbgstat & EMU_OAB (part)->dbgstat_##name) \
return 1; \
else \
return 0; \
}
#define _PART_DBGSTAT_CLEAR_BIT(name) \
uint16_t \
_part_dbgstat_bit_clear_##name (urj_part_t *part, uint16_t dbgstat) \
{ \
return dbgstat & ~EMU_OAB (part)->dbgstat_##name; \
}
#define _PART_DBGSTAT_SET_BIT(name) \
uint16_t \
_part_dbgstat_bit_set_##name (urj_part_t *part, uint16_t dbgstat) \
{ \
return dbgstat | EMU_OAB (part)->dbgstat_##name; \
}
_PART_DBGSTAT_BIT_IS (lpdec1)
_PART_DBGSTAT_BIT_IS (in_powrgate)
_PART_DBGSTAT_BIT_IS (core_fault)
_PART_DBGSTAT_BIT_IS (idle)
_PART_DBGSTAT_BIT_IS (in_reset)
_PART_DBGSTAT_BIT_IS (lpdec0)
_PART_DBGSTAT_BIT_IS (bist_done)
_PART_DBGSTAT_BIT_IS (emuack)
_PART_DBGSTAT_BIT_IS (emuready)
_PART_DBGSTAT_BIT_IS (emudiovf)
_PART_DBGSTAT_BIT_IS (emudoovf)
_PART_DBGSTAT_BIT_IS (emudif)
_PART_DBGSTAT_BIT_IS (emudof)
_PART_DBGSTAT_CLEAR_BIT (emudiovf)
_PART_DBGSTAT_CLEAR_BIT (emudoovf)
_PART_DBGSTAT_SET_BIT (emudiovf)
_PART_DBGSTAT_SET_BIT (emudoovf)
int
_part_dbgctl_dbgstat_in_one_chain (urj_part_t *part)
{
return EMU_OAB (part)->dbgctl_dbgstat_in_one_chain;
}
int
_part_sticky_in_reset (urj_part_t *part)
{
return EMU_OAB (part)->sticky_in_reset;
}
uint16_t
_part_dbgstat_emucause_mask (urj_part_t *part)
{
return EMU_OAB (part)->dbgstat_emucause_mask;
}
void _bfin_part_init (void) __attribute__((constructor));
extern void bfin_init (void);
void
_bfin_part_init ()
{
bfin_init ();
}

@ -0,0 +1,88 @@
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
*
* This file is subject to the terms and conditions of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later
* version. See the file COPYING for more details.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Non-GPL License is also available. Please contact
* <david.babicz@analog.com> for more information.
*
* Implementation of `Blackfin' target for the GDB proxy server.
*/
#ifndef _BLACKFIN_PART_H_
#define _BLACKFIN_PART_H_
#include <urjtag/part.h>
void _part_dbgctl_init (urj_part_t *, uint16_t);
uint16_t _part_dbgstat_value (urj_part_t *);
uint16_t _part_dbgstat_emucause_mask (urj_part_t *);
#define DECLARE__PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
uint16_t _part_dbgctl_bit_clear_or_set_##name (urj_part_t *, uint16_t, int);
#define DECLARE__PART_DBGCTL_IS(name) \
extern int _part_dbgctl_is_##name (urj_part_t *, uint16_t);
#define DECLARE__PART_DBGCTL(name) \
DECLARE__PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
DECLARE__PART_DBGCTL_IS(name)
DECLARE__PART_DBGCTL (sram_init)
DECLARE__PART_DBGCTL (wakeup)
DECLARE__PART_DBGCTL (sysrst)
DECLARE__PART_DBGCTL (esstep)
DECLARE__PART_DBGCTL (emudatsz_32)
DECLARE__PART_DBGCTL (emudatsz_40)
DECLARE__PART_DBGCTL (emudatsz_48)
DECLARE__PART_DBGCTL (emuirlpsz_2)
DECLARE__PART_DBGCTL (emuirsz_64)
DECLARE__PART_DBGCTL (emuirsz_48)
DECLARE__PART_DBGCTL (emuirsz_32)
DECLARE__PART_DBGCTL (empen)
DECLARE__PART_DBGCTL (emeen)
DECLARE__PART_DBGCTL (emfen)
DECLARE__PART_DBGCTL (empwr)
#define DECLARE__PART_DBGSTAT_BIT_IS(name) \
int _part_dbgstat_is_##name (urj_part_t *, uint16_t);
#define DECLARE__PART_DBGSTAT_CLEAR_BIT(name) \
uint16_t _part_dbgstat_bit_clear_##name (urj_part_t *, uint16_t);
#define DECLARE__PART_DBGSTAT_SET_BIT(name) \
uint16_t _part_dbgstat_bit_set_##name (urj_part_t *, uint16_t);
DECLARE__PART_DBGSTAT_BIT_IS (lpdec1)
DECLARE__PART_DBGSTAT_BIT_IS (in_powrgate)
DECLARE__PART_DBGSTAT_BIT_IS (core_fault)
DECLARE__PART_DBGSTAT_BIT_IS (idle)
DECLARE__PART_DBGSTAT_BIT_IS (in_reset)
DECLARE__PART_DBGSTAT_BIT_IS (lpdec0)
DECLARE__PART_DBGSTAT_BIT_IS (bist_done)
DECLARE__PART_DBGSTAT_BIT_IS (emuack)
DECLARE__PART_DBGSTAT_BIT_IS (emuready)
DECLARE__PART_DBGSTAT_BIT_IS (emudiovf)
DECLARE__PART_DBGSTAT_BIT_IS (emudoovf)
DECLARE__PART_DBGSTAT_BIT_IS (emudif)
DECLARE__PART_DBGSTAT_BIT_IS (emudof)
DECLARE__PART_DBGSTAT_CLEAR_BIT (emudiovf)
DECLARE__PART_DBGSTAT_CLEAR_BIT (emudoovf)
DECLARE__PART_DBGSTAT_SET_BIT (emudiovf)
DECLARE__PART_DBGSTAT_SET_BIT (emudoovf)
int _part_sticky_in_reset (urj_part_t *);
int _part_dbgctl_dbgstat_in_one_chain (urj_part_t *);
#endif /* _BLACKFIN_PART_H_ */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,270 @@
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
*
* This file is subject to the terms and conditions of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later
* version. See the file COPYING for more details.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Non-GPL License is also available. Please contact
* <david.babicz@analog.com> for more information.
*/
#include <stdint.h>
#include <stdlib.h>
#include <urjtag/bfin.h>
uint32_t
gen_move (enum core_regnum dest, enum core_regnum src)
{
uint32_t insn;
insn = 0x3000;
insn |= src & 0xf;
insn |= (dest & 0xf) << 3;
insn |= GROUP (src) << 6;
insn |= GROUP (dest) << 9;
return insn;
}
static uint32_t
gen_ldstidxi (enum core_regnum reg,
enum core_regnum ptr, int32_t offset, int w, int sz)
{
uint32_t insn;
insn = 0xe4000000;
insn |= (reg & 0xf) << 16;
insn |= (ptr & 0xf) << 19;
switch (sz)
{
case 0:
offset >>= 2;
break;
case 1:
offset >>= 1;
break;
case 2:
break;
default:
abort ();
}
if (offset > 32767 || offset < -32768)
abort ();
insn |= offset & 0xffff;
insn |= w << 25;
insn |= sz << 22;
return insn;
}
uint32_t
gen_load32_offset (enum core_regnum dest, enum core_regnum base, int32_t offset)
{
return gen_ldstidxi (dest, base, offset, 0, 0);
}
uint32_t
gen_store32_offset (enum core_regnum base, int32_t offset, enum core_regnum src)
{
return gen_ldstidxi (src, base, offset, 1, 0);
}
uint32_t
gen_load16z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset)
{
return gen_ldstidxi (dest, base, offset, 0, 1);
}
uint32_t
gen_store16_offset (enum core_regnum base, int32_t offset, enum core_regnum src)
{
return gen_ldstidxi (src, base, offset, 1, 1);
}
uint32_t
gen_load8z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset)
{
return gen_ldstidxi (dest, base, offset, 0, 2);
}
uint32_t
gen_store8_offset (enum core_regnum base, int32_t offset, enum core_regnum src)
{
return gen_ldstidxi (src, base, offset, 1, 2);
}
static uint32_t
gen_ldst (enum core_regnum reg,
enum core_regnum ptr, int post_dec, int w, int sz)
{
uint32_t insn;
insn = 0x9000;
insn |= reg & 0xf;
insn |= (ptr & 0xf) << 3;
insn |= post_dec << 7;
insn |= w << 9;
insn |= sz << 10;
return insn;
}
uint32_t
gen_load32pi (enum core_regnum dest, enum core_regnum base)
{
return gen_ldst (dest, base, 0, 0, 0);
}
uint32_t
gen_store32pi (enum core_regnum base, enum core_regnum src)
{
return gen_ldst (src, base, 0, 1, 0);
}
uint32_t
gen_load16zpi (enum core_regnum dest, enum core_regnum base)
{
return gen_ldst (dest, base, 0, 0, 1);
}
uint32_t
gen_store16pi (enum core_regnum base, enum core_regnum src)
{
return gen_ldst (src, base, 0, 1, 1);
}
uint32_t
gen_load8zpi (enum core_regnum dest, enum core_regnum base)
{
return gen_ldst (dest, base, 0, 0, 2);
}
uint32_t
gen_store8pi (enum core_regnum base, enum core_regnum src)
{
return gen_ldst (src, base, 0, 1, 2);
}
uint32_t
gen_load32 (enum core_regnum dest, enum core_regnum base)
{
return gen_ldst (dest, base, 2, 0, 0);
}
uint32_t
gen_store32 (enum core_regnum base, enum core_regnum src)
{
return gen_ldst (src, base, 2, 1, 0);
}
uint32_t
gen_load16z (enum core_regnum dest, enum core_regnum base)
{
return gen_ldst (dest, base, 2, 0, 1);
}
uint32_t
gen_store16 (enum core_regnum base, enum core_regnum src)
{
return gen_ldst (src, base, 2, 1, 1);
}
uint32_t
gen_load8z (enum core_regnum dest, enum core_regnum base)
{
return gen_ldst (dest, base, 2, 0, 2);
}
uint32_t
gen_store8 (enum core_regnum base, enum core_regnum src)
{
return gen_ldst (src, base, 2, 1, 2);
}
/* op
0 prefetch
1 flushinv
2 flush
3 iflush */
static uint32_t
gen_flush_insn (enum core_regnum addr, int op, int post_modify)
{
uint32_t insn;
insn = 0x0240;
insn |= addr & 0xf;
insn |= op << 3;
insn |= post_modify << 5;
return insn;
}
uint32_t
gen_iflush (enum core_regnum addr)
{
return gen_flush_insn (addr, 3, 0);
}
uint32_t
gen_iflush_pm (enum core_regnum addr)
{
return gen_flush_insn (addr, 3, 1);
}
uint32_t
gen_flush (enum core_regnum addr)
{
return gen_flush_insn (addr, 2, 0);
}
uint32_t
gen_flush_pm (enum core_regnum addr)
{
return gen_flush_insn (addr, 2, 1);
}
uint32_t
gen_flushinv (enum core_regnum addr)
{
return gen_flush_insn (addr, 1, 0);
}
uint32_t
gen_flushinv_pm (enum core_regnum addr)
{
return gen_flush_insn (addr, 1, 1);
}
uint32_t
gen_prefetch (enum core_regnum addr)
{
return gen_flush_insn (addr, 0, 0);
}
uint32_t
gen_prefetch_pm (enum core_regnum addr)
{
return gen_flush_insn (addr, 0, 1);
}
uint32_t
gen_jump_reg (enum core_regnum addr)
{
uint32_t insn;
insn = 0x0050;
insn |= addr & 0x7;
return insn;
}

@ -64,7 +64,8 @@ libcmd_la_SOURCES = \
cmd_include.c \
cmd_addpart.c \
cmd_cmd.c \
cmd_usleep.c
cmd_usleep.c \
cmd_bfin.c
if ENABLE_SVF
libcmd_la_SOURCES += cmd_svf.c

@ -0,0 +1,570 @@
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
*
* 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 Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "sysdep.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include <unistd.h>
#include <urjtag/part.h>
#include <urjtag/chain.h>
#include <urjtag/cmd.h>
#include <urjtag/bfin.h>
#include "cmd.h"
/* For "bfin execute", Blackfin assembler assembles instruction(s)
into a temporary object file. When this variable is non-zero, there
should be only one instruction in the object file. For example,
assembler assembles one instruction a time, which is how we do now.
Blackfin GAS rounds the section size to 4 bytes. Usually we don't
want the padding bytes to be executed as a NOP. With this variable
set, only the first instruction in the object file will be
executed. */
int bfin_one_insn_a_file = 1;
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
static int
cmd_bfin_run (urj_chain_t *chain, char *params[])
{
int num_params;
num_params = urj_cmd_params (params);
if (num_params < 2)
{
urj_error_set (URJ_ERROR_SYNTAX,
"#parameters should be >= 2, not %d",
num_params);
return URJ_STATUS_FAIL;
}
/* These commands don't need cable or parts. */
if (strcmp (params[1], "set") == 0)
{
if (num_params != 4)
{
urj_error_set (URJ_ERROR_BFIN,
"'bfin set' requires 2 parameters, not %d",
num_params - 2);
return URJ_STATUS_FAIL;
}
if (strcmp (params[2], "one-insn-a-file") == 0)
{
if (strcmp (params[3], "0") == 0)
bfin_one_insn_a_file = 0;
else if (strcmp (params[3], "1") == 0)
bfin_one_insn_a_file = 1;
else
{
urj_error_set (URJ_ERROR_BFIN,
"bad value for one-insn-a-file '%s'",
params[3]);
return URJ_STATUS_FAIL;
}
}
else
{
urj_error_set (URJ_ERROR_BFIN,
"unknown set variable '%s'",
params[2]);
return URJ_STATUS_FAIL;
}
return URJ_STATUS_OK;
}
else if (strcmp (params[1], "show") == 0)
{
int found = 0;
if (num_params > 3)
{
urj_error_set (URJ_ERROR_BFIN,
"'bfin show' requires 0 or 1 parameter, not %d",
num_params - 2);
return URJ_STATUS_FAIL;
}
if (num_params == 2 || strcmp (params[2], "one-insn-a-file") == 0)
{
found = 1;
urj_log (URJ_LOG_LEVEL_NORMAL,
"one-insn-a-file: %d\n", bfin_one_insn_a_file);
}
if (!found && num_params == 3)
{
urj_error_set (URJ_ERROR_BFIN,
"unknown set variable '%s'",
params[2]);
return URJ_STATUS_FAIL;
}
return URJ_STATUS_OK;
}
/* The remaining commands require cable or parts. */
if (urj_cmd_test_cable (chain) != URJ_STATUS_OK)
return URJ_STATUS_FAIL;
if (!chain->parts)
{
urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no parts, Run '%s' first",
"detect");
return URJ_STATUS_FAIL;
}
if (chain->active_part >= chain->parts->len)
{
urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no active part");
return URJ_STATUS_FAIL;
}
assert (chain->active_part >= 0 && chain->active_part < chain->parts->len);
if (strcmp (params[1], "emulation") == 0)
{
if (num_params != 3)
{
urj_error_set (URJ_ERROR_BFIN,
"'bfin emulation' requires 1 parameter, not %d",
num_params - 2);
return URJ_STATUS_FAIL;
}
if (strcmp (params[2], "enable") == 0)
{
part_emulation_enable (chain, chain->active_part);
}
else if (strcmp (params[2], "trigger") == 0)
{
part_emulation_trigger (chain, chain->active_part);
}
else if (strcmp (params[2], "enter") == 0)
{
part_emulation_enable (chain, chain->active_part);
part_emulation_trigger (chain, chain->active_part);
}
else if (strcmp (params[2], "return") == 0)
{
part_emulation_return (chain, chain->active_part);
}
else if (strcmp (params[2], "disable") == 0)
{
part_emulation_disable (chain, chain->active_part);
}
else if (strcmp (params[2], "exit") == 0)
{
part_emulation_return (chain, chain->active_part);
part_emulation_disable (chain, chain->active_part);
}
else if (strcmp (params[2], "status") == 0)
{
uint16_t dbgstat, excause;
const char *str_excause;
urj_part_t *part;
part_dbgstat_get (chain, chain->active_part);
part = chain->parts->parts[chain->active_part];
dbgstat = BFIN_PART_DBGSTAT (part);
excause = part_dbgstat_emucause (chain, chain->active_part);
switch (excause)
{
case 0x0: str_excause = "EMUEXCPT was executed"; break;
case 0x1: str_excause = "EMUIN pin was asserted"; break;
case 0x2: str_excause = "Watchpoint event occurred"; break;
case 0x4: str_excause = "Performance Monitor 0 overflowed"; break;
case 0x5: str_excause = "Performance Monitor 1 overflowed"; break;
case 0x8: str_excause = "Emulation single step"; break;
default: str_excause = "Reserved??"; break;
}
urj_log (URJ_LOG_LEVEL_NORMAL, "Core [%d] DBGSTAT = 0x%"PRIx16"\n",
chain->active_part, dbgstat);
urj_log (URJ_LOG_LEVEL_NORMAL,
"\tEMUDOF = %u\n"
"\tEMUDIF = %u\n"
"\tEMUDOOVF = %u\n"
"\tEMUDIOVF = %u\n"
"\tEMUREADY = %u\n"
"\tEMUACK = %u\n"
"\tEMUCAUSE = 0x%x (%s)\n"
"\tBIST_DONE = %u\n"
"\tLPDEC0 = %u\n"
"\tIN_RESET = %u\n"
"\tIDLE = %u\n"
"\tCORE_FAULT = %u\n"
"\tLPDEC1 = %u\n",
part_dbgstat_is_emudof (chain, chain->active_part),
part_dbgstat_is_emudif (chain, chain->active_part),
part_dbgstat_is_emudoovf (chain, chain->active_part),
part_dbgstat_is_emudiovf (chain, chain->active_part),
part_dbgstat_is_emuready (chain, chain->active_part),
part_dbgstat_is_emuack (chain, chain->active_part),
excause, str_excause,
part_dbgstat_is_bist_done (chain, chain->active_part),
part_dbgstat_is_lpdec0 (chain, chain->active_part),
part_dbgstat_is_in_reset (chain, chain->active_part),
part_dbgstat_is_idle (chain, chain->active_part),
part_dbgstat_is_core_fault (chain, chain->active_part),
part_dbgstat_is_lpdec1 (chain, chain->active_part));
}
else if (strcmp (params[2], "singlestep") == 0)
{
part_dbgstat_get (chain, chain->active_part);
if (!part_dbgstat_is_emuready (chain, chain->active_part))
{
urj_error_set (URJ_ERROR_BFIN, "Run '%s' first",
"bfin emulation enter");
return URJ_STATUS_FAIL;
}
/* TODO Allow an argument to specify how many single steps. */
part_scan_select (chain, chain->active_part, DBGCTL_SCAN);
part_dbgctl_bit_set_esstep (chain, chain->active_part);
urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);
part_emuir_set (chain, chain->active_part, INSN_RTE, URJ_CHAIN_EXITMODE_IDLE);
part_scan_select (chain, chain->active_part, DBGCTL_SCAN);
part_dbgctl_bit_clear_esstep (chain, chain->active_part);
urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);
}
else
{
urj_error_set (URJ_ERROR_BFIN,
"unknown emulation subcommand '%s'", params[2]);
return URJ_STATUS_FAIL;
}
return URJ_STATUS_OK;
}
else if (strcmp (params[1], "execute") == 0)
{
int execute_ret = URJ_STATUS_FAIL;
part_dbgstat_get (chain, chain->active_part);
if (!part_dbgstat_is_emuready (chain, chain->active_part))
{
urj_error_set (URJ_ERROR_BFIN, "Run '%s' first",
"bfin emulation enter");
return URJ_STATUS_FAIL;
}
if (num_params > 2)
{
int i;
struct bfin_insn *insns = NULL;
struct bfin_insn **last = &insns;
char tmp[8];
char *tmpfile = NULL;
for (i = 2; i < num_params; i++)
{
if (params[i][0] == '[' && params[i][1] == '0')
{
uint64_t n;
if (sscanf (params[i], "[0%[xX]%"PRIx64"]", tmp, &n) != 2)
goto execute_cleanup;
*last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn));
if (*last == NULL)
goto execute_cleanup;
(*last)->i = n;
(*last)->type = BFIN_INSN_SET_EMUDAT;
(*last)->next = NULL;
last = &((*last)->next);
}
else if (params[i][0] == '0')
{
uint64_t n;
if (sscanf (params[i], "0%[xX]%"PRIx64, tmp, &n) != 2)
goto execute_cleanup;
*last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn));
if (*last == NULL)
goto execute_cleanup;
(*last)->i = n;
(*last)->type = BFIN_INSN_NORMAL;
(*last)->next = NULL;
last = &((*last)->next);
}
else
{
#ifdef __MINGW32__
urj_error_set (URJ_ERROR_BFIN,
"Sorry, dynamic code not available in windows");
goto execute_cleanup;
#else
unsigned char raw_insn[4];
char *tmp_buf;
char *tuples[] = {"uclinux", "linux-uclibc", "elf"};
size_t t;
FILE *fp;
/* 1024 should be plenty; MAXINPUTLINE is 100 in parse.c */
char insns_string[1024];
char *p = insns_string;
for (; i < num_params; i++)
{
p += snprintf (p, sizeof (insns_string) - (p - insns_string),
"%s ", params[i]);
if (params[i][strlen (params[i]) - 1] == '"')
break;
if (params[i][strlen (params[i]) - 1] == ';')
break;
}
if (i == num_params)
{
urj_error_set (URJ_ERROR_BFIN,
"unbalanced double quotes");
goto execute_cleanup;
}
/* p points past the '\0'. p - 1 points to the ending '\0'.
p - 2 points to the last double quote. */
*(p - 2) = ';';
if (insns_string[0] == '"')
insns_string[0] = ' ';
/* HRM states that branches and hardware loop setup results
in undefined behavior. Should check opcode instead? */
if (strcasestr(insns_string, "jump") ||
strcasestr(insns_string, "call") ||
strcasestr(insns_string, "lsetup"))
urj_warning (_("jump/call/lsetup insns may not work in emulation\n"));
/* get a temporary file to work with -- a little racy */
if (!tmpfile)
{
tmpfile = tmpnam (NULL);
if (!tmpfile)
goto execute_cleanup;
tmpfile = strdup (tmpfile);
if (!tmpfile)
goto execute_cleanup;
}
/* try to find a toolchain in $PATH */
for (t = 0; t < ARRAY_SIZE(tuples); ++t)
{
int ret;
/* TODO Pass -mcpu= to gas. */
asprintf (&tmp_buf,
"bfin-%3$s-as --version >/dev/null 2>&1 || exit $?;"
"echo '%1$s' | bfin-%3$s-as - -o \"%2$s\""
" && bfin-%3$s-objcopy -O binary \"%2$s\"",
insns_string, tmpfile, tuples[t]);
ret = system (tmp_buf);
free (tmp_buf);
if (WIFEXITED(ret))
{
if (WEXITSTATUS(ret) == 0)
break;
/* 127 -> not found in $PATH */
else if (WEXITSTATUS(ret) == 127)
continue;
else
{
urj_error_set (URJ_ERROR_BFIN, "GAS failed parsing: %s",
insns_string);
goto execute_cleanup;
}
}
}
if (t == ARRAY_SIZE(tuples))
{
urj_error_set (URJ_ERROR_BFIN,
"unable to find Blackfin toolchain in $PATH\n");
goto execute_cleanup;
}
/* Read the binary blob from the toolchain */
fp = fopen (tmpfile, "rb");
if (fp == NULL)
goto execute_cleanup;
while (fread (raw_insn, 1, 2, fp) == 2)
{
uint16_t iw = raw_insn[0] | (raw_insn[1] << 8);
uint64_t n = iw;
int is_multiinsn = INSN_IS_MULTI (raw_insn[1]);
if ((iw & 0xf000) >= 0xc000)
{
if (fread (raw_insn, 1, 2, fp) != 2)
goto execute_cleanup;
iw = raw_insn[0] | (raw_insn[1] << 8);
n = (n << 16) | iw;
}
if (is_multiinsn)
{
if (fread (raw_insn, 1, 4, fp) != 4)
goto execute_cleanup;
n = (n << 32)
| ((uint64_t)raw_insn[0] << 16)
| ((uint64_t)raw_insn[1] << 24)
| raw_insn[2] | (raw_insn[3] << 8);
}
*last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn));
if (*last == NULL)
goto execute_cleanup;
(*last)->i = n;
(*last)->type = BFIN_INSN_NORMAL;
(*last)->next = NULL;
last = &((*last)->next);
if (bfin_one_insn_a_file)
break;
}
fclose (fp);
#endif
}
}
part_execute_instructions (chain, chain->active_part, insns);
execute_ret = URJ_STATUS_OK;
execute_cleanup:
if (tmpfile)
{
unlink (tmpfile);
free (tmpfile);
}
while (insns)
{
struct bfin_insn *tmp = insns->next;
free (insns);
insns = tmp;
}
}
if (execute_ret == URJ_STATUS_OK)
{
uint64_t emudat;
emudat = part_emudat_get (chain, chain->active_part, URJ_CHAIN_EXITMODE_UPDATE);
urj_log (URJ_LOG_LEVEL_NORMAL, "EMUDAT = 0x%"PRIx64"\n", emudat);
part_dbgstat_get (chain, chain->active_part);
if (part_dbgstat_is_core_fault (chain, chain->active_part))
urj_warning (_("core fault detected\n"));
}
return execute_ret;
}
else if (strcmp (params[1], "reset") == 0)
{
int reset_what = 0;
if (num_params == 3)
{
if (!strcmp (params[2], "core"))
reset_what |= 0x1;
else if (!strcmp (params[2], "system"))
reset_what |= 0x2;
else
{
urj_error_set (URJ_ERROR_BFIN, "bad parameter '%s'", params[2]);
return URJ_STATUS_FAIL;
}
}
else if (num_params == 2)
reset_what = 0x1 | 0x2;
else
{
urj_error_set (URJ_ERROR_BFIN,
"'bfin emulation' requires 0 or 1 parameter, not %d",
num_params - 2);
return URJ_STATUS_FAIL;
}
urj_log (URJ_LOG_LEVEL_NORMAL,
_("%s: reseting processor ... "), "bfin");
fflush (stdout);
if (reset_what == 0x3)
software_reset (chain);
else if (reset_what & 0x1)
bfin_core_reset (chain);
else if (reset_what & 0x2)
chain_system_reset (chain);
urj_log (URJ_LOG_LEVEL_NORMAL, _("OK\n"));
return URJ_STATUS_OK;
}
else
{
urj_error_set (URJ_ERROR_BFIN,
"unknown command '%s'", params[1]);
return URJ_STATUS_FAIL;
}
return URJ_STATUS_OK;
}
static void
cmd_bfin_help (void)
{
urj_log (URJ_LOG_LEVEL_NORMAL,
_("Usage: %s execute INSTRUCTIONs\n"
"Usage: %s emulation enter|exit|singlestep|status\n"
"Usage: %s reset [core|system]\n"
"Usage: %s set one-insn-a-file VALUE\n"
"Usage: %s show [one-insn-a-file]\n"
"Blackfin specific commands\n"
"\n"
"INSTRUCTIONs are a sequence of Blackfin encoded instructions,\n"
"double quoted assembly statements and [EMUDAT_IN]s\n"),
"bfin", "bfin", "bfin", "bfin", "bfin" );
}
const urj_cmd_t urj_cmd_bfin = {
"bfin",
N_("Blackfin specific commands"),
cmd_bfin_help,
cmd_bfin_run
};

@ -75,5 +75,6 @@ _URJ_CMD(svf)
_URJ_CMD(bsdl)
#endif
_URJ_CMD(debug)
_URJ_CMD(bfin)
#undef _URJ_CMD

@ -131,6 +131,8 @@ urj_error_string (urj_error_t err)
case URJ_ERROR_BSDL_VHDL: return "vhdl subsystem";
case URJ_ERROR_BSDL_BSDL: return "bsdl subsystem";
case URJ_ERROR_BFIN: return "blackfin";
case URJ_ERROR_UNIMPLEMENTED: return "unimplemented";
}

@ -35,6 +35,8 @@
#include <urjtag/data_register.h>
#include <urjtag/bsbit.h>
urj_part_init_t *urj_part_inits = NULL;
/* part */
urj_part_t *
@ -61,6 +63,7 @@ urj_part_alloc (const urj_tap_register_t *id)
p->data_registers = NULL;
p->boundary_length = 0;
p->bsbits = NULL;
p->params = NULL;
return p;
}
@ -116,6 +119,10 @@ urj_part_free (urj_part_t *p)
urj_part_bsbit_free (p->bsbits[i]);
free (p->bsbits);
if (p->params && p->params->free)
p->params->free (p->params->data);
free (p->params);
free (p);
}
@ -475,3 +482,27 @@ urj_part_parts_print (urj_log_level_t ll, urj_parts_t *ps)
return URJ_STATUS_OK;
}
void
urj_part_init_register (char *part, urj_part_init_func_t init)
{
urj_part_init_t *pi;
pi = (urj_part_init_t *) malloc (sizeof (urj_part_init_t));
strncpy (pi->part, part, URJ_PART_PART_MAXLEN);
pi->init = init;
pi->next = urj_part_inits;
urj_part_inits = pi;
}
urj_part_init_func_t
urj_part_find_init (char *part)
{
urj_part_init_t *pi;
for (pi = urj_part_inits; pi; pi = pi->next)
if (strcmp (pi->part, part) == 0)
return pi->init;
return NULL;
}

@ -253,6 +253,7 @@ urj_tap_detect_parts (urj_chain_t *chain, const char *db_path)
urj_tap_register_t *key;
struct id_record idr;
char *p;
urj_part_init_func_t part_init_func;
urj_tap_shift_register (chain, one, br, URJ_CHAIN_EXITMODE_SHIFT);
if (urj_tap_register_compare (one, br) == 0)
@ -392,8 +393,20 @@ urj_tap_detect_parts (urj_chain_t *chain, const char *db_path)
if (part->active_instruction == NULL)
part->active_instruction = urj_part_find_instruction (part,
"IDCODE");
/* Do part specific initialization. */
part_init_func = urj_part_find_init (part->part);
if (part_init_func)
{
part->params = (urj_part_params_t *) malloc (sizeof (urj_part_params_t));
(*part_init_func) (part);
}
else
part->params = NULL;
}
chain->main_part = ps->len - 1;
for (i = 0; i < 32; i++)
{
urj_tap_shift_register (chain, one, br, URJ_CHAIN_EXITMODE_SHIFT);

Loading…
Cancel
Save