OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.