URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/tn_m001/or1ksim/debug
- from Rev 861 to Rev 1765
- ↔ Reverse comparison
Rev 861 → Rev 1765
/debug_unit.c
0,0 → 1,468
/* debug_unit.c -- Simulation of Or1k debug unit |
Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
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., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* |
This is an architectural level simulation of the Or1k debug |
unit as described in OpenRISC 1000 System Architecture Manual, |
v. 0.1 on 22 April, 2001. This unit is described in Section 13. |
|
Every attempt has been made to be as accurate as possible with |
respect to the registers and the behavior. There are no known |
limitations at this time. |
*/ |
|
//#define DEBUG_JTAG 0 |
|
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <inttypes.h> |
|
#include "debug_unit.h" |
#include "sim-config.h" |
#include "except.h" |
#include "arch.h" |
#include "abstract.h" |
#include "parse.h" |
#include "sprs.h" |
#include "gdb.h" |
#include "../cpu/or1k/except.h" |
#include "opcode/or32.h" |
|
DevelopmentInterface development; |
|
/* External STALL signal to debug interface */ |
int in_reset = 0; |
|
/* Risc stall state */ |
int cpu_stalled = 0; |
|
/* Current watchpoint state */ |
unsigned long watchpoints = 0; |
|
static int calculate_watchpoints (); |
|
static int watchpoint[10]; |
|
void set_stall_state(int state) |
{ |
development.riscop &= ~RISCOP_STALL; |
development.riscop |= state ? RISCOP_STALL : 0; |
if(testsprbits(SPR_DMR1, SPR_DMR1_DXFW)) /* If debugger disabled */ |
state = 0; |
cpu_stalled = state; |
} |
|
void du_reset() |
{ |
development.riscop = 0; |
set_stall_state (0); |
} |
|
inline int CheckDebugUnit(DebugUnitAction action, unsigned long udata) |
{ |
/* Do not stop, if we have debug module disabled or during reset */ |
if(!config.debug.enabled || in_reset) |
return 0; |
|
/* If we're single stepping, always stop */ |
if(action == DebugInstructionFetch && testsprbits (SPR_DMR1, SPR_DMR1_ST)) |
return 1; |
|
return 0; |
/* TODO: Enable matchpoints |
switch(action) |
{ |
case DebugInstructionFetch: condition = DCR_CT_InsnAddress; break; |
case DebugLoadAddress: condition = DCR_CT_LoadAddress; break; |
case DebugStoreAddress: condition = DCR_CT_StoreAddress; break; |
case DebugLoadData: condition = DCR_CT_LoadData; break; |
case DebugStoreData: condition = DCR_CT_StoreData; break; |
} |
|
return calculate_watchpoints(); */ |
} |
|
/* Checks whether we should stall the RISC or cause an exception */ |
static int calculate_watchpoints() |
{ |
int breakpoint = 0; |
int i, bit; |
|
/* Hopefully this loop would be unrolled run at max. speed */ |
for(i = 0, bit = 1; i < 11; i++, bit <<= 1) { |
int chain1, chain2; |
int match = 0; |
int DCR_hit = 0; |
|
/* Calculate first 8 matchpoints, result is put into DCR_hit */ |
if (i < 8) { |
unsigned long dcr = mfspr (SPR_DCR(i)); |
/* Whether this matchpoint is enabled, calculate conditions */ |
if ((dcr & SPR_DCR_DP) && (dcr & SPR_DCR_CT != SPR_DCR_CT_DISABLED)) { |
/* Get one operand */ |
unsigned long op1; |
unsigned long op2 = mfspr (SPR_DVR(i)); |
switch (dcr & SPR_DCR_CT) { |
case SPR_DCR_CT_IFEA: op1 = runtime.cpu.ifea; break; |
case SPR_DCR_CT_LEA: op1 = runtime.cpu.lea; break; |
case SPR_DCR_CT_SEA: op1 = runtime.cpu.sea; break; |
case SPR_DCR_CT_LD: op1 = runtime.cpu.ld; break; |
case SPR_DCR_CT_SD: op1 = runtime.cpu.sd; break; |
case SPR_DCR_CT_LSEA: op1 = runtime.cpu.lsea; break; |
} |
/* Perform signed comparison? */ |
if (dcr & SPR_DCR_SC) { |
long sop1 = op1, sop2 = op2; /* Convert to signed */ |
switch(dcr & SPR_DCR_CC) { |
case SPR_DCR_CC_MASKED: DCR_hit = sop1 & sop2; break; |
case SPR_DCR_CC_EQUAL: DCR_hit = sop1 == sop2; break; |
case SPR_DCR_CC_NEQUAL: DCR_hit = sop1 != sop2; break; |
case SPR_DCR_CC_LESS: DCR_hit = sop1 < sop2; break; |
case SPR_DCR_CC_LESSE: DCR_hit = sop1 <= sop2; break; |
case SPR_DCR_CC_GREAT: DCR_hit = sop1 > sop2; break; |
case SPR_DCR_CC_GREATE: DCR_hit = sop1 >= sop2; break; |
} |
} else { |
switch(dcr & SPR_DCR_CC) { |
case SPR_DCR_CC_MASKED: DCR_hit = op1 & op2; break; |
case SPR_DCR_CC_EQUAL: DCR_hit = op1 == op2; break; |
case SPR_DCR_CC_NEQUAL: DCR_hit = op1 != op2; break; |
case SPR_DCR_CC_LESS: DCR_hit = op1 < op2; break; |
case SPR_DCR_CC_LESSE: DCR_hit = op1 <= op2; break; |
case SPR_DCR_CC_GREAT: DCR_hit = op1 > op2; break; |
case SPR_DCR_CC_GREATE: DCR_hit = op1 >= op2; break; |
} |
} |
} |
} |
|
/* Chain matchpoints */ |
switch(i) { |
case 0: |
chain1 = chain2 = DCR_hit; |
break; |
case 8: |
chain1 = getsprbits (SPR_DWCR0, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR0, SPR_DWCR_MATCH); |
chain2 = watchpoints & (1 << 7); |
break; |
case 9: |
chain1 = getsprbits (SPR_DWCR1, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR1, SPR_DWCR_MATCH); |
chain2 = watchpoints & (1 << 8); |
break; |
case 10: |
/* TODO: External watchpoint - not yet handled! */ |
#if 0 |
chain1 = external_watchpoint; |
chain2 = watchpoints & (1 << 9); |
#else |
chain1 = chain2 = 0; |
#endif |
break; |
default: |
chain1 = DCR_hit; |
chain2 = watchpoints & (bit >> 1); |
break; |
} |
|
switch(getsprbits (SPR_DMR1, SPR_DMR1_CW0 << i)) { |
case 0: match = chain1; break; |
case 1: match = chain1 && chain2; break; |
case 2: match = chain1 || chain2; break; |
default: |
break; |
} |
|
if(match & !(watchpoints & bit)) { |
int counter = (getsprbits (SPR_DMR2, SPR_DMR2_AWTC) & bit) ? 1 : 0; |
int enabled = counter ? getsprbits (SPR_DMR2, SPR_DMR2_WCE1) : getsprbits (SPR_DMR2, SPR_DMR2_WCE0); |
|
if(enabled) |
setsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT, getsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT) + 1); |
|
if(getsprbits (SPR_DMR2, SPR_DMR2_WGB) & bit) |
breakpoint = 1; |
} |
|
watchpoints &= ~bit; |
watchpoints |= bit; |
} |
|
return breakpoint; |
} |
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL; |
|
int DebugGetRegister(unsigned int address, unsigned long* data) |
{ |
int err; |
#ifdef DEBUG_JTAG |
printf("Debug get register %x\n",address); |
fflush(stdout); |
#endif |
switch(current_scan_chain) |
{ |
case JTAG_CHAIN_DEBUG_UNIT: |
*data = mfspr (address); |
debug (2, "READ (%08x) = %08x\n", address, *data); |
if (runtime.sim.fspr_log) { |
fprintf(runtime.sim.fspr_log, "Read from SPR : [%08lX] -> [%08lX]\n", address, *data); |
} |
break; |
case JTAG_CHAIN_TRACE: |
*data = 0; /* Scan chain not yet implemented */ |
err = 0; |
break; |
case JTAG_CHAIN_DEVELOPMENT: |
err = get_devint_reg(address,data); |
break; |
case JTAG_CHAIN_WISHBONE: |
err = GetWishboneMemory(address,data); |
break; |
} |
#ifdef DEBUG_JTAG |
printf("!get reg %x\n", *data); |
fflush(stdout); |
#endif |
return err; |
} |
|
int DebugSetRegister(unsigned int address,unsigned long data) |
{ |
int err; |
#ifdef DEBUG_JTAG |
printf("Debug set register %x <- %x\n", address, data); |
fflush(stdout); |
#endif |
switch(current_scan_chain) |
{ |
case JTAG_CHAIN_DEBUG_UNIT: |
debug (2, "WRITE (%08x) = %08x\n", address, data); |
if (runtime.sim.fspr_log) { |
fprintf(runtime.sim.fspr_log, "Write to SPR : [%08lX] <- [%08lX]\n", address, data); |
} |
mtspr(address, data); |
break; |
case JTAG_CHAIN_TRACE: |
err = JTAG_PROXY_ACCESS_EXCEPTION; |
break; |
case JTAG_CHAIN_DEVELOPMENT: |
err = set_devint_reg (address, data); |
break; |
case JTAG_CHAIN_WISHBONE: |
err = debug_set_mem (address, data); |
break; |
} |
#ifdef DEBUG_JTAG |
printf("!set reg\n"); |
fflush(stdout); |
#endif |
return err; |
} |
|
int DebugSetChain(int chain) |
{ |
#ifdef DEBUG_JTAG |
printf("Debug set chain %x\n",chain); |
fflush(stdout); |
#endif |
switch(chain) |
{ |
case JTAG_CHAIN_DEBUG_UNIT: |
case JTAG_CHAIN_TRACE: |
case JTAG_CHAIN_DEVELOPMENT: |
case JTAG_CHAIN_WISHBONE: |
current_scan_chain = chain; |
break; |
default: /* All other chains not implemented */ |
return JTAG_PROXY_INVALID_CHAIN; |
} |
|
#ifdef DEBUG_JTAG |
printf("!set chain\n"); |
fflush(stdout); |
#endif |
return 0; |
} |
|
void sim_reset (); |
|
/* Sets development interface register */ |
int set_devint_reg(unsigned int address, unsigned long data) |
{ |
int err = 0; |
unsigned long value = data; |
int old_value; |
|
switch(address) { |
case DEVELOPINT_MODER: development.moder = value; break; |
case DEVELOPINT_TSEL: development.tsel = value; break; |
case DEVELOPINT_QSEL: development.qsel = value; break; |
case DEVELOPINT_SSEL: development.ssel = value; break; |
case DEVELOPINT_RISCOP: |
old_value = (development.riscop & RISCOP_RESET) != 0; |
development.riscop = value; |
in_reset = (development.riscop & RISCOP_RESET) != 0; |
/* Reset the cpu on the negative edge of RESET */ |
if(old_value && !in_reset) |
sim_reset(); /* Reset all units */ |
set_stall_state((development.riscop & RISCOP_STALL) != 0); |
break; |
case DEVELOPINT_RECWP0: |
case DEVELOPINT_RECWP1: |
case DEVELOPINT_RECWP2: |
case DEVELOPINT_RECWP3: |
case DEVELOPINT_RECWP4: |
case DEVELOPINT_RECWP5: |
case DEVELOPINT_RECWP6: |
case DEVELOPINT_RECWP7: |
case DEVELOPINT_RECWP8: |
case DEVELOPINT_RECWP9: |
case DEVELOPINT_RECWP10: development.recwp[address - DEVELOPINT_RECWP0] = value; break; |
case DEVELOPINT_RECBP0: development.recbp = value; break; |
default: |
err = JTAG_PROXY_INVALID_ADDRESS; |
break; |
} |
#ifdef DEBUG_JTAG |
printf("set_devint_reg %08x = %08x\n", address, data); |
fflush(stdout); |
#endif |
return err; |
} |
|
int get_devint_reg(unsigned int address,unsigned long *data) |
{ |
int err = 0; |
unsigned long value = 0; |
|
switch(address) { |
case DEVELOPINT_MODER: value = development.moder; break; |
case DEVELOPINT_TSEL: value = development.tsel; break; |
case DEVELOPINT_QSEL: value = development.qsel; break; |
case DEVELOPINT_SSEL: value = development.ssel; break; |
case DEVELOPINT_RISCOP: value = development.riscop; break; |
case DEVELOPINT_RECWP0: |
case DEVELOPINT_RECWP1: |
case DEVELOPINT_RECWP2: |
case DEVELOPINT_RECWP3: |
case DEVELOPINT_RECWP4: |
case DEVELOPINT_RECWP5: |
case DEVELOPINT_RECWP6: |
case DEVELOPINT_RECWP7: |
case DEVELOPINT_RECWP8: |
case DEVELOPINT_RECWP9: |
case DEVELOPINT_RECWP10: value = development.recwp[address - DEVELOPINT_RECWP0]; break; |
case DEVELOPINT_RECBP0: value = development.recbp; break; |
default: err = JTAG_PROXY_INVALID_ADDRESS; break; |
} |
|
#ifdef DEBUG_JTAG |
printf("get_devint_reg %08x = %08x\n", address, value); |
fflush(stdout); |
#endif |
*data = value; |
return err; |
} |
|
/* Writes to bus address */ |
int debug_set_mem (unsigned int address,unsigned long data) |
{ |
int err = 0; |
debug (2, "MEMWRITE (%08x) = %08x\n", address, data); |
|
|
if(!verify_memoryarea(address)) |
err = JTAG_PROXY_INVALID_ADDRESS; |
else { |
unsigned char t_data[4]; |
int *tmp = (int*)t_data; |
extern char null_str[1]; /* From cpu/common/parse.c */ |
int i; |
|
*tmp = htonl(data); /* We have already converted to host order */ |
|
setsim_mem8(address++, t_data[0]); /* Back to network byte order */ |
setsim_mem8(address++, t_data[1]); |
setsim_mem8(address++, t_data[2]); |
setsim_mem8(address++, t_data[3]); |
} |
return err; |
} |
|
int GetWishboneMemory(unsigned int address,unsigned long *data) |
{ |
int err = 0; |
if(!verify_memoryarea(address)) |
err = JTAG_PROXY_INVALID_ADDRESS; |
else |
{ |
unsigned char t_data[4]; |
int *tmp = (int*)t_data; |
int bp; |
|
t_data[0] = evalsim_mem8(address++); |
t_data[1] = evalsim_mem8(address++); |
t_data[2] = evalsim_mem8(address++); |
t_data[3] = evalsim_mem8(address++); /* Already in network byte order */ |
|
*data = ntohl(*tmp); /* But we assume it is in host order later */ |
} |
debug (2, "MEMREAD (%08x) = %08x\n", address, *data); |
return err; |
} |
|
/* debug_ignore_exception returns 1 if the exception should be ignored. */ |
int debug_ignore_exception (unsigned long except) |
{ |
int result = 0; |
unsigned long dsr = mfspr (SPR_DSR); |
unsigned long drr = mfspr (SPR_DRR); |
|
&debug_ignore_exception; |
|
#if DEBUG_JTAG |
printf ("dsr 0x%08x drr 0x%08x \n", dsr, drr); |
#endif |
|
switch(except) { |
case EXCEPT_RESET: drr |= result = dsr & SPR_DSR_RSTE; break; |
case EXCEPT_BUSERR: drr |= result = dsr & SPR_DSR_BUSEE; break; |
case EXCEPT_DPF: drr |= result = dsr & SPR_DSR_DPFE; break; |
case EXCEPT_IPF: drr |= result = dsr & SPR_DSR_IPFE; break; |
case EXCEPT_TICK: drr |= result = dsr & SPR_DSR_TTE; break; |
case EXCEPT_ALIGN: drr |= result = dsr & SPR_DSR_AE; break; |
case EXCEPT_ILLEGAL: drr |= result = dsr & SPR_DSR_IIE; break; |
case EXCEPT_INT: drr |= result = dsr & SPR_DSR_IE; break; |
case EXCEPT_DTLBMISS: drr |= result = dsr & SPR_DSR_DME; break; |
case EXCEPT_ITLBMISS: drr |= result = dsr & SPR_DSR_IME; break; |
case EXCEPT_RANGE: drr |= result = dsr & SPR_DSR_RE; break; |
case EXCEPT_SYSCALL: drr |= result = dsr & SPR_DSR_SCE; break; |
case EXCEPT_TRAP: drr |= result = dsr & SPR_DSR_TE; break; |
default: |
break; |
} |
#if DEBUG_JTAG |
printf ("dsr 0x%08x drr 0x%08x result %i\n", dsr, drr, result); |
#endif |
|
mtspr (SPR_DRR, drr); |
set_stall_state (result != 0); |
return (result != 0); |
} |
debug_unit.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: Makefile.in
===================================================================
--- Makefile.in (nonexistent)
+++ Makefile.in (revision 1765)
@@ -0,0 +1,332 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# Makefile -- Makefile for peripherals simulation
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+BUILD_DIR = @BUILD_DIR@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPU_ARCH = @CPU_ARCH@
+INCLUDES = @INCLUDES@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@
+LOCAL_DEFS = @LOCAL_DEFS@
+LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
+MAKEINFO = @MAKEINFO@
+MAKE_SHELL = @MAKE_SHELL@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+SUMVERSION = @SUMVERSION@
+TERMCAP_LIB = @TERMCAP_LIB@
+VERSION = @VERSION@
+host = @host@
+host_cpu = @host_cpu@
+host_os = @host_os@
+
+noinst_LIBRARIES = libdebug.a
+libdebug_a_SOURCES = debug_unit.c debug_unit.h gdbcomm.c gdbcomm.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libdebug_a_LIBADD =
+libdebug_a_OBJECTS = debug_unit.o gdbcomm.o
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES = .deps/debug_unit.P .deps/gdbcomm.P
+SOURCES = $(libdebug_a_SOURCES)
+OBJECTS = $(libdebug_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu debug/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libdebug.a: $(libdebug_a_OBJECTS) $(libdebug_a_DEPENDENCIES)
+ -rm -f libdebug.a
+ $(AR) cru libdebug.a $(libdebug_a_OBJECTS) $(libdebug_a_LIBADD)
+ $(RANLIB) libdebug.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = debug
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu debug/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+ -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-depend mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-noinstLIBRARIES distclean-compile \
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-depend maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: gdb.h
===================================================================
--- gdb.h (nonexistent)
+++ gdb.h (revision 1765)
@@ -0,0 +1,133 @@
+/* config.h -- Simulator configuration header file
+ Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef GDB_H
+#define GDB_H
+
+#include
+#include
+
+#define DEBUG_SLOWDOWN (1)
+
+enum enum_errors /* modified CZ 24/05/01 */
+{
+ /* Codes > 0 are for system errors */
+
+ ERR_NONE = 0,
+ ERR_CRC = -1,
+ ERR_MEM = -2,
+ JTAG_PROXY_INVALID_COMMAND = -3,
+ JTAG_PROXY_SERVER_TERMINATED = -4,
+ JTAG_PROXY_NO_CONNECTION = -5,
+ JTAG_PROXY_PROTOCOL_ERROR = -6,
+ JTAG_PROXY_COMMAND_NOT_IMPLEMENTED = -7,
+ JTAG_PROXY_INVALID_CHAIN = -8,
+ JTAG_PROXY_INVALID_ADDRESS = -9,
+ JTAG_PROXY_ACCESS_EXCEPTION = -10, /* Write to ROM */
+ JTAG_PROXY_INVALID_LENGTH = -11,
+ JTAG_PROXY_OUT_OF_MEMORY = -12,
+};
+
+/* This is repeated from gdb tm-or1k.h There needs to be
+ a better mechanism for tracking this, but I don't see
+ an easy way to share files between modules. */
+
+typedef enum {
+ JTAG_COMMAND_READ = 1,
+ JTAG_COMMAND_WRITE = 2,
+ JTAG_COMMAND_BLOCK_READ = 3,
+ JTAG_COMMAND_BLOCK_WRITE = 4,
+ JTAG_COMMAND_CHAIN = 5,
+} JTAG_proxy_protocol_commands;
+
+/* Each transmit structure must begin with an integer
+ which specifies the type of command. Information
+ after this is variable. Make sure to have all information
+ aligned properly. If we stick with 32 bit integers, it
+ should be portable onto every platform. These structures
+ will be transmitted across the network in network byte
+ order.
+*/
+
+typedef struct {
+ uint32_t command;
+ uint32_t length;
+ uint32_t address;
+ uint32_t data_H;
+ uint32_t data_L;
+} JTAGProxyWriteMessage;
+
+typedef struct {
+ uint32_t command;
+ uint32_t length;
+ uint32_t address;
+} JTAGProxyReadMessage;
+
+typedef struct {
+ uint32_t command;
+ uint32_t length;
+ uint32_t address;
+ int32_t nRegisters;
+ uint32_t data[1];
+} JTAGProxyBlockWriteMessage;
+
+typedef struct {
+ uint32_t command;
+ uint32_t length;
+ uint32_t address;
+ int32_t nRegisters;
+} JTAGProxyBlockReadMessage;
+
+typedef struct {
+ uint32_t command;
+ uint32_t length;
+ uint32_t chain;
+} JTAGProxyChainMessage;
+
+/* The responses are messages specific, however convention
+ states the first word should be an error code. Again,
+ sticking with 32 bit integers should provide maximum
+ portability. */
+
+typedef struct {
+ int32_t status;
+} JTAGProxyWriteResponse;
+
+typedef struct {
+ int32_t status;
+ uint32_t data_H;
+ uint32_t data_L;
+} JTAGProxyReadResponse;
+
+typedef struct {
+ int32_t status;
+} JTAGProxyBlockWriteResponse;
+
+typedef struct {
+ int32_t status;
+ int32_t nRegisters;
+ uint32_t data[1];
+ /* uint32_t data[nRegisters-1] still unread */
+} JTAGProxyBlockReadResponse;
+
+typedef struct {
+ int32_t status;
+} JTAGProxyChainResponse;
+
+#endif /* GDB_H */
gdb.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: gdbcomm.c
===================================================================
--- gdbcomm.c (nonexistent)
+++ gdbcomm.c (revision 1765)
@@ -0,0 +1,660 @@
+/* gdbcomm.c -- Communication routines for gdb
+ Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
+ Code copied from toplevel.c
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "gdb.h"
+#include "gdbcomm.h"
+#include "vapi.h"
+#include "sim-config.h"
+
+static unsigned int serverIP = 0;
+static unsigned int serverPort = 0;
+static unsigned int server_fd = 0;
+static unsigned int gdb_fd = 0;
+
+static int tcp_level = 0;
+
+/* Added by CZ 24/05/01 */
+int GetServerSocket(const char* name,const char* proto,int port)
+{
+ struct servent *service;
+ struct protoent *protocol;
+ struct sockaddr_in sa;
+ struct hostent *hp;
+ int sockfd;
+ char myname[256];
+ int flags;
+ char sTemp[256];
+
+ /* First, get the protocol number of TCP */
+ if(!(protocol = getprotobyname(proto)))
+ {
+ sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
+ perror(sTemp);
+ return 0;
+ }
+ tcp_level = protocol->p_proto; /* Save for later */
+
+ /* If we weren't passed a non standard port, get the port
+ from the services directory. */
+ if(!port)
+ {
+ if(service = getservbyname(name,protocol->p_name))
+ port = ntohs(service->s_port);
+ }
+
+ /* Create the socket using the TCP protocol */
+ if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0)
+ {
+ perror("Unable to create socket");
+ return 0;
+ }
+
+ flags = 1;
+ if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0)
+ {
+ sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
+ perror(sTemp);
+ close(sockfd);
+ return 0;
+ }
+
+ /* The server should also be non blocking. Get the current flags. */
+ if(fcntl(sockfd,F_GETFL,&flags) < 0)
+ {
+ sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
+ perror(sTemp);
+ close(sockfd);
+ return 0;
+ }
+
+ /* Set the nonblocking flag */
+ if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
+ sockfd,flags | O_NONBLOCK);
+ perror(sTemp);
+ close(sockfd);
+ return 0;
+ }
+
+ /* Find out what our address is */
+ memset(&sa,0,sizeof(struct sockaddr_in));
+ gethostname(myname,sizeof(myname));
+ if(!(hp = gethostbyname(myname)))
+ {
+ perror("Unable to read hostname");
+ close(sockfd);
+ return 0;
+ }
+
+ /* Bind our socket to the appropriate address */
+ sa.sin_family = hp->h_addrtype;
+ sa.sin_port = htons(port);
+ if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0)
+ {
+ sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
+ perror(sTemp);
+ close(sockfd);
+ return 0;
+ }
+ serverIP = sa.sin_addr.s_addr;
+ flags = sizeof(struct sockaddr_in);
+ if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0)
+ {
+ sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
+ perror(sTemp);
+ close(sockfd);
+ return 0;
+ }
+ serverPort = ntohs(sa.sin_port);
+
+ /* Set the backlog to 1 connections */
+ if(listen(sockfd,1) < 0)
+ {
+ sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
+ perror(sTemp);
+ close(sockfd);
+ return 0;
+ }
+
+ return sockfd;
+}
+
+void BlockJTAG()
+{
+ struct pollfd fds[2];
+ int n = 0;
+
+ fds[n].fd = server_fd;
+ fds[n].events = POLLIN;
+ fds[n++].revents = 0;
+ if(gdb_fd)
+ {
+ fds[n].fd = gdb_fd;
+ fds[n].events = POLLIN;
+ fds[n++].revents = 0;
+ }
+ poll(fds,n,-1);
+}
+
+void HandleServerSocket(Boolean block)
+{
+ struct pollfd fds[3];
+ int n = 0;
+ int timeout = block ? -1 : 0;
+ int server_index = -1;
+ int gdb_index = -1;
+ Boolean data_on_stdin = false;
+ int o_serv_fd = server_fd;
+
+ if(!o_serv_fd && !gdb_fd)
+ return;
+
+ if(o_serv_fd)
+ {
+ fds[n].fd = o_serv_fd;
+ fds[n].events = POLLIN;
+ fds[n++].revents = 0;
+ }
+ if(gdb_fd)
+ {
+ fds[n].fd = gdb_fd;
+ fds[n].events = POLLIN;
+ fds[n++].revents = 0;
+ }
+ if(block)
+ {
+ fds[n].fd = 0;
+ fds[n].events = POLLIN;
+ fds[n++].revents = 0;
+ }
+
+ while(!data_on_stdin)
+ {
+ switch(poll(fds,n,timeout))
+ {
+ case -1:
+ if(errno == EINTR)
+ continue;
+ perror("poll");
+ server_fd = 0;
+ break;
+ case 0: /* Nothing interesting going on */
+ data_on_stdin = true; /* Can only get here if nonblocking */
+ break;
+ default:
+ /* Make sure to handle the gdb port first! */
+ if((fds[0].revents && (gdb_fd && !o_serv_fd) ||
+ fds[1].revents && (server_fd && gdb_fd)))
+ {
+ int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
+
+ if(revents & POLLIN)
+ GDBRequest();
+ else /* Error Occurred */
+ {
+ fprintf(stderr,"Received flags 0x%08x on gdb socket. Shutting down.\n",revents);
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ }
+ if(fds[0].revents && o_serv_fd)
+ {
+ if(fds[0].revents & POLLIN)
+ JTAGRequest();
+ else /* Error Occurred */
+ {
+ fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
+ close(o_serv_fd);
+ server_fd = 0;
+ serverPort = 0;
+ serverIP = 0;
+ }
+ }
+ if(fds[2].revents || (fds[1].revents && !gdb_fd))
+ data_on_stdin = true;
+ break;
+ } /* End of switch statement */
+ } /* End of while statement */
+}
+
+void JTAGRequest()
+{
+ struct sockaddr_in sa;
+ struct sockaddr* addr = (struct sockaddr*)&sa;
+ int n = sizeof(struct sockaddr_in);
+ int fd = accept(server_fd,addr,&n);
+ int on_off = 0; /* Turn off Nagel's algorithm on the socket */
+ int flags;
+ char sTemp[256];
+
+ if(fd < 0)
+ {
+ /* This is valid, because a connection could have started,
+ and then terminated due to a protocol error or user
+ initiation before the accept could take place. */
+ if(errno != EWOULDBLOCK && errno != EAGAIN)
+ {
+ perror("accept");
+ close(server_fd);
+ server_fd = 0;
+ serverPort = 0;
+ serverIP = 0;
+ }
+ return;
+ }
+
+ if(gdb_fd)
+ {
+ close(fd);
+ return;
+ }
+
+ if(fcntl(fd,F_GETFL,&flags) < 0)
+ {
+ sprintf(sTemp,"Unable to get flags for gdb socket %d",fd);
+ perror(sTemp);
+ close(fd);
+ return;
+ }
+
+ if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ sprintf(sTemp,"Unable to set flags for gdb socket %d to value 0x%08x",
+ fd,flags | O_NONBLOCK);
+ perror(sTemp);
+ close(fd);
+ return;
+ }
+
+ if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0)
+ {
+ sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
+ perror(sTemp);
+ close(fd);
+ return;
+ }
+
+ gdb_fd = fd;
+}
+
+void GDBRequest()
+{
+ JTAGProxyWriteMessage msg_write;
+ JTAGProxyReadMessage msg_read;
+ JTAGProxyChainMessage msg_chain;
+ JTAGProxyWriteResponse resp_write;
+ JTAGProxyReadResponse resp_read;
+ JTAGProxyChainResponse resp_chain;
+ JTAGProxyBlockWriteMessage *msg_bwrite;
+ JTAGProxyBlockReadMessage msg_bread;
+ JTAGProxyBlockWriteResponse resp_bwrite;
+ JTAGProxyBlockReadResponse *resp_bread;
+ char *buf;
+ unsigned long long data;
+ int err = 0;
+ uint32_t command,length;
+ int len,i;
+
+ /* First, we must read the incomming command */
+ if(gdb_read(&command,sizeof(uint32_t)) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 1");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ if(gdb_read(&length,sizeof(uint32_t)) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 2");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ length = ntohl(length);
+
+ /* Now, verify the protocol and implement the command */
+ switch(ntohl(command))
+ {
+ case JTAG_COMMAND_WRITE:
+ if(length != sizeof(msg_write) - 8)
+ {
+ ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
+ return;
+ }
+ buf = (char*)&msg_write;
+ if(gdb_read(&buf[8],length) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 3");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ msg_write.address = ntohl(msg_write.address);
+ msg_write.data_H = ntohl(msg_write.data_H);
+ msg_write.data_L = ntohl(msg_write.data_L);
+ err = DebugSetRegister(msg_write.address,msg_write.data_L);
+ resp_write.status = htonl(err);
+ if(gdb_write(&resp_write,sizeof(resp_write)) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 4");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ break;
+ case JTAG_COMMAND_READ:
+ if(length != sizeof(msg_read) - 8)
+ {
+ ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
+ return;
+ }
+ buf = (char*)&msg_read;
+ if(gdb_read(&buf[8],length) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 5");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ msg_read.address = ntohl(msg_read.address);
+ err = DebugGetRegister(msg_read.address,&resp_read.data_L);
+ resp_read.status = htonl(err);
+ resp_read.data_H = 0;
+ resp_read.data_L = htonl(resp_read.data_L);
+ if(gdb_write(&resp_read,sizeof(resp_read)) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 6");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ break;
+ case JTAG_COMMAND_BLOCK_WRITE:
+ if(length < sizeof(JTAGProxyBlockWriteMessage)-8)
+ {
+ ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
+ return;
+ }
+ if(!(buf = (char*)malloc(8+length)))
+ {
+ ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY);
+ return;
+ }
+ msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
+ if(gdb_read(&buf[8],length) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 5");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ free(buf);
+ return;
+ }
+ msg_bwrite->address = ntohl(msg_bwrite->address);
+ msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
+ for(i=0;inRegisters;i++)
+ {
+ int t_err = 0;
+
+ msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
+ t_err = DebugSetRegister(msg_bwrite->address + 4 * i,msg_bwrite->data[i]);
+ err = err ? err : t_err;
+ }
+ resp_bwrite.status = htonl(err);
+ free(buf);
+ buf = NULL;
+ msg_bwrite = NULL;
+ if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 4");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ break;
+ case JTAG_COMMAND_BLOCK_READ:
+ if(length != sizeof(msg_bread) - 8)
+ {
+ ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
+ return;
+ }
+ buf = (char*)&msg_bread;
+ if(gdb_read(&buf[8],length) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 5");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ msg_bread.address = ntohl(msg_bread.address);
+ msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
+ len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
+ if(!(buf = (char*)malloc(len)))
+ {
+ ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY);
+ return;
+ }
+ resp_bread = (JTAGProxyBlockReadResponse*)buf;
+ for(i=0;idata[i]);
+ resp_bread->data[i] = htonl(resp_bread->data[i]);
+ err = err ? err : t_err;
+ }
+ resp_bread->status = htonl(err);
+ resp_bread->nRegisters = htonl(msg_bread.nRegisters);
+ if(gdb_write(resp_bread,len) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 6");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ free(buf);
+ return;
+ }
+ free(buf);
+ buf = NULL;
+ resp_bread = NULL;
+ break;
+ case JTAG_COMMAND_CHAIN:
+ if(length != sizeof(msg_chain) - 8)
+ {
+ ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
+ return;
+ }
+ buf = (char*)&msg_chain;
+ if(gdb_read(&buf[8],sizeof(msg_chain)-8) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 7");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ msg_chain.chain = htonl(msg_chain.chain);
+ err = DebugSetChain(msg_chain.chain);
+ resp_chain.status = htonl(err);
+ if(gdb_write(&resp_chain,sizeof(resp_chain)) < 0)
+ {
+ if(gdb_fd)
+ {
+ perror("gdb socket - 8");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+ return;
+ }
+ break;
+ default:
+ ProtocolClean(length,JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
+ break;
+ }
+}
+
+void ProtocolClean(int length,int32_t err)
+{
+ char buf[4096];
+
+ err = htonl(err);
+ if((gdb_read(buf,length) < 0) ||
+ (gdb_write(&err,sizeof(err)) < 0) && gdb_fd)
+ {
+ perror("gdb socket - 9");
+ close(gdb_fd);
+ gdb_fd = 0;
+ }
+}
+
+static int gdb_write(const void* buf,int len)
+{
+ int n, log_n = 0;
+ const char* w_buf = (const char*)buf;
+ const uint32_t* log_buf = (const uint32_t*)buf;
+ struct pollfd block;
+
+ while(len) {
+ if((n = write(gdb_fd,w_buf,len)) < 0) {
+ switch(errno) {
+ case EWOULDBLOCK: /* or EAGAIN */
+ /* We've been called on a descriptor marked
+ for nonblocking I/O. We better simulate
+ blocking behavior. */
+ block.fd = gdb_fd;
+ block.events = POLLOUT;
+ block.revents = 0;
+ poll(&block,1,-1);
+ continue;
+ case EINTR:
+ continue;
+ case EPIPE:
+ close(gdb_fd);
+ gdb_fd = 0;
+ return -1;
+ default:
+ return -1;
+ }
+ }
+ else {
+ len -= n;
+ w_buf += n;
+ if ( config.debug.vapi_id )
+ for ( log_n += n; log_n >= 4; log_n -= 4, ++ log_buf )
+ vapi_write_log_file( VAPI_COMMAND_SEND, config.debug.vapi_id, ntohl(*log_buf) );
+ }
+ }
+ return 0;
+}
+
+static int gdb_read(void* buf,int len)
+{
+ int n, log_n = 0;
+ char* r_buf = (char*)buf;
+ uint32_t* log_buf = (uint32_t*)buf;
+ struct pollfd block;
+
+ while(len) {
+ if((n = read(gdb_fd,r_buf,len)) < 0) {
+ switch(errno) {
+ case EWOULDBLOCK: /* or EAGAIN */
+ /* We've been called on a descriptor marked
+ for nonblocking I/O. We better simulate
+ blocking behavior. */
+ block.fd = gdb_fd;
+ block.events = POLLIN;
+ block.revents = 0;
+ poll(&block,1,-1);
+ continue;
+ case EINTR:
+ continue;
+ default:
+ return -1;
+ }
+ }
+ else if(n == 0) {
+ close(gdb_fd);
+ gdb_fd = 0;
+ return -1;
+ }
+ else {
+ len -= n;
+ r_buf += n;
+ if ( config.debug.vapi_id )
+ for ( log_n += n; log_n >= 4; log_n -= 4, ++ log_buf )
+ vapi_write_log_file( VAPI_COMMAND_REQUEST, config.debug.vapi_id, ntohl(*log_buf) );
+ }
+ }
+ return 0;
+}
+
+int gdbcomm_init ()
+{
+ serverPort = config.debug.server_port;
+ if(server_fd = GetServerSocket("or1ksim","tcp",serverPort))
+ printf("JTAG Proxy server started on port %d\n",serverPort);
+ else
+ printf("Cannot start JTAG proxy server on port %d\n", serverPort);
+}
gdbcomm.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: debug_unit.h
===================================================================
--- debug_unit.h (nonexistent)
+++ debug_unit.h (revision 1765)
@@ -0,0 +1,102 @@
+/* debug_unit.h -- Simulation of Or1k debug unit
+ Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+typedef enum {
+ JTAG_CHAIN_GLOBAL = 0,
+ JTAG_CHAIN_DEBUG_UNIT = 1,
+ JTAG_CHAIN_TEST = 2,
+ JTAG_CHAIN_TRACE = 3,
+ JTAG_CHAIN_DEVELOPMENT = 4,
+ JTAG_CHAIN_WISHBONE = 5,
+ JTAG_CHAIN_BLOCK1 = 6,
+ JTAG_CHAIN_BLOCK2 = 7,
+ JTAG_CHAIN_OPTIONAL0 = 8,
+ JTAG_CHAIN_OPTIONAL1 = 9,
+ JTAG_CHAIN_OPTIONAL2 = 10,
+ JTAG_CHAIN_OPTIONAL3 = 11,
+ JTAG_CHAIN_OPTIONAL4 = 12,
+ JTAG_CHAIN_OPTIONAL5 = 13,
+ JTAG_CHAIN_OPTIONAL6 = 14,
+ JTAG_CHAIN_OPTIONAL7 = 15,
+} DebugScanChainIDs;
+
+
+typedef struct {
+ unsigned int DCR_hit;
+ unsigned int watchpoint;
+} DebugUnit;
+
+typedef enum {
+ DebugInstructionFetch = 1,
+ DebugLoadAddress = 2,
+ DebugStoreAddress = 3,
+ DebugLoadData = 4,
+ DebugStoreData = 5,
+} DebugUnitAction;
+
+
+/* Debug registers and their bits */
+typedef struct {
+ unsigned long moder;
+ unsigned long tsel;
+ unsigned long qsel;
+ unsigned long ssel;
+ unsigned long riscop;
+ unsigned long recwp[11];
+ unsigned long recbp;
+} DevelopmentInterface;
+
+typedef enum {
+ DEVELOPINT_MODER = 0,
+ DEVELOPINT_TSEL = 1,
+ DEVELOPINT_QSEL = 2,
+ DEVELOPINT_SSEL = 3,
+ DEVELOPINT_RISCOP = 4,
+ DEVELOPINT_RECWP0 = 16,
+ DEVELOPINT_RECWP1 = 17,
+ DEVELOPINT_RECWP2 = 18,
+ DEVELOPINT_RECWP3 = 19,
+ DEVELOPINT_RECWP4 = 20,
+ DEVELOPINT_RECWP5 = 21,
+ DEVELOPINT_RECWP6 = 22,
+ DEVELOPINT_RECWP7 = 23,
+ DEVELOPINT_RECWP8 = 24,
+ DEVELOPINT_RECWP9 = 25,
+ DEVELOPINT_RECWP10 = 26,
+ DEVELOPINT_RECBP0 = 27,
+} DevelopmentInterfaceAddressSpace;
+
+#define RISCOP_STALL 0x00000001
+#define RISCOP_RESET 0x00000002
+
+/* Risc stall state */
+extern int cpu_stalled;
+
+/* Resets the debug unit */
+void du_reset(void);
+
+/* set cpu_stalled flag */
+void set_stall_state (int state);
+
+/* Whether debug unit should ignore exception */
+int debug_ignore_exception (unsigned long except);
+
+#ifdef DEBUGMOD_OFF
+#define CheckDebugUnit(x,y) 0
+#endif
debug_unit.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: gdbcomm.h
===================================================================
--- gdbcomm.h (nonexistent)
+++ gdbcomm.h (revision 1765)
@@ -0,0 +1,39 @@
+/* gdbcomm.h -- Communication routines for gdb
+ Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
+ Code copied from toplevel.c
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "gdb.h"
+#include
+#include
+typedef enum {
+ false = 0,
+ true = 1,
+} Boolean;
+
+void HandleServerSocket(Boolean);
+void JTAGRequest(void);
+void GDBRequest(void);
+void ProtocolClean(int,int32_t);
+static int gdb_read(void *, int);
+static int gdb_write(const void *, int);
+void BlockJTAG(void);
+int GetServerSocket(const char* name,const char* proto,int port);
+
+int gdbcomm_init ();
gdbcomm.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 1765)
@@ -0,0 +1,22 @@
+# Makefile -- Makefile for peripherals simulation
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+noinst_LIBRARIES = libdebug.a
+libdebug_a_SOURCES = debug_unit.c debug_unit.h gdbcomm.c gdbcomm.h
Makefile.am
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: debug_unit.c.bak
===================================================================
--- debug_unit.c.bak (nonexistent)
+++ debug_unit.c.bak (revision 1765)
@@ -0,0 +1,715 @@
+/* debug_unit.c -- Simulation of Or1k debug unit
+ Copyright (C) 2001 Chris Ziomkowski, chris@asics.ws
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ This is an architectural level simulation of the Or1k debug
+ unit as described in OpenRISC 1000 System Architecture Manual,
+ v. 0.1 on 22 April, 2001. This unit is described in Section 13.
+
+ Every attempt has been made to be as accurate as possible with
+ respect to the registers and the behavior. There are no known
+ limitations at this time.
+*/
+
+#include
+#include
+#include
+#include
+
+#include "debug_unit.h"
+#include "sim-config.h"
+#include "except.h"
+#include "arch.h"
+#include "abstract.h"
+#include "parse.h"
+#include "trace.h"
+#include "sprs.h"
+#include "../gdb.h"
+#include "../cpu/or1k/except.h"
+#include "opcode/or32.h"
+
+DebugUnit debug_unit;
+DevelopmentInterface development;
+
+typedef enum {
+ false = 0,
+ true = 1,
+} Boolean;
+static void ExecuteInducedInstruction(unsigned long);
+
+/* External STALL signal to debug interface */
+int cpu_stalled = false;
+int in_reset = false;
+
+/* An induced instruction has been written to the DIR register */
+static Boolean induced = false;
+static unsigned long induced_insn;
+
+/* A flag to indicate that we must perform an ic mmu cycle */
+static Boolean lookup_physical_address = false;
+
+/* Variables for implementing ExecuteInducedInstruction */
+extern unsigned long pc;
+extern unsigned long pcnext;
+extern unsigned long pcdelay;
+extern unsigned long pc_phy;
+extern int delay_insn;
+static void GetIQueueEntry(struct iqueue_entry*);
+
+static int CalculateWatchpoints(void);
+
+static int watchpoint[10];
+
+/* This function returns true if an induced instruction has
+ been inserted into the instruction stream. It will remove
+ that instruction and return the result. This function is
+ called from the fetch() routine. */
+int OverrideFetch(unsigned long* insn)
+{
+ int valid = induced;
+ induced = false;
+
+ if(valid)
+ *insn = induced_insn;
+ return valid;
+}
+
+void InduceImmediateInstruction(unsigned long insn)
+{
+ induced = true;
+ induced_insn = insn;
+
+ if(in_reset)
+ return;
+
+ if(cpu_stalled)
+ {
+ ExecuteInducedInstruction(insn);
+ induced_insn = 0;
+ induced = false;
+ }
+}
+
+void SetCPUStallState(int state)
+{
+ if(debug_unit.DMR1.DXFW) /* If debugger disabled */
+ state = false;
+
+ if(state == cpu_stalled)
+ return;
+
+ if(state && induced)
+ {
+ ExecuteInducedInstruction(induced_insn);
+ induced_insn = 0;
+ induced = false;
+ }
+
+ cpu_stalled = state;
+}
+
+void ResetDebugUnit()
+{
+ memset(&debug_unit,'\0',sizeof(DebugUnit));
+ cpu_stalled = 0;
+}
+
+#ifdef DEBUGMOD_OFF
+#define CheckDebugUnit(x,y) 0
+#else
+inline int CheckDebugUnit(DebugUnitAction action,unsigned long udata)
+{
+ int i;
+ DCR_CT_Settings condition = DCR_CT_Disabled;
+ long data = (long)udata;
+ int match;
+
+ if(in_reset)
+ return 0;
+
+ /* If we're single stepping, always stop */
+ if(debug_unit.DMR1.ST && action == DebugInstructionFetch)
+ return 1;
+
+ switch(action)
+ {
+ case DebugInstructionFetch: condition = DCR_CT_InsnAddress; break;
+ case DebugLoadAddress: condition = DCR_CT_LoadAddress; break;
+ case DebugStoreAddress: condition = DCR_CT_StoreAddress; break;
+ case DebugLoadData: condition = DCR_CT_LoadData; break;
+ case DebugStoreData: condition = DCR_CT_StoreData; break;
+ }
+
+ for(i=0;i<8;i++)
+ {
+ if(debug_unit.DCR[i].DP == DCR_DP_Absent)
+ continue;
+
+ if(debug_unit.DCR[i].CT == condition)
+ {
+ if(debug_unit.DCR[i].SC == DCR_SC_Signed)
+ {
+ switch(debug_unit.DCR[i].CC)
+ {
+ case DCR_CC_Equal: match = data == (int)debug_unit.DVR[i]; break;
+ case DCR_CC_LessThan: match = data < (int)debug_unit.DVR[i]; break;
+ case DCR_CC_LessEqual: match = data <= (int)debug_unit.DVR[i]; break;
+ case DCR_CC_GreaterThan: match = data > (int)debug_unit.DVR[i]; break;
+ case DCR_CC_GreaterEqual: match = data >= (int)debug_unit.DVR[i]; break;
+ case DCR_CC_NotEqual: match = data != (int)debug_unit.DVR[i]; break;
+ default: match = 0; break;
+ }
+ }
+ else
+ {
+ switch(debug_unit.DCR[i].CC)
+ {
+ case DCR_CC_Equal: match = udata == debug_unit.DVR[i]; break;
+ case DCR_CC_LessThan: match = udata < debug_unit.DVR[i]; break;
+ case DCR_CC_LessEqual: match = udata <= debug_unit.DVR[i]; break;
+ case DCR_CC_GreaterThan: match = udata > debug_unit.DVR[i]; break;
+ case DCR_CC_GreaterEqual: match = udata >= debug_unit.DVR[i]; break;
+ case DCR_CC_NotEqual: match = udata != debug_unit.DVR[i]; break;
+ default: match = 0; break;
+ }
+ }
+ }
+ match <<= i;
+ debug_unit.DCR_hit &= ~match; /* Clear DCR compare if it has changed */
+ debug_unit.DCR_hit |= match; /* Save the state of each DCR compare */
+ }
+
+ return CalculateWatchpoints();
+}
+#endif
+
+static int CalculateWatchpoints()
+{
+ int spec[11];
+ int breakpoint = 0;
+ int i,bit;
+
+ spec[0] = debug_unit.DMR1.CW0;
+ spec[1] = debug_unit.DMR1.CW1;
+ spec[2] = debug_unit.DMR1.CW2;
+ spec[3] = debug_unit.DMR1.CW3;
+ spec[4] = debug_unit.DMR1.CW4;
+ spec[5] = debug_unit.DMR1.CW5;
+ spec[6] = debug_unit.DMR1.CW6;
+ spec[7] = debug_unit.DMR1.CW7;
+ spec[8] = debug_unit.DMR1.CW8;
+ spec[9] = debug_unit.DMR1.CW9;
+ spec[10] = debug_unit.DMR1.CW10;
+
+ for(i=0,bit=1;i<11;i++,bit<<=1)
+ {
+ int chain1,chain2;
+ int match = 0;
+
+ switch(i)
+ {
+ case 0:
+ chain1 = chain2 = debug_unit.DCR_hit & 0x01;
+ break;
+ case 8:
+ chain1 = debug_unit.DWCR[0].COUNT == debug_unit.DWCR[0].MATCH;
+ chain2 = debug_unit.watchpoint & (1 << 7);
+ break;
+ case 9:
+ chain1 = debug_unit.DWCR[1].COUNT == debug_unit.DWCR[1].MATCH;
+ chain2 = debug_unit.watchpoint & (1 << 8);
+ break;
+ case 10:
+ chain1 = debug_unit.DCR_hit & 0x100; /* External hit */
+ chain2 = debug_unit.watchpoint & (1 << 9);
+ break;
+ default:
+ chain1 = debug_unit.DCR_hit & bit;
+ chain2 = debug_unit.watchpoint & (bit >> 1);
+ break;
+ }
+
+ switch(spec[i])
+ {
+ case 0: match = chain1; break;
+ case 1: match = chain1 && chain2; break;
+ case 2: match = chain1 || chain2; break;
+ default:
+ break;
+ }
+
+ if(match & !(debug_unit.watchpoint & bit))
+ {
+ int counter = (debug_unit.DMR2.AWPC & bit) ? 1 : 0;
+ int enabled = counter ? debug_unit.DMR2.WCE1 : debug_unit.DMR2.WCE0;
+
+ if(enabled)
+ debug_unit.DWCR[counter].COUNT++;
+
+ if(debug_unit.DMR2.WGB & bit)
+ breakpoint = 1;
+ }
+
+ debug_unit.watchpoint &= ~bit;
+ debug_unit.watchpoint |= bit;
+ }
+
+ return breakpoint;
+}
+
+static void GetIQueueEntry(struct iqueue_entry* iq_entry)
+{
+ iq_entry->insn = induced_insn;
+ iq_entry->insn_index = insn_decode(induced_insn);
+ iq_entry->insn_addr = pc_phy;
+ iq_entry->op[0] = 0;
+ iq_entry->op[MAX_OPERANDS] = OPTYPE_LAST;
+}
+
+static void ExecuteInducedInstruction(unsigned long insn)
+{
+ struct iqueue_entry iq_entry;
+ unsigned long pc_saved = pc;
+ unsigned long pcnext_saved = pcnext;
+ unsigned long pcdelay_saved = pcdelay;
+ unsigned long pc_phy_saved = pc_phy;
+
+ GetIQueueEntry(&iq_entry);
+ decode_execute(&iq_entry);
+
+ pc = pc_saved;
+ pcnext = pcnext_saved;
+ pcdelay = pcdelay_saved;
+ pc_phy = pc_phy_saved;
+}
+
+static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
+
+int DebugGetRegister(unsigned int address,int32_t* data)
+{
+ int err;
+ printf("Debug get register %x\n",address);
+ fflush(stdout);
+ switch(current_scan_chain)
+ {
+ case JTAG_CHAIN_DEBUG_UNIT:
+ err = GetDebugUnitRegister(address,data);
+ break;
+ case JTAG_CHAIN_TRACE:
+ *data = 0; /* Scan chain not yet implemented */
+ err = 0;
+ break;
+ case JTAG_CHAIN_DEVELOPMENT:
+ err = GetDevelopmentInterfaceRegister(address,data);
+ break;
+ }
+ printf("!get reg %x\n", *data);
+ fflush(stdout);
+ return err;
+}
+
+int DebugSetRegister(unsigned int address,int32_t data)
+{
+ int err;
+ printf("Debug set register %x <- %x\n",address, data);
+ fflush(stdout);
+ switch(current_scan_chain)
+ {
+ case JTAG_CHAIN_DEBUG_UNIT:
+ err = SetDebugUnitRegister(address,data);
+ break;
+ case JTAG_CHAIN_TRACE:
+ err = JTAG_PROXY_ACCESS_EXCEPTION;
+ break;
+ case JTAG_CHAIN_DEVELOPMENT:
+ err = SetDevelopmentInterfaceRegister(address,data);
+ break;
+ }
+ printf("!set reg\n");
+ fflush(stdout);
+ return err;
+}
+
+int DebugSetChain(int chain)
+{
+ printf("Debug set chain %x\n",chain);
+ fflush(stdout);
+ switch(chain)
+ {
+ case JTAG_CHAIN_DEBUG_UNIT:
+ case JTAG_CHAIN_TRACE:
+ case JTAG_CHAIN_DEVELOPMENT:
+ current_scan_chain = chain;
+ break;
+ default: /* All other chains not implemented */
+ return JTAG_PROXY_INVALID_CHAIN;
+ }
+
+ printf("!set chain\n");
+ fflush(stdout);
+ return 0;
+}
+
+/* Nearly all compilers today store these bit fields as a packed structure
+ in network byte order (Big Endian). If you happen to be unlucky enough
+ to be working in a non standard environment, you may need to rewrite
+ this routine or the SET_REG32 macro. */
+int SetDevelopmentInterfaceRegister(unsigned int address,uint32_t data)
+{
+ int err = 0;
+ uint32_t value = data;
+ int old_value;
+ char *t_ptr = (char*)&development.RISCOP;
+
+ switch(address)
+ {
+ case DEVELOPINT_MODER:
+ SET_REG32(development.MODER,value);
+ break;
+ case DEVELOPINT_TSEL:
+ SET_REG32(development.TSEL,value);
+ break;
+ case DEVELOPINT_QSEL:
+ SET_REG32(development.QSEL,value);
+ break;
+ case DEVELOPINT_SSEL:
+ SET_REG32(development.SSEL,value);
+ break;
+ case DEVELOPINT_RISCOP:
+ old_value = development.RISCOP.RESET;
+ SET_REG32(development.RISCOP,value);
+
+ in_reset = development.RISCOP.RESET;
+
+ /* Reset the cpu on the negative edge of RESET */
+ if(old_value && !development.RISCOP.RESET)
+ {
+ uart_reset();
+ tick_reset();
+ pm_reset();
+ pic_reset();
+ reset(); /* Old or new mode */
+ }
+
+ SetCPUStallState(development.RISCOP.RISCSTALL);
+ break;
+ case DEVELOPINT_RECWP0:
+ case DEVELOPINT_RECWP1:
+ case DEVELOPINT_RECWP2:
+ case DEVELOPINT_RECWP3:
+ case DEVELOPINT_RECWP4:
+ case DEVELOPINT_RECWP5:
+ case DEVELOPINT_RECWP6:
+ case DEVELOPINT_RECWP7:
+ case DEVELOPINT_RECWP8:
+ case DEVELOPINT_RECWP9:
+ case DEVELOPINT_RECWP10:
+ SET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value);
+ break;
+ case DEVELOPINT_RECBP0:
+ SET_REG32(development.RECBP[0],value);
+ break;
+ default:
+ err = JTAG_PROXY_INVALID_ADDRESS;
+ break;
+ }
+ return err;
+}
+
+int GetDevelopmentInterfaceRegister(unsigned int address,uint32_t *data)
+{
+ int err = 0;
+ uint32_t value = 0;
+
+ switch(address)
+ {
+ case DEVELOPINT_MODER: GET_REG32(development.MODER,value); break;
+ case DEVELOPINT_TSEL: GET_REG32(development.TSEL,value); break;
+ case DEVELOPINT_QSEL: GET_REG32(development.QSEL,value); break;
+ case DEVELOPINT_SSEL: GET_REG32(development.SSEL,value); break;
+ case DEVELOPINT_RISCOP: GET_REG32(development.RISCOP,value); break;
+ case DEVELOPINT_RECWP0:
+ case DEVELOPINT_RECWP1:
+ case DEVELOPINT_RECWP2:
+ case DEVELOPINT_RECWP3:
+ case DEVELOPINT_RECWP4:
+ case DEVELOPINT_RECWP5:
+ case DEVELOPINT_RECWP6:
+ case DEVELOPINT_RECWP7:
+ case DEVELOPINT_RECWP8:
+ case DEVELOPINT_RECWP9:
+ case DEVELOPINT_RECWP10: GET_REG32(development.RECWP[address-DEVELOPINT_RECWP0],value); break;
+ case DEVELOPINT_RECBP0: GET_REG32(development.RECBP[0],value); break;
+ default: err = JTAG_PROXY_INVALID_ADDRESS; break;
+ }
+
+ *data = value;
+ return err;
+}
+
+/* Nearly all compilers today store these bit fields as a packed structure
+ in network byte order (Big Endian). If you happen to be unlucky enough
+ to be working in a non standard environment, you may need to rewrite
+ this routine or the SET_REG32 macro. */
+int SetDebugUnitRegister(unsigned int address,uint32_t data)
+{
+ int err = 0;
+ uint32_t value = data;
+ int old_value;
+ int group = address >> 11;
+
+ /* This is a memory location */
+ if(address & 0x80000000)
+ {
+ address &= 0x7FFFFFFF;
+ address <<= 2;
+
+ if(!verify_memoryarea(address))
+ err = JTAG_PROXY_INVALID_ADDRESS;
+ else
+ {
+ unsigned char t_data[4];
+ int *tmp = (int*)t_data;
+ extern char null_str[1]; /* From cpu/common/parse.c */
+ int i;
+
+ *tmp = htonl(data); /* We have already converted to host order */
+
+ setsim_mem8(address++, t_data[0]); /* Back to network byte order */
+ setsim_mem8(address++, t_data[1]);
+ setsim_mem8(address++, t_data[2]);
+ setsim_mem8(address++, t_data[3]);
+ }
+ return err;
+ }
+
+ address &= 0x07FF;
+
+ /*****************************************************/
+ /* TEMPORARY!!!! */
+ /*****************************************************/
+ if(group == 6)
+ address -= 32;
+
+ if(group == 6)
+ {
+ switch(address)
+ {
+ case DEBUGINT_DVR0:
+ case DEBUGINT_DVR1:
+ case DEBUGINT_DVR2:
+ case DEBUGINT_DVR3:
+ case DEBUGINT_DVR4:
+ case DEBUGINT_DVR5:
+ case DEBUGINT_DVR6:
+ case DEBUGINT_DVR7:
+ printf("DVR %d set to 0x%08x\n",address-DEBUGINT_DVR0,value);
+ SET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value);
+ break;
+ case DEBUGINT_DCR0:
+ case DEBUGINT_DCR1:
+ case DEBUGINT_DCR2:
+ case DEBUGINT_DCR3:
+ case DEBUGINT_DCR4:
+ case DEBUGINT_DCR5:
+ case DEBUGINT_DCR6:
+ case DEBUGINT_DCR7:
+ printf("DCR %d set to 0x%08x\n",address-DEBUGINT_DCR0,value);
+ SET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value);
+ break;
+ case DEBUGINT_DMR1:
+ SET_REG32(debug_unit.DMR1,value);
+ break;
+ case DEBUGINT_DMR2:
+ SET_REG32(debug_unit.DMR2,value);
+ break;
+ case DEBUGINT_DWCR0:
+ SET_REG32(debug_unit.DWCR[0],value);
+ break;
+ case DEBUGINT_DWCR1:
+ SET_REG32(debug_unit.DWCR[1],value);
+ break;
+ case DEBUGINT_DSR:
+ SET_REG32(debug_unit.DSR,value);
+ break;
+ case DEBUGINT_DRR:
+ SET_REG32(debug_unit.DRR,value);
+ break;
+ case DEBUGINT_DIR:
+ InduceImmediateInstruction(value);
+ break;
+ default:
+ err = JTAG_PROXY_INVALID_ADDRESS;
+ break;
+ }
+ }
+ else if(group == 0)
+ {
+ extern unsigned long reg[32];
+
+ if(!address)
+ err = JTAG_PROXY_ACCESS_EXCEPTION;
+ else if(address < 32)
+ {
+ /* Assume that a write to the PC implies
+ that the debugging software has recognized
+ the exception and wants to do something
+ else instead. */
+
+ if(address == SPR_PC)
+ {
+ ClearPendingException();
+ ClearPreparedPCState();
+ }
+ mtspr(address,data);
+ }
+ else if(address >= 0x0400 && address < 0x0420)
+ reg[address - 0x0400] = data;
+ else if(address < 0x0600 || address >= 0x0620)
+ err = JTAG_PROXY_INVALID_ADDRESS;
+ }
+ else
+ err = JTAG_PROXY_INVALID_ADDRESS;
+
+ return err;
+}
+
+int GetDebugUnitRegister(unsigned int address,uint32_t *data)
+{
+ int err = 0;
+ uint32_t value = 0;
+ int group = address >> 11;
+
+ /* This is a memory location */
+ if(address & 0x80000000)
+ {
+ address &= 0x7FFFFFFF;
+ address <<= 2;
+
+ if(!verify_memoryarea(address))
+ err = JTAG_PROXY_INVALID_ADDRESS;
+ else
+ {
+ unsigned char t_data[4];
+ int *tmp = (int*)t_data;
+ int bp;
+
+ t_data[0] = evalsim_mem8(address++);
+ t_data[1] = evalsim_mem8(address++);
+ t_data[2] = evalsim_mem8(address++);
+ t_data[3] = evalsim_mem8(address++); /* Already in network byte order */
+
+ *data = ntohl(*tmp); /* But we assume it is in host order later */
+ }
+ return err;
+ }
+
+ address &= 0x07FF;
+
+ /*****************************************************/
+ /* TEMPORARY!!!! */
+ /*****************************************************/
+ if(group == 6)
+ address -= 32;
+
+ if(group == 6)
+ {
+ switch(address)
+ {
+ case DEBUGINT_DVR0:
+ case DEBUGINT_DVR1:
+ case DEBUGINT_DVR2:
+ case DEBUGINT_DVR3:
+ case DEBUGINT_DVR4:
+ case DEBUGINT_DVR5:
+ case DEBUGINT_DVR6:
+ case DEBUGINT_DVR7: GET_REG32(debug_unit.DVR[address-DEBUGINT_DVR0],value); break;
+ case DEBUGINT_DCR0:
+ case DEBUGINT_DCR1:
+ case DEBUGINT_DCR2:
+ case DEBUGINT_DCR3:
+ case DEBUGINT_DCR4:
+ case DEBUGINT_DCR5:
+ case DEBUGINT_DCR6:
+ case DEBUGINT_DCR7: GET_REG32(debug_unit.DCR[address-DEBUGINT_DCR0],value); break;
+ case DEBUGINT_DMR1: GET_REG32(debug_unit.DMR1,value); break;
+ case DEBUGINT_DMR2: GET_REG32(debug_unit.DMR2,value); break;
+ case DEBUGINT_DWCR0: GET_REG32(debug_unit.DWCR[0],value); break;
+ case DEBUGINT_DWCR1: GET_REG32(debug_unit.DWCR[1],value); break;
+ case DEBUGINT_DSR: GET_REG32(debug_unit.DSR,value); break;
+ case DEBUGINT_DRR: GET_REG32(debug_unit.DRR,value); break;
+ case DEBUGINT_DIR: err = JTAG_PROXY_ACCESS_EXCEPTION; break;
+ default: err = JTAG_PROXY_INVALID_ADDRESS; break;
+ }
+ }
+ else if(group == 0)
+ {
+ extern unsigned long reg[32];
+
+ if(address < 32)
+ value = mfspr(address);
+ else if(address >= 0x0400 && address < 0x0420)
+ value = reg[address - 0x400];
+ else if(address >= 0x0600 && address < 0x0620)
+ value = 0;
+ else
+ err = JTAG_PROXY_INVALID_ADDRESS;
+ }
+ else
+ err = JTAG_PROXY_INVALID_ADDRESS;
+
+ *data = value;
+ return err;
+}
+
+/* DebugCheckException returns 1 if the exception should be ignored.
+ Currently, this is true only if the exception is a breakpoint
+ exception and debug_unit.DMR1.ST is set. Sorry, this is a quick
+ hack to disable processing of breakpoint exceptions on single
+ stepping. Just one of those historical accidents. Feel free
+ to rewrite the behavior. */
+int DebugCheckException(int exception)
+{
+ int result = 0;
+
+ switch(exception)
+ {
+ case EXCEPT_RESET: result = debug_unit.DRR.RSTE = debug_unit.DSR.RSTE; break;
+ case EXCEPT_BUSERR: result = debug_unit.DRR.BUSEE = debug_unit.DSR.BUSEE; break;
+ case EXCEPT_DPF: result = debug_unit.DRR.DPFE = debug_unit.DSR.DPFE; break;
+ case EXCEPT_IPF: result = debug_unit.DRR.IPFE = debug_unit.DSR.IPFE; break;
+ case EXCEPT_LPINT: result = debug_unit.DRR.LPINTE = debug_unit.DSR.LPINTE; break;
+ case EXCEPT_ALIGN: result = debug_unit.DRR.AE = debug_unit.DSR.AE; break;
+ case EXCEPT_ILLEGAL: result = debug_unit.DRR.IIE = debug_unit.DSR.IIE; break;
+ case EXCEPT_HPINT: result = debug_unit.DRR.HPINTE = debug_unit.DSR.HPINTE; break;
+ case EXCEPT_DTLBMISS: result = debug_unit.DRR.DME = debug_unit.DSR.DME; break;
+ case EXCEPT_ITLBMISS: result = debug_unit.DRR.IME = debug_unit.DSR.IME; break;
+ case EXCEPT_RANGE: result = debug_unit.DRR.RE = debug_unit.DSR.RE; break;
+ case EXCEPT_SYSCALL: result = debug_unit.DRR.SCE = debug_unit.DSR.SCE; break;
+ case EXCEPT_BREAK: result = debug_unit.DRR.BE = debug_unit.DSR.BE; break;
+ case EXCEPT_TRAP: result = debug_unit.DRR.TE = debug_unit.DSR.TE; break;
+ default:
+ break;
+ }
+
+ if(result)
+ SetCPUStallState(true);
+
+ return (debug_unit.DMR1.ST && exception == EXCEPT_BREAK);
+}
debug_unit.c.bak
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 1765)
.
Property changes :
Added: svn:ignore
## -0,0 +1 ##
+Makefile