OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /adv_debug_sys
    from Rev 65 to Rev 66
    Reverse comparison

Rev 65 → Rev 66

/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_xpc_dlc9.h
0,0 → 1,25
 
#ifndef _CABLE_XPC_DLC9_H_
#define _CABLE_XPC_DLC9_H_
 
#include <stdint.h>
#include "cable_common.h"
 
int cable_xpcusb_out(uint8_t value);
int cable_xpcusb_inout(uint8_t value, uint8_t *inval);
 
int cable_xpcusb_write_bit(uint8_t packet_out);
int cable_xpcusb_read_write_bit(uint8_t packet_out, uint8_t *bit_in);
 
int cable_xpcusb_cpld_write_bit(uint8_t value);
int cable_xpcusb_cpld_readwrite_bit(uint8_t value, uint8_t *inval);
 
int cable_xpcusb_write_stream(uint32_t *outstream, int len_bits, int set_last_bit);
int cable_xpcusb_readwrite_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit);
 
int cable_xpcusb_opt(int c, char *str);
jtag_cable_t *cable_xpcusb_get_driver(void);
 
int cable_xpcusb_init();
 
#endif
/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/utilities.c
0,0 → 1,69
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include "utilities.h"
#include "errcodes.h"
 
 
int check_buffer_size(char **buf, int *buf_size_bytes, int requested_size_bytes)
{
int ret = APP_ERR_NONE;
 
if(*buf_size_bytes >= requested_size_bytes)
{
return APP_ERR_NONE;
}
 
free(*buf);
*buf = (char *) malloc(requested_size_bytes);
if(*buf != NULL) {
*buf_size_bytes = requested_size_bytes;
}
else {
*buf_size_bytes = 0;
ret = APP_ERR_MALLOC;
}
 
return ret;
}
 
 
int create_timer(timeout_timer * timer)
{
int r;
//first timer alarm
timer->wait_time.it_value.tv_sec = 1;
timer->wait_time.it_value.tv_nsec = 0;
//continuous timer alarm -> 0 (we only want one alarm)
timer->wait_time.it_interval.tv_sec = 0;
timer->wait_time.it_interval.tv_nsec = 0;
 
timer->sev.sigev_notify = SIGEV_NONE;
 
r = timer_create(CLOCK_REALTIME, &timer->sev, &timer->timer);
if ( r )
{
fprintf(stderr, "Timer for timeout failed: %s\n", strerror(r));
return APP_ERR_USB;
}
 
//remaining timer time
timer->remaining_time = timer->wait_time;
r = timer_settime(timer->timer, 0, &timer->wait_time, NULL);
if ( r )
{
fprintf(stderr, "Setting timer failed: %s\n", strerror(r));
return APP_ERR_USB;
}
return APP_ERR_NONE;
}
 
int timedout(timeout_timer * timer)
{
int timed_out = 0;
timer_gettime(timer->timer, &timer->remaining_time);
timed_out = timer->remaining_time.it_value.tv_sec == 0 && timer->remaining_time.it_value.tv_nsec == 0;
return timed_out;
}
/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_sim.c
0,0 → 1,305
/* cable_sim.c - Simulation connection drivers for the Advanced JTAG Bridge
Copyright (C) 2001 Marko Mlinar, markom@opencores.org
 
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 <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
 
#include "cable_sim.h"
#include "errcodes.h"
 
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
 
/* Only used in the vpi */
jtag_cable_t vpi_cable_driver = {
.name = "vpi",
.inout_func = cable_vpi_inout,
.out_func = cable_vpi_out,
.init_func = cable_vpi_init,
.opt_func = cable_vpi_opt,
.bit_out_func = cable_common_write_bit,
.bit_inout_func = cable_common_read_write_bit,
.stream_out_func = cable_common_write_stream,
.stream_inout_func = cable_common_read_stream,
.flush_func = NULL,
.opts = "s:p:",
.help = "-p [port] Port number that the VPI module is listening on\n\t-s [server] Server that the VPI module is running on\n",
};
 
static int vpi_comm;
static int vpi_port = 4567;
static char *vpi_server = "localhost";
 
/* Only used for the rtl_sim */
jtag_cable_t rtl_cable_driver = {
.name ="rtl_sim",
.inout_func = cable_rtl_sim_inout,
.out_func = cable_rtl_sim_out,
.init_func = cable_rtl_sim_init,
.opt_func = cable_rtl_sim_opt,
.bit_out_func = cable_common_write_bit,
.bit_inout_func = cable_common_read_write_bit,
.stream_out_func = cable_common_write_stream,
.stream_inout_func = cable_common_read_stream,
.flush_func = NULL,
.opts = "d:",
.help = "-d [directory] Directory in which gdb_in.dat/gdb_out.dat may be found\n"
};
 
static char *gdb_in = "gdb_in.dat";
static char *gdb_out = "gdb_out.dat";
 
 
 
/*-------------------------------------------[ rtl_sim specific functions ]---*/
jtag_cable_t *cable_rtl_get_driver(void)
{
return &rtl_cable_driver;
}
 
int cable_rtl_sim_init()
{
FILE *fin = fopen (gdb_in, "wt+");
if(!fin) {
fprintf(stderr, "Can not open %s\n", gdb_in);
return APP_ERR_INIT_FAILED;
}
fclose(fin);
return APP_ERR_NONE;
}
 
int cable_rtl_sim_out(uint8_t value)
{
FILE *fout;
int num_read;
int r;
debug("O (%x)\n", value);
fout = fopen(gdb_in, "wt+");
fprintf(fout, "F\n");
fflush(fout);
fclose(fout);
fout = fopen(gdb_out, "wt+");
fprintf(fout, "%02X\n", value);
fflush(fout);
fclose(fout);
do {
fout = fopen(gdb_out, "rt");
r = fscanf(fout,"%x", &num_read);
fclose(fout);
usleep(1000);
debug(" (Ack %x) ", num_read);
} while(!r || (num_read != (0x10 | value)));
debug("\n");
return APP_ERR_NONE;
}
 
int cable_rtl_sim_inout(uint8_t value, uint8_t *inval)
{
FILE *fin = 0;
char ch;
uint8_t data;
debug("IO (");
 
while(1) {
fin = fopen(gdb_in, "rt");
if(!fin) {
usleep(1000);
continue;
}
ch = fgetc(fin);
fclose(fin);
if((ch != '0') && (ch != '1')) {
usleep(1000);
continue;
}
else
break;
}
data = ch == '1' ? 1 : 0;
 
debug("%x,", data);
 
cable_rtl_sim_out(value);
 
debug("%x)\n", value);
 
*inval = data;
return APP_ERR_NONE;
}
 
 
int cable_rtl_sim_opt(int c, char *str)
{
switch(c) {
case 'd':
if(!(gdb_in = malloc(strlen(str) + 12))) { /* 12 == strlen("gdb_in.dat") + 2 */
fprintf(stderr, "Unable to allocate enough memory\n");
return APP_ERR_MALLOC;
}
if(!(gdb_out = malloc(strlen(str) + 13))) { /* 13 == strlen("gdb_out.dat") + 2 */
fprintf(stderr, "Unable to allocate enough memory\n");
free(gdb_in);
return APP_ERR_MALLOC;
}
 
sprintf(gdb_in, "%s/gdb_in.dat", str);
sprintf(gdb_out, "%s/gdb_out.dat", str);
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return APP_ERR_BAD_PARAM;
}
return APP_ERR_NONE;
}
 
/*-----------------------------------------------[ VPI specific functions ]---*/
jtag_cable_t *cable_vpi_get_driver(void)
{
return &vpi_cable_driver;
}
 
 
int cable_vpi_init()
{
struct sockaddr_in addr;
struct hostent *he;
 
if((vpi_comm = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "Unable to create socket (%s)\n", strerror(errno));
return APP_ERR_CONNECT;
}
 
 
if((he = gethostbyname(vpi_server)) == NULL) {
perror("gethostbyname");
return APP_ERR_CONNECT;
}
 
addr.sin_family = AF_INET;
addr.sin_port = htons(vpi_port);
addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(addr.sin_zero, '\0', sizeof(addr.sin_zero));
 
if(connect(vpi_comm, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "Unable to connect to %s port %d (%s)\n", vpi_server, vpi_port,
strerror(errno));
return APP_ERR_CONNECT;
}
 
debug("VPI connected!");
 
return APP_ERR_NONE;
}
 
int cable_vpi_out(uint8_t value)
{
uint8_t ack;
int ret;
 
/* Send the data to the socket */
ret = send(vpi_comm, &value, 1, 0);
debug("Sent %d, ret %d\n", value, ret);
 
do {
/* Ok, read the data */
ret = recv(vpi_comm, &ack, 1, 0);
if(ret < 0) {
printf("Error during receive (%s)\n", strerror(errno));
return APP_ERR_CONNECT;
}
} while(ack != (value | 0x10));
 
cable_vpi_wait(); // finish the transaction
 
return APP_ERR_NONE;
}
 
int cable_vpi_inout(uint8_t value, uint8_t *inval)
{
uint8_t dat;
 
/* ask vpi to send us the out-bit */
dat = 0x80;
send(vpi_comm, &dat, 1, 0);
 
/* Wait and read the data */
recv(vpi_comm, &dat, 1, 0);
 
if(dat > 1)
fprintf(stderr, "Unexpected value: %i\n", dat);
 
cable_vpi_out(value);
 
*inval = dat;
 
cable_vpi_wait(); // finish the transaction
 
return APP_ERR_NONE;
}
 
void cable_vpi_wait()
{
uint8_t dat = 0x81;
 
/* Get the sim to reply when the timeout has been reached */
if(send(vpi_comm, &dat, 1, 0) < 1) {
fprintf(stderr, "Failed to send pkt in cable_vpi_wait(): %s\n", strerror(errno));
}
 
/* block, waiting for the data */
if(recv(vpi_comm, &dat, 1, 0) < 1) {
fprintf(stderr, "Recv failed in cable_vpi_wait(): %s\n", strerror(errno));
}
 
if(dat != 0xFF)
fprintf(stderr, "Warning: got wrong byte waiting for timeout: 0x%X\n", dat);
 
}
 
int cable_vpi_opt(int c, char *str)
{
switch(c) {
case 'p':
if((vpi_port = atoi(str)) == 0) {
fprintf(stderr, "Bad port value for VPI sim: %s\n", str);
return APP_ERR_BAD_PARAM;
}
break;
case 's':
vpi_server = strdup(str);
if(vpi_server == NULL) {
fprintf(stderr, "Unable to allocate enough memory for server string\n");
return APP_ERR_MALLOC;
}
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return APP_ERR_BAD_PARAM;
}
return APP_ERR_NONE;
}
/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_common.c
0,0 → 1,279
/* cable_common.c -- Interface to the low-level cable drivers
Copyright (C) 2001 Marko Mlinar, markom@opencores.org
 
Copyright (C) 2008 - 2010 Nathan Yawn, nathan.yawn@opencores.org
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 <stdio.h>
#include <string.h>
 
 
#include "cable_common.h"
#include "cable_sim.h"
 
#ifdef __SUPPORT_PARALLEL_CABLES__
#include "cable_parallel.h"
#endif
 
#ifdef __SUPPORT_USB_CABLES__
#include "cable_usbblaster.h"
#include "cable_xpc_dlc9.h"
 
#ifdef __SUPPORT_FTDI_CABLES__
#include "cable_ft245.h"
#include "cable_ft2232.h"
#endif
 
#endif
 
#include "errcodes.h"
 
#define debug(...) //fprintf(stderr, __VA_ARGS__ )
 
#define JTAG_MAX_CABLES 16
jtag_cable_t *jtag_cables[JTAG_MAX_CABLES];
 
static jtag_cable_t *jtag_cable_in_use = NULL; /* The currently selected cable */
 
 
/////////////////////////////////////////////////////////////////////////////////////
// Cable subsystem / init functions
 
void cable_setup(void)
{
int i = 0;
 
memset(jtag_cables, 0, sizeof(jtag_cables));
 
jtag_cables[i++] = cable_rtl_get_driver();
jtag_cables[i++] = cable_vpi_get_driver();
 
#ifdef __SUPPORT_PARALLEL_CABLES__
jtag_cables[i++] = cable_xpc3_get_driver();
jtag_cables[i++] = cable_bb2_get_driver();
jtag_cables[i++] = cable_xess_get_driver();
#endif
 
#ifdef __SUPPORT_USB_CABLES__
jtag_cables[i++] = cable_usbblaster_get_driver();
jtag_cables[i++] = cable_xpcusb_get_driver();
#ifdef __SUPPORT_FTDI_CABLES__
jtag_cables[i++] = cable_ftdi_get_driver();
jtag_cables[i++] = cable_ft245_get_driver();
#endif
#endif
}
 
/* Selects a cable for use */
int cable_select(const char *cable)
{
int i;
 
for(i = 0; jtag_cables[i] != NULL; i++) {
if(!strcmp(cable, jtag_cables[i]->name)) {
jtag_cable_in_use = jtag_cables[i];
return APP_ERR_NONE;
}
}
 
return APP_ERR_CABLE_INVALID;
}
 
/* Calls the init function of the cable
*/
int cable_init()
{
return jtag_cable_in_use->init_func();
}
 
/* Parses command-line options specific to the selected cable */
int cable_parse_opt(int c, char *str)
{
return jtag_cable_in_use->opt_func(c, str);
}
 
const char *cable_get_args()
{
if(jtag_cable_in_use != NULL)
return jtag_cable_in_use->opts;
else
return NULL;
}
 
/* Prints a (short) useage message for each available cable */
void cable_print_help()
{
int i;
printf("Available cables: ");
 
for(i = 0; jtag_cables[i]; i++) {
if(i)
printf(", ");
printf("%s", jtag_cables[i]->name);
}
 
printf("\n\nOptions availible for the cables:\n");
for(i = 0; jtag_cables[i]; i++) {
if(!jtag_cables[i]->help)
continue;
printf(" %s:\n %s", jtag_cables[i]->name, jtag_cables[i]->help);
}
}
 
 
/////////////////////////////////////////////////////////////////////////////////
// Cable API Functions
 
int cable_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
return jtag_cable_in_use->stream_out_func(stream, len_bits, set_last_bit);
}
 
int cable_read_write_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
return jtag_cable_in_use->stream_inout_func(outstream, instream, len_bits, set_last_bit);
}
 
int cable_write_bit(uint8_t packet) {
return jtag_cable_in_use->bit_out_func(packet);
}
 
int cable_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
return jtag_cable_in_use->bit_inout_func(packet_out, bit_in);
}
 
int cable_flush(void) {
if(jtag_cable_in_use->flush_func != NULL)
return jtag_cable_in_use->flush_func();
return APP_ERR_NONE;
}
 
 
/////////////////////////////////////////////////////////////////////////////////////
// Common functions which may or may not be used by individual drivers
 
 
/* Note that these make no assumption as to the starting state of the clock,
* and they leave the clock HIGH. But, these need to interface with other routines (like
* the byte-shift mode in the USB-Blaster), which begin by assuming that a new
* data bit is available at TDO, which only happens after a FALLING edge of TCK.
* So, routines which assume new data is available will need to start by dropping
* the clock.
*/
int cable_common_write_bit(uint8_t packet) {
uint8_t data = TRST_BIT; // TRST is active low, don't clear unless /set/ in 'packet'
int err = APP_ERR_NONE;
 
/* Write data, drop clock */
if(packet & TDO) data |= TDI_BIT;
if(packet & TMS) data |= TMS_BIT;
if(packet & TRST) data &= ~TRST_BIT;
 
err |= jtag_cable_in_use->out_func(data);
 
/* raise clock, to do write */
err |= jtag_cable_in_use->out_func(data | TCLK_BIT);
 
return err;
}
 
int cable_common_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
uint8_t data = TRST_BIT; // TRST is active low, don't clear unless /set/ in 'packet'
int err = APP_ERR_NONE;
 
/* Write data, drop clock */
if(packet_out & TDO) data |= TDI_BIT;
if(packet_out & TMS) data |= TMS_BIT;
if(packet_out & TRST) data &= ~TRST_BIT;
 
err |= jtag_cable_in_use->out_func(data); // drop the clock to make data available, set the out data
err |= jtag_cable_in_use->inout_func((data | TCLK_BIT), bit_in); // read in bit, clock high for out bit.
 
return err;
}
 
 
/* Writes bitstream via bit-bang. Can be used by any driver which does not have a high-speed transfer function.
* Transfers LSB to MSB of stream[0], then LSB to MSB of stream[1], etc.
*/
int cable_common_write_stream(uint32_t *stream, int len_bits, int set_last_bit) {
int i;
int index = 0;
int bits_this_index = 0;
uint8_t out;
int err = APP_ERR_NONE;
 
debug("writeStrm%d(", len_bits);
for(i = 0; i < len_bits - 1; i++) {
out = (stream[index] >> bits_this_index) & 1;
err |= cable_write_bit(out);
debug("%i", out);
bits_this_index++;
if(bits_this_index >= 32) {
index++;
bits_this_index = 0;
}
}
out = (stream[index] >>(len_bits - 1)) & 0x1;
if(set_last_bit) out |= TMS;
err |= cable_write_bit(out);
debug("%i)\n", out);
return err;
}
 
/* Gets bitstream via bit-bang. Can be used by any driver which does not have a high-speed transfer function.
* Transfers LSB to MSB of stream[0], then LSB to MSB of stream[1], etc.
*/
int cable_common_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) {
int i;
int index = 0;
int bits_this_index = 0;
uint8_t inval, outval;
int err = APP_ERR_NONE;
 
instream[0] = 0;
 
debug("readStrm%d(", len_bits);
for(i = 0; i < (len_bits - 1); i++) {
outval = (outstream[index] >> bits_this_index) & 0x1;
err |= cable_read_write_bit(outval, &inval);
debug("%i", inval);
instream[index] |= (inval << bits_this_index);
bits_this_index++;
if(bits_this_index >= 32) {
index++;
bits_this_index = 0;
instream[index] = 0; // It's safe to do this, because there's always at least one more bit
}
}
if (set_last_bit)
outval = ((outstream[index] >> (len_bits - 1)) & 1) | TMS;
else
outval = (outstream[index] >> (len_bits - 1)) & 1;
err |= cable_read_write_bit(outval, &inval);
debug("%i", inval);
instream[index] |= (inval << bits_this_index);
 
debug(") = 0x%lX\n", instream[0]);
return err;
}
 
 
 
/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/utilities.h
0,0 → 1,21
 
#ifndef _UTILITIES_H_
#define _UTILITIES_H_
 
#include <time.h> // for timer
#include <signal.h> // for timer
 
typedef struct
{
timer_t timer;
struct sigevent sev;
struct itimerspec wait_time;
struct itimerspec remaining_time;
} timeout_timer;
 
int create_timer(timeout_timer * timer);
int timedout(timeout_timer * timer);
 
int check_buffer_size(char **buf, int *buf_size_bytes, int requested_size_bytes);
 
#endif
/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_parallel.c
0,0 → 1,546
/* cable_parallel.c - Parallel cable drivers (XPC3 and XESS) for the Advanced JTAG Bridge
Copyright (C) 2001 Marko Mlinar, markom@opencores.org
Copyright (C) 2004 Gy�rgy Jeney, nog@sdf.lonestar.org
 
UNIX parallel port control through device file added by:
Copyright (C) 2011 Raul Fajardo, rfajardo@opencores.org
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 <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
 
#ifdef __LINUX_HOST__
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
#include <linux/parport.h>
#endif
 
#ifdef __CYGWIN_HOST__
#include <sys/io.h> // for inb(), outb()
#endif
 
#ifdef __FREEBSD_HOST__
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/dev/ppbus/ppi.h>
#include <sys/dev/ppbus/ppbconf.h>
#endif
 
#include "cable_parallel.h"
#include "errcodes.h"
 
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
#if ((_POSIX_TIMERS) && (_POSIX_CPUTIME))
#define PARALLEL_USE_PROCESS_TIMER
#endif
#endif
 
jtag_cable_t xpc3_cable_driver = {
.name = "xpc3",
.inout_func = cable_xpc3_inout,
.out_func = cable_xpc3_out,
.init_func = cable_parallel_init,
.opt_func = cable_parallel_opt,
.bit_out_func = cable_common_write_bit,
.bit_inout_func = cable_common_read_write_bit,
.stream_out_func = cable_common_write_stream,
.stream_inout_func = cable_common_read_stream,
.flush_func = NULL,
#ifdef __CYGWIN_HOST__
.opts = "p:",
.help = "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n"
#else
.opts = "d:",
.help = "-d [device file] Device file to use when communicating with the parport hardware (eg. /dev/parport0)\n"
#endif
};
 
jtag_cable_t bb2_cable_driver = {
.name = "bb2",
.inout_func = cable_bb2_inout,
.out_func = cable_bb2_out,
.init_func = cable_parallel_init,
.opt_func = cable_parallel_opt,
.bit_out_func = cable_common_write_bit,
.bit_inout_func = cable_common_read_write_bit,
.stream_out_func = cable_common_write_stream,
.stream_inout_func = cable_common_read_stream,
.flush_func = NULL,
#ifdef __CYGWIN_HOST__
.opts = "p:",
.help = "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n"
#else
.opts = "d:",
.help = "-d [device file] Device file to use when communicating with the parport hardware (eg. /dev/parport0)\n"
#endif
};
 
jtag_cable_t xess_cable_driver = {
.name = "xess",
.inout_func = cable_xess_inout,
.out_func = cable_xess_out,
.init_func = cable_parallel_init,
.opt_func = cable_parallel_opt,
.bit_out_func = cable_common_write_bit,
.bit_inout_func = cable_common_read_write_bit,
.stream_out_func = cable_common_write_stream,
.stream_inout_func = cable_common_read_stream,
.flush_func = NULL,
#ifdef __CYGWIN_HOST__
.opts = "p:",
.help = "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n"
#else
.opts = "d:",
.help = "-d [device file] Device file to use when communicating with the parport hardware (eg. /dev/parport0)\n"
#endif
};
 
 
// Common functions used by both cable types
static int cable_parallel_out(uint8_t value);
static int cable_parallel_inout(uint8_t value, uint8_t *inval);
 
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
#ifndef PARALLEL_USE_PROCESS_TIMER
struct timeval last_tv;
#endif
#endif
 
// If cygwin, we use inb / outb for parallel port access
#ifdef __CYGWIN_HOST__
 
#define LPT_READ (base+1)
#define LPT_WRITE base
 
static int base = 0x378;
 
/////////////////////////////////////////////////////////////////////////////////
/*-------------------------------------[ Parallel port specific functions ]---*/
///////////////////////////////////////////////////////////////////////////////
 
int cable_parallel_init()
{
if (ioperm(base, 3, 1)) {
fprintf(stderr, "Couldn't get the port at %x\n", base);
perror("Root privileges are required.\n");
return APP_ERR_INIT_FAILED;
}
printf("Connected to parallel port at %x\n", base);
printf("Dropping root privileges.\n");
setreuid(getuid(), getuid());
 
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
#ifdef PARALLEL_USE_PROCESS_TIMER
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
clock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts);
#else
gettimeofday(&last_tv, NULL);
#endif
#endif
 
return APP_ERR_NONE;
}
 
int cable_parallel_opt(int c, char *str)
{
switch(c) {
case 'p':
if(!sscanf(str, "%x", &base)) {
fprintf(stderr, "p parameter must have a hex number as parameter\n");
return APP_ERR_BAD_PARAM;
}
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return APP_ERR_BAD_PARAM;
}
return APP_ERR_NONE;
}
 
/*----------------------------------------------[ common helper functions ]---*/
// 'static' for internal access only
 
static int cable_parallel_out(uint8_t value)
{
outb(value, LPT_WRITE);
return APP_ERR_NONE;
}
 
static int cable_parallel_inout(uint8_t value, uint8_t *inval)
{
*inval = inb(LPT_READ);
outb(value, LPT_WRITE);
 
return APP_ERR_NONE;
}
 
// For Linux / BSD, we use open / ioctl for parallel port access,
// so that we don't need root permissions
#else // ! defined __CYGWIN_HOST__
 
#ifdef __FREEBSD_HOST__
static int PPORT_PUT_DATA = PPISDATA;
static int PPORT_GET_DATA = PPIGSTATUS;
#else
static int PPORT_PUT_DATA = PPWDATA;
static int PPORT_GET_DATA = PPRSTATUS;
#endif
 
static int fd;
static char default_dev_str[20] = "/dev/parport0";
static char *devsys = default_dev_str;
 
 
/////////////////////////////////////////////////////////////////////////////////
/*-------------------------------------[ Parallel port specific functions ]---*/
///////////////////////////////////////////////////////////////////////////////
 
int cable_parallel_init()
{
int mode = IEEE1284_MODE_COMPAT;
fd = open(devsys, O_RDWR | O_NONBLOCK);
if (fd == -1)
{
perror("Unable to open the device desriptor\n");
fprintf(stderr, "Check permission of %s (eg. 'ls -la %s').\n", devsys, devsys);
fprintf(stderr, "Your user ID can be added to %s's group to allow for unprivileged access.\n", devsys);
return APP_ERR_INIT_FAILED;
}
 
// I don't know if these ioctl() are supported under FreeBSD
#ifdef __LINUX_HOST__
if (ioctl(fd, PPCLAIM) == -1)
{
perror("Fail to claim the parallel port device interface.\n");
return APP_ERR_INIT_FAILED;
}
if (ioctl(fd, PPSETMODE, &mode) == -1)
{
perror("Setting compatibility mode on parallel port device failed.\n");
return APP_ERR_INIT_FAILED;
}
#endif
 
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
#ifdef PARALLEL_USE_PROCESS_TIMER
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
clock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts);
#else
gettimeofday(&last_tv, NULL);
#endif
#endif
 
return APP_ERR_NONE;
}
 
 
int cable_parallel_opt(int c, char *str)
{
switch(c) {
case 'd':
devsys = strdup(str);
break;
default:
fprintf(stderr, "Unknown parameter '%c'\n", c);
return APP_ERR_BAD_PARAM;
}
return APP_ERR_NONE;
}
 
/*----------------------------------------------[ common helper functions ]---*/
// 'static' for internal access only
 
static int cable_parallel_out(uint8_t value)
{
ioctl(fd, PPORT_PUT_DATA, &value);
 
return APP_ERR_NONE;
}
 
static int cable_parallel_inout(uint8_t value, uint8_t *inval)
{
ioctl(fd, PPORT_GET_DATA, inval);
ioctl(fd, PPORT_PUT_DATA, &value);
 
return APP_ERR_NONE;
}
 
#endif // !defined __CYGWIN_HOST__
 
/*-----------------------------------------[ Physical board wait function ]---*/
 
/* Multiple users have reported poor performance of parallel cables,
* which has been traced to various sleep functions sleeping much longer than
* microseconds. The same users have reported error-free functionality
* and an order of magnitude improvement in upload speed with no wait.
* Other users have reported errors when running without a wait.
* Impact apparently limits the frequency of parallel JTAG cables
* to 200 kHz, and some clones fail at higher speeds.
*/
 
 
 
#ifdef __PARALLEL_SLEEP_WAIT__
void cable_parallel_phys_wait()
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 2500;
nanosleep(&ts, NULL);
}
#else
 
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
 
#ifndef PARALLEL_USE_PROCESS_TIMER
 
/* Helper function needed if process timer isn't implemented */
/* do x-y */
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
 
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
 
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
#endif
 
 
void cable_parallel_phys_wait()
{
/* This busy wait attempts to make the frequency exactly 200kHz,
* including the processing time between ticks.
* This means a period of 5us, or half a period of 2.5us.
*/
#ifdef PARALLEL_USE_PROCESS_TIMER
struct timespec ts;
do
{
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
} while((ts.tv_sec == 0) && (ts.tv_nsec < 2500));
 
/* Doing the set after the check means that processing time
* is not added to the wait. */
ts.tv_sec = 0;
ts.tv_nsec = 0;
clock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts);
#else
struct timeval now_tv;
struct timeval results_tv;
do
{
gettimeofday(&now_tv, NULL);
timeval_subtract (&results_tv, &now_tv, &last_tv);
} while((results_tv.tv_sec == 0) && (results_tv.tv_usec < 3));
last_tv = now_tv;
#endif
}
 
#else // NO WAIT
 
void cable_parallel_phys_wait()
{
// No wait, run max speed
}
 
#endif
#endif
 
 
/*----------------------------------------------[ xpc3 specific functions ]---*/
jtag_cable_t *cable_xpc3_get_driver(void)
{
return &xpc3_cable_driver;
}
 
int cable_xpc3_out(uint8_t value)
{
uint8_t out = 0;
 
cable_parallel_phys_wait(); // Limit the max clock rate if necessary
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x02; /* D1 pin 3 */
if(value & TRST_BIT)
out |= 0x10; /* Not used */
if(value & TDI_BIT)
out |= 0x01; /* D0 pin 2 */
if(value & TMS_BIT)
out |= 0x04; /* D2 pin 4 */
 
return cable_parallel_out(out);
}
 
int cable_xpc3_inout(uint8_t value, uint8_t *inval)
{
uint8_t in;
int retval;
uint8_t out = 0;
 
cable_parallel_phys_wait(); // Limit the max clock rate if necessary
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x02; /* D1 pin 3 */
if(value & TRST_BIT)
out |= 0x10; /* Not used */
if(value & TDI_BIT)
out |= 0x01; /* D0 pin 2 */
if(value & TMS_BIT)
out |= 0x04; /* D2 pin 4 */
 
retval = cable_parallel_inout(out, &in);
 
if(in & 0x10) /* S6 pin 13 */
*inval = 1;
else
*inval = 0;
 
return retval;
}
 
 
/*----------------------------------------------[ bb2 specific functions ]---*/
jtag_cable_t *cable_bb2_get_driver(void)
{
return &bb2_cable_driver;
}
 
int cable_bb2_out(uint8_t value)
{
uint8_t out = 0;
 
cable_parallel_phys_wait(); // Limit the max clock rate if necessary
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x01; /* D0 pin 2 */
if(value & TDI_BIT)
out |= 0x40; /* D7 pin 8 */
if(value & TMS_BIT)
out |= 0x02; /* D1 pin 3 */
 
return cable_parallel_out(out);
}
 
int cable_bb2_inout(uint8_t value, uint8_t *inval)
{
uint8_t in;
int retval;
uint8_t out = 0;
 
cable_parallel_phys_wait(); // Limit the max clock rate if necessary
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x01; /* D0 pin 2 */
if(value & TDI_BIT)
out |= 0x40; /* D7 pin 8 */
if(value & TMS_BIT)
out |= 0x02; /* D1 pin 3 */
 
retval = cable_parallel_inout(out, &in);
 
if(in & 0x80) /* S7 pin 11 */
*inval = 0;
else
*inval = 1;
 
return retval;
}
 
 
/*----------------------------------------------[ xess specific functions ]---*/
jtag_cable_t *cable_xess_get_driver(void)
{
return &xess_cable_driver;
}
 
int cable_xess_out(uint8_t value)
{
uint8_t out = 0;
 
cable_parallel_phys_wait(); // Limit the max clock rate if necessary
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x04; /* D2 pin 4 */
if(value & TRST_BIT)
out |= 0x08; /* D3 pin 5 */
if(value & TDI_BIT)
out |= 0x10; /* D4 pin 6 */
if(value & TMS_BIT)
out |= 0x20; /* D3 pin 5 */
 
return cable_parallel_out(out);
}
 
int cable_xess_inout(uint8_t value, uint8_t *inval)
{
uint8_t in;
int retval;
uint8_t out = 0;
 
cable_parallel_phys_wait(); // Limit the max clock rate if necessary
 
/* First convert the bits in value byte to the ones that the cable wants */
if(value & TCLK_BIT)
out |= 0x04; /* D2 pin 4 */
if(value & TRST_BIT)
out |= 0x08; /* D3 pin 5 */
if(value & TDI_BIT)
out |= 0x10; /* D4 pin 6 */
if(value & TMS_BIT)
out |= 0x20; /* D3 pin 5 */
 
retval = cable_parallel_inout(out, &in);
 
if(in & 0x20) /* S5 pin 12*/
*inval = 1;
else
*inval = 0;
 
return retval;
}
 
 
/tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/configure.ac
0,0 → 1,347
AC_INIT([adv_jtag_bridge],[3.0.0])
AM_INIT_AUTOMAKE([-Wall -Werror])
LT_INIT
 
# Use "make V=1" in order to see the gcc command-lines during compilation.
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 
# These compilation flags must be set before AC_PROG_CC/CXX,
# or you'll get "-g -O2" by default.
CFLAGS="${CFLAGS=} -g -Wall"
 
AC_PROG_CC
AC_PROG_INSTALL
 
AC_CONFIG_MACRO_DIR([m4])
 
 
# ----------- Detect host type -----------
 
AC_CANONICAL_HOST
 
case $host in
*-cygwin) # Normally it is "i686-pc-cygwin"
echo "Host system: Cygwin detected."
MY_HOST=cygwin
CFLAGS="$CFLAGS -D__CYGWIN_HOST__"
AC_CHECK_HEADER(sys/io.h,,[AC_MSG_ERROR([Include file 'sys/io.h' not found, please install the Cygwin 'ioperm' package.])])
LIBS+=-lioperm
;;
*-linux-*)
echo "Host system: Linux detected."
MY_HOST=linux
CFLAGS="$CFLAGS -D__LINUX_HOST__"
;;
*freebsd*)
echo "Host system: FreeBSD detected."
MY_HOST=freebsd
CFLAGS="$CFLAGS -D__FREEBSD_HOST__"
;;
*)
echo "Host system: Unknown, assuming a Linux host."
MY_HOST=linux
;;
esac
 
 
# ----------- Check whether debug or release build -----------
 
AC_MSG_CHECKING(whether to generate a debug build)
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug=[[yes/no]]],
[generate a debug build with assertions and no optimization [default=no]])],
[case "${enableval}" in
yes) debug_build=true ;;
no) debug_build=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
esac],
debug_build=false)
 
if [ test x$debug_build = xtrue ]
then
AC_MSG_RESULT(yes)
CFLAGS="$CFLAGS -O0 -DDEBUG"
else
AC_MSG_RESULT(no)
# If we let the 'omit frame pointer' optimisation enabled,
# we'll have difficulty later on while trying
# to analyse crash dump files sent by the users.
CFLAGS="$CFLAGS -O2 -DNDEBUG -fno-omit-frame-pointer"
fi
 
 
# ----------- Check whether legacy debug_if -----------
 
AC_MSG_CHECKING(whether to build for the legacy debug unit)
AC_ARG_ENABLE([legacy-debug-if],
[AS_HELP_STRING([--enable-legacy-debug-if=[[yes/no]]],
[build for the legacy debug unit, as opposed to the newer Advanced Debug Unit [default=no]])],
[case "${enableval}" in
yes) legacy_debug_if=true ;;
no) legacy_debug_if=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-legacy-debug-if]) ;;
esac],
legacy_debug_if=false)
 
if [ test x$legacy_debug_if = xtrue ]
then
AC_MSG_RESULT(yes)
CFLAGS="$CFLAGS -D__LEGACY__"
else
AC_MSG_RESULT(no)
fi
 
 
# ----------- Check whether to support parallel cables -----------
 
AC_MSG_CHECKING(whether to support parallel cables)
AC_ARG_ENABLE([parallel-cables],
[AS_HELP_STRING([--enable-parallel-cables=[[yes/no]]],
[support parallel cables (requires libioperm under Cygwin) [default=yes]])],
[case "${enableval}" in
yes) support_parallel=true ;;
no) support_parallel=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-parallel-cables]) ;;
esac],
support_parallel=not_given)
 
if [ test $support_parallel = not_given ]
then
support_parallel=true
fi
 
if [ test $MY_HOST = freebsd ] && [ test $support_parallel = true ]
then
AC_MSG_ERROR([Support for parallel cables is not available under FreeBSD.])
fi
 
AM_CONDITIONAL(SUPPORT_PARALLEL_CABLES,[test x$support_parallel = xtrue])
AM_COND_IF([SUPPORT_PARALLEL_CABLES],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
 
 
# ----------- Check whether to support USB cables -----------
 
AC_MSG_CHECKING(whether to support usb cables)
AC_ARG_ENABLE([usb-cables],
[AS_HELP_STRING([--enable-usb-cables=[[yes/no]]],
[support usb cables (requires libusb) [default=yes]])],
[case "${enableval}" in
yes) support_usb=true ;;
no) support_usb=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-usb-cables]) ;;
esac],
support_usb=true)
 
AM_CONDITIONAL(SUPPORT_USB_CABLES,[test x$support_usb = xtrue])
AM_COND_IF([SUPPORT_USB_CABLES],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
 
if [ test $support_usb = true ]
then
AC_CHECK_HEADER(usb.h,,[AC_MSG_ERROR([Include file 'usb.h' not found, please install the libusb-0.1 development files (for example, that would be package 'libusb-win32' under Cygwin, and 'libusb-dev' under Ubuntu).])])
fi
 
 
# ------ At least one from (parallel, usb) must be enabled ------
 
if [ test x$support_parallel = xfalse ] && [ test x$support_usb = xfalse ]; then
AC_MSG_ERROR([Support for both parallel and usb cables is disabled.])
fi
 
# ------ Check whether the xilinx parallel cable mode is given ------
# This argument should be called --set-xxx and not --enable-xxx ,
# but autoconf identifies only the --enable and --with prefixes
# for recursive configuration option processing.
 
AC_MSG_CHECKING(xilinx parallel cable speed limit scheme)
AC_ARG_ENABLE([xpc3-limit-scheme],
[AS_HELP_STRING([--enable-xpc3-limit-scheme=[[sleep_wait/timer_wait/no_wait]]],
[limit Xilinx parallel cable speed, as some clones cannot operate as fast as we can drive them [default=no_wait]])],
[case "${enableval}" in
sleep_wait) xpc3_limit_scheme=sleep_wait ;;
timer_wait) xpc3_limit_scheme=timer_wait ;;
no_wait) xpc3_limit_scheme=no_wait ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-xpc3-limit-scheme]) ;;
esac],
xpc3_limit_scheme=not_given)
 
if [ ! test $xpc3_limit_scheme = not_given ] && [ test $support_parallel = false ]
then
AC_MSG_ERROR([Option --enable-xpc3-limit-scheme can only be supplied if support for the parallel cables has been enabled.])
fi
 
if [ test $xpc3_limit_scheme = not_given ]
then
xpc3_limit_scheme=no_wait
fi
 
AC_MSG_RESULT($xpc3_limit_scheme)
 
case "${xpc3_limit_scheme}" in
sleep_wait)
CFLAGS="$CFLAGS -D__PARALLEL_SLEEP_WAIT__"
;;
timer_wait)
CFLAGS="$CFLAGS -D__PARALLEL_TIMER_BUSY_WAIT__"
;;
no_wait)
# no_wait is the default, nothing to define
;;
*)
AC_MSG_ERROR([Internal error in --enable-xpc3-limit-scheme.])
;;
esac
 
 
# ----------- Check whether to support FTDI cables -----------
 
AC_MSG_CHECKING(whether to support ftdi cables)
AC_ARG_ENABLE([ftdi-cables],
[AS_HELP_STRING([--enable-ftdi-cables=[[yes/no]]],
[support ftdi cables (requires libftdi) [default=yes]])],
[case "${enableval}" in
yes) support_ftdi=true ;;
no) support_ftdi=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ftdi-cables]) ;;
esac],
support_ftdi=not_given)
 
if [ test $support_ftdi = not_given ]
then
support_ftdi=$support_usb
fi
 
AM_CONDITIONAL(SUPPORT_FTDI_CABLES,[test x$support_ftdi = xtrue])
AM_COND_IF([SUPPORT_FTDI_CABLES],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
 
if [ test x$support_usb = xfalse ] && [ test x$support_ftdi = xtrue ]; then
AC_MSG_ERROR([Support for FTDI cables requires support for USB cables.])
fi
 
if [ test $support_ftdi = true ]
then
AC_CHECK_HEADER(ftdi.h,,[AC_MSG_ERROR([Include file 'ftdi.h' not found, please install the libftdi development files (for example, that would be package 'libftdi-dev' under Ubuntu).])])
fi
 
 
# ----------- Check whether to enable the high-speed mode -----------
 
AC_MSG_CHECKING(whether to enable the high-speed mode)
AC_ARG_ENABLE([high-speed],
[AS_HELP_STRING([--enable-high-speed=[[yes/no]]],
[enable the high-speed mode at the cost of some error checking (requires hardware HDL support) [default=yes]])],
[case "${enableval}" in
yes) enable_high_speed=true ;;
no) enable_high_speed=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-high-speed]) ;;
esac],
enable_high_speed=true)
 
if [ test x$enable_high_speed = xtrue ]
then
AC_MSG_RESULT(yes)
CFLAGS="$CFLAGS -DADBG_OPT_HISPEED"
else
AC_MSG_RESULT(no)
fi
 
 
# ----------- Check whether to enable the JSP server -----------
 
AC_MSG_CHECKING(whether to enable the JSP server)
AC_ARG_ENABLE([jsp-server],
[AS_HELP_STRING([--enable-jsp-server=[[yes/no]]],
[enable the JSP server (requires hardware HDL support) [default=yes]])],
[case "${enableval}" in
yes) enable_jsp_server=true ;;
no) enable_jsp_server=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-jsp-server]) ;;
esac],
enable_jsp_server=not_given)
 
if [ test x$legacy_debug_if = xtrue ] && [ test x$enable_jsp_server = xtrue ]
then
AC_MSG_ERROR([Option --enable-jsp-server cannot be true when using the legacy_debug_if hardware.])
fi
 
if [ test $enable_jsp_server = not_given ]
then
if [ test x$legacy_debug_if = xtrue ]
then
enable_jsp_server=false
else
enable_jsp_server=true
fi
fi
 
AM_CONDITIONAL(INCLUDE_JSP_SERVER,[test x$enable_jsp_server = xtrue])
AM_COND_IF([INCLUDE_JSP_SERVER],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
 
 
# ----------- Check whether to enable the JSP multi device support -----------
 
AC_MSG_CHECKING(whether to enable the JSP multi device chain support)
AC_ARG_ENABLE([jsp-multi-device-chain],
[AS_HELP_STRING([--enable-jsp-multi-device-chain=[[yes/no]]],
[enable the JTAG Serial Port (JSP) multi device chain support (slower, requires hardware HDL support) [default=yes]])],
[case "${enableval}" in
yes) enable_jsp_multi_device_chain=true ;;
no) enable_jsp_multi_device_chain=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-jsp-multi-device-chain]) ;;
esac],
enable_jsp_multi_device_chain=not_given)
 
if [ ! test $enable_jsp_multi_device_chain = not_given ] && [ test $enable_jsp_server = false ]
then
AC_MSG_ERROR([Option --enable-jsp-multi-device-chain can only be supplied if the JSP server has been enabled.])
fi
 
if [ test $enable_jsp_multi_device_chain = not_given ]
then
enable_jsp_multi_device_chain=true
fi
 
if [ test x$enable_jsp_multi_device_chain = xtrue ]
then
AC_MSG_RESULT(yes)
CFLAGS="$CFLAGS -DENABLE_JSP_MULTI"
else
AC_MSG_RESULT(no)
fi
 
 
# ----------- Check whether to optimize the JSP for parallel or USB -----------
 
AC_MSG_CHECKING(whether to optimize the JSP for USB)
AC_ARG_ENABLE([jsp-optimize-for-usb],
[AS_HELP_STRING([--enable-jsp-optimize-for-usb=[[yes/no]]],
[optimizes the JTAG Serial Port (JSP) for USB cables (as opposed to optimizing for parallel cables) [default=yes]])],
[case "${enableval}" in
yes) enable_jsp_optimize_for_usb=true ;;
no) enable_jsp_optimize_for_usb=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-jsp-optimize-for-usb]) ;;
esac],
enable_jsp_optimize_for_usb=not_given)
 
 
if [ ! test $enable_jsp_optimize_for_usb = not_given ] && [ test $enable_jsp_server = false ]
then
AC_MSG_ERROR([Option --enable-jsp-optimize-for-usb can only be supplied if the JSP server has been enabled.])
fi
 
if [ test $enable_jsp_optimize_for_usb = not_given ]
then
enable_jsp_optimize_for_usb=true
fi
 
if [ test x$enable_jsp_optimize_for_usb = xtrue ]
then
AC_MSG_RESULT(yes)
CFLAGS="$CFLAGS -DOPTIMIZE_JSP_FOR_USB"
else
AC_MSG_RESULT(no)
fi
 
# ----------------------------------------
 
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/configure.ac Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hwp_server.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hwp_server.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hwp_server.c (revision 66) @@ -0,0 +1,1059 @@ +/* hwp_server.c -- Server for hardware watchpoint handling + Copyright(C) 2010 Nathan Yawn + + This file is part the advanced debug unit / bridge. GDB does not + have support for the OR1200's advanced hardware watchpoints. This + acts as a server for a client program that can read and set them. + + 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 "spr-defs.h" +#include "dbg_api.h" +#include "hardware_monitor.h" +#include "errcodes.h" + + +#define debug(...) // fprintf(stderr, __VA_ARGS__ ) + +#define HWP_BUF_MAX 256 + +/*! Data structure for RSP buffers. Can't be null terminated, since it may + include zero bytes */ +struct rsp_buf +{ + char data[HWP_BUF_MAX]; + int len; +}; + +int hwp_server_fd = -1; +int hwp_client_fd = -1; +int hwp_pipe_fds[2]; + +/* Some convenient net address info to have around */ +char hwp_ipstr[INET6_ADDRSTRLEN]; +char *hwp_ipver; +int hwp_portnum; +char hwp_hostname[256]; + +/* Other local data */ +int hwp_server_running = 0; +int hwp_target_is_running = 0; +int use_cached_dmr2 = 0; +uint32_t cached_dmr2 = 0; + +/* To track which watchpoints are in use by an external program, + * so that the RSP server can have the unused ones for GDB + */ +#define HWP_MAX_WP 8 +unsigned char hwp_in_use[HWP_MAX_WP]; + +/*! String to map hex digits to chars */ +static const char hexchars[]="0123456789abcdef"; + +pthread_t hwp_server_thread; +void *hwp_server(void *arg); + +void hwp_server_close(void); +void hwp_client_close(void); +void hwp_client_request(void); + +struct rsp_buf *hwp_get_packet(void); +void put_hwp_rsp_char(int fd, char c); +int get_hwp_rsp_char(int fd); +void hwp_read_reg(struct rsp_buf *buf); +void hwp_write_reg (struct rsp_buf *buf); +void hwp_put_str_packet (int fd, const char *str); +void hwp_put_packet (int fd, struct rsp_buf *buf); +unsigned long int hwp_hex2reg (char *buf); +void hwp_reg2hex (unsigned long int val, char *buf); +int hwp_hex(int c); +void hwp_report_run(void); +void hwp_report_stop(void); +void hwp_set_in_use(unsigned int wp, unsigned char inuse); + +/*----------------------------------------------------------*/ +/* Public API */ +/*----------------------------------------------------------*/ + +int hwp_init(int portNum) +{ + int status; + struct addrinfo hints; + struct addrinfo *servinfo; // will point to the results of getaddrinfo + int optval; /* Socket options */ + char portnum[6]; /* portNum as a string */ + void *addr; + int i, errcode; + uint32_t regaddr, tmp; + + debug("HWP Server initializing\n"); + + /* First thing's first: Check if there are any HWP. + * Read all DCR, mark which are present.*/ + status = 0; + for(i = 0; i < HWP_MAX_WP; i++) + { + regaddr = SPR_DCR(i); + errcode = dbg_cpu0_read(regaddr, &tmp); + if(errcode != APP_ERR_NONE) + { + fprintf(stderr, "ERROR reading DCR %i at startup! %s\n", i, get_err_string(errcode)); + hwp_set_in_use(i, 1); + } + else + { + if(tmp & 0x1) /* HWP present */ + { + hwp_set_in_use(i, 0); + status++; + } + else /* HWP not implemented */ + { + hwp_set_in_use(i, 1); + } + } + debug("HWP %i is %s\n", i, hwp_in_use[i] ? "absent":"present"); + } + + if(status <= 0) + { + fprintf(stderr, "No watchpoint hardware found, HWP server not starting\n"); + return 0; + } + else + { + fprintf(stderr, "HWP server initializing with %i watchpoints available\n", status); + + /* We have watchpoint hardware. Initialize the server. */ + hwp_server_fd = -1; + hwp_client_fd = -1; + hwp_portnum = portNum; + + memset(portnum, '\0', sizeof(portnum)); + snprintf(portnum, 5, "%i", portNum); + + /* Get the address info for the local host */ + memset(&hints, 0, sizeof hints); // make sure the struct is empty + hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; // TCP stream sockets + hints.ai_flags = AI_PASSIVE; // fill in my IP for me + + if ((status = getaddrinfo(NULL, portnum, &hints, &servinfo)) != 0) { + fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); + return 0; + } + + + /* *** TODO: Select the appropriate servinfo in the linked list + * For now, we just use the first entry in servinfo. + struct addrinfo *servinfo, *p; + for(p = servinfo;p != NULL; p = p->ai_next) { + if (p->ai_family == AF_INET) { // IPv4 + } else { // IPv6 + } + } + */ + + + /* Save the IP address, for convenience (different fields in IPv4 and IPv6) */ + if (servinfo->ai_family == AF_INET) { // IPv4 + struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr; + addr = &(ipv4->sin_addr); + hwp_ipver = "IPv4"; + } else { // IPv6 + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr; + addr = &(ipv6->sin6_addr); + hwp_ipver = "IPv6"; + } + + /* convert the IP to a string */ + inet_ntop(servinfo->ai_family, addr, hwp_ipstr, sizeof(hwp_ipstr)); + + /* Find out what our name is, save for convenience */ + if (gethostname (hwp_hostname, sizeof(hwp_hostname)) < 0) + { + fprintf (stderr, "Warning: Unable to get hostname for HWP server: %s\n", strerror(errno)); + hwp_hostname[0] = '\0'; /* This is not a fatal error. */ + } + + /* Create the socket */ + hwp_server_fd = socket (servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); + if (hwp_server_fd < 0) + { + fprintf (stderr, "Error: HWP could not create server socket: %s\n", strerror(errno)); + return 0; + } + + /* Set this socket to reuse its address. */ + optval = 1; + if (setsockopt(hwp_server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) == -1) + { + fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: %s\n", hwp_server_fd, strerror(errno)); + hwp_server_close(); + return 0; + } + + /* Bind the socket to the local address */ + if (bind (hwp_server_fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) + { + fprintf (stderr, "Error: Unable to bind HWP server socket %d to port %d: %s\n", hwp_server_fd, portNum, strerror(errno)); + hwp_server_close(); + return 0; + } + + /* Set us up as a server, with a maximum backlog of 1 connection */ + if (listen (hwp_server_fd, 1) < 0) + { + fprintf (stderr, "Warning: Unable to set HWP backlog on server socket %d to %d: %s\n", hwp_server_fd, 1, strerror(errno)); + hwp_server_close(); + return 0; + } + + fprintf(stderr, "HWP server listening on host %s (%s), port %i, address family %s\n", + hwp_hostname, hwp_ipstr, hwp_portnum, hwp_ipver); + + /* Register for stall/unstall events from the target monitor thread. Also creates pipe + * for sending stall/unstall command to the target monitor, unused by us. */ + if(0 > register_with_monitor_thread(hwp_pipe_fds)) { // pipe_fds[0] is for writing to monitor, [1] is to read from it + fprintf(stderr, "HWP server failed to register with monitor thread, exiting"); + hwp_server_close(); + return 0; + } + } + + return 1; +} + + +int hwp_server_start(void) +{ + + hwp_server_running = 1; + + debug("Starting HWP server\n"); + + // Create the HWP server thread + if(pthread_create(&hwp_server_thread, NULL, hwp_server, NULL)) + { + fprintf(stderr, "Failed to create HWP server thread!\n"); + return 0; + } + + return 1; +} + + +int hwp_server_stop(void) +{ + /*** NOTE: Since we currently don't use select() in front of the accept() + *** in the server thread, this won't actually work unless/until a client + *** is connected. Otherwise, the server thread will be blocked on the + *** accept() (though closing the server socket may break it out.) + ***/ + + hwp_server_running = 0; + hwp_server_close(); + return 1; +} + +/*--------------------------------------------------------------------*/ +/* Main server thread */ +/*--------------------------------------------------------------------*/ + + +void *hwp_server(void *arg) +{ + struct sockaddr_storage their_addr; + struct timeval *tvp; + fd_set readset; + socklen_t addr_size; + int nfds, flags; + int ret; + char cmd; + + fprintf(stderr, "HWP server thread running!\n"); + + while(hwp_server_running) + { + /* Listen for an incoming connection */ + addr_size = sizeof their_addr; + hwp_client_fd = accept(hwp_server_fd, (struct sockaddr *)&their_addr, &addr_size); + + if(hwp_client_fd == -1) + { + perror("Error in accept() in HWP server thread"); + } + else + { + debug("HWP server got connection!\n"); + + /* Do new client init stuff here */ + use_cached_dmr2 = 0; + + /* New client should be non-blocking. */ + flags = fcntl (hwp_client_fd, F_GETFL); + if (flags < 0) + { + fprintf (stderr, "Warning: Unable to get flags for HWP client socket %d: %s\n", hwp_client_fd, strerror(errno)); + // Not really fatal. + } + else { + flags |= O_NONBLOCK; + if (fcntl (hwp_client_fd, F_SETFL, flags) < 0) + { + fprintf (stderr, "Warning: Unable to set flags for HWP client socket %d to 0x%08x: %s\n", hwp_client_fd, flags, strerror(errno)); + // Also not really fatal. + } + } + } + + /* Send/receive data on the new connection for as long as it's valid */ + while(hwp_server_running && (hwp_client_fd != -1)) + { + /* if target not running, block on data from client or monitor thread */ + /* if target running, just poll (don't block) */ + // if(hwp_target_is_running) { + // tv.tv_sec = 0; // Set this each loop, it may be changed by the select() call + // tv.tv_usec = 0; // instant timeout when polling + // tvp = &tv; + //} else { + tvp = NULL; + //} + + FD_ZERO(&readset); + FD_SET(hwp_client_fd, &readset); + FD_SET(hwp_pipe_fds[1], &readset); + nfds = hwp_client_fd; + if(hwp_pipe_fds[1] > nfds) nfds = hwp_pipe_fds[1]; + nfds++; + + ret = select(nfds, &readset, NULL, NULL, tvp); + + if(ret == -1) // error + { + perror("select()"); + } + else if(ret != 0) // fd ready (ret == 0 on timeout) + { + debug("HWP thread got data\n"); + + if(FD_ISSET(hwp_pipe_fds[1], &readset)) + { + ret = read(hwp_pipe_fds[1], &cmd, 1); + debug("HWP server got monitor status \'%c\' (0x%X)\n", cmd, cmd); + if(ret == 1) + { + if(cmd == 'H') + { + // Save state so we can tell client on request + hwp_target_is_running = 0; + } + else if(cmd == 'R') + { + // Save state so we can tell client on request + hwp_target_is_running = 1; + use_cached_dmr2 = 0; + } + else + { + fprintf(stderr, "HWP server got unknown monitor status \'%c\' (0x%X)\n", cmd, cmd); + } + } + else + { + fprintf(stderr, "HWP server failed to read from ready monitor pipe!\n"); + } + } // if FD_ISSET(hwp_pipe_fds[1]) + + if(FD_ISSET(hwp_client_fd, &readset)) + { + hwp_client_request(); + } + } // else if (ret != 0) + + } /* while client connection is valid */ + + } /* while(hwp_server_running) */ + + hwp_client_close(); + + return arg; // unused +} + +/*--------------------------------------------------------------------*/ +/* Helper functions */ +/*--------------------------------------------------------------------*/ + +void hwp_server_close(void) +{ + if (hwp_server_fd != -1) + { + close(hwp_server_fd); + hwp_server_fd = -1; + } +} + + +void hwp_client_close(void) +{ + if (hwp_client_fd != -1) + { + close (hwp_client_fd); + hwp_client_fd = -1; + } +} /* hwp_client_close () */ + + +void hwp_client_request(void) +{ + struct rsp_buf *buf = hwp_get_packet (); /* Message sent to us */ + + // Null packet means we hit EOF or the link was closed for some other + // reason. Close the client and return + if (NULL == buf) + { + hwp_client_close (); + return; + } + + debug("HWP Packet received %s: %d chars\n", buf->data, buf->len ); + + switch (buf->data[0]) + { + + case '?': + // Different meaning than RSP: in RSP, this always returns an 'S' packet. + // here, we want to know running / stopped. + if(hwp_target_is_running) { + hwp_report_run(); + } else { + hwp_report_stop(); + } + return; + + + /* + case 'g': + rsp_read_all_regs (); + return; + + case 'G': + rsp_write_all_regs (buf); + return; + */ + + + case 'p': + /* Read a register */ + hwp_read_reg(buf); + return; + + case 'P': + /* Write a register */ + hwp_write_reg(buf); + return; + + /* + case 'q': + // Any one of a number of query packets + rsp_query (buf); + return; + + case 'Q': + // Any one of a number of set packets + rsp_set (buf); + return; + */ + + default: + /* Unknown commands are ignored */ + fprintf (stderr, "Warning: Unknown HWP request %s\n", buf->data); + return; + } +} /* hwp_client_request () */ + + +/*---------------------------------------------------------------------------*/ +/*!Get a packet from the GDB client + + Modeled on the stub version supplied with GDB. The data is in a static + buffer. The data should be copied elsewhere if it is to be preserved across + a subsequent call to get_packet(). + + Unlike the reference implementation, we don't deal with sequence + numbers. GDB has never used them, and this implementation is only intended + for use with GDB 6.8 or later. Sequence numbers were removed from the RSP + standard at GDB 5.0. + + @return A pointer to the static buffer containing the data */ +/*---------------------------------------------------------------------------*/ +struct rsp_buf *hwp_get_packet(void) +{ + static struct rsp_buf buf; /* Survives the return */ + + /* Keep getting packets, until one is found with a valid checksum */ + while (1) + { + unsigned char checksum; /* The checksum we have computed */ + int count; /* Index into the buffer */ + int ch; /* Current character */ + + /* Wait around for the start character ('$'). Ignore all other + characters */ + ch = get_hwp_rsp_char(hwp_client_fd); + while (ch != '$') + { + if (-1 == ch) + { + return NULL; /* Connection failed */ + } + + ch = get_hwp_rsp_char(hwp_client_fd); + } + + /* Read until a '#' or end of buffer is found */ + checksum = 0; + count = 0; + while (count < HWP_BUF_MAX - 1) + { + ch = get_hwp_rsp_char(hwp_client_fd); + + /* Check for connection failure */ + if (-1 == ch) + { + return NULL; + } + + /* If we hit a start of line char begin all over again */ + if ('$' == ch) + { + checksum = 0; + count = 0; + + continue; + } + + /* Break out if we get the end of line char */ + if ('#' == ch) + { + break; + } + + /* Update the checksum and add the char to the buffer */ + + checksum = checksum + (unsigned char)ch; + buf.data[count] = (char)ch; + count = count + 1; + } + + /* Mark the end of the buffer with EOS - it's convenient for non-binary + data to be valid strings. */ + buf.data[count] = 0; + buf.len = count; + + /* If we have a valid end of packet char, validate the checksum */ + if ('#' == ch) + { + unsigned char xmitcsum; /* The checksum in the packet */ + + ch = get_hwp_rsp_char(hwp_client_fd); + if (-1 == ch) + { + return NULL; /* Connection failed */ + } + xmitcsum = hwp_hex(ch) << 4; + + ch = get_hwp_rsp_char(hwp_client_fd); + if (-1 == ch) + { + return NULL; /* Connection failed */ + } + + xmitcsum += hwp_hex(ch); + + /* If the checksums don't match print a warning, and put the + negative ack back to the client. Otherwise put a positive ack. */ + if (checksum != xmitcsum) + { + fprintf (stderr, "Warning: Bad HWP RSP checksum: Computed " + "0x%02x, received 0x%02x\n", checksum, xmitcsum); + + put_hwp_rsp_char (hwp_client_fd, '-'); /* Failed checksum */ + } + else + { + put_hwp_rsp_char (hwp_client_fd, '+'); /* successful transfer */ + break; + } + } + else + { + fprintf (stderr, "Warning: HWP RSP packet overran buffer\n"); + } + } + + return &buf; /* Success */ + +} /* hwp_get_packet () */ + + +/*---------------------------------------------------------------------------*/ +/*Single character get/set routines */ +/*---------------------------------------------------------------------------*/ +void put_hwp_rsp_char(int fd, char c) +{ + if (-1 == fd) + { + fprintf (stderr, "Warning: Attempt to write '%c' to unopened HWP RSP client: Ignored\n", c); + return; + } + + /* Write until successful (we retry after interrupts) or catastrophic + failure. */ + while (1) + { + switch (write(fd, &c, sizeof (c))) + { + case -1: + /* Error: only allow interrupts or would block */ + if ((EAGAIN != errno) && (EINTR != errno)) + { + fprintf (stderr, "Warning: Failed to write to HWP RSP client: Closing client connection: %s\n", + strerror (errno)); + hwp_client_close(); + return; + } + + break; + + case 0: + break; /* Nothing written! Try again */ + + default: + return; /* Success, we can return */ + } + } +} /* put_hwp_rsp_char() */ + + + +int get_hwp_rsp_char(int fd) +{ + unsigned char c; /* The character read */ + + if (-1 == fd) + { + fprintf (stderr, "Warning: Attempt to read from unopened HWP RSP client: Ignored\n"); + return -1; + } + + /* Read until successful (we retry after interrupts) or catastrophic + failure. */ + while (1) + { + switch (read (fd, &c, sizeof (c))) + { + case -1: + /* Error: only allow interrupts or would block */ + if ((EAGAIN != errno) && (EINTR != errno)) + { + fprintf (stderr, "Warning: Failed to read from HWP RSP client: Closing client connection: %s\n", + strerror (errno)); + hwp_client_close(); + return -1; + } + + break; + + case 0: + // EOF + hwp_client_close(); + return -1; + + default: + return c & 0xff; /* Success, we can return (no sign extend!) */ + } + } +} /* get_hwp_rsp_char() */ + + +/*---------------------------------------------------------------------------*/ +/*!Read a single register + + The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC + (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a + sequence of bytes in target endian order. + + Each byte is packed as a pair of hex digits. + + @param[in] buf The original packet request. Reused for the reply. */ +/*---------------------------------------------------------------------------*/ +void hwp_read_reg(struct rsp_buf *buf) +{ + unsigned int regnum; + uint32_t tmp; + unsigned int errcode = APP_ERR_NONE; + + /* Break out the fields from the data */ + if (1 != sscanf (buf->data, "p%x", ®num)) + { + fprintf (stderr, "Warning: Failed to recognize HWP RSP read register command: \'%s\'\n", buf->data); + hwp_put_str_packet (hwp_client_fd, "E01"); + return; + } + + if((regnum == SPR_DMR2) && use_cached_dmr2) // Should we use the cached DMR2 value? + { + tmp = cached_dmr2; + errcode = APP_ERR_NONE; + fprintf(stderr, "Using cached DMR2 value 0x%X\n", tmp); + } + else + { + /* Get the relevant register. We assume the client is not GDB, + * and that no register number translation is needed. + */ + errcode = dbg_cpu0_read(regnum, &tmp); + } + + if(errcode == APP_ERR_NONE) { + hwp_reg2hex(tmp, buf->data); + buf->len = strlen (buf->data); + debug("Read reg 0x%x, got %s (0x%X), len %i\n", regnum, buf->data, tmp, buf->len); + hwp_put_packet (hwp_client_fd, buf); + } + else { + fprintf(stderr, "Error reading HWP register: %s\n", get_err_string(errcode)); + hwp_put_str_packet(hwp_client_fd, "E01"); + } + +} /* hwp_read_reg() */ + + +/*---------------------------------------------------------------------------*/ +/*!Write a single register + + The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC + (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a + sequence of bytes in target endian order. + + Each byte is packed as a pair of hex digits. + + @param[in] buf The original packet request. */ +/*---------------------------------------------------------------------------*/ +void hwp_write_reg (struct rsp_buf *buf) +{ + unsigned int regnum; + char valstr[9]; /* Allow for EOS on the string */ + unsigned int errcode = APP_ERR_NONE; + int dcridx; + uint32_t val, cc, ct; + + /* Break out the fields from the data */ + if (2 != sscanf (buf->data, "P%x=%8s", ®num, valstr)) + { + fprintf (stderr, "Warning: Failed to recognize RSP write register command: %s\n", buf->data); + hwp_put_str_packet (hwp_client_fd, "E01"); + return; + } + + /* Set the relevant register. We assume that the client is not + * GDB, and no register number translation is needed. */ + val = hwp_hex2reg(valstr); + errcode = dbg_cpu0_write(regnum, val); + + if(errcode == APP_ERR_NONE) { + debug("Wrote reg 0x%X with val 0x%X (%s)\n", regnum, hwp_hex2reg(valstr), valstr); + hwp_put_str_packet (hwp_client_fd, "OK"); + } + else { + fprintf(stderr, "Error writing register: %s\n", get_err_string(errcode)); + hwp_put_str_packet(hwp_client_fd, "E01"); + } + + /* A bit of hackery: Determine if this write enables a comparison on a DCR. + * If so, then we mark this HWP as in use, so that GDB/RSP cannot use it. + * Note that there's no point making the HWP client check which watchpoints are in + * use - GDB only sets HWP as it is starting the CPU, and clears them + * immediately after a stop. So as far as the HWP client would see, GDB/RSP + * never uses any watchpoints. + */ + + if((regnum >= SPR_DCR(0)) && (regnum <= SPR_DCR(7))) + { + dcridx = regnum - SPR_DCR(0); + /* If the 'compare condition' (cc) or 'compare to' (ct) are 0, + * then matching is disabled and we can mark this HWP not in use. + */ + cc = val & 0x0E; + ct = val & 0xE0; + if ((cc == 0) || (ct == 0)) + hwp_set_in_use(dcridx, 0); + else + hwp_set_in_use(dcridx, 1); + } + +} /* hwp_write_reg() */ + +/*---------------------------------------------------------------------------*/ +/*!Convenience to put a constant string packet + + param[in] str The text of the packet */ +/*---------------------------------------------------------------------------*/ +void hwp_put_str_packet (int fd, const char *str) +{ + struct rsp_buf buf; + int len = strlen (str); + + /* Construct the packet to send, so long as string is not too big, + otherwise truncate. Add EOS at the end for convenient debug printout */ + + if (len >= HWP_BUF_MAX) + { + fprintf (stderr, "Warning: String %s too large for HWP RSP packet: truncated\n", str); + len = HWP_BUF_MAX - 1; + } + + strncpy (buf.data, str, len); + buf.data[len] = 0; + buf.len = len; + + hwp_put_packet (fd, &buf); + +} /* hwp_put_str_packet () */ + +/*---------------------------------------------------------------------------*/ +/*!Send a packet to the GDB client + + Modeled on the stub version supplied with GDB. Put out the data preceded by + a '$', followed by a '#' and a one byte checksum. '$', '#', '*' and '}' are + escaped by preceding them with '}' and then XORing the character with + 0x20. + + @param[in] buf The data to send */ +/*---------------------------------------------------------------------------*/ +void hwp_put_packet (int fd, struct rsp_buf *buf) +{ + int ch; /* Ack char */ + + /* Construct $#. Repeat until the GDB client + acknowledges satisfactory receipt. */ + do + { + unsigned char checksum = 0; /* Computed checksum */ + int count = 0; /* Index into the buffer */ + + debug("Putting %s\n", buf->data); + + put_hwp_rsp_char (fd, '$'); /* Start char */ + + /* Body of the packet */ + for (count = 0; count < buf->len; count++) + { + unsigned char ch = buf->data[count]; + + /* Check for escaped chars */ + if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch)) + { + ch ^= 0x20; + checksum += (unsigned char)'}'; + put_hwp_rsp_char (fd, '}'); + } + + checksum += ch; + put_hwp_rsp_char (fd, ch); + } + + put_hwp_rsp_char (fd, '#'); /* End char */ + + /* Computed checksum */ + put_hwp_rsp_char (fd, hexchars[checksum >> 4]); + put_hwp_rsp_char (fd, hexchars[checksum % 16]); + + /* Check for ack or connection failure */ + ch = get_hwp_rsp_char (fd); + if (-1 == ch) + { + return; /* Fail the put silently. */ + } + } + while ('+' != ch); + +} /* hwp_put_packet() */ + + +unsigned long int hwp_hex2reg (char *buf) +{ + int n; /* Counter for digits */ + unsigned long int val = 0; /* The result */ + + for (n = 0; n < 8; n++) + { +#ifdef WORDSBIGENDIAN + int nyb_shift = n * 4; +#else + int nyb_shift = 28 - (n * 4); +#endif + val |= hwp_hex(buf[n]) << nyb_shift; + } + + return val; + +} /* hwp_hex2reg() */ + + +void hwp_reg2hex(unsigned long int val, char *buf) +{ + int n; /* Counter for digits */ + + for (n = 0; n < 8; n++) + { +#ifdef WORDSBIGENDIAN + int nyb_shift = n * 4; +#else + int nyb_shift = 28 - (n * 4); +#endif + buf[n] = hexchars[(val >> nyb_shift) & 0xf]; + } + + buf[8] = 0; /* Useful to terminate as string */ + +} /* hwp_reg2hex() */ + + +int hwp_hex(int c) +{ + return ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 : + ((c >= '0') && (c <= '9')) ? c - '0' : + ((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1; + +} /* hwp_hex() */ + +/* ---------------------------------------------------------------------- */ +/* Functions to report stop and start to the client. */ +/* Not strictly correct RSP protocol. */ +/*------------------------------------------------------------------------*/ + +void hwp_report_stop(void) +{ + struct rsp_buf buf; + uint32_t ppcval; + + // Read the PPC + dbg_cpu0_read(SPR_PPC, &ppcval); + + debug("HWP reporting stop, PPC = 0x%X\n", ppcval); + + /* Construct a signal received packet */ + buf.data[0] = 'S'; + buf.data[1] = hexchars[ppcval >> 4]; + buf.data[2] = hexchars[ppcval % 16]; + buf.data[3] = 0; + buf.len = strlen (buf.data); + + hwp_put_packet(hwp_client_fd, &buf); + +} /* rsp_report_exception () */ + + +void hwp_report_run(void) +{ + struct rsp_buf buf; + + // Construct a 'run' packet. This is completely non-standard, non-RSP, made up. + buf.data[0] = 'R'; + buf.data[1] = 'U'; + buf.data[2] = 'N'; + buf.data[3] = 0; + buf.len = strlen (buf.data); + + hwp_put_packet(hwp_client_fd, &buf); + +} /* hwp_report_run() */ + +/* Used by the HWP server to indicate which HWP are + * in long-term use by an external client + */ +void hwp_set_in_use(unsigned int wp, unsigned char inuse) +{ + if(wp < HWP_MAX_WP) + { + hwp_in_use[wp] = inuse; + debug("HWP setting wp %i status to %i\n", wp, inuse); + } + else + fprintf(stderr, "ERROR! value %i out of range when setting HWP in use!\n", wp); +} + +/* Called by the RSP server to get any one unused HWP. + * This will only be called immediately before a 'step' + * or 'continue,' and the HWP will be disabled as soon + * as the CPU returns control to the RSP server. + * Returns -1 if no HWP available. + */ +int hwp_get_available_watchpoint(void) +{ + int i; + int ret = -1; + + for(i = 0; i < HWP_MAX_WP; i++) + { + if(hwp_in_use[i] == 0) + { + ret = i; + hwp_in_use[i] = 1; + + break; + } + } + debug("HWP granting wp %i to GDB/RSP\n", ret); + return ret; +} + +/* Called by the RSP server to indicate it is no longer + * using a watchpoint previously granted by + * hwp_get_available_watchpoint() + */ +void hwp_return_watchpoint(int wp) +{ + if(wp >= HWP_MAX_WP) + { + fprintf(stderr, "ERROR! WP value %i out of range in hwp_return_watchpoint()!\n", wp); + } + else + { + if(hwp_in_use[wp] != 0) + { + hwp_in_use[wp] = 0; + debug("HWP got wp %i back from GDB/RSP\n", wp); + } + else + fprintf(stderr, "ERROR! hwp_return_watchpoint() returning wp %i, not in use!\n", wp); + } +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/adv_jtag_bridge.pdf =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/adv_jtag_bridge.pdf (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/adv_jtag_bridge.pdf (revision 66) @@ -0,0 +1,2648 @@ +%PDF-1.4 +%äüöß +2 0 obj +<> +stream +xœeQMOÃ0 ½çWøŒÔ`糑¢H-]‘¸ +*q˜8ñuaH첿P›"9¶Ÿã÷ì &8ª/@èÝ@†mLb¯ðxŸ”sxWã¢(EÀÏË \ÏÆÁò¶ËHÅf4¥£Œ]½}1CucaÓcªÁÀ-ÝêF©Ä^žHâæ˜p#Ðܪ [÷ò´Ü©Í¢¶gâ\HÚ€Aû&Î…U\ÇR ¿å˱㹥íEWŠôµÀ_´Ö)…•{!ðfþÀcâáC^á ÂGždâ`ÃÞ,ÔSé‚Ìa2QËñX攕*/Á)×ó^¡Npü'éþVñ·‘v°rQÛ|ÀÃåb,2lMÔñL7Ù*—÷Œ9‘å9˜Kçøã(P¤¾Þ‰YÛ_©[øw™yf +endstream +endobj + +3 0 obj +297 +endobj + +5 0 obj +<> +stream +xœ•VKËãF¼ûWè°3Ý£I ,?¹mbÈaÉ)É.„l {Ù¿ŸêÇH²-_‚AÖc¦»ºª¦gšo»šÐìn31®Ý ׯ4¿|×ü­å÷õónºíR>ôMä×ÛïÍ÷Wnˆ›Û§#Ma +§0„+ +Ä¡ +±ìÓ2i¢ þ3 +ø]9èݱÄ8Ò1ä@øЈ<†¶ì;N!˨ЕÁ^…1ôeA©üzûqw¹í>l!äÝB¦²GȳĽR+ ix~•¨#)‚¼úŽ× +JaJ fÀקɦ„‹ŒP&JîFêCf^ÇÑÁÎQ⨳æp˜o˜å·çŠìvë±8!¼å3ÆîÔ¤88Ú4 +–T™£¤p*æ :Àa,œ*Äò30¤y†æ¬‰EFîC¯d_mÄù¥X‰ÆZˆPn¾–·ë0íÁ€Q3¿]¹› ¶œ¥Ö¡zs÷¹Îr:åAd,AŽp`ªÄ”þ…mŽD”…*%×=3 Ñ´Â0ó[ö½vªt߇D€ªI:w-sëôœšàA– +¤´Ìç’GQÇÚbââãlˆÍ›Ü%3Þ_^êÙÒ!mÈóžž¹Eǹ×Ó YΕ?3(™€ñ +'nƒæµ©MuΫýòT“ÜÏá*U“¯nô(4´YÓH,CɽÅdA—XuñÖ°ÑÙ1þÿ˜„@¹¤~ŒmIé¾½<,ÅÕâ]¬²íçWÚ¡«ç +)ÞÓ.…C|\‹Õ¢ð¢J`Q7˜aK¶RõsônTíü,þiuûº4MC"·(S¢‰~蟖ʴô„K¡'Ê v;Ûlðr´WN”jwÁ¸Zܺd‡µl~~âÿ +Ù9mÛ|h7I'©.ؾäõaO› ÓBn^' +OÍ:äo_v½öÛ]æŸ~Øá@ÐýK““ÝýÕüü¬7Ñ&6#Ôö)Ù™^¸¥åíÙïø+f´”­ÞPþ²²ñz[œÖ2¯[ÛÜié¯Z"½ìˆë]^{ë›ïž|—œá%4»ÂF õºŒ†‡5™¶“ìÄ'øº‰Å[Ï3Ýr +xÃd”»'}€ =ײ*¯¸¶í¸‚apÕZt½Öì(Áªâ îSò•³¢÷*謣Šà¬Ö“¥ê§ +©J‚&5È5Žþö`œM\He\O‘í(‡L-!±œ(å¾—wut½àT\ Τ±VEjøhi­VîVºi,ËÆ’—7TÚ"ý=•R|R ©õÍ&qlCé¬_¥Öf4¨»ôðºèÌËìè#ô­=k*+Îê<.%~hþ‘½Ø‘ +endstream +endobj + +6 0 obj +1078 +endobj + +8 0 obj +<> +stream +xœ­ZMo#7 ½ûWÌy¸#i>À€ØzÛ6@‹ÞÚí¥)°{é߯DR"5¦˜Ù àµü†|¢žDRƒí®ûïð­ë»‡>~œŸóš>¿ÿÕýþ©û÷Ðwéïû߇q:ÎÝ4÷Ç¥ þè;ŽSzêë§Ã²W‚&w%äÆþ8¶ ña(Hð.R +°?®½[§nûo™Ç0Gƒ<¹š@ys=Àps=rHóÈ ’ÅÆFÐ5‚L +šn‚²q]Å +W‘!¤G†˜Yv¨E6ÎSäQ#CH 1-²ìPlôbëÈjD˜9T#óɯ@ÈS##‡jdý(–±Ž  Fd€©‘‘C-²aq‘] !=2ĴȲC-²aœÅ2V‘!¤G†˜Yv¨FŸÈjD˜9T#s½XÆ:2€‘¦FF7‘}ëJ½¼$꥛}Y_þì~º +›º—¯_{wzð½?ÅÐéŸ~™Ò×ùôÇË/‡ëËáóás—<&²òuœ~œtØäë_Þ&î5ÍñµÃ¬ƒºßbøÚQÚ* ¿v”º +*ǯñ,ŽéÅäžIaÀ¤„É!H •EBJ¤ERÈä™LJ˜¬‚”PY)¡DZP$…ŒžIaÀ¤„ɪ H ••AJ¤RÌìDŠƒBš1Y˜4£²B0iF‘”Q$… ŸIaÀ¤„É*!H ••BJ¤ERÈô™LJ˜¬‚”PY1)¡DZP$…ŒŸIaÀ¤„ɪ!H ••CJ¤ERÈü™LJ˜¬‚”PYA)¡DZP Å +@¤8(¤“U„I3*+ “fIER¨™LJ˜¬&‚”PYQ)¡DZP$…ŠIaÀ¤„ɪ"H ••EJ¤¥&“€I “ÕE*+Œ %”H Z%|Ѷ3–ó'·ÒŒå4Ç/c9q£Z°’4¸¯d,ŸmnËG»6ÆòIá&‹±¼¡¹'âÏûŽ[ÆòöàŽƒ±¬"«VɲsµÌ*9Ve°¸•g­the-+¹X9À:ªÖ‰Úl|î+ø¸µ»RÛ%Õ®}v‘²«‰öíül'R;ãÙ©i›C¸CãÄÕj¥ìžÇnNì.Â.÷v]¶ ¨]éì’d×;Éo³±ì}•¦TŒ•îQŒ•6OŒ•~LŒ•ÆIŒ•GŒ•VDŒ•žAŒ•â.ÆJc¥\Šñ}]ëOóMÕ·ÎÁÝ´Öt‡[Ò‰€›ÖØ9ŸoZcºh=¸xÓâ{Um½ºÔÔkÖC²Á®f¾åÂ!]Y5s¿°ƒõ4=ög_Z¾|˜[¾žÒ|Ðü9þa\Wv“>««(,”ºÚ¥ë“µsÑÚù–5.fbºõ4é÷83\¥¯-2Z^ìròÙëS¹»§2÷œ~ŒpoÇÕ¿ô7'diÒ¢!Ä=ÜV ·ЭcÈW^ö›¡€oú'4‚¤@\^{5CïÒ^G^ϪùàXAÃ)>…xüõ!®ã’ÌîD@ìvZñ8ù™?ó‚'ýRG]žé¡ =’œÖÈ´~õç ‰2N=8ÒùFϱμý2ݘ^ÜФ.(&ùµ7D¿Þr¹!‚½!tëzCXGòÍ +¡ìÚŠ¡?ƒ¶MåpW<¥EÏòa¡_ŸÓÇ•c€OãïøX€ à'>¬tJobË¡wÊ^Ò2iÞ –xã2Fšâùf6ñÖS¥X¯‹×ÓwS<•`xšaÜÜ°´¸‚õñ…—Uiâ¥LÇpaI¯Åsõ3¿öÌéô*2<`z8g¿ç×h\jíòAGo¤]´äLRr¶-ëäÍ$ÝLñ(«fʤg-}#Iï“U#Ø%«bhËJˆ‰Žftb=ãrèUÜwµûuƒ•`Ý V³Nɉ¤£;‡Já}Rj®wI©~¤”ȾÔÓ‰ +#üXu;àhâm >ÂÀ ý¹sˆ+ï +Å&S1ÕÚß•Ä÷(¦ºÞ£˜fø‘Y3¤_±ë\saÄJYK¶û”ú,¿zJóõóqw¦ÙÊ­í» +«YobîH…Õ\ïV1´… +ÞA-˜b˜å/x´D+”2ž¸ªÊ=‚ånW&“õ0ëŠÿ>sö¬º¥7TÂq5:Tû¾©Zƒj·{‘~P5Íõ.ÕÃ:Žp‡ÓZRÑè®~„•ot¡ß)Äܽ;±ò#xÇ›ÕzÓ”’7¥6ÚJj®w)©ÚJÒÅmæÎb{Ï÷<õ )U>/ôj KQT)—Ç<z…qwñ™EV®:Ûçòâq_«[¿Õ˜äC⿃üÊLJ> +endstream +endobj + +9 0 obj +1858 +endobj + +11 0 obj +<> +stream +xœí[KÚH¾ó+|^ ¶»úa·dY€¹EBÚC”ÛfWÚÃJÉ%?UÕ60tµÍ$ 805ÂbènêûêéµÒÅ÷Å×BK…O½¼–®ß¾ýQüÏ/ÒÏ·í~áüª*JP+(öv¶Ð¾Øÿó©VU³„Z¹ÆÖ*ðSÛàe}ú‹i>ï?,vûÅGqU¥W&® +…^U¯µ\Y×`”S»FÓ*Pë +­×âv™µªVV^òI¤Y–õowÍñÃÍÚ¸fÿŸô‰É\™¥/øD¦ª'bÂFm‰TløÌ+þK•¥–ñ¸®¸úSÈü‰’b3NïÐß DñZÕT®6–¹¢ƒÄðÚ4Ã\9ðG«,_ðL™MžNn„¢ëÚ”ü+z«·e@[ +@wØŸ,} +m†" ¼á ø‚3ìe”otYŸq)ó4¹—ôD oü™Ö¦`‡jrÀ“ñG¨Ú˜» ¡k–UO†Ös}äèø}˜«ÐËøÁ¥KYáˆ9ð +é\&o¢·)h…‰gÆó|¬ ¹èèÛCÚé ŸAüõ”˜‘ÒK=üdù¢ÿÐm¤“±|G_B:ÓleÉÀuI”è¿6퉖K¹ða6ƒ9Ö.È”CèðP²oâF.(«Ü¦"³àÈLI1È3ÓLWÚ•xBŽF·ì2´‹´`†¼>ÑtÝŸ¸ÍË/!œè²Öݨ/p~år¯‡€‚É_ !_3hÚ^Zíád†~]Çà6ECݪ mü@³%?ÀÉ^Ç™#-øp2 &\—9 nSÌ%6M9{¥VÇüÔÕ.1Æp¼Qœšœ×6:èòùGÀ¨'îû$r5°N­@ìh2ИiÆd2z,;>Æ ÎlèpÒ^O!oh݉N'·•;“ ¸n`Ý€¥©7“¿b­¼Ø»°¼ÉT—µí4XŸKýM9ÙgˆùâÑ–c“É©«{LrÁü¾i‹yˆ@{´ºÔ»l/¢òÒ™çÓ,Ãø¹æ¦ÈaK±ÉôhÏÌ +=è|wÀ)y¹wy=Š‰§p„ ¶9ïÇ“ê:4ÏØ$c×–ûƃ“õ^vŸ»*åm{™…•_Â’DûS,ÑZì2K(ìWEkGGmÈ»§D¡“½Kw YæâþO%Ášh)k© ŒÜÜ£0Ýðõ!öFHÙ Dôº˜œ÷Q_CÞ¹SëWÜê‰ä6fjyÿÒÉ?GÍøãýíäaìdª³”iŠË¿‹¾QªhSBaSWÊ]9tÒ4@T«íŸÅ–n5‰Û<¹üšý2Ú‰V§Ð6AíŽÐ¶ª9‚Ý·T.›$îò@2‹|í +!ÀˆXQˆgX +ïœÁë#Da °o²Û—z—Œ\ó k}ÝX kæ“ä<”I{kýø:ؘíý÷i`hÑľ¼Žå)éM?7´]Ûœ;ñ%TÜ÷áåFæŸè9#eó‡êm3OàÄEî­­[Ë,lþµ^ ÁmŒ-1œhHº‡SáÄÀ!ŒPxÅÉ?Ftx–È+>“$ù1¥à)V‡¹7®#wæE¢Wª\iÆÇâ“°ÞÀ +endstream +endobj + +12 0 obj +1385 +endobj + +14 0 obj +<> +stream +xœÅ\K«+¹Þß_áuà:zw7 §m÷"» Y„ì2 dÈlò÷#©J¥Ò«eß9! øúØÝj©¾z|õðˆ«¼üçÛ¿/âò]ø·N*ÿºláõ·_/þÃå_ñËðßoÿø¶ÿøfÝu½,bõüøÛ凹HÞÿý/b¿}Wâ~ûë?}{þøöKu뢯ÛèÖÇM~ˆgxÙÂËW2·ïþ½Šï-|7ZÚoÝ/ï`aw‘–•án ÿnÝÖþ­:ÞhnÎ?[¸›öïÅ?³b.¦®ú⬾XN]¤ŠËiq ‚s:¿ù¡”ºeüslxšúˆŸJe”´âwÿ‰RÒïùH·ÝÅ!v©ük¼ÔÄ[]¼TŠ(¦pŠ„%Ø•ß>üÿÝ}¤?wÿÝÞD¹›ø ¸nX/Zi\õ·K÷Å+ÿ |.­¿Lá™Â]ÚÀ¦­~òýÅG9ücÃãª8‘¿RÂúþ tEê¡a­ü­µA‹ü·ÿìÞôÙé-)!¢HRU°ï0þóGÚœWŽ$2”ŠËÝì‡ÔáKíÅ%&ñ{!Ã÷j§–ð‡ßÀ“„­²Üá!:.2½òoW¿ ?\W=¢vo·õƒp úEÀe +Ë]Б;ü=xû.wù”2Àw“ Óûbz¹Ú3Ä”õ¯ľ̪˜Î= Ë{Ò¿ïR„kâ7;¨­I ¸$ÅñÆwÄ âš•¨;ˆQ¡U‚’‰V™vqhwº£aËD3¿B†~à>``äðljI³q´a”Á·5rŸ.*a"¡y™ô¥–<w7(/P/v›FÑêhh"̯¥Dp£€@Èt·Æ?Þìú¡M”W§äÙH +”B½×d@É z—e³Å¡,Ó£ä} +ºh¿)À=6ê#È'þ¯÷®.C«wí?B ­‡À™ÅÛVÃ6»­×¸èå`GˆOt){ÜÊžD“bHyÎÏž÷A +VÖõ-,¨õU_rg½æ\ »;C;C¥Kqô«OÙs +Ct•u-\3|WÓr”¸U/ÕÕ&íw(Š(-0 /RŠ +k²Ÿ¤…{ä{rdÒ_3F=ôÓ÷Òœ™Úùj½£¯™» ` :± FÂà<™y@0ËA¼t´n„†qâºpá.äõ<ZÜb”À‚õŠºà_>ãç‘é®wîc_¼u2ƒ| +ÉáZý$+AÆXî6Ç&ð ú3_ª9ˆácÎ>بA'ÐJµl9¶e#›QO…ŠÈ–±¼)Û¸Š“;wÓ’ +C¢jT×Øý¾€mhË!kqš_»AÖC˜œ6±çŠÆgÞ~9QÛM[rT#<®¢Å¢vŒ)4•2/²'S† +,¯œá +ì×ÍQ”Œq¾Éï×F.urà’êìâä"§øÔº>pŽ9G%Î;?È à€=ªŒ7Ÿ·Í06ºkº3l‚“ * ›>jK«ÙÔ3Ÿõ}]æŸ6AGD–ñ‚¾«(Êe²‰eå•ä,ï¶ÊxÑþŸò1T + Éœ½3³™Ô¯9p‚ z +ýÎWSÒ ¼è¸FÚ*—à‘ÁδUÊTäÉé%g¾g’ô`hy@lD(¢c Lþ"º-_N»ÉïÞŒ¤D‰ Ø!€ñù[ßíg®[†<ØÀ^rIb”­Å`Ä‚–Bç†5°¿X…çy­x'x˜m¹Öþ#jT!W´Ç™ªÔ9Š,+6¼)åb•î{»2à3&´}(—æÉëϳ½6«&Öʽ%§®~`­)>±•¶#á™&©ºóU‚s œ»¦ÃR(ØÒNéRyLN©‡y¦à/hãªíîæªB©n¥?KõF=ñî© U +4ô˜V˜&î·TÅì0é`*“¡ŽX“]‚¯Voõ„Œmô<\²¸IG²(a))ŒQ¸d¸¾Ï«ž¿‰}È\™ÞYÙnp¹Ø§ÊÅOxÁ=¥½@×Ë…’©VVÙàÀú•"” +Ë |v’3è´›ß/œçŽK*$'ÐëÍ5ÅÑa‡€Vt¯ ‘sÍJª<ÝÉâk|È€{݇…ò·Éò h¦˜çïÔdYj<(èR®B\J½_?ëjôšA»ª¶ÓË‘Ö%‚çwÄ_Û:1kCÌ +ÅÒ†¦ ÛM.ßo‹«j‰~¡XR8fœ£Ç(º«ÝCÓÚo¢ ¨&¡I‘zâiñŽ„#…}ÓÿCy–ËXËž‡O<“ò‡3ž£iR¤ÿy-¨Û£âï fP¨ŽÜ½(¼vu§”+Ç€¢áȦ*7æ…oD(örÖm¤EbpÒt’όϊ&ùéÑ€nÓô^Дh•ÝŸ¡³uycàH#/i@ª@†L¨¬êÜùërÛš´©G³Iæxƒ² +èn>=ZR*z¥zÙiåºÅpºvm¢ÔVâþµ®“L¥Ž4¬äŠ¶0Ó=t ÷{MÃð˜kÇö\æ=)èV¬T3uãÝ“\û3ˆtø0/©ì8¦ÊöY1/¥ y“5z`²²¯…'ã7²ƒÑ T¥Û/•ì“%æ$v0H–*{)ýÑ`bµ${ßäB’Ufæj`ñÃGM·äbá9¾É”å#8e¿£u™ØZ®uòžV1ç‘ŠÃ\3å[ fȉ­)ÿž¾Oóèû7ØOZxÍ5 „šT{Ú  õ4•òwæ­¨“ÜÿüÑhº©ž­Oå7öO:¬ûšìÔfRS—¸Ã?°`ˇ‰­Ð¨X”eCLeÙŠäÍà˜é¦ÞãyýØÆ”Ï^AøáQC®’; +—½?Ø5 ÎÌPVbÆbZˆf˜jÛ<å=cÁ†„Xÿ¾–úÖÍ6X£€ÿ>ô&U‹éÇ ¼KŸÈOAAúBGûV"Q(irþ¬‡¯åM=•ë«ôY-_uÀš¡«dÃ{¹ØZÆí~ÛðœK¡Vý%Ý»¯éVWh {ü…H¹WÎÛ$¤ã]œ?Ÿ ¸´¨LPt²Ö|âLœÓ›tâ짙mÕȦœµ=5Ñ‘ê·©'3NÔc­øåÛH'MøŸY¬"Cð³Ûa>²…ÿAAGî—ËìµØ +endstream +endobj + +15 0 obj +3454 +endobj + +17 0 obj +<> +stream +xœ­[I‹,¹¾¿_QgCµS[.P$tÖrðm Áã›Ç ž‹ÿ¾¥X¤Ð–ª~3<èW¹)¥øbù"B9}¨Ëÿ~ü÷2]®“ÿ9+íÿ.[øûÛ¯—¿þéò¸þýö¯Ç×7¬—E[Ã×?.~é‹Ò—¯þí6é]ݦç~o“ÙõMMûUߦÎgþ¿pÃôð¿õ~¹ýºà1^™é~8óÒwú±_×ððº»ÛdÕ=Üù ,<΃k“=íÏÃMpÑÑp昜ÿ÷Àië¯.NîHᛜÒü +7mi +~½´^ŽòäÕáãôz\ât÷s;ü /” +·®b%ð0}ø5ˉÐ]0Å¡ËÆuìÿúËç×_J m G?Ðþõïæý¼š>L¼|­ÓIHðóÅò +j~ÂÑpfö7黦sw\¨Ô˘u÷÷^@jWÓ|Sª·D¯Ææ2û¿º˜²±0åL×L|å ~k3ÝÕÊXh}·Ú"¶ñN¥­Vnzáš4á‚p¼¨¬þÚy(_Õš’‚*‡€Óÿœÿï.dˆ¯rI§4+CÐæB%Hͽjùiƒ‚Ehð!¡Ÿ4ÑUÀ'­ +ÆMƒÝsCè›S®Æ@ãæeý°¥Æ¡¼K›"ÙL[ÛˆfzBßÃuá>$B$Œ–°A3í«#Ò3­½"H6ªhˆyWKxHZ*σçÀ¶!Gb¬ªôµ‡qŒ~öŽ‚æ ‡’;)§ÅTÃ~®©4~ 8È‘idz(¹uá%£-uÎÒÄt¤³ý˜[JÀ«&‘zó1ÊÛat”J§þÁÎ^/ó±õ ŒÉK›µì%—~°I¾¹ý Ã“³Ét†>ƒB¢TÚ,ÔÓ±û8¸ÒUü¿+5Sɯ°f5Q¦È¥FárÒÂqîÊk­¦ÑúJ ÕÇÖûH ŒþXJ ÄƒkŽöì§ý(#Z+AçÌS.ì‰ÏàÁæå59 ûà] Aî½Ò?Fð úP‰Œ-J!«×½né– ŽrJ:"#¹û¿Ê'ÎDG''c]VýòxŠ„rä;¶>x«G¡ÆbžZ=æïƒ×wÃ-™…­†ø¼PD0Ô7Œˆò‰†ñY´Ô# +"ÁÌö[jˆ¿Y=òµÔøÛmªÊ‹£¼´®0¬{fÓÑÆÐøµçÿ»ɬÚœèU¤F +ƒéG¢D*c +ÔQW¸DÌ@¶|tkG1¿ÖãZsttdCˆ]èVÔˆ ^æªxxR´Ò…$ +èÙ äF6†ÀœZUa)YMýýƒç5õ'Öj$‰¢¾‹˜ºðEÒ¸÷M¿‹ŸÚøqµ…^¬‡VÁZ–ø@¡ç‰DÂàŽÆžfIŒ’‡-ÒSa›qè~ð²!xU‚!5™*¿(Qê€À 9… úæ¹³s³™uÄzâ z´±Fšz<Öbµ°¬#¯-à ]^¨¤Ù<[ +†dùÞ{͉EãȬ®Ýÿt/S²D$dÂß4š‚íYáM5 `iÖ­.¤þÌî¢]%]IÑW”~2£SŠè×j65[]{0é " ++î +é7 ©½&Æ>‘Ëx¡Z\À££)}ä÷_—™=bY¢èþœd ºÙäÅUÕÕ¼'E=â²­Štl‚BÙ9ÏzJ‡,Ô ‘[jfö¬*«Pø2a,,‚Û¨ ‰ + -zðfãζwc¹-«Z%âÕ+¹ +.–EŸÀ•ÂˆÝ«q=«ºëÒë)ˆÓ2‚¹‘ë¾Qª©ÄjgzžÝ”,ðˆ}Ò¶¨‹ÑÓïù¢,N?8ä+0’®´¶µýèç¾Ø0;š7Õ•§5ïæ6-plƒ«‡]ç +„ÒL[½WGÌ÷HúEUkíB¤]ªéSun*8£‹”‘¢Ô¼6ZÑ»›²ü ÃT€lÈÄ]=2rªÀã=ÏÓÇÔÎK½ýfíˆâ$ü' øo¬ÍI‚sâ[Ø ,Eo®×ªhe<‰5¾'G:K4ö?dWJlµ P«G+jI*ðæÀBÏt»GGõ-™X„”…ÔJ*:PV£A¹5ã÷«MºQöo9ÙÕ17ðºêööíØHiU™ÍuÛòYÝBº´( FÌ+Ã\¹#Âió¢.î¶ï[:­ÊÏÆà|é‘´—¾ÏK½§7‘V¹,hk¶«‡Æ›ƒÉnW6oÔ5¤#˜×zóÇ°=[júe؆¦¬3Ù®‰²ìæu¾§{užÕi(öÃämTà ž~Ƴá”Zƒ0ãyL­¢pºC×7<¦ŒÊ!ü:ÄÎpÖª3ü^Š6á68îö§—…OžPo,U_¢¥[•Ð󫔦E~ +U’¸‹¬Q÷k¹/H#A‰“ÆómEN)5µ²g{(hΉޖ.椄”i–‹~»Þ'$“)“k:.礶%×PLoªw3‡°õFi]ìï”byeþ•-Å):çistÄA„ôt[Q—ðÌJ¡Q³dR…Ñi¡ÕÄÙà=o´[HïìXÎj¶‡¾Ý!T³Ç©þ-µMuû¡üdÄñw,/6¤¾bÊíE:U E¼x€¥«ÃÞ¹îC ìE¤Ô[ž§Ñ«q’Nu1'ß1Ù—}Íõ2¥€Tµ½O¤ñÈðñk&Þ ÿì舙,²ë§L‰\u¬ºK•ìË.XÞµ8›MÕóÍd±ÒCYîË ÞÔÚ-ÕèÜ›§–¾UWbfÁuð˜®Ä2jÞÆÊÞDé.¶ï«-o­’|3§Í¸V±íã|[k‰ÐÐÙTû.ðCŽjCŠÕ¤•ìyìfCi¥Ú€¨où>ÿ»ØF“vŠ76lý^¥û]ÕÃ!¡)¤×Ü™kA•`–ÖJàÑç=ç=ùÓŽ){”²ñåšt£‹] ˆrÆÕŸf‰zGñ ìŸ+~³³¹Æ_]?ÿ $~Îå +® +Ë°ZäCžÇ¨ë´¶*‘Ùiô´ó¦Æwv”AÒ£&ÇÐ ’žøó4éiG¹‰Eù@^3ÆA‰¦8G¨aøùËF{ÊäHS¶Ã©PÊyº›h!çYëÊû[L¥.—\Æ*<^*¦¢y*¡{€ÏŒ¡à‡ÆIDÑÒ$Gšeï2| +Rž7šÏ·ŸøëV|D^ußn¹ž|>…/¾ç[ÚœõdÈRC6ðK]s—]m–ñ –ë~Ñ›Wn‹(u®dœ†)ÙAL©òɼ\d‡†y07¥ZŸq`¥ÖQ§XÄ‘˜£RŠíÎìE ±5%©¨ß å0ƒØà+êiÞ8O¾Ô\jÐ$È¿\þ`û7 +endstream +endobj + +18 0 obj +3436 +endobj + +20 0 obj +<> +stream +xœµ[I,· +¾Ï¯ès€é”¶Z€FS5]‡Ü àC[>°/ùû‘DJ"µöø%00ž©EEñ#?nzÓ]Üþóöûmº½Oö×YHûsÙÜÏ?þuûù/·ßüM÷ß¿¼_of¾¯·EjûÀ×?o½äMÈÛ׿ÿþrúÜ…ýŸ8÷wó˜žöIºj—¼·¿/iö(‘nL×dü-÷¼<ÜåY^jÞßåCû¼‹å¡&wCÛõíÕÉÝ‹×WóPÚ]‘bWv½™=$Õ¾†?¨ÂL›]Ü‹¡AYkû}FA¨N<-åé^÷_°×Ü}©ÈZj/:5¸W„ÔÆ/J9ì[nA±¢:V/l ÑQ,¾9]þˆÄšó‡üêþO¸#'6þ¯¿½=¿Þ~Êa5ò.+¸:ýZ}˜î*3üˆ{3~ÇJ…Â6qw¢%5Au›7'_­á’'â°¿¯„…·"§þYùoF1935ù¢½Â¢ˆÏt ’é *¢o0ò™>„0ûš…Z‹¶à's0 k:@j0<,³Ò;¾Vsê¯[”IhwÑÛž¿ +RsYLÅ{˜’Vòâ-›Ñk£ÍÌËz×9y\ê4i"M0ÇÊé;¤Éïí`—¦JðM‡³õ_ +‰!P‚+@@¯AÓ^,Bt` +VNo92R¾@è$P¶/H`ß’‚æŠu@ –³ð‘dç2ÐÂBZâ4vÖ÷¹„‘JÖÅýMØýKP¶“ñ¦œVÅ=YF»Ì”Þ*|&šIIÛUý¾[¾çŽ¥vÑüNà®@í½v³òH6¯n?3’ +mÐXÑ¿¿¤ß<×u [!î[ª¶f²?9¶ È(4A…‹AŽï¦DòU`ïv+D™³4ø»*Lôä#‰Ö|8:U®e¤þ\œ" À~ 4õi/*iÓ¹xSš™Û­Ù•“‹ƒçr‹?aÞ@)ÖQöˆl¬íDuQÁn¶Zª1½‡^r#D¢Ö™ìÂ&¸o_*¥ZOË$¾·*™C “&<@"Wç¤Î¬²íóù +/ò(“û ‡€aó +¾c¸ŠgC¥gŒ”ªHœrò¶-L ÛozN-D·§ŸåM¦¨&¾™å¡Í}:‡ó|í?[¦]ÚñÜëÀ"ÁÄóýß–0ôøqž*^u‚LJ|$Ðñ 3xN°=bÛ³M©Ý=¨\~`c F®¼rñzë$ÿŽ JFf6Q$ÿͬv'Ÿ»ÌÌ&*6E¹¤!ÛeA»dNã¬äà6é’øÃrÍ•4kíž, }£™—¥P'âb‡ „ +1I$òáà¨En„õÑ,^a/Á€îƒ‘v¬M@…MÝJ|F€.ËÝä¬Aó`¯ádœÑ¬é3¤öLmõTÜgc¶¢4øsLÐMŸ³oMøúÞ}+¦û¾¾gåC0`ÒÕéL)•¿¨¥µ`©FiS‘&ðÖK)GAKI¾fìñfQ 2²#mŠB@lJˆ«Š[´w&ãž©ÉÅ86Jèh¢÷ àHçm#´n"²îË•î£WNçÌÂiŽïŽí¬G?Ø‚}ˆÐpãiÆ u»œ-<%H#T•(JJÐ+õöϺ?ÐÊ óº-зÎ@æé° + Iè'Ò¸¼òŽíÆ€¶C~—©; 8™†kÁ?švn].ß|­î­¬©äx]×1©ØU¸Ò¢À9kFÚ"»Z£Ãi» +"ËŽ 3³0NüÀ_ÆnW3t—ˆ—*±SgÚÉ\že5ƒ+P^©¡Î1Y‡×ˤ%휖F}O½m¶HïÆÁÔ ¦ñ+e‹œ;©!V"^Ÿ6íõ£üŠ†*‰4/õâa)…PC3'´ÀÝß @,åÀ,¾U§Tkò‚x)ë·8bH´ìÆ5It«À4p,½ÎE¥CBÓµ‹ùái=6·ºmjÍ:‘´&}p–ˆ*Þ‚ÃÄê +¯$­U‚Û¸¡Ó¶™ÒŽû'GgȘƒJH’ŒæÒé­y®9:鳚,®%X#tY©‡¨õ·$ùáŠAt2ëÕÜåMk6££å®u2ENÇ_Oüµ±œ«Ûke=ñi…$I¦wZéZ®CcøU»Õÿ!0ÿ ôú-û§Åe³*kq06r“$ÙLU7¥lÕµY°ÙfÛ¹eª˜¢œxǾ€-)Ë~3š9˜<ïJv1™,?•|¼S4Þ[k %† \ C!žYçiª +WµG2l2©¬©9ws²PiäWÓZΈýÅAÞ¶«”ÀY……¡œgÙ‰%¸3T’=*¢Ô c¾Ïß0gêô/¢1¹ŸóT,BGÚLP|ĽCŸEÀÖ¼&¡7kÛg‡•òG23™Çc6qiFFcñ-A ¬6]–H÷tÂÀº¼.0¥0ÞŠMÜY%õU%å§gô: Z…ÙL“Øï°C +F_\Ú +øŒ* +¡eÑЯø~:U0*M{±À³¤Zæ{ÞàçÙ%ÓŠ‰J‰ì“Î? d³Ó$$¶úù@.¥blê?Àz}dZ€'dúv(³\Ã3¦››QnŽµ[÷z'ÊYu¡ë‘̲Hýùô3²wuú™§ƒéO6±W\ƒ·¼>ËrÊ+Ž¼ë·„kәŅzoÐÕzŠh^±YK‹j3ÃTá5üµ˜ÌË>¿™©‚ÒV½•™uîO›y ˆñìP>‘Üyè€>`Cõ† +Ž +†¤LÌùâð¶GEºb,>“££YУ_ÁÏ3žÉ*É"’ù8Ò§@U œÚ1¢GϤƉœ¹‡Ò«&9uÀ>ò2¥æÕ?R17 a—ã`-üB! lZ«VSK¯ÈO½«wú%#GK9ÙDn{’&;ͽ´½R3ª%õ0ôZx·.ž¢J €Ë\¼÷ç‰Q°*-^z.!OÛÊcÆŠQqõäT%Ú¹†b‰Á´IuÙø(aæ‰c®íw’“el,¤´·WM5ÒœÂ]+Ã41hTøщãh(+óIÚÖ +iÕÙ ±öÒHW4>€H®[QdÑnKôBÙ*QMƒØ=ñlY÷ÿ‹xMœÃ‚±šk¯MO妀‡Œ² |;ßɲF0ÜZ†ZÛÝ>ŽL³¸AJÆQ§¶ž€aÆåß×nºñ§*ãÖ–^7³¿¼ì˂Uú¨+ÕÖ*<þÇí,‹ße‘*‡²quÝ™PUCÆä]ŒŸ¤MEÈêƒ,è·_ÄËÝ—Oû庠K&jÇ¡;§@k˜ˆÄ–ÿEszeø|e%YI}^›z#dÄBl[^é0è…øá›ÐÊqª³ IðÄütH*&«‡¤%‡p,„„îbLR¥Ã­:ñÞK˜Æ”F°Œ†’éŽT‘A'dQ¤¼”¯MüÔHãó(æ¾£óÌL/†"æµì80:Ô\œ<ñhêµH}Xvt¥åXúR´2ŸªEsw6ˆ—éýS̓ºên* 0ÛZþ‹Œv¬Ã¬.9æd¼¦ÁÚH ”ቋBˆqÍwtg7è|‡¦S­¦ÓqöaîÐïdÄ3éü´í*7{>Nù%#ÌV]œ» +œŽÅk‘Œòx t‡kÔ©NQ=§\©”-o•„æñò—­ hnå‚y1w'5Ï·N»g=97˜çmìv6]¯(*ƒ&yºVM‰ÉÄe*’› ÞvòÛÌÎ&çýdÍ5!ì¦êb[–mU9ðˆBêXíÑÉO·ÿš € +endstream +endobj + +21 0 obj +2856 +endobj + +23 0 obj +<> +stream +xœ­[I븾¿_ás€îpe 0 ´ìÖ!·È!È- Ã3—üýµU\$÷˼¸ÛZ¸ÔWËWUlón/ÿýñÛÅ\ÞLüu¶.~^×ôùû?/ýÓåW¸™þÿþïÛ×k¼íÒí¯\þ¼Ï;]¾þõ·›±ÆÝßìÍšøóï_ùñùõã—êÕué¾jí=¾çîóÍúû›¿Ù) +d‚yÂÏÏx×Ìw3Wø>Å;ðuÍæ÷8“q8»Xó8ïÇsøaö´èù涻‹s8gñî6^ üü÷·ëÍxx—´¥u†´ÚøŠ7ÞÅ[0(<Œ7z=Î`vœƒ`Íý +Ætb²¯ÆQñÿ/ÃÄ°r‡#Ù`VzË9÷˜ÜÀ‡yN.>³ßß\DÜœƒ¬ïÍw{½y“žžð*®ã +¯VâAè)Ÿ6NËᇃâìúî@¨_ÿâ7/Ë{ƒ “kýDºP¾¼"‹Ø!¬›Yîó”´l°¼%ĉæ°àdOf6P—îÍWƒY»¤Å7£Ù§ýˆ yƒÁFöáÞýeöKüÔû& $³ú‚tÔ+Á¯P¢Õcb”ý­ÇÝ +Ä&ø¨ ÎÂ6 3‚Ž"}æïqê[(·ìBÚžW±ÐJksØÓÿF!O÷iÉØÒvœ¤…ÖÑ.lÒÌGÙ›9/37(• +ò€Q\Èn~ºÇÏCµ}¼ÎÛMìWû(®†Ä–¤¾ ²AMlûf¥g=³ÅkKÜSÒïáKU£®B +û¸Û);Áz‰Z†9Ûarj1RDWoh +éÓ¦b×n‡Ì® +]©lÒBXüÊ2ØÈOàx=‡NNL$„wäȦõýÚð qkâk•+—}W\ê1†åiŠ×¢…>`õ~¸tà¡c ñsî;šýš¾ÝüÚs(Ú86!¯s1Sç |Ì‘­á59m{‹‚¨"t +õ…´ÁšŠRggDz•çörKqØpõdì ”<j€Ð¤ÚQÂä<È=Ï.â<ïGêO1­âDÂ5Å”ÊctVØZ£r“ãá—¥ò³ïˆº”*T3°zf±/:–¥" Ùß8ñ† ò+É]>PoñQ…#wëàù˜.Al*kߥ”ÇÊ‚Z@¡ }Ô¦íð©ô ðþ‡áÁt±;{®ƒƒò¥E +…^ª|ºkÃìgJ6™,ûrƒ–%'#,hæ ãÀ…<`yÊ6¬$ŠIºÜ3Û¿5BK$u®Rø6`¦¦‚H®(pî]p®Ä½…ÀÍGVæ,9\ñ]ð0^ؘíÔˆž)@° +ñ……‰½ ßIo¼6±ÏÈ1Žˆ t^²ù¥îÁkCL˜"¦l bŠÏ@ :£ðÆÊ…³-èï•k¯"O1|¥öÙù“8ÈÕÍÉÕArX!¸ÁsJ–oÓvǮަ˜Û`y¾¿¾O5U)½Ä-é‰æäwò±KGaÞSki¦ÀdËI¦¶ vÆþf³A…P?çH6ÈþØ‚ã'ñ‘önñ¶@ÑdƒˆÄ™Ydj¶ª|·„Ÿ6*Û@É©!9ÓlÎFn×¢p›ó +·¢ÂYHqni32¬ÖÚœp“ns™Þøây g‡º@ +ƒ(u¾Œ0ÈPŸ=ö°,Í=¯_ó¶ý§F–l¤ #+‰B͉£Y#wìNUÒ‹íÀ]´Eé V³¶Ä«ÃJshÞ +÷©=R_€mj7diµ »lÁǼ³c®êH•þPâÌj”as_ßõƒU5)»]H¨.…ïgoÌvµ«Oð£s›6D¾ª“Þ"f;Xž€?­µE·ù4™žÐSY¿c¦¸¬Èµ8ÅK=×Q"ÛŽÑæJÈî2®m1ìÂV‡dJXì8ÂçøÞ°®ìE7UÓXBýzî§Ô"›Êªš³}"²ºHϤ`ˆòâXW +ßÚ‹kX× 9– Wæ,õÓÛ\¹ È@ÉøR!š£g!0TÝd¨dUÄó! +‡ÙâÞ+2üÝ´c* %ˆiž¸ú/KóÂ,bÖ5oÏ·ó>xá3›)žr%½1²ì>P[«’A‰Å],t¢$`ÇÄU­Žó Ø|ŸÐ*@Âh¬Ûª8¡œ$3ÎPæ¨ö-.gÖ]j]¤vA¦“º%]¶TjýÉ +%½¥¬RiHYÛéN·Ð–ìæÚl·èèVY& +‡îqи‘Ù«V*\æ  tØí.m"æ%¤y9Ü “é}í€r†¢Ÿ›J4L¦ÙŸÙ!Çeኄµ9alù鎵É=×Ñ2w´(²ˆzP!.—8]`_dž +¶IŠFÔ§W<Š6Áܹ¾Ú¬‹´0ÂÚ³â`B3X”vª&ý£ÝÌj]ܨÒ6Áê»øœê\Sh>3ŽR.×bÅmÇO1n'õ>hÅ0©ú¤Øòs•Fò.ÜR¶.Z¿ªR[¨¨pùYå+ZD®gĆŽŒßë9…ƺ3¬ÍmþÿÅZ£"â¼`ö{ +?ëzi6—"?SÓÃf«¿.¼Ù“v+Ô*NÛ­íx7ûŒî!þˆèˆµ_l@:¬þhKŠ$ˆ@ Š‚?è"¿c—Üók¥Ÿ¦Î&(3Ž`‰>ºpJ––J:… – Yù@Y(¡?ÈÑÀáÕ€œ˜€ŸBÃÙ±‡åŸI¤XÒCÓO9)ï#êÄR„«êéÙ<>gv’õ*ÚAí2œå㾬©·¹§Ìi¹±ØjõRl²hÕͪtšaV=Õ…8̸ݒ(6tupÔÔâÙ·iáÍEvIáîÚ.{¥-Dg˜zÛ@SèŽ1¶9ÛƒÛÔ‘ ÎãF›\Ó=HñSI[›xû8©pNÈ°„ã¬ø„*ì@ D»‹O4\ +5k­éÄ ³ùJ>óÀ¥ƒ!Ž©ÛÝÂr†£½6ÑW»áµ@¨+NVˆ4ÿÀ +Š^ò·’aªsƒº S­*qY¥9…#¼È¸Ó*ÆóàTK¿Â4§„S‹Ö¼Æ·•Ñ¹NR7´è5`CõYRÝí;èUöN±Àv©†\g9¹oƆι)Q—)‡.å£#I;O2ΞÖô8uÆÔ9…ÑaÁC„}¢\ +`'»Õ¼Xþ¬™7ªêïg¯(ów))WÉ7#iªr”êì®uÂH}|Íé;ýþžé§Îg?d+ýEìB®FŸ1àÇ+ ¸7žÅšM¹èì.£”àÈn’,ø‘L‹ "àtXÒs“iKzD*~†Ýbegv:߃aÚ´Ý¥Zp¤þƒ:G(ᦛ윃ÒA½ö•X3¤Ðk3+wsSÈËaLÅ°££ÙæN“eQÆŒŽc¹Þ—cYuŒP/†þÊ‚ußq`ƹÎкÐR=îþ(Øð}ªfÕó®àÚœ w²»q…6ÁÚ t«uÊ^}ü‰¢ÜwGVý“cñËnÝt™üðtB§œg1èµø£ ——ˆÕŒBÐ8"'tZŒN@µëÒT÷tŒ…­#ë옇>yÙzØ~3ÌÙyá=ž„9:p~æzã%L Á¸æBŽoÉÁÔèÞa@³S{زWµo»X½³© Éü±ª¤õ3v„‘ª¦ã0]oâ„3©ž7|¼}\YU\Åñ¢|êÎo7HÞÛÎ&ˆ}þ]>ÛÒ·¾¯ ÎLÃ7Þ.PGåÚýöŒì¥Ú­9߉+‡ÎÌ°Ó?~»T³ª3̵R¨p;èœéÞd“ì—\ÈFÖ_:ðt²Šª“È„E{'5  +SSÕÓgc§”ÞѹîÑŸȸ6 aìÚs‘ÕñâNñ²Ž8Œç{Š¾–Œ¡€¦λ;yæ¬Fy\øB#O¥‡Üà +ÄkÄ!‹ }œùÊ¥ÓHëÖ™]÷oJXµÆµ8$©j5‡mÉ·3 M{òµJP›aßI&ÉñNäµÿrù»†@± +endstream +endobj + +24 0 obj +3035 +endobj + +26 0 obj +<> +stream +xœµ[Ɏ丽÷WäÙ@•ÅMR‰J™•ß(ÀÃ7/€Ì\üûÆBIQT5ÌÖN/üÂ>à90½×ým…ïá÷ùfÝô€?ÛôšœºgúŒZx1áþ¶ÜìÇwË&ÐÏô1þÏ™a ¯gß¾Íqk\ +NÍÌîá‚ŒOósÁಓ،¿ÛtÌ.ÿ¼hêóÝ,q¤y¥gò8ðЦ¸;]i<ãòÔô$¼ºXÅSOo°/óiÖžåƒÁÆôqj_ÿÙ½c†æëô*¬hJ&VÂÙ[g-k,-"›W¦›ó8K\­TÀ>¯° þúÄE"ð¯TXñMš×=¬7cà1hX?eTභÀƒ×€ê𱞄o^Ñ ¼&wt• &ô¦ ¾èͽã¨Óz‡™€‹:—|: ËÎä-›ö&ÀGt¾Bà·¸€^æ÷¥zLfM&e÷'«‹ y¦)6=Ž%Fš%6$Š¶…å(}ÄoÙÇøz~vŸ©Cž]Ç,ÇhQš"†§„ÙÄ·ÕSÔŒŸ6¾.#Þ,G ù_É@=íY¾e„âl߯?baš?-tË…Mùª- +G=.iº*Ož³#Ç!ö=yÌÚ +ØçòDâ)“i* +KÙK%¸R‰Ò’Ää±vòvŠÀ»§GvËäÇÑŸÖÕu´Êâ¦Fy³'Øé¨)¬Š‹JXQHø+D9øU™4ÚŽ§QФ @– ™lé7öDäå½Ë¥U43~'·^|Pƒ¡tƒBÓS +y'F:KèÊÃÛÖðJ>€7G&¥‹ìG2ö:— ~Äê¾ò}`Ó]yÇÞˆÄ,NÀv“%êÑfò”-Ò}¤Ô ÀvU’Ï)ë“·#±ig³1OfŽ¬•¦å‚„ÁY("4›Y¢Œ ½°˜÷¹&½Áù9¥3’aŸäÎ*n•ê våkúæÕ¤ˆä(È:Ÿ N$@µ?M‰)çéÊ%²¶ŽùTt“ßfïÉOPŠ7óç7òΨrá<ÛnuÒâ22,ðZÉž³*çÊB#f¶sÌÕB~qWcÌULV[ƒÀMºÕÃèŽÄe&ü‰óÁ‹×›z"쩳 \߀iZ  dQLDŸ*‚šÃìeƒPΩٷI©HWˆâÁÌ#¤à’Wweç ÜÞ"4‚Ô×üI© +³Mõ\5y矤P‰ˆ¸²rKugâ@P¢Ù˜½ NZ§o5KqÓ©!C{[­n’ƒqbàAJvÓ™”¼;^Õšá׿?Jˆþê}ù„8H‰–C,º„'ø“_“Š6q˜(¼êŽxá¾W"ÛSžFþšÈ(3;SÑîÙmõ”˜^¡rP¬Ï;öÄ›_§VTöÀèëu[Êõ½Æ͉8ÖŠ½½Z;Uò£Ð¯%¹¦ä]&(KTa‚–4©ï‹x˜„–déžÄ¶&‚¦&*›¢¦óÜtÚJÁŸó Çx7ËFcÎpÌÞxQZ"Õ€ù ¥?Éy06[Y$ üp#Ù=& 37Zïg*ÕdÀ†RD´i¥¶íšäÓîKQÄ.$Á”sánÀ½§¢zÇ8»¾®L5W +Ä·%¦…Z4hKâÄ_)Ï—Þ/µbNºè·¶C M0”Nb¥&Ùueç9r`lý3oSR.˜G{€¥)(8—ƒô¤•¼uÐBfɪ­»¶ÕQlô”³.|dz#J”Q»\<·˜@žMÓËêsqjþ W¥Ž’É?Éi«Þ)´ºV×6iFmãJ‡¶SŒ6D²¤].è6ŒÇøK¹Ï®yn{¥f3¿8p-#ÌüÒ¨ˆ‚â­\¡ÖÌ®m÷y¹‰¡+V<í°îquÿ¯¦ueF|ê”[o¼P‰ÀsÄÅ"VZ£TtÂúlŽÇ$ù„•§klöÃ.¼_wAè\#Ž‹±\êAŒ*¶HÕ8Ùšp—u¶>ÏÔ{ã9êÏ/¤WÍ*íÿam@èÏ£ÚÀ®®ÙâüvmpÔÅV{„B7–%D³ï{ªÐ¨÷Š v¬+Þ°uŽëŠä*»ŠQºÿ“j‹”)Å6v®UŸtd®^ˆL ÐÂ0»Lí¦eÃn]Å[¤Ön€sÇü€Òø´I?%žG€÷lZÁiƒêÑËVìëˬRï)dØ+`uúIû/xR…D¬Úë,3Q;8a‚uB·m±@ÚjQÁ榕7Þõ¡AGLß_¤J'×æ@”ÔI·àᄲ&uZy:e7rX'M¤j?é¬*&-¶ŸÈcöƃ\ßÑàÒ>Uü`{fœÞ6]¨3çYjup\–uT)H~(б°ª»RªT»—jàëRìwö +má=y«ðð_‹ÐR»6'»Z!û§µYyåu±˜‹¹¦¶Ñ|1ž<'&}<0uÝôºîÞjæøÀEJ6ƒ´ +ëÖ»‹S_€ о»™Cõ`–¶ËZíý\3ã€óv Bµ?ø(j/¸‹Ú|ZLiëƒuw¯X(Yq¨ÔRäIb-L)¿s:Så˜e•ƒÇÈU]2Ü¿9Ú.¶; Ü×̶=˜xÜÆã¹'ºé[ïè0B +Õ󭲺9¹}‹Ýßç=Ÿ{ G¶Æ— +ç"{•Ó”ƒ”IshBÞöR–ê$˜¶½^î“Ëj¾ƒGJjéÎpiÑÁé×ö„¢6Oê‰b(@ë­ öx +f*@b +rÜxÖ4ëåPiR íušnA”'·ªÓ‚4Iô·a¡&Zo|H§˜Pç1»‡ùÔ±el-+ýJ:³¸k®#Ò&BtS[¹âQ—Rþ´ž-­Ñl,lóŠ)€Ú•˜j¦‰¬Š=¿¼; ²ãW'‹÷ŽòÚd®,ÆÔÎ?ºðéL íAM/¶³ï3jâºeÇú£ð1M*O*ô‘£ä¢8TWSrBã(²—A:ˆvµY“͇â©Ý­måz"2þ…g‘¨:`óŽ§ø,VÞôG“®e±½¯£´â÷†wÇHÛÃûÎæ¹çQ¸ÒWæÌn45æ¡5¹^Ëý 9µ¦‰û§¥JÁpÓòIj’c«ô€ŠRïE÷Èù&ý¢Çe·½‰¼—OYr‰Ãîýè:ÌßvkSuÈÓØ9£q| +·>ê«y2ÀA"Ûƒj€ízmí#w/6ë8D‹"T¥”:$X#rxùPmdÕ(Z±ûmb8Ì”‹u¹³QéÌdÙÎئ$—šÝ'¼»5fÇœ˜KhÏ–îHn”Nj%éP“òJ—Òp…Üz©¼rÚl[¼ÑIâ‘*Ÿ,OÕ¹xüÆoñëkq‚ž"Á²?$Ïñ:\òN†{ž¹‘’AÖç‹žœååá¬óÂYò|6V·çl> +stream +xœµ[I‹#ͽϯÐÙÐíÊÌZ¡L©Uß >ß¼€ÿ}Gf,‘K•º±P–*EÆ‹åÅ¢áÝÝþóãß·áö6ÀgçáqÙâão»ýéw·¥7ã¿ßþñcÿõcšß×ÛâGøÀ¯¿Þ~ø›ó·_ÿó‡ïþcðw÷1L>øéþ¶ÒÓg|ð®Ã1|Æg‡îonøæá¯íþáñßžƒ÷Ÿðîoðòv¼ê'üÔ¿)~0Þŧ7†n3»ø7~Ó0ÂãËþþ6£h|éÛ„ÿ57 &ø<~= rõöct<¯¾ßz àñ¨øEQTø*<üõñuÅO‚ã<‡“cÀmQÛ}^>œ»ÿå×~<ýøc Õ8¿ +¬àŽ÷_ÿl^‘ÀuÃ{(À +Jõ™¤b FÏb²ˆàéì#ê +°OzÖx…¡Cè} ›&…ùþñÀHÃm†G_ +;&£ÙÅT¢‘y1;¹u‚Å£qF¨Ò œì5ÈÉ(¼ÅýmÑà¡>«d!ÒJŸ”)Å—érçÛè“\/¹DBǪ8+„&S=’ƒf½÷t”O·ÓzÆ7E`jx.Œo^V°Y‹'|ù„¶$懾G" Héñ¼t¸ Õž€=‰o‚†öäpÉõùP|Æ•‘CyžK1å k±†g¸;ˆáµ_‡»h’$ÒÊÓ7JB Òˆ‚qw`r^Ä‚ÈŠ²jËÿÅ€Iw‡×º±Ã½/ +4®à›Ç÷¹tÇ€²>Ìyu^ +Žå|ˆšB‘éï)Üd Q•±KÀW–^LúC)’*àùt_?”Í‹”Q@ +"z;»8L’c9X”÷,º=»™öqŠ||Ìä™Í£ªC¦hz–}J™ög·è¬xWhO<ÎZ8* s˜Åºg˜ø‚q'±‘¸jhr¼=ÞŽ0̸¦÷`T4w(ÞÏxÐzŸXFJt:ħCn¥Å4C¬[9–¤+5ŠIЫR7îº.W@†¥„‘³ÆZ‰ÅÉ|6óÃÓ¾G?/ ï0¾o(À|s# +ࢃÀIwøÛckóRP\·$eÞÃEé9å…{ˆV Ÿr‹i+óÎDÈñá½÷ÑhrrvçGÀÄk G±ƒL´Vë+Iq†Fª¤Q˜"»†_?§×iˆžFöä9(Z“®Ž C f÷ô…¹ƒøa´U&h +ÚB6žÉ•|Ÿ™š­õ{a¦ÓR¨IŽ¨?I˜°CÒD¶Z÷QË›TЮ“Ç™TKÖsdf‘^rþ'VìC‚Ž9Ùg üT±Ñ†.0Rô›üî$71L¿æÏ»µƒcu1ÛÊ®\-’J9®÷!ˆàí$”Då>Ów瑇¢—ý÷®›®@gj½_¸iØêa–@£Y£th.”É„ñ¨ÄM +k5Í»ð¸«ï~b{Éýi;JPø5Æ +b®0€‚”ÔÐP§\Ä~Å^ËÞ_2§5W-s]I¨t®Ë*³c/aêä5¨ò¤n5á€Ñˆ²#wgð„Sž9d&H6©¼SÌ;W1†~+î·'¤lì4K-ˆª¹Ú‰ §=W>{1¾…cÌE¾ïÃNðM€'}gmÀx…ûì«ÊC–Y5;·ò„´-¼¶†å°‰pw=nqKx„‡2Œ”Ò¼”¯5súÓ«MÝä©–]¾F¾nÛ0Ý’cj ®ƒØ\–×]âžn`8êž+ ïtÄpnO·äh5CÑ1°a§\Ìë‘ÃCPµìnHO™\[tÛ±TÙp,Aey…”j&“/•KÙùã?æ0¹-wy¸c&ê³_S¼8ðoàùiÇqmÇ•5…š[•Ö®ÂLȳ‰ºìnOÞŠ“:i\ªÞ°î>mz^×(ö‘¢ãp825B)Øÿ{7ä é¹çg¹îñáZ2Y©ôšµ2Ä• šnPZ!2£XÎI”+UÃu…¯oP²‡n¹.¦»©eßͨ@ +µÀVAk]cÃiªÑ:˜RñúüæØËhb÷‚G› +¤C§‚GVQQh/ÉŸõ9Æ1æ… +¸+¤‡šÉ•J¥è½ O¶ÉŒ?“®L·G 8”šm?®e…†.††½mAe!§YLÝ*âÖ>³ÒIµ7Ë&²¹¾±y”WÒÊ"VØÍÁºîGC5f û­¦mç„Ì~àîŸBKQµ9Zv#Q­e;ŒÉ9•”A¶ŽÑP·ð‰Íµòäx¿þ˜}Ôj‹©cã1¿Ô+VlǦíÜØ4³Ež„Æó"¯³MøH}Ùn»¿?Ûym¬9,{)*’¨tŽìØZpD†r¬òR|ÞS'Ã/ª°>Iy>zG +Á•ÌE©’¨îÀ´R3³G9“H¬fK;µ‚BFF:ªëM§‹ßºŒ>³|ÂNUÒbåÖú}°›uL;¤ÕZhz_­4{J#uvÉÛ¶‰ê]Þ,ÐOQ×4Èp’¢ù¯örÔ— Ÿ­/˜a&¦hr4Ý…ÔlúÜë³0Õ`]¡ë¦ªÈKñPðÂÜ$F©ÜÖÚ”Ë#‹ñ’J/3êèüê×ã´\sÏ}×/’×Ó'.eL8· ÎÔùçÃ5µA“–ƘæÜÅïJçϪ¶¸Ù]ëÿ +°ÁUU›4«>›^dn/ÓË<ýU%×U–ìíK^5­PãXÁæ[cðV¿Š¹hŠu(»ù­hæÕŽAÏÊóؾðiÁ暘]€ìÖ¥*Ø’DywòÈk‡j)Ré¸?ÉsÓÄ«dõ$ï8äµ.õ±¡†®&yáÆx#<kfÖ8ÒÚˈ_óëÏZÞS¯ŽµGtÓÚÖÖ«cÚÄgɃÞúêÖÞ’óöåìÆœøK´ZãWæè;e¯Ï¬%Ðrv(ÚZoØ<óÀ·Õö¦ÚÂÕû¦hò¶f’EL/?ÿy¶8Ve°0 +ÛÎê»jVN' -rnk†®ë0s¤*£JýŸÄÎP +Ô²C½eæ'}l³}Ú÷<Ê,‹ü†Ñ¾Pj~Å!Z%¡Îµˆs;º‹‚«.ØÌU6ÔI>¥Ö†ŸòÐT‰G3õyzlïÕÈ\@¹ÕëfÍ ïšâpL/­GôÕðt?ÝÿQù“÷b)p¢G´>i~ÔÚÉi +ÓóbM±0ªhã!»õNÿZ¨æÙÉKwmujª›é­þ•±¢®‡ÆqZ…Òªk½¡Öú±,íPÖÌl¥gó­úFkS +äsA­ئ4™‡ê§¹³ÝËŠ{Ø"â«ÛOeŒQc‚ýK·{11ÅߤítÝu¬Qº@unì¬=u`,šÝyãáÖÙIýŽÑɪª!IìqÕo‹ÖïgÚìÒÒ¤€RT¹§ìª¬z›¿²Àueœéô +>äb¹\¡¡Ñûãí¿±£à +endstream +endobj + +30 0 obj +3417 +endobj + +32 0 obj +<> +stream +xœ­[Ik,ɾëWôÙ žÜ« +Dƒª—ƒo‚9 sóØàƒÁsñßwDF.‘[e«ßCÐjÕ’K|±|gyúßÛOâô.à«“ +>— +?ÿúóôÛßNÿñ7ñ篽í_oÖ×Ó¢ <ðõÓ/u’êôõÏß?ÄzyWB]ä‡ÐøvÇoF\Å~y_>ä¯Yºåèæ.,Þ¢k±«=ß„ïï6¼uÇñU¸·¯ø¬Tð‰“IC/ùAüTÂIKï8¥¥ðËÂ?•’+Ü Áqübq˜w÷á'§ÜÒßð”ß½ä§00ªó×4~j?h˜mŒoŠ–Þöƒ§iõW6/=w»üñõ÷·û×Û¯•üÍæ:â‡/_ÿî=OxIqÖ^Ê* +˼^IÖ¸tUÉ߯hƒ5ïʦxI“”µ—‡¾ËO¹áy¿¬J^Þa Åà”òOK˜°s89ŒŽ¢Áñ¤mtQŸ|ªjZDú5ü[~6LS“䣙à]).¢RŒg•óbayKzæYóbÓS콬‚”së©£1øëj,šÝ:ØJ¸Ák°3gWì'$«“Ò²Hœ(lÿˆAaÂä° +Ž‡öT>X"m’®‚7¹b¤Ëú’°§B󻋲Ñ2˜ßÊ¢•TËd;é,³±ÄbYUà©ÝFxLÅ›yæ€÷ƒ©Ó/û(Tó9†æ+׬ºVÀgàiÑRq‹"¤*µ|p¼®ëÂ׃.‡à¸]ÜB¯âE*_)•nŠ$ö ˆ¡;^d뚎Ïl®ôŸICŒ_ÈLБŒ"jr?$;Cÿ³1"p~¶ªîdáùzkAî¤r8˜TÑrFŠ —óÖÁu¦z©½ø^Æõ¿&­ðû¾ðãHa}ÀJ7ÙÇLFÍý.#oúíÜ°*/­ØZÈæoOÙ|æ‘1â²&ö[Å´8£j¼CT•€fGEê=X- +Z3p•nXÕÁÆ“WˆKbð×®e¸ ¬Àp<õA„a¨6QÊ!gC#„òqt ‰@k>äKi§ÐiÐ;4k›™Å+Ê|ó‡kÐbŒf Š­a^K!|dƒM>ÒNT_ÿ™òržáÄT¨Lâ¼±ƒ&'"½¨âuI)Ôž¢P†èn€k Ö ]íÚº° + Î*–‰[Ò2zd¬ +.mÊ““1ºœ‚P̘-Ï·µË:îsF?ZK|!ý/cO£`„qÚÕÞ#´‡Ò=(ýèh3”•jªÉ߶aF'¨ñ²=fÕeøŽâêÄb’##·ôºíûû”©N(†0“BtÍÈæJtiì„?Kj0`†¿˜Þæ?÷ÁñÅ ©ĬpYÚÕHó¤1¶ÂœhžÙD›Û©«QF§ó„àÆBã'7Zøˆad +Ž˜å=I_;eûCx‡Š_z½aLX`TÀ#“6Ãú.<© +y’â@MŠH f -®I[‚‚šMi^¬©¤T{¶žU|#f¤ü‚¶LÈEN.S ogïÉÇOs‚ÊD2Þ|xY˜håÇêq\¤ªNµâa¬T•ö•.s`‹1Áˆ•®)Y=|A‰Iyì^yHx^¦1¶¿Bßcµ—Ê•·D)¹îÄbf™n§Ã~DÒz®»H< ›˜ ·ï[üf€›†·³c³Á¹v\lq°òxºÓ/]´§AHÀ1 ÝTÁ<¶6†ø@ÎÏÿD‡1=—ðOïã²|Д»¾ÏùKð¹GlÂhÑfC}ÊÞ)ÞåÓ¿´˜Ö¡fÕÿWÚéà(¬)µRÄ ‰£Ò´…³€®t==à¯h½{4ÚXc§=¥ç™Š_L™cVMGö3ˠ饃Mò AÝÊîï)aë½à·C1í)ò”ýŒ³´!½<›f^¹[›Ká/ÓòN­V][–æ£.¤cm›’ðnð·u»É—Töl;èÌàúG²˜CkâØš¬eþ2ªe9z…XØÂ21 µˆ&é#çÚ´½ëOöXÖíì}cì OÍÑN.ðãäcè-‹§ÑIl¹8F5‹“é=«_,¦Gkµq‰Uê¤Ã^Ç9òµM€bðùD‚Q-~´ 9«åc®q> +stream +xœíZËŽì¶ÝÏWô:ÀLÈ"©Ð0Rw/²30€FvqdaÀÞä÷SdÉ¢HJ=sÛŒ ôí‘ÔyΩ'©Þôå?/?_ÔåUá×A~Ž³ÿüåÇË÷¹ünú¿üëeýxqÃÛtÁâÿ¸üõ +—þp…85(§Ve–WwUƒVËpU›º-úªîËëpÕÛWpá¿p@OËëˆ+ðO +tÝ…¿ÁÀÆ2þƒZý+ôHÿð›ßòêo‚áo<®^þþñ·—ûÇËw­ Óø6Ó +&ZÁUieÔC#Zã¬günô¬ßqAwµá,z¼å×¹‚^Œ¿„C­ê1q¸pëï;úůMa4/Üü;Óà<° áГ»ë¿Ã@“8"aŽ ¢b÷zCKÀà}üʳÈÈCÁ¶›!Á°ÒG-ëÞ†Àš6!Äïh*…„<-——¥ƒ~S=›Ílߦg34ôl¿ªç<Úÿžþ!«§}7êZûåôÎð è9Z|tõR„¼Á;:D]C\h}+¸ÕûÁ˜¤R9‰Í胠þí•_¤gõ óÑ£&F:ëÛhåá‰9ý2¼ê ¼~`|T(æV‚gÅà]ê½ÿª™<£Þo¦­QxÓµðIÀ~‰BÀ~•ÉF¥ñ¯Ñf|;f>·ÏhˆÏ;ÑO¤þfô£"+˜(޽Ѽ±-’Oíò,",O7-Œ#IPûckÞÜ>á8úa’´õÏ゚y~•¤ <ÿ%|?"Œ¯ê¦fmñ¯n:3ÌŨŸIh0iªÔó0wüÌà"ŽÒšÖÌ6+lL@ƒ'‡ º‡ÒÌ^äÐ%ºFDì}]TXc¶¼s¶X?îÕ¼GÒ°Ù¥0¸ðU¹ZéOˆ–•þucd=V@€ºà+Ĥ%ÎÈ‹PõD‘)"ᤔ J® +9“æÜš¾>[óUÂèƒSEÕ·JUµ!5|Ã)§Å[ÁÏNÌdxÜ3©¢EÊED)Y•Ï»VTÄWM|bïÙ'H•‰AxQ[ÄÂèÓbƒ¢\€ì@ÍÒ/…ÝaÀ*+á”nQß:XðMØ d@ýˆÀ Œ¨ +ö‚Þ¨ãïº-6h*ãDJfru­¹7%Ì×’É'<ø9±˜¢¡“`úûî“xMñ½g°š“Kä½ .*hÞS4ÈèzžNðÑ—¿î£ 'oäxœË&Ãé—KÕg=Ù·T†-Íf«Ÿ¡@j`Ïd2ªª†a÷kY Ê{¡Q|ì&éwœçä×pl&y¬:ûD1/ +2*qƺ§Ø¬Ð:Y¬)÷ªÎU#œ»9Ðvtœ>¡$ûŽa‚µß2ñL™h]±¼®Ëá®/1Ë­a=3=×m¡Ð Ù÷ÓņM«ŸNÌõ {.³#Ò úv6v@ÆEk¢íĽ¾ó];¶žyÞßÔFÐ"% +-—;ÝôÊ÷_kZÎxT®®ýŸéOˆ-£Ôñê×o©äç¬Ñ( ê¢ì¤ÀÐhï§Îfj>Õ=(±_¡œ}«]5[4~ŸæÀba44È:af]Fú†ÊEè>…=¨_céà1†÷e°×2‰x¾ˆmVtˆO6ŒÁ¹F‰?~)®ˆ±¾)®02.8À¤—"EF`Æ ü} ÔY£z&´ +)óÄé)Ç¡°!Ã!º0Æ“Vf7Ë +Žñ–¾]¥R¹¢“^9þ(üƒ@£8ŸIت^·*ùù[,TÓœ0Ù¦¶z3$é3–ž}·Åq‘ˆéý–úî·> +stream +xœíYËŽë6 ÝÏWd] ©HY² +Æy,º»@€.Šîz[ ‹½›þ~)R’iËŠçÕnîLO2–h>Îá¡2懞þ>˜ÃÑÐ[H׶×o_?ÿpø‹o†×·?ž¦û“ó§îÐbC î¿~¼áðpÿý—Î#æf.ãÑæ:Â`løËdntë躘ñˆtÆËzg¼,kâFÏ&`À3ÿ¢Í¼C>ø` +1Þ!r/. +Ïd«èÆc'oÅÒÒËê98…˜}¢ÛÁI¯#U ¦íÀÏõê±d/>W?S–Ò¶EŒ  O¤kôø´‰}K ’=ü)zêuNPrÁ&Þÿëý§§ëýé˺„?ù’Ùñþçæ.:˜“]=Æ{Ë$¯1r?¢¬áÈß!P^βá,É¥,IB$¢ž–ð›sʳ*ûYmbeÙl´­ÊfUE¶Ï †jrCª|›sÛ¥Üt«ä·íNÞ”óÛ€@Ò^Ñr~æ²s,èЈ· +cFˆDˆŽa!¯WDØÌpÒäGÊŸ +K-.±vˬ]7¨BC› +½,rÇlgnLrá€jNOH&ÉëV¶S|6å}•øÜTÞ5J\òSázðöÌÙé ¨ÈÔ8ª¬i—•}k¼ë Öæ¸$~î›Õ PNåIÇpøÒOlU±µ¦Ñ[ pwŠ¶D*Üv:o*Jõó7|LÜ‘ÒÆÚHÓ=C+8ã#U0Ƴ–S¤Øœ{p¨–&=¾„ó¢0E뉩{œ,×¹S¿Š;‚>Y®í§¼9½?%(Zòk‚Ö\Ikië)ã[ÏOMK“%$põûZÂ#õp‰ÃZQ¼åBQ´uô†+ã#i®©7ƒ“ê&}ňƒÜ3X„§Y·¥U—ÑÆ΀ª—ÆàšX?Å%vìÕ¬ve¨VkhIËdï0ݵP°âAu5–Ê^b8ç$N ¾­Ç`-6è=E¥\Í@43)·@ͦ7úMNƒ«ÄmM³´6îÓËåöÇ!PX•`4ßkÈ3%CM—Ð=©žº +I +r‘vFR +Öm–tt]wûífó˜m‘[‚þŠ™77Ùi‘î[–;•NµãâT¹³œ5hS£qªÅOÒÚ³»TA¢gì÷É +RÃçoŠ£Ér”®Öõ4gãUEïBS-J¶Wã©—¿¼Æñ€á“ŸS*Ù¢Ý-ãÜRÅy¤ì‰•i“›ý<ƒ¢!Î>Š®iMõp’™t¿æ %í¡qHcÃzÊœd¹$~¾YÚÐCG(¼>3Do6ë0ªsR#VgÐs60ÏÚS>à +ö|†©Lc52Ç …˜å”K2D˜ +7ì3Ù”‘¦Ux<ÈGë:"À‘¤•)Üzcƒ®†W;Aœd'i÷–šÑj{;IʃSBAŸ‚ËÓ­ì¥$ ÍX)Ï™ +8(J:›ØÉ1Ð!dö!Kàâ$3xqnmjðõ±ééÃñÎœ)t1PÒ%|/BÓ"ÕÞ´æBD2M‡#x–É‘¼]IÒieS‰ô’90Ë6žcƒÊGÞ|¨R€cÉPyÓÇçW«5{9¬©N6ŸªÍ¶8<`dÒü5#1+X¯¸†kuhŠìí0Çv¾`²¨§üòœÃCKL9ß'÷?€2¸dŒÎÿŠ5i{¦ÌVV|))/t!<è4'º`Ÿ ä‘¥#*ÍpñÂ=ΦïõÉ~5½¤9ë5ã +´H×Uïb®.ˆ*$}CŸm“q%®Žç¥G¨0¦@ÅŽ¸>êØåIäͲªl|W²³´Ë ‚<¹ò;E1¤ÐWˆ^ +$.ºÌíN×@ßžÚ5fß,§ù›#9q½_Kká#…ô}äZX(iñNùT6?åóÕòYfoà "|Êçÿ)Ÿh°ø®ñÃä¨Ïõ+ùléÕ=±µÀÄ;Ä“„2iñ›ÅSÙøŽÄõ¿N{ÛÿFMh{뉵 _-– Þi}[}ŸÖÿúÀꡤÒ;w6ù©·¯ÖÛ"yš5_ÿ;I\ +endstream +endobj + +39 0 obj +1550 +endobj + +41 0 obj +<> +stream +xœíXMã6 ½çWø\ ©H}Ù€a ñćÞÐâ·n ôP`÷²¿¢äϱg3½,AŒX¡(Šï‘"e.T}?}­Lu6øˆñŒ<¿}©~ÿ¥ú7ý)ŸoŸn“—ºŠì ðø³úuàŠ¸züõ¹e×qËlž:j¹ïÎQGLo#fÀžcÔ‰€ ÅÖsÔË?¦;ã%@´WQÅ›WySËÿioå‘Ľþl²\Z³ÇGÌ)äéÆé¨Ç€íòû9È´R7bYc.ÍE`±¯ƒeÒð +`:†Ï¯iS»è‚#2ûèP;†ý[ÑI¾L|ÝA‡^'§?_ïÔëvŒÒÌ9NÀ(r­Û|!°}pÅÓc`ß@Ö„³çx‰ÎÞ4—𮀞iøÒÒ®1ÿ®žiøÒÿkH;› +6P¢göQX;Š›*âÝam›æÂ+¥†V©rÐÂZVª_ئEæâg3W +tê£MZþðÌeM½=óÞ”¹f~”̯úÖÞÕ‚ö½Tß䳞§×ð?å©kjŽ`຾ïÉS3 +?RžR‚bÁ£ K,2šÌ4Ùß,R”q¤uiA ö(4Ùº·–‡| ðLAá„xJºˆòCƒ 8ú©Á»¥Æ,÷¢3N¸Ü¼.´3é4 @qZùƬ¡SФ +)àéáä˜ _¨;tµ,d©tÑXEúáD ÍÔû©'ømë=ÙÅ m‚PÛéUóšzãìú’K$TÞ,ξcÍŒc¬–t>­qH; +~¯Ž—ƒvÍåp²-t§q{3"d·3>ëI‘">ß´ˆÇY„/b-CH¸I왾Uå+.rÉÂÍéŸùÈT ¥ëœ-0Ü9|lo½ööBZ";„±nx"WM±ØÇ1®û¸ì]©µf‡U–à)6ÝQ¶5Âv|acÊÖ*ß2%Ó4l×|Ð ãÙâ.lXÔS7„É;.PQ©wsXÍ.²Š(XaÕ;kaöÓÅÝ,Ÿ¬oõÆ«µ)+é†lÛI\YTÈŸªÿ÷Kt½ +endstream +endobj + +42 0 obj +1094 +endobj + +44 0 obj +<> +stream +xœÍX˪ä6Ý÷Wx莪ô°ÆÐv·Ù +4d²Ë$E ³É離ô°lË×Ó™@Bs}mYR=ÎÑ)ÉêÍ_—?Õ\Ý:@º¶ž¯_>7?~×ü!/ù÷å·Ëøº´ôùõë—æûÙ5`š×¯?õÊ+®Ð+ ÿ?¿~¸<_—O›¡¾«EhÜ 8¸îÃU÷ʪ‡Lf© 5 šA÷hù˜ðFÍGf¬»uël2Ô5€d¨CãœjU§49lÕîF5©µÞÕ“œð`¨e„VYºóÔ6 +¯ß«ÑàM7ι`ƒŠ&x®ìULîA +WjqÒ†ˆ“A£‡«-zda¢D@N‚ã1•æÐÛP[¼‰]°l4­ýyÚ`9{œzò¼¶Ô5¿r48:0Å΃¡NäAÛ'«!¬. Âä<˜q +¾ŠÈ”zðô'ïì.-Qj5t¶×†ïÑ…œÅ²ËD‹#è +ÜìšâÃ@‹7Ü Œæ´‹™·Ð%ø$a!Ãû˜9˜Ç’wöžIL,›ˆYsÎÕ¿#_¤¾š¼°H‚€<óz~Àˆ=½¹+#ý&åY³¡ëÿBØ:Ñ45¤åsÑè©*(pà´·S5Ìês¤jbŽ}­Q}µº™¤oªü[¢fÕ­­@rB{Û*Ò¯“µ&eŠmÊãÈ¥ÖrÁMˆ[*Õ¡ĸ5—E¬Hβ^qœ¥`a¿‚ã@° ëU‚d ãN­ *Vâd +Å  Â3½’E\×,Ñ«E²q5A©‡… +ÓDg˜ÒµÝbúždùþÐ×#ÍÒV·z„@ñ"<.™Y^ÅQÛ…¬LlgÅ’, +ÿÈ\äÔ"P_—BÜL~‡Å‡Áv&+ö±™¬¨d’Hô…)¬¡™<š£‹u`æè±s Î#Àý¶I¬6æ}¥ŸX‘OîWJè¾ô[AEPfEM床cM|Gû•êÚ;Õ·Ð`eÙ;­vR +­jSæÞ,…w2ü”bçùFvÚÛsIœÐæ§'Ä>¹\†âI.⟜G^T8K+õ¤¹ˆ\xt6°Vß\ÍsBñ’Ÿ5>`V'SÕâ}xàÑDR¿Mkw[Úÿ¦~Óªš„‹Ú¿wêEš7Éj±bË“H.S +I¨ÐG~ÞˆÚaM¨ï±áÎF…„˜Ö­0o,ÇuÌeÓ1Â;`NtÃ8Øm^e7ôÏN ³”Û¬¿¦<.ÆwQëŽvE÷ÐÓ¯£žPƹ£ñ¤ßòrN ï2Bí-Å{-Ü‘%ϼe°YS´©å*“v-¥ØE¼gM««@›X–zD4éÿœ34M{Û~0`)’cŠ5d×òÒ§jÇÜeRó—G€’š½¢§ Ä>…KžÂ>wÙ)Oú Š=@[0¯¾ñŠ”<]a«²U +Ÿ‚$ø³›¶óõíênêÖñªÔPÎPÔš®›]Ø· ¡¾7>¤{Li®å¸b‹˜?ÊÞjfˆ8úýEîÀ†y1|R"•ÛJ¹[›ã(êÔæ¨<Ééx2 å/¿PåÆמ(Rà‰C#Ÿ´}9ùF´Çð tTÇßÎ 15Ô5„·ÎÒ®(¯‹ÝêÛÈÑö½þ¹áÎgcYýëÜ·Ÿ +j_2>5ÕÊM +endstream +endobj + +45 0 obj +1379 +endobj + +47 0 obj +<> +stream +xœ½VM‹Ü0 ½Ï¯È¹0©$ÇvÁ0I&‡Þz(½õz(t/ýû}’“qfÙìîZŽãHò{ϲlª¹ú}øUQu$t ÚØiûøµúø®úi?õyü~.궊ÔÂàò¥z?7íûÔó˜ŽÒÓ˜>_>ΗÃÃ×èênÏ•÷tJNao­`€‹ê¬õ»±À +m¬}ŽÍTuˆÜ§Ëç@ñÆ!V,…â29B &êÀ0S:Æž »ÄÔÓ` ÏgûŒAíÁtùl“ï¹Ë&Ì z ¹tªÀ#Oöœ1­ä_Ùe^§,3ÊÍ„Ã˪„®nîR¥8ȪŠÌn¬hÞº*>D N5‡;¹‘£ÅÈäLG©õ½³¥”eI˸SH”¨Éb;H!N¿ó™ºëÌgÈæçÛeØØŸFÒg€4¥ÕÁðbeÓ±ÍÃ|~Y?ϵ»K¿âpÕD¢!Óo VDÆ•ƒÁSD+yÎYo ½8PŸaXÍâ³÷âkÑyÚ#kÝå`›š‚„ŒE;Ð ïIN;ÈmŒ+I¤nÈ@¬á X·ÁÆ?ï”)“5b€µ‹µÒL~m‡;©å®µ(e-þNø)é¶Õ" ›œZH…]Å9Þ¸*îÉžöT–&ÔáYøÿ\cvk…~£ÆÅ¡¤Ê_Gg¢EbMèuZµ,¾F]:¥^¢îP·\¿å.ꪃ¬þmÔ}wW¡¼š¯´y  'vèµúÎ"à‰Ü ¶{¤×Þª7%êÿ£¶»‹xqØQ²Jëüò +s”mŒÿGÔ{´÷-OËǶe`9NOsÒãž–Cncc‡mørÿÈ'¿råYòr[hËá?S.Túƒ‘ÓúCÖK +t³a(˜ NäA5͆v¥‰zj‹[.×kÏro=–õÀ5(¯Iëbï’¶8<‘¶Ó9 LêUÅîhûW‹œ#æšsãlùôL˜\ȨaSÔ©p}¨þL> +stream +xœµ[K‹+Ë +ÞŸ_áu`&]OwÃ`¸íã^dwa ‹]E w“¿•¤ªR½º<žH×î“'?Œ‘êß +‹Á=Ž¢ùý=ÏüŒ%•ì¦Yøæ4²þQóÈN€»¦-±3”æÿ=2 ;=(&â¼® +dÿ…ç!=HdÓ3R0V‚jèpž¥ +¥ÃðÇ_J`ùYˆuwø wÑe}¼A¨IØ;),6jNKƳ&“‹ÅPzÄHË!2bSXÀ6£ f+¬A™V©È+ˆ•mDnÓzm饽9'W +Mú8˜<"­Nz‚:2Ö -md£=ÿ­´e¡¸¸kËî©øœÊ¦Uæ!¼`Z ,„]Û~åiTíEÄtM¶'&m°Ï‰™~(Û²ÏÖgiWðæ(zƒòë\¦C:D +U +€ìØòPC6ÛóÛ‰ýT³ d“®ÅÌ€ãsF+¥ )-rÇ7Ę Õ#:DþT¦ôÑ{öt{!–dèâ™èÖ›—à‹ç’b5 jžiIJ´L·'‡¸ tmÂáFÉ1mó‹¿Ç<°póì*HFDÖ"•+âŸî„¿ìœ!F1Ÿy.»ªÓ´Xz¯äàÑç—®+É"ª ¹òäAâŽrø¸N+­°¤tO¤¬Sfm8­ +ò’|ú%MPavUZDÊìñ±DpxIÛí +1¨õD +­¿6 PujÞ69m’£ÒwR!Ö‚Uòi¦Î¸ÖÄRöY'_/èaòh”F?"ÓKžHB5\«Õ +±á°I‹r\»ˆFøYyL7*ÇãWªz˜Ìqe&ƼŽs-§Ek¯3 +e¨úˆôX[L£c>[‡rÖ™ü7 mz”¥“ +C~y’ŒÔÀº8¶E ³ÆD³L’ÏEP–ÛÂ6³Lj ÃHÒl†°Ùfñ-bþ96T"ægKÈ×ÕÍ”¢Œþµöz`ën•6¥] !¢LÚ:.(çHÍ…#’“–Ý!³9røÕ%[š“œÓüÂúà¨àfHë6¥?¡èóBn¡¦6XVʈ†ÎWXAN=KŽ4«–嘦\ŠŸU-ÁÁ +Ä™À…ß,$.bñþ̺R-­RKÜû„Ó,µÙé£I?ÅbŠìæ4G9íCÊkǾ(gök“ôˆI3GlR½l¸zki›Ãà ZW0¶dQMð8Ä‚C©td>‹ Ö°|Éx `ÖTU^9ŒIeDieÂú ¦4<¸K:ò@žÝu²\ßѧ•L£¨­lMm#ÙJéqts§þsš +íK“ò4é–žbòÐ.ï×&3¯m¤›ôæU +RQÔ&Ebh8©íÓ•28åÉ“šL[Õ›nÜyŠ´°?tjp +AL¢ëVh &‰ŒÙ¢5ƒ×·E¬|â"ãa:¥àü¢PÑXy'›è˜Âr—ÚÝ–ªÅÁØ#–¬JΙ*»:69Á;=H=N—Ös0wKùrp)G°òÅ% +#ül’ÝxÇŒmöÚAh©ëT9xïÑXžSÜ»`bGa“êq^ýÍ|à)ŸXd,½Lõ5¶%UìŒWs^+ù[2!jS§ZR‹ŽÎÒ,ÁáÓ™FÄ9«ófš)•«Ø1f¹Õ9±(òZ[¢å6‚Ò<•„Yõîfj®Ú*ÊsÜ­JkàqP¦|PSY*ó½T©Rå—X*à·ªä15­TÖ¬­6ÜB,úhËà_YïjªÅnöÒÖTzÔ¢”€ä¶A£ó!ÓÇß'‰)ùø^-Ú›8Ÿ…>õ|îà…ú¦n±|­¶÷)Ÿ•ëmà èzmË,}ë:Ô ’YÖ©K)s±½{FÒ-C´‹¢ò‡+Vô­²Ap[6×TëJI'¤àÚD¥?_ÃN´lv*sûóP49špæú¾u©Â¸µ¢4¨³“q‘p•ê‘èÜXŽ&6q &[üˆ#ÍιB¤ÂUF*UM¤UžBœ»N]JÛ¤ÓÐ¥î²áÙVÙ;U©«uŒŽ‡mi P¬ÁämGFµ]ɺzŒ+¥X>X•» +ži£“°bÞ—vŒÛÏ&Ñ$ŠÉ&33ÉÞŠ£&=±×¤.*õ Ïi‘êrÆ--›qÝ°þÌœzOàô +:30;½8«QÒVLA…{ûŽû*±ÎÖð<£¨PŠïŠ†­H»`äG„3¤b–Î)×s +;̽Îr­,äª_m%Ÿ¢±A +stÿ\¯šÚ,¼þ_{Õ¸]R-é<¡,§À ØGÙÍ‘°®›-5˜lCQ´?‹nÌ’–A¶mÎWJ`Î{xž)E5ç¼7­ýÄx@E#ò¿Gµ×ÆÚ4%¥ŒƒÕº Å›/ö¦5 ·‘æ¾Ì·z¦£àIGn ¥rÛ ¶å©n_Ì5ŒÔ3Y5)ÇC©:áÍ›vÂï’ç/Ž”O s.Øm‹á tï߯½Œ'!³3œÝc¹¦-û„’Ôµg‘1–ö$sþ¯÷¯#5)–FëàéfÆÑ¿OŸEã>sŒzéÇTÛ½W9n`„×¢6ƒÙiàÃ=Û´´6›ò4€›àâ[j›Ž™I.Ó#¸|¶Üiäñ£ô¢Ýde¯[Ê"w½ð’³Œ;Žm +GÆÑ©¤ú¥Z_,íœF@cÛ”‚;;CË{©Î•Wbí¯JàÙWäÚZEø9¾¥2]’lM-ì#5_'ï Ê\vX5g!A¯»õÕ~¼êÖ’ +tè¤:m 89¡ð±Ï,D×µÙG3"&mC:¶ÿæÖ¥˜Õ¦ÛšzìËBŽZ\‹<{ÚFë+eŠVI§Ö½¦œ¶TH¥ +©¸"ª— A,>׫B»‹Ò_*થÓÇÇð|âK? ÜaŸ½,­SyŠ»vnž\e8Œªl¦Ð4«˜V>Ó^5˾־Å!ixT“ï°¼\ÃØAeãÖév{ú×NJÂT;(ùéíIà]™µµ—öð¶G&jvÃ\ô,$T?<> +stream +xœ­[Kóº +ÝϯȺÀ¤ÖËq€ÀÀu/º»À]ÝõtQ wÓ¿_J)êey¦0_&ql‰‡<<$5ÓU]þûñŸËtùœàå¬4ü¼ÝýÏßþ~ùó.ÿú¿ýócûúpóu¹Ü´… ¾þvùã®/J_¾þñ—Ç´OfÕ½Á«×ϾTOÿÃiëÿ›ÖOí/|¯Ÿó#¼5Íø¦6pÃç¯U=ð¢pÏiƒ÷îë|{(5ÍÓ¼þõëOï¯_‹µÁ²Íå6ÍÅÊŒ¦Â +?àa¸’ðöŒÏ°~ÉôN¸tSa…OXÕ§ÃÝ„ÏuØÝ4ËýÁýý:aKÖßð¿ºxÛì¹ZÃsÿ+îZ,ÂÛdŽW=ñ»þöÞfas´”v«‚÷]þsáFØ—è÷¢ +Ü€—F¦‹šñ]¶MùƒÃŸP§tøîu®€[¯_ÿj^ïiØtY\Ò=þoÈô*¹‘Z9øÈ/qF¼^¼7;mŒ• NXOòSò8¿¥pYº¡ª^?—G²&Œã3žüqòU;‡øŒAH]éP/ßÄ~2—Tã¸tÂîˆïl° Ñè3}áÍžþ É¥{ÚЩ1z[®¶Ÿ/\¼Œzâ;sÍ`©ÌH€©+r¿É|†_2‹àhx=I‡òO‰ç2tšûø6è›ð…)}}IL²±;¡Ï™¼®Ñ1ìŽ×ÏÖë¡îŒG½q„úl¯%ûž ZÑFÁר(ñd _Ɖã1>†¾ŠvöL£œ "I°™Þƒ[…‹OmÄŒñð±kÐјªƒ%E:ɦMŠù‚ªÃ2/cÖü)Asu +˜F¸º ~~‡¢—2‘Õ®VÃFÞ˜’-‡˜Îä{gf;g:f€<ÑO,%Ö¿Ã +™26…È F÷>ie…-xé¹ezaZ¬è— tÜí¡÷®~ÒÇqºÞ°Œp4·RµVìá©"Í«v3å!y´Êeá!ot‘ÏB\`ò–Ñ„Á¼‰µ œ>ïjòt*Büè!Xä'TâÆ…ÐöL¾…ìÑLŸ¹æIïÈ•Ygyv‰àÍ*MG׌° 1Y@3BR›Z4!%™AËJÁ"Z"¥¼ë%¶»gÙ0Ø:\Äì4¯nz ÖH®^•ä…EÞCÜ#«F=.’§zgJ”ýé>¤ì´ZC´gîjŽw%Éó’Õ|v¥ÑQ,AÙHÓõÖÀcàt¯ì&¬FùûÝQÁV“JŠ—›t`£€a}"2#úl™êM©Y@ÛËh ­áX;A¹±†K%¯pIÒ.ñs#ûŸZûIö‰Œ,ª­`Én<º:8ÝÝUʇë¡þpñw’±g꜀ úÅw‘K%òÀ³NSw‚¤Q:¡Ñï@®¢$uAná­~Ѩa:(%µ©î¡›É¡~ý33aÊš÷z·}à T¹5A·¨JÜT~í ƒŠ‘dkøÅGóòøž £~‘îp`>õÂÇê—¯¥~ÁÛä8¤Ò!î‰Ø°{[χ +7›k%#nP›8LóYœ¥Ò¤½ŠI¤Ôœ]¶¬ˆŸH¯èBÁõR»Ç´À:¬ë“O~W`†uì«[¨M±¥R.nŠ`Ÿž}”Úø¼K^ âQ Ø;|­ˆʼ/t'.ÎíÙjMAÊQ/(v®¯6JhiÏ"'y–¢ÖX*«„}ÿ€ C +/¹Žø{PŸ6ì4³Êq +Âä°9DüYË…š'ë@ö@([ôiïvU +G›¹îáý´“5ih‡l69tj­4*Œ·OÄS»`<ºŠ;ªË#ã7*ÔL–î‡-ÁsU‹\L² +UæÝ_¾ÃrLð~£ñ~:S +ꂦ®Ú“t+Fƒ~’›m˜Dƒ‘CEª–(PÕJ3G¡øÊêboS÷­Ø+øÕ+2qÙWof5|õL) ò')ÂXˆ»QžÊJÙ´ËZ˜CAbïm@FN _ÔvXS¹œ3¦¦"],_R +øeÉ +¹l²•÷–ŒÈEƒ¨Ò¶¼Ë˜ +qb%ÓŠVÛq*Ⱥí\! +C¸hY<œ‘¶ì±ïÓwºj¢–£â Æg¨½ÛJ1án`+©³3H-í’xU3ôòfŒœt¤òWlï±íEÅ Ni©MÑz.ÇMÏŠMcÛ.kJÚjÇ©Ö Ôî®ÏÏeªÕ’¦4BëO r‡²Úκ.C^Þ©E„‹XŽ^ ¤M%5Rð§tªwL?i5n#Q§Ú%ÝhSYǾD‘Ôêä!Ikî.˜jÙ]Ç:´’ô«eTy¡g…WÛ.òÓÍ#_Ù|„¼-q'Î3)Aî±­•Ú©ƒ\ìM¶õa”Øh¿2ËMÓ +4ð¢å0ŸlxÆJÎ3†ç +h¿´RBÄöiµò‰_[í·»-±i+Æ™îâd©Á€Ý.ηë|¡Ûý;í®¶‚g„¦qU5PSXÆ3¾Hà%Pc­¹äؤ®&‰â¨@~®½éJGÙú*fŸ^.3•÷§èNÞ$ú„ÒvþcÂOwà“¬ò$eØÐçÑ‘I 4<¹Y´Æm¦®ZU½UÉdÜ’*+ÃFÈÜlÜyKÔÒÇ‚ábY¨ä]V§'ƹÕÙjjñcˆÚC—TPW6ær1D¯4˜îs)*ªaôJ@ÁeËô'‡Ð›æû%ùÑžd^Nl¹»ö°ïõáR‚Ë'‡:‰‘Øí•…¬¨;¹1À"ÈìÁÒ>x¡"4B4ÏV»ˆmFlr§è>¡·êx@TÊÁ´±…×`s7õÔ¸0lÞ >êáò¡…æÏ6ÝëÌò´ $QÅ(+@` ;cµØ=©Es·ð'EK<.§—ºüw‹ßa˜Õ¤x(S'Žûžžƒ%ù/n7©ª<[&²MXг=´Ê/E‘8ô£ê/äpó.§ØZ#xouÞÌrIÝë÷ªa<ýÃÓ¬xÏ]±™‹F¦¢4?áÍ…œÁÙAcö= çŠÉy +ÓúôÄøDÐ8x?7SÃ5Â×õê÷’óRC"LëËÛÅL[|ú3 Tíòa')¯açš3ê®)ú˶t@ªqí+…NÑØÍ +O“ÇïöIë&º‘‡ŠÅß!çg¨àçb#ˆm£‚ÿ]: ±#¢î3`vF¤QwrŠŒš%B~ò·bû¦97ü›[æéQ¿›‚G¤+š59áD:ܨ$Î3÷Èì|Ÿl‡MLMt> +stream +xœÅZKoãȾûW𼀕îꛀ À’Í{›¬¹%›`1 {Ù¿Ÿzõ‹¤%jbm0ÙEVwU×WÏ–ÍÁ¿?ýg0óÁ_£ü'úüíÃ_þÍ/éßoÿ|:¿?…xHÃh2¼ÿ}øÓìé÷_~>Út‚£s§gOŸöh^NÏp4þj™¢í†“?Ú™øÓ³%ZžÒ +ÚÇ„²ì¥¾²–ð +ùó픎fæe^ð;OëþöþãÓÛûÓ—Åðxnˆi<9 øÎdo^yÔ×àâÁã©ÂÑ8zMO-x°ÁÌö‚O,žl<æe3›³üdVÏK#³šÀúÁ™–9^b +*nˆÅËcz˲dÍ…6—‡b6Ð:edYÏQO_—žÑŒ¤Y”å´ÎL²Ë,Ëm*ª '®™U1Ü5Êögdbvpx¼ ñÈ‹Fçl UZŸ¼~BðäIk¼÷_7Wð‚ÑÆ%l‰TCðR`wB…"›&Š=Ä\E!±¸]Þåæ}˜Cb£õ<·ÏKed8t„ˆ.Ŧ'Ê !‘‰@‹hÕ Ûð†½v&°WÅä,AÀªâýFéIÁä³\tÍuíykQ'žÅªçºzÀ‚èÆöýc7!XkÈna¦Ã´ÀX¢*{#‹=—¸P‹Yd%/ÉéYIÕ%ô¥’ð÷YN²/Ê?Æ‘rü–[8ú˜ËDűSkÞæå´g}ª§NKn¯'²+H<Š0p*›¶yziFdl®@ñx44+Ç:ª0Ú3Y"iC9³bKUžWt4È¥ºÓ¤fUšš¯Œ‡¬™…ÅKß’ØíÃKs˜Œâ°ü‰Ç²cÄ6ÔN4Z|{²Þã)Ô×A(ð–)0ö\=¥œÝ._‡=!rb¸¿ü™5ûÿÿˆ`ÿú y?‰†Îµú)èn0`Émw(è9Jí8!ß‚X¬0R´Ö½¾wYC¿Üyä[Ù1… Re‰à"ñ +d˜9‹Ñ¾= …*FKiEe¶»\‡ì1òö@nD°®@&ˆ™ï À¶AËãâ,î°Ábi†9eÜL7ë]ÎÁØrj}_¨l:͊ʆlw¹ÜcäíÎaJŠ5n6,ýPùs$Á86ž-Tölg§Æ—{J9»]öDÒgËÛIipÆ<*¤€mÎ*ý9ºn–ö™›Ê/2ow äœm,&T±X +­ÅzJ8»]ö ôÙòöç: +½ +„¦¦ŒÐÄcgÀÛ9,}ΈÉàPAïþÙ-4áíƒËP®ð æ³£/Vw¡¢ƒy³¦@Í×ìr®‡ÈÛÕM$&õر,áÊá$vs.5¤Ö¸§µ röÑØ9ã[ÂØXhPJ­ç\\SjËv—Õé!òv…ÚH·‡[صíÃTÃxÆR¬šóå=PÂèÿ(!2ÊäÄ´…ú: ­,=¥œÝ.·²æ#äíËšÄ0€aiÒJD~PîÍ1›î +Oº…@ú~ãö&SèLE£ÍÓ˜V”rv»ÜŽ‡ÈÛÕº9 ‹& +‘Eb³@ß ‡£ïiÙ¦!Ä”¯5ꎳ >Ø?“¿»B5¤!ÿǽ<:N-Ïnj˳RZ}„5¥å¹Ýå: ‘·o"6U.Žù˾¾¾d÷Öúrt“$.™JÂÝUÆ[ºÔpÁ¯ã(V„´õÐZ¦³ÏýR°ø.å^–y¯¶9¹û&,±tND‚PN(BåÔ#õTNDí.{üã³åíòK=K°nݼTÀ`fSº{ 2œPÍz,žµ,j‘„Ë©z”©x?L0¶a%T +ëÚ@ê(åìvÙÓgËÛ“£K¬”Öq5q¥lJ>ïŦÍܺ(BaÏb©p† +ʦ~z*w–úô ÐÏÀí-²¨S¥Bãž½-Õ](¬3r-7®©8­Ñº…%zîñh +'•ªœ÷(¢}`O­É/4`ÍØ*2M"-çJ‘nìPÊh¿Ã³_O¹É®¡©õ‚Îñ§›@ñä.… +meéé{h¥þŠ,æf¡`Ã!%¼¦VÄVX¦ÎmaåE(n7…É¥VFBª°B5œ»„QK®ÆÔZ‘üBQb#eÑŽGóJߥˆÜ‡/¨µ"ù…ŽË‰œ!‹¶#ÕæJUΕÓIa³j׉JP½ù¥Õ/l!5êžC)pi +ì–0íÔ=µR"¿ë…õ…Ø}÷íSäí=Ï…ºRÜûvO)»J"ù… +ãíHÚÑ•ªœÛft!5fjÃŒ• G}Z5£‹Ð˜1o±8™Ô5ÝÅxÊ)TH†Ïéã©TëÅ2Zð ôâÄŽ‚ RIÔj9U‘=—º.Ú¦™1¹/tNþ$uâ?RþÛ +©Á¡7ú( ÒD‡/èPzôB°}¤G¯üÇmô'­ÓÞVÒƶüZ×N`Bå™ËNiEå ¬ÝåÆc‘·ë*Ë ÞzâsP‡=Ï_hÃŒŸNÚs‡»¹k´Ü¦Ü5 +5‹X}ÆM'¸öša¿ø‡·K·®c²jz!¢ •Á”î© m»Ëžë˜Ï–·ï:Æ|àJ|…mò– '2ç½ÔïÕÊw¤÷\ª9úR~ÓŸß74C¥ -/«/ï–{p_mj¦¥¦˜ÊõFÞÕÏl¦Í»JiÞm9U˜‚_dÎôZ=„Ê[5œ+M§VSêš75UÿɦNÓ©Õ´åTazÇUd´š*•‹]iúeø/ += +endstream +endobj + +57 0 obj +2630 +endobj + +59 0 obj +<> +stream +xœµ[Mó6¾Ï¯È¹Àd-Ùrl °NâÃÞ + °‡Eoí.ÐCöÒ¿¿EQ¢HY™éô}LÆ–-‰ùðK3œÍéÏ·ßOÃé}ð_gcýçe +Ÿürú÷§ßàføÿÇÿÞ¶7k<]ìä|ü|úÇnOÆž>þûŸë8ÝÞíuoþcŽ?&s÷?Ì7æá>lpapþö»ó—Ò¯iüð¸½Ïqèî[ÿioæj¦øÒ‡ÿ>ôô¿ØŒ¯Ùg–ÛûåZ¾Î„YâÂ/vó7¬³þÊ‚k +—qD\;_ôæ×Âæ€,½+| +N»û9cü·ùf.×qè-CYv—fñWàZí=?Þ~¬0rv=¯ +HþÙÛǯêóy9]Ìà±å¨& í0E¡Å +Ã&îi/°ä›[P¬¹½ûëû0û-zÄÍp p+¨Q|Ög¬Ÿ'ì{¸Ç‰ +<e:xjKR‹º‚Ò°q’(¾.þMÁ[º?íµ¯ªNi·ù:>£¦¹Ø^¡ÿ{ùXœKJWh ¼v/FyùÏiºèÓzž ; Ïë|v5è xþ[0a¶ŽÆ¬ü?ŠbÇÅ~nfjô(aBî~¦^Ž[ƒ¦ÞͬinÓx-E:¦Åٌ׶ôÀ´è$9 z4Åõõ¯j<÷¨÷Š‡D½5›×øùj/MhFsžI÷ YìùRA“ô¡P—@:O€bbÆ´D>ÏÖ3EEäÞ”¯Éj+#K’~H^ÌœhžÀ®Ÿ²;„KÛ,ÁF™›åEw¡šT|IŒO°`äXq†ð¿„¥¬„Ñ—Wñ%-öîɲ¥ ­7ÖÚêSZõ †€Ÿ°ÿh-Qµ#P¹Òf$?(yÏ9Úø Í^[žíEÙÎDÖ#N´¸—ˆÁ_]å÷q<bÀQa÷~ =N1`þ¤p¯TÀ±éE©g²£.e—ˆ<9иoXZ°À“è1Và¡€ÒT¸(|4Ú[Ä©ð' #0ÌII9+zƒÏF¯v¬ã#M½,ܦÒi7´Äè2miß +I”hWSnrð8XàÓÔéÍ£2†D™½^$W%<ˆ?6i¿G4xÄaÍ~­Œ%øk¾1NCã›ÝÎ`„g«(vÃ%™ÚßÝ!Ên¦C:™‘k)î*1I3£€@ 2yŒGÒCk}PðÊiÖà79_³å­ím€?-ø“ïëKÚf>0PÇPÜr‘Ä9îI™¿‘H™àJ"%ÃË‹X˜êaÌ…WpISž‡­=³Í Úbm„I’llB¾æ¨s°8ÍPZ˜‹·: QÓ‹Ló'RÉ+~ó‹ûd§‘H4¸çÏZ{|Ú[lUr}|7ѱUØXá‘O3²†¹†dòµQ0yAœ}Š¸e7‘uæl zÈÎJª_ùdyÆq=Dü®ƒ„¬én) húŒKR è5¯"cÏW]A+þ4ß~6«2ƒ§T)ùTS#AǤO nKzk°æ ñÙ+œZ³ãD¿ é³ºI¼ÇâÍð9döM¢L“àû"Š˜vW¢”‚Ë¿Ÿ6 œ| +QéA8ÊDþ ø%TœUðûé7¡^bÇ}hU±ï) &¿È^z¹Õ tÄz›E„?‡ß)ÌL«,pÔ¸|™Mr·„K5=6†rh¯61ÇW…W {Í~{Ï…4œÄ·Éœ½Rßa¸ð«Xwƒ:Ÿ&.½>¹ +ë˜ÄHc› âÅǽRîà§Efü}hŠ!µdÝÿ0|)íàÒv´t[#_0Á"*#…‰¼”˜&ñ L”‚ ¥ä\ŒEÿ·×Ï¿òÀŽƒ"õL™Ç£:QPլ̒cM[/¶e‹&PÑ}D£)üŸL ! =ÃsT'wTú&µ~ +ñx+YºÐ˜JÑŽ,¶ƒÀf“­ãn\’VJtýÓ~Ù‹»BýÝ6ënZΓW_w‘µrÁHaàÇÉÒ¢*2Ãä`‹ ¾èü…Ëê6LÖïŒ4ë Í +§ÍxØnyµHëKA)Ñ’>ï=ç&‘œTïÀ×:ºÖÓ(K +ŒÉŠ¼oñ4JÎ=äDz!ý†cêÅl ’ ïm¤–UfrÖ2/òÝ㘨jÄ&hzq…Ö¹ÿj\‘åœì¾4EÚRaGXR:MFTÖS„r +k‰*ÞX2ëfe›M‰È óH»@vj±_¨”ÕimU"|T]³ + +=•×Zó1¤Ú îôuçÁ\MÁ¡(’z /³F‹wú^§W7-#G–lú³¦œ¶ªÚbÜ2…×R —ÙÔ+ü˜Üaj2>Ù€ˆ©Ž0O×Òªš˜O*„ÌG­3/*KH1l>Š1C¥TV'M­ë{áàX§µñÛº£0-ÖÝ‪‹ŒuÜ×aH¯ÑÄY”hà×9„xJ +%0Ì'•,z +™}n¹ÈÐŽV](¤K,{à7{ÿZÃüïóÜJš@) +ĸ8mË¿n èTÓ¨D`Ž©œ¸Ôëþä…¿dSбµZ}-õåÕ=õõü¾#Ÿ\é—|2ê=³¾ÁŽB"l»'6”ìA.ìHzJÛ<ÕZb“ø‘9í ›,¨:÷™ DŠ¨Ð{qv¦]±à ©2¶úšLãb´]VW­)«¢âlÇUÑÒÄiÝUØÓ$«Ðû“0öpWN=h¥É'^E‡Æ,‰,?;É:¨pB¦n +ëóTÀš©2…Ip8©´¸|œ©­g²{œœ +$ +ЖÛL.ÃËF6žwmö×£w¥Ÿ›,;ÊSµ8Ãlì \DÀ]É' ¾¨þuùdšÝ _ÉWî€Õ¤ùL˜§³‘…ì¹*Ôì@ícPFçLüT®ãùòÑ' +ÁäVióWüóò©†îÉ V=èГNYI˜vµJðfO³èJþíŠh;1×e +Ž„¡û@`ËdâÇÓÿ÷­·÷ +endstream +endobj + +60 0 obj +2572 +endobj + +64 0 obj +<> +stream +xœì½y|TEÖ0\uïí}»Ý}{ßn/é,}@rCXDd!B$[Á„¬€¨#¨ãâŒÌã6 +J TœÜFtÜÆeôÁeÔ¨ã ãŒ¤û=U}; è<¾ï÷ýñþÞŸiªêÔz«Î9u–ºÕMo÷Ú8Ò£MˆERs{cg–6_D½ˆ¶4¯ë#+~yàã©._ѹ²ýO_¿Õ€¦!ÅY+Û6¬X{ü„!ã.„j«â-×®ZfBhÞcÜ*(Ø>ôò§ YÕÞ{a›µ™Ch>yFS[Gsãßòä-ÿ9É·7^Ø™¥‹²ÿòâšÆö¸ý•×}-PC÷é=½ Q4Ðú¹¤¾³;Þù›WûgA¾!í#P†áCþô*Iža9…R¥ÖhuzƒÑÄ›-VÁfw8]n×çˆÁP8’ÍÌÊΉåæå ÿçþ¸ Ü‚<úÙ&äG(yLï'.MÕ'†’IæMh¼P©¿…ðÙFã…xV*E-è5ÔŽnF¿€²üGô ’ Ê_C, ~ ªD[Ñzô:Z”ü;”Ñ=è ”‹& UÉ2£(†îÁ b W9zÅÑML%ã>ºåàBv'¾åÁ( ÑmȎˆ9I-ä÷2>¦z-D/°ËÕ¹ÉÂäWø)îùdú/\ɼÁ=;ˆCJ\‘Ü’Üž¼ ÑIÖ7ôûdQ²z-B +h-ºf° ý +½„ë˜*æpòZ˜Ó˜ÃFôzÇ8Ä5 š­ŽnGГè(ú3úclÂYx~¿¦@CGG’3’MÉ4ÍFsÑ&¨õá \ÜǞÇ>̾9ô߉ãI?Œ½­C¢‹Ñè&´½‰ÞBï`–Ñ2 ™EìÃȃªÐy¨ °¹æô zÃj\Š'b _…w1ë8vèìKÙƒgQìߌ¶NïC»Ñô2zÆü;à”Å.Ëð2ü3|%¾ߊïûð#øSFÁü™eÙ˸g¸Oo$µÉ;“Âs=È‹D” +”)Gç=_BŸÀúrp.®ÆbbL.‹9ýP"Q’œžÜ˜|:ù& +£Lh[…¦Àšg¡Å0ë +è +t=}_BD¢–X¬ÅÀ…ˆÃx>^€×Â,Æ_à!Æô+gÚ˜~æ56ƾÄ-æÚ—°%ú_$’Éɾäï“/RúŽƒçÔêQ'ê¡ÛÏy@C_Ã3”8s= Ï„õÞãç€ÔÌ¥Ì.&ÉV±7±Ïs.îöÄìD{âöÄÞdirð‹È…Já3¸iªƒ±/lÞƒÊìîy}ŽØ ñ |.^‚ð*Ü;q¾_X}ïÇðøü9Ã1JÆxŠ1ÍÌåÌVfs„yƒ9Á"v»„íb/f·²ûØ—Ù9žËå +¹Y\·»H¬Ò®~ñ”ãTûPÓÐC¿Oä'¦$.HlIü6ñFâý¤.y8ùR¢B˜cZ sü¬ÿ*tºøã!˜ã{è#ô)Ðü+À‹5Ø +3PºÕ¼gÁÌã:¼>«ðjÀÿ&¼÷ãÇñSø·øyüþ~Á`˜}>|*`,bVÀîdv2}Ì[ðùšùesÙb¶„Ä6Àj®f¯õü‚}—ý€c8WÄ-à6rÏ*XE‹â6ÅvÅÅsŠO”¼r©,#Ž–?ì‹Ìo¹IlÚæ2,û ó'¦ÿŒù?Àøðoái>v.;—©e*ƒ—·#Aµ]Tñª2s“Ç.梬õÂ~CÌyÌULº?Ž¾cÎN[ǾÄì`–³Û¹[¸IøM´ž‰þÕ < h÷*ê +å±»¹?’jö”¢1$¯æ>R0ìŸ@Vªø>⹌°UÁÜ€Âçñ ¤3`¾œ/FåÜqö:ælæ(kC[ñoa‡PsÿÐ¥öc7ž‹ïb‹Ð¥¸ °1­fnE!¦“ ?/BÿÀ—cìÜï€6fâXÓŒ^cê€ê/c “/>mG[ðf”‹‡ðSèEæf4ÇÙ'O¹†²|jïaÏB{ðwÜóÜó #ý°YÒC¹dÄ"Ø™A6 +\SŽL.ð=HÀs™ù_´¡V|;û7|Sƒæ 8ÛÃL÷%¾æjØÀØA&µÊ j¤¨Tø¸R øGhpãJ„”«¸cŠË ̾ʞLÖ%ƒ‰å +câ]t`ç,n[`/…ÞÆv|>žÇ%™™\2y.ÚÉìæÞM:°Ñ+IØa‰ý¸G’"îJêð<àðó•ÝÁmá®äÖr—€nú¤æUèt'úh“{AoeÏl.ÙÓ +:¢£2XÝ$4¤Ò ¨›‹ÎyÚRrZƒº@òþíB{@CÍ|œýV ÕPÞêbt)ìÿ«Ñu nC÷£W˜‡˜»Ù s +ó4³ŽiEo£·ÙgY Ÿ‹^ã®å6¢(‚æa+¾¬´¤¸¨° ?/7–“•͈„CA1à÷y=n—Óa· V‹™7 +zV£V)Ë`”;5<­Aì‹6ôqÑðYgå‘|¸ +G4ô‰P4ml›>±6Ƕ” åŠÓZJ©–ÒpKÌ‹•¨2/Wœû^šðyó–|ý”pØ7HáY¾‰Â€ƒAè Nu®š"öáqjß´u«6Om˜ÃíÑikõqm^.Ú£Õ¨¨Ïî܃“0ÇÔ‰{¤6À¤úÜá)Sû\á)d}lÆÔÆ–¾¹ó–Lâ ëòrûpms¸©…'÷™b´ ª¥éSÖö©ècÄV²´EÜ“ûÔæëxÔÔÓ·„[—-écëÈ3Ì1xî”>ÇE'œ#YÜR»äêѵvóTg«H²›7_-ö혷dtmÄuu0ôe2¦5lž¾8sOc®¬[Ò‡¯„GŠd%dU©õÅÃSIIÃj±Ož^µyuƽ¹Íßìw»¥ÉãÈ=UܼpI8ØWí ×5NñîÐæùöº$Ñ5¶&/woN!vÑ$zÃh >\G!Úœ@3çc“…gCô‰Í"ÌdIÖTN¢x9ÚÜ\Íà¯C¯¾ HkŸ¦¶a3?‘”“þ}Š >,nþ„?[Ò(—(3ø¯ Ÿ ³Ô§á¾X¬/'‡°ˆªh +sœDóey¹ë˜Öp'/BèCs·u ýÁ !ð– 5A¦oÓ¼%©¼ˆš<ýH*ˆÕõ1 +¤æ©tm©Ù”®îÞNÞGý [Ÿ::üÏÄÛ­SWMìÃöÿPOÕÏ\ž9ï¼%âÔÍ +2ng.“KÕ—×ÉPŸµv ëadˆñ°´˜rÙpc’Y¢ïã2àŸ’2uË€J +\IK°8­o8+×iƒÁÙi ù%éE“‘nò4û&ÆÆæ+ÆäÇLO¿™… sQfæÂó6oÖŽ©›hóæiaqÚæ†ÍÉMMa‘o>vGtsçÔ†4E’·xú¦]W‹X…'æ…@t7|@Ÿ©Ð´=JÕÖïƒRGi• +eYÆ­Q‘²G1r©ç\ìŒÍæOVΪœÍS9‹ªDÕ•C•$ÍAsD íS"ûÔ)I¾C"÷ñ&2*ÎÊl„ç¹%=zŠAnãâšw’Oð¢‚YƒE…Ø,㬧`6^x!ôÙ™<ÆÍd7¡ôåþ Vgª¶ +$¿‘rxÖönÆ[™ÇǃŸf|’©ŠØ2íSÄY³2‰õçe®6­vµf\ëÒÛ’_I=V¡Îz®í‚Œ™ß¸J·‹·¹³ùlK†{3¿¿Í¹Í}Ÿí>hŽZÌ&—à#Wmty&bÍ:t9˜­Òíå”ÞÿrÃ:c…ºnGßx*ÀܹB0*™4Õ;¢Ø +DoÄ»bGnpàÜ+ ªê»plÖ «¾kÖÉAT=8X +Ÿf‹c‚Ù2“Ô2a‚™dŠ +QW}y9îªÇ±.+WRl·Ù”Êp(š†CJ›`/)7ž– *(Ge¥¨¤˜}Úi±:±Ãjv0ÊÝ·úÝ5½0ßÆ›ñ{ž{!ñÖ½ð[Öà +¸Ý'n‡gú¦O~qÏkgÍæØä 0ûì œ|íK\Ê–+Ì@!º[ŠñˆÇ<óKMu^À§·×´ ´MÌ&v›É8[}£únõNïA¯Â«öLžDÞäÉ~…N=€~”ãB:öifß*uJ÷B—h±í[ýàå’™ëÕÐDŸo‡9—ÿ Þ_A”³ê)O2 +*!åOî:QýÍ?ˆù¯_C€ r@ª-\f +†¢KA³ lÈ9Eñ¸2æØ%—% ~·+ÀL_²¤jaâk¿ÛíÇš ~®0¿õÖÐ)§Õâ<Õ|ÁMy‡0wÝJàµòd’»üú,6Wº/˞鸊}È~Ÿc€9`ßçP#†g6Úo´ï¶?i?fOØÕ;ÀÈ?Ê°jNmsrN[“ÍeÙ2å\¹í,î,Ûbn±°Ä¶Äµ$k¾€[e[éXéZ™u1w¡ívûmŽû™Üol;û™CÜ€­Ïñ˜ë±¬çíÏ:Þ±¿æø›ý„#¦³{ìàÙcŽ«]Wgí²²?£xFx×þ1þØñ-óý[‡Ù``‘Œ<_ ð¼U[0“åvF0Šˆ)Â~I ‘—#lgdS„á#s#L$rGV$’™ +f!½’tÈ^®Ù¨¹QÚ4Í +û…ïÖÖ#X£¹C¡Ñ(!½‚ݤµÙç+pù|nWHt9·1v‡8<[*¶q¬((8N´ ‚Í&d!$:]‚Óé‰Å¢Ó°ƒ ŒmvhagããÈ{‘RŒlø¸æÐBp}rÚÌŠ »B´V”ú ( ze‡;ïºNŠ¢­.©°Ì%eÅJ]RF&D>?D.7D&s©«BjÈÂY‡ðÀÕ¼ErØ1RÑ„R†´cH;FâÍ¥À¡H…Ø`Ã¶ß ÜV¡B1|ª¿°Œ${Ë'”Òl,•…ÇÐF )ô§) FRÉbw”*$[ÙFÅ +)æ(Åø}”3ÀTwâ–+c êcé¿Á.þD½›"™!ç‡.~¨ÞíLUžüT"gu%O>ƒ©OõIؼZ‘SÿŒ?©s )$WÿìH,æDj~¨ +ö‘ó/8ydL¶¾¾¾«ë̲3 O™<³O·`f_ÔÔþ,µKÍñåååu¸¾ ¤îªX6“ +§öLÊpØj-±ZO+c¯Yu``Õ#Ùd'~D¢ ¶ím¸qµßã|HdSf¼C'0k »“„¡Œ0ôsg:OdÔM Î^\“4ï!Õ½‡òÙ¨*#PÁõZ×»×y6 Wºo¶¹wªv÷º)دzܸGØç>àÁx²È¦—,³wšou3çoÎßžÿqgþÓE¯}P¤Î +wg32BÁP–Ågud ¢qÙ˜-ÑkrÇ +—ž‡¯ÉBÚ’ «ÓQ.ŸÛ™ËæfWèõYÂ]|Ч"$ŠAÉ`¯6qA°:8'¸X¦”ÉXlw”•‚R¥ +ÆËjÈ,“—Ò:YC±K{ùsâ5s6mjÚ#jx‡ÖØ|×Ü»û; ¥Ÿ®øùŒÇVÎ^ßÝ~¨yÃwt\ô¨‰¿fêŠ Z§Å¬5¹s~Ù<ôšŽÿËÌÏ©˜ΪÅË í/Úï$§¯`¼÷茜U9Œš¡B)°¢+ ©ýNRÄ{ +Óòkí¡,M½v7ïÍ +‚=€›%1üH¯T`aG@#n"ç’»s3‚›@ëÙËÙ”¢ÿM—¬¿‡*a7¢êêj²'a'ž8I°?ñ£¨POÈ0³Ï.Sa¯QmQ´ÎìÓËEPNò³~QÈ<ô‰&?ÚVG\ÃtÁiÔ†) +ã³LkéˆEÀ1)´Þò^÷+6¼Òóîm4ßùçm·ýùÏ·mû3÷ÑwíŸ<·áøú ]ô~›jÀçv¼ûÿò¿äl´_tÑN¼Ó²ËÊŠZQ'êEƒhM"?UàrËDë +f¥¹Uh +ï†FY-Rky‚q›xC5Ì6 ¼9¤5[¼t?™(€ËÂ@(ò†‘†¥DS*—1J%Ë„4 öØHQµÓä 8çlÐ6!ä¬fcÑb, R¬‚`µ‚_‘6TáõÚ*<¾BËVh5Êp…0€WK:+SQ`®6ï6³æƒx5²bd,¸ÐÒaÙayÙÂYžÀ»Qd”TíÓõƒ<±Î*AºVÒÕ•DÊ‚0•eê‰ZºH›=½º>%I»êQ}0Œeeúâ’ÓK˜¾œKm– +oÁ¥8ÿ:ZPp¹‹FIÉéÌ ‰Ñ¬¡£ +w"Œ€ûTK±Ž+(@Ä´Ž~÷þw÷á¸znè(˜A ÿ-°Ë*¸[P.z^Š|çÁÛÃܫݯýöUí ­bñ*ã6ãýÆgtoè”5VdAî–ljŽS©C˜463y?$(\úì|döWD"ª +Œ‘Rté„kÀŸxPrsÕ1|yy¯èíô[r€ù`o^ÎÃN¢,OT’ +wò~”(Cƒ)s™½Óä]íÉèöhu:·&€´}¡Ž]v‘bðOF,XŠc,h*ËÒ;ªD¶¸ñAüAM¢|m×¢gÆ ÞiÿÙµõ‘í¤t;±µÙ&ŠùWf4•ˆ—ÙdÎÚ¼–) …ß’FDZý,q)w)hªLT‚ýRÑT¡S`Þ +¾šñYðDÆwÁ“åÙíyÍÍ%.Éî*¹.{SÉ/³o.Ù™½£ä ßȨɆh¢‚M£P¨5!ùcEN‘wˆf3oôo- +ŠÚXmªÔŒ+q–OÄ¢VËkvhúˆí6G³\³[sT£Ð¸Ëòƒ›Â7…w„ûÂÜáðÑðñð—a.ì*Íiå§È^ +àƒ€wsƒÕ'ˆ«RM +±’®^Ö1iQvyÀpƒ £.H~ÛïW£Èåª I’­/!…yö‚ä'å£þRZ—¥EYP™°L¡T‘~LY©¥¤x´Èc/{š º+âì\6ësþýìõ™ö«_ø»ï~ýꮿþ¸þú˜ç¨õpêÀÂɹçgQcÿœ95§`¼?F‰™·¾øÒÖ[_z è•|¿´‹eáÈž”u­6®½v’·º +l.—ÝòúU,Ö‰Q}½ÊþhP#1Q-9¬\j•Fç š@¯3JwNx!ÒƒULœD“Ð!XÁ•}þ +£•=Qñ'ög +õR ÖŸpî:Ỉ^–Zµö;lL13™™Ï43Ï0ÏXÿàzÛò¶ë]Ï;?üÛnpys¼¥L¹ÿlÏ9ežóž¶À¥žëïWªŸ6»Ealö*.hÖéº+v Ü œ<€?!±Wìp‡pX8 +"\Áœ]c„ñ ƃTùÃÄŽÙìývA [sŸGø™ägÃ=¸f8h?]ѥΊ*Å6\Þ©ßØ?xðü?ÖX¼“/üú²?'ŽaÓsÄÚÅ®×·n}Íyϳ“JL.Ð6Å‹±çùÇ`ÿã²-ìºÑ£ÚöMn2£+$ÿ%Vk4„¤zk lXÌê¥ Ú‹´KÍ5üÒâÇ‘ž¹ +™™HïWÀÌNI[cº,hÎe€ƒð•1ä*ÀN‚ˆY'ártºxˆ®VçÇŒÄÑUƒUFÂf,/ãÔîÈd¯³ë̮ЩoXMÈeÖÙ™éøßz—ÙeMÌM̵@O¼n¨Ð!>K*·Ø9»à°³Ïãçu¯3ï(þ¢z]§¼@ÕjfâLœkU·jWÚÌqë +‡ÚdMA +¸€*}‘c“«š¦FM%ƒ­¬a¢`þæjÉiŸš)%hÓnßQåqå—J…r¿¿× 6ìmÓ¿Á¡ú®IA‘B ¯V¶vP¶Bòä>^0 +ŽƒÉ÷Áe{¯ÁoöèUbö ®ÚeK$]à=Õ‰ÌäøÔjòWëˆÔZˆT$‚òÏ$ŸEW­t¨„È.˜“Y“@Z‘,hµzzBÄ°¦@%Ž¡ØØ¿:L4BšÛF{)•‰AñŸcË‘ßaë¢÷vìx¼û©Ä—Ø|ø)lN|ùÛ_ýõØ/ï:~Œèc°Ÿm2PΓª‹´¦ ™ÊòæáEL½¡M”zñÅ9Ýùºß+ŸÒ¾¥zKóvæ[E*?Ъ]l.{±ê:öv«´{©zpø\.¯/d·™hÞòœÑb1C¶ŒÉׄ +ü¡PÀÊÀ†ìS…Í[a·ÛŒA6;ˆ·r*¨ÈPFƒ&5V»Kr‘Qô›|s|Ë}>Îç*­Ò‰P«L+ôÁJjH}Ÿõ?j‚áÍž¥/$§¬y@õ˜Þ bBõ¢ä_öd†‡iN)NŽŽSjžRÍi7òt1VCÏܵö’?õ$†žxﺩñÛ1JQÿòÕÛïxíµ;~ñÛtÇÒe½G»÷'’%”T[€ÓÀUm‘h½ùèË7ÝüòQØÉm 5íÊq›4þuåëjæˆòˆš¹GݯìW³]ªM*¦YÕ¢nñ°Û=÷)™‹{ñ>†õV„9†ñ«-)/Þd ØÛ4—Íæt…,Ù”l¹Ë +ss +CÙf]Êû7bã4­Ñ¨Ó†Ì©eðLÆ2ù§¼˜ʦ••…Š+Ê•`äG"lV¨ûì¬,ð0µ­è>æ®æ üÝ XtSáŽB¦Ð5azã(e ÕVäl®zè$öO~0wæQx0‚Ç«P«ÔJ5£ô*ÜìQû˜ø19àÈÌìó¤y! €Mö×=!ets¬«¾¾>Ex‡}äXfØ,+M ?Ä ‹—ÜP×0§|étBï÷ˆvyû‚‹º–S^ öõrZÇ6m¬›’íß2cè‹a•ÊÖ]\{åÐßG©Xb<`t4yŒMLÁ—®ª½5ŒåT‡Z§ìwÿuù‹Öç'ÿÕú†ýIïLþÔz¢ôãɧ¬'K¿lÑY•vÅ$Íä€Õf·MòLÞÚVzȤ[l=¯¼µ|uÅEå—V\[~mÅ}B¿ ½¡b€™§Že‡£ERUe©Ûi2ªlú ¨´¸0Ìå3õ¬±fWEUUЬÕà²}¬˜óðm’7:.DªE‚süËý~ÖïžV´0\‘m JDŠÛA^KuÙ8Û5µVÅ*£Ú î|ù\ˆXêÕ˜*©“86È¥,ø¡¡AD6z=DCæ òAY>¬K½÷™@ÞöÅËÇO¶ˆÞ k†c’-€*<x¼‘e2díÕÎr8'UMôU3¸+*ËãH¨1®ˆöKE8%y)“¤MÇ}B©Öûxò#äH~†¦$?ëŸ$Œ1¿7d¯ôŽø_©c\PP9èÁ^]!@TN4‚“·A¢)DL@èOt¦j/0C=FŸ@¢Q*´üöJ6U3åÓA‡|d-¤üoÙí†:"ŠÊJ3£‘hêÈ‘½„kNú^«|þÕ×Ï®˜VxÕî)Ëÿøì³Õ6?—#|Gǽ;æÍO<{Í9¯m}„ù€}oò»í®ÊÌò ±²Ê,¯Éê _rÖÄC‚Ñíl_[~ °ú¢)³ +ÄÒU•mÇÚ4WI¡ÃÊWô_eFÛ8KÍÔ®û¦Fv +±iˆm#Û5ƒQ£G +À1³fîÅÀ2ÁÑfÍЉaÖ`,¶bœBˆƒ}óT/5lXí©ʆMBI +܇ûR† +&÷PñðeÍhš5ëŒ_!T¬cÔŠ¯0.Vë´¼Ú‚pDÃk µsµ¬Öe‰?8"Þ€­+Ï0¾­Ã’#m/L©‰ãX¤ÇH·üû0QŠOä½4€3p¢z©´ÉÖc»ÂÆš4ú%<ÒÀD–`oÛf6‡œ€\À¨hæù9üažå]®Ñ¾q þƒOðƒþÀÍc½¯ˆ7>ñ1ÑlM’ÄÓ±Åë,mWSû4…§Si<>Eúá€%Y°²/ÐÇ‹‰ã$Ý­¨!ýo»#…¥¥`Ö±M(%%½–Ûog²ìØ­6i¨žÓ¨õz:dJië<³å#íÌ Éç¡ŽL#‘ ÊÄv“ +P¦Öá¬øý&µ¦‚7)… «O9ìD§i²y³¨>ªÂªüéÞ¬éÃ&'ñ.NVÝéYÛUm©·úgœûü'ƒ$o±rJE†•3E)¤ÎáR¢É*‹¦' +D’ Kò}Ùg¡/2GÆÑ“ºñ#Ùô{†«v=w±´€Ú%O¯šýÒNz(÷ÕMßU»d-ã§Gs×Ï_ýx +Lù~„Î6àÉà¦1J©Ò4ÞTnœ`šhª4U™$S­iªÆÕÓïóôçr™xfy›TMÞ^U¯W1NU쪚ê]¤RªÇWQ«ãØD‰¦ËfÔ¢ž©Ó¦M­8缡ý„?™_H §Æ‡^¥ð͵‹}Ù-©Ì‹*¼äE-s‘´-`XK¹y±™ñO3jÀí–Ž`G¸¡ö÷ø÷ü- ¾~±øw¥¿«5©AßbQ1¶Ôš-µa>惥%Å8XZæ-¼ˆ‹w¥µ‹E – +Á`)S+L|…ÖZa©VˆâŠHE¸"grEmEYEiE…T[[]^^gæçgV×)Jpþ>±öÎjž¼)õ`¬Ðƒv½^ìØn÷á;MŠ£pO-†ú½á;3-´]ðÎÌ:“¯@v¦>×­Ö­ÍQV(?<ˆUÈyš¹ubXm‹Ë5ë„øªl-rw„Ôžp:ù¤È©9ùAø;-R\£übIþa¯«¸Ú2|m¯#¤»ö +Y$ýf¯%LÒ÷‰‡é_û=•“dsG~GDœí0?úó¹Ð™— '¯…n¼úð~Ø||h¸íf‚?ù½PŠaK’ïKpÄÍ~ðÁKàqÒÙ˜µvÇ$³Öl™T[ã·TcÕŽ÷š«1‰jÇ{x€ ª\¦jL¢ Ö'N*5AT,¸<“xbų +R‹œÖ‚O¿—È®8"WB$Žñ‡†M;\lãE`<Æ­­‡Sï+‡ßýc<æ2€2ÌìÀ—E“;øŠ(é-‰‰CôõVâ ¿ÛdâËE¬PÿyÛÕ‚=Ø×Bø¤6‚ŸNܨ²R›OH<›Ú(» +wá³Ô´†x¤_`sê͘ޮF ~)ù>‹a÷IS¿]§îGJË!lG.Äaû~Îåò¶À~$_s#ÒžÀ‘Æì~똳(R>wÞø±Û4w|Ål†nœS>q6 ˆAÀ,>VïPà‡÷Zmø`ò+Ä&Oö穳k4gŸŸ™ü'hÈ‚¦üç£^£Æ¨62ä-1ŸüªßgÌ#=r’_Iál…×0†,íj¿×‚òq¦Â +ƒU–Ü*…E¡0¸«Ðóâ£E‘*£«ð×±2µ—`m³ùoÒ§K©W ôZÊ-9Éç£N—ÃewÙ\‚K¡ôz|¿'àᔙѬhv4'Ê)uz­^£WëUz…’†Ì ‰V·„cÊ åq›‚ö¸ Šês%”Ï@D˜(Å]9ð» ¥]<ú½P9ÙK6³ßêªüflˆì~`ûÐ@ò;I SÖÏ€ë3 Ãg +cu˜D™‚ÝD¬íX?l§<-DvùW ò™äÀ$8¤W šÑòæI}ïÇR +ÃÆ«ä“w°TÊxzº +^‹Ã®*•}<êâ”[ÊØ/‹ßyöù¾©&@3/Ï÷Oáí ks\Y¦_¿£6æÌšpÖu;˜w^NüýW—T”o©:·çeÌ8tKå¹׿Tv…ÇŸ:°þU!WéMʱsßïé·¨=Éo%“Y‰Ôä™k™ëá4¦ƒÌƒH·K^¯7ñOjÔ )Q@‰…^“xR-ßWY<ÂAæMð[V>†µÞŇ˜ËÀv0”´h¥ÙŒW’‹€O0È‹~ÿ˜â »ô…lê­yõà ½Éø³ê)•Ï°×ÃJ˜›RÎÄP›l3.hL.­ÚÅ}ûݲa³½ð\%yãªÖ&>l˽/–òîp'2¶áåZåMøV1÷2}x/£½Oy¿jŸb¿êÕŸUÇÜ*·ÚìH. –9Áá ™O?]⵩Ó%6,Ó ZMˆO.éN;X +—¤–ʱ˜í +rÙYYf3_Ž8¯UkD×1'vó[G”-d +‰>átK<ãèè4£èŒ#¥ùs·.mºvÙùD€'¾ Rþü+Ö.«)h}¦DíxïOŸz㜡Žœ)-½(O\?ôÙéÞƒöÍ—r· 0ÊC_JNÎÍyT~°z, O™gªç@L›cÉH~.ñkÝ?w3™êõV÷¶£+ý^p«btSø4äòäãè–ð©’/²ÅÌ6›ÅìsæZ¢.'Fþ ‹)RMnN:5juv†É‹½î‚<ì7ó®üo6 ŸúÊ·¢é™o%±H‘b¦ˆ<ú"©šHÙ·ú±çÀ¸ž¼s%7ƒOß>ÃèN«È=ØŒ`ñ¸qä®V÷¥6TÂ3r˜‹?~øéÅ3çN<7ñ/¬¯¿gæC—'^ÇǽiL³ŸGþÅkç]žQî¶.\pá¤æ_©óH¿ÞèM)¯€ËW„ÉÕ A´x ü“%úB¡ÐVí­öÏVÔê%A²ÍôÎñÍñÛÒX'cÝ yï8äõÏõýTÈ´“©ˆº(˜¨ÚÕ ~H$—xݱ1Dz«BÎÝ~ ^Ï@ò™²iÌ•™0sóiò‰úôÌ­”‡'²Å ½Nü +ÈãÖÞ|(ë¥à +Úku×X®µ^+\g»1p£¸9x}ææìsôº,œIÄÇ@ò¸¤¹#s©U;|7îlävûÏ‘ÂU™"[Æ•9ßðƒ]íw¨c~†ñ«™HÔdÂ&“hbLîü\?LÍY¸òá X=¬þëÓÌÚ•zCAÞZ“cŸÓoÖœéà—Š9Z›Ñd0éM:§ŒfdfdedgpJ«E°0Ê`FŽ6’E[8g˜bù8d ä#”Rú ñ‰WN/¹gŒâ]¢2m¶Ñ׸K(“Ó@ò¢;ˆ}ÔoÂGVïΟ“íë¾²ùòD%u°pÑêõ®ÈäÈuóG¦p¿¤|ùêY­½—}uÞdBÍ¿=ÿöÙUussgó@'1\'yUHå,Dç8ÏŽ5øná_öýËù¯˜ö7è7>F/Ty¾ÄÆó‚ͧ·ÙC9¤È‹¢QEùhCôå(fǢќ˜/C:–4pv¨°IPu¨X•*›Q©XƧcpÐE*gø|%NŸÏåôƒ±X Ä«3†ßáÐË9Ñ+¢z6ª ƒz½ŽA@;@a´Ð9×ÙçüÒÉÔ™$éL´À¶ÜvØÆÚ ¿7éÀŽƒø +dg^Þ›;µ +ÚÐ nÖÓûmõƒäŠÂØ;Åÿñ’Û׆ϸ3ü½÷…»ä;n)g ˜ò†ï¹^ÊÜ·6QWã ly§Õ`´:~¯RâËv8È8qy*•¸I›^oÓ¤âSvö“Ñy"£¶%.ån ¿?.U;‘Óâ Å AG.3Ï1HŽï¬ÿ +é4Ö™Ö³C«ð*ó…Ö C×X¯ 0?a=z&ôfÈH~«¡Øb.¶¦î4ú +†‚áËŒž“ûïùý¡'ŽA“}ù…ô]‚CÒçç‡bÅVMêRªBqGêJª#·@/B: +@ kÈm-ΉÒöÌÌ‚pff$Ê ‡¬ÅÅb8$€_aGœœ6[¬C…ÅŒ‘Ú¯°hÈÕGG¨p»Á7gÈÕÇHENQì.#òÏõ3þãþ/É›ŒÒ¹ +Œ¼BTt*Ž+¾T(®’œƒôÞ#'ê»ø뻆¯­Œºü(3…œJ+ä[åü'æø±"ÓYþôÖ*5_©®L±ì.þr¬ËYdÚ¹ünƒÍþ!Õux1žOõÝ7/ä}vU„^*DT¬¼E›†žÎaö¤œDp¿{:ýN“pÓ‘äûë2ýU +é<oH“íšèTäeŸ“½<{MöíÙÏ»Þq~êT»BžH©} ùWÉ +€G «^ŒØnðÑx)Ê@â >!i|U§EÑ ëþoIã¨Òº«x¹Ey%ÊfÚöCË•‘ü—ÇxW^§5|voŠEè 9ÿ˜u’Þªá|‚§_–J½Z¾NEµÓéUh¼ +ðÉœˆZž箪¶Ï±3ö<(éJÄ*þ½Ü*«ø´£¤“Ôº ßI)ø0}cm²fa^‘'`¶qj¿E”W9”¯Ê•P¡"*á€$’ÇQžº@BE\Á¨"zäÆ骧¯¬éai,ùñ^¿¥òñ^‡‘¦R¡ÝP­pBNá;i™ ¯¶9¡¹”ÙH™”9î©ÃòËi"ǧE!½B7~Ô}™17‘­­ß±ãø«—åL|ý¶_¼61Ûðëµ½¿¾{Ýú»»6mÚõðÆ3[JhØööÛÛ–?PZ6a^Óæ£G77Íø·¶íw­nÚº5¡ê¸÷Þ5Ý¿ù +Xêo€Ÿõ&ð·Ñ+’8EdüA…/ൻð‡ú|OÚM6Ë0½Åh|Ò&ƒ+V`– ļô1–åA¿Áp?2‚,úªßçó¶·#”Ùm`§^!™°Â¸Òç “#0l2k@C-•t «°+Äq6=ùOctO׬!rE¼Rþr&&ŸS«lòÝÍ ä4Z §½¯5vá`.y³rúá9ŒYvèUüêîiô +Ï‘ø—¹‰Åxy#›yêE²»_§Ý-¼œ96Éð&¹# ˜+E/H’~®b“â +ýeE;ôýú}±ßÅ^‹ij“Fÿy]š› 8îQ„BùŒZ1€%ÉMÞJG²B(£>;èCÈ"ºòóœJZ"_;ÔŽNt¥_Ú& +l’­Óö²³¹ÊÖÀ/Êß`EÏq*ù©±]I|ý!*²'ŒEHýèWÇäû 917Ç›@1Ovê„$ð^iÉØï+ ߦ iK»ª˜Z?Cô× ’øÑ]7¬¿ºx^mýŪ5ëñµôE”ahúØ×LWßeWÛ-ëh›º1ýŽ|'áJV1ôïÈ–N.(ܳL¯Ê¼*ëªìû³îÏ>¤ß—£1X´ö2}y—ÎñÇ„LVX/舤1|b´ÿÛ2dU™>Ž|÷1ù4Rñ>4H‡ +ÄPÚ§Ñhõîü¯}BUHçêÀbXºOýž¹*£ÆÀt <ä€R?´×1í@–›Óòˆÿæ$9Ù>™:¸'—îÀF˜þRv°,Š¯,õ¢P)'.­•àU1WҗϯaôU×ÂÀ#¯yÈ¥Ôèy³£õ@ã/ß.]—øóÁ…AB‚µ—|øyǪ9Ym÷_ZïTi|á½ç¿½ybcOoâÝ_ÜÿžØ¡€ûrlÞÛVŽùJ{Iqq™ybdFäìŒÚòn¤Ü¼ª|·µì¶òûÊî/?`=èxÁú‚ð’ãë_ŸYÿíH˜I¿ý1UÍÄTõ‹ImÒŲÌlLĉa/rùŬh.š¥{EÑ’;€¯ß­*1BºßR¥ WÀIk«b½Þ ¬{bÁA €—¹ì1kB‰B™6VsGŒÕ'fóêÁÅ8™2X‡NXä[Q ZS_€w¤-VoiY$Ã*pŠŒÒ°„­ +›„#e (Î2bµÂ®ˆÅÊë»ÊQy×°¼>ÍjŽ|‡$M¥ô9sŠH¬µ÷¢¯Ú>Î79À¿ßþð-O7>Zïw»\gum½ó’Å·äòfÙ¹xÃw¿ØÄì,Ýßô‹–òÞiêy¬sæM è÷7/=ÿ¦ÊRAã೪þùÂÛÈù$ó>ûwBdES$ðü= š +XeNjµX¿ÔªëÕþÃú¶ +÷¢h˜ì0j~ÜÿjLY÷$å\Y’N ÇRÖ«¼ÅG ½oïÔøí^×H}vŸ‹û(1Ï¡·ù³ð_døæÃäböE;âQ»4Q£±c—†-G4Óð ÍRÍšuøB͵êk5·á;4÷á5¢Gñ³øyÍøCü7Í7ø[C§ÁºüÜ~V7 -Õ à~I‹—ªŸ(`1û¦yÚ3‘7´=‘ú–YWý¨kKòŽ`-3{Ì.-sN0š]ŠÈ¿—d¸Lz›â7£Ë{½Ã¼Ï¹d¬UK¼Ú‚9#A˜¶W÷óoõ€(ÉdC½øªß2oʞݙBÙÉAy»FYÉðF ›ÞJ¼ãôÛüfÙ[‰w]>»_ H gùƒï–Ô-0æ•Ï>ŠmÛ¶ÜTùµZ£¦¿½uOƼƑ_â"ß°¼"¤‘#‘ö#¿»4êçº0û‡¹—ÐJt$é>TŽnB—’ï\¢[ÐÏ@–íDO M#¿`—‡ÚÐQt+Sr¯-;7Ž_B hÚ é¯€žÛÐlA¯¢ÀZxzÿj>DïÐ産ùXƒ¯a—ru +•â3¥^Ù§ºF½XcÕlÒàs¹n®>ßPd¼Öø¹©Àt¥éwüóÛà=.üÅÖd_æp:ö9/q­vß쑼˼Où^ô·×Å]â߃Ӄ×É++DÓÁ2¡?)ó)@5 ~¥}„|Ïʦ±³É–ÑúDêÇËh?;ͱ´— 2Ì¢ópH†9dÇ—È°$É-2¬D^ü «ÐýøV£(Ó&ÃDéöZÆÏ<"Ã:Ôƽ(Ãz´BQ.Ãå>ůd؈–éçÓl£þÆHgÈ“a© å2Ì¢ôY s襽æÃx=ºÑ:ˆ[èÖB®•–‰h6¤ëi«•PÞóê>cæ ×D:f7ŒŸ^I1̤beÁ(­0ßn¨é°FËþqÎýQƶNµ ¸!¿ø:¦.¢x'Xm|;]ÅPFžûNJ ^Zan½tƒ"äI›fZBèžÎ“­’Ô¬z`g>1Eã•<±f¶ùõtÎdô™Ð®>mtü)t$BÑ5òÓ)] ·¥G]OŸØ+ãt„¯WÐuΙ 3É•×;ÿëåѺiû:§õt5äWT OµÐÖ´lÀ)ž\9ü¬ÑO |§ón–±@p˜â¾4FD:jzî¤E#åÚ_(¯°“®¦p#Rz¦×OVÐ>ŒÑŠ‘45Öœæ{‘η…>›ptÓ¨Y¬E¿º£âð¼^yf‹h»:¿ˆ /¥vE/}Ö÷c¼ƒb¥“Æ#8é¦#wPé¡sï¥sIï22ç™OÓóí¥¸[¹Ì´@«fèÕukèi>ͧ«%OžÒ£Æ#ŸüQ8JÍ6Ÿ®µZöí0jĽЦ‘ŽJr=h¹ÌÁiîXC×™?Üçÿßg­§œ’jõ”Ùhì‘Àk3€[k(<JÉ[×iŸCËɯ/€˜ðÒt^Séoÿ’Ò…È€´4]ßJ¹»÷ ‰Ÿ.OÉ…N*¥:åý¼aXnü¸Ý;B½VY殥\”ÞC(VÓÏ$+^7J–¬¥}S|”žOŠ¯ÚiûÔLÈno£<§Ú NËVÒQâÃœAx¸N~Ú*¨_GÛuÀ<ÒR*ÍÛ?Œ™´¬NÉ£8Ý­ò̺)7¶Òòf*¡6P~ï¦Tü>|uÈëê cd”õò˜ß÷¼YÞ>l¢{*5ë&™2kä‘¿B™tUc1•’;grÅ™On–¬ëèÞ[K÷k›Œí:Zï>;ŸÊ5´}iôHÑi¬&IIšF:£NŠÙV* +›ÍE™×P©°r#Ï%Ú°…b:%/Rò¤{”};ܺ{ߦÖ×û?bŠÌ®]–ƒ#2sd¼´|ë#µF$äHËYëÚDÇí¡OO­'5¯ÑÜM4<á†þS»ªSæ4—žÎCÿiE#ü1ƒ®ýLÊ “ñ» ?Wl'íX'ËX'¸×´ˆ=mMtˆt}kšã½0Ø¢¡·CŒ·)zã£'Þ±¶·sm/IwÕÛ“+ö66’‰ë;§dÜÞxóª5t2-ÍkÛãkz)NóWõövN,(X¿~}~»ŒºüæŽö‚U½ímí½ä?;)hïYÞœBÇšøú|Ró#{­·Aiœv™=gáŒi3jkΘ3[œ3MŠ‹ñV¬[lií‚·mWtw´Ì ˆÐÛ±2N›¬‡–#ýZ€o»[›ÖöÂÐ0MBúQ ÊìIO +xgÃ[ ³®kl[ÛØÔÓîé‰÷Žî/.ZÓïé¡‹§«€5É›˜¦QìéŒ7·®îˆâcÆŠ‘Å5®Ù v­÷ÐÇÐ=Ò½F^A·G©ƒºÄ$$Âlµ³ÔÏߨÒJ×- J˜¸(ôx‚½“ÝÃ>Á†p€=Èîúé0í§Ã´ŸÓÐO‡i?¦ýt˜öÓaÚO‡i?¦ýt˜öÓaÚO‡iÿW¦ñzFàFÚþûêÞ;­O|Œ?”²1¿Ì6Êá£òœŸ+âfrÓ¹*ˆ'Œy‘Á?4ÊlºgˆìI­~îÿfÝ?ÜçûaùþJ„Çþ?ˆé¿ɧاú•HL¤É^c¤xIušökJªk +اP'„ÝŽBàÐrˆ7Ê%, +@\ +”ÞHëw°‡P„§ ¼ ”„’ƒPrJBI5;€0ûûh$Þ·×)þ¢ÆÍîEI {3»aìóåt¹œÞi¤7Ééõì–þŠ€©FyŒ¾€8 µÝÕ?}Nñ +Œ¯¤ÀötÉö½P¨q±wÁ¬î‚Yݳº fõÄFÝåÛ¡|;”o§åÛ¦C³å¡dà®~“]. FËÖ±ç‚û`—ÈéböÜþâÀášv ½›Æ;Ø…ßHãå4žCã´v#…;(ÜAáj +WË0‰ FÅ›HÌÎgÀV°óسi:—Š2 y’ÎfgÐt;¦ç@¹Ò™ÐÎéÙì4šŸù)žy’Ng§õO ÖtB~9Ô1ðæ0æ4DJn„°Â1Z²âŽB`iKÌNO-|jØè!ÁÔHˆe%øTÃg; jª mÄ[I×X ­*áI•€«J¹ÈS ä©D*¶b‘-C…$s!4@PÀ8¹Ð/æ• OÈeóPÆ +2×!RQNÌä‡ÔÏlé÷¤ +³ͅСÂ&f_¿Âbª i[a„å6B¸ÂnjTª‘tL5SÍÎaæ°pwöÞÊÊbš–ŒK¥^_*Õ»‹M5Ýl6 )Ý +…)gÔ³a©é\¬“‰C8 +á‚ðL@F& #˜ ý3i+%m÷„$˜(ÆÛFA{ Œ…”fAIä² O´Í‚Òcle±LZ?ÂËu!ÊÌ!Êœ!+³-€¸šB&ˆl¨Ÿþ~À–~<ÑT3ð>T2×6¯¼]O8„!›¸jªå7BØ +AÁ€O6|2á“Ÿ|‚ðádý@½›às#|n€Ïõð¹>[€ÂîØá³¼¬£lcÙew—í.;\¦:Ä4§i´Ènh1«Ý5<áeÈ€ÿMã‡iÜMc‰ÆɽÌpb™á¹e†;–¶-3,Yf˜½Ì0m™¡`™a7IŽ˜á˜á¦˜áܘa\ÌP3”Ä Ù1C×áÅ !Ÿ¤ñdÓ8Dc^Üo@šÇÉÕÀñ8s_ð²ÀÁ÷®¨!¹<•[šJ*Há£ÂàÊ@nª$šJ"Á'8-» +Ǥ\Õóªå*I5A•¯ÊSe©2UaU@%¨-j^mTëÕZµZ­TsjFÔù}ŒÜÜ”Ex2î³ÌD3NvöÍP%ç÷•Çföiæ.]²ãê ×Ç\3€ÑÂ%8IŠ®ôÿñòÂ8÷Êë=rZWGú,ÙÃá믯CöuÕÎjË$ó„iS¾'jãQ_KrŽþŽ™‰¯ï¶™ –ô=ä«ë+&@ÒW70GþƒÌL93nê”Ìx’Ô-9 ÝÄ”OOʵ›¦Ô´C"”O9€‚$¡íHÚ!ñ´v~f> +endobj + +67 0 obj +<> +stream +xœ]“ËnÛ0E÷ú +.ÓE q¨G;¼èuú²4vÔ”@Ë ÿ}ygØèÂÆáð’:ŒòÝaðÓš ópäÕœ'?¾Í÷0°9ñeò™%3NÚVò?\û%ËãÙãã¶òõàÏóf“åßãÞm +ó´çÊò¯aä0ù‹yú±;Æõñ¾,¿øÊ~5EÖ¶fäs¼çs¿|鯜˩ç÷§õñü |<6$k«*Ã<òm齿p¶)ŠÖlº®ÍØÿí•9‡Ÿ}ˆQ£EAû62 ×ì”·àR¸iÀ•Ö-¸V.Áfjð‹pÕ_µ.™­æåž7eï4#¼×ú+ø]¹wêYD¶…°ÛտƳ¬ú7’Iþïàä÷²ê冷þÕXýk¹3ù£'6ùÃÁ&©«óV‡^Yõwâ þ½²ê_#Oê_!Cê_â}IýKôŠÔ¿B?)ùK&ùÇÔßIFýzKêïäYêïäÎä/yõwè9%ô‡àO…EHý ½¥Në{ª4=/ÌÿŸ±5Ã=„8²ò‘ȬbJ'Ï¿£e^pJ~¿—4Ùƒ +endstream +endobj + +68 0 obj +<> +endobj + +69 0 obj +<> +stream +xœí½{|[ŵ(<³÷Öò[²,[²%mI¶üeɶü¶£íØŽ±ÄNì€0ñKN ŽåØNBx$¦6Jyô‘Ð(¥Å Ô PÒ‡S 9Ímx¶§8m)ÐiÒž„¶$¶îšÑ–$i¹ýî÷Ç÷û¼fÖ̬YkfÍZkf¶%{|ts©Ñb‘Ø·±gD¬.+Dý!lèÛ2.(o<ýmÀO ¤øx`dýÆÜkw>‰P´+ÒÖmxý+#/ Ĉ{ù†POÿÙZ„JÀ£dT|cær(A9cÃÆñëN³u ”÷@9o(Ü×Ó¶Ñp5”Ÿ#å=×üĨW@ø!a¸gc¨º0©¡2%BÙgGÂcãG‘{¡DÚGFC#«*ŒïBY@(©ê0¼ÉK +¨œ”–“ÉÊU¢Z£ÕñzC’ýÿéÅ}pJƒÜÆö"BÑi ~7»¶'ÏΠļÄG%ˆ½ÐQœeòþ:ú¤;ÑN|6ÓÚ{Ñã^nA_½ëа"î@?D9Pÿò ËÑýðþ;” èeh?ý3ZŠŽ£vJŸ +u÷Cù%|ceìˆAG¹LtG¹°}mÁ;ðÿ°ë€ÿýÀa–y!ÚˆV£[Ñ7•yÑ'‘‰h#ºݾ…uØŽ¾ƒäȲë£DF²íGSøGl+wSt/ôlCÃètçsÝÜ+3¿Ÿýr4ý%ØÊèQœˆ @–½¥£2DW¡×b³Ç—3ýMt?ð÷ à´¤Þþ +CÆuø8ç–¡YµG_‹þ +)Ðè{fáÍc'^†Ÿ`RØ_°Ÿ"JE +Ðû*BëQ¢ÇàýCå)ÀŸŽ©cº˜Û™û˜Ù{¹›¸í°2;г`ÔÎÅ"nÆmø üKüKÐÖ6ö&p9`¾µ¨-G]0ßÝ°R?££~Í` #Àa|þÞ‡âß2/±íÜeÜGÑè-ˆL×úr ,T +Úa}ŸDÐ!èý[h†±á ÌïKÌrf `[Ù+ÙÙ=ì#ìëÜÜ“³Ù?Eo>}.úfô×Ñ“ÀOœÈ‹šAÓí¨Ý+w7úpý)z ý»ðR<Œ¿„¿†¿ƒ„ŸÄÏá7ñ,£až`KØ{Ùg8̉Ü}Ü˳úÙïÎNÍžŠÖG;£ça~½èËèv°¶ï¢GÁâ·iÜ€—ãUx-á;ðcøEü1Ã1W1O³nv{={{{–Ëä®çÞm™íš½wöPÔƒßýo«™Q)j‚‘^Á2FÐtŒùFÐù—`ä·Ò÷W`?™?FÏ‚^N ÑYœ€5X‹­Øï2¼fÕÇñ]øAü=ü;üþ+ƒa$¦„Yɬ‡õ|˜y‰9Îü–mgÈ>Çgs&n·¬ð1îI’éåÕÊŸŸ{çüS3Ì<4ËÌæÌvEÑ´hz´!úTôÅè;Ñ?ç +(ìr%øÔhXͬÔk`Ç`­ÿ€>’½éqvãø*|3hú6Ðõ7ñwáý8XÎSx +ÞÏÁûþw| ´ÿ>ÿ€Ïa0^ÆÍø`ÄW1Ì +Ì÷™ç™™Y6‘Mc] Ï*6:½‰ÝÉ> +sø%ûgö¯œ–KâÜ\%âîážà~ʽÓ5ÈVȶÊõò»ä»¥Èqta4ÂõLø3¸ü_ +šy™ñ‚Gýá}þ+ú^Šþ€gÀÊï€÷ÍèCð£+˜Zü>XÒwp)¾?Ì°Lh }èaö‡øMæËè.ðþ|ô¤˜Ù€óñíL:Dû™è÷`GÁ_þÌ4~V:eâô7üüt +æÒÍ$£õø—¨ ߎëГƒ\h ƒ—Lä°ìJˆ·ëIìåîcþ›¹ŸB +Ì^:æ»pÚ‡sÀÞŽâ+ÑSÌ4WÂ=Vº ¼ÔÔ«9Þ¶ùM†C1/ƒíî?[ ^q?xï>ð“u6GµxÂø¯8éñ`íWƒgÞãy=gØYµ,z˜Â‡Œìü>ô ïÊ@?ˆ~ý÷‚Ä*ôMô[´œ=Ã%ÃŽqš³Êê£Ìl/z;º +½ +‹gßE—¡_ã;!n\†~…MèÑ¡h¬ñh´Æy Ú€ÖÈjd6ˆÆ=Ìú©bŸü]y•¼@Že×Ëúe«eͲZY©¬@–#sÈÌ2LÅâ~Ãã~Â}ûøn>—Ì©Ùw!~îgdïdÃì +6ÈæƒMZYŽù;ó'æÌ1o3G˜Ç™8£üuôgÑ£­Ñêhi4ivvöì싳OÎ~cö¾Ù¯ÎNÌŽÌvϼtþ7çŸßþüÉÌÛ¿~Š_={ÀæèÚèòè'àoÆè½ÑêÙ·ðn˜c&šÿú9ÄÕ{a]¾ºí€'2—aÍ¢³è$hèMh?„¾6¶u£Ëåí¨ÖÛ +žùeÉCkƒ ke€ _krb JgÁNûúaôav +ðØOå1æX˜ý.Ê‚(3 ûS3ú=^‚þÞÑÁ™‡@Ú÷åÔCòÇÑYù·ØsbÓåkÚÛV¯jmYÙÔ\R]UYQ^VZ(*,ðûò½yžÜœì,wf†Ëéì6kzšÅœšbJ6&ô¼N«Q'ª” +¹ŒcŒòê]˺…ˆ»;¹]—]æ%eWTô,¨èŽPµl1MDè¦dÂbJ(>C)Æ(Å9JÌ U¨Ê›'Ô»„ÈÑ:—0…×®êü+u®N!r’â+(ιiA‡zõ©ê„îê#˶lØUß]üö'ªj]µ!•7íW%šX$Å5²§,ÁaRê+ö3H©QE,®ºúˆÙUG†a3ë{ú#­«:êëÒŽNo^×ö¹z#ȵ4¢óPTKÅDäµ# ’é ;…ýyGvÝ5Å£ÞnºßÕßsUG„íé$2ô[I¹þ½Ôù"07Ôvì\ØšÆîªOHq×®BdߪŽ…­’vvèËd.ëÞµ DßE´˜êƒá“©Ä&rÕ“šîk„H‚k©kîkºaA,»"hõ6ǤÅ"Šž@–zaW{‡Ë ¦¹:{êÒ÷Ñ®ÕÛ˜EÁ¼¸Å›·Ÿ×Ç´¹_«“µf!šk£%'Xóê9ub2"W#˜ADè`$.˜HIBehW_Á«C¯H?,Ã`$¡¶{_AêIÿˆ,“w »Î"Xv×É×ôH5òL|ôc¢8,Ä + ÚãxÄã‰äæ»PÔÂB—Ðr±7oËsÔ5 úPktë¬ðβªwN‰¨ +‘‰U±²€zÓ&‘èótF˜nÒr$Þ’¼†´LÄ[æºw»À|Ò{KrDéžûÑñ¦¤ú +lúÍ¡X{s›«yÕÚ¡~W·¤ÛæöE¥X{Ù\›„E’j;Ø4F˜4–¶‚%^5GL +ê— ?rjÉýS +%˜"­Á²ß}Y,íT9Ÿ³ÓTô4éE³ùnÒ0#žÅåÊEåEÃSïbaÀœ›in_»k—jñÐWz"êÌHB&XED“ÑR<)sÒ¤]ã"ÚîL º¹”$˜_Óñzš£Sè"í¹YªROûNWEZÁÝ#‰™`¯$•Q^:šj(ÓäÌHJf*æ«ÎW•WûROœ&dªL"^GSef„ÏŒè)nÊœ4ëÉôT¶a.% º`d|Õ?ƒŽþ¤dFÌ™©ˆ¯RžGÒXh|ˆà˜ò[;ºÓz:‰ç‘Y暎ˆœª×A¨¤/-ÁÓŸÛvðÛH‹~ÀK;oŽy¦#ÖmÁ 8°nÌ7Vzó\€!Š nü@ +1J¡Ü0sWYšËÑ9v“¨JÀtg +¤yW7 ®H[.iu iºÝÐÚe°•ìÚµÌ%,ÛÕ½«g*:Ñëx×®C¬‰5í©ïŽ;éTôði‘ewu‚]nÀ^8p‚³6‚X*E›\qêdÜi©ä²Ó,ËXÜiŒÌÊæR=+ù3U+fªVòŸT­àgªP°j¦Š@ß¡wè3!ÁˆCçöÈyQ†Î!;NêSÝcì]¨œ¹êÒG?õµÅ:!X̦ÚÜ4’”NE?<¹r±SÞ¿åMëÞÈã.K[–÷†ì +Õ;êw oß0ÿ*ûWþOu‰Íºµº;u¯éþ=Ofo +[Å`1žŠ™ —OE#b9äÊÕÅ +¤´•âAíuZÙûv&›­fûqü+í»ÖwíÇË•¿HÄ-‰ëw'>•øB¢,1Që&â’䔀ÏçEIXLjMšHÚ—I’%%ñ9"4ää .çó<ØkÕÙµ|¹Íêµk±ÖnŸXÓè²cû3$<Øè:¯ÕJªW[±•Tÿ/7ò|9ÖòV›2EUî=ä9d·fÊ_Õþ;ÿ²çïyíþŒçœWyç[ÞǵñÏið=Ïz®}‘ÉóšW­÷ؼO¾·ÈSå­õ,÷Þ©½…¿Í³Ë«¾\»–¿Ü³Ö; ½†ð\ã}P{?¯JѦòFOš·I»Œ—{•ÍÅ^C1¯¬¨-æ…æb!ÏYJ<…ÍÅvÖrœSW‚£%¸¤„#ª04s¢Óhá0ÏE¸#Kªð†mNHI p\¥Ói!%mkñnË^ËS–,¿°È,¾.O‘O_äóxº6yíÚ¤7¤”{hB^££›6uúèUUí”å{º<;ozig~j ÑÁ ¥úö18ýðÑ7c?ãœÉ™ñžñŸ Èåi*7óŒãeÇÛ9oy?Ìyß+·§ñn_šàæ Þ UbÀ>-¦b­ž4±0#O‰æŸÞ½À<Ä|ƒù&\†£GP,„ZÅÌZÇšE­Ímãµ[£9Ý–áqX-gÍ×Y©òBGœyµYSÌÑåD¡U`‘À ‚pBà",%i×[,f3rÿŽÐxŠ¹B4ë/ð~þü4ŠòŠ½<æÍÅ}7Ò˜±©‹Dªª÷« fóïAøØÔÕµâ$¬}ðd0xæ=þ$ÿ1_KXà¯Ý&ÚŠÙ¹6WŽÛéεeÙq‘ ’l»ÇŽŽB;B°Òd¹o¾ùfÔؾMäý™n¿»ÐÅdú\ `Øp<È#µòòÓÒ½™ùi—,/ÚÓ,±vBàñÀŽ|ùÁ¢Uú ŸØpJ‚.è¡”O¯Å|’ÄL¬³ w¡M]™ú˜á¸Θé]’\RRTˆÀÀäPƒn·Ë©'ME…%xà +MÁ`Óì}MA±Ñå"øéËZõKœýÔ=?nyˆ1Ö}e݃k«ŸºùKOnš”çƒyóËÙolYö÷S¯Ý2œ¿ê¹µs¬¥qõ7‚È:}—»¬ÊƒN‰+ÞÑ7¾•ñNÖ +ïßÏøcÖ9ã9—JiLp1%†~½!”<}N-OTcC£aEV§á7Æw2>2þ1Ca1kÔH&O2§™Ô>OÃiSØqЉ®ÏÑN1Ÿä9Š„)Ü$&0r“Ù(_i#º‚±°1­¶c6Æfñ&‹1Œ¸1r °"#nÎmÎûϘ tmZqr%?;ÚåYñ‚U?œy‡…ïÒÊË0 ~Ô+"òJQc +ªH’@’4ÚS´t:ñ&²¸„,Yg–ÛzŽ©¹´¤$æár4”ØG3³òˆ‡Z“SóWm¿û©ï¿8±Ê¹+·ºk×ì'§n=ˆ3>Zs»Þl¼¥iIª!œæÿÁ—®»Ó¯X’[W}eß­üÛò}gôwœ(ó¡jôœ˜˜»"ó7üW3ƒˆ6–ù +¯£_›EEjBJÅ yÀ»M¶-ùºòMÕ Êm9ìéþt&=½L¡5­ÖØ Ðè +ìLA§¡Lf·€Õ‰®L’9˜š@ÙSÌÕ“••)‡™«KB.Ÿ`Ù` ÏðÆJĉs¡öd‘ïd‘Ç£/÷¡àL¡¯‹$qË}›N‚v1‰Ä0c’ªŽXmaŠ)…Xhq™ “…¥K(ó¥¶\()VÎÞyåÚ­¿ûñŸ®«­ÌµÚó²ªìëZ齶¨´*@‘ÝZ06öµ•)ÚdKnÕU·½ò“÷ë˜-ùnhã¡uM¹yÕF›JÛµ&¸Y0(Øòܼ*Ìå­È©Yw¹Y‘X•W_³îíZî€x‰–F§¹kÀ²­(CTM¦Œ?Nû4NúÓm~fÈøò·äoß6 ÿÐø¡ù˜³òÿ1œ7þÍþw—®DÞ g ƒÆÁÔk,×Ø\_cöÚ÷¸~hÿžëSs¢U!c“2lXI6³ÜŠÉEµÙ˜PS2§•Ð€MO ÜSK×Y…oâmÂÆì¶aÛN‹‘hp‘è$½ØŽ°µ _Àˆj]=Qg Bb :&çàmSL÷$Ú +k7qÀµ,Hóf7ÉA¾+#pÓâÎØ +Aµ[4&‰®b{ÒH“$jt$sfãu&ØWÌ0Ú±âÌIâP3tÕ=±Ýð$ÍÀ•ž¶‰fGÌá€1;–àiî2Ð|2Û n";*hÉq +ŽLôu1AŸ´çA⚊¾> 9!'NèéÂõ:Éé8—ÅœŽØTr €r7xþÇÂwï}~¥-§Ì–=ûêîOfßÁÁc7ý¯¢Ë|Âï} nxÀ¯ní-0Väe§gÖbÓkoc]GQÓÆåý[:®¸¢tz?XDXDóS±8Á /6LÅþÛü_÷/ÿ`þ‹ùo&¼®z³àý„ +Ψ?ñéUX!S$(J²ý%¾†œe>eQòH¢Ö Òa¥«-ÉY†ä>äÊÈ.ö-ó5ì,¸¿àï(ŠÿæRd‰¬:Á§ö§$ÕÖT»Ùâ7TÜšx§ÿ—‰¿öiß/ÿmÅß}¬‚ý)lQ¾Z…8"ÃaR›ýL¾à/ øI¢&þœ_PI¹š¨¼¢XËhkIy¬rÒz µ”iNÛ›ZbíÓÞ +¤÷áXvBL¬-öƒp. ÕWH2H.&X²U¬Z¥"Ïz¾ÑïÏg¥ +{ýŽúSõ¬®¾¥ž±×ãz¢M½XR\ÿfuu•n Ʀ~©û'sô2™™’~òH£l’éÏ=G/“s +§ëN¸7>g©TŠ«Åâ\öçcY‰©ÄUÌ +z‚yÕÞÚµ 2!Y¸_ù¢üáuù{òOJ”há¢Çfb´5ê“ü¹¥N„oËÁ9¹¥µn¤>šU­*FTM¨•c]nÉÃyy9FÑ[0† ¼Ã¦ÈQMà^Ï%jÀ¯8èXçÄNzANKyÊN?½T*DØ•í4–³ +sYðI/+fNÒpSÏÉMÉA@Ç‹Þµ N8~óäøMöÞ“r += žJ¶¾=jÍù4)O¦ù¤.~6.'·ÔrþcL®«ðã¡gpwG±ä×p’\]òsé*_+vnË'VÉÚW^þÈbŇ]×·„¯¼»Ä–SnÌ(_þmñ…ã1Û¼aÃMkËÒ +¯hz¶ÑŸ“óÔ57ÿÆX_‘¡©Ì·¸Sødó#»g×’åÄáÔê¬l«ÁQQ6ú5ˆ ‡¹ÿDy臓f%¸á¤hÏ4!‡;3Ó*O8+sèGÌØl6zsrðˆú„šQSuÃYÔ’Ÿ™3G·Õ–ŒŒ‚Ñol5vGŒãã ãi£Š‡JR1a”ÍÞÃàÇÅ(þ„§*öŒg%ÿ'OÜDÈ¥³ ážÇ:ˆ›ü{t{ä +I Ǻ9¶"&IfE±-ë©^Þ#xrì@ñ4¦I&–;ô­[‹¬Ù•BÁìtß /Pn¢Ú Y˜fCK“µ–*O¶Õ×òÈuøEÒxˆ´’¼y¼™<‘ËÁ?0~@Ž +䲘i)VñM<óÿ”ž±‹œVLUb¢¨52³%-Ýj³ gzÑS·D5€†ÆXn>–.Šø_Ô¥A/x}½XÓ‰#3 ×ZÈHÀõæ67ÍŸ1š8G›8…­¢C '¹Å¬BJAéW¶*»•#Jù¸¹Z<Á¹™¬£Þ‰‚ÃïhutÃy^î0çNa¼ÿÆøö6CÇ­äß%OaƒÁ°«ÑØK©©Óp{¦ã–g´.™ŽÕ»¯§G’ø¡εÄhÖõ$¡±LOê@Ä[èñº„Nz/Ô;.ƪn¾¯¦ÿj±Úãnwxž˜À4ªÝGÒë¥p=ѵ¤©0W½|hhöµx€Ã¡‹ «{¬î½«‹ð +Ñ¡HKIËJ+MãtcFÇŠYO槡ɰª`½¡•›ïŸYkUì)+YsQ­æò¼ù>AaÂ/|Ö$ ù"bklb}C C\ÑIq$3BÙ+2ô{‹P¿7/Oõ§Š©­©Ý©©òT¹®?!é‡ýÂã?+›Âÿ-ªÉÂ2K1,uZÁÂ'_§ž¥zó{ù§øxñ­ý‚l&k¿É³âÌ{|ÕIºþp¶yï=º½Âý+¸)æ­p%;¿¶ žJÂh¾ÔšINj’É‘£çœ¿†-`/I{_yaÍt°,'ɽ£w`®’¼V»x%WÞ¶ß^–ç«T˜«½+¥½ëAXYƒL G+³R´ì°î¶~ËÊV¥_nnM02ËJÌà ÅVòlų&h•~Ð<ÛHò ±}­7¨´È¬KŽÅe-·4YDë:ëfË׬XŸ±¾iÕfX ¬¯ZYƒ!ÝiI ¤‹îâtgbqzS¢&pc:¬~ë +6ÑŠ +HqÁyŠøúÅ/0ñ”(Rí3äñ{ºÕ:ÅlÕf‹Ñl¶X¬¦T+yâ)êa;J³a›"5%E!¦¹ŠŸ0«‘ )ñ£H‹Ò™ÛE +²p:­ÚÜ’IeRŸeVA+ÇÜ&ª”X¡P¦¥¤˜Ð³L/JGJ¦W´¤Ç®9¢©Õ4bš0í33%"czŽi«½—}é îçĹéû=,H„€Ú™ªYòˆˆ?9ã©¢bg¾‡#uCyjìhB÷V+¨ºÊFU.&”¦­Ä(­ä> +Ê$ù3îb è”hÓø E„‹3Q°J·kJ +û0É÷ë]ÿ;7Ñ£}À%ºÒ'`‘ÓEXát–7ý=XÚô ž>’Ó\Æ;é ²Ši.¸kB{š³q¸”Æ“É‹M¼ØQŒ“ô˜½"9DΞ$æÚ:s´tö-™öü»å^oÅjr~$Fºú ¶îü»øo³J‰n¡ÏŒµ(}*ểXiFé©`vœSI÷mrjÿ9­a‹Ã,fãO‘±NºréSe­…!ß#çº!cä–<ü,܇œäÃubÜÁ—ßźHÿ$»Æ§™ÐìÑp~¨éÖ°³ç0âÛã[úŠ3]ÒƒrÛ}v ²™ÏxÈS™™M]'ß‹]ySMNiáR=ؤ„Ä,KóàE²'~ßCì/*4€RñgÎsœã'¦x`Á‡G»žÿtföÜû·­¬Îu­öŠý‡oÿòúðW…Ô¼JfŒhž«9“1;ûó_žº¢°&§ºV“´õ†m».Ó‹EL«ÿ£OÍ<(sÏ +Ê5 +/Vz1J´è8³v +ìÿ™á{üûÈWµff+­ul Ü·Ï=Då 4—ÌB&‰<þǺ„ Á ɼÓ#zÄxM@-½¾C'$Åv’OKé![f’de’I¹0¼,0³á7«S +ƒMØLÚ9ûø›³[ Š“ƒþÔ¶¿ã—µöŠ˜?ÏÔ0/Äö¥r›v  °f8[°X_<Ævä@¢f Cf’ Hk5¢–™ûnEòâƒAìŒÈÌ´páÁÍ}1^ —jdZ–9Ì\A¤Ñ–!T t¹F­’= µFÄ0WLâë8bºädrvï6²F³5~…$×é3°vô¨·És²+~‰'Mv_úJ9ƒù‹Ü*ßygö†™šÏ¼pô]„d˜ý>ZÊ.MÓ:ü¨ü ëyÏZÙžÍ;j}-Oi àX\ôH+:’]CØÎßaß‘¿Û¾;¯}oþ´}:_U œ.›2AB  +”ê$@ÀÅ´(.)-+¯¨¬¬zžÙ»ÐcL8þÙM¶F»° +™ôžÐêdñÏ}Úm¡ÕÅèHQmÅ?2šï=#é—ÖˆäS¥U•Rí¤­QwЇÄt›7·+–Zª\·U¥X*/23“U`°NO§˜ÄÂbú 1Í]lmøH®›îÐ{LœÁ4…O‹z›`÷Ûá6îa'O +ìÐÿ™,ƒÐǧîb7eàžvŸrGÝ\·{Ä=áÞãæܤ›ôq§Iä͇®“U|%}êê.Þ[‰u•û*§+OTž®”ý‚",m̃´R¬*Åš¥Ê‰ÚÀ.kly`­í\Ù¨4×¥_KÅŸÍÞڼºã@¸WbfQ-˜_'½n|âñtuÅ6î§Ýä‰;ü“5öDXÝäîà¥_öz:ÉvÓUõ é`"¨ºR ‡‰š¡‰ÌÐDfÿ%=A>P‚b¡)$†¯§¿g.¯¯ƒ¡‘Ú[Éî©ëŒ}t„ÁèÞÈü¯~+»i®ê¬2AI?°ýÝ5ášø7b»²Ì´ ÒwÒèž*|æÁ…_ˆøÌ×µ0w­Gžè)4Šv¢¥èþèGhõfÔ‰¾÷øûàNpKô) œ ñâƒÌ4{?·\¶F‘¦LQ¾›ðõ„sªoRi:µûuCºø‡ôÙIîØHÑeÓÉ‹A<ò¡+RìNª…èNj×q×#òé8òš¥)KGh¢%–öRb£„³¨§K8‡ëa ã´×jà70Š¶@ÚOÇ°Jƒ´N@+!ß +‘ŸÈë¿`Ì— æzTP¾£ #>2š2H” +üaÌ£Ð20|sþ)ÇË/Áoq¿X¯VДwÁèÛS9œt=ˆ¶û¡¼òQt-Ô‘±üë+%@-ùFí ŒrœŽ†hV ßê¨MR{ˆ—Ɉ†¡&6ª1˜Ï…ck®DâŒlìža˜#3áÞ tãð¢üë('²ÒÃ’ôºÞÄ +ã\·R‰ã’žçí}€Î‹XÔRIž4ß…k²Uâ6Jéû阶ÒÙôobký”º‡Ö-ž˜]m¤ô±‘o¢6¢»DˆÖ­§\Bs–Al¸S’¶Ú·Pº0Œ#¥â¶}iÍÄãw,…¨ J#¥Ö8Hëûh„ÚFí}”®âÅô–æ¦cžËV‰çÅäõKñ–Øa/õ©Ø¨{¥•–8_l…²è¬k*w.´Š %ÎEÖ-Ô÷6S’´=F¹_Rv>Ô~ŒrÚvÁZÄÖiñN‹4=tD#T³ƒ4ö}®5$[¦QaJórÉnØO5‹±x2ºàÜ7G=ºÀncóÿ§š"£Û(ÅÁù˜9Ï/ßÆE­ù9O–vC{)ß1*=6ŸØ¸Z7Ùá‰5ÄôóªÉ>âVúYúG3š·F:÷ WŽh˜ðßõ!Ê;>›ù}d”Æí…k0ú}Ïs&ó Ó½ _Ú+¶Ð¸»uAø<«çóIâ«[¤Õ˜÷±8¿ ×1¦­Ø Æi ¿¨ÇW¬ç3ºø?í¼–/”Ð'1z¥ÒÂÅÏ=ã°÷Ä9¬øOÎ^DΟe(€JáÌ)@Z%/œš~DnŠkàL£ôCk´$¼^%¨NØ÷ÿ³½î_ßãm¾Ïhon?lß6èé íBŠðpxª„ÚðèHx´g|0<,Œ õå u=ã=ÿ„ÈG˜ má¡Í¤fLh†~åå~/$…ùBÍаzpý†ñ1auh,4º%Ô_Þ<:V†¶. +õÇ9W,¨HCÅ–ÐèS˜_V(d¯ì +…Æs>Kxù:© +šZÛ¼”}»Tõ¡}´§?´±gôZ!<ð'%Œ†ÖŽ‡FCýÂà°Ðï!yxóð8°ËŸë³¯íÙ°í²ðÖžÑ~¡94>>­ +®†î=cB@H·ŽCê} <*4.]‘'Äg²ÈFCBÿhÏÖa¡w›PÓ?:Ø3,,­®'½b„¶ÐP¨†Ð'€*É@¡†pìë¯#ƒã}„~*?OØH‘il +‘uz†û…±¡ž^Êb€Î/<ÜfkÆ€ÃxXmÜ<Ô3Z8ððæñ‘Íãt$£!PÖøXž0ÞÓ t0ü0è”ðõm¦ƒé÷mÞ§:Íß0>>Ráómݺ5£¤ºü¾ðF߆ñC¾ãägù6Ž­ë‹©c8´5Ÿ´|Î^[CCP¢]V¶´7.k¬­iolY)´,–7ÖÖ¯l«jV×ׯ¨_Ù®QiTíÇèÔèblad4<ë¼ØÆE–—No¬xóXˆ¬Ð¶ðfÒ³/¼…ZÉæá~ÐáºÚ8F˜ôCƒ}¡a ïY? +eä ÐmCÏ–î%&E´½h0ľÁŽBBh˜ +ýƒ£°àCÛ„ÑðÆùqÁ"Œ‡×‡(ÉV œï×v;:Ø»yXÃ0ÉÒ/˜PÖX|P`;sª˜ëb‰mÕdýÔc›ÅTãh3ÖÀfõÇKÒÏS  K?¤Öe(öÐãRTR;{;û<ûû¤û/E»ˆæ‹‡€_<üâ!à¿xøÅCÀ/~ñð‹‡€_<üâ!àÿ?õpîî5ø¹nh1ªåÇ,7Lk6_²ß…” +4šŒ]²G¼}Üî†À·?¾„ºKßÞÓÅûÇb)‰ÿLÒ<åå»}¬õ2å¶Ð»å¥iSµJ;:‰=1¯ÞvÉž£]¨ýKÏggç–p•\-W•q"WÍ5så—êyQÚöz Ÿ§Xöukm&Á@)ºyŠfél{í?˜í¬G¿c]`Í— kÿWlý_Ðý¿$çóúÅÜçѬkñ_ªŽ¿E°gTT«1²gF{hªƒÔhØ +ð€‰ì™Éu!éwf²¼¢°FE0T…Š¢·Aå«VÚklPh ÇdÀ÷ êØ@ºr í H8ƒöœ"5Àâ/“%TÊ_&W¶Ö¬$zrÿ :.åÏHùw¤ü6)¿Uʇ¥|ƒ”_.åmR¾DÊ«¥¼JÊ ¥¼@Ê3¥Ü)å‚”Ûiþçɶ¢=0Ù?ƒâºÙ?¢€ –|ø¯Ò…5{öDŽH§)‡4ö4åð!ÐôR.ªÙ° pàûád‚A¨Ù[€ä­ôzz=½‚^‘»AÊ~ @-oAË[ˆA'Øãè4uÇ¡î8Pêã@}oa‰e_dÖÁnhg¿ÇtMöÛ} ƒIXðIXðIû öuàõ:åõ:ðzz¿½_‡Þ¯S^ó%–];Éöۧ؛¬%ÙO8úíºš¶ØׂÍÔ„jÉ'êØ¥ ¤#ž`Àv–BëR`²(–”—"ÛÀzzV1—Ã6jg+¡Lò +6æåR^Æz&‹AŽ“õ?X¡®c³ ”¥,ZÊ€R”2`˜~H3 gäEg@°€2,¢0™d¦+L:2%$¿°ðyÖÁ¬A•”Äq ¾¡°»&‘M‡q¦Ãè³Ø4ôi“…´[Úä² YÕVX£gS˜!*+™9 &ggç@ž$åöIÛRû!\ÃtÀ* °#5h[ +ªRƒ~Õ 5¬³Ô£±j°5X„ìH +v¤eªÁŽÔ´ƒ8ż2™Q´÷0ó3tŠù™¸†x¯ì”ŒÙË☽ì)–ÙËœb˜ä/(»<(_'ËwËevEP±NVìVÈ‚LmaZXN° N!KÈd¼wðN>‹Ïãäëj™ka×1ÿ…0ó_LX‰`Z̯¡N`ÞÔ©À nHG(6éŠíƒ4B±#”šô™ e~®¡<p‚!¤åã}™w˜!*M`Þ)oõÛˆeÞf¾Okyæ-h!~@R?€Ð +À1o1Qšï3o¢)€·XæMæZp,;óÆd@g¯™aÞ`.§åŸÃû5x¿ +ïWàý3P¨ŽÂ«tV¯ÀØ_AQ¡¾``ÀhçU˜Û>æçú ºý«h7À ,´ý àU¨%¼ÖAŠÑæFt=³$í`®Øp=À +à@;˜q€Í[¶Òš€M£c´f`#À0@˜Öl¸àZ¨ ƒŒ•aa*# 2 # 2ÂTFd„AFd„©Œ0ȃŒ0ÈSaa¦2š@†ô:€m×Ü@ëÇ6lØJkF6ŒŒÑš!€ÃaZ³`à¿‚ò¯þÀ¿øWPþÀ¿øWÿ +Ê¿øWÿ +à_AùWÿ +à_ü+˜ð~®¢& +*@@¨ |T€ø@€ø¨ððQ>à>à£| À| ÀG'àþ>àïþ>ÊšòŸþÓÀøOSþÓÀøOÿiÊøOÿià?MùOÿià? +ü§)ÿià? +ü§ÿ4心Y†ôÀ“`\;˜>€~€Àm_Ð +ÐÐKk®¸ +  àjZs@@'ÀZZÓаàrºôëÑ5 'Då„ANä„AN˜Ê ƒœ0È ƒœ0•9a9a*' r ' rÂTNä„ANä„©œu gó8Z ²ˆ³ôô„hû:€n€€^Zs%ÀU]WÓš+::ÖÒš6€öš(¤kˆ¤Ô’š¨¤Ô’Z@R •Ô’Z@R Hj¡’Z@R HjI-TR HjI- ©…JjI-0£ÓBåANÈ`ëè жuÝ=½´æJ€«º®¦5Wtt¬¥5mík.§v·åR>á>á£2| Ã2| ÃGeø@†dø@†Êð Èð •á>á>*cdüŠÊ˜Ó cdLSÓ cdLƒŒi*cdLƒŒi1MeLƒŒi1 +2¦©Œi1 +2¦AÆ4‘Á܈enÀð’sà-Ÿ‚×< ¾±|d/øJ?øÌà +à!µà)Uà1~ð /øGøIøK&x…¼Ã^"€·Ø˜õÀsx†Ð¹ŒúSýÃ0Æ}0Ö½0æ~û0Âi-Œ¸ +Fî‡ñyaœy0Þ,w&ŒÎ £tÀh¦M4Û¾þ·~û£› +ò¦°E,†“Ñ9€} +U~€,€L'€`@&ò +z¥X“ÂT3p@ü­Û5÷m×ܶ]sÕvMÓvÍÒíššíšòíš’íàþWáwhúušÞMRtŽ¦£é š^MÓ*š +4µáªI +J˜Âg'Õ0ï3“ŽÈNN:z!{|Ò°?‡E#;þÞ¤ãj¨ýî¤c5dë'Å +L: + [:騅¬æ ÃoÿÔ1ÅaQgÿ­cÔþKG“=â(·?Lê&í{iS¢}Ô᱇¹öþXõ±¬–dÏØ«Oؽ±š¼XÍš¤„¤„=SøX¤ØóŠ=ÝŠ=~ÅbO®b[±'C±Ç®ØcU•%¯Ô*ÕJ•R©”+9%£DJ#ùëŽyäû\F9O29GRŽâ˜ä8gèÀ7ƒÊ$t(ó3tNf ¡Ë"YŒÎI霋èö78êëö;qšJÓ°˜fßbš}”fŸDÃÆh h’ʃÒ8’Ê. q~š¬‹Ò\ô_’Whé%›¾ð!´Oï¯ÜBþ;K·«>йsˆÔÈD¯ B•xZúÇ-îîÞ¾ +$ï MáiW¨.Réªö¯Þra{d i^íªÛ¶Ô·wìß"†ê&W‹«ë]=uZÖ‡‰»#.npýE˜­'Ì‚DVËÐEš‡Hs ‘5Dd +Y-b •U?H¼¯µc¿-í¬½*–`U`õÝiŽÎ¥&~d uJGêö´ÃÂßG‰žÎˆÚµ4¢ MÞo +iÇ'MZò¯w¤¦Ôí•Ž´ÃøûRÕz×R.pÁ«¾îÿþ{œ¾Æ>ÇëóP¢xûxjý`ÝÂêÔžqÏüx6Ï1‚0FcRÅø˜‡þÉuwVw^wÛmëv0ccôïÀ<·*rë!÷+ ux<þ‡åá¥p‰!ˆ°#|˜áXF†¬#Än&xl|3BrÑW¼Rýo™½cú +endstream +endobj + +70 0 obj +15827 +endobj + +71 0 obj +<> +endobj + +72 0 obj +<> +stream +xœ]’Mnƒ0…÷œÂËta“„$BJI‘XôG%=±‡ÔR1–qܾm¥.@ߌß +ϤUsnŒöé›e žõÚ(ÓxwØnÚ$"cJK¿Tñ-‡Î&ið¶óäahL?E’¾‡³É»™­Nj¼ÂC’¾:N›[}Tm¨Û»µ_0€ñŒ'eÉôaÎsg_ºÒèZ7*k?¯ƒåOp™-°,Ö‚V‘£‚Év\gnœ—¬¨ë2£þeœ,×^~v.HEr¾?”3bŽ¼‰œo·‘7‘wÔß!ç¤ý=õ3äé#Iõ'ÒTÈĹ"ÍùL½O¤É‘kš‰Á‰q¦ ýw5ò²?êŲÿ™öÏÏ1åË1¼»ŸÈ™¼;âŽsÆ„µßÀŽ]ñùÇè™á +endstream +endobj + +73 0 obj +<> +endobj + +74 0 obj +<> +stream +xœÜ½y`[Ź8:sŽö}_-éh—,Û’mÉŽlÇ>Yâ8Îæì‰I[±8¶c; „„=q Ph€²ÊV“ +'liKi¡½¸¥ ´—Ò_ÃVp¡m ´`é}3:v ½½¿÷þzVΙoæÌÌ™ùöof¤ öoË ÚƒXÄ·mií{í¿þ„Ðφ¶íƒÜó÷Ïôü6BÒK6öulq^ÜŠ|%BâéÝC?T5nAHs;Büí™Öö]¯-Ñ"´0}TtBÁµÙ=RÈwB>йeð’§Ñ¦Û =äèîmk/][‰Ð"Ré–ÖKú.R²"È_ +y®§uK¦ö +ò ””÷õ ›²]=Bž÷õgúì/ŒBþU„g  ÇüA,!y†‰%R™\¡T©5ZÞ`4™-V›Ýá,p¹=œ×çCáúÿëŸø\ó‘®v+²!”û=\ï“+;/÷¥x3òg;sÿ‡­…Ê…+ÿDßC°íBW¢zT†@/£Í¨-FGP +úÿ +]„DPkŠ"# nEsp%ä kîex²&÷ó.bÐwÐè/hú%jC/" º—£š\6=׌â_£ +t-:˜û +’Š’èAôëÜosY4}ý×àfv¸­@;ÑeèzlÅ…x¾ …` — gÑF'?ônB ÐR´u ã" ï£Eèþ; Þ´íÇ)|&÷â`T!TŒfà +&–;ܨ%Q5ªC× o£Ûѯp žÎ–ŠN!+Ì©ÂlÁ>ü|î.äOZ #½ÝŠE?E?ż”‰³ëÅdßGÔ #Ü…ö£_ ?c^/aFÙdzu¹M¹c¹ u%¼g6šãÞ…nƒÙ=ŒN¢3èû€“_c^„oà +ŠËƯȾ–};gÉýia¬ËP'êA»Ñ> Í=èèMt}ŽEX†õøL‚y“Õˆî[s(wPCq4°u ºí…Ï)hñ#Ìá.ǃø—Œ†Ñ2ÝÌåÌaæ#vû$ûÑ{¹Y¹ïå~8ÿI‘>!´¨º ¨v#Ðî1ô:FÑOÐÑ'è`rÞŸÄ'ðßó8ó Ñ—â_‹?ÉÝû)ÛAT„ð) ^„`,=è ÔKè?ÐoÑ?Ð?°§ñåø:<ŒàƒøVü;üs-ó +ó{+û;ÂþD„Ee¢Mâýâ·%‹¥­Ù[³wäavFè; |S 8Ì/OÜx<ŠžBÏÃØþ†¾¼a¶\—àKðeø +|#¾¿ÁÌe61½L‹YëgÃì^‘GtXôšèMñNñþl(»*W‚ß(€ªaÜ+á³m„·ì„Ï~ÀÃô PëÇÀµ7Š¾€·1@g%6c/ãzø,ª¯ÄãV܉wáûñaü&þ£clŒ¹‘ù6s?ó_Ì{ìVööNöûs6+ʉ•â2ø4ŠWÁ|‹ÿ"Y&Ù')Ý }Xö³ñÂñŸŒ¿•UeÍÙp¶9{uöéÜÊÜöÜŽÜ}¹‡sçŽäÎPIew]À_|¨$§ÍGÃø7£­À“Ãè&ô-ø< s8†Ž£€ã^Cÿ…ÞB¿ƒÏ»è} ì‡tNŸ¢/aN6ìÇ¥À/•x-Þ€7â>¼“~®Ä·ãïà;ñ~ŸÁ/ãŸã_á_ã·áóþþœ10F&ÎT2³™‹˜…̦É0}ÌnævæNæ!æ)æ4ó# ò/™_1ï0Y¶(QÏÎe[Ø‹#Cìì}ìSìëì/Ø_³¿g?܈€F^‘_U‰:DW‰ÞGOíâMâCðùD)Ù$9"9&ù©ä}©D‘Ε.’>$=*ͤA7ƒ”NùŽûŽ2k`”,þ!sß‚ÿƒ9*c4xÞÉ"¦XT<Þ„Þeö±A\Ë^‚ Ç7 †j˜»™‹€»Éßâràå⟋Ìøa„˜kq'è›W€¡Î^ts¿Fzô­Üft[A¢2¹ï€,ìÁø ÈP³•ù£èKVú{ö +à›wAö“øVÉOÑZ&Ü6B”z¾…†0Ç” Õè;ì^ ´ÙQ¡¨[ :ÿ…=Šeneö1Çs/1}zoµè"ŒDoƒÞ/Dü!zÆö2ósf>!’àûðBC+þø1 +0w£ » +‹˜=Ì_E¿Fo0if5[„ÿ"*eY´ètZ…?Ä2ô¾•ù{ÑA¼fÿþy +¢¿â3ÎÞÈtâŸàc Ã3ÙÊ2¿Ç`4ô'±˘J# ðջ̣ìF|'ú¹øìoEMìI$ÂÏáJæK–cfã&vZn %Ÿ³êì/r³Ðl&—»Y¤ÿ°³½‘{-µŠæ}qâ‹W+¾™Ý"^™ûKv—ø*¦m Ž†˜Y !^[tâàÝ%U€)«è¦/¾`#ó þ]‚oéÀL–‚æ8‚:ð÷ ®lSX0‡Ak6±Û@ÏœD/·_ºÝÈ´éÄKVBDíÁÀ +u¡!ð ¡gÁšÈ-~çùºÚé5ÕUéi•©dyYi"^R\+ŒF¡`Àïór·«Àé°Û¬³ÉhÐë´µJ©Ë¤±ˆe0*ª÷ÏYÏ„ÖˆBþ¹s‹IÞß +­S +ÖpP4çÂ:#ÜzZ»°&57~¥&Ÿ¯ÉOÖÄ:®Õqõ~nä?fû¹Q¼zñJ€o˜í_ÅŒQ¸‰Â7QX +°× +¸z[çln¯çêGælï®_?º{R©˜åŸ•Q¡'J•Xý}Obk-¦c­¯z’A25 jÄáŸ]?b÷Ï&#aƒõ­í#‹¯¬ŸíôzWàYmþ +#È?sD£UÐ,úšɬ)} +×EfƒösO¾~T‡6¬©Úýí­kWŽ°­«È;ô1xïìëγ¶óYèÜ0kåuSŸ:Ùáz[G²ÃÃ×q#÷.^9õ©—ÜW­‚> -œ³~x¼úz‚D[B†O¦’ŸTÆ_OJÖoâFäþ™þÎáMëŽá´dÈ{ÔáàOåÞFŽznxéJ¿w¤Îé_Õ:»àI^2tÌÎsö Ÿ=©Óç±ù¤F+*õT 3ùŒB´:—L¢“ù€ F¸6F²Ò™Fn™ih¸mTƒ¿UZ´ºFä³ÖëªH9i?"êüÜð§ÈîûèÂ’V¡DÔ}ŠH˜c’¿àù<‹¾ÎBÂki>U\´}”ù“¿OÇAèC‹VB³UUqÀ¹×K¨º”G 3²gñÊ|žCœG­aÖ“'g&ž˜—‘'{&žL6_ïö=Nóˆ,4ùO«³ë;«F°å_<ÎäŸ76û¯^ÉÕ¯pÛ¸ô‚\þù´Ég4bœµ’u2Ä8Yú8qíde’Y©ោrrû¨T¬HK07gD·~nþ¾Jáõþ›FsŸV49ßLæHUìÂ|õù †§faÀ¢Ó¸tõð°â‚gs@í Ïñss†×·Žæölðs:ÿð)pñF†ûê×OPt4wz¿sdÎõ«`¸ª˜ØX† \ ðn¤¨î8ƒ?—HG™¼‰EŸ³H!}Ž‘]&ΰ£xÞ1ùwk‹é>«¯Y ;WÓ4^ƒêÖ} ·Ò„WïÕá†}ɱg¾äÅà¿q¢3@×áÜïÅ÷æ£ù@@7K9K·VÒ¡TlWîp_«»UGÜôã*õC† +ŒD‹™QÜÄËe›eåaŽ52Ƨôí692có(ë>ÊìÅ£xæÑð^4š;sÜ”Fç4£ìnÞPÀ_Ô˜,àMéC¸ Éì²Å` -±XÓã±±scg[PÝøÙºš±tgK¨e+nÁ¬?\Âú}àÜHÌ&KyYEe¹Dä÷B©¤!P^f¥Eâû2‘80·gÖ±k·.zwtÿ-ñžì¹§Ê¡kÿ„ý¼íÒ +›-P(Þœm詹¸>¼a×Ùg¾ÿ£/»âȃû¿üÖ[øOâ&S|—Dî}öûì>°„)üo“s2o +_¯.<ˆowÞRx{Écå'cÊÄhî-Þª2Õ=`y ”©(œÇ1*Ÿ=¥Òø"I +y– ÎºÐºÎÊNO`YoO²¼z?ÄbF$B‹5 +™UjK8^ +ZD¥æ¢rWh”=ô +|>$ pÿÌ!“ÙŠæ~{Ìm¨‹²%¼ÚáÐ)Í‘Y§V=‹g!8hfàö©Ðãfê™ó¼ÆL"³Îœ0³7ÒäömN™Ÿe¢"ö +d@®Ü™c%ɤ‹Ôµ†ÂIמæÔ!×Ç.ÆUVa¶š+e?´ÅbºJ1¨S´Ñ¢Hit¬ÌžOmBÞìϧZ¡BSc>ÿ¤5þV5}p.Ö²5;7¦ÿlŒ¼DwØU7»NSÓìÒ½³Õ!ÈëÎb}ZoHëÓð€u/]GžËj®Óè^x¡4[P,ÖÒ¡ÛÔ8RØÜ8R"ûT[ÕAÅ(ãyR`Ýg-”ÌgÇÆ[ZbLwl¬.O_Yž¾Ø@)jH:û +ô¬©ÙE(º•HÊVJ˜M ˆ|Â!Ð)–H½Hâ÷I¤Ì­¿qAÏõ£Ù?^wÛ!œðë¬ÅæX´}þÊg÷¯©m9ojŸwó®û²ß?ºUd2;ÔièŸW^ËîZÛyðЀ sï3­€{Žòóä nððŽÔR´´àcÏß­"§L(yå"¥Héª7¯Ž$\M4ît±ƒÙd0˜µJƒ;b6èÎWìVœÆOC—^Å +È€Ï^50À¯pË +Vƒ[±c~ac[©|ÏVMàYfà#&š;´äK~3”z¡”'y3ÿ¤.ßJc…Ru¾ö [ÚÀ[&å./|xìì¹Z&¨2Ad«ËÓéZ^"bÃdH¼RIÞ£ 7 ÊíIšöÑ‚±D!At* ‘(˜Öì£v£ÆhI¦ÝëU§BåÖzCk\|à‹Õ«LZ“>ºÜsm*”ôúØGô64RÀƒl +쀨%ËWhuÊ Mg ŠL'c ͲÅr&"/ N“W»çJd +ò¹Š5²ºeÁ[Dß=h<*:Ô… ¦‡Rr_¾Næ3(ëdr™\ìD2¹™CÃN^¦¨U;]θ“u:•þ€A*+•\•Öì13fG^" V +ˆfOdQ†‡Ži°ÆŠýpÂjÅšþ~vЭi 8»nÌŽ·ÄÆ0ðsš°u:­#H¤J©…RVž{ë E8<¦WÔÉ„TJR¹ª–äBš'jÁ-Æ “gôR€ +±…áŠÊŠ<¦%礗¯ž{ÍUæ±_ÝüíQl¹eÓÆ™+é{áÛ-—^š*Ýø*ó®ÚUq}8Ú{O{|yuóü¶éQ‡>ZùúÂä yr??ã~ñ|Ày1úÝ)T{Ÿ/קã±ΡðÎØþð ·DmÒ¸ÔØ Üì,(p›Ì&“Éì/Q•`F-3•DÌ&]ô4»I€CÖ:Éiùã„é¾8Ž;_/8Íbdfë´&lÅ'Kä&«©ddúÄ0›SnéÇFëXÄFS^Y ¼-mâõi‘›ÎŽ +ZbŸ1ÁÏucº1ÂÓbàiÒa(¤÷ÄûLA‰K#*y<œ×Äqe+"^N—óòErV~šá‘‡aF_∔XÓŸœžäø¢ÇàòÁåá  À•DFÜ!îyîUîc.ÇI Þ{"ÆY˨Ö:Gìw^ÍŸ¥Ú¤®æ:ñ¤rã +Řšn¢åuJïƒeˆƒlÞÚ¶&‡¨†—©ß8¡ô;𪛎ܸ¸ÜòÙŠ­^#•)õZGª¹µÐ](á¾sŠÓš¼æiìâiYŽí˜ά)v{Œ™LÃo¸kfs¿õrfKw‰A¥“k»4~‰Ø‚”( + +:lí©JY¶W¥ 1ÞŠñvgr• +ÛýØbÖ{WG"‰h“ +õIFÙ»x‡JQiUQ­Çí5¹Ý^§Ò]ñºuÖaË(žu\+ïcU£ø¢£ìzí(ö?í6¸ygÊMTtUu’¦…Išòr é&è¦9#(Ë„ûF7㶺­îBÅŽk/ð¿ò.¯tmäæÕp#YÔ4¼«UD$Þ¿é¼W5Åâ¢ÏÆ:Pí´µ…vyÂʃ3 ¦ý­“Æ´ÕgLð„6m嵂‹aB¤¼"ª0²ß úª¿\XUVWU¾h2ªµæt•öÚٵѤýJÎã´Ô‹-U…ÑêêhaUv`|ÖEIWÜlí¼(U .Çgz +,Ê0‘"°ÃÔÿ‚ŸñÆ^—Šð*¸4©UÌJö¤è +¯(ZP]ÐÀ°Ó|X&W`•Z#µI¥˜ £ÍXêá”CÜPg`ÁîzJ¶;f#NMaŠ$¼3”úØ–³1œ·í±Ýd{Å&¶9"ža5P_KeJÕ…†Ö…ž‰BÏ°~$?‰¼•$¹|?T”ìÁ(H +t¾ˆÛÃÝÄÝˉ8.Áñ ¡{Á±pÙ[$6k¡t÷è¬nlo'‘OM]͹1;J¬iJòµƒ ”à“×UÉ@Adˆø* EØë1:õ2Í.ÛÕ&¯ZÙRî/äuŽ÷˜^ÚæÛ«ì%lcí¼¦­w.ørØ{Ì“Š¸ŽÙ…\Y}yy|þoF­¯1Cw—ƒë“Éx°ž@Oñ2Œ­>§®N¦imJ³¶*,Ž(ýÚï°l×á…xA°'â%/¢„TˆJí£øŸ4¿h³*]½’:`ìÞ"ŒñKšªW¹·¹O8v7w#h–3€¤{eU¡ƒŽaû‹”ÆdÊÆ'àòú’÷ÚÎØÛe¥§ñlÜB÷)AÈ9ˆϵ´ŒƒHœ¥–·æìXþÞB| ` ¢Æ1Tç¹–¢Èo,·ƒ +*¥„¡H´’|%óÞô ¸³©¶ÁUzåüǯž{±×Pl +NJúÛæ¯Ò+¿¡—sh:ô1»/û×îœðÖT¸‰ï¼Ï§*Á³o¿|YmÄWóú¦Tëµb6ν,jXT/Žñ~–L_íÓ¥O¨±Ñar +J½Ë f÷2Ü^/£ÃŒŸfeH¼Ä·Ö§½:À}è¨QVÞN¡TºN“Ãá”(œ£ø.Þ„ï³1 +£AæðEœ:åD”'“4•äS4Ÿº9šòJ›#¹ÛqÈqÄÁ:F÷S>¹Ãêð):N±óÐyOtBÕœpð&UixÔšÎ÷g Ù§ ÆZÞé„?â70_‚Þ¯©©™°À±ºOZ°-#ÐÛL‹½€A=§¿fšcØËúóúÞŸ÷-Ë¥ÞJ¢e**1X‰$½!c±ï†ÍÙsåüâÕøQ¥cA¡+^ˆí‹·Ý¸² (žŸ½}amC°àËÕ#Ѩ»~ÕMìkú»ÀÓ¹ !ÑzñfäCAü-þ +ÖŒ,"ë•ù~I@ªò㸿οпÎßë¿ÜÀ‡ÿiÿ{ÜgœRìûÅ„·Ü—Ô»ê}Ë|[\í¾í¦m¾ïù^7ÿÂû+ÿ/Æ/aJ˜K]¢(*rÆ â.Q˜·W%C¼±*i ú +¦€ßoöú|œÂ t)\^ï(ãäçù¼n—KŽe.yÙé*ð›Í~¯Ïäõúü¿ÙàÆÈ„1 +MA¿Ñ(÷!ÖUP PÈe¬Oïc|Èï5›"C(ACü3Ç”UIó(;ó)ÿå>bÆ|B™o”­=H JÐ(žÉ«1¯«Jjqd™Å£ì‚¡ý~âN³«Ù5(oæcçbà`ÅνkуjEÔ•>u5 ®Æ˜01Úb¢¯:^p—}4™“B˜'C¨'­©¡rK ¸Èh+ÞŠY–[&ÈŸJ/(9"ÇPDØ€Å^‘§C¦5ÎhRŽÿQiué” +]ö²á¸-Y£Ìö*çmíc ïÏîÀËÄ›¿¸}¡=bvƒÆ"ÏÀcO×UÚ¸&d[n-Èÿxâà‰ÏÉéÁIÞ.a,ÌEÞ½Áo{ï >(}ˆ;)=áUH¸ÈÏ: ¦ÌõV{çˆWD. +ÞÏöžTŸö>TZ@Àõ>­®ÖQ(\‘ˆÒ`1º ÈZàBz¥Î¥€[¬&‹Åª¹<¡$+÷xôˆ1èe +—ßX-:?q¡EØz¬0òº’8ÌVÆxÜ°Ç‚-ÄaŽÊAE>yÅy9\Xòþ²…ÐüeH÷<î²ÜeRv¶LxÍ“nóg>3Äáib€1uczˆ_¾Ñ>O¾©F ] mmÁ^ê U™àU‡Dá +žæ˽zuöËÛ.þVw¨b£büå¦æÄÛ‘të‹[ë·Ë\vùìVñüWvü`È—=pu!W( dEûãþñøã®ÕÇ[3ÛõÄ7¨ßà°R5ø6þjY•½Š1¤J/*]Z³É2dÞiyÌü#ô³|YÉÒêMr¶Ñ¼­6³¨ÆÌx#Ñ4sXŽÓ¡ºÈÂȺȧæÏ,Ÿ¦¥¦êš£\ +OKWY¬ârs1vN/)/÷89“ÓÉŤ5H‚XÖc¬156Òiœáœ5FbX¾žeXÞY󸑟•2ò6{ÒÈ›SãBã:ãÆCF±q”Iòªò “/Á%Aî ÁIÔjUÊIÐìIššÌù´(ISÞî$NÞy/ªöér§Õh…—*vä—Y€þç]C¢®<ègÚ’>iÉÇêMçÆZtc´æY0Ÿ1"»@w¢±'( +ÑMÝÄÚbÉÊŒ¢X²Þ¦«Éûìà“ÀñBmf›2m†ˆùTéj¸p¹ášà±Ìž_'|ÄŠJæBoQ"%¡lÞ›ê×2••ì O„ÕJ}´Ù½°¹²<\¤Ö5>úΆ¾h§W˜ çy—òÁxäâ°ÝìÝôäÀ »uü±kü½§Ûº«:Tä÷M›÷yöƒ×ùÒÆ;qª×©Ò»×[+cñ`Åþì³WûÖ™øñó!˽”#‚ð +ÅÑt4+øôͳî387¦#«§èÆÇtg‚ÑeR*ÍàÍ<>Òœ¶¦'(K¨HX¥Ñ§¶ÔiÉÒÃD +šKG–  Ô/,7ÐÅw+ñBAÎ ‰ +ĤIHðG­Ò¤àtb‰°ÄJµ@Hs=lìÛú£M)S á÷%ˇ>¸á²Ÿ­LÇœ——,¾ªçŠ¿¿Ò¸¾¸iÕÜ­·\<+Õ6;’õ.n®YþÐ?mì®f;+âWwt(¹"ÞäÕ‡’©ú%{›ªÛS±·ñ¢@,²ºÂ|`Å·ÝÜÝ‹ÖþáÒ¦ +Uïßœ63VÛÚžcQƃÆxè\oäå8·.Y®¿Ëhª5AØ#‹[“qÆE‹¥KäKÜ‹¹!|iñ>÷Cá"§™Ó!åZ¼6ò–œX^™ ò©±T‡n¬Ÿ()>¨ +f× ²Iß8RÖÜ8R±xõÊ'9ß4à/²@—0k¸P|c\)9¿"@²Ò0~ᚧ¼¶l†k§Y'WéSuž–檒`‘oÐâ0„çÝ»*î)»õ$çw¨Ü! ¸îil™™ªiÏ®iÐiŒêÂåÆkÒáâPb¾¹±Ðd·¿r߲̃LÿV«Å+’€g4¹ß‹–ƒ¿X—ñ×\StEœ¹X}±æbí&u¯¦WÛ«Û¥Þ­Ù­½T·§xOÉ]ê»5wiuT¨N/-îð¶_&»TÓ_²OvmáµÅwªîÐÜ¡;Xþ=ô¸êˆæˆö1݃%ÄOáçTÏhž×+9?Wⶔ,V.R5«×/K$&«ižj®fžîꉶX]"’F\£¬›WDÚÍþ½^3Ëxò-c„#o|¤# zÛ’µ}êñYå‚‘ n?ùa™Õ’ßÚ+§ WЄú¡Ñœ¦Ï'=rÃU{=ñŸµ”¼þд2Ï’*‰Fï*,uúD÷^Õye3Ž­Üò³¡šÎþ°£ÚëÁkHì{ì¾®ÙÓš_k/]¼êÀËJ‰ÏÊ°îÒlmMp莋æìÎþþ¾5ßßd‰iA,¼>;‡½tÆ4lä×ÜYŠKmU)¹ÝaÚ§ÛbŽ3§Ç#£e/²/Š^¶¿ìP78W9»œ¬¨4‹]1·£Ô¡‘s/±HSæ-8ˆ+³ŠRÃÓ^4!ià¥XØ­õŽâ3|e©žW’Z½GÏè#ªmV²˜p“õ^+³ÈºÇ:be9kÊXkCÕ´†ç+q]åÂÊu•lå(ëçÕ¢wJɪP)Ùü+¥zÁhò¦Ò{K?.e•î)e¸ÒD)_Ê–’ňôÄbDK~1¢å,=dè2ÞYT7þY‹ÀygŸ:üÈ@îtíNôBM>ÎÆýœYã䲄R!©°©–±…¶ŠJ–„å ¸>‡º¨¦¿rq©R¢©'EµÝÙŸý涛“žøŒI-3ÊÄR‰¶²a}É4Í´™æ +9»¯*óí¬iî]ó¯ZÄéôJ±Ü-kàþ4»öóà èa^.ŽËÄ +ß¼ +µÌλgK‚ÄK\‘{ŸÙ(º¹±äƒªßªMkymúñÇÌv™s}†Ù€« +­Ñ°ZÎÅ1»¹9Æ4Z,K¥ÈUàvbGËmÛEX†,»]$boA÷‚…3*A‰{,vpêíOÄnÑ1 +ZÖÃ29³Ý:"ÕkNCð&ßPe°ðéäË«ÆB÷€<ÄŸ÷\°Dø´²çc!ô´zRk<þXy²æz6ï³OñÛêjÎŽÓpŒR å7K)­Ä55˜8p„`[)¹1[.õ£–õ“øŠ±.¸[×c:¥=jkö®]2-]4{ø6EÏÍ«EWd?©?º®@oð›:ì×V†*c½Ì¬°{Ç-×þÜûâ•f¦ž¿ÚŽ±aZ1^%_£Z§^aZ;­¥ª¥úâšeK:]–MECª!Ë΢Kjö±û‹ö×ì›u7{§æΊ»g=Œ«ï«|dÚ‘ô‘ª#ÕOÔ<:ûþúÓNVœÜ\ÑY¹i6XØU³—,a÷Uì}{=›Iï¬ØVuéìísïOK"8˜__Ö»Tìõ5gGq¿4²$ÑÜ„ÔURÜ0C­¨Â¨1Yª×Ï(•J›_DR“Ýî‰&LÑhBQUå©®5UW×¢¹¨y®§¡ÑÔÐÐR6Ì[]]¥ˆ.$¢µÕ +:ß°—˜d»)˜%[{ö`”פÖGe¢àãŸì­ÂGªp ÌÕ¼?UÍ; ’½Õ¸z‘+‚µWŸÆgÐ\†=Þøø’—òk+4ñ§hâ¡É1hD³ö|¶°ˆfyk<™ìmø¸i°/Z«­ +ÖèÒóÆûë}\}â÷ƒ‰kÙ +åS,ùä~; â'í¹ì¹æBÃ~Ô6ü£Ëøyó>ÕÂSE@þò;…z5xT5BL0Ò +28êW¦Eùå ›ó‰•®:›j}àMÝ£$«xT±ä©aj”0±u¯a&\„ʉ}º":é20R ë7V +Ù0~æÊÓ×­NU•Í´^tÿÍ‹–Tzr‰BaO—yí»W‡üñèÃ*UÚÂøð% ëo;\`Ñyƒ5Ï&íû”Mñ¨«Ae§ZtÙ4Ž/+]˜Å¥—ή›Y5#{énF!5Í5G®/KøßÂ3zUFƒ]£‰í~綘– +^§ÃΡm•Ù_2{—å¿*ˆpöX™—ÄÐ,>É[ÇV×±ÔM[«“ðÖÖ™i$2Ôó‘hÒOÊv?Xb¸Õóe©zÞ— +..YO«S^_8 ŠhÖL‘? ò€Î‰<ž° .ÝAgùÁébpGyèß?Š7óÆ@Iœ¹Ö3;öè*ªÀH2Ù£ÖR5ad]ÂÈãã³=VÏlEÙo„]þs-ãcãc“û ÄÆÇjêÆÏêΞ$óÉu/¼ Ó½ ,LngœB"˜0Œƒ!ž¸‘¯Æ]Çð5¦:Ÿ¯xu—ÜêùIîXEW +A‰1Rª¼ÂS–Ã…ˆƒîéù+ó€p„@°GS¸„i3ÜÜÓ0¯khíÚšBDæA³N*7ÆÖÍój¦?ñ„¦yfeQużûçÎ_[ð„rµ½®lVÊ9—Ý:3Û˜ýÝ=¿[6#`pqŸÅbÔHåbiÅæLá‡Ìƒ3­3V]2sÕª¦b"`×Åe©"’ÚZýG²ïDÖ-Ž–T#;zœŸ!cä¬DÁ>`|Âv¯ó¨á¨å9›dm•ýãõ¶ƒÆ»m¤Æ*ûEÆû +ÙrÃR£T¡RéJ)+["¥‰lT¤{›“Ò=³R7JI©Ý¡!ÅaD<ÄÃ3ÄÏJ!àÄ»Sä Ä£{‘ýЙßÏÖ|›>˜8Ô$ªÜòBòHaLìCÓ`/:ÆÀ;”={í¾ÇÁΫ¯>üК¹·üm}à +cÝš}ó±#ûoÁ‘Çž˜ÓÒ–]óêº|?ÁÂÎÜïÅÏ_­C>ôÄ ÎVŽ(~.I{UA•o¶}nA£o)³BÓlZf^íºØ1o*ØäÙnÜYp™çÓ×m’oï*¸ÃuÜü¼ëY·Sª‘}9bå2¹•8Ó«xSZůM©ø‹Ú“ªŒŸ#¥6ïQ'âÍ~¸­M‰È3oO‰F±õd_2kÁ9jùŒ"äI? á´°_†Ë,‰ø*V²2=±ÔA7ŽÙ?_÷êöñlç›wÿ<óTs{ÚŸ¦qíÍ·­9²nÇwooÞöÎ¥of½_î?»ù9<ð÷kù¶ßŸ|ûÇ~³zË>üÈèÞדsgç±?.ñ£2ÜÌ7.Ã7¨îV=®zF-N›ÑÍóÜÂe’Œf›fÈñXä”ì™è©Â—šY¾Eh¹†M ¤G,VJË4ðY¬ ‹YcJ˜ýõÎQü0¯‰øþ&ÀñFÎø({ï#ii_ãÉï5„ +%´Ò:°£<âtèŠN³W )èì’””¨îh> Ó„7s))ïI-”b^ºHÚ'½WzF*–žf«bcÇ~ÿ(Ý7(K9ˆGC÷" qº’;°Ó^î°:Ê£lÕ“Ë'• !ÀÎ÷mqÝظ°Õ,¬Wn%‹•cS·5EìÓ„ušºfIO g‹ò¼,Ô"Ñõ‡èªsEÅùmL²rYË +«TøGõ[¯ZuyöŽ?•5%,Öd“<U´ÌŒ[=œ+ÙSÛ•ìîX2£¡´ûç¥ì¾w÷l¼aëo³iKA6;œ<}0(š¶›ín69ÝÒð¸q^UÿÁ—Û-ûü!rþâ5„DßÏG!TŠ‡ù]2‹<\S8Í/œ[6¡KÑÏPñ­’;Š-Ÿaxi^—8¢%à”:˜J¥T"™ +-2–ELFBåÝÈM‘‹ó[Õî|j´AJ$¤——¾."‹Ó&ÆxÂHö¶Œ£ùÕg’òòˆ­ÎÈkíµFºÏ` )]‹6ΰ¥IÙICÚÈë)HÞbÞBÁ[ö±‘¬v—ÉVc]í~áëkôoâøÇgTuM¬e[ÓŽ°žm˜\ý¢ŽÍ?Y×8EG¹„Oð²’pÞÛ »çŠH+ó+ÞR#Ä6R,,rÏ°ÍoÌ_´Íê²lÿU9Ï5rþ1[ã>ýÖ /¹:±~³r|%_öØOví⊘[°.»qQe¡Í Y•ÞßÁ–/).áqð{û®zÕ¸y¥$ÈüFþüÞí²‰UïnÐ ¬æçPõ!·T„cá’H-ªÅUâÚpmäzf¿w_ø0ó@à„çX@çj;Dv±#ì‰H® áááðC^Ö"¦ÛGõ)šXhÂkü©C‘#&‚PDm×bÑqW@! +’UB§®Òßò>w:f•è%SŸ=¬ÞÓœŠ«ëÔ ÕëÔ"­Ú£fÔŽB1An <ª“,”¬“ôJD{$÷JF$g$¯JÄ{4¶<’j+5;Y’ŽAô9‹ÕåRé^jÉ{ [ÉÉNosãHÉâÕ+ŸFžÜûÀ¤ï“óœ[©RJ¾rDŠæj™¼¹?¯žYgçëÛ:Œ½û·t‡ +¢ž¨6®0ºRÎÌ^2ØÞtÛÅoîÚvïußÁ‘SkfÖù"n#WlR‚îÞ}Çw4e€»@¥­w"'z™wHx9ÓÁlgÙgÕb’é¬ØªÉ´òQ<í˜LŠ%3”x’">£Ad‡¼óF¤ÓbÉ":­öÝü&Ÿý4>‡¬š—;H,“ª~š€•t0Êc-ÖŽ²a^©ÃP†­¸@qš‰à?LìÜRö}Ör¶æÓzž@wŽ*I¢#IdLÿuÕH5"`Oî² |>é4ÙÙç +Ê/VŒk–8 +Í^ßûf† +y•j¼XÜùÅ¡¶¢`X 2Jƒ»dlPšŒþˆ*p1µóï³\P]Ï/HYª¹¹’yÒ÷BÏ|n©u5×ni·ö¸{<›¹íÚË õrϥܕ–k¬7p-ß²ÞÃÝo~ÀrŸõ°ûwŠ9n>j9n}Öý<0þ‰ FqïP¨í‡÷¨±ÚôÞþÂþŽý˜Í±bÖ:]Ø‚òÞMÓá4ᤙ2=Í"x$‚€ðì8#8ïk4è“!æ…=G®Ü~qGÍÂ+¬ì¸·ëªª»«WóÓcK®Y-îüå{/fÛoÛ‘rÿòýwÞÚë×&×dßþCöW¯uvDº±ÆÊÞ.à˜ +¼“ÉàbQÁ1tƒGYýI1cm9@Fw¶IwÅÇaT€}&ÿG箹°ν/Z +qAUãð÷HÝdqY[§oE—’¯¨I*ÈMiK¦’J¾¬²e©¤SáPv)º”¿S¼¥”Ô™š×™—•‹Î7óU#Üàn¨^Vr]êV|§éóCè$UœpOKi–"Âø¯)¬²AU©OM烩é¼?@AŠ „BÆnk•ñlhÿ•EJñ&¿©<9«*ü&ÖHN#³(ÎzŒ!°D¡ò'MæÞ<êN§ÉYv¥Í¦Qk"!£²ì±Ð£’è EŒ³ìž¤rXAü† +ù¬{’` +fñ +ölü 2ê Éi7žf’M^ãmã„A:yW€î Ð +6^_’L~ì?£ŒJ¢ìá Ï)p.¶õì8˜‘1²á}Áqô ü át焧1·PÿBFÝ‹¼e"‹-Ò~Ü?a¬Ð…fÿÉ¡ó)‘lŠ%ò‡h$Zšý^^®6øùæÞÂûŠÜáoíXÒ8ësw]ÚQ± ´A)UiÍ^kÊ9/}yöã™%`|Ѿޭ0¨mëÍí—%ŠÒë/{{yõuƒñ’MËŠÊñÚ %â0kôÒàø¿ »þ¹Æ…ø`ergçˆ Ù;€n^ÅDrˆ±]T—¢Üªû Å›ˆ yS^‘á‹ÿù³s–‚“} ;‡©›‘¢‹÷NÊx­.YF—2Â4å]êÔ:õºàšÐšð- ±#Šõ¡Õ‘x"1y´Î«’ªÔª„Ú ™‚ÁeÔÐiƒ¼6,„‚:yŠ5…©›X̳‹X†]Q¦ecdž00à¡!÷Yc•c”MñÊЇ¥Ak°trqD÷Ùgd£¬eŒšÆ1ò“) 'Ç Î>]3©a2 +¸Tp…Ο‹›z(O]ô¤á(=^tÞ¥”HSøÂêêB¸ª²ãõ¾¾nF)ç²ì†U©¿íyÕzµ]l¦•àÊ~yÅ'¯WE¨õé„7,2°:6<Ã.@rˆR +é"j!=IÒ4VLSÞPZ•ä +qá%åòB«Á +}CZ÷ä${LØLR渀7Æê.ä‰ Vø§ ,—’ƒnR +4•NžxÈ–©ôJÉb;±®9qˆ«˜éÊ•)×þ Tuü¶¶»z×ú/)žÞ¢ÄG”óg•yn¹èòŸüÙ?”2ϵéñü ãš×žåöDøÊ¡‡¯{o;¾çθ7.QlìÎÊ?ýàî÷VÏ*êÆÿÑF%„žro‹&ÞŒ*ÐùùFÞ”¨Ó¦tiCéjÃFÏ |P=T¸=vµêVÏItB~Úü¦â—½Ó t€x‰2ðþôz·Ïkòéµ>/.Ô2†aFY†WIËËo®ˆ³„NòÝ@á+‚{ÑÓØŠ¦!%»›×Fá­QòÁh¦’,ÂнŦtŸ‘ïRt4þn 9![Òvþ ÊWù#rÊ_Ø6äX‰Þd˜ÐÁä`!=P&%Ê:ÀœÊŠÉ/þ ’?~{ö¥Ýýƒ—ËV­n3; +/.P2IEÓ»>Ô¾ï{-¿Ì~¶ûÛÿ}å±}k[Üb÷ˆ7g—56Ü–ýí{Ùÿó\ö#ƒ·ÌŒ®pû¢Î+³T‡ïÃò«FðôßÔ­H­EDcÿ'BâU =q<÷„Ù§Køñ*{UR¬1kn =zVtBÿTHŠ5„5Z-’©Õëd.©Åáe¸3o¸Â’¹ Ó*vIÌZ“Ë, +â ›¨g­–ªg—;^dJÔ9ÈXÌ2W"âvé$ )/e^‘þNÊHÃ7£P"ć…úB⣽®%½›­çU­Ë㊻Ø=.ì"ñxBoNÐxüË)ñøVá[tÀ%|]Ã5ñu +oK»¾úu϶6Ond Ïj¾þ­–|R2ö.8ŸL)¹NLbui~’îlMÙ/ö³_g 4ÔÏ?N`î¸÷è%;êB7D´‹{oç*7«ÆßW/pDŒÎàÇ.Gù|•¨ =¤lHGö‹EãïÍÊjÂÓge;¶‚î@¼ÝÖ¶Ms +Áì#µ‘™M:yÆ;; ~UžBö[G‘¼”o5(ÙQ …„Wæ¿nd·õ,ÊÂMãŸM(Sü +v +ŒÖÔÂõ(9b;\]H‹ªÇ‹ªó§ê«KW”N‘óǨUâ;ùíR‘EÄŠuÁºÄÂÄšä¦òKËûÒ×'*îŽJ< x"z8qLtBñLðù„qyÑ "ÆWY\\DÍ?v".*.ž8„œ +ÄKŒ…%¸²Ä(O•Ä}7úŸÏˆ£ÌWYTì˜F– åòpqÙ(»ûX +«Nã™(Ìî>!áõ†¤„¨` +Rl=‘.z¶øÎQ`8ÁAN§Ž8Î8^%§“sgNèS væ›FÎ)OûÚw…Zb-ù=YCÒÓuE‡Iþ$°¡ãk,H˹­ÐóöÂÂ=7e«#ÌØž"ýµ#1 /P2Àt”ëG"Í#Û¯^y4iŽæÞ#+#1(¬…ˆ?â‹ïbjèU Ÿ9]æó¦Ãp ‡¬ÈZ]L¢w\øµ$ŸñüúÒ”¥&×à³;Ÿ_÷Èó—vÞ?°ä‰¬V½  ¢·Eþê©lÒ?3ÃõêO/Û˜–ýn÷ô»þ|ð!®DÎß;Û³Å%·¯ÉŒn´éƒŒZ_Ú˦: ƒ±ñÿdNìíP}±FóÌ}—³Ä&Ø zÿâÏrð±V¨|¦tŠWk“)ÞœJñº”B©PÙ”vÕtþA´ÒZ—šc]n9ƒö£˜çT„&“ +„-Öc, +GÂúr{ÔzMB­)ªòlŒlÒš#e‰ò&d²Ù<)aF"²/U¦›ôú0‡L"U“_)‹ òˆ'3E£1µJ(ÜaŸ2Õ©)÷°gŸ:i;5 +=ÇÆ!0¹EÅðÓGË~¾Dóg¡h6¥YrTŠž·ST¥¢ödÔJƒDjƒò»©ãïC4>¶@÷.p ªk"ßU? +Ñï³B`˜?l'ûŠGðõ•ÝKR™®F¶LGbGÍ ßgÎñ#†±ðu)VK*Œ™!Ã!VÊúñÄZMŠY=Ûÿô4ƒÊ_äWâŠÆ-ån¹…«0Mzk²Ú¿e0Qh´ìë¸ Ï/ýÖ2ñ/£­÷Ì·«å:E($ +‡]óç^ñËHDj¶ï[á­Æ·îÈÞ-ÚÖj7Ú8‰7Èo¼öÑG‰‘Ÿ¯ÓÖ|*³ËèOÝï}v◆Ȏ&D$@ʅߣ£í¤Þl=Z1ùƒD6$½à§Ú¢’4./GÃ"„pU0i´½ñ ù%„ç~ȺP!”­„²"Ö• + EÈÝ×+P¿F„r/A†KÃÞ[ u—ŠŒüL:{'yðN¨ã†ú¯AÓ l\;™GQE¾]îc¨{¯äÑܳP÷M¸@Ýÿ„ç;…6&JÂcN°;EIø|,~B²GZ-ýoÙ#òcŠÊcª‡Õß×|_{Ÿn…þœáÆ-ÆqÓ9‹ÜòSk«õ¬ +Ùkì+&ç‚‚Š‚1×oÜ.Ïͧ8Š¢¥qÓ_~@:úfHt¥â ”‘é¯í¤ß7¦è~óŠàÔMs,m¥ÂÌ¢>*,AŒt»‹‘ +¿ À”À¿`)ú5£` +1gXŽ®e¬/go`%ê—½+À*´‘ü"…Õ’ãòçXƒÖêú'©¿[÷ŸŒ‘Vß$À ’è× +0‹¦é7°Yôw°©ô#,A6ý3,EÝú×X†Œ^€åh–¡Y€Ìaí¬DióŒÉ_G,7ï`5»Úü¸kP‰] +#Á"‚u=%À"(ŸEa1-ß*À¤|7…%ÿöÇpn?Ea)-G€IùŸ),#å—C¹#Ja9¡¯c™}Í õ[èëÜ%ÀÐÖ9&À@ß»} Jè[Ð*À@_WZ€¾®u ôu½#À@_µ}ý 0Ð7`` oá)L¼MÌ/À€“Xþ½J(7ÅÖ °%cV=,À"”ˆ=Ea +”Ëbï °EbSXGú/² +0ô_¤°‘–7 0)ÏÏÑDpUt£~Šî¤°™Öÿ±“ú¿ °…”³ åÅz +ÛI?Åu ý7RØIëï`Rÿ +»hýcLê?Oa-ÿP€Iùß( ý”øú)Éã­–¯`R¾…ÂÅD”Ü)À¢ XFñ? “úP˜Î«äWLÊ)}U´~Ü(ÀP÷R˜Ò%¾P€.ñu “†PÊ ¨µAÊ¡GàZŠ:)Ü„zQ\ƒB-Í‚\?ÀäÞ +å]´%Ýо Ù´¼õÿeOñÉ‘q¨žt£m“u ¬ÒüûJQ> T,@e´t´è†t ´é€1 ÒVK ¿¸úÑv¸·Ã;ºÐZÆ¡î uz¡¬úo óè†:m_ÕÿЖ» uZNß:09K2ÊipçÀái¢uúáÉ\¡]ôÕû?ëû|ùη_8-þÊü–þï|‚R“Ъž‘²~´ÊȈÿïéÌAi(Ôo¤ó tá Oê +½.ƒñr0jÒžC!ú¾&¸/„wo¤ô&#$í2Ðë{§Ð[É7Œ)Ï[½ð^2¦>¨;ôOke(O“z;è¨:&ßÛ%HL1åÑA:†n(ðÐOgEz-‚’å´þ -çÐ|Š?‚É:'»å”f´U/XnEhÏÜäèÎË+G?ÅGçBž¶~½Oä'¨5•ây:ΧãmhÔC19}¶Ò~ûéL6 +sØAÇÚwÒï -i¥}µÓ>‰äõÐq”Ð_îl u:…: Ñ(­¶”ÇC7ÅÝȵQ¾ËÐqõéÆ)±ƒŽ¡ú&}m¡²3(ôÚF13Ÿëž‚5ŽÊYf +c›ÀHžjO­´mû´ ïÎsGéÓN¡mkŠ—Í aC]´¶)±Öþ×|’—€¯Óo*†ó8êFÚ3YF4Ì6ª +9A‹dÐ%Têz(µ¶Ó>»9Ìã(_ÖGÛN`5ÏEÛ©VÞ>)×ý»û')´y’ç¾*_y<ü{2–ŸÝLÊ9y¾îž/óxèôü…Ïó\;¥~ž»·Q ç{ÚFçžç"ÚéqÊ[§è•E0×VÚ— Ï]ps^GÑ‘uÓt¦Ý×uR:¶ +ïíô™Ý¥ü¶ 䇌–HÜÄ 7p”+óô ón£º®{’ÂÝ‚ÝW7Ý0ãmT×æ{ÚAŸtÒÞzá“×™mm¶@›<®W@½vú†!GSõÉÚv³0Ö<†:àÚIëN™ª+¯çmÀ ð¤÷ÚNùkÛTœè¹•êôÞ)½µSüõQš ]P³b¨Ÿâv‚®%ÔþBý*ð+â€ò)¡Zc*G–Z'NëoÞãp¤š€Œ‹äÐ:Úw^êòú±ÒF–L¶üÿö;(%&tâù·,)Y +R?®Yàóx!”é™Cµ)¯‡’f¸¯è"°èõði¢¥K‘)èuÞî|ÝÂL”wNÑ}–‡&5ó¿geÏÓªK rž·&´ßå׉w’oŸâLÕ²ãÉËÓ–)6¬•JCž³z„Þ[é(2Ô¦æ9Œðù*ámD:· úÕÞ]‚åÊ¿çŸafÂ_Û!X\"K]StàT-Ÿ—¤·|¾z…yŒe.Ф2ûõ÷µ š¤ŸJþ¶I±A ÌTÛùÍøBLåmÉ×¹âëoîd”̵Rÿü¼—ÒJíD†ê¥o~7Áþ2ÁFæmÊÐ×h‘§Ó…>a^¶ÒõQÌv Zäß¡9'ðâ„ï˜ò^¢;Ú)¦óö8oýû§ÄE“µû§ðíy¿ä_cª›j®¯èôóýMØËÊ罂 w¾f/ÔÍ{ÐÛ(ÆIÿ“óÉk*wo´dÿy©êøã¼6½‡þÕŒÎóGû×)7a óžÝÀ”Ùä-M¥jÏWhÐÿ|Ÿï™Ì¯—úrí‚-!~G>B™Ðÿõ'úËËdF°§Úʼnþ¾NÇ<¶ò3lù7ÉñÅZ¿‚ëÿ«ÑžÇò×ßÐ&øo„ÜÔeK8¶g¢?Í@ùH%±a‘ÿÅ‚ƒ{)äŠ!zNÒÿÑ€¬-CBÍ<-…'I®„¢’¶ª@)ˆ(ÈEzÿßÙºÿ{Ë8ñ,þìMÚÃ¥C}™­mînig†kêíé„"nVo_oë`Wo××ÝVÂÍnlý*ÅIg\so÷6R2À5ô@»Òt:Q ·²nFw7·¤«£sp€[’ÈôoÏ´/íÚ’àdvpKz·´ö4 ¶vwµMô_õ•§\þqÕòLÿyeYÉ´2.ÒÔÕÖß;лq0úÍÕ§Ö¦5 }¾¨¹XxßÒ¯´ü·´¿µ=³¥µ3×»ñ_ΙëÏtt + fú3í\W7U—5s‹Z¹·´‰[¸qc ×ÚÓÎeº2;:¡ZÉdO€­ÞŽþ־Ρ©Env뎮žÒ¶ SÌ5¶ötg†` ý]½=EÜò®¶ÁÞ~n~k{¦gP\^¶´³kÆB†Üº¡;à +NÐucWÿÀ ×Ú×—iÆHª“”L+?q˜ãüÞžv˜QOfÇ@_k_¦¿ˆÛoØÑÙÕÖÉu +r;Z¸öÌ@WGO¦½„ÌrP2°mÃ@fë6C÷·!ÓÖ»%ÃõödH;zû»Û¸-½0€mmm™Ûºéи¶þ ÅáôFSëèêiíæÚó³àv²¸-@n[O{¦ÿ«XÀºú3m”†¾Š Àäüò†õ@§=êïÝÖÑ tá2— fzº¶g`’BU€úú{ÉPEÛ{»·JlÜÖ­ûÉ„6ÌMÐ Æð +ƒ×Íl\÷’þ—0†àyaà€¹v® +н­m*m -eúû2ƒÛZ)¯,êníì:wåÑ 9Äõv·sƒC@Ú¶ÎÖþVh ½ +vµ +p¶åéÓÚÞÚGzìå:È<2—´eº»É„»G7tuw +Á‹·õuC¥]ƒ\Go/p&Œ¥wËŒzEW{¹m Ï'z{7ÐmiíhÝÙÕ“ÈsE$`2½ymïmÛ–Ÿ"©ÜÚ=ÐK«µw +ôu·å Û·gú»È\K:ûªâñ;v”lY¬ïÜÒß2Hþ‡§ø–uƒ„tÀýD"KÈóáŽL7áDÚdÁÂ¥ +sfÍXÚ°p·p7¿aVý‚æznÆEKêë›ê,U+Ô +*;“CàNÊ@:À0ó7ˆ,UL°EØo¨wiÙÖ»ª‚<Ë’~€N[¨„µr j€Ù2\kG&CV­‚f­@¬Þ +ƒ­€a Þƒ!zm.—题gy ÒF@Ëùq¶{;2y&%”lDìï®a˜‚tNa`aP %“¨˜l p+·½µ{U)­™Á©­K¸e ‘ )C³€9 š˜°•èË´u‹|}æ`ñÿiïÚƒ›8ÎøîíY:? ñ°°A+[¾ ¶ðCw§Æ'c™&jÂÃб +Á0Á5Á®eÓÒ„'a¦a&Íéô‘¶vÚÑø|â!c +t:Ó™þÁÐéý šRÚÉ v:ôAÕo÷„”Æ&ôŸÎèN»ßí~¿ïûv÷¾Ý“vçVÌÇ_ä²={÷ö±~ ݈?V±ì!Þ¶|,y¨Pú^êËy:DZ~™¶ÇdæyЗØÏì€.»¹_—„òí<ì³Ý4×B³ +ñöxfßtåX/„Á.ÁÍ@§ÙÓ;t0Wƒ¡\¹98±`:ëPï¡>x 0øÏê3ÜÉ^觹¾ÈpSu„baèåÓ÷˜U¬'Wê}VË‹<%°ƷݽžáfØÖ‡ÊʦP¸Æ6Õ5† ·Å ³1 … ëa_xÍ굫×ÊEÿ¥×}bgd©†\ñx?äC¹)³ž9§êg£ûyê«èμdg£ûghšŸ¤=†Ü ,yL’3$M&Èø\raó‹JùE¥ü¢R~Q)¿¨”_TÊ/*å•ò‹JùE¥ü¢R~Q)¿¨”_TÊ/*å•þ•àY÷8³=³Ñ3g^¸7Œ<Î Ì”Ìô¯jÛûçÿKÞÆ·ãÍžSîÎþ}ý  s×y&zºØSmþíÅПr¦jj¶ë0ïYó³Ñ¬­~›»ûs×uZ,׋†›Dm.ÉYØØcÍÎFÊ6ÂS>Ñ?—Ü,ì&4€{øèxpí3}»}èC~5—ìlô“ô»'¸§Ol÷Iú©ýnMöîéŸe+aÈ}Ä1‘½J&ÓѨfd€ê9µVÖh6£\ÕŽF‘It„ëDÐ:‰(L +cðxÂZZÁ¥2V[[îbM“}‘®­ÓnDŠHÝ… ™€1žK¥WÖk÷"ÅAí„! úódÔj¦¥‘2’F.b!„M!Ü„à€Â¤Ñ +w!d!ˆÈMNY¼I/““¸¿ J¾Þ‘°QB“b²@H +I"tO +&ÂÙ«¸ÌZ¶ï8Ò[¾Šy'XÆOɸŒÙÏ^Ƭ nd€Ôs’†fáT}ʦ•ŠM—û8µü6z™þÞ%hÂMaì1He +úsºYmÑ.‘×؉š%tŽÊý»¦µc/>J+õ:Û¢‘݇¾Ëd”ýÙ.°¼ÍÅx›·³MLFÓÏoÖئYé +ÏilÿF«ƒmG0jª4·²¾‹ƒ,Mg2V­îfÐp‹æž…-HÏþÅX¢´èeõvÍ¥¨!Í¡Ôê%`?“ý—Q­Ôé%Í +ºöå´rQù¥"(k€«5iËškš›š‰G)…gW*MŠx‰Œ²)2\´”²ÂÓ¯P¡˜6êP«?¥)¯öQv" + %4Üís +ÝŽ1‡Puð…gt¶OXÑZ¥Uù[X•’VÎIk”¤åõ¶?\ðtÍ Á+yþs5M]¥GŠ²‘$›AÌ~ 4ôCiÖ}ü¥âÍËhC³æfšêuž§äúU]dÉgž +1 + +ÉI¥îa@–¬Ð«ÔFM«Rõ&°ÿ±Q¤‚ñBµ¢R;~La’d'R¡bõ4L +ŽV9)Œ W„ë‚x’Œ‘+ä:õ6!”4V²‘t“‚ÒÈjáÜÜnˆOB¸!°÷² n…0ÀScàCm„4"¸cÀeW­Ì‹9§û!ë˜XÄîÀi ZŒò0FØÀƨ HBeeÐÿÝ %#R,¼,øá+”Œ[xæq…Q’ßÉo„äý!9’·†äφäU!yeHŽ¸„Õ0àÈB‹ñ?yüsoâñ*£Ü'ßóÉ—}ò7|òaŸüEŸÜã“»}r»OŽÈxn‚/f-b³pöÁi¶n³OÛìÓÀüŽÞ¶¹ѾÎ6ÛÔ5.¡¶øú6]ê\Çý`á¹–£ñròTˆ›Eþ6³Ø߆Z[=×gpà ŽÓyN þt¥çÕŠ‹"‚&gðÈ–s¬ºH]„±Àkd—æXžWŸ®#§r,d/#àÇõà—ýQ³v{y¢}íðÉ‘###‰Äð;@@팙-ì¯UT5j.ÛÕD=}íßPÿÜ_¥·2!§3j ”H¸\ 0b_€nvùð1lçq( +$¦òÙ¦V(Á´04)Û0Ô»œ?uÏtÐ'²÷Èè¸[gà8N 3iÐekHp­ÿ 'S +endstream +endobj + +75 0 obj +20848 +endobj + +76 0 obj +<> +endobj + +77 0 obj +<> +stream +xœ]’Ënƒ0E÷|…—é"0„ò”²èCMû&)RcCùûzæÒVêtlÏã&^ï7{×ñ«ï›êÔ¹ÖÓµ¿ù†Ô‘΋´Qm׌ÓJÞÍ¥¢8äîב.{wêË2ŠßÂÙuôw5[¶ý‘¢øÅ·ä;wV³õ!¬·aø¢ ¹Q%QU©–N¡ÎS=<׊%k¾oÃq7Þç!å/àý>2²ÖPiú–®Cݯݙ¢2I*UîvUD®ýw–%H9žšÏÚ‡PB“$K«ÀFØjæl˜3ðš9çÌVØ$ÌêdÌÂ…ä.¿`^bß2¯ÀÒw-œKîuÄa‹}©¿C<÷Õ jÌð·[føç\Sÿà¾þ×דÿ†þ–}4üíŽþ™0ü vÐðÏù^þVzÁ?eg +ÿTâáo¤ü-;øç\ßLþKføgoàŸó} +ü3¾¯ÆÎþ©äNßŸÝ üíJ`úÓ< +<«?#¦š›÷a¼d e®x¢:G¿3?ôgÉó +(\ȳ +endstream +endobj + +78 0 obj +<> +endobj + +79 0 obj +<> +stream +xœì½y|•ÅÕ8>3Ïv÷}OÂ}nnö„$$7„@$OÂ!a'h$!¹!²….D‹¢`«.-Ñ*(Z b)ѶZm}Å¥ŠÖVÞE­TÚR¤•Ü|ÏÌ}² ¶ß¾ïï÷Çïóû˜8Ïœ™gÎÌ™sÎœsfž ¶·v„‘u!)5Õ-MÕ B¿FÛjÖµËýÁ‰€O!$MªkYÕØq•"¤õ $Ì\µfCÝk78ã2U!4‰Ô‡«kÇ/yÒ„PI-ô1±*6Gn‘ ü0”êÛ×oýáP€òÛkškª÷Þ}M B3ïƒòšÆêõ-oZÞšE$7U7†+¼çvBYF(+¿¥¹­ý]”6„Pç2ú¾¥5Ü’ò€é(¯GȲê0üÒ€"-ŽDI£Õé +F“ÙbµÙN—ÛãõÅÄÆóËø`BbRrJjZzÆø̬ì 9¹!ôÿ§áŠei/Šå“P,BC§‡S¤aè4}Gsò0+.šÔŸ^ô4z§`õá"7ºˆ½xšxô%hË~4ˆîG´íÀ6”€\h1šyh“ŽîÄ +­ú]~€zß2´Þß^B‚ßóå£yÐ~1 +£O¹PÅЃHƒ¶ =š‚`ªFïÀï߆{Ñ}è§ø†¡‹0ªÝý¢bT<ôÂÐ%”†îä· 'µÏ¢{ÐQ,Õ 5 q(m%éCï }ˆ’Pú1zhJÇü,@«Ñ­hör/t?z E°TrÓ„ã0Òl´5¡N´íC¯b.N +熮:ƒDdG)@Súçá¹äqÞ04uè}t5:Œ~ ó¥¿üÕü^áêHÑЇ^DNôÖáçñ BŽp×àÍC =™„&GæÁ8+Ñ÷Ð èôôW²ih¨ûBù8Ë8 8þñ’›ÈMÜ[(f[ Ôv Ý¨$rEÇ€7¿E§ÐGØcð¼߃ÿJ ¤–¼Î=ÄäÞæ1ÿ$ð;ˆGíèqtÖókèu,@ÿÙ¸_‡›ñNüC|ŠôÏÉ—¼†ÿÿ?($ENE¾š7ôwäA>tÚˆ6oŒúÐAô_è7è¯èoè¶àI¸?‚{ð)ü9Ñ’xRFZÈò8ù 7»‡{Ïã¯äWó¯ñï · Û¤j)riOäÞÈO"o =7ôèŽ úOB%ÀÑ›A+GÇÑ[Ðû{èwèT ÿ)x9¾Fi÷ãûðOð/ðø3˜%b¿ñd +™£6“VàÓ-ä^rŒþ:üž ï“ß‘?‘¿sÏMäÖrp=\?w‚û˜·ðI|&?/ã—óC ™a¦°PxBxJxQ8'Šµb‹ø‰t‹´YóëÁ´ÁßGP¤>ÒéÝÕ€&mNü= +zdð*pô¿€âSèüˆ7ò7€}êG;@¢O£ñ“èŸXú¬Ö¨¬Ì ï·"jõ*am‚õè ²F|¤EʧòÑ9ôô©p4êJ°¤g" +üø?凫 =ë®Í„óhÉ1(ÓÒ5°Òu`Kr`U—£å¨ÝVïž¡ž¡‡‡¾7´a¨ý +pÿ‰3ð?q7¬ˆ~À(D¿„ß»Ñ{x¬Ã™ÿ;/©Eè3ìÁ‰8ÖÃYa°]Ø'~*¼&NnoFFÿ´Y3¨Ao ÏЗX²ñ¢ z'íËÐRÁCÓ°µÀšM;~¥:“6èåàÞðžÁÚ8vâôStì†ÕÀøè§ø¼Zï ~÷AM-Xí4ô'˜· O"í0ž=í«54}€>n1º2À.LÇK ¯/ÑRT #LDåø*:–jšÎýø€-èJ¼*X¡&‡ +„?b‚2"ó†&‘îø˜!¨ïÀk +3Ìc9qÊ‹,@Š¢M½¢pÊä‚Iùy¡Üœ ÙY™ã3ÒÓRS’“‚ñÙ?..6Æçõ¸]N‡Ýfµ˜MFƒ^§ÕH¢Às£ŒÁ’*¹'©ª‡O +Κ5ž–ƒÕPQ=¦¢ªG†ª’ËÛôÈU¬™|yKZÖ}­¥m©Œ´Ä¹ŽÏgåž×¦å~¼|þ2€¿?=X!÷œeð\og°à@äžúér®’gô”¬«ß:£j:tw@¯›œÖÏ@tzõõ¸ƒ-°{*fqϘ|€ ˆêñ§Ïèñ§S +z¸ÄÕµ=åó—͘TŒÏèÁÓj‚+{PðÊs:k‚¦±azÄi=Fn ³AÛä[ïì· •Ué†Ú`mõ5Ëz¸ê +:†5ÆÞãÞxÚ3Z„ÎmÓ–mû6†Û:ÃÓ ÓâÖ­[äžùËƾ +ÐgEô¸$±¤jk }'0±t¡ £‘[+–õà[aH™Î„Î*:¿pp­©ºNîѯ Öo½® +DãÛÚƒlôú|Êá¡SÈ7CÞºhY0ÐS¬¨ž{À¶.ØÐçUdïåoÆg°X£Œ=`2«€Á8¼ckN¡Ò#œÅ”¢àlPˆ¹FJ–aN“è#< m­™Íà§VO-H¤¡G;­j«e2­§ø=B¢%(oý; +žýüòšjµFL´üQêɈªÁûa¸'=½'-ªˆ4 +d +4Neå¼ñëúÉÄ`‹E† ؇ʷÕ“³€ýð¶~­„BO×üeѲŒVÆô"%+½¢‡TÑ7Ãoœ‹é›®á7#èUAÐäƒlàìÑ$üg¶¸ì3ê'÷`׿yŽ¾/],¿|™þ™R×öp ”¬Ë%=–ªYÑg….ø—8ý’f RÿÐ9ŠÅ²Q4•ÊžÉé——§\V¾Œ:ÃVèå“Hé¢å[·ê.{WhëÖ’ \²µjkuÿP×Ê l n=Lö’½[[fT + ´èȶ˜ž’;+`õxòx (·ø+¡+¥~R¤Ø‘ÀG8¤“øF^(D÷/˜— ‰:Áª +xŒÉ†øøø ”¯d´Ö;68×¥v¤ÝîÜœö óþ´ƒñƒÆ.|·ûNÏiO¦õdˆñýC¿êKI ÔʧúÆ%Ðò©>B´ìõ±²Àj#ž_¿Ëx_üÏãߎñ#ÏûpðYoLåb€úÜã‹ ïéÓꦲr|bˆæJœ/6„`Ë¥À¦‹¯Â]ø† ×¥**iK» Zb¬´ ¯àÏñ„/IÑ»èÚ•ëV _·º•¼ü[IÏ„Gb*< _³Ûï^ánvóîÅ>%>!döárßøJì’;àRÁK‰õ‡ü.ü¡ »r5òÄ»I¢â‰ %ú2(ynP£ò œ³2pƸ@¶[rq€N®Ï¬-b94AL]´Æò¦¯ï§êr TyîÙókÏΣ« ýBúZZjMO?‹Š@{ÒÏW¦³ŸÓé´x>6bE«Í]ïÙS-´~*£k&aèE«·™Sàøü±Àà0P°×P²ù쀾Q\ K ­­´'º\¹9ùóBÉIÉ  y¡‰¹9.·”Œ—D§Ãíâix&㓲±ÏÖTÓ˜ŸèpÎŽ<}õMïôþÛ)‘/­+–5g˱Iø…Šeç¿xog¥/Xœ›%;ÖÒ©KØúü]Û&L½Òï +ŽsÆÖÍ)½íoö€Æû‡>!÷?„èø5%UF2êRÍ“MsLfÉëDÎåDn›ÝÝ6âÀN+é$ƒ‡ +ÚŒÜÝî7WÙ€›s÷c¾×‰ý¤½9©elWL½6K—…P^Ñ3´PR<\’Û¶ØYäØíØïàª]ŽíŽŽs9,Ù‘íà^ßúî¨}ZÛZÚ“¿°´g +XüÃÈ140©¢p.µž`º,罧‘§è,³¨Ðô´ÕV`Í5ÃÈ£;ƒVã©›2- Xj +æåæ%ZÉÆ}rlòÏÊ®ÚX ×Þ|3öñI§"‹nIy?-wþŒ ÷ã×O½õXä°Y À"<ÁÚ©ÌúŸÑ|iÿÒÉ¿L>ˆÍ+xµ¤Â²Ä¾ÄUáÙIv‰»4; +ýÚßß +hc8#œ?1Zöj~E~-þLó’AèÐÜ!nÖpVàN¯Nï¦Lrð’£@òUÅ´ÄSy}ËŠÙìç‚R®½04ñlÑÙ Ù %¸rí´eŠ¶ÁRg«s5xx\Y Ò²¶ §ã’0kP$ÐqÁÖÁ‡ÿ‚C‘W>ÿAäË­XÞÑÔtÿýMM;HüXÜyù‹¿D~¶yè‰=ñD÷ÃOwÐ OøÏ38oFxúÇéék[çZΟݨÌ*ÿf)Ä þ­Éd—‡¨}ŸÊÒ 0m20­—· #Cç:w€³àIðSÁŒ–0ô‰b2Z‹ì»6O‘¡XhÞ åh_ö€ÝÀ’‰ Æ''S]Ë7áôÈEŒÜ1-qÚÒMåóçy¯Ì[y­—O4‘¿^"‡+W^oýÀØVA5¬zèŒp­ðò¡·•¹·iïpÜáÚv‰/kßæÞÖÿÓ&jS )ÆTGª«CèÐÞ&h$pn»ÛJÒ¸DAJŠp~@Ø©}…û…^ ,ôTÿð‹YyOˆå:0ò°cTÜžñ¼Æ¤˜l!Sé +3.3c³âô„Ìý8E‰·×qæ/LKк$Ø—‹cÉÝ6K~)[âÀŠÝÙsÓBÕÑYy¡\uÔP¿p>ÀlXŠ••Xù Œ¬ݪ­Ê'¾û¯Œ¼öyäƒÈíx#aãµ9‘ßú_÷ã_ý²{Ý>sõ¹OñÝx9nÂ÷ᄊ§¤uóg‘F>û|åÛ=ñ°2]h·â‘ìnûrM½†ïçqH²L×L7jDjP⬒É(ôzX'¹"'„öƒÀ¡Ÿ‡ê¢ ¼ìvO·‡´xÎyÈìÑé“ &X˜½F£¶0J·Ÿ3`ƒ×­FVàúÆ,Pp–¬b4jdFª\!,È›¶è´²µ™›3Ž8ùŠÈ™„ù³ÛÓéêÜöVåƒe~2îéð¤òͽ?ŸôðÁiõ›¯‡8ƒÍM†™:P,þñadº¨”è Ð>hÜayBØ«;ª=jì÷i4<‹ÌKteãž0ù^ÖýÒðŽî¤á¢ô¥ÑkŽu*1q!§b²†ÌÎãÎ×[æqE,7¹!'ßW f“­ÜTe"&F2‡ dÁ¹6¦EqrT›âS£yúøhî‰e¹b6™CÝtf²WØlÔùñz›‡Š!A/¡ÎrÊLØäË·b\ó¸Ýãøqæ€Fã¢ñÆ5Dí|úeju£âð()Ž"2Î  §Ñ +´è(^BÀ¤R1 +ˆ÷ó2ßÃó¼WwïÅÝhx¿C÷blwp¾òlÕWPVQÊ›˜ŸË%EÎ<øF&Ù§ùàöC ¯ÜF)`»ì…½G‚â$“`M%™‘QÍ#/¿j]´ë¹ƒ¨hîÙèVè^ú)%r†bï„U»ö€i¤"±L$âv›Ä'ë³õDÏk£›7¶nº G·nLm +çBMiíÚÖïÌ-ÎK;¹³ƒSHíàÑ‹‘Ç/ÞCiû>¬³…à]èaŽԺʺCà´¢W,$…ÖRRj=C$3Õd+¯w!ÓáÐiE»#ÉéDÔ…›\Ì®¸ðåÿÆ®h5#EƒÏi°ærƒ2ÖšÌ=[hù†=© ä‰,„ËβnâD +ró&kX½ï*ìõ/(šÕš†½»¯¼vßÒñœ +O)ë8`Só\ ó,{âEÿ­Ì_f®°U¸êÍ +¶מ +Þd§á%ËKžw-ïx>?Õ|jÿÔyQ´O²OrαÍq•x* +i²-ß•ïá:…Nóá6óÞ'l{]‡m‡\Z³1!š?ks„L¹FZãb¹Ù2ÁΕÄ/áo÷<ópìÃqûb÷Åil(Î'ÇMˆ[·9n{Ü;qš8¦Bg(ŽX æ8 ,1B_¡§ÀJ› Œ.y¤`¸ï%JÐoÈ‚àSzû =érá2êãüæ“–Nâ÷Ö‹Q¶§|[[H°-}íiX*ಠÁÜKîÙâÀZ ( +½f–)&K¯±+äÖ‚è^¯‚½ÒùËŽ¡˜¡S(RÜÐ)CïÁù[mùóÕð[Jœ˜œ‡}›$ò¢Ä.%[º?ÿiúäpŲzMä/Ö¼ôÞÅ™ss#fº°ùê>¬ýí¢¥‹¯ +_w}ì'¯~öLMßÊâóåITs†>æÿ +qSîQ®8lí;”òRÁ‘‚#§'=,„SÚÅõÆö”÷ ï +ºÅ¦ÅñÁzCmU !eUFgÜmq;[øC4WÂ^_h~üüà ñ/ùµñkƒ7ÇßüïøÿŠéº4cB|B°À +–êJÓ㧯3†ƒŒãï0nߣÛk|"Þ®Õib¼ôê¼FW¼Ôyì^âQ¼r¨Ùƒ›=»=Äs„„_ŠÁWàÁ1ãšÅÎfûäPôT¡ +o‡ +A?ðg^ñXxÌOÓz¾rc·bw‡Ü¥Rr’/ÓŸÜmé±K)þªÆÉãßTbéÂe2©\i%:äé­Tèl':š·¦Ÿ¦›w¶•g¢~ÄÄM~œPó?öÚé.ýdPz<'”N(f[Q¶èX2Ó:™ +Pg,Ðyh²«Z’>¢,tUª»{ªÉìv÷seþ²í½‹ª ç`Ù·{ËÝ÷\qUè🫶lúâI »o)rÒ~ã7ÏÎʘ„{^ï¸s|yÿ.öžÛ7ÌÍŽ±eNY²á™–ŸÕýõUãÚš¼ø‚PbV]ã±m7}°l pi6XÁL°‚A”ƒç)õ’O+Ĺ|sbfÅÎNü­åC«v¢·Ä»4©Î»*鶤xïõíÅþ²ï—1Q4:]¢×•,¦:+¼ä6²G|V|I4½g!q 9¬Æzª“ Ä§ÀÃjN¸”@JØJʆ0éŠ8LW|OÜ?âø¸¸ œ‹¨¥ž” Åjh¨P<ôЊ´?ËK£ŽžîôÁ» 5Àa9´È ~IqèÇMHÒ¤jSŒ~ÃnñðD¬àšB_Y‡ª`ÝÜ• +v675°Â?tã2vÔĹ½¹jôjÀ€*©3M–NS'tN¦;̵¦Ÿ¥çA`78Ø^©gŠTÂÉtû ä.w€Š˜y,*f0Q[€EQŠšefpx(ýÍןï/åb#Ÿé-7ë±ÊÇŽ-y迸ª¼¹t¾vâg ù˦_5#×¢'È|ð¾Š;ž‹ôßyëU±ù^MIIïíË¿_›(ÇΟ1%ò¦-Ç“\8eINR~B˜ÊzȺ¢3ŠEÛ•ñ¶ +±BWa[âZ⩈Ý%= ½¨Õ¶ŒëG&s!ÃdgÈ;‡›n˜ãœî}@«¥8½‚ÞÇÎoô’É ,Ô¹SMÆ$L½¾ÙŒ|wÃã,`—Ž9¨(œ{v°ðãèÉëÙ‘½À´eŠ±AlÐ5Øê\už†X±²"uèà–l°g·0¨ÿȉ_ùªøÀòç"_E^ì½{mYÓ7Vß¾yUí–‡¯®ÀÉ`LØ{±\jÙwUÓã=÷Èîá,/¤Ù%•ž+ åéz„á„ð… ø…*a“Ð +ÁÐTG¸$Œ†O!”ûÆ ²zf¬†t‘–ÀXÁ¡3Ük0– +-W4{d‘¶NÛ`l°4X7Zî°HºYú›Íã%-AØdØØ“mŠ­Å³Ø¡ÿ¯Ã:¯}P=€Ÿ{v®e-å]tÄÁóê>C¨#1%JNtEÙCöàd9ý‡ßû c· g¯¬Y ¹Tuhe×Cû“|S¨lm/P—þú0P'A¼ÌÒfóÙB¹¶Eۥݮ•D,Dž#ÒhéIÄ&AãñŠN”dœè=-Z9S9i!]d;á‰W3ø´j[ç/;@zñ&;›ž~Z +<ÙZ¨„X3F›øÃÈ\þû‘yü‹/~5º¥_NŽ3ªt8ç0’†N*Úü‚˜‰I %/$*ð€ÒI¥< ïà‘ŠÒø4!E—e˜„ò…"Ãuè:æê„zÍ*Ý'œyŽˆ‰F‹9VË¿!L–I¢–çeAt‚¨Ñ)¾¸©::„ÞÒ%Žym?~^1‰x#˜‘Eµ¢÷cv±¨ s¸Ÿ$(Z¿gïˆöI€8­ZÑÊÀ3¯þÚšá ß{¡r-ØõXf8t{lÛ*n2Ó·Üøó-™šI`6¶üüçÀ¬ÒýÂÒžqì`“ŠôjxÝ‘¡°æÒ‘Ÿ4I +)¢~$ààì'ü´kðІÈKd +.H{õ%<7Òz°•Èƒ§@þ+‡ÎÇ JÑI¥dÒ¸ÒqK¤ušu†[5› +·º7ÇhE·csÛbR¬)ž_Ê8Í,ýÕü"írýuüõüFO»ïéåeãK–w-g,&.V”Qô¬À½Ã6»bÇ‹Z=Q±•–Ù±§ØéqJšk¼™CÀAï +¨N¶-!~Yæ`ŸOâ½ÉÝ:lÖùuÙ:NGU7í¾ìX…®Ëù³kç¢Ç+§Ó‹ÎZ)צÓ`M=bÁy°eãƒñ $/ÁÖˆ#Ô €½åŠÈM•‘ÝÏ~Ù÷ôÀá￉­87#ò¾ÿ©®?úäùÊ£ÓHÌ—ƒýËïx¯zë#\»böG¯æ¯¹ñÂ_Áæ|5;tôõ~XE™ýŒAJ¢(vöp3¼JxG 6k¢ÑdB1ºk3#+y?ýþžI«Ñ##ÅåËŽ«Šk‰ëŠâ,汸ر8Xüì“Ãèö}dAXÙÍ¢pÁ —° +!‚÷ãßbÓ‚›ö­Ü9ïºW^xtÿºi×ÎÊ뎸¿Û¿¥¿Áê|—1R•¹²¸¼Þ¨CxhÖß"˜ˆ¾èC†YÄ4dÊ"ßäЀæüyOÖ‘ +üza'ÞAàw »5éÅ,Í*RÏWi:±äE.1%‰³ÑLq)¬gŽ#= åFV×OV*zÁ~—'À#á©F<ÝÚ +ô<ÞÄwñò§`wÞõŠn×Å}ÈâxŽm¡ +ôæŽ`="t½Qçí•Æ¬7ðÅ•ç++Ó=”i¶ÚÎ^¾Æ˜Õ®¬¤gŸ°½Ç ÿýày\ŒÛð*K7¿Jwµn3§î~·®››ÿ½Î˜ÏOÒÝË?¤{™Ew‚—tD+ê%N#êyN# L´Òj8N&Z‚¨×ËHï ˆ‚J«Ñjõ¼ßóωŠÝK©OèÓøŒ zÏ#Šµ¤TO=…^Ýf¨z©zèÆâ,€¢Êùp~¹.F?G±õ¼víZÔ:Gõ‘þ‡ÿ™Œ—Ãn[ÆK#“ ôPähä$Ç"©øÝÁIƒ&üU¦Bï€óU|ð´KÙ–"ý’'»¤ÃøüéœQÐH>Þ#žMÒÌÂøÜ!é’pº4O–Jði—þ¢xQÒ&òIRš.ÄOÖMãçé~Æk®Ò-â+tµ|£n=¾Qw¿C:¢û +ÿî’ÎÈñ’¤Õ¹@qÓt¹|‘®„×:y¯n²nžnµn/ÿ°ü¯•èç›'º}²Ïé¦ù)Åi°†0¯“xDX¦aR€7‡RLJ†èGhdv%„¸¤Qɨ¯Ïé17¼Ö'‘–¨J‹4öŠ¹ZȽ&\fÜmícþÏkN­˜’HtÙüÎ2'Évîw§ÓŒO´Ù5²#‚Șä±K$biJò~Øݨ~Æ@ýL ;SÉ,ϬÊlÉìÊÜžÙ©‘3³3I¦#^F²=Lu9ã/w9•QŸÆ„ÝF¡‰š‘µl/ìÏWàŒ^÷€¬kôº53(j^¢Á‹™}ƒ“!P¡Æ&@ù¢4첄¶ÒÍŽê³8k@-$w9Ï<µeyóŠÛ¶W>²nN䣈§¼ø“´«––ÎÉxc¶u§_¹PÙðªp$îšV¬z:=ùùMµÇÖ5„)òA»tæôÅZaðpd½ÖP9ïÊkÒèùÈ.àsž´â=ŠIˉ/çÖð6 +¡ê‡úlú"ê_ú®® Ñ\I[¸(ÄåH‡$i8 +!§_¥…¯@^÷|Žø:;eÞ¦x}¹¾Jϵè»ô¤[? 'ÑÓYVíTËŽŒ. is.»k£s×&~@©¾n%æ÷)_ ¤-™4Øcl‹ +»éó4]úg|ɨ…m2ˆFIÐé2ŒÆ~üŒâãxa1ð`7¯C’b0ž€ÂQœ‚4`²B<°ZvP¸öjÔ­Û,Òné¸ÄI>sÙDñšŽà«ð,öUáôZz(ËöD¨¨Èr¾p°’‰” +•eÔÀð7Z~®ÞL€µ’N7J8ךë Z!8%7 +>AnøüСȹÈ~œ|ûñ¥k¿Œ¼GÆOÐÓÝ-Äô  Ù^´U™$i$­dqk\Ú™š™Zi©v‰e‡e§u—ó!×^Ës®w‰D½Ñ`Ë!%Úµ½l|Ý„MÑëa1å1U1\KLW ‘c²cºcbøLÀZx³½^ÎKUÖ÷/¯‡e“}÷±ÃÕ=zo1õšÅ½8Eo¿û†›º|8%ûæ“ϼùÞMŽ8ëÇÇ&-o\µã.ýR$rñýÕ-¾é]¹4Ú>ÇîºmW®€˜QÒ$Š6¿€³…ýmôóˆN›¨GI,åÈ,øB½^pS@x—!1|Û’Âó…ßbìv·M Ñ°e_»Û6ö JÀy?_téSrjPæréW”£_FÖ~ Ôß S8ÈΚY}9¡@B0‘åJ‘ÃB=èNE!Z„sß%`˜‡ÀB½^«‡Þo ²é\èm75ñ†7I­cO%¢‹ˆžK܉SÔs‰b¼…4n #üV ó|ð?0 Ù ôÓ…¨[ä—| +SÜʹ–+QÖÙÊ ÙôZ\1IÁ[†¿[] +qqž°Åa‹’ª1Ɇ|Û ÛlïÆ™vÚÞ7imV»-` +Únµ u°ÆlVk?éV\&£Ãd2Út™]ãÊñvvùgL(ü‹„cŒàÄ–+F¿.KGt4hÖíq°­ºÃ¢WçèÇO)«Õoɲ,K‘¥ÌÂYhS Ën6›x³Bçn¬¸±Ûç7õã€b3vâçOÐ[ƒ»Ñ~:åqoÆ3ÑÈ~óüiú%…”¥ö5*ÒGâêJº +¥ × ×,²¾,¬N†u¢×o`›Ÿp5öÖÍ]¶qCõ†ªÓÛÉ™Á?g\»ò(æîŽüjá +q+šïÞ¾eËêù*òdEν÷ì]/¾º»8ž–΂è°2å:}‡f‹f§w¯°Wó¤iŸý°éõ˜}ÀúºÝè&Z§[6ºž%oZN8¤£èu@ç±ä±YbäCY,ŠÙc6úY  ìQ´'´CZ"ݲ¾ýRNÅûù,‰Ââ`ßÑ9îd„¾DÏI›7ad¢î@¢_PÎê:›¾¶ÒpTP½Ÿ£~¢±±Í…úõ ¹•Ä›#çt‹¦U\oix¸ç«ÈÅ×ùNûóÞß>rÓüyõ-‹æ·ð Ç-*ï¼!rþíÿŽœƒ°ö|/®=zéÓ;î߸íî[7†zÀ=|,¼…\¨_É™Èã4^¶ÈÖ +¾Ë#høãâtY‰Ã沚ìfd1Ù1²‡VcÖãú!pÜô|S'b«9ú“ÇY@ói)Ú:mn8Ñrˆ +R,YÖVb¥×׌&{q¬@Ý®qÑÛZCÈåu¯?L¢ê•¾6zCíReáùJoô +ý& ‰^!,ÈQo¨Ñƒc{.û ^\r:©?€Eåy¸àŽõmIÓ¦^‘÷曑3óIå·m^˜ðsKÁüÒß]zŽ›MWèM‰»ø©(O9ŒRAä•V]‘ Š§è2„¸&ä §“šžéAÄ© µU©]©»S÷J{ ÏŠÏzRO¤žJ5¡Ô¬Ôrxq<õÃT1•ÞÉ,‚r{)H^òŹØ5)ÀøÄK«59&66)YÜ2[’lVey^•7ƒ?ë'%ŠÙ“ uͱ¸*ÇBÝÁDpô ¹¡dõb&Í•‰@w24MVŠ!BJH%+“¯e%¿žüa2gNö'w%s(YNÎNJ擽),6‹j`¡ÞLEÌ¿°¶2}øC?;$°°3é1lk:N·³ë).7;À‡M1ð?”3rf\ÑÄâúñ‘3|Ò=O.Z¼xÑŠk¦ï¬ +~”Y8kÛŽ!%-Ï(ÙüÀà%X¤[†>áïSÏåHoq\T&è òcfÆÛq‰.zBÿ¥$æñSŒSìy13øRc©}FÌ}ÒZÁvùؽDÏé»^oF:w@ãk¡gò©„K2ÓSznA]tËWT<|µŽžÎ_(dÜ ž„]*œ¶LÑ׉uºè ½@/2ßB×0¬^zí´=¤/qKï‹‘Èàá«(¶Ðì +•ßÛ¼*|›pdðÜ}‘3‘@óþÕ“´ÇËZv?uè‘R}]™Oêa½ZP‰bJ1ïåèÑ-ÒZMs Ç#-ÂðDä>E§ý›á!™Ï¦®‚ìè³>¾šÞ¡¯<;xþ,ý€[dQCL"yûÄü\›ÛEÂ/<Ð]³dóÀ«®È FæŸÁý”žýœ:y#²ôÏEžx¨ŽÆ”÷ÁN~± ?Ú¤ä¦)º™î06iî÷,W…«Þ%¸'Æl‰y@Ø¡üVº +³ÛÍ÷g}ö®–Ù`e­6ˆ£,Ùb¡qˆü­»®‘(døÓ` ¢(uô7Ý4M%tŸzx‰{®êæþªñùus¿·ò±Á·pÊïnÈŸµ¢°pÍÂ©Ï +Gb“^Œœù¯g¿×]Sšæç_¼”g²-ùž}‡êl&Ês`<ÿ¸ð Њ¯\¢ñÏ% +Hà >‰pcÃ&qÂá±aS„.ž¹ƒj¸Áî÷;ˆSÈ)ᙯf½¥õ1ïPýÕ¯•eS¬¥Ö°~£æ͓“š=¦=ögÑaîYS¿õ ýèUë€Ý²/ÑWWXØ«ì¢Wèt=àþåC‡PÆ™¹/L¸/%êºK@¦R adî«Lû¡öœê¾º£îkÌáZLÔƒ='ËlØæKŒz2Ã6|Šö¯<˜z{Ø¿çƒ71Ð+MÑE€C£7+*±E·hÆÒÖëvÿä+¬}íC<.òÎO¿M®½qÁ¼UàÁšñÂq Ë»/]õï|ˆ­‘½‘ŽHSäáç¸ØÛw\ç]·vt¦ÁŠPØŠ˜­x’I²nY¥ÛIö’'L’VcAðŸÍBׂM-[52ÐUa»n]gO_¾(ìS9Øäq¹L¥7cáôɱuwß¹÷ÊÒ§#ó{zñÃŽ?ã'qÖ»‘qßø"r>òÕ“¥ 'ˆöôè¶Ãˆ‡Íá³5¤Óûô“ùIºYÂý>ýOõ¯éßÓëxsòë³ô$K_¤/Ósz*0ýz⧟#CoÐÀª/‹ýYJ•b"eæ|FŒ¼U…ôFìš™¶œe!Ž#èŸi8EBÜ›-)÷Bç…›qä/ÒÙ—øG°ðëŽÈœˆýEœMÖÿƒ~ñ=tƒzPÊ•ÈÖÄùCIý`Z;xÙú²ý]á]‰wêÝ&§Åéè°¬sl¶HI(Í0M1” « M|f•µÞÙ™¼%y§q—ç1ã“ž'}{ÆíMÞ“ñdöaßsãÜöÛì·9¶$ó;!4Ú ‹ÍÜPº–‰œ?gR.e–e’Ì#ä. *iwyB-±]±¤<`¬h³¤à¶‡–Ù)J +Ié'w)›Ñ‹âËâI<í#žVúDÁRÛ™~’^XõåxOr‰']Þ ß<¦Ww[¤¯µX‡?R3¥®¤‰ÅfŒ«L¹ÓÓq’ú×Ç5|0ž]I° Ѹ10žÕXóÑ[oœ¹®jã¦È໿¼õ‡ë¯(+¯Z1o~•¯³bik{Ū0çÎ|¤ê±wÞy¬nwÚ„ç¯ÿU¤á†“/ãù‹®]±¨lEÕàí·Ü¸nÕwQËAOÄžûëDtQ¹¥À<Û¼TºNaŸv¯©;xÈtR«5¢6¹º‰¦S‰YÒX´V‡ÉavX&š&šgš;L,oéôëµë½ëân×Þî½-NÔºZƒÙ´ÐÔaÚlºÏôc“`’‡Ñh0œF·+Ñnqà*G·ƒ8HÐ=¥Ñdr"‰ò&#£ÅHŒoÇ$w‹=â€xBäÅ--A,³ƒ$pŽµ•ñjFm%»¬®ž¦±3ÅÑkxìdgKfzå˜]„ú]œšÔ—*·=Àe’`ÐjýÆÜAšÿô›®_¨ºñº¾ÈÞi]tm]áos]aÙ¬„ƒg„#e¯Þòø»±“n{ +b碧*ƒsó–]9çjƒ@y¼-²†ßÉîñÇ¢•ÌIöYvb qÆ{(f:7Û8Û>=æ1Zu ß ¸ ý#FñÜØÃ¥×[̦áÚj2™“,v@ÿõ#z}ÏrúQÛЛ4Ês€ž²›ûª…M¦—FosŸ¹î0&‘K‡—Ý]9ƒ]wÕ­¼å¶šU·óI—×F~Œ\ˆ¼W²xðSîpßS?ìÛûèn è0ià“Øß™e*1Ü$,Š“xv?Gˆ˜„e![ Â~ÍkO±¸‚þùHáõ,†ÿ<ì•èŸ‡qFš_ú[tWŒØ÷ +òÆç3*¾·`…¹ð﯆ýUú£,ù×F††"óÅ]`Õ1 +i†ÿl!ijdš6ú‡ü_ûÃö<ª„—ÑR€îåÛP6Ù‡üüÑ.m² ÞUCù€‹!=ÊÚýí„ô}(/†”+,As Ÿ +u‹è{HÊA(g> ÐJhs¿°dhêçLßè¸vœù½´ +àÞ 4´AÝÕ–ì‘âÐMÐ×€WC»ûþ!¥ÊÓhH i_P¿ +ê@h"êF!בr­ÜiþÇB‘pP<"~%ù¤zéÍFm‘n…~±þ5¿ ?4.0þÝTiúÌüK¡5Æúºíˆ½Ðþ´Cï(s¬sf9_vÍtܻݧ=ž-Þo£÷W¾Çb–ļý÷ròP.HþÐü,T sžkYuô +~#Bêû{rL:Vâ–kT˜CË°E…yäÀõ*, ¾A…E€ïSa ý?­Â”DZTX‹¶’*¬ã_ädÖ£•ÒTØ€ê4ÓUØ(ÔìSaºÆ|툮l2QaPK +ÃÖß2U…9”a¹R…y¤³4©°€ –õ*,¼Y…%´Ò²]…5Ènù« +kÑ « Â:Rm£Âz4ÁþÔÈ¿L”kÿ@…Ür‡Y…M(ÓÝ”`žrÝäÞ©Â<ò¹g°õ:÷qæ‘Ëý +ƒE¨Ýª0lî,Q¹¸¿Ta…{ˆÁ¨7xì*Ì#ÇÏ`-•¯'_…A¾Þ<†~¼E* òõÎTaèÓ»[…A¾Þ>ùz¥Â _ïUäëÛ«Â _ßk* òYªÂ _Ù«Â _ùzùÊÿ­Â ßäû¬£¼Jþ‹ +¯’£sÔÓKD)^æѸ”tè\Rf«0П2ŸÁ&ªù)aæQlJƒ-¬Ÿ{T˜öócÛ)ÏS^PaàyÊË vPzRÞSa 'å ƒPïHÅ*Ì#9ÕÉ`mŸš§ÂÐ>uƒ½¬}¥ +ÓökCu õH}ˆÁq”žÔ* ô¤>Ç`?kÿŠ +Óöo18ê@ê§* :úw§Qþ¤Uø“¥s<µi©*ÌÃÆÿèOcú£aóJ›¯Â´~… +ÑöT˜Öoa0“KÚ#*LÇ}-BP +£:Tj —Ñ“¡zÏEͨ R»ÚJ/ÑŒZ¦Ïj¨o`-d¨Yø™MgõÕÿ{Ê¡LF áÍÔ1Ò¦ +êfCo*€ßl4^…rXm1`¬|à¬ÚÖè¯ +R+ZÏZhÕ +ï«¡å•lŒÚoÐ9yLy¤Õd´„õÒ6B5uFÛŽC×¢1õÏ0ÎR¾ÕB·¢ÕPGGûßó\†Ú0p«hjg´QÉP¦mÚÕ^ƒ~¿†W!åXxL/£«ø›ãÕªjàJf£T¯T%Ó¤öümJf³ºœSQ‹üM­øæÈöZ±j‹VèkTn·©6ä_M¹¿jFíì†oÈ"¬Fcc®¨õ®fµ0Î6¨‘Î"sYÕŦ1¶mx\jIj§Æx‘Ö1±rÆHëÖ1z;ê»ÿ=§(u¬ÿa½j¾¬¿N&ÿÕLšcãÐaû8Ú²ÚF#ÔÆqÚýÈ|¢tÕîFÕ¢Fù]U-ª~ŒZÞËuèßÍhT?f³¹Srñõ9a5B‹Î&ïÕ0©6}M­_ã÷hÏm,Zí`QÔ­c±Q']ýߥ?Ü_«ÿ5¨{žo‹â¾)Ç(·F#ÖÖç7×ñ°Äª¿Æëºÿµ£\þæ—ûûË) +«Ql;øžáèþ¤Ew)ÇP>ì¿dxN€ÒxØ)† e#z:²•ª-³áíxRá|” ‰bMDy° ‰öþ?óuÿ{Ï8ü.ëkÜñ‡‹6´„ëªkÂò“ò¢ú°<·¹©¹ªäiÍ­-Í­Õí +ÍMrËššLyzu{õÿ¥QíL^ؼ¦ƒÖ´É³›oBAAöxxädÊÅkÖÈ VÕ··É ÂmáÖuáÚâÖ†ê5W6¯©îs2«‘iÕä%áÖ6ÚuNæ¤9enCMks[s]{êh“±-XíxÖ×"?!/j­® +7V·®–›ëþ-årkxUC[{¸5\+74ÉíÐtñB¹¼º]N’Í•Ëêê2åê¦Z9¼¦-ÜYÍ2Gz‚97¯j­n©ß0¶*,Oo­îlhZEq€½ãåÍ+¡ëy +5õÍkªÛ2hï­ +5 +ÕòÂꎦZ˜°jRδæ¦öp#¥­uƒÜV +\F5ÔɵᶆUMrtî5Ъº^66·†åúŽÆê& _®©¯n­®i@¡¡¦ +æQÝ$û +tþ +Àö˜`¸&ÜÖÖ ÃÑ UCÿ5õrƒÚ|GSXîlh¯glhln®¥Ø²Û`jÛp]{g¸©½! ­kèhÝ)3N7¯ ·Vƒ¼Û[ÃÕíðŠ"Ôt€ÌÛè`TŽáVFB]Çš52ZaøÆf¤¡©¶£­Mµ­}ÚðXNPmm££„[šX‹ÖæÕÐm5Ð_ÓEXÛP½ª™¾ï¬žËõá5-À‘fyUú0kÀÔ¾Z^ìÃÀ»¦†h^ÝÒ66Õ„a(»(³äðz˜LcxÍæÖº³†öÑØ°†±·]]Hmêx5€±2,w´J1n†×vPb;j(ÿåºf˜2ô“jo§zSo +ƒÜÛA5@LmÀ2¦žPl¬^U½±¡ º·×dD™èµ +m-kª7Ð!(vS¸³­¥ºHƒ&µ@b{Cí˜6oimnlf½eÖ···LÎÊêììÌlT6³¦¹1«¾½qMVc;ýwü³ÛVTÓ‰gÒÊÿ¡3¼jà e^Ù¢Ù%³§/š]6O.+‘¯š=mƼ…3äâ™ f̘;cÞ"£Î¨[Tlæe1•  +3hgý–%Æ&C™ÎyåyCsŬ¡Ú|fë(ª– LGA¾°üš yõªÖp˜jb¦\hõÕ Í+é2Ìöˈ¡ÚÙIÕ) ‚ SN·†kÚAÎuÀÇQº¨›W…Y&â< +hïÊŽvèÈl†5fBÉmÃD"°b™j›¼®zMGõJаê6бؙòâ&¦³†gsR-¨wµÜÖ®i£óÍ™ËÀÅ&¦m·º¶¶êhe+³Ê´º•ñ–­î¯µ¦¡±Naí:›[W·E•”é#«lîƒÚ±rMC[=úŠ²»èQµl£Ê«rèò?f×NŽZ¯µá66 ؽšpk“:ƒV•nÖ¸­¾¹cM-¬¡u +áΨ¹úÆôi;d,@í¨‰™#Å kMû¨ŒéĪUªë¾½[Fò‚ºîÕŽ`œêöÉ´Áâ…ÅàR&…òSåü “Æg‡²³µÚÅ¥P™=aB(ÏüÜ|9b^A^Q÷/VÝ¿]Œ´”¥’ÇÖ!lWÃjDC±Ç,—¿iGØ¡Á§—µ­­C—sËjM‰zè1öZÇÝÎã~·ç±ï/«ÿî³ÁwŸ +¾ûlðÝgƒï>|÷Ùà»Ïß}6øî³ÁwŸ +¾ûlðÝgƒï>|÷Ùà»Ïÿþl0r~ЀþÕÉBôÍUGµµ™Õt\Öö›og2«ÑvY«áºô)”W£ ÐþS¨»üÔáòwÃ8ÃñUó·ö8úv ƒÆ¶‰ÖÌb¥uì¼ãò÷—¿)W½oÛû5³U9¶õ·½Ë©æÉÃfÞÏOå§ðÓø‰ü$^á¯àKù‚±­¿õý¢o=Ñ­-ùÆ|¢5¥´„'@›±ïFkKÕØtõ×(S­è\´dÌû‘ºÿToþCÞüÇýý;½RïË£¡dô.ú–Ÿc܃ȌéÿHd€ÛÕgqä(ýÜ}f{ŽRláîGåêáæ¢H5s÷ M4/í?!ç0út¦ ´ß†dH]8Ô +OÌÊ +$Ú~[ŸÝE»ÿ^¯ÙÊð®ïÍE>‹'§¼ØÁ­G˜ sM(ˆüÜMƒ¼ò8ÈWrµ`'(JŸÙ’ÓãAó"Î FÈÏs.”ùt·bX³Ž^StœŽÞ”´œb7ó°&fÎÖÈÏi8©7Ç/å TánïÓê)}·÷Zœ9Ǹ[9 9 U´rûÍÇ8Ê‚Dg²¨OkÌÙ^làÁ4[ü½ª¿›=®©:‚ñfp±ÈïVsqÈ y 7®×é8ÊÝËšý€öãMíÕäÒ¬ÏhÊ(Örô¯z¸»€ãw±Ñ¶÷%MÊAÅI\ +ʆD€©›¢ÿÞ£…Û +ÐVÓVÍVÍV b+AîwÀú¿@Éâ6¢®m‡´`ºtö3 !%ç0çå<À ËQà†Z_ŸÖD)óôÚ쬙§Ï`Ê):Ƶ¡2Hˆoïs{ršril*}žŠÐÒ«5ëÜQY¢‹ÊàËcœˆcè)öC#3çG˜¼JNPî·Èo¨|éÿ<•å¿Ró×Ôü¿¢ùÐ9Ñ£(ýäMšŸ*Ž%ô_.[A~‡vDÈQò3p4~ò>é§T÷ÈaTùI(×B~ò\Èô~éï'ý}íõ]t²äg½éY*àOTwŒ +Ø\9ʼnäEòŠ….Þ…<òÈŠ‡ü8¡Èè'¤ýògIšùA5ÿ9yžê4yŽé'}½&JBO¯D³ý½"ÍžéEÑRy–ÿyò y +ù éOz“|PûD_R‚ß|úÃäqÒÞç·ëÈ#x>ºÑIš#y´7Ÿv²½÷yÙ˜l'ÛO¾’¨ŒWöpÙ‰Ùã³÷pr¢<^Η÷ÈÅr€y°`É6x‚w& =HÛɽ|~Oñ ̉΋ .xv3¨ +ž- B𴌼=Ç "r+*ƒD › m‚ÔéfÄÃs#¤ë!ÝéFVÓ©R'˜ÀhŒÀha-€Ñ-€ÑÂ0ZØè(F`TF`T1Œ*À¨Œ*À¨b”Þ*À¨bå€Qå€QÎ0Ê£0Ê£œa”F9`”3 0ÀPCa +`(€¡†Â0ÀPCaÙ€‘ +Ù€‘Í0²#0²#›adF6`d3 0dÀCf2`È€!†Ì0dÀCfÀ°†0, ÃÀ°†…aX˜|: QŒS€q +0NÆ)†q +0NÆ)À8Å0NÆ)À8E:p'Š('å œ`('å œ” å œ”êÔÛ3¨ÍM6Aê‚Dqwpw€á0õê€Dq{£0z£‡aôF`ôFÃèŒÀèaÝ€Ñ +Ý€ÑÍ0º£0º£›at3Åí€D1þçJù? +¹/Ó€s%]8•å›Ðç,¿ dùèËo@{X~=º…åQ>Ë;QË¡?–·#¿÷úóÍÅ.0eV@j†´Ò~HÇ!I zÒ‡†HžÏ›¥2i·´_:. û¥S1‹eânq¿x\ö‹§D"Ç#³£`ZÐÝì¹ ž_@'Ï"‘Œ;›¿!R¬gå/ÒðëiøxÞŸ†ïNÃÅZ2óÌÒAœO€p¼L1$MõŸ„”Ÿ”<,Ó]‡>wû{“&úûñóÑ,UI‡üsH ít ¤|H9ÆCJ„äguiÐ~™¯vù<¤dHH2¹\Ûجå01â=}¿0"úDö&§ÞÑÞälÈú{“Ë {®7y¥¿X‹¡dágArOA¾¿×^ÿ$š=Ýë? +Ù½þd•½É™]Ý›üš¿Øˆ#?OQ©ùB˜7Íôú—@³ù½þTÈÒ{““hë4(Þ¦âeè4ä‰*VBt¤`¯ +dñ½þÚZƒ’©à±ˆÆ3òH4çú€ /ÿŸÒ® µ# +ϬTíFŽÛAªÎ*Ë*©·WW 6ÑjY¥4{q-v“dArªAÚ„^Ô´`¨)†B¡Šz1¡¹ÌJ4¬‚ý€^Ý{nm¡§^Ý÷f%Ç-ºu¤™7zï›÷FoŸ´¼ÃΣ^’ZSìOö-û–ÿŽ…ðøM’@~Õ±ÎBšš?¸ÊzÕ4âáþŽ(Gú ;ÐwÙ ‹êÏØ÷ì*{lF +°÷`ß»ÂD}¥FÒSë<{ÄÞcmók±[l“­³Ouà÷Ø'ì·I|êIOŸ±5Pø!| ½Ç>Ð#±Å›ìsf±Ëìºzˆþ%×b½eó=@–bëï‚ôcüãrDç¬ù/y_¾#ÛòŠ¬É—ä·å¼œQæ•YeF9«¤EI)IERˆ’ÁSñ |¸2““€H*‰cRÌg%¥øÉ]‰*¹Eøù„+¹u›ºüå]ân©üïºÑôG·ùšMù¼KÜ +›_3ÜH>^çeÃåòÚ/¤ô±\.}Q²áEôY;9¬ûR²³—JßÜÙó}’½ð ’­Ìߘ»~Ó™04Fã©¢ÙÓÓ<ÿέ{üç¼Ï—prœ÷]þ%VHç¤éš3føÞ ¹-«­#?¹íø{%`Í3#—‘L±‰Š0ø?±×(Æa9à +H—ž&E+¦§.I©5'TUÑ 9˜#œÂ@ÄÀZ',JS©‡(êiªØØ;Bc1™€@ÞÆ„"F…1¾ø¢ Ë'ea+A_cXŒÉ\c2WcüÏÖ´ +Ú/!Znhµ&ôÿæÁ½,´¥ªa'U`.6¶îÞCºÙäÖtxGsÔ°4œ ¢¸¤9!Ö6¼ph5^É*Õ´MÇïWV½ê¿lížØòV'([EeÚªT'ˆ«(® ­*Úª¢­ŠU¶j÷1î×¼P!6Ö´/M¥!†¹‚o_˜Ý¾=X)d;¹çIBŸ)Ãçg5›OCG‘Y5«(‚ߊf°šöH”í¬rÏé“‘hØsšMNΑDVty¡~ÛÃPáÖæäkÖÂ&ÄYR»ïÀ>·E‡×i$iMlíI-‚9²Ëê.ÏC•e0Õp|à]ó Á Ïœ©EÇ/AhÀ&hÍáÌ X‡ÄJCÖ%KÝTW–0Uh÷/æ—>{wð/ C'=ì-Š|YzØ¿¤cþÒî/.ÇòS¤½‹…%<›¨ K‘ê1µæL˜ìëûæ~¹«wÍn9…G—“à­´·x m£5vLÛ>‰Ë£€½Ÿzoå…á.N Ã7Z¢ ù¯«Q½Apú‰c[#­-¡¾=¾ 1¿Ebp,4‚ñ¢`´D±¦ÿøl‹| +endstream +endobj + +80 0 obj +19856 +endobj + +81 0 obj +<> +endobj + +82 0 obj +<> +stream +xœ]“M›0†ïü +·‡ø²+EHÙd#åÐ5í à¤HƒrÈ¿¯ßyÝVêôÏŒFãr{ظ”ßâÔý¢Îc¢¿M÷Ø{uò—1Ú¨aì—¼’wíæ¢L¹ÇÇmñ×C8OëuQ~O{·%>ÔÓf˜NþSQ~ƒc¸¨§ŸÛcZïóüá¯>,ª*ÚV +þœê|îæ/ÝÕ—’õ|Òö¸<žSÊ¿€Ù+#kM•~ümîz»pñźªZµÞïÛ‡´Ú0åtîu1…êZUî¥Ml„›W°^Y°#;p͘=¸áw^‘%÷…5%÷•ñïà +¹¿ [ +Þ +‰Ù1·¿³¦Äšºb.ÎÕô¯å{öGMMÿΚþÍLSéï6`úןý¥ýÝ +LÿZré_ÃSÓߊýkôSgaú;8ú;ü¯¡¿Å¹†þ5þ×Ðß Óß¡·&ûïÀô·C CÿF8÷_âsÿÅþn†þNrÿÑ+C+çÒ߀mî?zb³?êØìú6Ïzeéo72yò0š¸;F^õ÷Ӹ˓9Ç„Áÿ½ƒó4#KžßtUä¨ +endstream +endobj + +83 0 obj +<> +endobj + +84 0 obj +<> +stream +xœì½y|Eú0^U}ÎÝ3“crN9&Ìä"! ÁHš#áˆÈ$&!É¢®à‰ +ÙÕõva=uWB¢@…UWðZX]×swQñ`eUpU2ù=UÝ Áë»ïû~ÿú}ÌP]OW=UõÔó<õÔóT÷ Ý+­CÒêZjÛÿò÷W „^B»êVu«ÕŸZð„Ļۗ·ô9/>‰|BŠåÍk¿šP°íByŸ75ÔÖ—¾qĉÐÔw ü&(¸-¼ABhZÜ'7µt_ü×kÛá~Üß×ÜVWû¸rÏ·pOñç·Ô^Ü~—íB¡’l¸W[k[nÝ^îû +„rîioëê~{íþ’Ö·w6´?¸ê®÷ºú·Ž‡2 úgP¤÷„ãQ’Mf‹Õfw(N—;"2*ÚŸèU}c’’SRýièÿ¯ÂnÇÒVǧ¢8„†ÞNáCïÓºpóÐûäC`V¼žŒ¿KÐß°{ÐIìBÛqz=ŠÞÀtz×£(N“d¤b‰Èƒæ£‡Ð XB•¨è#´ +-BŸòý +Áéh!z ÛAà»Ñ9ô0ú“¡#ÐÃDTzp„°Jx_‰Ì‘k†² +Z^…"Ð$tz_fzlè5T€žäÏú7º +{HÙQ;úú2ÈR5Ô‚jÑZôG,rS…›†ÒQ+:Í];t/P"¡y0n5ºÝ +£NÂûÈv¡Å£b4ÍBU¨mE  Ð‚RQ3оÃÀosǸ¯y™¿¿AH ØcP.š3«FËPº݆ž…óâ¹øv!gð +à‰ +=ŒœuèJ´õC­;q$^ˆï&—“ƒä_üƒÂCkAŸcgâl|%Þ…ÿB0YC¾áÔ!4ôJCÓÑ\´­FW t;êCO7ÿHfsS¹Õ\/ÿ ÿmøYÐ÷%@Ó¥¨=^¹¹pîî^î%î$ÌÄÍ_¸G`Ù@ãyð™óï9¯G7¢ß¡‡ÑN´è9„þ‚ÞFïÕð +|þ-ÞƒOáoˆŒ!E¤ü†ô’Ýä\w>7Ÿëànáîàžã^åü¾Œ¿›ßÉ¿%fˆÇ¤ÚðýáÍZhÂV‡óð,</À͸߈7á›ñmøOøÏÄLœ$’”“ +²œ\Kƒ\!w7À§ñ9| ¿„_Áwó× +9ð™-Ü lN§E—øŒä—ƒï†›Â«Â2Ù‡‡²‡BC'‘€Azµh9ðäNàÉ} ¿Gûг`ÿ‚þ +Ô½ƒþŽÞE‡Â/Ði£°>q8tk¾_Œ¯)Þ†ïÄ÷âx?ŸÁ/ãCø/øü~ÿŒÿ…OŽÄ/I"ARMšÈZø\Kn"·“;È  'É!ò7rŒçn —ÅM€O7™›Âmäæñ‘|4p»œ_É_ßÊïãÿÈÿ…ÿ§€Ep ÉBºP&\/ìö³9ÛE˜*¶ŠW‰W‹÷‹/EIùÒ•ÒéNéwÒ_å9IÞ"ïY¤á;Ú~àÅø9´;Wâõx>¶á¸E úßAfñw‘M$@¦˜b!ßKsîAt#‡‰ƒïá~…oFaŒÎAWãIh5þ5Hú9ÜÚ•ŽîàöraRŠÁ,àûðtŠ;6é5àÖx<OG³ÈþÏÂþ¥ëI2¹¿É_(šøçÐMd_Ãçñx»LýuÜ/Q>ú×Å…UÑÂ÷ÀŠ¼ óè\rúò¿)8…d¢b<“‹Á\#Ž…yÒ¶¯•‘¤=‹o&+¸4|)ÎA'Qõ Ï Û…¹ükCsødžT(¹„1ã!èæˆoàjø±C‹Â_áõœ‡ü‘K%çâÏùZ +?‚Ëñxò>7w‘nü-îÇi A/Ùd2Ž%÷îŸDŸ‚FÿF}üMÜ/‡ÞåŸOž@ÉÂRô +X4Ovã/Ы`OŸ­ÁæþÏGq­èWCÈ þŠ|…~‹+¼øñÛDCÇÅjþ~¿ÍŽ¹F°iÝVy÷/4yè=äÅÝC‡öâ8X/»Á.ý[x†´¡_ƒ½x +,Êå`ÇjA››‘¯`‡O?èþç`¢A<ØÐVX§w€½Ü +öâ5°Ç þt +Öîíèm‚Q…xP~= +óûËhÊ=ÃkéèÐ)þàÝ£h‡Ñ3’[œÄ_‹žöJ“´ÉZñ¤s‹Î™X8¡ ?o|nθì¬ÌŒô``lš?5%9iŒOõ&&ÄÇÅÆx¢£"#Ü.§â°Û¬³I–Dç`Üô’¤Òµ7µ¦—OMš1#ƒÞ'ÕBAí¨‚š^ŠJÏÆéUkšz6¦˜ßÁÔtLm+j*ÊHWK’ÔÞ—§%©xÉù‹þå´¤Jµ÷8ƒg3˜Oe76¸ñù …Zâiš¦öⵤ·tUÓÆ’šiÐß‹yjÒÔsF:Úa¶h¨7:©}Žž„@¢K&î H¶U½±IÓJzc’¦Qz¹”’ÚúÞŠó—L‹óù*3Ò{ñÔº¤e½(iJ¯#ÈPÐT6L¯8µWbè!:t½º#}ßÆ´¬&h­Oª¯]º¸—«­¤c8ƒ0î´ÞèKŽzÎÜB箩‹×®ã6–xB*½Ý¸q½Ú»ïüÅ£k}ôZY }@[’RZ³±†¾rÑ“„PòéTôI5$•Ð’š‹Ô^SÒ”¤¦Õ€@b7ö¢¹k|}±±Ú.pbKÔó'ùz‹ã’*k§Åïˆ@ç®éÑÔ˜³k2Òw(N›;ì°ÚF +#u bè*›;ÂNL)Jš jЫ֩@Éâ$˜Èzi˜€6ÖM4ø«ÄЪ·Äê5M­Ù¨L¤å´}¯¢$©O"{ÒñOÏ.©5JÄå$¢ UŽƒúa¸7ì +¨^HSA@ã$vŸ—‘¾j€,LjWTÈ€}¨b14«œ˜<÷ù¨T¯ÐÐ2¸é]wþbý^EËâú–¬ì%5´fßpMäZ³n¸f¤yM¨ï£Ì½Žì•SGþ9”(wIÓÄ^õÕ +z}Ù¼¤²ó—,VK6Ö¼-›Ö^?a¤Î€°^ ïåS€S3“@ãæ.YL àŸRšTª™+ hìuO]ÌÅ‘J"që +ÔvéHÏôf±•öŧˆLíë{9P[V€ÕÒ^¥f†~­4û|?Úf@’G5:A[±ìL3cJ½ƒgߟsÖýYÔY7r@/ŸJÊæ/Ù¸Ñ|V])بK“ÔÒ5k†Ö-KR•¤»Àœº±½¤fXúC»¯ë-½¡&Ñ„'f D¨hÀ?€ +ìyÑ£?.Jä¤æAÿ8‡Ìÿ8F1²(g +\0âÑi•ÛwZзHå÷Ñøë „ø(Ø?Mè7Z\šmªFÕ¸Ú$¤ƒ–/ä‹ ¹¯M"/¸ˆEIB»I+Â\´fá ZD«$*Üd ¾ñ¸Iä—ô"‘¬„p®Cs*TËŠQ9ªñcÌbô±ã O0¤VuÌ>zêø—ƒÇƒ +%¹¸Hùr°p½ü…òì¸l\…ªÜîä‚\ìs‹âù¸ëÅíáÇ_[ò 7 £{^ÿæ\î?k ÿ%0•^ ¼JÑ¢ÑLÎL¶ÿ°M×y/>—vQþT<ŠŠÇe»}œïf?1|G†?nCôX*¼Š”€ºµ˜(·'*&6:!Oµ6E=Ï?g1™xÁB"È‹}6SdZºÈyÒI11q¦XÍ[ãÝâå¼NND¶ ¬A°Tƒ¸#°Ï4@îèO,Ì¡TtvtTŸ£tœªš}/>3í¨r/Èw%çªÈAø¤1É$%"*7'ß•7>5i ê÷çþOzœ£ò·Â?}9üq7 ÜrÉ{7íîù{øR|eÏqüýáG Ïùx7vÿúÖ—~‡§ßù‡?…ë©œo9¥[v!Ëо>W!: Uº +çŠÙ.”˜9‚¸T”„ƒB.ž‰¦â…h>®Ç]x|þ-ºo&ws·›n7ßfé±=ˆzmÏ›XÙâÍW¡5–ÛÑø!ô0~¿…ÍâY¥Åbº÷›!¦AeEÌYÌfŽˆ›Íä?šËk)¶T[¸! FÅ¢Z8Ë)Ñܶ[»³‘¹^®‡#/q˜£å– +±Fl‡žD,>"+Ù‹'#O0†*üóWhÖyœ©R‘R„]…NWáz;hÓ³ëíEÏ>‹<ŠÎm܉:q0èKâ|î¨èüüì# +_½†c˼¢|©Ë8ŸO +{b’ó½h¼ä·zèC¾/KÅoh¿ºÎµÑK¢½Øu½é:ÛÕöã&Þ-+¦(3/Çš½3&Òíu©•²¼QYï}Ò´Óþ’émÓ?eÉ"™] +VˆÂ)¼’¨x§yKTóB[£íéb×ÅÞ +ÒoÔ{M÷ÛžöÊå7åCæ·,IŸÉßH_ËŸG|ÿ¥7*è¼ÎEy—{ï1sªìÙ«âM*†½ä3Ð|Ð +L*0V1Æ¢+Áï–L/ÉCûúSÒÆÓ\‹ŒI_!ãr#Y‘Uù|Bä2]Ëu‰~«E¾ÌôR‚ç—’qÒ4¥D©Q\Ôº1jòUÐe2r(ÕqÂÁ;Þ÷]ÈÖÔñŽãôÚÙñ%ð}¬î.$€91Å"8#ZÏÓ"ô<ÉÅò¾DGqþUR‰ƒG‹CS-&Aƒ† ´JРI‚ø Ú²³°³Š«:©p©‰¨ªê@Lœlheè?}æBÁ\(ë»3éw&ýÎÎîvØ QPÿ«¤ÆûÄHºê +@_aÑåÁ’ôå€+›’ÏV¡(ñK³ñšE›€ÃeßÞõ·ð—kîÇ9Ï|þ_TYù˼ÛiºèÊ›ƒwÞ‰‡ßz胿ٴÔm^µêÚ«`NSþ"h½§U¥óxÓ~îmë§Vq..¸h¶¦ T[–³ÀV&-²T;Û¤vq=>€öÛö;^·}hsÙ¸(r§t«_ Ý"B8›‹ÄĶÛUŠp8Ýa6 +àG4/a) +e¶f?7¯BÄ +,tQ‰H“S•p´N"ÒÛØiŸ &jÖãåì¸QqDï&»p,-f4+U§ª:29évúxq‘a¥qa!‚5‹ìY™šìÎŽ*Ô Œ”òss¢%Ê4Qâ| Öà-Û'Moõ§Ïº}a 4üŸú罟ØÛ÷¼î‡õ5Œð½ÂnºÛaIÛ¨šfp=¦-¦C¦&bvŽ8ˆƒ#2/ Þ#l“¶›ðûÅýÒëâqˆºñ¶$>IÈ2å‹ùÒBa‘¸Ît‹x‹t¿x¿tŒ³ÉDæ‰ë%½Ü>²;DqŸ‘Ï8™€˜1ÇÃŽF,‚õ“°(ªŠ %=Ü®—ã8ª³Ñ1ã¹.E³ó°•Qc&™‘¤àrkŸHùv«æ´â¼ —õ7ÊRôÙµãe}AØu†÷7ØáN;F˜G9G“¤Ñ4.”¬SêNbØ¥$HøjìÍ¿—ˆ½ï†ßv‡O÷|ûµé7A¿ lº?ªíµ"³KŠ0 "'É‘\ŒÌ»õœ‘Ó$üŽøŽüŽé¨™Æêâóæç¬ïwéAË{/êÇK{Ì»,ÒþZé.t—p—x»e›(]$…Ìky°OòZûÕœTf¹@:_®0Í7¯ !NÊCùü8¡Ð<ÁRl/ARÊâÓÅ ) '[U»” +áþT"N“fY4ûËUÖWÍfŒ8l,"2Gá‹D^2ÓÝ"{9âEY´X­¢ Ê&N"hñÃl­ä?;×YðØÁˆªE›ÑÜ6¼Á~é°›ï¬6µ™ˆé)2Ô‰Ç÷‚Û${4sµØ&®?yPû¥Z<¢:¯JÙ’&µK=ÒI”^GD%Å„ƒ`ýë~Ûù 7ØPé–r\X8 +‚–3±Ý…~t`°ÈÉŒlìÆÈZf’ÌCG4st¡ìqœ]…xØÚø|H8× +Þ +öñÛŸ?>uÍÐ,\†…d<«ä¾Á¥|êàr€&àÁe ~¿ö!/ÎÓ–‚ÏfFdE6ä×Dà;ÜØ•åÈR2¢'F—;Ê•òˆòÈò¨Eî›Ý÷ºûÝ»=y÷™÷Yö¹_u¿é9â~?êýè/Ý'£NFÇ:œ—Ãíˆà³íš}Ÿý·à‹4§' -ëe¥”^¸SqZ«’ݤ%àø>^Pv“ä ›4[lh“4ò’°*$°Ó‡Bt# mý +ؘÝxRÁù»•í”§'§_R—ìh8¬U”ζhÆ;ÛÐðT\`ÕºåvšõÌ¢gV=³é™]ÏÜÐ`‡Œ;Ûw}a¥äƒ]‹.J tmM"ùù†}' áÇ|½çågÌ='üå¢4|:ÿô5öº›ÿt³¿tü¢©Ó¹^zó݇m¯™öõ¹áošŸÙ¶çÆàœÎÌYK—Óy +|ö߃“p¬va» ;8|ß”ŽñMrˆ?$pýÒóä€ÄÝKî•%Üf~³ðâ6ë¥Û·]®Áœ&.GË17Ï åö€a#¯„_Á(<7—¿*7¼˜ÿÓÉ“ˆ }¬£Ý>©Í?lš«Övë[Ü_y¾Üº†ßk=d=aR¹ŸfZÈ-4ßÆßj–L&d‰ÊÄY²f‘l’°Ùd¢~Œd{nâ9n 1Eb2Á„ûxÙLhGsÀDˆj'O®Ô,ª´V"ÒaÐá=R˜ 2{Ii'GFb§æ@&ÍÔ»Oýbzç é#{£§ª<Çà9®‹â"WaÉŽLYŸé¡µúëŸ-büìDÌêƒIðqæ#÷ô†_àÎÅåÿ +ÿcá‚ðoñ´ðÂîoJÉ2g° Ý<à×o_‹vh&%¤¹9*Ý‹bÛâßtŽÿÈm΋=O +c±H±#ZäT€ÙKyáåÕ,ЧÈ4º„+À6òÒYñZ|M<ûØ,D*!Ó4ç>|“lP +P¢8 ÞC;ê +ö»9Ôe˜=Öd³7æ.Ñv¹*ª +9Q°íD“’ + à¡K15) _Ê‘KæoÞÕ¼ð=—Læ9UŸmYšµà¦7„Ýe¸¸í•Ë';Í_]]ž7Í |¨>¼|p"/ºSs ;á|lü®»c]Ôöd@„rø—éøÞ]( öxÍ.)Ô|š +“ Ón°*™jfv¦–Y‘)˜íòØ|Ëtëꤷm¯¥³ÉR’•äNIN)5—$Ià]ÆÊäÔÌñcòSJÆLOÑ2«Ðöù‘Qs£%ÏO­N¯È\¼6x‡ý¡È-Á-é½™/F¾µ/ølú×±qúá¯ñÐÖ€]9ÚëÁ×Síi?n€KÖ\®ø@8S I5x lè<àâ5‡‹,žiYÑÅÑåÑ0zécrò!?öS«æ·ä!¿âWýÙ~Í/øoÌôNSprÂÕ¨ +‘ +´DŸ!lÛÍZ®`‡rH!*Ä]ø¾þŒ)zàÒÑÉ‚E…†/A؇ªFâ^_x#~áø…YYˆGXÌP þ0C×"âiÌOc–x³Äk#80õh«t yÒ*wJ +4@Ûý©þdªkD TÆ@E?°S%IÍÀQ)­ÕËÎU>=©ö«0yù•øðW‘YÚ’%åi1×½2½>üáßâ±é‹g¦'¢£Ô…9s.¿ü‚µ·¬Ëœ˜à/ò§Å*içž3oå­ï>Hµ¥ ´åRð$ÒÑçZ@õLëâ®Ãgy¾•‰*/Œ +ů +ÞA«Ù戉ô€à’R]6ÉêÀ`ð¶²Ìåæ#æfÞìZƒÛñ:|d·› Ø ¿€ÍáÁmžµžMž!5-!AÏ`ÃãÙ©å©$õ +X…4+R•¨±™`é­œéÏñ„PLOLo 3€§YzÀ‘€’Œ/¿ðГ£ÙÇ«¨öAÕ…®7]xL$p(1«ã8fœgá óÚœ¹úÄU:óõM_*E)£áP«$Qæ7a·³rÖ²+šGyrö®‹ÏŸ2iYBø›œÊõzá•kWV-îºû?»ÿ×úV.¹zù’ÿYY?}î­ãïYtå{wwÇݵàžëv¿\zèá+áU‡ú´ÌrTŽ5»æà¥èèè )hFÌÊÓ#fy*Én‰õ“ +£{¹£‚ŸÝø`‡^ÔÌ. ƒ â-Š¢‰¼ ¥µá½˜”ãj¼,òŽ4dWìÄþ¢–€$`5AK¨H¨Ià¢Ò4°ì57ì¥ÝѯKQ÷¶£ +Ö0Óàfñà—U…ºkKù&ˆ(IEÎñ®äÜ4•¹L,`Îç/ÁÙ•á»> þË‹¸é¯ÿ©±áÞ +¿xóÊ/_ù Q2¿ +‹§áñßàÍï ½¿®ë¶ð“¿ëÝwØ‹ÓÀr%¡qø­íâ´kc¯Œ»&~cšàâ9QE¹œÅU;-n¦ÿºØ +þ]±ÏǾû¶ÿTª%*gåþ;–u,ûHîéàɬ“ÙrJŽ™èªt…\M1—ÆìBǾE^óü-æXìÇþOÒ‹cð¸äx.Ñ.91ò +%ãä¥ÅÆgƒ^·ÇŠ?/Äû ˆæ2ÜäDÎÐmA†a2Œ3 šk±`\3üØSqÀ…šŸCèÞÔ´õQÃà£6ÁGm‚žc8|xö•„Ó¼‰XITI" +Èc­s!²ÒîØç úIK¶cÈ!8HñÎ\”ì`¾t‰æ L‹†p³:gGkÑ£GóÑ19S^ðèGªAX,^éüòøivÁ sÍ`}§äEt‘ï 7$f PHKŸÝ |¼=4e}ö¼fC«:Á{a<}ŸÅU4†þ€í{…ëG¢ ªMø£Ú…Ù1óáèZ3+…° + $|æ´çr¹=wc²fpoóŸ?öåö‡?ï¬ÿOp›O7|~xñóáú”j.xà€Ì\(¥¡Am’À ¼ +?àÝØàë­·Š C~‘{‘·Ær"À-~kv€s§y-~‹ìIôz +ÿ<ÂMÝòhÿÁ4œ¦¦N#Yiåi½iûÒø4oB"õÝÁcW™ïžáÍCŠ'M•q–Ü&ùÅä4-€é¨Ú³í5öÍö½vÉ~a{wƒ;ï%ÉßuåÇ¢èÝ ;‹Œ#ÏX®ôÌó8=ôíËÓó笎3N=6 I ! + sé¢Õ½|2ìGˆ|g¬Wêæs>cíúæ‚ÖŸ¼wró-s®»±cí-áÿ¼ðƒ;¯›¦ã»üã?ã¤ÇQÖ|yø6a·Ù±ä– .éÏôn®¿úxwQz}á„Vñ´?«¹hf5õç.úPgÀNmÅi–2Ó9;.dkRZÜm uc{ðfysÔæèžø_%>·+îë>縧Ó"!\(µÎô•%q¥&Í2'±Ü[®®KEoŒ9:1Ò›?f¶¥ÜVš¨y§ú´1÷%pÿ)å­Ä·T 8²- +G +àJͱ=foÌÁΓSLý5p“Ý…1äÅÇ\ÜAºi’[ÐÜ…[„^aŸÀ)`i²N OÑâý&9 +%+É$ùdTš‰#cÓãÓÚx³ÃÆ—®90{¢¦‚˜b‚ÎÑ7¹ÙL2£}¿Žª uX‚UÃ> =G¥î^´îäùS“Sa£JÎU‡ý—3Ž6òIN½{űSún¾:?5üðÝK°5 ‹1Î>l¹rí/VŒ·m°dyøåð¿ž Ò‰ßvlÈžsQÙä ßÍu¿½h×—Ÿ?o µ/žZ<60³eZýÝO‡¯ý•ÍR°fÀÊÐoµLUÂ)(…SyUÈGùܹ¼&,äæñBßη p0«Æ*àÙ)Y@²ŸæhˆWø~3?Ì‹|l…†Šçœ¥ZG´Z<[«Gâò£gâòѦ˜m4>i)(eÆù8WØýí9'þ…@ÿðÏbð +íQ³„e$‹’$;x—,ªq2Cð#Ê;ÒGÒG + s|¬p/(û£ö{ÞVøG­ÛHû-üÖÈ>y§ùQ Ÿ]*n5oµñ)Ñæ[~Ÿ‚’Í©6î +óë–7íÜCü{éAÓƒvnt©c•š§Û™9íñ`ˆ)­“Ù"Gbl±¨VföxÔƒ,V«'Æì +ôñ‡ÃŠbË\zD¨ÅOÏë±âϬCV¢ZZ‰Ãše-¶rªu­•XHŽfõÌ-Á17ÆZ£cØùýlvÊuŠúÃÃ÷Èã€FäØ +S°ÞN4*ú¥è¬s/fŒ‡TòЉ>¥Ð10ôdævgƒl‡Âlð°–ŒM_3<¡°§)ã±߸cÙU·ú~~ïòøÉ‹ïHWÓ. U6..»å² w +>@.X[P|Ñ¢I{ÃçÁŽª…Ï翦 ñ¸L»^ÍÇ룯Ê"ùIslecæøÔè´ìq(ó1ŽTL¦Gï;‘ÏmÌZ—ÿ‡ÌmY|Eþê´öü«ק 3§Ç•&ÎH_ìüÁ´Ì î 1…A!Ã=6‡x¬K ÕcÍðp1–ظ8Õ…q–±öØ1;)õÛÍt5“áE½›KF‚î\3ÃN²ð9,yi1%váR ™¥©q“‘%ËÒcáÕ²ÏÂq7–-–½–É2€ÿ¤Ååãdtcj2r*NÕyÂÉ;ßϳD[òÌ7dÓEPÄzê¸2HÝ‘£ÊQV´ì†îSÑê³2ƒ‚.ÔèBT¨?FVŠÎe¢Ä3£…=‡OԢ |œg÷x”³œŠ³§N¼ `l¬cþÍæ»\wjÝE½ãÒ°m cRÅ%[kßû/h™[ö˲K*f_P'¤gfù’ã'ù¯Ê¹ì¿îÁ¶´7ä9Âõ¨Ñ4ìøOßsÁn½ðXdTV}tç°q„ØÁñc§ºzÐïíµcûmñiª´O:¤ì•8éE- «I8É÷‡¼c¾wÈ«°4ºÿêû ;æ6ŽzƒUgöÒÝ…•±š«0’R4$dØ»‘“`𘢣ܾTŽ¹JƉ0€>|;¾~Ûž®#ÿœ˜ÛpYø ç¤ÒàŠK3·|±yÉä´k +»K®ÚóEÂø¿?w–n—ðÎÄ˦U¤yh¬¸uèþNaŠÿô¸Ö$«‚ŸäÉyþ)ò£Üä_%_+ß"ßµU>%ûu’]”!Ž5GGHr ¦@-•G5Ê!×E€yµüù~ùoþŠÇ¢>ð»Á½—ÇÄU¤à”Å\n&fèQÌaàÜnü;z$Öçéñ™ÃiË¢gYkÑ&ˆ•8‹As 9lÙ[»mí3ÛM´ +àó4%Ò"×E©DöDr‘O—ÑX¼…BÃG6§t TÑ7‰Vuf<앲uЬÇÌÙÍc8ŠÕOÍS°œY§á°]äï !O-œYxþ¸ª¦‡Þ¹ãƒu—þi^Šî{z0oé´ùEç/™\Ð^ÌÏZT:qÞ®sØ~ÿÊK?}o Éž¾·»uNhGg˼ǨßsØ"z&ú´óöE +‰¤)âb´:​ŸÀMpeG5ÞÉ»\.·Á+ˆ¾ãâxå]È"xú:;HãÍŠÅl“#FÔÞ²?&âEÍ*˜hÈ™ê +ø•ýí8b€”jŠ-mŒå #ayGš¸jÄôƒ©8®›|º~@uÔ>Ê?³eƒ+Dt{^`X°ðÜ}8m׬_¿úŠ€£ÅŠyÝYI9ÂîÓ×…7óôIÁÄô„ÒYÓÆÿèþ+øL¯€v GµRØ`é?<69¢y +ixºTj-µ/‹‹|£´JXc[c_ã¸F¸Þ¾Áq;»ãAÇÛÇëÒëÖX ØW¢÷h +q¨ìeº½è :LÏ™ð…; æ!â_±£ŸÄ:MOÐx“t°·ï¬·m¡¯Þ)»ñV|'2h°¡à>Ï>ªûUEÊ v‡`9Ý>I$ô…>Ÿ(øk·?¸ôÝ'‹æE„?sM{êþnlziVøõð¯î?ÚÖºïS<ð"•W%Bb"ÈÜ‚k™ Í6"ó`åÄE$Y¶`QˆÉlöZdp d½½ÁØ1µX1’˜-b‘7[,„“M²,ðD¶ðœ"?E¦A§<\!fKQm9h9láÓwÇ64dáÁh~T³a¡¶Î½;Ä‘lNã*8Ž+²ZØc„‡v\bøu°xŒ'ºpƆÁÅUX5êÕ¨‡uúk˜)ˆ&7\ùéƒÏo æ g¬"«qFøÏáWȦÁa÷à $ÿ›RàÌ „äë3VükíJ+‰'t‚“•sýMzËLº¤W$’%dÙóPWl/áfÉåö…\µP-VKÊÕö&Ô"´ˆ-ÒJîJt5w½|·ðz½Ïá¿DñÀuÎ,Ydd}’%ÉL8‡”˜KècNŽ—Á?3Ñ—+Dº¼W>†,íb ö›¯§‚—ôãë ¹f篸Ä+m’ˆâ‹Ü¢Ye/·‰>®æèbKŸüOØÏ?xTØäÚ]\(ØžãàF±×ñŽ+ÿR¾„_²×ñ”‘÷%èu½¾M#ã¹Hó¦˜g, +é³P—ødd`èXŸ­PÉNì´Z<ìÍÅ}.ú蟾 Ð +W¡¬¸ +9Zâ¤õÙfW +e’Ç)ªpä…øCgÞüÒßÅðéïbÏ…ú??_€ý6üž>ÿ'óÙß‚ˆ(Ì“Ó&î+ªë{†>½ ÑXôµvÁX°ŽuŒˆ&â ¶ öYhže›e_l­Œ­ˆoCmxiTVÄ®!kb¯C×áÛ¬·GÞû¸#ž~åQÀìKQvk¯~Ö„Á…À¹D2 +“]n“Ý[‰²Æ¥Ù¬(JßÏ£«f=låi Ûbí…‡³ÒgÔ^!m_Ô¡(’¥EUDÕDñQEq&+ĺ֨8sáaf‹Œ•€õã9*°ûŒ…p|Ø¡‚ÜcÜ1Ž4ú¸3ç¼à^‰àV©ÉôiV^3¶Žå×®i¹qNÚ6œñ@ÞÆ𱿠+¡ð ‰¶>úlLÔ¢Ž¹÷<ÍùN¿;þrÛ·›­Þœz¬çômUb×ÞtÍGtk$ +çÝ’j£o‡ÊfN,–l›f[Š–àjy±i¡Å\ÄÍàfˆh9·mFwp7‰¦±\Ÿ!¤JÉr†Yµå“|._Î7eÛÊÐL<ƒÌáÊø2a¶8CšcªDp•¦(„—q5|½XgYÉ_lºÄ¼Úrº +¯7mF7ãÛL·™ï²ôØ>àÒ9Q„@‡^ˆ(J&³I6 t­Y¶ð&“¨¶@¬l9p$IxÌì_fÓQñj36ï&K`†Ó5³ +¨G¹«Ùñþ’GÉÕ°uÑEh­‘¶H½à©‘èS3ÿNñ#îj O@;žÌB~Qã%ØA¼¤šp^¢BÖFÖ’Md;ÙK’Ãä3b!»±ŒN$=†eaXþ*eú +ªèíðÕ¯°,%Y)’‹ÖÓë/ž…ìYãæÙõÃî5fo+P§Îi¡K¯ÑÜ](ÂúÝ [žÊ–ò‰ÎBNvÒuj¬Êèow2Á´Þ£²èÏì€î€{Çè¥ ++ÕŒ±³5 +WrNø?á-ø“ðçxÜ؆«Ânl +Äð߀bø/8kðÍ0¦+u&ØÇ/ ú +IsåK¥ÒôNF28²Ê»è³œ¾)yì‘ÎPq^EFMI•±þ!òAß;Ö7¯GHY´t_Æ‘ !Å‘âJ‰KIH›,@…R¾öǸü±%–éŽé®éqÓZ9Å­'×X6¨ë2DÛ¬[[]Fn{H} ¸=ã1K¿m§cgÜÎÄÞŒèyë~åùÈçâŸKxÞ·?°?ã)oºßŠ|=þ-õmßëcèCå£Èã?Q?ò}øýÇ:ùZ|0ƒ´e`ØBÆØîP›ÛåtFHIÄ?– `›¢¨Îˆ(‰‹W#q  Q0Sq:ãAstÀlN +°7E#œ‰ (¨(šyn–sÈI:±s€<©Yâçf% %ƒ 8ayÁ­˜Ñ`o‹jÙA\ÄåÁž Þ˜îŒNˆ²£“è«ŸùÓ8A:tûb¡)ú)Ê÷RàväD‚oy:V‘ŸõÚ¯ñŠv¥0b€e6=‹ÕÏUâ {L)T=Ê°Bœ®Ð0ý{G,ì„eø¸Å8oñc{Üo¹øJWÁŸÛÖÞ]ø½ëbòòVÌ?7Ø~ïÚèÂœ¬ú²8k\#=€¹âŽúÅÍ×µ¬\M6\¢¤çvœÿçp"¹²ÍÈŸ°lvòÚ°‘¡“áü ‘ +JDßj¿œm›á**‰ot ãA*ÔFW»zºÓq§² +muìtô»žGûíû•Ê +Ž’lNŽ"`\8‡»ÑyHˆÓîÀ$Û#¬v'áìp¨ +‚°´_Œ R„ßjq(Oòvù LdúPk“<$“j™púÛàr;}—=®ªxŠUöŽ«CÇ•zè‡ÀIWTeÂ)1Þ|ËŽ…ÆCÇÎÙTÐUìWPÿ¬\Î葧[ög‡ßw}ʥЇí~`öèÓX¯D/ºmÑ/n¿ååW›»ÂïáÃkæN¿zQçâ¹ëgñ©-3&}p4üÞs><ø&·ä² +Ë?k\½vå?‘þlK¸vgzL‹‘ñ"~‘üº‰‡ÒÆÙ8`úø¥&ŽgG­à˘Øã°·Svq/x£»ÉTÄѓװBöŽÄª\aCO#fDÌ?ð~™¿Â@g¿ tª +˜,;úSoGaú¦¤¿\sy2~0}y.wpâ•Âî“á-'{`ŽÓ!¬}€=¿;´‹¢M>žšÑþbMÏ‹ÎÕóÜñzž•Írm²?c|€a£!š°ˆT5ÂZa‹°Ÿ|HèÃ?«"T ›…^á h>s" +üáÈ“Ô‡y«læj;ê(£ñtö5ˆSèPà(#è=^QªYç(KgÌÑXý¥hÏÙÏ;;ª:õUJ +N§µñPf{ ¬x%Ì¢-·X®„ _-/G¿A·ãÛ…½²™êp¹ü.æ‘(ŽøØsñH„NÖX¢¿éÆ^÷sЙn8úèsŸÀ {È3+RùX–îè’_kN…Wù +~ ÏÓ£÷#<B IèZæôß>ý¾ŸþVðwÞôc*O9`÷âÆ…Ÿ +3v“j§òa~‹vAœùÔ|é +Û«E'å™}ùÞó÷æ¿{èÕðùE¼ +7¿ÁÚI“ÂsÐÔ‘¯û€ºÑcE@â»Ð¤- Q?À·CZ +3˜es¡ì&¸¿Œÿ':%ìúHXˆæA9ö£J(Ï€ÔðÓ/œYPWð(› ¸—C-_Iƒò+¡| ä[!鯴é—èä{ø®¡W¥4“ÿçÐIÀ¯€¾¦C ]”‹nAÚßOŽq«y§`Þ/•ÜÒ­Ò­²Ç”eúؼÒr“5Çz¹m±=Úþ¾£Dñ;㜯¸t׺G\q,ò/Q—Goõ|³%Ö»!ökÆ£±(øEÿØÛ,4¼Ë¿[ÇC²jž~[\¯³+Çxjfwk…eæP#N4`ÁW°€*1`;Zê¸yDúk' #Ai3`pC•næP®²Ö€yäTú X@Vå‘K9hÀZ¦¼gÀ2r;§° •8°™Ô:ï4` ç>=òK.¹lã–DÔ°eFS;…yÊõÄècÌ£€Gd°å±žlæQªgƒE(ð´0TÏÕ –¨\<÷0È£÷/³~Þ1`ÚÏ)›¨|câ +äkÀÐOl²ƒ|!„Óaè3v‹ƒ|cŸ6`oì[ ò +0È7näwÌ€A¾ñ òõ7`¯ïùúN0È7­—ÁfÊ«±V^ +0ØåÉcç0²Ç^Ì`+ûØm s«ÓcgåÇ Ê„Á +” ¤02:ÏÝ”'‹ +ø¸‘ÁPè5`¥^bp$¥'ð¥=Aƒ£(ýÁ ôCÇ +ö0Œìcp¥3xÄ€Îà7 N :®0è@ºÎCúæ¯'}¾ó(9½™ÁÉ”Îô:ÓÏàÃÿ«SüOœA-A†bÀü0,3þÀ@F&ƒÙ¼20-_Ea«Ž¿Å€iùS frÉ8fÀ0¯L‚æ£5¨5 FT‹ê Wуæ£&ÏFm¨R·¥‚uoCÓk-”‡† +%ÍÐ> i¬¼öÿ±§¬ÊT4jšÑÊœ.(› ¹>Þ8TŸl”a@9¬t2´h†|.´Y4t³Vs¡¿.Hh\ë«êks +£žõÜÍJBÐÿw©ž8ª…ú#m&²¾;aœáQŠ&ÀUEiÐ#Åé„š.HÐnìÑçÂéñLËŒ‘–gÓ?Î#L”ÛõÐýõ£N´Ê(ÿ÷’R¡´xúº +ŒþÃé6z]RTÁ!¥íéïÑñfõÆnd«|Ú®z¥2ZÍZÒÞ2€&];Ú`\JS;à®ùQ¬¦•o5£jùȸ!Cç3˜n´¡eÕsXMãh-P“>B{'« 1ýžוŒj]:º.R¹Le”t3.ó­hQ«ÖÐ`]CŒ÷õL/©¦¶²±FkDÑW-£¶la=Rº›`üÖ£Î}•Q]ËÆ«3¤¡×Pª» yÔ²9êíÖŒÈ?d¬‘vC‚ +Œ7]LOõÙ +K¨Ö %Me#Œ¦jXò”7ô~5ë»i”6PÜ6Ö—>öp¹Îínƒ#u†¦v}¯úl`\ A®÷]g”¬dœ¦uF§ÛŒ5YkX…nF)•g‹Ñjx„:Ö~•1jȘ©¾Rig¸Ð˜´7½ô _CwÛŒ™„þJvwFª]LK›u?¬Ã¹kd.´®…õw¦jIVÔÖü¯c¶R5Vé0ÏêÙØËY©Þž®°!Ã&¶îÚ +iƒ+]Ñ« në=œÙ#j™¬tíPëŒù‡˜ÔšN;[{º6¶²–úLFkwhD³èÊ¿ØL £†êæ°-ÕíNó-ìîŒövgëúÎüêŒ1–±V2Nן¥› +¨ʇ9Ku»nd†L·U¦3Þv1½ë±'ºÔ)íúzï6¬†¾šº -;c=õÚ&‘Zt k¯SMû­cµg4M½žq«­’5#³»•ÙLZ_Ë8ÑiŒA×ÎÅnÖ~˜âáÞÛ™µ0»9L[&Û1»¡n"ìÄYÐ/ýd2¬Ñ6“Y§Àhbk© €Z™„Ø]ªf: KÓ¦®Ð5u¤\_':GÛ +žŸÑÑÿn;#™a‹<,çe¬v +௳nĶéú|f?m-uËqÆŽêë7dØÌ.cM/g½4ŒØDºZ+Ñèê^eØÒe#»‘>f÷OpfØv®±N +ÆŠkÑéNf?ºõÜhèãñkxRŽ5ŒêåÌ*þþxõÆH5p³Œ:ÕË É´=ÿ„ülVgsJ·Èß׊ïG-/UÏ›9µdμuòô¹%%³KæÌ·™mæùMÀÖa®QS™¡0ƒnÆÑXbl2T‘霗­Q×´­¤-먶ŸÙ:ÒÕ”ƒé(È–_+ ×.ïlh š˜©VB³¦ZPƒ¶etAË¡Ú¹šªS®rº³¡®äÜ|²Â¶Õ`PW.ku5Ñq /Ý- ¨@?ˆª}ª+¯Á¡³bü˜ÙxfrÔzu¬lèbÀݫkèl5fÐiÐÍ»šÚVÂîÐÙ°*Ô°Z7Wß›>ÅI6€¨?câFæd1ÃZ×}FÆtbµÕ?Ü-#y¤±îŽ`œÚî‰aÁ¼É° ¤M_0V-7!#{|v¶É´  +³Ç?®¹jA~^a^¡Íü#«î'#½Ë2Ècë"ÙÃê6¼®•Æ‰2MFŸÈü4f7Z‰màU|5+XÍ%èø÷úøq¬FÃûZ1ª×Ñ-¨¾Ô8kQÁïúáV?ˆÁ]Ç=É=Ëí…ë¤r[¸=Üï¹~nÜjûX??ùùÙÈÏÏF~~6ò󳑟Ÿüüläçg#??ùùÙÈÏÏF~~6ò󳑟ŸüüläÿwÏFFN>BHѧþg$?Œyäº6·1 ª3£O.héèÞþüéÌòèÑýp «¯Ñ=ý8V)úîV SÐßGúºÅçCI÷wÎQ~ k¸çaß® + +ǾÃ4þ?Ž½Ð°ïg8GwÆÑ}ü0Æ V»ŠýÔ‰ÐOáU^ÅJÓêÖú̉Ó¶fG÷õßàÖˆ6ƒÿïšÖö£ºó=LÞËOâÏá§òùü^ãÏåËøB¤ò±P¢ñ“¡lô¹†ú_`Ï7NâÞC?u^÷ãX¥ÿŸ¨¾ŒÖáqÔÆàì=\qV»Ã)3â„Œ7àÿáZf¯[¿ÃÅŸÂke{@}¬ï؉þÁ%Á +ÝþÇpþ·lÀÿ’>ü¯Ñóÿj?Øw>†¾„äG¯£øÛ…4nvVnŽ6ÀÍî›”K³þ’™úm»í[¢g +¹ëhe\«ìwEè¹Å–ã˜ÉÍFk!}‰CÅp-‡´ Ò$9ŒzÂ×ÇxkžäÊྌþ¶7³êÔœµ{¹™h3¤Ã8VšÍˆšÙŸ—§çYãôÜï×ó1)0°Ћ!­…tÐh.°æ&wNÖd7 ªfÁ8›àºÒAH‡!}Iºf¡,Håj m)=ÌZiܬþ±éx³Œ Ïê·(9“nt<Ð/(Ð+†&3 Û¬ÙŒ~“’ãÚ5´¼Ó§MÎÑÂ"¼Û_49篓cÈ»Ð(›¼ƒ4Hj ‚tÒ HBpí´R/ôÀôLC^„v=ìÿtЬ18›ÁÙ V¬8÷# i´¹zºrŸ–R}D<"‘½â^‰l·Kd³¸Y"åb¹D¢Ã(sL®â¦ƒ¦ƒ¦À,§0QNŽOAÕ¶CÚi’ˆ²H>Z ‰ \½hI1¤rH› m†´’Œ¶Ã3¼aœj£õ$)$îòX_y€“Œ¡_Ä¢e˜ÕC*§eÜ,øLá¦øäÃ'ä—_êógì~qxax~8@úÕÆ–Ø"–›G+ð}Ђˌ|•‘×y¦ž÷Æç²,WÏrôlœžeëY–žôl¬ž¥é™OÏ¢õ,JÏ"õ,BÏÜzæÒ3›žYõÌB³þ€AŒ_'Ưã׉ñëÄøubü:1~¿NŒ_'Ưã׉ñëÄøubü:1~¿NŒ_'Ưã׉ñòѤœç¥ÿïË^гçõì€f¼%¹Èû½Çh^È/ƒ´ +R +¤LHH~H>ŠÃ÷Ý8²Iýj’·z²‰;µAZ i$ž+ìW}^/Ø£  ¶@Q'€êNµÝ ×íöBâFê—·úÝT\ãÇìR¾b¤ô3 +ñÃz¶PÏèYœ6òo } éH«!µBZéè;’Yw€ÛP|{`‚÷WP†L(†ûÕÐtUàao;tõyv«oßµ-þ›¼ ++¼5~¸ßé­¼‹2pJŸw. ˆçÁÝÂÞ2|¦1ðô@Ð; +ŸJéìóNNc=jÐÖâ¼çúŽzÏ +2÷xóçxÇeõ&J¼cBÐÑãÞ6“ÍTÐ3€“´|©çïRO§Ô³@ê/õdI=A©'UêI‘z¥ž)BvÉŠl—­²Y–eQæe"#9‚þºL:ýÖe„¨ÐLäé•g°Bô¯b_Î%X&hrõº¹2R6oJï„`Ù€44·· XÖ+W\°xÆ7VÒÒÞ}u¨l™Ú{j^Ò6Ÿ¿¤WHš‚{]e¨lþO/¹n£ù‹AËiƒkâèÿíº asÍ/㌼²rêâÝ`££îªDQ«Š=Å®IÎÂÒi?p©1®£~Ç3 +–U¬Ùê±­_òæKp;n{èm½õ$ôÞR6oqïC •½9J¨,ëÝ0O]ºxñ¨’i»H4Í*ïâû‰§d.-çû§UV–ˆìnÀCÉ4<»ŒTŠ‡T»ÌðÈÃ:ž—DS¼4šžç~äex^Ïý ÇoGH-™¶CUNB!†JB£pváj” XÉÉ:Ö\M±puÒŠÕdùý€’ég(8ùYG~ÏPòΠø ”ê”j†rÔ€ŽÂ=4ŒÂ=(Áÿ…¿†)%¡ySpYÅâ2šR9u©žG)퓘fØb&Ý·½Â}‚,ÁÊ^sÒ”^KlüÅž R„³è.õ­Å¸ª’AŸQH´öŠ€&A¢=œãó\·›GxëÁ +Å6£*crÆdZ:O«ìô?/6ª<—Ÿãûÿ9c0 + +RSmA44ÑÒø:5EK6ÕØ|çïѱQ×~]Ÿ +}Üyò~¢žËóLΞñ£o‰'<÷×¼Î?¯ú¯¢ivO»1í'·/lÚòYÊÑ¡^õîx97I’Õº¦9Ùú +–5Ã!ë-Í}_.ÁÙG´Ö ”Aø‚a +BÀ½º·´±«ýÈ|®2Ÿ+í¼ŸÛXX…P +tAs¡ ‚ÎÂ/Ö…`h5Ç —vXl¿>’½ØGå‘cÇm#°t­ÂÅþwõ®nT +endstream +endobj + +85 0 obj +18942 +endobj + +86 0 obj +<> +endobj + +87 0 obj +<> +stream +xœ]’Ínƒ0 €ïߦé °‹ˆ‚<-t¾ÏS==ׄTµ­ZÝ/÷­/ùKx¿O %«4c óT7àj{… ‹¢\de™`Ûw:â’K×|ÖΧJŸE±Ì=+buBŽ‰u‰¬‰Sƒœ›Ùp\!§ß#ï8ž"ï¹?åˆüÈýéÝ‚ãò‘ˆOœCù%÷Œ=ˈ{³¿&fƒ=%û|W²¿)Ù?Æž’ý5å°B}Ø_S>ûœ‰dƒ¿K²Œs«?õaÿg%Wÿ2ûÇX«Ø_ïÙ?¡8û'ØS±J9«ÿ™ýSœZýñ-Åþç¯Ø?1´ë?«€»ú³b¢¹9ç׋šö +7ª·ð»óÓ8a}¾ü¦Èt +endstream +endobj + +88 0 obj +<> +endobj + +89 0 obj +<> +stream +xœÔ¼{|ÕÝ?~Ι™ÙûìýšÝÙËì%»ÙlÈn’ + äBH !#‘›(ID”²^‘`%µÞP+Øz×–pX+úh«ÕVÚªÕޤϭVÓÒ­} ›ïgfÄþžïózþýídæ\ævæ|nïÏ眓×^t(($]~Õò¾Ðا!„Лaóå›6 +O¾Ói†ü)„ØWVõ­¾ê›ßÝú;„Ô!Ä\³zýæU%/?ތщÐMï­¹bùÊ[ªþfDhè <£j +TÜWØÌ"ô­”Ãk®Úxý÷m¯–Cy·ýÿïÇÜûä‡ÝK݃<ÿöÓ°\h?Ï\‰B…uã§( \üý‰!݇ö 0:ƒ+ÐËèjEO ¨݃f¡·Ð>d@›ñˆF!ÔˆžB"ö#‚š‘3h7z]ŠЇèŠ¡6ôl†ç4¡>dG¹ñOà؆î?WiPú:Ž×ã¨ò-$‰ðæ]ã'ÅÆ6þ”¾ƒ>Äáñý¨r!Š¢mè[Ȍ֡ŸŽŸ‡–†Ñ +ô$¾‚¨í¤3ôàø•h*:ŒÞÁmkG›™÷Ô‡Ñz¸ë{ØOŒ0þ'ô#£+àI7£; ÅÐ ’¢˜½H@4 +ÍEËáì +è}lÁ”4Ÿ9¾jŸD' òcŠ…v$Ðl´ }= +½ñ.:>ÇZœÅßÁÏÂö üæ=h[ºmÙúôÞ“è9t Wà +â è-Š£KàÜ.ô8¼ÿ :‰Ûp7>_¢gÒ…úqë¸müOãã¨uA ÷ —àgq®7PAj#í£72SÆn‚/\‰F'Ñ/ €~ÿ}‰Kaû#ùÙ6¾xü©ñ¡-ò£4-AÐ&tú.Põeô +ú>GÔpå[ô«ÌæÌøÝз4ÚÞW/€gï*@#°½ _iÂ|E +ž‹çãÕx¾à÷ñûDE¤Ÿü™¦Þ ~GW1Ìx-<ÉŽ|ðÞZŒÖ¾½}7|ïSèUô:¶á.ƒ/zîÿ‚L%°}¼Eþ@ÝFí¢Ï3·N>-œD,pÙ,è‡kÑ3Ð ÅvhC¯Ã×àÿ-"‡(ÅS!*KÍ RÝÔÔ=ÔkÔÏéúYú7Ìlf9ó,»¼puáãmã·"YK¨ ]Q”DT +ü³ +¸éJh_lèFtDw¿Üö¢gá»_D¯£wÐïÑg@„Ðæµðö«€ënÃwÁ¶?‡_¯â×ññòF‚°ÅH©' +¤™¬&·Áv9IÞ%S^êrj•‡íêõ>hšg¦ÀÖÂìdžT½ÁÆØv÷æùѱұî±?PÁ]XZ¸¯ðRáOã‹Æ7CûET†RÐÒíÐÊÝÀƒÃö pâôcÐÝ¿VÚúwL0ïÄ!à†$P­ϳakÇó`»¶Åx lËñ +¼¶m8oÆ·à[ñ7ñ½Êö|Ûãøi|¶£ø8lïàðGøÏøPÀÍ"‰’r’ƒ/m ³H™Ûj²¶>2@6…ž$É1ò.e¡DªŒZNõS»©P/SoSÿ¢ ¤Ëé:z½š¾…~‹þý}Žñ3MÌææe•G•Q]¢Z§z@µOõ±ê<«b;ÙììÛì8'‚¶ú |÷ᯩ¼rÕ[øÆJ_O>¹pR}Ìv| ô˜Š,¤ÖSwQ¿dVá3”€ƒ©µÔ•ãߣšÉ—Ô¼ˆ¼ˆƒ”Ÿ©¥V¡;Ñ8~–ü‘œ%¢mx!ùÇèoá£dÕ@TŠ^ým£oaÀî_£Z²Ÿ ¯R·P·Œ¿€j™GðÌ#äH O ú¤z;¹nú9YKv¢.:ÃœCk¡ßŸf®‡þžNîÀ¥ÔÛô#èC*DþÏàû@kü ·ÒarÉágAãŽaÅý¨ß‹$ü<þ=A?E=‰çPk˜èq5˜¾ŸQü6¥AÝrq„Øp'9C.¡~¨:Ie1-ñK´S8 +¼3ù+ «Aî!QÐiM M~…§ 'ºôýÙÂeͼÇì>{”J¢ù(zȨdãCغÐíh +:€„&çšFa÷ +MÃÍ›Ö 6õ6Âãök5 +¡†+4eI´_£…¬rÃŽPß~옎• q4Õî'ˆÓC£†Ý¡Æ¦aW¨QnÁ0%6-_9Ü9¯«©Ñt—%‡qÃå¡Ã(4sؘP.A +Êk†U +ìòa­ü5h§°?ybðέèMèV†V.¿´k˜ZÞ-¿Ã”€÷6;¶œv~U„‡›º¶_|ÖC +69× +rqpp»0¼w^×Ågò±»ž1LÄæÞÁfxñÐ…m x¹­»kß/äï¿©øuW„šäšÞu°:43´fp]/Æ=8Œæop»¥c㧻I\Ø + ×{BÝ˽û­hpþæƒ.Ip}ýLYr?o*vë~ƒq"£Ó_œ¹âÂ9%§\.çÚæ_èW,·(4ØaX¸\€–t…à›jäÃ5hðò¸ ~Ýî^ ôX;¬nèäk¡ž—ïfD>$ ~Ž€þ¡ÑϾ^³|¢F%òŸ#9+sÉFƒó“ùáDb¸´Tf¶( +mœ®”³eÉM#d8ÔÇ @÷¡NèÛåݵåÐù€LÞ#Z…áü¼®bY@+<Tžè&½ò™“gl—Ègò“g.ÜÞ>>¤x#¶a.ráÏÈÛ-Mkj‡±ý8}Eñ|Û‚PÛ¼%]BÓ`ïD߶-üZ©x¾æ¹‰.ž€¦Eè©Ù!`½ùKºä +øcÄæPÓÚÞ5hã°¥¡‹òîbŽx(åQÀ¿—^x²\èÒÉÏ¢E•Âÿ+GXX©ÁBó0ßÛRÍK<Å??!ñõY)Ž…8Þ?'q‹U¹.Hñ‰ ºbË¿ëLÀgõô×µóc°÷ô$¾èÌGòwÖ×Õ×ñuüèèöT‚ÙÊ¿‚Ì9œs&àÇòðñ¨g ¡KŠ©Í.s×£œ¹µš—¡%æ +hy‹ù!@›ÏãÃæ7ðaó_ +=¸§õ'p?ðÓ1DÆŸ:è3×hçA»¾Þ<2þñGKÞœœ=0‘x”äˆ+‡9§œ}O2šsf»9Gx쮜êhsð˜“ÅäËÃÖ‘L9”(þðD +ånԨʔ‰FB¡lÀ +²*›)„MV‡½²ÒÈVN«lŠDà¼÷QÓ¼bg9~/½(lŸ¿ÙéHbå‹Ãö©Ó¦–Leæœg)ÃV©(f„s;èÆó/L–¨}MI‹8Í¥vPûÙL#—H´ÞÁJb^P…Í‚?—¯J}DC™æ­hkåíh§vgVUb¶×òõùzZíÃÌQ5 MÁ9µRýŽNc`œÛ4³µ³³mÕ +µ³§-Ö®ÖÞ¦¾Us«Ö¸Ð~‹øë—Õ“^®eêRñ²Ìó؃tH7~âˆ:§‹is:™'ܵY^ש#zu” $›t´®Î)wo\›ëp.snpRåÎmNâü†ŸÇ¼ècÓuR©KÒ}eù2R–'Ó#T³d¢µ©e¸¬WD•z.“©|¯O^„Y +9$úż8$Ò’xF$y‹Ï“BÛø‰þœm¯–|žò\+r¸y–âY|†Å,f¦7\=Á‰öѳ£ ~LfPYüŠ°*ª?;vº‡í¯€³ SN¾$‘(5™sð—«H7l–fe§zCŒ¥º¦ª†¨Ôœ†#ª@PUV›©ÄâEf‹Ñ¯÷â`h*“ó¢.#àlFköò^l¡VUç•y +Þ <øK”––ÞtÓMx}?î@= +]êÍÀç¸'€ÏUÀ§¥FÆOà•äˆ!W-ÀÇʼ­““S’V›s +Úœv/èPÉ­Íi€XÕ19Õ@ªT +©úOOþ€¡E« +#ÙLuUUu6Q˜Úa-ÖUUNqØv›Éj·ËÌ]m“ë£&¸Ge³B™õÍpÕ´e7øâo|¶xA½!å±|xÏ–¹S½fÃÈëlu}«*jñýÉŽÆE5sn½Êäºy]CEãõ‹Â;VƒÉÚÔ”LÙ¢¡¸fâ¶Âë·Lµ²úºšû¿{ê\ÉÞ\Ë2ÙG·ŽÿÔÑ/>÷Ò,ÍÐå–áe„Ô—ì6ív½h{Ñ>âúØÅî)Á;ܸCס_¦[¦ÿÜɨœ6gÔIÙmN—›ÂòÁêÙ‹)[šÁÉ‹©4!X¥ËrI£Öþ–íÛ_m”í +«çM¤ÁŸIIA‡u©ò’áRNM3ak§ç-YxË°å„å¤å”Eeéõ>»CÖñÀ9“¼Õs¶g”Þ; +jJpê469rv3ðêïš÷ 6UÚB&¹C«ª+UrG²¦P(RU[ß}·2˜nŠ†ò©®ÒoU_SæˆÓ/~Õ<öƒîéñØŠË+—]NÖìk["W@oéÁPýƒ¹ <•ÿ’Êk¤Ò¬¦¦WßSe‘|ÍP +=\s¢æd +•PáΚޚ>¹JªÁçŒûL#”Q2Ëâ¾hkP÷ñ­¡@Ü¡ R*”¦fd|ÙF,D«*IÒl41™xËVið°5}š=š·4´f„¼ ‰e(NùË:ËzËúÊè|ÙP.èŒ/;Qv²Œ.ë­~b›Òo7VL‘b5êêGëëL¹Üç£çñç2³*‚hu{N%z"^ÆåÅ,çfK¼8eYJ€ É"„AŠ¡G«€y‹¼ëæU´s•¬ž3àq«°4ÔWOV²Q·o¸yÆÜ>Å IK…é6iŠ†ò7¦+ÖµÚrÍ…Úi!«ÓèwÛÊ +ØÌÜ5¶bKÓ¢K¥g +?\,8½áp4ÂÏÅ÷]Vžé(x/KùÃa‹¦f5í;-n>Ô”Ñeþ Ú¼sRm(Ãeeʤ³ÙÞl_v(Ë”ÑXRòy( +gUÃÙ“Y2œÅ½Pq"K•pö¸ÏX$R<î ·¹¸ÏÐ*‰ûBE"UDKg¤}^šRɺ“„ +‡BF£Aã°‡Ù!sØÈõq{¸·8š“‰ä‰W–„KýñÎxo¼/NçãCñá8…â<Ø{YÝ«­öL¼7S$TâO(³ÓE©hÑE9¼äqO’ ¨ÔÓ@(гøÿI% ÇÅ•_Ѩ·=zwÛzÁnÐVÌ,LµH•zFûu›´†Š¶ÂTksPÈ5bk‚Œ¾Ü¶¨îÆÂæÅ~—Bc¾nkÿÍ…’{‰'žµ/|¼Åm ÷ÉZÆ(ïiÀ[)|ß!asZþü§¥/s^æêLÓIÇ +ŽÍ‘ÍÑŽQ•‹q©JÛX[LHw¦†¥³:€fcÑpLL¥ÓÍXJÏÃ]ì_W¬3}êöšØ5¥}é<ΫneoåKóé=¥ßÃß#{Ó¯”¼Sr*-ܦÚÎnQ˜%l÷{ø@Ð<~KyÚï1B>g‰ÇŽ8Ž`4bF#,ÇÉÈ,A)æŒ8Êclš‹€:°¿ùý>Â9‡=(qê焨üif}Vˆ¦£R´3ÚÍG‡¢lt„oú¦xGìŽx>õ |±ø<L<{1õšøZì}ñýØɔܰ޴C-²QuLÏ:øS'3Ÿ]äœß¡ÝÅßáÜáÚºC¼#’O9¶«owlPzu7¾Ž¿ÎD«Õt¥(j€÷|˜w˜|¼ +øOúQcðý.ŸÏ?2~ûA.ð±U’œbXàXN͆ã1k<RˆÑ4§¶rœ¬¯ËÖˆVF …Ãi§Ëêtºâ‘ËécR pQ®»ÃåN0ûG£ˆ‹²ã ÕeÄç1"ÈXR'iÊ—E°ÉGHÀ!õÖh9wP0pA# ÎÇÎÄH n= ·Æö²2õtÆq>Že)Ä%PŸ'â'ãl¼·ì*= šÓå;}v´§ßyÖ= +Un¨€ÓÎÓn€ +ò>:¡RÝ2^¨¯“!Ä$V-æá(‹ávfBú }œœa&3“5‰Ä„8þÏG–ç긺¢€âž¢RNú=á­ºú0`ʃZdZ’s\”XåäÌGN”›RÚoËá ðÒ°É@Ña±D/¢ ¢ $•²,¢Å2Q8$‹°ç³Ó+¯fœQ{>Ôâ³r'_²Fs8°8^øyüÃÂçbá7%5uÔ="íóú“cÃßß^ç0P¢H9øÕ6öw|®J°øˆ(êמÿ”Ì;J‘Ù•zÙòš©³ µSðzéY5ÊƸ7N,™”}eÕ-Ìm*¢V3fÎÅ¹Õ «;¢›ÃîH¢W™³žYæ5ê5šµ®UîË=k’×s›5›]×¹7z®OîÐìp=€Pßï¾/ñ<:™ùPJ$’¥¥ÌY\VŸ%§øYcò™#œàr»Ó¥+\L$ÂjΪN”Â-¥n5­á’º@0¸ÅlÆÀ슞6@k£å¡\‰1ãp¸]2s{viðš3Ò €ë¯J³µ^Ý¡^¦¦Ô[¹lJïlöDص,‰Ë“õI’tUfžȆ<1÷lÏ@ûéžþÓcg¨öôÍmº¢ñ#Tß>v:QdÀ¢ªFã.b4YË›.¨ùÿ‰—pX)a™ÔÉ +Á.ÊZ48P]u‘‡!ÛüjQxD‡Ÿµ••>ø™‰å‚ \*ÆœjWagÕ¾ySçT§¹˜Æ7+<£pÔpñŽJà…hI´©0ÿW:Ö3:TìýåÊÇ>”ýݳ£üØGü‡õõ£üç=c=*†]öv²iç_ßÎê7µ±­z“žÕÒÜÒÔB©¦ÖÖÕU2¢mA4‰áHLÔG§ÍÞˆÚªg— U9]‚¸2íFÀ-–|íAä,qCz{=.7/ÊuR 2Dኖچ¸µfN bÒl Ò$ØÈp(w¹¼ÅÔ2BzëâÆø‚ï +êEæЯ{²E?º¿GþÕÔ ÐeÔ„‹ +"œ!áP&6«™®¥’ @0L²¼UN¡Í6+™ð€'xÒ\­€Òj\avâ!2(ÍD˜üµ3¼ aöÏî~¼ð«#*lüÓ¸ïmÌâ§7Ö.)D +¿øKaÍ~‰_<÷nÿÁ÷Îï˜Ón¾ç@㬫_xøš¥ +Ý|àå¶öþΩ³’µù;…šÙÔ +ý§® É»qËgqð¡Ï ™/?*Üñvccá/…çþˆ¿ó%æðë?[8zìha÷c-3j–\·mÝ·ðšþMMW[:6¾:ÔUßÑuôÒ=+gÎo?MÈJp—ÔdÎÛð“ö#öWñëêWJÞW«ÌÒàu“}±í6|§z‡ñ}ë—¦dix"{üøǶ×ÝDòãÙ/"Ö!rZ3-k¡h¡ðNh|R>vÒ½t=DÓ*ú3'%ÝÑ5øÚ” ‹q‘ýºDÛplAÛpç¼%ûu¾ÙûýôìùKº^ƒJˆ†Ý?~¢¦¦¦»¡ë‡ÈMMA4²RS>á?ñ\T“×ÀÇUX² +—˜EC„ˆÞˆFTELF«_ê°] +9' 9‹ž°‡‚ƒMë‹ÃÅ‘<ÙU”C.`éÀäá†.Ét-¹VµE³Å°Å|½ýZçµ^®§l!Ø@IíåM9ì6Ù¸i<ÚAiÙ¬2»DeVåÊÌf–ÝÐrüÆ•›ÞÚöÖ–Õ[ß\½ræž›—cí,jß#Û÷Ýp>ÿøÎïã_×ͨäÆ× +ØûgïìEˆŒÿ«ÐJºEQÓÒ74SezäøÙüR~‡‰¾=‰§&맶%—&×™Ö%¯á6›6'oåg?áþ¥Ö§§vUvgÖghi*.ç¨XÜlâ>×íAKÜ猆P4Ðõ¡FbNÄ(:ÅWáªnKØ”hкœ†)~ÍlJòš}`J>ˆEA5‚Ðè |£œœ 0ÞÚ—Û&c¼â +È èS?:`räø 72ðuðSh&”gY='f"ºHZ̲S\®‡C¥ºJÀÚ”€Ðâ(>|êïIPb¥­J16+«ôttÒg¯´_ä´3E/QöäÀ,È,ÁîȬ]ƒ—ößÑ÷LkUlŠ#×V\ÕQ‹ßIĵáª+§Ï»TêJ—‡©ÜÀ»›—¯¿õíч¶ÙŒe…O.«ô‰"¶k+VR+ºÓNöÂ3Bµ]sWûeÿ\§YŽËÎ)[@ +#+*! +’˼ÌÙãêE½Öw)Æ%xsØí’7ç—%GÓКáñ’‹c±ŒR½´4•ñ¨\ê.ËeöeŽ%Î¥nSj«ætŒm¶j¹Sµ]7ÈßVò=ò¬ó°åmò¾ñ7üYòÊbF,âx0¶½l/×ÇæÙê—Ø׌gXYý­„R?…Tà_5T©›É,u‡!Y¨^AÈË×nËcêÇ4#Üaõ°æ'äOä”‹{’%;Äîe‡YšÝJ[QÚn“Ûj1çÌËlÛl{lØh›Íó+ÓrÀÜš£egÍ"'ïI-æ]¡Õ^êÁÑIJorö˜'g´ã +ömö]vÊ~ÖjÍs8Í +q$Ííâ>à(ž“8øn˜;Å©¸g 6íg PIÉœ6H†N… ¼A0Pg Ø „# 3 +”L¢` }¬_ Hô@àNPõ£ÀL¦\¹QÝ`Ã=ÝJØWFÛ9  0ý²ìR!LH·ôUâüŠ{ÊÂË´¡œN*ËéaçdG.&û¦r¢’O±ä)ž›(iŠ%M±¤VJ’A³ñ®œK0åô‚2²€_ Åv[TEäu +È&"Q%Xõ¼råö%·•ùm?}àñOÿväÁmÇO1¼ëòª·©onÜxùõÖÄøýO1ûÆ3µ]áé&@½ÍÀ¥­ SøæCÍ!¹1×”–ePHfG‡~1C¼–…ôfj!Ûåéò²«™MLå‡<¯ +'…SèCF]gáEÎK¼ËB½Î^ï&ç€wÐ|—eÈ4ä|?Fö…â—ðOØŸ¸>áN{ÿ,œÅNi5/6ïôïò¡3!Ö$à? +°ûÁi@%HŽü§ùî +äDV.B 3Ð Êf(°wBÑœ +œ è«J>0bãO좚-‘Çi¬99‘j̹’ +Jxӯú]`vÊy”FêE}h +£èRË=sû7étã=n XLÕ k^%¨Ò*IŨ‚ +ÇÈ·PÑhõƒÑèëï9Ý/«5`¢úÑÑ~…mNË![°U¸`†ì'!à9BxgÎÆáˆ%Çð|Ë„çåÐü‰ý|nÂðtã~´ýÉ©>“6š¾rÚ¼Gw¬˜[Á—þ¬úà=lØÕ)Ø6ù}­+}ì\Cj3*F}ÉQ u =&mxjœB¦%"o¦Y©/+Å~ÙMqŸãöP4*̈ø¢H£-5YÓμ«s¼ëº) +±à /SaI…U)).E¦°œqœ†‚^N0Boü‰ ƒ,Ê ?]W Œö˜&BFhÒ.€ð +Èa [Õd?(}ðU¬O#²s®Ù\Ý’ ‡Û̶²´E?sz!Ñti}Èíj°Ú÷óŸ7$£UMÖøe…Ùs¢žp8lçC¦N|ùÞi^9¸‡ÑÊñÓäè +J-ÅÕIW’˜Í)I›KÆ´9§µ[·$òO˜Ñ°š˜&Þ[ÙW™¯T+G° mAyCÿ†á•ð+â¯Cï†ßO~Dú(üIRk®Oö$¯.ۚ܅w‘]TÞ–wç=y])=°-ÑPjÊ«I¾|=Äy)»Õìµ—¸âžänõnÍC·CßkÍ },Ùšì¨\Vy}üúä톧Bû*?¦>òêâ\…½N¤—c‚Gpâz!5‚Ý’©Ôés½àñ¹ýnÌ»7qË']/Øå“A³9ÒkicTIþ J•—V Ĉ¥¬û.—S?«½Ü'šµäMð3Ío>ü5@F(«¤í3â^cŸqÈHø®’\Q·+åç0—ÜŽJ¤’Æ$z àO ûÛ&éß>:pVQÅc²Ò€ÒÍ•ƒ„Ç•Åé4œ '{˜§‹ Åɦ ‡Ba½Öª×kÁÕT\Înð3?; òˆyð^Šy%«` +o,îx“Šõ›^¬Šs^`KŸ±1Æ‹‹xâ&Ù%€¦Hêsìü¦s1º§ä¶_f“\{ð²‡Ú£}P?dry†¼»ƒ÷‡ö”éû%p¿"Þ]’¶Ë\|–Ñ ¯0Ã+̹¤`–ï9#p™1Gñzx^~Àɬ‡÷èáØ&eÿ÷¾¯ÿ°2ò‡M!ź€{nw8&u]ÈT)*Ùá G/öÑÉP rݥ͋ÿ²»ßxáÚ…ë6‡>ð>²¢iñòÂÊʺ¡ª½ÒÄ›uÔ¾Âkß^×ZV‹§f]þÝ­»}7žuç]órM— +Õæ÷?à0œ²ÞúÖøi¼½Œ´(!y‘¤ÒR’ZªÍª¥úì25Þ£Þ§&êÛtë¶È˜S¶Ñ2U¤ÅIݭè\š‘J͘ñ²rL•KòLi…fê· ñSÑlÔM>”n6Û;ï쮢P¿”l*Ý´€ RUJ5§@×Ww,ÝP}m¤oé.zs‹ãVç®ìàô[švµÝÞq¯ã^çîŽúsÈqÈùzæõ¶KO.=µôÌR[°UòYk•)ó$×ZUïAvª*ÐêA®†¯fÞ©-«šË‹Ø¬­ºz9•´à1í÷‰/Š”8‚‘ ] Úæ=}eI,^ª¤pe@¾Ä<ÔŠ[%¨m•Ý­ÖN+¶Ž`î—UíVB +’ÎÕª)wáNWÞE\/_"RSí¨NiT¬kž—LÛD¥ÁXúà˜CíTZròi¼!½+½'M¥³¹•_ˆŠþ–£œR‰ÃÙñ¾Ø‰ØÉ»VXš^*-Ý À,•¯°ku™¥†]÷5ãæ +ÁŽö>û[öä±%Ëîz\_‘¦:)ÒIaDñ¡ä/r•däôÜI­]²ô8¾ Šfÿg"ñEBcR†âGNó‰~p4`‚OŸGC*ènì#ëÕƒ‰áÏÂ7©©>$«2ÒÓ=ºBßCo‰ˆryrübbøB±I“ƒû[Ú×6…³Þ‡3qJEeE¦‚R͈tDRbid‘¸Ð‹½SA·´eÛ4× hSïEeí^4?±PÀÎf/¾$ºØ‹-.©õÀåž©hNE«€ÛZ³Ui€Ó§Óu^<·|ž-ˆÏP“£Á‹9Uæ|u¸ØOM$J5&ÏèQÆ‹x*iRr 3Ë›åIgö›'ÜÒÈ„´ÇÔÀmR…B‚­DCÊvÁ¡’ýaSîÂEE0áÂbÕÅ%(g.ùÙÞ[z_N(C×Õ¼òx㬤?ööý|ZφuŸ{é¶6­)Ë.Ë$rØÖº²1Ó9gESeáËòtíÊ=[™yðxnüÛÝw¼"1*µÃ­aT-}ù#ÖHÎjXšbÔú¾ùý—ß½xJ•Ó)ÎT_î¯ð‡.#Û7mydñÌ-{–Ì<Se—˜OßÖ’±Ûi »˜µÍÌdGô–´TëÑ–ÜÎßË¿Ã3›øMÖíü–ݶ×=¯—¼ÍsN“ÙZâ£XÞî¾ÃGbœÊïA ë÷è!GÀå zâŠÙíˆóÖu˜12ófÁœ6KfÆ<[Îîú¬ÂB÷…ö†N…¨PÀÐå‘àòË(OîšœÆPåÊ»)—›õº}F/Z#>£wvÛàPbò/‹kѤ|ÓMrôj §¿rbxkbº‘@›m<« +D*ÈÄ#YQW. +Û½ÑöJÃi<í¥ç^*\ûÛm‹>ÆS +??³ä±:p +µ~› ?úUáý½Â‹›±»pc‰¬{M©Ò #ãFÉ›aOvÿÕNå»±©[•NèñP78`ã9(X÷U@FÒçÄ}³Z$9B…q_z„Ò +͈ûš!#M]mŸ±ÐwI#¯n—rñ‡XqÖ¢Ål]’“:–UÑ ;«¹" +8³Ûápó¦p -à>À•DÁYÉXO%Â5éjÜW=\Mªå:{ûâá9süíí$ß>ÔNP;ßNÚeMbµgÚ{»ºGÈ’ƒr„{¯T ‰ ¨ô¬<`}º˜ÔMD»åøàTù¯]n™àD†²'gÃ:£^ EÂ:cÐ ^<ë`É€¡ƒ0)‘ÃÿfêÁ¨*sXÇ…Ù_U³ÍI¨*VNŽww®4—­©\t£mõ]m³ûv½¦jZ¡Î25àÐОè¢ì•s±Õ6*æä´L ÙQ•]Pæ’Ã맸լor4ü³•ÆHéÊe×·µ]R{caÓ"Áî‡ +RìKIÙm¢Ð¦Ì[‡Mó¡®B*IVlKªR{¦^‚/»?p)£ådüœgdîÉ £3Òf>‚SQfÿ짙ˆì] +‘k©MôíÔvú êYŽÅâZÎÕÏ°ø¬N‡Ñ;0ÐMX¨Öú*üÌCz™<³¡˜Ouv„œa›N}Ÿ~HOçá0¬§ž× ú4dOèOêY=Pÿh]Vß+¾<¸@òÉØÔ¨l0ÀQˆª3æ(-(Ÿ€Ý§¹œZ—ƒ’ŸØ¥õxQ‰Ê£Ä¥”¹Z„Fýò´,y»è¼°ÅÙP&&˜L“¸I&'žzÛƒßüåww>Ûùø"£àô–°¥¬òªÜÒï|ge6#_ûÛ/ÎÞ›¯­¥?¬Ì‹ýnJåk/¿à±ÊžcžeÖ n–nfÚœÃé–qJppÉ£Ïn³uìlöiV% Ké%ÜRÇç•ÜFÓFóÃÚïv›žÓ>gxyÝñšó}ÇûÎS¿è9l6\B»Íew9Jœ¬Ú¡ujK2®Y®Ž]ëtâp»t.•žrFåT ‰…Öà5’Z-ãÙS¡*%ϸw¹ð×>€Ç©JDáoÄDçÁß”ôHõŸ–e– +–mÚ2‚YÉ"ÁG¹‘ yêö‚¤»žÇÿ¬¦Ç’d]F6mdy‘¼E> %qùã»0.ºæ=í§ëFç‚vý¢§]™[ò; +(¡®~¬?qz´+fð†ºí<³õÃ+àlÊÑÄY±¢¦Y„ê¨ØPÕ$ +YÂä?õì²ó§ðr,ÝúÄ¿¦ãë7»1S8'â™ø§ozâÚþc?~{hõêï.œ©á+ÊÀÍyx +¨å@Q¬“*oˆ¾Ïü:ø~”^Cof¶r[Ô×é®×o¶\'ìän±hÔÜ®8™Ê1Qg êd(ŸH#–9Ž/GN,ŠÊ“Gpƒ¤.7ˆDt¨ê€ðÎCÒ;ãéÈG‹&Š2à+$3ŠKñ|œ’â½qyº.ÇDZÀÊxTÒ¼¨!Wì8öá'»sô´Ò™c§‹vjÔœ+ïQà”©8„/L~,õ„9“.‹ÞH(â×V £{s´¾Øc‚CP-®@“³5&C¹Ð÷ŽlU•¹zrŽa1žK@r&fi\€ëo>õ‹øw¶ízsÕ +?~òº»ÿðãGD*Í37·wßÞ=cYê^‘\‹Ãû®øýÑ;Ÿ|öÜ6ß´Ž»yîò?^¿÷‘_]·( ìuuáYüz +¨°@Šv“nÇ+vJíèutQjŒXš6rftÄ,é´t­Ñæ·åm”m—JZ¿q™‘]·›èž±Åa5=Ô☦>e2È<9z)ë«W÷«YV+š­µmU3Wï*<› îê´èÕVumeEó5ËVƭãSGGxЙÇ,ç™® c“½¼x£dV»QDŠ)ÒÙ9¡#&¹Ú° m@ÛÐ.´1È%Ê„¼ E©hýjŒd‡ÂÁ0QLa¢bE¯§ÄãóP*KÄ(j#N—ÃETÚ´ùU@H«rvLR,598˜yÛ +äÒÀáÂÈI©²—–Þd)Ž9ì&eä,©æ‹þa•I‹J ¾õÎKz¾ñ¡;~µâå›®z¥)×_µÑ—J‡sñÚÆlK†<ò1î˜?cÏ«…}ŸŽÜûáKÿ,|¼ÿÞåÏáÜÇ]“L[Pxèyt  +zÌŽî—¬’³×¹×yÊI#§ä$›ÐíˆfXðZ<©ñ^ý#ç9È.Ä_"#^‹ìPƒðß%6‰š`FÍé…ŽãÂå³%³Á`”LÙ´q›qȸ×H]Žã$ŒOOtnL Jq”¢`.€yþ:0¸Ô>˜m˜íéä‚Õ>ƒ[–ºK ¤·Æ®aE·8“þÉ£ç¶ÔÈ“HIÅò»{JŸ_Fa­ãdŒÌ•À礙j_9.'åT¹ÿ>ãnß÷Œß315k9¶;ðVêÛõöoRƒöïP÷¹Ÿ£ž§Ô:Ê@“’ª›bÊ9@Q4‚™Ãăñq4Bµdb^ +›Ã<æG¨‡wé÷è‰~„*—âV5yaŒ§ðÏí3a¿©ÞDLn)‚#ê:Á‰N¿“8g‹+‹WFµÀl_ÈaÒ³ýÀpcýg{Î~T?úÙÙQ%2ÿ^ï±yT:øêˆ6bUuÒÙàÀ¹˜2¬qèËþm¼§ +x²£ò(íD(œ ²bã¡è_øýÓ?ztûo¶n}àÖŸnö¯*œy¾°ïØà\ÿ·w•š=V·–¹²PùÖ‘…·?)ü}¨ÿ)ëá§þëøù7ðÂç[ìOä°„‘좞ù­ä +ãÞp_x(¼7|&ÌáÎ0‘äCXöU§LÉ(iMm1-KÓ¨¤RÊåÎ8ã>KkP÷™[C¨k†à 4ê\:Ë +«ru¬Å¬’㫲Û{ !K)áú,u¥N§wéÃN)‘s*FUmfȉ;¸×Ùçv?ãdœB¾71æ–H(ѳ³£¬ò¨›9wQtµáéé—aÊEQË.q¼têÔÒÒº©ßpUÌ(44¤< +`Œ°•¹K>QWZ:µå¼á°»î¼üÞ¤à*FUZÉÐT+…î3=i"·ëv˜ˆæµ =€-!ú)C°º!o]x™ò £cuu²<)ºJž¬‹m 2H–GÕ6•L}‡ï¿bèa<å‹™p·n-lç¬ú|Wáñ«K?+Ü÷ê»ûŸ|Ú‚6,RÚ“Âqº”ka(x¹ aÆVk ÅP?¥ÊÛºûÿ6÷X²€ÖÁ»B¬l«@çHê+v=\xëŸ7ìi¸ÚndV–¶­º»pÝ;…ŸðÕbÓ§øÊWß|âA@/7‚VåBT‰·HǻᵕþÊÒè†Ê-Á¼6¯“ãÂ7‹ùÈ`åÓÎÇÝOŠu‡ÜG#ÏG_Õ¼ªýµÞÎ" +Vé‰[µënQ/Úðøým†§‘a*ªÅm¨ +ÏŽ-ÃK£—V®CëðZ²:².º¦ò|ctSòÆJ9j•góÜͦ›Í»¬»ìÐ÷q÷˜î3?d"òýè÷+Gè#Ü'Ú?ë>1|ýdJœÕ«£µ(‡k¦0Ò¹£´ràŠ=R1erbÑ—ÌPc#hVIÙÓçñ*‰GY)KäIÊ{³§²t6ôC8A)3¥I;$ǃr¸2Çñ_ð'L¨°Q£§Ï­”‚/Et1%Qî šì4gLL[²'­¥+PÊœXAƒ5òÉ&)a/[ÊMeE”1¡@n*Nû@²™ ÈLÏÚ/D4¡N¬*‚r%b™œ¢:v<ÚóæÓ½¶þÙáÜœßìiý¢Í¸âziÓªUùlEÕ‚Îo^µþæÈ,òì­{Ýúâ9\yÇÜUý»Þؼüš%ûß]¿µcíu›:2kÊ j~¼÷¦‡¶,nÉ­®\€ó¤‹8€;ê%0ù’•UÛ0Ù +S"<îĽxïÅ'± +`]æ0ÊÓ —ȼ9Ö#sf¹,å2kÊS¨ 3vŽ8î—1D!:!ÿ”Äs¡(o×fËS×:7z6zoŒõ¥îõ²›GÃÇc¿õüÖû›°ÊåS±HNÌE§ÆÒ©%ѵѾT>¥ý1ÂnoÜÛæýµë·æ©þiø}ÇoÂïGß‹}Vy¥PIŒ3ø=\ ˆý62ú=¶@•ÉÒ’X}¨#DB!ÖV³Ûm„cV¹ywÚ-¹ûÜŒ{vj"\‚RXJ +§ÈžÔ‰ÔÉ•Jâ ÑðHYj_w0 ‡MÀI¿8lÒÞÐu E¨²O¹7wxb,wD*qØ ‡¨«´‹žPåE±”Ù 7K¼/ð‡¦ÒAŸ0?ŠK‡EÖÀʪĿÏ+ž¼L±OhÑè¤w'«Nü˜7Òž{¾r‘hõDÛ+ñߎürè·¯U ÌÈÎ/YsË­ +;É +…kóþ¤(Öø7Rëå\Û-Oœ4ÌÒhÍwÝßfz6ŽŸ¦Ð_~T†SÇP9˜–Y³2årÿÍL¤2½å7Ò72ƒt¾|_ù‰rV*Ï—Tn/µ%.a.á&îcÙ åÕšYšEšè'K÷–³'ÊÏ$ˆ ! OÐŽŸ’šê„á2a•f½°E؃öÏ°ÇØ—j#œ%ª›aöYm%Qû ¯¯¤Ñ·ié¤ +‰¢šõ'q2駴~¤ +èyZˆÙÖkÏÛ÷Ù)¿}ÈNìŸÆ;Uʬ†TFNÎʪR +ÛŠ®x¢}tl §nL ´ÈþÚÿ…9"C‚ +1Ý‘ÍEÅP‚†CŒ\Ê$/Ì +‘Ãb5òð«L1 €!‘'çk>È~å„×*9˜PÖ”"ÆWÉOò­÷úò?6w€3îN豩Ì°{Ê´…3)UÝåå]MK‡×/]Ý<íÜ«¯âYíOWmœûý£³¼¦Pÿëø½Æ¾\Çš×~úk³ðöƨ{ˆ~'eqTŽ— Qytl8Jg´ÕþZ¡Åß"0nÎÒ!ÏÀ tøÄhˆ‹â¬k´b 7‚›$‹:ÙårªJ’ƒF«ÑjJÐ0ÆF܇÷à·0•µ4f—;l6wZ†,$‡a %¯A&V!©,½‘—·}} VvŽ'ì\1©Ì"–½º `zž÷x&¯ÑíE¼É×x‘Ö’{»(:srYt4› +L,V2ɳx©Ë¡#ýQCá/e›nljïOz«[ðŒîúÄUm¹%Ô=cïìQºðåüÌî;óx÷Œ),Ž=”﬚CعÕD„þ¤ÆO“é š/©ó†uï**é e%”&"X àÖ/Y*MõR}Ô^ꥢžÇß'oÐ#xÃþdý9z¶G™T'O‘ÞÊ¿R‘N`ÂdzÁÖ‰?eîú¯EÌ32;À³ØÂÜ Ÿ["Mß)ì¶íŽPT£®Åuu›ŽyÆåeÛCª!v·Gýÿˆi¸LÍ«x–,+]– ^ÎpÈÇÝć|ìÅIþoïEñ™Â¢':i§Kãf“Šc5¼{Fðüƒ»ÊpÙùâ.MŒ`^ÒÇâØl4ñw8,On9ØÛ›QÒÚÚbZ__LÃJ*Ù½ÌËSb–ú ' ' +*ƒ+yz0µÅY,í`>Î*¯ƒä£žÓE¬XW76PW?fÊõ”O®Ò£V{D´ED{Ì‹¢Ö°ÖœjNàò‹”¢ŒCÙJyÆ[ÑWXB‰iªl¶J~Â+N_0öûxl¦ëÀ®Ãýk»j3>Ge«ßIIÞϨ9cOäƒÉp8Ö¸‚,i©Ûñ£kËj|ÙÀUKÅêwg¶]ZÀz¼¡ ¥…º9E\QwŒðNÞE„*©ª·êz®ÏÙ纾tÈ9äv»´eå›´Ûµ”³*åî¬ê«º“þ>}ªŠÖQ·kOTQ-œÏïqþ#hö{PFñ*þ>,Ð&%*L:œÎ *–¤ ± 'ü€GLæ!31š;ÌD²l3›i³y„|)ñšºÎ6Fü™]98é}Q>1'î´‚qÀbÕñ“ŽÑDwg„Ësb,–F)•.ÓT,øy›Ð”!}¼¨OU•a­h(C_›òZZô˜ +rÉ~P@ÕœyR&#_-O±&Gz”¨´| ý ¶…›TÛÞß?òmwÎðϘOô®¹%ÖkNí(\÷æîE«ÜûFëæ +5‹‡jáÞy×þìû}¹pâÞˆˆïXUˆD2âU…åÓkÏ¿ðσýÇÚÅθ +,/–í +³_YGå<†ÒÀ¾¥åy-ÕA!¬¤ÒB»7SÕªæ¨6i1$F§„¦D›BMÑÇ£l<š‹’ÎôFí +Æ£/F¿Œ¨ê œßCA¿ßã +KýY€¤Ëé$1¦W—ÆåõOfµš“t9NªÏ +\š#œ[yŸPŸåÓ¸/½7=œ>•¦Ó~!h6o³à +lq•ŸXÂÞ£hM9–8$‘PJ2!ë&'W¤ÛæmÞ_Í#˜Æ „De£bØ ÕL]H¦ ðbŠiE™rxbo¢TYö†dÛ%Óóy”I¤@@eÅÛWT³úH夣¢~OUv&lóFßüÃGi¡©½’´f†]%sv­¹í—íÞh;ÅÿØoÞüã£ÞÜý91o+ŠÙðÀØþŽ7Z7~ˆÛ„¤¬÷€åÿW†ÑþXùöIÕâÊ*5­Ö —S$Ž'~œxŸúUâúÍ9úœFÝÇô©¶±Û¸<“Wíbwq ÏÔ¥„ +èt#8"é9["KVP D®‰3ÀF{ r „ɘ†ÓÑ P*¤Óëe(A1^^DC~%‰Qðýì.šˆ=‡ä%4é¸$/CŒ©T~w°øE%zXÒ CÐWòHꢱ6ÅÔÉ^±ÃBý¥h&ËÝX]qñ¶Ô‰0úâÇ&ÓâÂ[ 36)ëmM!€ !YÍý;ú+â?‹|tèEG›ÿ©×ÉtÅØñôˆS¯ñgPÓ‡ÜMW¬cÈاm +ÙŽV±°huÀevŠb…°…Z_ÌÞ]Ö“©**èvÉÃc` +KÁÅd5¹Ž +»…§…c‚Gð]R¥aeÕ%äRQû=T h¯ö˜¦5òÂÀà”yoú“×ÄoˆPz¯'#äIkwÕjÍ#å=]½sVYb$sõéž\Kãèõo°×Q©&F°dV¤ï l<÷ ]›2à¸jýb×M¹åò‡¿±_džÄa#u¥<Ø(âRióùçømÖÔµð­fÐè?=ü}ɤ1ªüÄÌ°Ó架cy†ÃgV™è†EI“åJ*Ý/„2ÿ0ŸóŸ PÇǜϻ‡ÿb™§]ϹÈQcÁN<©zš}Æö¤yˆ2™´˜µ¶•ŽôfM>À,±/vt®P­e™¥l7·Ts™¡ÛÆHN´ZÌ,P1B C×ØšÑl#ªâlŒ‹Ùbv|„@:Ð+ÏwF ö £÷ +œÞcð;|ÿÈøvÉdgUDzA°‚à0*•¬€²v‡ ô"¬J}ÎJÛ%ÀÊgì´ýã´M²uÚ†mglŒ`ëµõÙò6Ú6B>="î È / ˆ\g{N÷ çä²Ë k½˜‰•–ÿï…]òxGÏW?e:+ 8eÊ€Zã4猒Y™²{„ÏqœEž¤úÞKN+ÎàÝo¼°vK^niSê„ä…9ŵZ_­®”s1?h³ñBT,ÐQÞ5{:)½¬&…»±T^ÛÄè˜9¢>PqŹoÐßZbõ‡ð&Rá)ëÎH™6–•dµXÁ}ÓÖ÷ÙÐCG‡'g”CA>Í9•jsS3Øq@¿²ªÓ%G§£×Ñçrì… Y]ÜǶqܧŠ†&m±* +Âa½nâ1ÅÿY‘šÒáNîÕõé†t{ugtŒî€ý¢°ZÝÄBׯi=¸_Cx=v6:»Á•™U¨¯O¹ +~§;fÂ&æ®s3Õ”(q2Jzh–²ì[goa¼ÔJjóM—s©‹r)ÿx$”Û·Ü–µº¬î:¨ ˜sØ)¸w­:§©5çœYW­»•›­nÔ49›\³Ýk¹‡¹Ýêï¸ôì >žâW×õ]÷Sžq‡ÕG4GœG]ÇÝÏ{Nßq~¡ùÂyÎ]¶GƒJ(³7£¤‰Šbê‹Sð7•4-¦¡P15™”T’\ÞŒ1x#?™ô17 +71·™vÕµ\F“qæo4n{ç]§ +fp"c +y ÏÇ Çì1¿i +uBé‚ŠèkJ j£Vi“¯ùü_(¦ªœWs2ŸæÇÿH3€½kÈbÉe¾7‰åY¬Z +éŠ3‰ÜAÔ¦ÚÜ,¬ª©rSz™s™k™{™GÅè*=QKoÔnÔo4l2öùúü}å}éÜíÚíúí†[ÛOÑOýßö¾40ŠãL´ª»ç¾zf$Í=ÓsI#æF!P 7Hq£À +HAHbFc›@;ÄŽÏH8ÉÆ{câØΓ·›ÄÉf×dC;’g}H¼¯ª{„ÀN6ûÞûñ~x¤ªúºîúꫪ¯®¯R¼Å2Ôj=)O§–lvÄ8Á+øÊËc©Ùx6ÓÄ%IoÒ—ôϪ™U»Ð°°¢]·Ú°†_]¾:êñaãJùj]uíövG»³£z}j}ÍúÚõuëfY®Üªs•uBÃÌòdCÎ’³îݯº?ñ@òÑÄ™È7+^Žži¸ØP´\]ïBŒë8Ì®¼Ë{%¢¡öÁ*·Ë3àsy½§=ĦÆñ`Qô +zc‘^oŒê+Œ\©†Ê ž@H©bƒ²‡‚E/àûJqé8Š|Âü¼™yÍŒóqókfÖ<Îì{ÆwÌåÉÞ9xðŽãçãˆ_Ž³qqA­>XâÉø™8ÏGi<Ûåy]gT:_K¶¼s¹t"*­¤6N;F[88+›½êÔìö±ٺPRe”ê*5)Tn" gVÐTIøÔÆô)¤ÓWFËøŠ6Ë+Â`èÕ eŠ¨½rD­°òŠa‚H×vé6¶ð]Q®³ƒH4‰Ò¶0äèuvSšKšÒ)PÒ 5ÊlÉgN½Lá<Ý7§(ÓKG—Péôs§ìaKç±õ=·Eg¿ù;–üá¹™5¾o9U8ì\ûtßîÏÍh(›üêÝKÏ=Ù·«ÞæôkaÂÝwäc{®›Z²{ó¶{®{ð5¢É›À?þüç6Þ²®zs¥÷[Cw¶þŸk¾YUýìäxœ=t(ˆºD—?üMó–º—M/½Áe-æ5ú“v½RDª¢qv¹èóŠv+š4>èVê\|ƒÉïóïõ³þï¸!rTjŒl ót-bª)A$¿Žb`=§íÌ°cW;ÉiVP»v{™=!Ò“®qñÝw?¸ÑŒQ +Št]#¾Iìô‹‘Z‡?cæQvŸËâ8è< +8J³?h1s®¶;šAõ^õ95{™ÜÒiSoT³ÔgÔg¡§ÍƒPÀs~6Ioj°äŠ“ù%”È‘¬9‘E'y•æJÑhøƒ¬tavCYm憉geº2™dZªV–:€³Ž&ÃWñÌ~ÿ +“>j6pÎ#´lßÖáuÌ:Ï:ïV¼•ÙêÙêU'üMþVÿýŠû\*q©ìñJ"4$Á*{ùˆ ÿ8sF´Â\‰6c“Åѵ¡ãˆCãLäµ&`+ñE½ôêqF^Þ»Á{ÄËyO3TÂÀT¶»“p—:ÉzµÆ]-ñ>ª3Õ•GÏódzBÚuµ  +ö¯SM4’YÉwÉv)½sOçð¥Ò$dÚ„` †•û²©TgõmiÞUÚš˜ø&dñð†HÍbU)¯X:ùB{¨aÆ{— +²+8½ÑÚ·Ï&Ør!Äþ8z6+^¶´hñÃãó¾Ò}5?ÕýÔö‹²_¤4¦x©6¬ ésÚaÝëÕ*wCÜ´®Ž‹7)šø&s}iS$]“lX¤kå[Íó½‹J—F–Ôˆ +««Ãm +ê=º=üóž’=¶/¨ó‡Í_³?[ê5*L¼Élªôñ>³¯²\[nK4hù†Ušuum +\©Ýî€YEYMM­V§×§ìZ nGiMmMª6l9P’Nª¦Š%zÏnG›{áàž <ÄAG8O§b*//KµAw×âZ…Bv¨T¡ÚpQmmX_RV–Lé‹R)=t%vÞ–* ;tõ ±¢Ô®eõ5ªZ“»}¾ÊD"nå™z`RÌfÂyĹŽÅ¼^æ¶-O”à’xxÇvbÐóµ¢cÄqÎqÑÁ Âq8žeê Á©ð–ÑÚxÙ8V¡N=Ë|¥Q³lÌÿCz¬¹“lMD¡—(‰Œ¨GAÈyºTÛIz *"JîÏ÷wKwï €ƒß°ÿændCä<Ñ@u&:Á†§ŸüÍ¿H¥æûŒ|ãî_$Æ‹êU`¨ÉÅnœë¤ HÛ‘$IOwùâ¨6­¿ü_ÏhÒ6rYà7ˆp½b0EÛÜd€Y*•Ï2Ä­Ð0ä ºÊZ·fyÄDb»xÒ” &ÂÓ¼:j"ss`T!fp0PrÉ¡T Ê vfŽˆã#|ШE2ÌWä2¤y(¿” +f1ÐÓÓå,ö„ì=ûÚäø®*6*2Úl/¾x½Ù^Æ„BŠ"ÏÎËï÷Í w"ÈÞáëÐwzQx¼1¹­óîG·y÷§p~©ì˜óXÙ›Îß•ý6¡¯G7–íJ=Xý@êhèñÔ«ÎWË^h¹†qæ·c¦-u¤¢ÇÜbŠ¿.¶Õ¤D%hoMµŒ€æòÔÌ Í ïwþÿ4ô‹ÔoÂ*.„Æjž-VºœEÞ’PI¤8¯n -®Yƒ×:֕ݢy}^ÚØ0Ø°·áHƒÚ™tV·!–W9CÞˆ#Á)Ökó¶¦n =úyJ%4ˆ +m +]L»Q±Q¹Qµ1¹C™wæ]ƒÞ¡P¾ìÆÈ-Êϸ>ã=ÚÛð½Ä/o…Þ +9:Ô&"3ÀÓªT±\%ªúBl ¼¾2ÅÆ‘ÚZMIyÄf+aâµZ£>HX: ¨†ZjÌ!ÆÞ±¦æò96w>5Å"°_ºÁµÞ¤›q¯â¢¾úÊ**B³¥Ö"rG8vŽcéez­Á\ƒ8,k´øÇ'+¼éPºá9ücäGÊóÑ}QÂìE;·“1¦JÚ­"{¢Qr³šÌJ.PÊË]9hÀz”ÄÊ Ï͉š`ÄîÅ*§Ëáb”ÊÒP˜ §J#v`þªªzKSl +®J±e®òN*â)öRÈ[ÍÖ¦ w¾¯q:½WH·«¶ã\Ž,COmÉ#2ž•È×ã¯ÝI¥w”aº*“5_ÙSUªØÑ»ægö¾ö›‰½©Ua›‡,4-þj×½‡nž¸)¼!ýù»—¿pº»mhûÓßXýÂÙk]ÌSÞ9ëoÍžZ® æؾOø+ÃöÐ3;7Ù¤R5}jÙÎGKÞp=|CëçÛ9…|ÞÓ+>‹f03Å˦´/ÍX”<†ÿ»5_ÐÔÔ?dzÐüåAßáô˜V›v¤ø +æ +¾>~À<à{ˆÑ¼å½àcöj>i|™}Ùô&ó¦é‚ùut‰M¾z¡)=߃¨I`*x!,”&Òõ¸žWó«ð +¾]à‚ü¼Æô:ÿ^±È¼Ð÷‚æí¯µ +›¦„÷y|¾fŽI©3›¬§Þcò}Ê•ì*n¥¢ƒo7·[•“Çãõ­d8Þ„³Åjå>§×/÷–•´ŒÆ«%¢úÊ‚ue‰æZoÝ<”@:+χ_‘€Ágâù$fŠ0Ly$øD“seŒIËóv-ô6"ðp©]ÿN«„Éá°kuIý^=sQÏêÏé™AýrÓÖf;lÇv§/ÓþP… çã#tƒ_ÑÇ{ããL|c}zß0æ'·C–·çÈòúþÂr>GåÃ^"3ã)r’¸#!`Â%ÄhœŽ{t–­–D¤ÏÈg¦‰ÛGÜ^T©ÈЖÛNæ°´† +cCVŒM¾ˆ%AyD¨§ʵ‘aç 4&ÉÐH†~ÚH€äÞž¬‹™gHÒ@¤51Ò·S~–tç¤wÇ…ó€×Þdm}s±^í/ÅŸ]±­ù­·6’!Çìɹ¥®Èäoñe“ñùÁbÉ(8‹+̘W|öýÁŸÌ³èõEF˜øÌŸOþì&¨ +…p±Õ–Â[&ÏvÔÛq(dÖÙü×±s/p™ƒƒ0—áRŒÀ,Þ|ø˜èRM&¯õj|m~e±ÉÊ;ÍN—Ëm÷(éÚkXZ{M®•Ö^£qjŽ–KÖB©díôJÖ6j=Z\+-ÐòÖƒI‘§M‹MóùEÞV‡i +¿ªh­÷ã¦-|w¿—Ûg¼Ý´ßgÙï½Í÷é!þóCÞS¦Sü?9Oy¿oúÿÏ÷¼ÿjz•Ëôÿ†÷ÓñïxÞñVjLK\ŒÏ sj/ƒ<^¯[cÔº4%n›«Dͨ\j˜F¸ŠoðšxríÓ0óEæAày“ÑH–bÍŒ·ˆa¼>ÏQ„ñ^zƒöiQ¯æMlqI éØÝãø]Qc‚0ÌQ£3ôäX+p›ãÌïE£@d\4²Æ¯ dU–»Óá„ Èå*°o„l/uÆ0jD¾ñ¾NÊ©)vÿ%Ú}üîUðOk¯0¹Nì¿Š/À),Ñ¥*Ã>6ñçõ™›&W­r¤fã âWÓ+'Þ¼.éý÷ø埶–ù0%6Ù“wsëß»ÿ¶ëá0÷WnÀ&4ñKÒnºüKîKù±RœûU[:¼½Þ=Š=Ê=ž;¹»<ªZ¦Ö¿Š]%¬ñouïPìrïcnwÞî~˜}TC.<™PÓ—“ŠKlê"òãØ-š‘Àr‚ßér³*;§ÛÃc‚à·žÆï ;k™Çÿ˜ÿðûa†Eή»ð‚§÷ªŽ¨Õ8þ‹¨ƒX n¿d¿s’gŽø±ŸD"j‘?Â3¼#pA>Nv¾“t$¤Ë ç×/Hç×É v²åz›Ó¹U +©Ç §··Ëâ\t[¹K·wP1èQ)»XåWqÒh5mö-ß|#«j˜Ýµ|²§kºuÍ-×åwÝ8:ËK– +Ÿ8tǶç0§XúøɲC·o=¹·lÆÊjw”÷לØsÓOb*ÆDÖÈŽö +Ðõ0;!VÝgyTõ˜ö1žÛ‰w©öáÛTÜ\µ!‚ØâˆRcoô± –!7%É!‘U°‹<òQ*Á#z¹‘×FZzXäžv0w¿½pï¬p¼»Èyog©µÔ¨7Çíö.RT¢ˆ×bØÁ€fQÇ+Ž]-'Æ÷N,€1ó}F¹îf¦‡½-f¾¬”¹€ÕøÓ“7N¾5ùÆä§ùü_Oöïÿ춱çßÙ߯Ø:90ù/“ߟìÁŸÅxîN,Ú÷èäs“O݆+p3^ÿÄm7kO(zEбbX³C»Óø)ÍÏÃo†•Jïfoän,¹ÕÆ5ª#JtDJVØ Æêq<÷¤œY© Úõ]cv¤ ‡ÇLŒÈ­‡ 9J¯s¢ +±‚+6V©8WÁU8$Ú'éìLÒ*ZZXUVGù•#õïw.›8/Ÿ©¿$mË—# + m¹•î°Æâq{ÝŒÒ6”†5ÁMØÇ»6!¿ ¶tv[„M( ¦ß‹¨ Gk¶wâb#«ºr¨¬Ô\c Õ¥°tM³p‹HÉÞ{Ë×Þ:ø¹;~°åæÜ‘ùÆç±é¿¶NüÀ²`~jÑšý·í.]£è Z¿òíý]çF¿óñõcØs/œ\;1oßÊ¿š“øêýO¼+¶_qùW¬Ú~Š3[,xƒuCÓm´ÝªÂt&¬°Øq2,†§ZZ(òÐ%¢»›/q0˜I‰E ½tÌjÅ°#bÐxÜ&©ÕÔ‡ÕÇÕŠçÕ¯©/«Yµ3üùs¡ð8S5æ?÷ÂÀüômYJ<`”ÜÝm4KWL +çœ.­Þ©wÏÄ:­Kç˜Y8‡$]àÙn½fÇ\ºK"cJ^`ú]C²ÏýêÐÇúþJ!Uf ¹tI‰lW 7Nô>ð»:«¾Šëëæ´³‡¤e%ŒV®:¬ÆKO!-L:õ” õéfM‹v¾nI€{EƒËËëËÅš5¯Ôœ«ù«V…jp³fOðÆøã¡S¡ÓñïÆ_ ¾þ×øïo†õ‹ÔåãøαH„GãÌù±³Iœgkžf| †nîðÓ1š¨ññ†òȳ¸! +ókQ×&옃ô~Ô8›Ñcý8>öDrúÁØ‘û§7¨öþ“ù +ôŸ5øHÍ™¦ãÙψÖ筌Ցºê¶tÙð~‰hçyJØQr ¯“v›Òâp<á-Õš8%9Úò‡ýœR6––j…M8ÁÅ6a¯ ¿®lÖjâÊ$¼Á³‰® +_¡n™¾sh{4jà$]:öO‰ü+™v¹˜Ì +f3Òt §áÄ-¯™sz÷ÞÁÏO¾µ¿+áw8Í7Ø›ï :}Ñ{— ­‡~rãC=Üâý_øxëº{U¼iä“Î+óTªMJÝ¡¾Ö%õžH³Wû±[Z·ìy„P>tÊã@ùMÌWD~—šÒ|ÚéWX|d9ÀhJ'ø¢4ß,FÅf¶™Ôü/|ÁšèóÁè±Áðù <|$öXâÙà³ágKOןlúÿ’ë%á;é3Í?±üDxGw±ÙmIð‚% „¢‘x"1‹OZ’ÂL]Y2º,¨YhN6Ÿmæ^Žá¡Ø͉[£ûÜÜh‡¾ÃÏj‚Ž`Éì¦æ%ιeJKQ‡âYÿQÿÑ88æf?–|6y®V½Ú1¨TíQïÑìUîUPÐhB>—Çû\QPí7}—ZågŸÒ¥ró.aÚêI¡£Ñ8y/†<æŸÅ…••Q¦¸è¨Çõ†ÛíQkŽ©ÕÊcMdD*^ÕªbU;âÇ*£¾Xô9 .Ñõš‹u­l«¬=RËÖ">ª9w +ï+<ÊÃw’µùÎóowv’ÝTÒ_ý°Æ$ÜIçÉzèñ±¿H§È +;±ÙOæù€%:’ùéQzrFJ>RueŒÜqÃCe5ÊpØh´¬X5ùS>Rÿz¾'9»92üÞ[ÉdT°9CíI®ØTVœªŽdÌÄÁøÐd¤ËŒL6¯+³ ‰Ù»'…m¼ØÅnÿ¤7žüÙÖ¶b“,£j"ÌÉóâø¾¶ÜZúRð¥»(ôµc÷Ùâ›C¬kÂ¥áh-`B7ᛘ¼//ìܾïî=Ÿ?Sú\ìr¨X)Ü‚ï ÝRö`è(þ*óHèxìùØ«É?Ä.Ç`(+ÁNÆq&U +ñ†äæPoB[¡fÜn\LöÛ(q!à&ÀGú\nPd*áP€Á07Ç¡cŒÀ¨*ÊB嵩6ªØƒtJˆ\ÇÜ5ãøs¢©:âñ¸˜ÐQ«-tåa­´òào­Eþã~¦ÕÄÏøŸæë°X7Xw¶Ž­«QJŠÕfNaš:)Èwæ.‘ƒd%5!­¤&äÛ%…õ'˜AZÒ¹à€iþ”ÀcKÚ ã™´ÚD¯•W%íäúI¬Êô…cÁD +WyA‹*S(J +Õd»\戮œ£¦«PaÊYb²OQ”Ž±¤ˆ>Bàŧùt’'Ûäòz ~˜¦S ç^ŠŠ ¸úŠÜEÏ体µ)ÁàåÝ¥Kké +zfÿç«?<ððؾñö÷gYÝš^:üé†.æFãÉWßSizlx÷xéäMŸY«gîÁ~jÏa+´rB[_ÚjAß·.8²àì‚s 8ë‚Cn±® +@Æâséü©ê@Ï÷Z|®ÙþC¦"§v]þ ´ù˜?XësÍò!Ê`(äš=k–N§eⱘÛíR[¬F àט7Þâlà\@ ü… :ùœYÀ + ð‚–p ¶ +˜q¦æÐ|²½Œ¿D7¡yrŠçª÷)$‰Ö´†\z·Š<)pÍæôÔîôtûÿöÑP9>Êì ÓŒ$3¶^iK{â¹äÊRÇÄíÔ©êšÍîdÔgg~†oé‘6¹m|s÷û_¸²ã¿4Ù5íüèÖiÞè¾îå_©vCM¤™GE‡FiPéÕZJ«M*Ó*‹ÑnMëeYbcjM‹lX€éS¼ @¦6±XÓÁ­Õ|M£,UFÕ•ºˆ>b8Ë]‘²ª:eÚY“\ œ§Z¢[èjW®U­Uwh×ê×:×&Û«z•Ýª>]³Çµ5µƒÛ¡Ü¡Ú¡½Aw“þ&ç +®Ýî„áÄ­ÜêÛÝ·%nKî¯ú¼êÝÝÖ»í8ïwÝùBâžä£êÇ5ëw>êzÌý¸çk‰1Õ˜úí¸ó©ä·“ï¨ßѽïyGXÜ“È&{ªök¸zWŸwÀ×㲪¬ºGÃ.Ñ,õ-Œ,Ip®5‰ë’l›ªM½N£)Ò²:»$Qá.÷U©Ò0dºÝjF åñzÕH‰]Èê,r‰ÅÖH¢Ü±èÍ.K™·ØæªzWzüòà˜K§~m@,JªU‚^§ ¸À¿Ëév{5Z-aš‹]n°p'­&)öb‡µ¬L’þþg<ˆjwíoQtò3‘ÉïOþ04¹-¦/j™‰ß¶×ÖWbݯ"B±Ó`u8¬å ª¯‰a3•ž’ÒYŠ¥áÒšà-ï=Ëv½ÿ%nó'l¥áp8~bBÅìË]_]j5XÔ0'ËS{&|Ì[7'mµ1L8¼‘ËçñAvxXšs‚uŒã°è1l©;è8â`È9 "òÚ$³¢¦æ`ñ‘b¦ø9Fvô¿0’8ÎK’¤2é~ñUÇ}¬ÓE×ùå#>•‰æ9ÄdG$vñæ ë šíýò&çs–IrÛX8…r- +™XT§`ðnÁBHñ/Ò”’ó×ú9Ë{ÿÆ'ç·I=]“óñÅ(K9zãäXéÀQB…鵆訡³NŒ¶EF5>ê9U +ð±7Êò`s6Ê:ÉCÍeÞÈ<‡Õ©©p¸„r½ª„¼1`áåëíz•ëG¼é°S±Ñ•ÒEw`ÕÙxÔfsêõ†ÏwkñŒ¹}·2×gEN¯«,)Ÿµ¬~ÎÇ?£ØZïž4M³*“-C«ºŸ,-mX?Ûm4ò3£U s«zŸD—/°€Y4f#(3éÚ„™ +¶*©“´®¹“/²+©”–ºCœõE×ã%ÆßI¼™PÞh¶Ýn¼ÕÆÙî2„9“_]¡·Ÿ¬C:IpKU“»¡-†M1_loŒQ)ÃeߺJ¢Ë˜É‘¬šŽ:rïíN"Š\Ï:ÿQÓ1¶½óoÉwQü +û|¶I«3hKJJ*—͘³uîZ³L«ÕJlf@dݼ¾['_¬HwÎ4©ÕÑäÂÜšÞ¯‡*bÙ™A£A­žMÎT’=€òO0¢'ñ7Å7LvlDj›Ñaˆ˜ÊM\Re™…g%:ì¸Ç¾-±Ë~~0ñ}û/ìoà·ìƒkmÊäü$[g¯K.°³%É2{i’UÚI›¢røš‰lä,ym²©ºµº݈vØw9†’·£ýö[“ û’¡G’GªGª`û®ýLõ/m?·Ÿ­¾`ûýwŽsÕo£wmM†âE¶ù‰u¸Ã¶:ñqÛ +Ž—í/%jÿiò7öß$ÒÉ +¼8ˆû\Êö©ýA鬅ßç*óÉE;„‹Ý°Ãn§+Qd$µÛ’ {' ï6§Ãac4j5BÉdYD¼HÆ‘ˆašth¥ÿX«1y¹ô$o:TE#NÉà#߉F˜ã&&ÑÔh( +Žd +j{ˆî,À~…-ìܾm·›éÚRÛÉc7gŸ¶¥mÉ¢4–×pèP§ÿCn’“‘ +ãi' §?`ÅΟ¸ä +·%'#äh_‘qÉJ¼ÿŸÇ{É{¡äщ3É5Á’‰¿pÃïï˜z&tǺˆ§,üÞ¿rôóýÛ§nïÒΗϳÿ +}’ ùðÇÄõj…ÊbWØ,œÅhSšM0¤Û¼»Ò¬WñvƒOëRšu*Þ¥UhÒ¬ÖÀ”Úa°3ÅV¶Èf,±™b[d78™b—ÖíÒ²Ei˜bŽ-B­ËE®êj¦!Ñf#_g‘Ýn(.)q8œN 5–6¶Èj…I›ãØgTf‹Åëõù +%q‹©x“I|0NJ£Á ÕjЋ˅´¼Ù\TTÜdÜg{Ò°HFa€t ¢M»Ï¥Ùçz51À†³&3ëIÄÇvZé—.œçÏ¿ +“ûKÒmØ«&M…—•ù‰+ॳ•ï„¦k~„hlÖ`mÊ +C¯fý RÅAP~6hõ³V¿ÕŸï|âÙ–Ë[¯_y=¾.³rÃã§æ_ž¼ØyÝõ“OnèÇ+N>áÆß^×´áoO¦‰j›|l…1¼x€ÿÄ/qfÆ<€Gâ´9à7Ëù·QbY0¿´ˆH˜\Ì!ö8ò1RüºÓäô®æY£B{Y[Œ¡+ýjäHŒK:“þ¦Šúh+/:a’]±0ºÖÔæìð¶ù×Ulˆ𛜛ü7óÛ{¼Ûý{¢·:ïŠ~Ñt¯ó‹Þ{ý÷WŠ>Zòˆó ÷“ÑS%߈þ0ú‹èï£ïE+„X>œ°Þg½¯èLLµÒŠjc¹WU&_ÞqÙM^t–ãò‹.öØU@Pï>Ÿ‘°A ߃˜Ùmâ8fñ[¥U|q[1ó|ñ+ô½Î¹•²¼rB:xéö_‚´½Ð4‘£¯mÊ»LöPÄj ÙJ±‚. +¸¬ˆ(ðdv{®>Š®Üú‘×pä}'D%<Î`Íéed0e·ÚS‹'«­õž"ûõ·-ºõǸè[é¥ +µŸ.ën<òp~æzöø{›×V»Ãa^—^oïkýÓ÷ßÄaAp‡&øëKV7~㛧Îû³×±Aì¤ûÅ׉.­q¯wKÎ^Q[£¯m\÷Ý«º7tœãög”,´6§³µ¢V¯×lc÷Úi¸N\X*ò¬=õ =”•½Tì¡:[M,6ÓY FnŠŠ +3“áÏMþ\¾ŸÈö±÷ b¼A¬·¨9;w˜;l8l|ŒçT‡mØ`6TÕµ! ŽbÖÅÙŒVÓǸ¦×¸³&z›ç›‹½ä ÕX­P<¥õê8£Éb¹"–åXÙ°Þh3@ƒ5rm +¬HôJ~ƒ ›’˜Ñšžef##â˜Ùb%‹ã‡‰ŒŸ6NDà58¶&[«µéãºZ-ÞQbû²tÈvù¥íË.‘[² +~©š>O;ïD+pHò¿¦F»_´ã«VõšP.Ú‰¥õãå³¢Ækib“ Ñ“{L"ù +•ãB¿büqµZ‡ˆ…Þ§ñ*P'4äѱ;ÑË5?Gª1it]×2)qŽØÖò~˜9*ždNjGæüýÅÿÂü”} ½…/â¿h/êÿd°—¤Jjjª“5íøtáÞê/Ô… —’Ü×÷”ƒhlžåjTpœKa¢÷÷}”‹˜YÓàš 3­€ÑPd4š"ŒD{²æà5jš-IÔ\Ã50C„p«TÆAãóFÆXªâT*‘ŽÙgÎŒDÊf54”——+³ÛlJ¥¢ŒQ¨ïæŒ0±çö*ð æ8S/êEC›ÙkÀ#lgÞy&a +ø¼‡æµ<‡éMšdC.ÁtÜêkúàSø '·-6zÚM>í=í¡µÂ[šW=¦9õšf®8òzº&‘Š5'æÄæÒ +.*ºŽlki…"é¨5Ÿy#Yr|cÔ˜FdËXx¢M{¢Bž¥SIJ…(é þo—¿Ìu3tÚ™Ø"R³_ºéëk&njHYk'+é +X|âÓVÀæÄ•>{Ñ0.Ÿíª¨öá?U.ìYZò4sqÒtSLÊËìöÒüÊä’«nQìÒ*˜Ø=™±öaþúˆ×$õ4Í/:E‰ü,·†yfý¢GË*LN¶ØTΖ™ØZÓ«FÃsÅÖjŠã8ÉݬÁ¨FC˜î'ò˜˜$1LWx,ÀPÓ’t`‡þ~C‹}í¿ÓN•ô-PâÂ%Â]\j$wéF@J¾È?%[ÔVÂÁÀÀUĸ;³ñÿÛƒÍó7U*o[_ïÁ+[–lfþÔݾuâê̾FïçÈPhýåß°3¡ç 8zãiÚ”d²qVŸ¬­I$›’­É +É›5whŽê:viJÕzƒ‘åKX…ßÇa“ѪU*8–W1¬Ÿ-­ÜC'ä'ŸÖÎw°³+DWP,×á„J+U'^ó`“{ö•òÛJ^¯LŽãmÏ”ŠBe²’©|–1ÀÄ,‰gŒù¿¸Ž.4M¼N§™Û·KGŒQÓÄÛä6˧íT§qÚÜj½+¬³ded;ÖI[òhZ<}²N¸•JÕô©êË媪e¡}›Öt7Æý-/<ò£ÌÂæë?×\,¯¡`ñGïÞ¾köž{W$Ã}îPÕÊÅÛ¿~ÃÚ­‹ìùêþKÍ úF +‰ç?þýú÷^ztƒ©ñ/jÌ8à÷•_{^@ò¬¨v+¨¡þÉL•²­)øšr)üÚ”iìV|jó.´ˆI£"!(=ŽŠo#+(ú­úÊ€Ù¡Ëï€ß¥ æ3#ëAÝà÷sà6 ü•€`ðó|W‚ºÜúÁ¾]T¬F‹!F×*v7ƒ¹’Ë£Àó@1à΂]+ĵ”ÜüܯQ9Àp›~Ì`·àÏ‚¿¸Í;ÄMâ0ƒ?ÌM$<˜k!`®„o˜KA ¦üI~Uw!Ä5yþ“¾Üåš[P*3 nÿIò‡·ÇsÍK€kGE¯4Íij˜3ì.Äý™û3À¯Ô¿Ñ®ÖUë5†õÆÆ_ñ_çaù¡µ¯èöâ™%–’ŸS÷Oö„ý +ÇŽ9M.‡k¾;îÑxNx~ç=é»OØì/÷<BCá?–®-}¹¬³¼»â|åšX6î‹?™èJü1y®ú¾”:õ¹šÕµ·Ô-šñN}sý`¿~´¡zæúƹf͘µköŠ¦Ÿˆ5âïåZoCë€'2%ɹÛ²RüÐd;RÕ ØuˆÜ» ¿Iª³4œ—~˜AFì–aXÎ +æQ†ÈŽOË°ðÿ’az_’a5*e~ ÃôæO2¬U¬foaÊ©$Ãz´Y#Ê°Aù”æ6¢õüº)zÞß”aŒLæZfÊFa-)W…‰Â:R– +…õÔ^ʃ‘Â3(Ì“²TÌ¥0‘=g©¸ŽÂEÔO…‹i<.¡ö{(ì aï °‹ú‘òæ¡~£°ÂOS8Dý“Â~…Â1 +ÿÕRþߢ°”Ö_ ¬§öQ–´,QZF¡u¡v´ +¢,ÚŒ2¨ L=ªõPx@ý †d_š _9€‰žû^êC›>hµÏü_Æ”˜Ê™€V‚Kžò“»E`JéU¡4ü%QL†ª©m3„ès„Ùy¢¡V@|yP9´ônH£m£vZæNêgì2?ñ½Ò탯ÜJÐðß„® ߀VÓ”óS%%9­fÐ{/”'.yP›!•òÿ&þ¿Û•PR˜+!Ú“ËÀýïÇûuZk¤NºÁmÍûV°#¹ú?¯Ol 6z!Õ!šs‚¾‰Ÿ!9ÖUCòI ¨”¦· ôVH{3­W’C. ±æiÞ{äØâ’'‰† ]’§Að»ëoúÊRÚ%þvÒ\m™J·Wn1J‹C4}`³KÆCŽ–ŠÄZ 6«©ÿ!j/ ¥“ý´L„FS´–zh( /,gÐ&³0•»+í’ä#G±'в×Ì5x,Ä^ø.ÔÖô—êq)Ío·\Gý“yˆ3CãÍÑ’l–Ë°“æµ tïµÉиºiœ¤…õÓ|"m“øé‘ýä¡l¢uµ }w›à«‹Ò]–æ«_67O£ˆ4}7‰kmCr¬]3yøÛL[™0­N»(f2Óú )oŒHµ¶…â)CÃv_U÷yš¶DY­Ÿn + +S¬e)^þ>-”Éê¥qtMk›¨ï¿O'R ø`ýMÇ°„£~9§ýSv¤¦½ž ÷DYtmuý´¶vÐ8{åv(áH²¤a X•¨hí}wLµ ‚뜜vnª†¶NÑܵíKÂÃ?ÖƤÒÍ¡”#ÑõÀTþ%º”ðÐ/÷çWc\¢¹nZûuS K1 +Ó²Ki¶Ñ¸HŒC`Ÿ™Ö¯´ÑÞºŸâDjϽWQ³ÔGî¢9ë£!ò´¤}2ÕõÐzÌÈéæäþŽ”.Ok~øªöCrKZ\!„J•R}rwѾ®oª†ûä~t¨>š»]r‰‡i_+Å´“ºôÐØàOê3»äºÙa$\¯Ý4…]2Ž¦÷'›hØ­r^%  lu#õC(ez_Ah]†d—«úÐnJ_ÃWÕb!æ íÓ¦ÅÖMñ7Hëd×U>»)†r·…zÓq~ü7ÿ¿8í5¦Sd\îuÔÿ6ˆ=úí H¾ÈWm qK­NêsScd|*äÿÛwÒš(ô‰WRY­¤Zý|Ps·!p+Ø’Ö3ŸöľlV‚N¸Ÿ0¢·Àß2jÛŽ ô„­vÚ¸óÁ¦`ß3­/”±¼kªgþÇFÙ+uÕ+ײD[…Þo¥×Bš¤Ä;¦qÓ{ÙB~¤ö´mÚ–¡­A¢¬~9ö ÍE–Ž©…:ïS#­s‡Üÿo¢½w¯pz//µ¤Í2µ|¾ärŒe¯êI möƒéuË=IŽ¶üá©c“\3ÓÇÎï¯Æ”4–|*>˜r¯ÜFÀ\†òáW¸” '²´_úð´ öWÉc¤4¦ìú@]Hõt5O(õ„š£AŠÙ^¹ùGê\i±Ðo™–.é;º)¦¥ñXýsÓæ •S¾sÓèö +_ò÷1ÕG{Þkúô+ñÆË<¥¿+\A¡Ï»âsüJô0Å8‰¿gª®ô¦WÓÐß+ÑúXDËþÁš+Œ…g—ŸVi¤é¢µÚMä®Á÷•˜Iù(/×-%„ïf(…~à©ýB|R›ÌÊãéÕãb!¾Ö£„-©CòXþaí¸Pc™kp½ù”Û+Xþ` +]2ÿ¶Iþšž£¬<ÁØSˆÌŸš‘4S‰Àl°Í€y¤z|Å`–\ƒÈ‹¥dÕdZ"ûL‚k¸ÔÈð ˜CÌ ¡êP-Ì(ˆ"±ÿÏƺÿó‘±à–¸{Sãaû®ÁìæLWVxLhïÉ +Ëú†ÀJ˜;Èe†zú…Á¾®¸0/3”ùo<%HdÂʾab“õC¸ªt:­:.4÷õ +z·ô å…Ù|6·#ÛÝÞ»-›–gw ++¶eúWd· ÷er…®qd÷†ÕÙ\ž$Z¯¯"Ëz»rùÍCå×øŸî: uh[¹¬ý¿ +í¹Lwv[&·UØüwË)ä²[zóCÙ\¶[èí†À몕B[fH(Ú— ­›7Ç…L·íËgwö€·øTL€¡-¹Ì`Ï®éVYa^.³³· Û •Veúû²» ¹Þü@¥°º·kh ',Í亳ýC€ÖTu{OoòB²œÙÔ—† +u¹¹7—2ƒƒÙŒœG☤XRÁ¡ŒKú»¡DýÙùÁÌ`6W)l†vöôvõ½CÂÎL^èÎæ{·ôg»ã‚°hHè›üð¦|vû0ä¡o—°)Û5°-+ ôgI|;r}ÝyaÛd ?ÜÕ•Íç7÷Ѭ ]¹,Åab#¢méíÏô ÝRéóÂN@–° +ªAîïÎæ®ÅBd¨7—í¢±i×µ8 +˜*Ÿ”aÈQ?DÚO ÜÀð–¨!{ÃP¶?ß»# …Ì’Zh07@² +(Ú1зƒÔÄæá„Αm%˜+ÔäáCj ’›“É®Hü€KÈC?йœqÀ\·ÐèîOÃy²-›Ì +g(­´õeú‡z¡ž{%4Eîúº…üÐ.¨Ú®žL.a!¶¡Þ®¼°iXªŸLwfÄ84 l!åÈÞЕíë#îÝÔÛ×;´ ìO;{‡z„-@™—m» ×kz»³P‘Ãy‰N6 + lÍÓ mËlÉÜØÛŸÍKT‘ËB ‚‰B»º†¥"Ï™¾üõÖÝ›ìËì’,»wdsC½¤¬ñž¡¡Á†DbçÎñm2"ã@:‰ž¡m}‰mCý™mÙĶü†!Ru@9Ò"ãÄñ ¸3ÛG(‘YÞÚ¾hþ¢¹Íí‹Z— ­ó…¥‹æ¶,_Ù"4/XÑÒ²¬ey»AkÐÒ¶3Õ`ÜC©ª0Äü!M––ªŠ Ø"ä·k`˜„ìØA»‰dIÈž`ÿ‰}Ô)ö4{죕6V>ÚXùhc}´±òÑÆÊG+m¬|´±òÑÆÊG+m¬|´±òÑÆÊG+m¬ü¹±rÕêÇ8Cý˜Û¯® “½j]Dâ¼?<Î>JáÓ¾9/WÅ-áp³@O_•éƒÿV,Ëi›!}Tú<‚¿Ì"Ú.šÁWŽŽy$O;†‡§Î›£Ë~ˆþC~§.Ÿa5ÖÒR-ŽƒSs4R^MFîêbŃq¯–¸¨Ë¿Î™#uõ0V«~­YËþ;ú(†ýwö5 3j,¯¾Øl Ì~™0F>t„ý74ŠA"û‹±PiõáçÙ€û÷ØïBNI°ïŽÌÕá·ÙgùØ“ìÓ²ËÓcFs5jγw!ŒÎ€~Ô9PAqh€ýÚê¨ã 8dÝ*ª•Ø°O°O@>’£ì '@ +€:ŠCíìã`¿•èì£ìÇQÂÞI®?‚y{75¿ +¦̯€½Ì/Ã71ËßIÜ”í€ï0ï—ÍûÀÞæ½ðMÌ/Èß;ØanH6°ùQ¯oö‚»* Šè€îÔÝC*tÌ~ší£)³Ìm’ èÚ=êÒ:Ú=fsT”îÔïÌíÌíF8Ý\ðs³ä'ÆÞ ~n?7ƒŸ›+I6éåÉUÐyP(ðž¼çécöyðŸÿÄþЂ:B¾Ø€ÇrÈÕ~öã£Ù–±´XÝô,»P-²›ÇžêW¾4ZBˆ`eÓDüf©kvL£'¶Ù1§G2Á×Öf#Û…nÅ "ÐC j@Íű]£¡„ï4»mS#ÑèÛÃìa÷p{\r¶<ÏV£65’´°1ÔÊ}ñŒšAÍ^ +K,'5¢¦M£`÷°X–enb[Ù +¬‚ÜœS5¤ÈUÐʆÔAÝ݈îŒî¬N1¢<£<«<§¼¨TʤRT¶)7*•{••G”ò4³Q7¨Û«cy KêD]›NáSá#Í·²›ÈUÐyPƒ ‚âÇÀ^`?jÔÆ@ÅÇÀŽà‹uàs`*àËþLà϶&°5-¸´ÚjPvUN¹Âÿ‰ ¨2p5‚-¹Ã Ÿ¡Ù€aHÍ¡º—ê.¢ã?=ešgBšgñŸÐ<ˆ 6–ûÆD +|y´±ŒÉÑÆ`LŒ6ãÝÑÆ»}Ïáw0ÚðÛ£¡ó¾æb| /âÈ÷ŸeóxzÌ‹`nóÔˆÃ`~u´ñ“ÄÿÃþAøþ + +¨‰ÿ/£6î0^Dí¿$‡ûâhå&Hõ¡ÑÊ]ꃨ’¦zßhåy°½{´r?Ÿ­ìãÀh˜dð㣾f3Þ‚B ñÛ…Â ÉÉR9Å…s˜ ¤À-£•$Ô<’À8ž;¬£Œäò9Dm49ßhÒƒ‚4 +7 +ÒL»P˜šFl¢™7 5Õ£ÁOB,ʧÂç}m|–ý›Fù~ý”o5|þ^4ú„ïǧºF}¯TŽãðIß‚Ïú^ +ãÕ£¾3•ãjpx¾rœÁOûN’GÀ/ƒOúŽWnñ=¤®Gƒà +U}¸1æ{(¸Î÷@¾G}Ÿ¬|Ždmƒ¯çŽÊÙ¾¥Oøæ‡Ç18‹D¦—Ö×ÌùÒ`]?Ž=á« +“¬$!Ž'Nú* ÅÒ Íʪ§™Z¤ÂÃb¥jHµIµZuj¦*¥Š©•GåV©-j^mTëÕZµZ­TsjFÔETî-¹?W¤ä‰¡äˆÎQ˜gˆÎHW ¬f íŒXÙ%Ì’•sðˆe ZÒ>gdFtɸêòŠ‘úè’uÛõkO`üÙøanǨ}-(±ºÕ5b!Ò-1NÜz—‹˜7ßzWG^2r¦ -Ù$Œ¼½Ê¡½n݈"8ÇŽJv4Ù›,³Íéùó>DÛ(ëÓDدXl÷ŒÜ»dåÚ‘Ç=#Õ¸ìéX2²`¥°~í)f;3Ð2ï3HŒŽµ§ðÌö–Äß8¯cÊ +0ƒà +5ƒxCâ +ðõ¶”z2 +´Ì;Hž^À‹ˆ' Ÿ¨§-R\!Hâj#xc¼(Dã +1^â +èAŠÌ4=2=Â&™IhdnâéD8 ^*ÃÄˉaðp"<ƒ:?qÅ9–²ÓÂ40î é`|ÅODòT ûaÔàçZÑÏÿW¿ìœÿg<–ùewWK6ز1Ø’µqäŽ=ö‘½›áD÷/‰ƒ0–nÜÔÕCÌLvä—Á켑îà<áD¦ëCœ»ˆs&8ïêji_{¢KÌÎ͈™–`f^ÇØ#{æ.¹*­ýSiÍÝó!‘í!‘Í%i=²äCœ—çGHZKHZKHZˆÐ´–¬˜ƒ—´­=¡Fs:æ®—Ì1F§…ö°Ñåï˜SÂΦc¦ßþ ×iÁ°¥‹vŒèƒsF  ˆS¬9ÖLœ u'#X›d'û'fú]§ñ£²ÖæàEö–ÞySÿù|~ˆ¨áá(èCÃvj7Ö¿rÉÈüëÖ­iil7Îë 2@†åßܵ"ÿ|ã+Ì@ãžÆ‡7*†‡;ÀÚò|à•³!0Ø888P‡õkOŠ‡°Ã@Mx~-óhšÃ`Â?ùΓ‚ò ¤ä¢Ãѹk›¨ ¸^ z YAA¥@­¥@ßýŸAýÔŸAqèÓ ß +êaPcƱ±{ï<’b©kg«Ç’µÕõã`f6KæÊu’Ù²\2›«í`Ž6¥´Í&`À1: +ú÷@ýÔï@½ JÁV³Õ4òa‰j;ò(Å}"¥bˆhùè&’S0A÷P>EyIú† ïu_M÷燠* ðDmó$Ø01 ¿ÿ +ÿä«ñ +endstream +endobj + +90 0 obj +34479 +endobj + +91 0 obj +<> +endobj + +92 0 obj +<> +stream +xœ]ÔÍŽ¢@à=OÁ²gѺ·;1&¶¶‰‹ùÉØó¥MÒA\øöù§f&™…æp©*¾ºJeÛÃîеSöcìëc˜ÒsÛ5c¸õ÷±é)\Ú.q’6m=Å+û®¯ÕdóÜãã6…ë¡;÷«U’ýœïݦñ‘>mšþ¾$Ù÷± cÛ]Ò§_Ûã|}¼Ãg¸†nJód½N›pž×ùZ +ߪkÈlÖó¡™o·ÓãyžòoÀûc©Øµ#¥î›pª:ŒUw É*Ï×éj¿_'¡kþ»W.9åt®?ªqêæ¡yîßÖsË ‡¬–KìY_"Ì6~aYräÒrñ‚¼äÜù…Ùê>ËÆ¿r=ò–c¬¾c½@~cVä=ÇÈœ]ÎŒº£_àqÑç:ú=ü.úwÈÑoëЯ–éW8ý²E¦_asô+úãè÷f aséôÊÑ/V§_Qú¡¿Àúý0Kì?ú ô z%Ñ¿@¦ßc¿ûoãé÷6†~½ý…Õcÿ­ûouú ìKè×Wdú=ö¢ôp*ý%ö¥ô{ôSé_`®ÒïÑ7¥_áÔèǾ4öþ +rì?<ýö,ú{WúÕ<ô{[ŸþÂ<ѹ>ú1×Ó¯x–§¿€ÇG¿Õá—Ü¡W¾`Æoç£ß2ý§_rŒåøÿÇÞ=ýbÏ¥¿´õé÷蕧¿ÄÿÙÇþóEŽo,^iœ9ŽŠ´¾ã|LØÁdçN†¶ Ï®¡0Ë>¿J"M +endstream +endobj + +93 0 obj +<> +endobj + +94 0 obj +<> +stream +xœí{\TU¾ø9÷Ü{gæÎf€A‘‘D`1ÿ›(Š@€¦µ#3 Í "‘‹ÖS´l­ ,+u[³R3s{fÿ673uÿ©ûÖW½¶²õõ{æúzí¾Âå÷=çÞaE×þl»ï÷ù1Ì̹çžóýÿï|/ø½MndB«AŽªzgcÏ'¾@C‡W-÷ËS†×üÆ€·Rݸ´¾¹9Û…k´{i]Kõ¦S†¿¡Øc5n§Ë:5¡Ä…pB +L* +:¸~®GÖÔûWdG<ø\¿×{êÿÍhu?B·¤÷½îÆê üi¸~!¡æ0¼è †"½æ/ˆ:½A2šÌ–0«-<"Ò5lxôˆ˜Ø¸ø91)ydʨÔÑiסÿ7ðxÔ…ŽÂëM´ =ŽwÂU5Lß3Û¹ýh +j‚™·ðQ¼ž s;ÑtV¶££dð4f:-pèK\^“q$ž¬yÄó/òe|–?Ž&ò>þ8_Éûð8ò¤°@Ø ïÉä\8:‚PþùÐòGòy¼}HŽ“]èSÀúÑÔ +´DbjãZ¹2˜9,G[àåûÇñV|¨;€ïA§Ð#„çf£­øðuýÝC*¸6°Ëq\5Ð`‡ý[GÂ),!…s@=àZÂ>ãÈXá{]@m€¹í»ÄH]2`¡Û‰ßÂçÄMh;:A~Hî ïá5|2ÿ ?mT%@*ÑF€½…î«q ðN_­:×ÌWâ]è3¾R·`ÿ‚r8_äÊ€£jtÞÍ¢xšŠ×õ@)½‡Žëæð™° èV×yÈx´ F­h/ÚÆ’N´ 1~ʼnÂ_`çãüGÀóF|?÷tœä¡4TÍŸY£H„:zY' +<á0J—­û¸”B×>Ç åw%ŽM¿äR¶êä}¨tŸ¹Eîêï/]ÈÇ‹ö ±ûHŠ~Ÿ’üÑ•n~46}néBy__~ž5¿2æÊÂ^Á4Ìçç±{é>!~ +÷ÉU5ò½Ö{“§ÜkuO bCÕJ'_-ì€h¤C#&þ"/b½ÐÆñ(óÐÉs?@Ö“çNžËŠ°%ÚRm‰Õ<êõ‘˜ÞO•Nå«/¼bÂý=>N„9‹Èu ÕO¹ÃÐY-ŸÛ†MÖ±ÏEIûQ*ÈÁQ+ÅcM†t)ݘnšj˜*M5N5e$ã‘Ühi´ñºˆÌÈLûuQ£ãG'¤Éi‰#S×JkkMkÍá4Ôqœ(‰Fb"fb!aÄJ¢ÉCbù8CjfÚŒ´ÛÒÚÒV¥=¶=íBÚðÅhñØž©à#£p<¶GŠÉI£RÇǃ&Œ¿~T&ÎÀ㯟ê ÷?sóúõKžqè©ÿþýÍoÕU¿í¼{ƒ{·c÷#øeõ‹üŒ½£GWT8 +-×=ºþñ—’“_?~ÑsKSÂFvܽuO< +ĺ£ÿþfЗÅ¢IŽèÝÈÙ-è7Xºðf2ŒGzn–-ܘ–öI•wî ˜ŠõÐù¬—*ãWÅo'ÔZ@{ã-@6g³"  +GF©ä#äÉ®®)/Üu´õ½ë…¾ÃO?ôÐ3Ï<ôÐÓä%îÖÿ9÷ŒË‰ó°^yNÅ~ôìÙ£ðÖèj½Ñ0ð˜±;u›ºÂ7 7„‡ÝHÂíùÃEš"Ïg9’gD·¢V±Mצo3´ImÆVS›¹ÍÒÖfm³µ†o¾mJ™`UÚR³P›œD?9ßÃ{vwlÚ³gÓ®œ¿ðŸÊŸ°|xöÈ‘³ÿþÎáÏWÞQÎ)Ÿ+‡!ÊF@œD5Ki$gÆh4Ã6¸Ž·¬5¯“¨ +¡ 7£Ù‘ù#¬½g²”*_R“닱ƬŠy f{ XPç@ÚD;•$¥*´|¶ø‰ÒŸ½ýöÏJŸ(ž÷Ôâ>åwx,ç?Éß3fÌ'Ç2fÌ®‘#ñtlÁáxJ2Óé^ÝB +ÂíTGlÐû7Hø`d— |?ÒX Q ÀN…8YõÉ3Ùð¢Çþ†ŸµªÂÐï(¼—纺f¾Ðôæ;øWø·³Ï¹mÛk;¸Ö‹Û÷TW] ÏhñG4$¡›£ÄpÃð0$Æéì¦ö8™tÅŒ¶ê-L¯Kmú°ÒØáúÉ4õöö +“iDšvæËi‡Îe3ŠY#KG6Ž|`ävx½>òÑý# + 6—족*´ìjÐJËãîç_ëö6mÜÙím¾gw÷Œ}-wî&ëïZþçiûÉã4„q[Ÿ|ìõŸöµó•{—.¹+èmÀC$ŠAŽ‘ÈŽ +kõëû³Xè6áW†w‡w™6ÄÆØ9½]æráaù±Ì(1¨ºÏXÏÃëËó0‘åH›×·=î×qâ„hžÁͰψÒu™úL/äÁÎc÷Ä €I$2ŸgÖ #æWHÇÌDÇ·õî7yÙá%U¿¾]ùÌ2­÷c¬ëâžZ·¥ÛÂÝzók‡¯¿~ïuéx–À^g*ÚüâÞ­yÙÆ„ÁyáàÐyáÌ€QTÚE%ä+f'M M~!l¼e,‚>Œ<‹lø ¾]2B4‡8c +·P¼ÓÁo6ЙçTýO†œô¼š“hº‹ŒšŠí`ˆãÁ"ÇÙp3nUÖÌõ½úê©'ÛÛ…­ÊÏ7öm__¼eÛo¹Êx:+6)ÏdðlCYŽHÑ–g$í–.ÃA$BŠ-§¹ùèîä1ª¬K#¶EPnU¿ ²:ŒÌI(Lüéîî)ÖDdÄ’ÃmG_ëÛŒVW ³›`7; ¦Õ˜JºMa†îáö +a]1›£Qxø¬á& žÆÔlUÌjL}{PLU…ÌüÙ9˜GSh!ŸB}š¾û~<å…Öc¨¿ÿXë Sº»¹L-„re.§rPù +^®g€ KYÀï9ÐX?݈õ]– +øUr0âü,ñC(³ž9÷ƒJÛây¼8e@"YƒÈõt¨â&h}¦o¯(í +¡ ÿG à3¹µ‚ÜÆ}JA©Ñ Æa zv˜Øm±ÉkÄv'CXfBÃÈpj§ D™? +h=vȵ1£9tæËÞ/©(­çm“m“©ß5dÅeÅg%dÉY‰YI3RqŽxG‚Cv$:’JãJãKJåÒÄÒ¤ÒÔÆÔ5qíñí ír{⚤R·§^Hl +l +l¨Œ¯L¨”+ãåÆÄUñ«VÉ«‡/É27à‰ÀI“v¢šuã™)q¯}¸gµçÑî®®×í9ÚwsOo®|©ÂýÚÍÿuWݺÄwúÅ´¢¾Õ»ªo>ùêám÷edìJMí¥6½!q<_‰Lø?…Â|Q0H~¾d ó%£ÄÍÇœÑ(‰6^'ØxA¯×q6™`µ +Ž¡¹’À‘ ×z“Q2èÕbüÂl=IëϹûl·ÌÝN?"臱▅ݠ"ǤEP š`™N[Õi(QÆb6¨!PL Ÿë¬zí-¿Õá¢$ìè¸(.JH’ÆK…\¡P 9¤[¸[„ùR©ÔÀ5ÕR ×ƵmB;÷(÷ˆð°t;(ü’;L~%Ä œˆ¼QôF|™ì\4‰âG1úC¤ÑnJA)8™K%‰|Š$&éRô©†‘R¢1Ù4™Là'è'›²,ÜlRÀ;ø\Á!:t}ž!OÊ3:,Ë´/àJù…2±LWª/7THóUÈ…ÝÜ2âæ— ËÄeºƒÓ¸Ôä±4¡&Ü­$+ø•Âb›x§®M·Bßbh3´JË+MíÜ:a£e3ÚŒæ6‘ÇùÇ„GÄGtꙦm–p¦ÛÁí »ùݳ⳺Ýú¦ç-ÿ̽@^å_º ¯[qo‘cü»B ‡ãb0ýÅÉFœ¼ ëŸžþã§]Ê{§ÿó‹Ó|eo'YFß·“ÎÞe`#ÁZ<ée´™Ãðyðo²f«àJ…J¡Q¸ ˆjÅ·ù?ç¨}e‚C~Å΋±‚›ôÏŠ¸m¶ˆ%.B‡tAo3AÈfG–nˆv`s÷YؘÚ å‡Â™[žÉî…*-.²ðK{©}»,¦q\ŒÃê!¢9uî«}Uóp¦ò›î}ûö¾*F>ZZSµ±7“üfcñ+»®­ýáø-¤ E;Ld+ºG$<ŽFÃE`ìä1Xp´˜8ÎN’#.œØ±ºLÙ£¼éQ*ê‘pþ2áV𗪿ŒAýeÄ5ùËóCøË×6üýÈBÏ_ˆœ(pÄ:)\-Œ”di:7]¸^Ê’Š¸yB.xÃ"nw»°Tª”ZÁîOX%urBœ8=A¼(€D¬ã!‰é ÈÀK’ YF;o×G›¬™OdQÖÉúd°þ£l‘-Ó¸)dòî»Â©ž1a*À1¢tG¤¾ƒ{ŽG«%QGb…I +ÔÄ*PV L£›µ¿ÔŒ™g$Ò>÷oï¾Û—0ûç\=c¸Ã}“iîòõ"œ.°óJ2œW:ÂQ‡éAz^‰G¢íVz^é +žWp’VÒÁg*+ïÙ'I}_éÃäý÷1VúßÙ¬PÖ)oƒlÚq‹P¤t)Ÿ*Tºðl<ÇàÙ;”[”­Ê6å¼/×SL^û–4àÓ†Ž(=g3"¡Ã²Á€V‡ëc¥IÀiNxP|ÔS5 ãÛèé\4!b#@„ò>pPIÜtï[?ß{TùèøTùP8ÕÛtáĉ ä¾Þ*ïÃéä:<’ÊÃJ{Ÿ@þsGÔzˆxÎ&<¶IDB6"él/ÒIƒHzz#]&« +‚A¯Y—È HFëÉCª§9y.<èiB¨s©þ6àh²‰:ZnãÂtaú0´-Gh2è°ž‰ÂÑܼ+5-Å5Ü +¼œ»‹xùfßíx·Êô÷(éä‡áp"µZ’H’¹ƒÊy.Eiý”›üÛu}·­;%Xú¢ÉÞž1¸MY°Waðn@-Žx +s˜³‰:p-bˆ‚­Ž‹å'èÀâ$fjå1d²Æÿ9} FÊBÖn’n67KWËUëVq:D;!àBñ&¼PtãZ±E\ƒï;ðq›ÑJ=-‘Êá#ù¶r‡” }Ëw%ðõŒá?º˜€p?üY SvŒ&6¦Ì ô‹ÀY@OƒŸ>—-r:Þ!Ä"‡ÎÀºUì„ôñhˆ“(ÙÓ.’ÏeqYm +8çú¹…õnMœ5 + Ò(œF&âIÄ!È +Ò(m“ÌÀa‘üŽ?·âÇN÷]8 +^·…«îý¢o2wX­©¬+€‡¨i_pŒ›!Ç O Žó$Wä‘ðöCd‡yµ‘Db3 Ø(‹ EGó¶‘R¬‰gÕ.œlÃ&Û&«ªøòµ2ú +r(h}!G<3«;#0„_,€!éx;œ +#¹(2Œ§•G +7Š¤Š£t£ô£ rü<+À\ÐÄ7 ÍëÄu:Z$‹8‹H&x å3QŽ²GŠ 7µuBîÏi~üôësî[ñþ»øŒzïé[¯<ÔÑñw0ê)5¸­sIßzáÔï~ÿ®¤ï|û=÷¬¡2a9’O†xi@)Žî¤ÛÊ߃vJ:½€£y4\b8–.Ïмœ1Žž*Ô¬y‚æM>Yé;È7€´A­)¢‹ŽÔKíD„ v"R;y]pXG:µ’ Äç¹û"¡h´ëEÕ™¯hAØñãÙýhÞ[Ë­âävpzŠÈNKe=‚ŒàG!j8i¼¬Æã)d +V¹¬òÂlÑ¡§uÜ"²ˆ/ÕW£j\Kjù¥BX©oB~ÜJZAwŠkмž¬‡\µVìDx3·…<Â?"lŸž÷éßШï×Oä.œ|Ã[øV|ë[Ê{ âª {.ng>œ­¨ŒÂð}Ž™:=g°¡0Éf” +³ØÂP˜Ùf2#úe1CÁa²A¹‘k6¬È(´“W-ƃV‹Ù$ ÊЇñaFk ×3™B ÔV‡Ù†MˆÙ¶A†zIñ!|>,›Jô‚ˆ½h æ(i˜ÙjN67J%R±ùfÃÍÒ2©Ý¼Ê¼ÉõˆA„ŠÚh1† +ÃvÎÊ[…aR¤1Ò4Â2",Ä#9™—…4ýhCŠ4Ò8Ò”j¾Îr]˜l›Zo糄IÒãÓ$ódËä°,[r`ð}•VÚ¹†|i–¹ÐRæ°U ñÜ|RÊ— + Äùºú› 7Aµ=ߴȲ(¬ÔV«¹©ÖRVikÕ¯°¬[î5¬1®1­7¯·¬{ÔÐaì0m±l ÛaÜaÚmÙ¶Ïö+Û‡¶~›t&XÀ³Æƒ?ÍÀ¬îà6?|צº¢Šq‰ÊTU‘5ïܹeöÚ +¾¸÷aR‡ñ[L µ"zÝq=¡E!µw­(„º˜dÈ• œëi@7B¦¢V/‰±üt ¢ºYêj¾¢-Œ¡KCˆ%¬\@hz2p’‹ÔEH£¸Q:Y7 +*Âëuã¥Zî.®U×"­âîÖÝ-=ÀEñØH"p IÆé$´p=žF F3¸õË ËáܱßO:ðc$’eH\Yp2KcñJ܆ÇþBi;ª´A6èÕ“¯ ÎJèE<êù(À;«‘2v±ƒ§O*ôüs’€ +P)iEÒÉC‡¨ûžc¥ÌþV%Ñ2^{!ûúFÐʈûªwºpj—R°«ï“] >­“R¡NŠF#Ì?±ì•:lø'h/ß1ìAÚ26£¬HëŠD+–(Ž¿œÏz1,&!†ÓZ¥jÁÚKÌŽR«ÏÞÝ” ØŠÑÝg«—}þOÊsÊx-._û¹°äÔm·*‡•ß+§•Ã·Þvböl¼ +C¾ÁÛf]„ñ}ŽåB’ÑLGr4ê á«q‡ô\‚ͨç"¢d‰¢c3 ‡„ó‰j¹x’jZmX1Z'gíKRÛUj¤‘àu´«Ï''âM8ï§O<ñSå óðƒ>¬9þlϪ»:žR.\ìûwîHßí÷mXÃU+Ó=Þ;w¾ñÂú'#壼󯚞–½Dx“ú8)–L3E«á3pÄ3déJu«È*žW‹XP̻ܿôÞõð©]ŒdV§¤9Â5]óÏAŽ`Š–TE³FSs˜1TÍÉGÈÍ}\iß¾w©†gïê›HõÛÞÿ ÿ$è7ýH{^ÃÅkl¸àŒì?‰|xx‡ï@§<|^“m«‹ŽLm}ÿ8Qèóš3̬oÛ?¯±Ø„¥}/%¤e¦•¤‘Å—>Fá/Œ2’ö.gûŽÝöÔÏšwÞùñ¿((g—ýiUë9ïsÛ·´~ü.öçÚvübâ„UË«Ü ÑcN¿túY™¿Î/X÷£†»†}c÷ÛgFiu?³Ÿ4Å1wXQ‡au¸UÒs<¢Í3l(ÖÀGª&£†ZdÐöû ûmöçí{’2`+<Më¼I¹Ë–û•Iø‹ôTpQyWÈìûÕCíkÚùÉ{|Ü÷ Èý=þ^8d{ÝÃÑ#ñÀYÎÃÉï8¡(ì︢c ýÑæÛ¦ý%èÙóøÃ5ž <›ïïQèvÂÉj¿à{8=×+q¡ð/y¤?†?ŽªùOú{„pt€›ŒÞäÇ wTg‘èþSxW£;àÞ^ÝQt€?ÇÆH2šHæ °†½ù³¨U¼- û¹ß LØ¿U÷Êã~ˆŽ@%wD,B>á=´_hAV¡|½ÂFt„Û¶òÑ +ô-žEG ¼;aíJXÓï-p‰Úù°ö>*+ú\u¢×p¼p&n!·…ë%ÕäIò~8ïâ_æˆ?ïß?Ö½¡;£×/Ôo1 7Ô~)-”VÃ_™–›vš¾0Ï1×™;-á–2K5“Ê4´ V§Vô(•"oç¢à›þMÁ<}@v ÈC¼}Ds°î§Ú˜ÀüÓÚ˜‡ñ~m,@nzU‹pÂ:¢iô:¡(ÑÆæð'pà¯P,èúˆ­Úʈßjcâ#>Œ˜7AYicŒ¢ì6mÌ!½=U˜ÏÔÆ<Œóµ±€†ÛoÑÆ"Š´û´±%ÙÛµ±M±?«Í)SìŸhc ª™§­(jêmlCú©Íô4¶xk—ÖøåÑUirvVÖ8yI‹œ[ë÷ù½ng}º\ØP•!çÔÕÉet•O.sûÜÞånW†tÙÖ tk…syý2OÃR9×Ys…yîeÎMrU³a©Û';½n¹¶AnlZRW[%»<õÎÚ†Àšrgƒ/×ã¹=ä2d¸ÀíõÕzäìŒqYêtÈ‚jO`õ5~ã”ÌLÌ/oÊðyš¼Uîjw©;£Áí/`Ë( +”‹ÆåÑ>·[^â®ó4§eÈ×@q†<«®¥±Æ'×Ö7z¼~·K®özêå¯{¹FJ“P“*¡P4’Äœ9e•´1Kc¯ú#]®kÖ¥| æZŸä”ý^§Ë]ïôÞ.{ª/…"I¥no}­‰¿Ö'׸½nÀµÔëlÖÓw` ¶Ä@Îé²ß#;ZäFPlð,ñƒÄjAN¹ +ˆ–`¥¿ÆSU•§¾–Óþ€Rv7ø@zIL$IiÌ%;}>OU­ðI.OUS½»ÁïôSzªkë@I£)D¶A.÷Tû›AüIiŒ¯»Ñëq5U¹W-0V»¤Éï¦4Hƒ6¤ƒš«êš\”’æZ§ÉÄÔ×jˆ(¯*JÛäƒõ”t¹ÞM¹–˜øjÒCp¤Sœ™¯ìsƒ`u-ª± jJ€m¤‚öKªè¢æ0¬Ë6P5T7y¡›mtydŸ']ö5-Yæ®òÓÊ_µ§Œ2TåipÕR>|S$©À9—x–»ª1Œ Áã5øÔYª•Æ ¨÷d_³®NZâÖ¤d€—8ñéi»ðÊõ¯{H¶eK£»Ú ˆ2T¢ß­w¶€·ÀvWmu-54gLÔér1ÎUÑQuz®¦:§W¢ˆ\n_íÒFÆRÕWaµPgñÑz|—b¢ %@À欀¶'@G×P×"׆˜¹DÙñºé_>²µtࣂ¤z ¸‡lÎíe›š=^—ONðÃ$Š;pCJ¢n›ÄDš)Òüe‰<‰BmP™,÷Ôæ^á‘à^Î%unzCå ÓTJÓ/×8}ÑÝ0H&Ôê‚Öí’›\ÁAR%FœÊáÕ´êóÔQ¯fj£JrÊu4z€¯6:«nw.ÆÀ<5Õ¯gTƒPAÀÝuÕ”¨ÙùrAIq…\^RPqSNY¾\X.—–•,(ÌËÏ““rÊá:)]¾©°bvÉü +V”åW,’K +äœâEòÜÂâ¼t9aiY~y¹TR&Î+-*̇¹Ââ™Eóó +‹gɹ°¯¸¤B.*œWX@+JØV +Ta~96/¿læl¸ÌÉ-,*¬X”.VL ®LΑKsÊ* +gÎ/Ê)“Kç—•–”çŒ<[\X\PXòçåhfI颲ÂY³+ÒaSL¦Ke9yùórÊæ¦Ë¬X.“Ù’  `Èù èæòÙ9EErnaEyEY~Î<º–JgVqɼ|© d~q^NEaI±œ›¬ääå«´+3‹r +ç¥Ëy9órfQvHè2• 8$ºaV~q~YNQº\^š?³@Ž…eù3+ØJ=H¢ˆ‘;³¤¸<ÿÆù0ë(Ò¥›fç3À@üÎd”1ö‹] +§¢¤¬b€”› +ËóÓ圲Ârª‘‚² —곤€YÀ|'U^±F/Õ»Ü:`Ý­1˜—ŸSË)0! +Z Ö•¿¢ÊÝ觶­9·YUcg:³Z5€ ÏjÇUçØÒxË:jt &lšŽÓÕÐËÂX7d"5ôº–»!úh(ñx% +&͵>æéë=jΓ}Î:@»¨±U+u°Í7@æ ‡’É°Ñ[ [š½µ~&²³ f½µwjiØ«¥)Æä€b •~¯Û×Yªv¹»®%Özi.c”Ô6@­V¯±ÎÄWåŸ(üòRÜåñKPÑeÈ’Ä*®o]:]k-ûÝÔA’ZÉߤ’‚uü +ë éò:H òU ’/3†(Pƒ‹ômj%9P+Iÿµ’¤êáoV+IªÃ~«ZIúk%)X+Éß°V’Õß V’®T+É×^+I!µR¨û*— ŸCø®Ê%I+—äoU.IƒÈeçÆïºd’<ò·.™¤ï´d’´’Iþæ%“tiÉ$“’I²d’¿NÉ$Uä,˜7§„’3ûUGRóoSIêHþ6Õ‘ZÉߨ:’†¬ŽäoSQcä(…tÅÂGþ…tõÂG¾†ÂGb…ÏàÚá¯4þÀz+¤ øʸjç*³¹ööÚÌZˆ +2k3µ0vIç ÍDÔˆZÕ¢¥¨ù‘ŒF£*”ßÙ( ^ã`´VÈ(Öø‘Þ^äFNTÒa¶5Àú å :xɨl–]¹áÛ +{–ç VJ×€uÂÖ +À´pÑj€Õ”'ìùzó`´ ö-@M°¢ +Ö:47ÛádÉ¥>aÍ€[ ëdØïìNvïR8å Š(òÀëö+Üzv£Ðp= k6Ð98]=4„j¶CåÕ¯i‚òîʧ Lx¹´õËa}¬óÀ·¸q³½^ÆwÀpÞ‚h9tq¹Æé=*[7Ó¤äAÍ°–j㻑1…4 î´Àš¶³î52ºýLŸT^¶ƒZ…ºü©\ÊGІšÙЕ¸¡$8ïªÎœ0 +•ÚåÖ,¡±ßâ%]“‡|÷~9´¾ƒ<׉ül†ZY=“õí0ç +ü5Z(g¥ ^=ƒ´þZFS +»çÖøZÊ°4hZO×ô®jKŦژjÏéŒ.Ó~Ûߨy˜ŠÁPýšÕjVàd0TIKL?£âR{ªb먪Ðèj•vÕ–ÝÌ_UÛK +±’$¦9º×ž}Œ®*ØãÔø“˜T…Ö3(~v' ŸjÕiž4z€Æ W(ý~°_Õú)Æ LèL#ó`¨b»Ô¸~fkKடÝUqHWÁ®ysPÖÄ ¨2if6PâŽ_“L=› å(ÀƒwUªÔ61¦‡h‡Žë™>U]K!ĻӯÀGúŸ™,‚È ²ê*ìZMªƒµu®’S©m°h?£+huAŽš™<ê¯ CÀªYÔnÐ8t‡`t±OŠ#}SI,ƒU žº& ?jÇuZd h¨Šáv1Šk5J§0ï¬Ð¨sD‹ A„Æ¢ . +°Þ¯yƒoÐÚ€¯%B÷ÉŒg'£\b±y°­©ÒPs‰ó*úô°,'kº¯gßÁøq-ºð³LD3§Sã(c¤®¶—ʤEË-*v*ójF£K³¤:f§Þ•R*SWˆÎC­.A,#Ö²˜QÇ®¤Ž\ŒRª¯†i,”WULêdÖ£ÚnÇ¥òñýUžTJA s2];ƒñ\*¡hK×ô]ÇöÕ^!šKÚñ²8ëdq%70ã°È€¿\š=ÜZœs3.˜šW.¶?iˆ|˜4À÷¥;$¸ȶI!V¦úLÑ%ùe ówO­Mšìd9Ü­Bbn´‚ɹAóäFx©ÙËÉ"ª{`G¨ÞUš3ÒžRÃ"¼Ì¾}nfIW²“@¬*v»X&h`z•×PR•B$ªÃoê«>5¹:èmO¢•CÝ@íáÕv †ØÈ,úvø\ªiL͇Ԫ¤¨ú·ŒTWæj‰æ#~-VHj6ÊgxJP1\Q<%pUn‚:²ŒÝ+„9ê¸2¸³®ò`6é%‡Ý¡÷“˜7Þc +±Íg°TeðIa/‚ +[f×ôj.¬/Xto>ZÈpä´r ¬Æö<˜-‚ï|mÝ1fæÃ5ÏB´ +Uñî +æ;t¥E¥´æƒXSUÈ0(›We¶v7`2x”þtVÑq±F§*¹2ʈB¦0gEEìŠÎ·ïRXWÎä™ÃxV©-f<À}•—|Fª •¢™ð] +¸éŠY@W“ÅT¡­Lgz¤üä±ýë\¶J¥¬DÓ2¡dh²Té ò_0€¹œñ_/™ñ_3L79?7`;³J·Ä¤1Ÿñ—ÃäPÂ0ä²uTŠTžEW¢•™L^To”ò<†)‡I¤|HNÐBµ3”uHf1þò™¤ŠØêrc>¬/˜Qí±ñ:S“µ +Sµ{Õ&ŠB¤;“ñH5{#`Í×l*‡Én0TO71úƒ\¨ÈÑ>g†È,¨ýbM»z*æŠ!¤róÅ|¶*‡éº|ÀG +˜ÿÎÓ(Ÿ?`aÁ0_³Ï’ÊË7àGu×;TX܃5˜Çì©H£°|@ê +é*pÕØ•y­Šsüq{pæ­ƒÕhhÝ™kC+5 +Ïbkë/YœUOKjÎ +žuBk·¡NØÓ±Z˪Þ`õ¡ÆnõLZõºX}®Ö€¾ªÄÃê@Ï@eÒÌîsz£Ö;ñ :çQÌN–ûÓprQ–ZW:Yµ@±ù†æ•3”tÙÉ°‘å{K3ûµÊ„òפ­¥ów^rô.×<¤¼ U9„ÊßËôݨ¥j™„i=™¡Áõ¢À¹,(*µ¯V‰ÖƒÖG¡MA—v¨ –†Pîb²–Ú££8%¯=®¿×é»îËþ#õƒ¤Aý K+¯¿]?H²$Ïý éšúAƒ+ùªš‚½ŽÀÊkë Õa‘þn}%ù²¾’ôÿûJ!}¥`‡ág_I”aÿ~}%iˆÓÚ?B_I²¯äèûé+IWé|?}% }ݾRð©ÓwÙW +úÛà¾Ò•²ï•»Kêù\­$þѺKÜ]º»ñýt—¤«HW‘à?v—Ib6vy5óýw™¤à.“tI—)xÖý>»LÒ_í2Éß[—Iú]&ùoÖe’˜ Ô9ŒZUÚ9pÿûëICêüïÕ;’.ëÉ·Þ‘tÅÞQ°ô·ïI_£wt5¸ÛÞQ ²^9£\Þñ‘¾AÇ'´Kó]v|¤oÕñ¹üÌöÍ:>RHÇçj}‡ï¢Cã¿ ¾; +ÃC¯2¾Åß\e2¹ÜïLF›‹UM¬~m„¹ÁÕØÕÿæŒýϲúä?B7£!~º¸UŽþ‹ +é‰$ÿ“B¾Ê&ÿÝIþb!VÈ— +ù¯ò……üg'¹BþtoŽð'…œï$Ÿw’s=ä?zÈÿQÈgSÈ¿ç’³ +ùc6ùôL¹ði'9 Ï”“O>Î>é!g’ò…|˜Mþ-’|ÐIÞWÈ{áä_W’Ó¯ß+äw°üw+É©“³„S+ÉÉYäÄoc„ +ùm ùB~­_)ä— +9ÞIŽŽ)ähðŠð BظXxàòÀ*~ãS„‹ÉFÿãr¿B6Ü—!lPÈ}ä^`óÞ²~QXIÖI;L´»ÈZÔÚ²ÆFþI!÷ÜmîQÈÝ6²Z!«Ò¦GÿV®~¤•+É].ÒZaZSÈ +iQÈ + i6‘åiRˆ¿‡øzˆ·‡ÜÑCâQHƒBêÉí +YfË–•“Z…Ô¬$Ká¢Z!n…¸R¥% +qN!•=äVY¬[r³B-”„E=d¡DnŠŠnÊ& 20ÏÏ%vRŽ­BùpRInœ!ܨR#)QHñ<«P¬yVR¤¹pg®BæZ…9¤0Î,ZÉl3™¥‚N’ßIò2“+Ìì!¹¯œ¹Ä¡ +™~C¸0=’Ü0-L¸!œL›j¦9úÃÈT3™¢É +™41R˜ÔC&N° +#É„ñFa‚•Œ7’ëãÉ83ÉþQÈVÈŒ$+Ó(d™I¦‘dŒ5V2Ö@ҳɘëR„1.r]Z¸p] +I '£SS„Ñ9$5…ŒJ1 +£ÂHŠ‘ŒTH²B’ÂH"ð™NdIè!ñÀB¼‹Ä™I,H0V!1=dD.‰†‹h… w‘a ©a +‰‚MQÑÄ®H…D($„+ļÚr‰u% s‹B̦(Á¬¬6E£B$+1(DËô +ÑEÑEx¸ÉƒØ Ì…ppÍ%ØJBpv­¹ùßðƒþÞ\õ'îÿGgæí +endstream +endobj + +95 0 obj +11616 +endobj + +96 0 obj +<> +endobj + +97 0 obj +<> +stream +xœ]“Ënƒ0E÷|…—é";64R„”§”EjÚ 0I‘ƒ²Èß×3—¶R cûŽ9¶†t½ßì};¤¯¡«4¨Së›@×îjRG:·>ÑF5m=Œ#y×—ªOÒX{¸_ºìý©[,’ô-®]‡pW“eÓé!I_BC¡õg5ùXâøpëû/ºT–”¥jè÷yªúçêB©TM÷M\n‡û4–üÞï=)#c +•ºkèÚW5…ÊŸ)YdY©»]™oþ­Yƒ’ã©þ¬BŒêÍ2gËÈF8džçÌV¸˜1;a“1çÈHmÞ1?‚%?G­c^b~üËü¼eÞ /{nÁ†y‡ ³Î0Ïþ¹f†Q0þkføç9óè/óðw’‡¿åójø[¾ +ËçÒðwì¬áoå»ð·ì¯áïdø;q†ÿlÙŒþìcà_pÞÀßòýø[þ–¿åû4𷼧¿å³˜Ñ_ö„¿“<üß•¿ÙJcŒÀ-Â=üÓzª¾…ÛN]ú;­õôû/ô]ÏUò|dHÍ} +endstream +endobj + +98 0 obj +<> +endobj + +99 0 obj +<> +stream +xœí| `TÕµè޳Ι$›L2’@€$'ÁðÑ!‰á£€è É$ äg2@PÑLæC“™éÌL…öú­\õZ)¢DŠ¾•‹> ‚-^P±‚­V_k‹½ím¤>K­ñp×ÞçLf"àç}rÈ9ûì½öú¯µ×Y ±Hd’•ˆÍÓíWL,S!{ ¡9že1%cÚöàøw„\þð’îÏB¤i +ÂlYÒÕëßsne¾ã:óvúÜÞ¿k>ì\ŸÖ‰j0 +߯Ã÷s:»c×ìȨœ‡ïð½¦+äq?5¢Ü‚ï‡øz·ûšðP*bNÇw%èîöå~PçÂ÷ „ÌÊ +‡¢±ËȪc„4\È×Ã_øòõq|o#$íaœ£xñŸLù»$Ù˜–žÁ†eš²²Íäÿµ꧓©Ÿì"Æñ,²‘Ä¡˜ðòã,n¡.Ò‡ë¹Jº‘ºðÙ-m"\¿AÚ‡( t2é ßÂQ™´‰î"O“÷q÷*ºZž#_Æ¡!ŽëcùçôCyºa:i“º¥YÒ6i•´ +!z$¿´ŠlÅûtÃëÒýÒµÒkÒµ¤sFëù/烬£séX²Î°ŽÖÐZcØGžü_B×Ñ™ò«ò«ä 9H›r Yn`ôEú­ mtîú˜|L‹ñmªa*=Lÿ9^K^‡6™‘u䚃o»È>äû}ò‰Jˆ•Ü!4œ'$?'ï‘_áˆ×‡ä²5ó5ȹi%’ßð é£ß5l6|BÇR^9´µy%ì“Ú¥¥[qµƒ.7Ša6Þ¯àòAº¹xÏ觽ǯk‘NŸáç†í(ã³ä]” ©®0\kXGޥѧ‘cBn¤IíiÒh²Î¸Nj#‡¹nÈë†}¨f¡ï‘ïÏ'KFò!ÔÓvé®1R&?‡aP’6טCÖйißEI\@®%¹¸ú2%òsÚ…PéÆB²F?DÞ +† ½Ñ^²Ï0:Èý⺛n'w“í$JŒûišQ–À@‰U1o5”9½[m—¶)/-*™dôª˜Ó”­¤y«©WÙ~ìXs›4Z^´U³ÊÒ·Jecß;Ñâ{“¬óšÛ”ít‚£FGëh¯ÁÉÖ6ò7œÆyGXãT·ÊeøÇÙ¾Uñt*·™o;ã6³oÆ$îéêÉ/o —FŠw‰ŽC5鸧hº|«A"{ôOÌúôU·”XÊJ,%~‰Âè£ï«kÒ²>ù(bœ(‚‰0Bä¥è5id²-ËhØMVKôBÈ'Êéæó¶2×¼­Y®ËÛv™Ø.\ÔwW髪¤ÛltñpÄÌ/&·«õÕ,Tßý´QÚ&poAÜ9Æ\2‚Lµ4¡“²ßäìÏ{ÅüP5˜HÅdÊ64í«:±^ÔwäPŸeúôé•O¶¬,0ÐÅÔR2Õ2eÜør:¶Ô˜'(]L'WåË9êZ“9oNyx¥ºŽú/}*øüˆ¶ Dï½;8jìøGïýì-cîgt,>,â¸íØd&qoMªm%$ï×4coúy}&ýÕÈõ9¯d®3:Ïžg"5SöÌ1ÈÒ‘¾=–œé¨ÄCGú™Õ#‡Í‡‘¯ŠÂK +9_y%EÈÇ´ ,Yt¬B,fR¢yÊ8ä2MfGwšî¿ý[¬¸õ±_}œÎ£¥4ÎRï\ÞÞù³a²ÿúë«kÔ¾ÊóéT:ãi†úüÝþ=A-ç =Œã…=Qm6Rh”Ó +F™¦3Ù(gð±¡PŠ¿é… +Ì`’eL"¥K«–‘ž&KèÌFf>°­èâ=#¦s +:З3½}.ÍœþAšYþ MûÃGÉ™E¥Ô¶r$«` ˜ŸÝ@n 7¤ßc·±õìgx½†×o™9'}LFqfYú¹J¦Sª•ëÒçd´Á"i¼ÐØ tÐ%Æö̹–~[ꑯMeÜ*Ý$ß”~kƽÒùžôuO¥ïÈx•¼@_0¼šö|ú¾Œ·È›ôMÃ[iÓßΨXLÓ(¡â©ö³ÍW©+ 髆‰êŠÏ¡÷î¥fõCù`üÌ@ÒvËÏ“Õ™rº‘æ dšÎÛš‡“YN„N{0¹‰”}”«©’>e6ÙLÍ&à§ò2Ö‚¼MÝEW!û/ºæZL»Ô?«}tìMßzðcþˆcTHæÙÊ +Fågš3H>˜Ì£vŒÉ ÌeÜkÇ.8?s2©>Éx^Ï#‡ŽîA¢{¸Vð”0¿`~É]sÛUÅ”..3J mH#„ž y¹9BOc-%rüNõ•©ßSëé.ú{¨¥wÅ?®ûã??|÷¢%ÿbh ÕÖÒ©è/¼@}µ®V=ö×T5ÛŒ‡ +w€U ‘oE=¥ QH³­,‡ìÈ~Ö¸cÔêŒ#$ +rŠ2³3FŽ–Ò ¿(3?Ïœ–_%Ü©xy`¡ó*ò˼0 2H©¹´¢´¹TBÊäwµ O hÍË•&¢ï)R^®r.¿òÊËþ>Öëù½aÎu·¨ï¨o~¶Ê0í9Âw776\ªîù,Úáq»Õ^CÁ9ϯþõùà®×ºïMÄô¡ïYÐ÷ò-YÆ4»‡}?ë•Œ'Ò˜ÑDÒÍ9ÜÔÃ]håôc»¹•«D@µ[„–é`÷}‹+n»‡û¾ã‰9çN€Šü¼ÿÑgG¥öíAÈDTçÄÀk^CMÄÊç]ò„ôA¦†ætóÑ‹Ôª£9£=#œ±2CJÖ;[¨ŸcW×IíŸn0æªïhçZ+gI½xúL@7&HÞÞüës +ÌÜŸñŠé‰±æ¼MöøLbʲå)³3'&òêv©?ÌM‚GÒ¹íçbt•‰Óhê~˜*œ¹tÜx‹¨A¦B"ìÐ<°¦}êš¹¯gÛ\<ª~¢î +ìñ\ùäå[7õ…®»&¾îºg;® ÕñO©ý +Ïæ£õ#õJ 1mêºM`Ü´fÝúM÷¬Ù$¾9 +õ{mw¼ñÜUÙý§‹O¢;ïúEâ; #´Ö85HIzòã ¿Z»ÕÂÔϵAŸoüóË=„ÉÛȹ›´^ƃï||š\!_@Še?iãkÒ³¸?¶Úxñ È.øˆl1<‹{ñŒ#.¬ì“Ãôvú¶á2Ã!˜Ø"ñ›l£´W®”-d"ZX;ÌÄÆ9•?0”àS¹Qôâ~þÖöóJ1ç¬ÕÇ„{HbxX£“Ÿêc¿Í_ÔÇF’MÞÐÇ<"¯‡aNù›>6å<@Íú8‹Lþ¨>6“aÃßÓÇ" +ïCŠTÊ@†*‡¨)ÉÏSô±¤çMÓÇ@”¼‹õ±„ã+õ±LFæ]¯¤(o>N'¥yOêãadFÞ›úØT6#߬³Hç̹úØLògnÓÇ’>ó¥êP¸7XÒS&x&*U••“•Ž^ev E|în«â zÊ{W—Ò¡¢J‹/ê‹,óyËÙq[§ñ­.÷²î¥¡àe¶»ók|KÝ zðkÈ\â‹*îˆO •pOGWÀ£xCÝî@0ÓêFg‡º¼)¯ÊPï |‘h TªÊ'Wjk|iR +¨?D&b(Sg,žQQáÅùe=åÑPOÄãó‡"K|åA_¬V€q–¸PýzP&D}>¥Ã×Z>±\9Ê•º®ÞpgT t‡C‘˜Ï«ø#¡nÅñ-ÓYIÐ +ëÑ–J†±$uÏ­h¬õkM:é;Þ>§lZeå@”¹•XÄíõu»#W+!ÿ`,Œ5û"ݨ°A ªtú">¤µ$â¢èV”ÅÂm¨1Ô³U‰…w°W £ÕpC¨#†   +ÜŠ™fëô%ôäñ„ºÃÎbˆµì FQ{¥B%¥™WqG£!OÀô˜7äééöcîçÇèB#MàÅ¥5ä-Gõ—NœD|áHÈÛãñ 4Þ +èè‰ù8lÀ+šÙÓÕãåœ,Ä:C=1d¦; â"š*mOá¹8V¥ÛÇ¥fÂA¢ÖVN³"Q¢>´BU]üA¤9sˆ6Ìcšê¡åèXÇmàfð÷D‚HÐ'6zCJ4dU¢=K}žŸáòùC]èl\ O(è +p9¢3s!:wGh™OH y‘` ß ‚¡š!ªÍr«„“ ­)ÑNwWëðéZC60JÜä Ñ/"Jw(âRl%ÖöùÝH¨\cjàj·»£·{þw4wW ]ˆÔíõ +É5ÕñuG¯ž.w„qB^_4°$(ØX¢Å*nâêö ’(ß‘à':˜GÉ€P˜»khúžIlÈ^°«W ¤¸9ãâD|¼±,`ù ÊÉí’úœ/"6-E¼Q¥´?K9íÄ+åa[*T†–©×ã¥Ã‡‘ıö  +¸N–…ýŒù®‰aÄ(îpÃËÝÑå㠚숙XÒ(î˜ÒéŽ"F_p€N¸×%½Û«ô½:ÃIV™`N“ðdVbòƨfãFr+]<{`¬$ÃnÏÕî%(Æa0ĸ«~1§@ +²èëòs¦æ8”Ú¦F—ÒÚTëZhoq(ÎV¥¹¥i³ÆQ£”Ú[ñ½Ôª,tºæ4Íw)Ñbot-Ršj{ã"ež³±Æª8Úš[­­¬©Eq64×;8çl¬®Ÿ_ãl¬Sfã¾Æ&—Rïlpº©«IlÕQ9­Yƒ£¥z¾Úg;ë®EVVët5"Nd®E±+Íö—³z~½½EižßÒÜÔê@5ˆ¶ÑÙXÛ‚T +U75/jqÖÍqYq“ '­ÌÕb¯q4Ø[æYDÖ„"·(¤¹DŠcßÜ:Ç^_¯ÌvºZ]-{‡åÚ©kljp°Ú¦ù5v—³©Q™í@Qì³ëo(Ju½ÝÙ`Ujì +ö:.N‚ÓÄIªƒñ +uŽFG‹½Þª´6;ª|€zt¶8ª]uš¨ìV75¶:.— ae ç8 ÀŽªgBüF—ãq5µ¸úYYèluX{‹³•[¤¶¥ Ùåölª0õÉרóËmÄçŽ÷„â»uközDØÊÙÀ 6½ËqÇŽqßÖƒ[K"j¹Ó*¼VKèÂuA \mN ñXÂȧŽ–Ý’6?Ž­Zêé½O"-õz—ù0Fy* EXˆ'“娈t<»CÚ™§DÝ]H wñ(P˜+Ý]¸-ÚÏ怀b‰Ã0 à–å‘@ “‰âîÁÙHàÛú1Ñ)!’”€SI&ÿˆ/ÆS*°Ì×Õ[Ž°~– NA¬ÕºuÑ…ú<±‰R!¦,Ƚ¡Ê®\aLT\g\:ji{vê ¦ÕAÊéÔA,Y)§Y±ãë =É{¦hâÌ¢@M,ìLj%%Q+±oF­Ä4;|iµÓöŒj%vk%–¬•”Ó¬•Ø€ºà4j%v¢ZI9õZ‰¥ÔJ©á; \Âó“ÄÙ*—˜^.)gT.±ìŠïƳ]2±`H9ã’‰Õ’‰é%“rú%\2)§S2±!K&å‹”LÌe_Ð0·‰³mŸsZÕKJ~&ÕKTGÊ™TG,µ:RN«:bCVGÊ™TGÜYJáÃNXø(_ ða'/|”S(|˜(|ÖŸ_ÐÄð6Q4°r|”Ÿ´sU±&¢ÀƒÚ-°ÄÄJB?~ué‘4¡ŸÇ$žk8ÿ1ô_Íû9ŤNøLXD)xÄî7^!ALøZ®ÆĪFƒ„‚UfrÖ#°h:Y.| Sd˜®™n1—*QB†È¯Ô¸í:´¦X‡»…=5[³” ÅÝÖÈaí—³BdE`ÖâAÃе:Ðú'—:¡9Ûp¿GÇ_I¯KJ´\è£û”($¢Á/²vP—ЗBÑ+U<¹&–"„GàÓ`öó‹3DËl ym¯à8 s:CD§KçÎC"3$mš‹’8>>¦GCtl"V’KÍ©û!³[pÎDnèkš6´³Ä}{†Ä)§è¶ïÏdþ8[ÄÄIÄON·.QùMl/×I¯~¶hÔ¹Îý‚G¯îI]ÂO#ý3§\§Þ›§z]âu‹1 rF—xcýy§Ü^Ám,p®j”9Ô-¼GóÝÁú‰~®L .™.AÒÃÜÂF§ÎÁ@:ƒõ1oVÝÞ]b_àÙœõ['"ò¬[ä•$ÞÄL´ß#ñ2øôðéyÎ'¤HPZ.¤òŠý¥Cœ‡¥ýrÞÁp-qÚ–¦x™3õƒÎ—ï¡^{ô8HøÉ2\ + ¡1¹Fè9¨Gr/íôr‹Œêëß‘jwçÄ 2R:E†WÄ3ªóèžt"?I亡r·WœAa÷T} +¥U–¢¹Tžn¬FõÊ[Ñ%ID["’xåÐÕ_{Dô1†…G_÷%ºÅ´ó{ëϪ_f¦:±TzŒÄôóÐ߯©9Ä!è4‘F|ãtšðÍEbÙ"Öœ8§`ׂ+ ð­gk„]ìb…¯—Šh\ˆcŽ±‰Ì¸4-xç¸á Ç­ˆwþ6áßë m‚†±µ"gM8æ¸p¶ŸŽï¨Æ™ùøÎÇu„W¡½FÜå±Ã÷q^4N]8Ÿ¤:+§ ˜à¬ßZÿ}ÕŽ¸çß*ê#>nÔùÔ4×"°sqÌg5rT/Þøì||6#\«Ð§]ȬqÛ(d¨ÅuM‡à@³„ÆQ5>›‘6‡¨C¾\B œ’K‡´ +;ryjÄ~Nuž€Ò8kÒ­ÌÇI,åº.5>¸þôSnò×ã¥ù]8㶱#þÞ„ïÔ œo&´1_Ègzhf 8®E®Ïú~kI±JµÐ·ç¼FP² ´)I[ªu†òÖO¡NÈçšªЭ¨GÂ;ûg4t +Y«u]k85¿×|¢>E»ÕBFnÙK‘ªC÷)»ÐÝ@)¸ +þ“Rh°ë÷ê%­ß¨[7ÁKPv +¡•…"Ê.lÝÚ#µ"~tÎç÷{X2Ì×ý³©Ÿ³úMÄQîTr‡†+A{ k„?Õë¶ökCƒ`'Á«å.žkñëÏÛOîÔª1Y¦ÖÖ”\›Z hY¸NÀv‚KÎj_KÚ™•üÖI­Ý†úÂN|kµ|¢êMVZîÖ¾‰R«^¯¨Ïµ0Ú_•„Dê¯L–‹Õä™Ö{'¡ßyœ²[œýÖ~Z‰³(‰K«+Ý¢ZàÔ¢ChóÄ';îË0,Î{Êr1Žé• —¯G‡åóßô5œèÿoeH$dªrHÕDØ;¬K„†y=Y®ãÄwYR'\Z_­{Õ“ÞÇ±Í ƒ» +\KR8÷ +]3¢õè8M&òU¢ÇõõwÎv×ö›ÔbúAƒ+¯/¯Ćì)_q?ˆR?h`%ïIá)ÙëH@žZu¨ ûÚúJÊq}%öÿûJ)}¥d‡áÿ̾pÂ~}}%6Ä×Ú7¡¯Ä†ì+%%újúJì$ý‚¯¦¯ÄÈí+%ÿÖélö•’ñ6°¯t¢Ó÷ÄÝ%íû\«$¾iÝ%Fv—†în|5Ý%ví*)üfw™˜ð±ã«™¯¾ËľÁ]&6¨Ë”üÖý*»Lìs»LÊWÖeb_ Ë¤|i]&&t°±ÎÜjÚ¶ãúW×;bCÚüëê±ãzGÊ×Ö;b'ì%{@_~ïˆ}ÞÑÉð~¹½£Df=ñ‰r|LJFÇ'µKs6;>ìŒ:>dz^LJ¥t|NÖw8šØqøm$Ùi`‚+?ƒsU!ôr5þVÞ¼¢j*õkçVc'ÿiDÿï¤É±ëÉedˆû¿VÒqD%@ˈïçÐäY¦ç8¾%ùx/ÕçJUÄz1Ù‰÷"¤´P¬Ž!xMŠð>J̈ûHq!îùâžGsIbÍo| t¸çˆ{6Í"+p=[¼ñ1PÍ$·ãœIÌ™Èn"ÑL: s†,V€òÿGœD‡QFÆá_¼ÛpŽÏÍ;ÓÅ=dŠ;ßaÜöƒrÙ>œ…\²¸K +„D1CÅØŽ­€cƒªÂÑO­òQ>µB\…~R'ÿs|RÿˆÃÇ*ü]…#*üm'|¤ÂÿVáCþZ‡Uø É¨ÐÇ Ï&ý忘ü—*ø/ŽÃŸîÊ—ÿ¤ÂÆáqx_ÞWá +Pá÷*¼§ÂïTø­ +ÿ+ï¾3R~× ïŒ„ßl(’ã…·ß*“ߎÃ[eðë×Ëä_ÇáWoæʿʇ7šå7sá ¼1L> ÀÃà—ñË8¼Žø_/ƒýßÏ”÷…×~‘+¿6~±/GþE.ì˽¸¼·^Í…W^Þ)¿¢ÂË/-–_Þ /¯”^²{±L~i1¼d“^,ƒÿPá/ì¹Ó,ïQáçcàyžSa÷ÏfÈ»ãð³GGË?›Ï>3J~¶ +žÙe‘Ÿ»vfË»,°óéLyg6< ;ض«ðÓRËCÎå•A®†[ G ¾[T0{!;Ë,g‡ìÝR–²VJ&\1Å!³ +†¡hÃòaØJ‰™€Ù¤ ÒUHSÁ(3Ù¨‚Ì@¶IRÀ ÜeP1{™djbºzo\MÏû¿ã‡|Ý |‰?…ä¿ÁÎT: +endstream +endobj + +100 0 obj +8383 +endobj + +101 0 obj +<> +endobj + +102 0 obj +<> +stream +xœ]ÑKnƒ0à½Oáeºˆ0$DBH)I$}¨´ ö@-cgÁí맭Ôè3ž„ÇIÝœ£}òê&Ù‚ç½6ÊÁ<Ýœ~…A–f\iéï+z˱³, Ùv™=Œé§²dÉ[Ø›½[øꨦ+<°äÅ)pÚ |õQ·aÝÞ¬ý‚Œç‚UWЇ>O}îFH(µnTØÖ~Y‡È_Áûbg´Nã¯ÈIÁl; ®3°RˆŠ——KÅÀ¨{i#×^~v.”¦¡TˆÝ¶ +ÎÈù½‰Þ¡·äL wämŠÎc +e r‘£÷ñ;Õ¢ÏècôýûÑut>EgèsìI¾Äì!8Ñð~<*ÞÅϹ¼9ÆGFsÉi¿wj'‹)z¾ v£ +endstream +endobj + +103 0 obj +<> +endobj + +104 0 obj +<> +stream +xœíUÛoUÿÎÌ^Z.m·h² +g.…Ýí¶åk@‘ÅÞ ´vÈ&2,gw‡îÌ{!´ BM4¸F5мñ¢9«ú`LP‰!Zã…4A%ñÁx1ñÁ‡Z¿™=]lâ?à´=óû¾ï÷ý¾ïLÏ¥T(3X@†XÊÔí6BŸoHkêL‰VýGÑ$¿âðXÚΘOvƒH}<“›H?šìØ ‡ñëY¦ŸlVßÝà9‹öŽ,:ž™=êG›£½>k–Î~ +w|hßF»!—Oé[` ¡ç|¦~ÖH«°ÏohSK7Yãõ¾ðzЧÚùb© +NÍ4v8q»Àìlè«×Ñ~íÓ(¸í㌀ø\ûÿçxž‡÷¡®QØaèãpTxnÀMø¾€·á9x +¦à2\ïA ðæ°b€oNðþ3uw;÷…»4×wN£·9YÑÙá$LâËB.…FûTM‰p9l´SN(<¦E¸'ì¤*ª2™¸œÖ‚ÈKÌïiAUáÞP‚ÇÏhn@ÓPÏ^ž<á¾pu¹ˆÕéÅd2Èeüáêz׫»­ÚðÆ0=çùe(—7ô©”{6ösNTXE§x$¨(Z°âZ#5Ë)¸¤Ö]K°EAÅ¥aúƒ;eaåþP2Aé~5®Ÿ¢ zòDMÂá-w*ciZ¡û+q]­ÐŠê–SqC&ÎÏqðs Ìir+íšiW” ©àgÀ¤>ìæ°èMqiÍa•Îˆâ*M ŒN´D'Ô§VTZ髨º“PKq^ðÿò”/;Ú[àC\!î™æþ('Ó„7D9Ì8¶§¥ê%!.OWIºº·”À% LÉ0{^‚¿Á—þëÒ”7 +Î.ê'·¤ãò]h‚5¸$°%ÔC±æ(÷Ìð¥Óø[mqUȺM·oÛ±µgõª•m~9f:tÍ2‡È­CyëÊÁ!Ë<àîL²ýóËöÕWŸjÞù'¬mpëÍ?Þú}áâug‚gΫö`žÿÈìù”÷¸„‡Å”tú׎‡!A³ÐÜS¢ÅqKs"gy³®³¦®I` ZDdù¡C`ýQ=ˆ{öâ¹³W`úÖ0í¸ój˜@#œX‚L +,cG/Ô¾ŠË¿,°ÃÿH` Ö§ËÐ +?×f†ƒ÷F>iX‚ÕdµÀ2H§‹eV’Ýh cc?$)° +ˆéb‘ ;úW– •¼#°ŒœñËO#Ú;Éh“š– IR–Ñß-°ñ>½Ð.iûк#µ™ötuõÒѲE‡ŒT!_œ(–˜Y¤}Vªó Í¬Ñ óD>7Â2åœ^¸ï¸Ž°BÑÈ[´»³§û¾wO.GÇ&ì|¦ ÛY#EãL/• ¬8hdj@X=²7oš(S'ÄóVª„ÂEZªëœ./PË—K¬HÓÿÅ£‡‹e–˹%Ù<)mSY†s¾”É©ì83JÌšO±\æžrq’aÌ*[™¢^Àø|ÁÔ1RçÅËÖ$–6è˜!TQtÕ¢cåR‰Q¤Ï³æÔ6Þ 8ݲeü»%:Î,“ÆìI¬ÚÏLÆ,¤ë¶ÍrÆ©ñ=áFJÁf x +uáO/¢Q(ƒ…ï!00V€<aÿJÀÀÄ7ÅëËÂH'n*}fL`ä2s0‚ž *ä@ÇÜÅ‹ùŽ §€ÚZNínTïÁq1.®H÷™Ë@Ûb—ì'dîYN^„Þ0œ¨ò’V;· oÁ‹²mÁía<õ“ +þËïi +endstream +endobj + +105 0 obj +1357 +endobj + +106 0 obj +<> +endobj + +107 0 obj +<> +stream +xœ]AOÄ …ïüŠ9î6´œ›&fÍ&=è«?€Â´’ØLé¡ÿÞ)VM<@òxïƒ7èk÷ØQÈú…£ë1ÃÈ3.qe‡0àHÕ|pùPew³MJ ÛoKƹ£16Ò¯â-™78=ø8àYé;{ä@œÞ¯½è~Még¤ •j[ð8Ê=O6=Ûu¡.;äí"È_àmK¦èú»Š‹—d²¥ USU-4·[«ü?ï †Ñ}X–d-ISS²ÇéNícý´·2K“2{©°?¿'Å´Se}~‹my +endstream +endobj + +108 0 obj +<> +endobj + +109 0 obj +<> +stream +xœÜ½y`åý8ü<Ïܳ³»³÷‘M2›ÍnBD² +$’Èp +Ê%¢¢­(VoP‘ÒŠ”j½ +ÖÖV¬‚ŠgM¥-ÒVÌîûyf'm¿Çï÷¾½Lfæ3Ï<ççþ<Ï3K{ë’¤ µˆAѪ†ÊföãwN „ÞDÛ«–¶k÷ý©ý Àçâ.h^ØpÃcY6„D!®caýŠ¿ÿñ +™#4jymMeõðQÙV„&ƒ:†ÔB±[xn†çôÚ†öå>ß7ðüSxþg}SUå¯È?e+<ßÒP¹¼¹V~œEhªÏZceCÍ”WߺžsÊ~»¹©­};ÊŠ#´Ñ÷Í­5ͯxÄÏBr¤a8è?(yúL–ãQ’MŠÙbUmv‡Óåöx}þ¤@rJªL ¥‡#™ý²²súÈ8hp^~Á¡Ã +‡(ºýÿàwùàôsO#A^„âŸÃù½Çêâ_Ð÷ôN¾‚Ì]ƉÐn´ס½è%t_€RûÐÔ‰~ž„Ÿ½0Æÿdâˆ!“€‹†2Ÿ ÛÐbòGÔ +r¼Ý«Ù…è.”‡W¡ÏÑS ý¸F>‹wá×H»…8p'"ì]!NÇ çDëq9ó ÿ +y-A§X}È<½?EžgJÙ Ü4\ °mD-ñuh7›ý-^ˆ< …Ùs ÝV1ƒÙ Ü×€V™ :í0H÷QУ˜RHñçL¾˜ âA8=ÁÕŒßZì7¨“ŸAºÐB΂Aë ľ›†æÄŸB;â Qcü^ÔôÁ¦ø*¨q7úÝvã +±›Q3JÉùOäÆ’SÜØx²…¼G¦“í?¤/`;Œ½è+8žGcÑHîE´…ýšŽŠã[ã¿îÎ +»ÍG×£ó0Ê¿@ ×1ÇQ^lÙË4ÃxÏ¢©ñ§ã©XFµñz4CO +ª²££FE‹G^S4bxá°¡ùyƒ +ÌÐ?';«_fF$œJ j©)É$¿Ïëq»œ»MµZÌŠI–DçX†`”S[¡uD*:ØHèºëúÓçP%$T^•PÑ¡AÒØæéÐ*ôlÚsF!ç‚åŒ&rFûrbU+BEýs´’ÖñÖ˜Ö…çL +ðcBeZG·—êð66 B­Ä[;FëÀZIÇØ¥µ[J*Æ@uûMòèÐè¹Ú/›4Ôá 5ïÇž‘Xˆ§dø~‚D3tªÃSÒá ¡=è`Â%•ÕS¦Î.“ –õÏéÀ£«Bó;PèÚk¶žÖ›éàGwz3Z +ºCÛŸs|ËÖ.ͯÈVªCÕ•sgw0•e´ +[6´;¦Ã³ò¼÷Ê#Tn={ÓÕo“˜-%Þ:>nÙ²IëØ5uöÕoƒôZVu@Y[±e,4½8aº­‘ +e³;ðhR£#¡£JŒ¯&TBS*iRèÚPí–E@ÿ–4mEð€ß=?‡ü%Ú–³CÁŽâ¤PYå˜À~'Ú2mÅA_TóýðMÿœýª-Øý«(æ«š¾w:¤g§Ð„i}˜Å´G¡ñÀZ•=™‚1 +£—šahKÕ0ÈÿÊ0”ꨊÔuH£+¶¨Ãi:-ßÁ…Õ¶å[êþú‡)•F +V¿E¤|ÒÇjð¾îÈÎîÈÊ¢,"ŒšBGêÏýs–v‘P¨YÕàèCS·•eÃsýÁ %ð]Q4:ÖNxÖÐü¤(š›]ÖA*è›ã½o\3雵½oúŠW„€“;uç×Õ!Fúþ¬ªÛQR;¼»ÿ›×5‰÷¦‡&L3[+ÙRaàvÂŒ<%Þë{g@ŽÑ³™$b@$‰ÑßSÎíËLf+lþx©«»¸ROÁÚصâºÄµLÿ—…ºâh)ýv¥˜ÑÍŽáÙ?|ñƒçtOÙÂ@‡ÁN˜1gËùï€Õ +Ž7nÀñhÆì 6ºÍÉ Ã_Wüø0z–%uDe£ià¿D’ñøƒŒI\ÿ(wöÏ ŠnË–±!mì–Š-•]ñµóCšÚr„œ '¶4—Tô2NWüèIc·–®jñðþˆ`Ýùäx³º¶“àó¼ÐEvDˆcÏ3HØóùDž;O˜c`Ô%pñ o¶z©¨§h’z±¨´§¬~—Aƒ¶ -  &í{9þ}”C—‘Æã +~=âöBÌàEixbÔj7Y°}H`Nê±!•µwÅ?>h÷çÃýÂÁ´Œ|}NÎÈW»Õ¸Ãû?LŽ$ÞC~Õ¸Ó÷Ñ6–ë×kÓMs +Vi¹e…uƒ¼Ùz¿yµËú…ås«jQÍfuÚlV›U‘ìà5úÝ2¶È¬p^Ir{ü¾ÓR&ÈëµZ-bJÄò_®¥7§¯MgÒÓ¼Ö@ ÊC#v{³ +åjù%ßyo7 C…ƒ"Å^˜ ÉE…¹vO!¶y +7Yds«Õ“ƒâòìÞ¨85*‹Qk¡Un³‡´2܉G%þaÔï+´¥ù +ípZ¢B5Í g*œ®B£†²<[p° */¸=n#Ä ‘PÈÉC†äGBÁGÉ–“o®|ýÒÌ™ãOÌl¼¡pÂGøÑ +Û'Ýÿxl wtò¯W<ônr8}Ò’X ´~ë0“г„ɺb\íFJ» ñ/Øv$øÉèÃhu* +¸ÈL¦œ+—fšj˜Å\“Tc‚À^Å*É°¿Ç}ç¼äÙ‡ûFÙKý£Sís}Ó•öe`9¿Üu‰\òªÝYÍÏw…»Ù͸Ömê.•¨*›ÔEž‰Jø>G€5y¢fàø¨”‘•ßaÆf*< Gòé=šœÊ˜ŠSÝyjºMÏÊOŠ…É#øRò‡&È“]Ús~’Ú’}©%»(ÔÝs¾¸¨S^ÔÓR„möÂB{!% +*Ç-­ØÃó¡4dSQÞ`ds +A·;oðŒNÓx榣99òeììüÓï!<ùþ ùÀ†ª­=gÈTeجÛWíÁ³Ê„ <}•ÒÂùÈ +x:=”9 ip±*ýP¦‘ Q|'Ï‚P°Lœ--À HX'-GËð2²B\.-“7áMd#s»°YÜ"=Œî‘ŸCÉ?G/ûå×Яä3è÷ò×èù2º(çȈ“½È-g¢ˆ¯ßKx“¬Èf™á]n§Ûáfø$ÆÄv \¼b ˆÝ²-HÿÖár*Ï Èn»ËI,$1ª 2p`ðü¯gçÜRÖÞ6iå=omˆíÇ…÷<9¨¤ôþúI{corG]ÉçÇN|:ÛS9xïA%_>õÙ?²Rè8¯€ g¢¡89z—d–²|fV?sVV¡yˆkhÒð¬ñYåæò¬E溬Š[Ìû=èþ™Ùõ”ï™Ìþ3OúNeþÖõA¦8ÆS=€Îœ¬üB¶0g<{]Î,±,{X—½TÙ¤¼¦üËü¯lÛÐ| fÕÜô|Ïà Ó;¯_S?Ò/k)¶ÜmÙi‰[¸–}–o,ŒÅ`vçÖžŸ”æ€ +$ñº2:YpJ´*W¨.k¥ +u3³M}{…?®^PM"W +lŠZkêPÿ®üÝüw‹Ä*¬™µ05r,«˜-"/ +À"¯àÏh‚â„Â0«8!‡”Âqb +Ïð]¤9*!Qù2 +¢MŽbÂص+ª˜iSØSìY–ÙÆb¶ ã¨iŠr\8«0Û@aÑgÕ*œÈ@~b}÷€¦‹å->8áÏÛ­‚¾R»»‘·¸ÈVØS»©–sOµÜt;c+,ܤž?¡sÉâ)wqG{þvoùõÌ#nºyú]«{^m?´}h{3ò¡—£åvAö)ãøëÄY|™¸¯Å|u¸}¸»À[¢N°Op—xçrs¥ij¹½Ü=ÍÛÀ5HÕjƒ½Á]í]†]Ï™odfp3ä•z¦†«‘ëÙ`[Àdr¦ tìŽôpþ@@A½ÂƒÎ&á$šî£J`K:ŠB–TT 䧮àx¤%»üRy9EJwq7HUÀÔ%–¦sÓ¥ùÜ|‰Ååeu( K}3‡®r tlŒyâö_½Ý7ÿùŽ³±î#6m;šÎ.`ÛY^²‰’(™6ÉŒ›¼€A8¤Ìm"Ó4v4ÛIoû¸“}ô>¯–_lÆ/.î¶é’¯k¤¾¶É¢û,å­ÔÔ繆ÀÈ<‚n`€´YW|ãM#¯½vÄMÎ6òhËußÎW\ÑÚó;ê?.ˆÎ-åÞ_¥+ZQE% + +6W¡fÔž¼­OÞ†äžež4a:ͯšO£óÉO¶Yìɶäd&‹Ï´e´ÔqæYÎ\³|µÜâä›íwØdvX ìÆOݶß[ '~Õ©úYpC?ûæžc_n9–t>Ô +¡WŽ œæQà†Ùóìyé#ϧ÷{î’F<¢’¼IšÄ0¡”ï&¦D +—O‡ñ¶ð®0 {<~Kx› +Ûºpù!oxeg\õ!’ +ãÓoC»¡ì<¢g_z¸ /?¤âž= „¼BÂó€‰î‹å=“JjÆ|ÖÒ +R_TJ°TsaóèìÐ+þŠÓq*¶$l7»zÅŸÆ#Ù½ ž,\:€bëÚàÑÁO-Zzê-¯?òÌÁÐÜ‘Í?íœ]=qÝp6rߤyógÝw¸'ƒ<\?oø}OôÜO,_>åÁ{zÞ3ôâg€-7z3êàÞAv«]ê'ÌçŽ Ì%ÏRC1¸BŨ§½ç¼q/«‰N‹b0æ6Ëf‹bI7éZÒ„áÏ4ÉK¹ÅOµ¤÷‚—4{wy;¼Ç½¬Ì–ËmŽýßÇÓ«$/õZ +0¡trAŸ^=éæm’,ÊxÓjÄÆ[’°U¶£®s èÌg†£vÂ6=¶äƒŠG§¨rgÖâëÚžf#÷ï+i.¼º§llluï›=”ƒŠÁnîœ ÄïEofÓœiÃ¥ë¥1é³ÒjÒVIwIëÓŸr<›s‚1K¿×3pBλ.‰Ì$DŒeï\q®4Wžkš«Ì5/I‹äE¦EÊ"sg¤3ÚIÏHï7$}Ž\fªŽTg¶‡ÚÓצÿD~H¹7óþœû>!ïQÏx"ó`äWw2 í)…sÄŒ°"³~-âbM’ýÔO¤úŠ}“}ó|û|§|¼Õ—êkòõ±©¾»}Ä÷"™ Q:‚lªŠ£˜¨ø4&«˜P1>ètçëâœb±åc<`nr}2I¸60À”êÇþt_ÔáÍ÷Ï}@HÏ‚œ/ +Ogá,ÿ`Z*xÅàãƒIñൃÉ`„?iéÖ´³SA È7¨7èn)×»»u’NNw_ÌînÕÕA øÞ  ZZÏ«=ôšðÁ +ˆÍèŸâœ9›jW*癵$$e +I˜ë—'<-¡$”2+b?9 gfH2ŸÍ&¡T5™²C6êDdge¯[Gíi .‡Ê1Ô0 ‘Œ †hx¥óKB¹œ4úò¤„¹‰°Þ~óªå៼²cò¨aY÷L_ýó9¶¥­nÕ"·;7iýK÷Ϫ{eõ©÷ð5Å­5c® yÃǯ›4nEfjöu7/ôN›;mh(ìÓóF­š;gç +ÏQM~¨t™;ŽdÔÕ˜¨Ù–¿˜]Cî&;Dö9Kˆç#qX!øu9!5A0¥HAý +5[ó9šl¡ÉÖ¸(Ò>ÓQ\„7 Jƒó€yÃéótÅTçÙÁç…qòÈåÎQï̸ÿãÜvöæ‘«RŸ÷ú<Ú¿£pÙ„ÞíŽzI’IÑ<Ô„Ö }ˆÝïw±> ;ƒåÎ+Ès}ë­·h¬93þ9kƒ±©`§uòšO +€29@4Ó/âçÀ;‡ìpZÁñšÏò›ÈfÓfëkNL^Râ˜èºÞ7:i†c®k®oZÒba±©ÊQïZì«HZA–ñKM+­›ø„íêkÞ3ä]þ]ÓûV¿?…åœ)f³§MŠRtPT•ˆ´-ÕÖ†z‘¤¡(tm[Ê«wôú—ÞXÂñ Æ Q§{†Ó¡Úuž°»TLq¨”gl*pˆÀÏ\üή¥Ú¯]ôΣ¿[qÏ‘=«VíÙs˪ëËÉ;˜Å×<7ï`,~&‹ýrï/à‡c÷s×âE©ÛHñZ„+nRÐçÑ!#¸ü‹ÜKü‹Â«âka¼R¦Ì°,Vª-+í+·ÛÙ?õštÁ¯¼dzÁA’Ô€š¬¦¨ü/ B"Ü%PÒþYyþõ€h¿ð3˜ˆþcNQ»È'ëfÌ{ÈœâäPJy1jÅD‘Û<ï@(¾ð‹dèb‹*¶CÅdi"kKŽ’t”ŠïÞŸ@Èó¥ì"õ¢1ãÑÝS~Þ¦OmÚs›#Êߦ‹ÃÀÞ—·†]ÁÈÐ!Æ$†HëòFÅK€?Vø~(ñ„ð›Ý;n¾õ!|ÄñÏ·ß¹tÝÓ'››²w諸ªã·œütÁâŸ<´Åq꽯öÎ~æØ›+_N.ó&=`ѡnÜÏ=Þ=>ò™òå@NˆW£ÕxÛ.¶˜Z•%æ•ž;м•Ý(®3­W6šïô¼i{ÅaOƒà@@óÓ›¦åÒ[-B£‚”~š‚R¼HIJ°k`¦ð\fŠÝœÒöD]daTÍn³F5`9+„ +ª•X»ð=‡{Û:ÌÀûém®>þsE]ĵmPÿ{ êÁÅòÚ Ës» +G8r˜ñ*-Ô‚#tJ"7Î÷"p…!åjo˜qº¯<àEÍõŸ½tü«Å +›îŒ]zï½Ø¥{æo\\»áö 7¿múºÝ{o]ó4“ÔïE»ÎœÝµàþ~9'7‹CX|üî—ñŒÚõ·Í«Ú´þûxé¶ÉO­½õ™ÝÔ`Ç?'…à}î ¼Cg!u£š³ð~à9f'³!ÌR„tÿ†|2ó"_à.¼çðýÁ•^ª•©e ¦½ˆ†Èå}Sâ.tñžm±Ù>îëïh +¨ʸ¹§!ŠiŽZNš1 Dd%ÆŒ($˜•sÃÊÆ“uÆeˆß*¶IF“ñ<<0ÅpkÂk@0}–.|/efÝ>7•jGÚÊÓ4"Ó¢GAÐÅ#†BCìö¡•Ì¡­±î C¬G˜[ÿ~;ûÝÞ­÷Åì±Ë]ïïÅ_áW¢}… — +Q¦„¾Úo7Q¢8\ù"‰D§ ˆD`Qb ‘‘e4žçÊ5ÖLSL¦fÓZg%-á )PRŸk”G”%˜%?‚w¤¯¸é“V……›Ø‰)Pœ +AS§[ñìñÃc Åèà8¸PHóéd:ìpp¤©¡ñL¡BÁâ„ÓAŸ/v˜œ“tQðŸûûÖ°1Ãj¬=äaˆPCØöЫ 9úê÷1îèåuìšïƲk/¯…ð€•±€ç¥á ;BêŠ~ÐîÉáµÀúàÂЋDWw¼Aúêѱ°™p±GØ~b–œkakq-_kúg9–axQx^âI“MNY6ñ /1ÁN:ᬘxÌ€ãcê"¾¨$ËC-]Ä•iZT^+¹ ŠšM&ECÌ´É`z ”h@¼‡Í–ÁŠÝàÏ_*¢Ž< ^¿}FY¥à"]ùÙ 7 +È…9:ÏCMtvG…Ë„Ïô :¯#*’Â_™¹¨‹u™>Ù¨¯ýHG„üí÷û(šËú汃6 : +7ÑóÆ×88¥äÚ›pàãžHS»jUÛ6¼ïûƒ=?A¾_`#ÈNöGU«g±ýdr½íFÛ]6ÆFz)5˜¯’3(²/D÷¦¦ç³¼"9ø$ÉgçXÄò&Édí*r0N! &™’!t Yb¶%ÃÅ–1Ì8>*”ŠL£­ãl×Ûo´N³/ªÅ…öüJ¡]<µ¶Ë_–2M¶L”iΰdZ3ì¹Îah¨}™¸Q|€¹_yï&»MO)‡Ðaþ¨å×ì»ü{ÒìÖÏíù豈á8 ´MŠ"«6›µ+>á ‡ìZW||tlµh¿´ ¢&ØìölNprœ`‘%l¶8Íf‹h³Z³eCD\ßš"X°³¢Õ¦X̲Mf»YQDQ(ÏØ­V‹ÉÎKªW˜›ÍkÍŒ¹ ?•µÉ2n’×PŽ!3£ØÓ&Û±Ñ'“Êá +®™[Ë1d>„/9.-ÐUŒ¯ôby¹\\ø£ËåÞÏúÖ0TãHØO}}æ_7•^½´ñÃðÃ&‹zR°¨Eô¤0='t¤NŸÝiÖ§Ãi‰ŸîD­š¬XŸ)›Ð‘?}öðNï¨u„ php(M=·_Щvc>’.Až>lÕhÝ “§iÐ0r4ÑR_å}å8ìÝS>˜—Ÿ¸÷˜¸göKÜCáÄ=9%q÷úžu®YÍ׸mÜ>t8ðÎÝòw 6üÈ)à¾_@œ]ƒÄmÐÜcì» E +=z——µ´õô­IQ÷\dP•/ ³µàˆn†¾é}Ðêhùdi›´KêŽKg¥ ’€¤T©YZ+í4’ÎIqIN¿ ,Äu겋е1ŒnƒËP½[ P3tXEù‰ûÀA‰{Z…Ñ°Ë“o3¸“;˱“árcRuéˆs, P&Lb€Ö¤›:^AþN„:ÉUl_¯³³ýÖ]ôV›·uxôƒ Beð.F‡Øg+µÊƒÊå5…›ÈL4ÿd¼a¤ðŒÀÉ&F@Šb6¿Î°N†aÁ Š™˜É‹Hå°+*#–…,èu™í" ^à89šœš¦bhÔ,DÓBùÂÚ`°ÍJhçÍfg>"*ÑÀë8ÞÅVÝUþºzž}œåÏt{] ÖâRQï  ì„Õjí 3xRöB3EÔ”WȤõ/dØää"Ý–'v8•¨©PY;¥P‰F +•´Üû',rYÐ,Àyú cÃd{ÏzòðO^y¥3V€ç=Éþþú'c‚3_ÏbÀV)øÌ.ð™“Q:ÍXìÃc„¨kŒoŒ6Ç>C[ÌTƒ_d¯ÖÚÅ% +âÆÀ»âïÜ6„¾3C iAêÛ2S¢æ)fƒOÂïÌCÔ\ÖF%.%‰KKqšÁ×u¡Cá6UÅTŒTU%ê¶ù(†RpaT.öÌó4yÖxXOI?˜mxÄÝFDfLêñEany·á +ë ô‚¾OÃCØa›>?ìÆW»¿ÌåƒÞœñ‹gš9ŸŒ:¶°³gÙéõÅÎ?|û{?è:ù®I­O|þ%&ÿg‡O>´•â£í «Y «Ê‹*˜°L +‡D®¹‘§£0Æ;Õûgå‰x3¡>ƒ®í'ÈoAôÿ¾hrml*ó;R§É…h…ÉÄ9sLaçDS‰“—’}É9¦ˆ3'Thâ¼Þ4Ö9K˜mª5}'ë² ådŒ ̘˜±-gWŽ0$8¤_qÎXÓØ`I¿Áýꄪ`U¿Šœµ9g2¾þ%ôM†Íãæ]]dgfÀ!`: +§jtV f´­Ew¬¬ŽŽâ«\’Pd·+/œ'‡½ÞÓ¬z¢ž +ÏZà÷v+£´Ôô—¬§¬g­q+›j-¶N¶2V_vN{0¿wþ˜ÎÓÙ1ð÷Ï_¢k°ç +Zž/.2æ*ZþÒ›¿|å—@˜)ñ/˜nÀ·½')850Ú1Ú3Ý1ÝSá¨ðüŒüŒyÐü„ú„_Í>y©cqKêHŸ'–)Š[Ù¨|BKÚ+ +¨’x)@]¤øÕµG]dFÔTlÚÉ<ûKvbïÂ׶â4T’$ÓWv«fŠF5e 2Ya¦(q…(ã`.ÐêèLÒV ì÷©=tyÜïÕWǽêÅó>:)Ùí÷ªÝ:„¼tsõƒéD€…ÒÖ8Gä]ç±E8S¬áÄÙi©ÙŸtÆêG¥\5+?¶pš™ž´ØšÌföìX²nÕR²øò¯÷][6Z„± +gA›ÙÀš¾}V&¬9lÎ71s΂À +d†<Í9=°Ts5R•³"p<õwÜïø>u|êüÆógߧÉçRã©îÔÔl‘»È?Áßœº-U@ÒÍÜÃIy)1uŽÜ Ï2/4Êîþ_´¨ØÅXLª%dØì +0&oFa›5¬ª§mXƒPa[kcmíöô—„SÂY!.°Wm‹›Ò;Cß­kÚê ôtU¼”Ä^b+Œ±ü^`(`|õtÓ°š“k~¿dÑïn«Øž{°G{nÉÒ'wß¼üÑl½üøNÌl™:ŠX¾Kìo¾þò+gÞ< 8Ûÿ‚¥³$ªŽ³ç0§XÓ¹®„ãŠS;RIjjZ /pm€b‚î h™èžè/Ëͳ­åî›ü‹Äzs­µÑÝè?žúžrÆsÆ÷±ãkÏ×¾Ot\ú4.ךëÈ[£ÜDënw&ù[ö;UQ]–'€3^À€2‹É›~Ú„USÔTaZkbMíØ–‡ò˜0!Ç1Þ†wá|³©¸OÆ ö¥Œë]Öh-*U{.êKº›’XÉ7P¯g¡Äš} +q©(”–Á8=WMÊõº³uÿü}-ÑØß~~l1ÉŸyÏÒçž\²ô9îhÏ·wO¾ûõ¶Ø7±wÆÛ_šyÇ[oœ~å-ÀÙ¦X­k;w*ú¤¢öW¯Q'¨l±Ö¡‘T­ŸJìœ|mr³¶M‡{†']ï¹>©L¼Q™ë™›´H\¬Ô© +žÅIǵwœx?ð¿“rÞy>åœ×Ü!6[Ív°ÃÕ±ìõêõSÓŸ“cªÉfaÜ}éÛ +¨B_úi«rT®×ʬ܎y$ÏFè?"+…ÿ¶ttÙ +¯F–£wÓírêÞG†¹ŠÃ6=1üÞÚͧ-9{óœ»ØžZºüÙ§ÛÛöÇ긟o™:uküÇc—ï˜8¼ç2óÄ['ßøý¯ÿôï3±ñmè-ˆ&’!¼z–ïÂS¢ÌA”/cº”ÁÀ⇠Ã'£Ä¢Æ.ðIv™ô‹åúö'ºúH¯T>ºÓ‚t‰Ã©O_=üÖ”aÞz«åŽH©¯òFˆ‘¨w󥡲к薚Zj“ÖK| ×,µ™nãn3ñn‰ñfd¥¸“%ÉaOÉÊê×%6¦¦¤Øèð3ÂÅŸ“œb¸DÙW\¢Iê¥ÄÚº±ñ,¤v.¤éëhÔY¾jc0\-$„ƒƒ“ð‘ +ƒ‡RÂÛId÷m n¸û†µ/oý_³nØõÆÞúHì}ÜpSdôœá3îÛÛË-;RsÓSyÇÖ.Ü_1ˆ™fs/(ßÔïò.A¶xì´ƒ¨7üä?sï€s‹>TÅT±mL;ˆ3 +˜ÂÀhf¼01¹$uLúØŒéL™07ù†ÌÛ–Ls$¤3á!ÖüИpIîmVhf¸Þ´È¼Ø²ÀYã]aZi^i]­.Io od¶˜n7o±Þ©nH¿-|¯y»u»+%œn1›¸  0Ix–!<§§AaIÿ»ýØßíFýU¬á)¸7ÓòàIwDÃýSRÜ —Ò_JŠø¯—"¨îçŒØqÂ!oPÕƦ†óÝê÷5WSξH'mžÄFBc!u*CSHÞ`cçfz†>}ÿãuFÖ£?=2÷ó¼_¯nzfú”¹#bõSëÞò·Ÿ>þ¯ÜQëÞ=ÃïÍ^»rãå‡_ý}þƒÚxç +׶)YòTf}¼¦éåêº7×Yî¸kÝ“óògŽ8´tÉ©¶ö/a V„˜¿‚?¢âe/XíØšæ+ä©OrØW8ǺÝ.î°±¸£oøWé6mEõs7óÁ÷Ÿ’Žž)Üѽ±á{{h›¡Í£úÎÔÉQ3GR@™ ýE©‹´ÔD_à5LréƇ°Þ2}+Þ‘PÒ´}ÝÊ?Su;RÜûyLm•8bÉì–XgÞ»÷»¿S +ÏŠƺ¹ã(½ÍäÌns‰y£™-±Ý`[šÄLs׫‹œÕî%æÎæ-ÎÛ“ž4Ëœ¦ï[4Ñß&`2+˜.õF¡²1ýœÜŒ :ÅÅz’'ÔFÓ])ŽMég¶·ÍÓšok…¶ˆ>»Áts5‰lëïíÂÃøÞÁt¢W˜®,›çkg?˜bè]¸Ll¨Öâ•­ؘ²iéÛoAgn†^1îÆ:ðÕ š‘Y©÷-^³ï±ÕyvS[×ÆEu[Á¯ž_þúâÕ·n‹}ñîËq|›wǦŽ[W=ê|„,_]uëúõÚ¡W¨ž÷Ѐ”Ÿßu<öíg€†GãŸsiú®Ï–¨±Îfg‹¯‰¬¾‰Óípåç³#DðyÄ¥Ö§¸/¬‚‚ètþ‹Ñ/9#¤\scÍ=ÅMè§)kÝŒÛÑd,ë_¡@Y¹ÜE×å€Ë²Ë»KÕòò–Kúw%‰Ø<Æ A8Ilr£ÛVõáÛØŠձ˿ûMì»æãö®~÷0wôûýľü.lþ’™üý—Í?¡¯œ¢Q@ÌE¤|ŠsÒÌR\ +ÎK?×LÍÛ|gb‡úÊ-í›Cçu€½F‘~¸ëÐ!ZËÐøçL¥î”FÕ²o'KøÍæÍ °¬Ÿ?dS¬’‘e1b*×XsDSÖ#h‚ý°>¥M·ñ^¢û™a€ÝÅÔ¸ôÔ·á&æFìš«Æ/Êv;wÔb¯9Üðb¬§ç9o]3÷6—áøG±:p¶þ ¶ÔU€óÁ‚‚ù=J7Ÿ½Ö“Ë™Êî‰ÕÝz+ý:é±ØT<\_÷´£ÑRcn›Çmä8ÈqË–s ( kãL]5ñBÀfÝ~¶ÇãWsX–·™pª©Ø4ÙĘ|çÞ+Äu‹5IÕ·†£âR}b„Zª¾¥Y[^Þ&UL|ThUkDTå$,Y„Ä2t8]·Å ŠZbªý6vÆjÓ†¤Ò™7êþñì—o¿ý¯›wXÆßËν¼ëdi5Õr«bSIXb]•3¬©vATÕ.œwí´wæEmÂNËMˆQ0¿Ìs¶‡·ê¤êWàRbߥŽxõCóÀ¼S1>{ßoJç[·"ãšô06õþ'¶üåLÏåÓe[¶¿øóXjLûQûJ&ÉT‰$«Ù%Úy'ƒi¬h's“Õ’ +é9ûnßB6ºƒ7’‘Gwz«¤Žì´k2V®;6§ôPðþèØ‘í[æüörÏ™¿Äþ¡õ'@©WhBµtÝõx4ü9–I‘ä]òi™È±9Q%[¾”&1%8Vÿàò¢rE3cÍ<ÅL·ˆ°Ô,oQ/eëkUå—ú6h–Œ¬¯Vé&)¸>q‚|wâDÏíyŠÌùn,9ØSJÝ9„„¥ôÛx¼5:¦ŠØúÙ#ÞB4ÄVhâÆÙÆÛÇyg£l³í7xÕĬôÇÉèè«lRÉl±Z§Ãn§?QæuuÅ‹rÈ«Ñ»b·Ñ{tŽK”4ºFKì…ñr¢˜âò:].¯]‘¤—@»M±Z5ÕæTU›]RD¯‹³ÚTðŽ9—Â1^Õ +£þI/ñÚí6ýÀëê( OERàê‚3Š8<õ°F?ñùºðûïäý¾RˆÉ{z 8÷ê_EüÇý0½`|/÷?oˆ¡{ÑÉ^èê h:+h:UˆvÙ 6"¡þ˜uEý¡„Þ´@ÊA%ÊE« ­}ßÃÍžX3aú ÆÄn~õlº˜Œ=_ývr(Ðÿ³_Æ_Œ½‘!xœ±×À°ßߟә{ü±¯ÿ~G'óüwcÙò­Z͸Ë#ý·4ÈÛ_ÏýÜŸæY‹¾“Dý—yû$#«÷Wz¨èw>lîýéà’‘±Ihô•óùÑO¶ä!‰{=ʶ¡ ,B~€øzRˆÒ¹Yñ€oƒsœcÈ3h¼_À?£?o‚üÅp? yÂ}&œEpN§¿Ñ÷JÈû…¹Yˆ˜ø%ü*Ú '­Óg©Qn;œ×B}Sà <δ +(ó ”ßç\xg…gû Ú +ç@x?‹öú5 +Þ +å Qƒ^B›!¿'Œ%þ~5þäYEOÈÿ„p'•4;ñr+¹Äü½†íæÚ¸n~ÿžP+ÄÁrÿB¶È9òQÓ<Å Æû)ó 8¾´ÖZ¡ªê|õ_¶íöaö +‡×ñ¬s§«ÐõŽ{±ûiO–çïÞw|S|[|'ýþ7ýß$$ lJÞœ’œÒš²5å»Ôá©+ROjÇ JŒDÃÀbд[.ºð¦È=F m,3 !ã}L¿2z9YbôR,0ƒnÂnf‘ŒÛ +„ßbÀ<äßnÀ:‰Ÿ0`EH­Kh ¹Ë€eöã5`š/œ1`-‹ ØÌwŠ°͵Îêã±5Ö ,¦2`‚uˆ3(W½Æ€YÈSoÀRÔæ!ÿjÐ|u½‹È¡~fÀ*QÿeÀ2©´4`äØÙ÷+yŽÓlfæ8¶ žrè f)ÖÏ:ÌQŠxî×a^OZ‡=ý ‹:üK–(<ï0ÐÈû¶¼ï0ÐÈû¥|ã hä›jÀ@#_|Ë häaÀ@#¥ü6` Qê^iViK h”ÑO‡e:®Œ +:l¢cɸG‡=ýQ¶èp¢N•Ž%ãˆ;¶g¼ªÃN=Ï{:ìÒëùT‡Ýzú·:ì£e3±'Ñ<™‰¾%Ó<™©:œªÃÙ:œ®çªÃY:\¢Ãý©ddN§°¨÷߀õ¶2çQXI¤/Öa},™ËÐ ´5£´U¢*¸khœ3P­—¢&Ôg»‘KÙ„Z¦×JH¯ÓshRå4FO¯üYSn_Ï44ÞÔ£%}yÚ m<Üí +B…p Dý +h°ž: +JÔÃ}”Y}h×KMƒúÚàlEKáZ +¹Zá}%ä¤oBõðÔúo½~UNíGy‡£Yzm}# =W +eBMuÐÏVxÓ稱ßUuýW%¯ä(<\yz^Ç(ÅW5”lÐÛ_ i´æÿ{\kJGT=i×{Dq£Á3ÍÓnÔ:è ¡)zy +EôöJá:Ú^ ã¼òÓr5P+Åò2½$­mÀèS‚¾MÐ.íS3ä]ñ_æªÑùŠæ[¦÷ja_»u×ö×é҄潞¤¿©Õ9§z“Ó×÷VýMΡÓáºDïu‚ n¢­÷¤]Çr/ÞZ¡/äª4x0ÁIu:î«u΢¼Ö¨·u5¿TuUê}£%ôi¿k¡ý½Æö5½×•z{U5oh¯Û zTêcL”[ÑGÿ:ƒË› +Öè¸iÓ9/1º^ +Uý_¢·¦é-\Ý«^ÊSÜÐçezݵWqÍۤוh»7=ív#U§¶ý[¾v¨³FÇJÜuW)KtLSŽºÂÓMºÄ¶ê­×ËÓžRz6¥z[¨ÒË/5Z­3Fš=ZÃ,,Ðe¸ÞH½‚×:»MÆHêôüKô§+TmÓ¹´^ïÝæ‰^ÚÖ7ú®A¯ïJT7,6z[ià¿J×vš!¥½8«ÖÛ^¨§&ÊS «3hX«Ë]³Á#Mp¥½ÔÀv¢†+Z¾R§U‚;4‡UÆøëtªÕëyšuÙKpc£^21’«¹»®³¨ä/7(Ó ÷†òæRC¶z§¾¯ +úÓîmÿ‘%jûÑøªŒ6æë5,Ñ1]ýÞ¬A-Þ‹Ù%úï÷ŽpÎÛšÎËuܶé|×Þ§OT§}OÈ{»¡5ÒÔfpÙí™xÛ S¤­ÔË'zMë­Òß^á´DëÕ:¶šu)YÑ7ŠÞ¶uIßWê˜h5Ú 2”Àb»^¾·Ç½µ7ë<Ô ëÍÞ¾ +Ðm^;¼¶4ê¥Ç=×Õv€® G­.Kõ5Ô¨S¨FjCótHP|@_Îÿo[X¦sL"oÍU­LM?ìýX8GçQx2¤R 0®õôH™WÊ›ãÀ”ÀQª§Î@f}G»¬ë’:C>~ìõô¦'ä$ÑfçWxôgÅ®P¦W#÷Òy¾þvä_Ò×fUŸnKðó{tµ¶LhŽ+z4!¿u†Îl3dz¡^KMŸN¤ÒZf´F¥{©¡Kç÷Y£D›íÿ +fzuç²>íTcH\MO·êú£Ýç?þ'|õJ!ÅXÍUµ\‘âo¯Ú°€”çëš1Ñëùešÿ…2ôQýS üï\ñï-÷ê6ªÅ*u´Z­7°ÝfèÿªmŠý™rEÏ®ø7ZÔ^ÆÕ>WB{Wê=jÖ1[gx:ÿšk/6^¥ÛzÛ¥š¤ZÇtÝUV¤õ*9§/wëU|{Åvÿ÷˜¢½kÐëï嫦Ô·L§ÿbšWû¡½úñJÎ&È›ðP—è§õ×ö'ѯ«¹»ÁШ ü'¤ªÙà+š÷‡<ôßè +Œ×Çþï”ëõ½¨Í©1<´Ähþ^•NÕÆÑ õGø¾Rs›î­R¤Ú°CKußhºÚ»úŸ©ß[_«áÿÕ±ÎòâþŽ l]ñX«ô:ÿ]Ž{)Vù#\/ø?êí,ÿ{ ?´÷?ìQáŶƒíé­Æ'£P"È> +…XKƒë xêb>œ%˜‰&9ê¿éŸGŠòथ† ˆèIkÿ?³uÿ÷–±÷]î°×gg¬h®YPYU£íÑfÔÖh¥MMí¤njmnj­l¯kjÔšë«hc*Û+ÿ‡L¹´2mzSýšÒ¦o„rƒ + ö‡ËàÚ¨úzmZÝÂÚö6mZM[MëÒšêQ­u•õÓj.©¯lí­v¸ž¨©ÃgÕ´¶Ñ6XË,­«jmjkZÐÞOÏuõK=¡t†~Û­Íh­¬®i¨l]¬5-øo{­µÖ,¬kk¯i­©ÖêµvÈ:sº6¥²]‹h3JµÉ  Ð*«µšú¶šeµm@_M0Þ¦…­•Íµ+®NªÑÆ´V.«k\HËÖjûkÓšæCÕ“êªj›ê+Ûrhí­uUu•ÚôÊ%Õ0@Ó°Á£›ÛkhßZWhm•€A@RÝ­º¦­nacŽ–ÀK䪬ƒ— +M­5Zí’†ÊFè¾VU[ÙZYÀ‡ºª6Ge£ïVÐñ×Ê›a€5U5mmMÐP%Ô¿¤ªV«3ª¢ƒ_ÒX£-«k¯ÕÑÐÐÔTMKSºÝ©¤¶õ¦µ/«il¯«ÜU,i]1@Ó1Ý´´¦µhÝÞZSÙÞ¯hª%@ï6Ú¥^M«Þ…KêëÔû +Í74A#uÕKÚÚõ¡¶µ¯¨¯¹”SÛh+5­ +uzŽÖ¦ÅPm%ô¿j 4” `u]åÂ&ú~Y-à\«­©oŒ4i ë–Öèt–¯ÔêZC +à®±® +²W67׫j ‘ºë(²´šå0˜†šúŒ­ +x§žÖÑPW¯£·Ý¢6£½*(1¿F[Ò,¥c³¦e íì’*ŠmA j„Aµ·S>¡·ÖÝÛ5€Lm€2=ᱡraåʺF¨º¦½*'4(^]×Ö\_¹‚6AK7Ö,kk®l†®A–jèb{]­˜fonmjhÒkPÛÞÞ<<7wÙ²e †PÕÔ[ÛÞPŸÛÐNÿožÜ†¶y•tàhâÿ²À²šzH­Ñ‹Lš‚q\iŸÂ‘g¢‚"¦x9¦ÞÛCÑhæVÔ}Ú[jyy(–3soSOF†ã‘>xX$¹?÷6õÀq᳧–z>Y;Ü;¢ÆNDû‡°é<Øs£x\xÏâ>¯;ò=*ÆV¬îÏ5jxèÙ!Þ!T"xã#£Çb¦“ +‘#ãØPã}ÃC±A^Ê2‡ûY8*Ú©:qJ5סՉñØ{d¥s|÷úF<Õ`ß뎷z0jµ[cƒ#ñᬡ“CÑqs»z ûœ‡™ŒbXÙâ–ûˆf‰µleŽyÇ"V«¬]¬hòrkÝ[¡žÈX'èàŸÀuµ¾Íªo{ÝÖšÚššìì!DÖlß^[ éÛáS}Oî¬ßYŸ›óU÷_#U[Íë·ª#â&_”ó[´S4ÿøâàŽ¸lXJë—Aü&‘_´ +H—¤)é—Ò0#ÍJ?ËégŽôIæH?s¤Ÿ9ÒÏégŽô3Gú™#ýÌ‘~æH?s¤Ÿ9ÒÏégŽôÿôWÝù¯ØÁ_+íöçòDW ˆS‡”9,<ü¾°ÍeÛn ÙZm»!ëWÕÀ÷à‡•ò±føÞcö~ôÇëâáyÖ¶—?ËKÒ›ø/?<ø +”“<©ˆ,i@" +d5ÐôÀ$%x©ü@0 Ì‹€½édïñO Ém?ÀØ{Nö.ºõ.d» ë&»‰¦ý9á«÷ÎÃSmJ¥e•XFA¡7Åþ”¸·YI±¿%Ur9Pî`¨ì: +¿NT èNY°nÀºAtàEà2`YÈsyn Ïð6pƒÔÐ8Ø; T“b×îf%PÈþÈ~KŠ0¨`¿úmö¦Ð¿g¿ú-hô{3áRH`Ò ò8¡ÐÕH„ý*YQ ¤ùlã@V~  +è&€,6Ç6&”r…,8˜ rG蟗D;ªhî§àc*î†Ý° &ÕI7ÓÜ€ î /ÁâÂýíïÀâÂýͳ°¸pŸ„Å…{à(,.܇z`qánë„‘b?úEÅ&Å×vŒª<6ŽQÇ(c”Ɖó7¹gãmûa¢ª +#vIól®RôYª¿AõýT™êQªŸ¦úYªï¢úaª{¨.SÝEuêWh†B§ÚÏWëµbª/Pý5ªÇ¨î¦z%Õ+¨®RŸ–be‰½;„j*àë +zw“7m,È–Á­Ë°ìç ¯iÒ@R7šä/º¸Þ˜¬ò›ám +Þ‘À6Œó˜†yò!`ÃÍÃæQÿtz¤è®‹@È{#>!dd5àz€3À"%š³02b5ñuÑ°j«Ñm<ÄæñæOS/ceZ©Svzœ{¤ ™æ¹h›+íb>RÈ¿PïÈOÑÜéÏrÿýY.Éd³ l‚”b"^´ôDâ^©’¢ßO¸¯(Çè÷ˆË¯£õÄM+¡ëHL„wÙÁu-‘Ù«ÐÞ„|Pá_cuoQfézžkZ¹'ÿ]¹#§ÌÈW”¿ª)M(AÌ«ÓÊuù¼òVuʘ7Ü) +5« +êŒ\§¼¶ ¨g‘p)¡œæjZù–ܪ“EBÔL8CHËSö»){P^PîS´ÊœVüòae—ÉÚÉóL+5h‚Ç4«ÐØͲ¨´Ü% +<àKÑAm‹ý¢½ËÞfÒîµo±—Ù{©½Ä¾ÁQàp:Ö;uä8Ž,‡ÍÁıÿœƒ‡¹bC–Sü’³K›°ŒKf~Ï„Q#Oã Rˆ…:šiȸÚOB}ªñ¯ŽòÍÙwÈx¤¼™!êl6ê<¡”=½ßðyB†½ýk]S”^#Ö`Ï¥(éìJÑ4:WÂ=C(Í?÷B ×Oœ{!&Å…'ýÅþ‚¦üú/×½–¼ïÑ‹Å«ìRãb¨£ËøiiØðr#]ßåÏŠž¡ŸÒOZ‚3ô.Wᮩ‰~Ú²ŸÇKMÁp8”¢¨ô.x𘻂çp•óˆêp™¼K&¯ùÁ«à +¼ìlR)x•ÙÙ‚g£œ7«h NUTN.='V¤ÞÏY¨§²Rp +u² 8 …:çM‚"Ë ¸dA¡YPdú¸ \¡T[”óË”ó¢&‰®pd““{k‰“{ ÏÿúŠ6{<4ÙîïæÏÙî-o‰½Æó'‹ +½OU§úÃָݽ}ýƒ\G¢F¸<4ú˃êTc÷ÉÝ<¹±<8Eº[:»¦ºµh0Ѩ5¶”G‚ádk{­oU]ç—ëªm_£°v^X-¯«Õ·F²'·òº|¼.¯«Ukuáãí]SÒ~ªÛÔI¶.þÚ[Rn.tžhÎÛXV|ºd$¯už°ñhy³‘ 𤭭ž„5Å“Öó‡©[IŧËJfé+V’ÑùåÍÄ3ÅIqËPÐü‹á…¨±8pSzb{!­ÅÐ"ÁØ!!£ª#dø÷êš²ÛÛË»d4,Å­[×’J_5#·!²GJÒ2‘ÇíâqÙÙñÁù[Z|§^gW’TsQÜÔ…%ÃêdØ +:­§VÏâr‰ÿ{ˆ…ÑÁõÐØR¢ÙÄ´ ïïÆâ–eØ¥Í\È[Žåò`«úIjj +endstream +endobj + +110 0 obj +20828 +endobj + +111 0 obj +<> +endobj + +112 0 obj +<> +stream +xœ]“ÁnÛ0Dïú +ÓC ‘¥08v ø6¨Ó%ÚPK-ü÷áì0-Ѓ„!9»|\róÍ~»‡%Swð‹: +cüuº…Ϋ£?c¦ê‡nI#ùw—vÎò{¸_Ù§iµÊòŸqíº„»zX÷ÓÑËò¡÷aÏêá×æLJÛ<ÿñ?.ªÈšFõþó¼µó÷öâs‰zÜ÷qyXî1äŸáã>{ed¬‰ÒM½¿ÎmçC;ž}¶*ŠF­v»&ócÿßZ•BŽ§îw¢UGkQ8ÓDmDWÚŠ®+èRtYB;z4tEÌ×ôÈüç%Ï3ýOÐkêô =²ï†±zKÏú•úzG?<ºm±—&¿G“ßÐä·È¯ÉoÁ ÉoÀ ÉokèÄ/yÈo$ùÝ34ùkñ“¿”yòW¢ÿšüõÑä·¨§Iüðò—ð›Tä7ä¯p^CþZü©þÈiÈ_ጆü5˜Mâ—œä/ÅC~'9SýQ“ø…ü¥hò;Ù+ñ#Ö’ßá~mª?îË’¿\C“¿ÄYlª¿øÿ 4ùö²äwà·äw¸#›Þä$¿³%¿AMlz?2O~WËãO¯m€>ýj/ÕÝBˆ­%Í,=…nFÿ·ßçiF”|Ÿ´ùþ +endstream +endobj + +113 0 obj +<> +endobj + +114 0 obj +<> +endobj + +115 0 obj +<> +endobj + +1 0 obj +<>/Contents 2 0 R>> +endobj + +4 0 obj +<>/Contents 5 0 R>> +endobj + +7 0 obj +<>/Contents 8 0 R>> +endobj + +10 0 obj +<>/Contents 11 0 R>> +endobj + +13 0 obj +<>/Contents 14 0 R>> +endobj + +16 0 obj +<>/Contents 17 0 R>> +endobj + +19 0 obj +<>/Contents 20 0 R>> +endobj + +22 0 obj +<>/Contents 23 0 R>> +endobj + +25 0 obj +<>/Contents 26 0 R>> +endobj + +28 0 obj +<>/Contents 29 0 R>> +endobj + +31 0 obj +<>/Contents 32 0 R>> +endobj + +34 0 obj +<>/Contents 35 0 R>> +endobj + +37 0 obj +<>/Contents 38 0 R>> +endobj + +40 0 obj +<>/Contents 41 0 R>> +endobj + +43 0 obj +<>/Contents 44 0 R>> +endobj + +46 0 obj +<>/Contents 47 0 R>> +endobj + +49 0 obj +<>/Contents 50 0 R>> +endobj + +52 0 obj +<>/Contents 53 0 R>> +endobj + +55 0 obj +<>/Contents 56 0 R>> +endobj + +58 0 obj +<>/Contents 59 0 R>> +endobj + +63 0 obj +<> +endobj + +61 0 obj +<> +>> +endobj + +62 0 obj +<> +>> +endobj + +116 0 obj +<> +/Lang(en-US) +>> +endobj + +117 0 obj +< +/Subject +/Creator +/Producer +/CreationDate(D:20111229185020-06'00')>> +endobj + +xref +0 118 +0000000000 65535 f +0000229984 00000 n +0000000019 00000 n +0000000387 00000 n +0000230147 00000 n +0000000407 00000 n +0000001556 00000 n +0000230310 00000 n +0000001577 00000 n +0000003506 00000 n +0000230455 00000 n +0000003527 00000 n +0000004985 00000 n +0000230602 00000 n +0000005007 00000 n +0000008534 00000 n +0000230749 00000 n +0000008556 00000 n +0000012065 00000 n +0000230896 00000 n +0000012087 00000 n +0000015016 00000 n +0000231043 00000 n +0000015038 00000 n +0000018146 00000 n +0000231190 00000 n +0000018168 00000 n +0000021400 00000 n +0000231337 00000 n +0000021422 00000 n +0000024912 00000 n +0000231484 00000 n +0000024934 00000 n +0000028041 00000 n +0000231631 00000 n +0000028063 00000 n +0000030789 00000 n +0000231778 00000 n +0000030811 00000 n +0000032434 00000 n +0000231925 00000 n +0000032456 00000 n +0000033623 00000 n +0000232072 00000 n +0000033645 00000 n +0000035097 00000 n +0000232219 00000 n +0000035119 00000 n +0000035958 00000 n +0000232366 00000 n +0000035979 00000 n +0000039173 00000 n +0000232513 00000 n +0000039195 00000 n +0000042269 00000 n +0000232660 00000 n +0000042291 00000 n +0000044994 00000 n +0000232807 00000 n +0000045016 00000 n +0000047661 00000 n +0000233187 00000 n +0000233327 00000 n +0000232954 00000 n +0000047683 00000 n +0000066767 00000 n +0000066790 00000 n +0000066985 00000 n +0000067489 00000 n +0000067839 00000 n +0000083753 00000 n +0000083776 00000 n +0000083976 00000 n +0000084358 00000 n +0000084605 00000 n +0000105540 00000 n +0000105563 00000 n +0000105773 00000 n +0000106244 00000 n +0000106576 00000 n +0000126519 00000 n +0000126542 00000 n +0000126737 00000 n +0000127256 00000 n +0000127624 00000 n +0000146653 00000 n +0000146676 00000 n +0000146880 00000 n +0000147353 00000 n +0000147679 00000 n +0000182245 00000 n +0000182268 00000 n +0000182468 00000 n +0000183094 00000 n +0000183571 00000 n +0000195274 00000 n +0000195297 00000 n +0000195491 00000 n +0000195970 00000 n +0000196296 00000 n +0000204767 00000 n +0000204790 00000 n +0000204990 00000 n +0000205357 00000 n +0000205587 00000 n +0000207032 00000 n +0000207055 00000 n +0000207248 00000 n +0000207540 00000 n +0000207704 00000 n +0000228621 00000 n +0000228645 00000 n +0000228837 00000 n +0000229396 00000 n +0000229798 00000 n +0000229927 00000 n +0000233507 00000 n +0000233651 00000 n +trailer +< + ] +/DocChecksum /D462BA05E1776A1A510440C7D26CE5D4 +>> +startxref +234123 +%%EOF Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/adv_jtag_bridge.odt =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/adv_jtag_bridge.odt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/adv_jtag_bridge.odt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/adv_jtag_bridge.odt (revision 66)
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/adv_jtag_bridge.odt Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/ajb_block_diagram.odg =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/ajb_block_diagram.odg =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/ajb_block_diagram.odg (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/ajb_block_diagram.odg (revision 66)
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/src/ajb_block_diagram.odg Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/License_FDL-1.2.txt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/License_FDL-1.2.txt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/License_FDL-1.2.txt (revision 66) @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/gpl-2.0.txt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/gpl-2.0.txt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/doc/gpl-2.0.txt (revision 66) @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_parallel.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_parallel.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_parallel.h (revision 66) @@ -0,0 +1,26 @@ + +#ifndef _CABLE_PARALLEL_H_ +#define _CABLE_PARALLEL_H_ + +#include +#include "cable_common.h" + +int cable_parallel_init(); +int cable_parallel_opt(int c, char *str); +void cable_parallel_phys_wait(); + +jtag_cable_t *cable_xpc3_get_driver(void); +int cable_xpc3_inout(uint8_t value, uint8_t *inval); +int cable_xpc3_out(uint8_t value); + +jtag_cable_t *cable_bb2_get_driver(void); +int cable_bb2_inout(uint8_t value, uint8_t *inval); +int cable_bb2_out(uint8_t value); + +jtag_cable_t *cable_xess_get_driver(void); +int cable_xess_inout(uint8_t value, uint8_t *inval); +int cable_xess_out(uint8_t value); + + + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hwp_server.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hwp_server.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hwp_server.h (revision 66) @@ -0,0 +1,32 @@ +/* hwp_server.h -- Header for hardware watchpoint handling + Copyright(C) 2010 Nathan Yawn + + This file is part the advanced debug unit / bridge. GDB does not + have support for the OR1200's advanced hardware watchpoints. This + acts as a server for a client program that can read and set them. + + 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 _HWP_SERVER_H_ +#define _HWP_SERVER_H_ + + +int hwp_init(int portNum); +int hwp_server_start(void); +void hwp_server_stop(void); +int hwp_get_available_watchpoint(void); +void hwp_return_watchpoint(int wp); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/autogen.sh =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/autogen.sh (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/autogen.sh (revision 66) @@ -0,0 +1,10 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset +set -o posix + +set -x # Trace the commands as they are executed. + +autoreconf --warnings=all --install
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/autogen.sh Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_jtag_bridge.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_jtag_bridge.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_jtag_bridge.c (revision 66) @@ -0,0 +1,617 @@ +/* adv_jtag_bridge.c -- JTAG protocol bridge between GDB and Advanced debug module. + Copyright(C) 2001 Marko Mlinar, markom@opencores.org + Code for TCP/IP copied from gdb, by Chris Ziomkowski + Refactoring by Nathan Yawn (C) 2008 - 2010 + + This file was part of the OpenRISC 1000 Architectural Simulator. + It is now also used to connect GDB to a running hardware OpenCores / OR1200 + advanced debug unit. + + 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. */ + +/* Establishes jtag proxy server and communicates with parallel + port directly. Requires root access. */ + +#include +#include // for exit(), atoi(), strtoul() +#include +#include +#include // for strstr() +#include + + +#include "adv_jtag_bridge.h" +#include "rsp-server.h" +#include "chain_commands.h" +#include "cable_common.h" +#include "or32_selftest.h" +#include "bsdl.h" +#include "errcodes.h" +#include "hardware_monitor.h" +#include "jsp_server.h" +#include "hwp_server.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +// How many command-line IR length settings to create by default +#define IR_START_SETS 16 + +////////////////////////////////////////////////// +// Command line option flags / values + +/* Which device in the scan chain we want to target. + * 0 is the first device we find, which is nearest the data input of the cable. + */ +unsigned int target_dev_pos = 0; + +// Do test before setting up server? +unsigned char do_selftest = 0; + +// IR register length in TAP of +// Can override autoprobe, or set if IDCODE not supported +typedef struct { + int dev_index; + int ir_length; +} irset; + +#define START_IR_SETS 16 +int reallocs = 0; +int num_ir_sets = 0; +irset * cmd_line_ir_sizes = NULL; + +// DEBUG command for target device TAP +// May actually be USER1, for Xilinx devices using internal BSCAN modules +// Can override autoprobe, or set if unable to find in BSDL files +int cmd_line_cmd_debug = -1; // 0 is a valid debug command, so use -1 + +// TCP port to set up the server for GDB on +char *port = NULL; +char default_port[] = "9999"; + +#ifdef ENABLE_JSP +char *jspport = NULL; +char default_jspport[] = "9944"; +#endif + +char *hwpport = NULL; +char default_hwpport[] = "9928"; + +// Force altera virtual jtag mode on(1) or off(-1) +int force_alt_vjtag = 0; + + +// Pointer to the command line arg used as the cable name +char * cable_name = NULL; + +//////////////////////////////////////////////////////// +// List of IDCODES of devices on the JTAG scan chain +// The array is dynamically allocated in chain_commands/jtag_enumerate_chain() + +uint32_t *idcodes = NULL; +int num_devices = 0; + + +const char *name_not_found = "(unknown)"; + +/////////////////////////////////////////////////////////// +// JTAG constants + +// Defines for Altera JTAG constants +#define ALTERA_MANUFACTURER_ID 0x6E + +// Defines for Xilinx JTAG constants +#define XILINX_MANUFACTURER_ID 0x49 + + +/////////////////////////////////////////////////// +// Prototypes for local / helper functions +int get_IR_size(int devidx); +uint32_t get_debug_cmd(int devidx); +void configure_chain(void); +void print_usage(char *func); +void parse_args(int argc, char **argv); +void get_ir_opts(char *optstr, int *idx, int *val); + + +////////////////////////////////////////////////////////////////////////////////////// +/*----------------------------------------------------------------------------------*/ +// Functions +///////////////////////////////////////////////////////////////////////////////////// + +// Resets JTAG, and sets up DEBUG scan chain +void configure_chain(void) +{ + int i; + unsigned int manuf_id; + uint32_t cmd; + const char *name; + int irlen; + int err = APP_ERR_NONE; + + err |= tap_reset(); + err |= jtag_enumerate_chain(&idcodes, &num_devices); + + if(err != APP_ERR_NONE) { + printf("Error %s enumerating JTAG chain, aborting.\n", get_err_string(err)); + exit(1); + } + + printf("\nDevices on JTAG chain:\n"); + printf("Index\tName\t\tID Code\t\tIR Length\n"); + printf("----------------------------------------------------------------\n"); + for(i = 0; i < num_devices; i++) + { + if(idcodes[i] != IDCODE_INVALID) { + name = bsdl_get_name(idcodes[i]); + irlen = bsdl_get_IR_size(idcodes[i]); + if(name == NULL) + name = name_not_found; + } else { + name = name_not_found; + irlen = -1; + } + printf("%d: \t%s \t0x%08X \t%d\n", i, name, idcodes[i], irlen); + } + printf("\n"); + +#ifdef __LEGACY__ +// The legacy debug interface cannot support multi-device chains. If there is more than +// one device on this chain, pull the cord. +if(num_devices > 1) { + fprintf(stderr, "\n*** ERROR: The legacy debug hardware cannot support JTAG chains with\n"); + fprintf(stderr, "*** more than one device. Reconnect the JTAG cable to ONLY the legacy\n"); + fprintf(stderr, "*** debug unit, or change your SoC to use the Advanced Debug Unit.\n"); + exit(0); +} +#endif + + + if(target_dev_pos >= num_devices) { + printf("ERROR: Requested target device (%i) beyond highest device index (%i).\n", target_dev_pos, num_devices-1); + exit(1); + } else { + printf("Target device %i, JTAG ID = 0x%08x\n", target_dev_pos, idcodes[target_dev_pos]); + } + + manuf_id = (idcodes[target_dev_pos] >> 1) & 0x7FF; + + // Use BSDL files to determine prefix bits, postfix bits, debug command, IR length + config_set_IR_size(get_IR_size(target_dev_pos)); + + // Set the IR prefix / postfix bits + int total = 0; + for(i = 0; i < num_devices; i++) { + if(i == target_dev_pos) { + config_set_IR_postfix_bits(total); + //debug("Postfix bits: %d\n", total); + total = 0; + continue; + } + + total += get_IR_size(i); + debug("Adding %i to total for devidx %i\n", get_IR_size(i), i); + } + config_set_IR_prefix_bits(total); + debug("Prefix bits: %d\n", total); + + + // Note that there's a little translation here, since device index 0 is actually closest to the cable data input + config_set_DR_prefix_bits(num_devices - target_dev_pos - 1); // number of devices between cable data out and target device + config_set_DR_postfix_bits(target_dev_pos); // number of devices between target device and cable data in + + // Set the DEBUG command for the IR of the target device. + // If this is a Xilinx device, use USER1 instead of DEBUG + // If we Altera Virtual JTAG mode, we don't care. + if((force_alt_vjtag == -1) || ((force_alt_vjtag == 0) && (manuf_id != ALTERA_MANUFACTURER_ID))) { + cmd = get_debug_cmd(target_dev_pos); + if(cmd == TAP_CMD_INVALID) { + printf("Unable to find DEBUG command, aborting.\n"); + exit(1); + } + config_set_debug_cmd(cmd); // This may have to be USER1 if this is a Xilinx device + } + + // Enable the kludge for Xilinx BSCAN, if necessary. + // Safe, but slower, for non-BSCAN TAPs. + if(manuf_id == XILINX_MANUFACTURER_ID) { + config_set_xilinx_bscan(1); + } + + // Set Altera Virtual JTAG mode on or off. If not forced, then enable + // if the target device has an Altera manufacturer IDCODE + if(force_alt_vjtag == 1) { + config_set_alt_vjtag(1); + } else if(force_alt_vjtag == -1) { + config_set_alt_vjtag(0); + } else { + if(manuf_id == ALTERA_MANUFACTURER_ID) { + config_set_alt_vjtag(1); + } else { + config_set_alt_vjtag(0); + } + } + + // Do a sanity test + cmd = bsdl_get_idcode_cmd(idcodes[target_dev_pos]); + if(cmd != TAP_CMD_INVALID) { + uint32_t id_read; + err |= jtag_get_idcode(cmd, &id_read); + + if(err != APP_ERR_NONE) { + printf("Error %s checking IDCODE, aborting.\n", get_err_string(err)); + exit(1); + } + + if(id_read == idcodes[target_dev_pos]) { + printf("IDCODE sanity test passed, chain OK!\n"); + } else { + printf("Warning: IDCODE sanity test failed. Read IDCODE 0x%08X, expected 0x%08X\n", id_read, idcodes[target_dev_pos]); + } + } + + if(err |= tap_enable_debug_module()) { // Select the debug unit in the TAP. + printf("Error %s enabling debug module, aborting.\n", get_err_string(err)); + exit(1); + } +} + + +void print_usage(char *func) +{ + printf("JTAG connection between GDB and the SoC debug interface.\n"); +#ifdef __LEGACY__ + printf("Compiled with support for the Legacy debug unit (debug_if).\n"); +#else + printf("Compiled with support for the Advanced Debug Interface (adv_dbg_if).\n"); +#endif +#ifdef ENABLE_JSP + printf("Compiled with support for the JTAG Serial Port (JSP).\n"); +#else + printf("Support for the JTAG serial port is NOT compiled in.\n"); +#endif + printf("Copyright (C) 2011 Nathan Yawn, nathan.yawn@opencores.org\n\n"); + printf("Usage: %s (options) [cable] (cable options)\n", func); + printf("Options:\n"); + printf("\t-g [port] : port number for GDB (default: %s)\n", default_port); +#ifdef ENABLE_JSP + printf("\t-j [port] : port number for JSP Server (default: %s)\n", default_jspport); +#endif + printf("\t-w [port] : port number for HWP server (default: %s)\n", default_hwpport); + printf("\t-x [index] : Position of the target device in the scan chain\n"); + printf("\t-a [0 / 1] : force Altera virtual JTAG mode off (0) or on (1)\n"); + printf("\t-l [:] : Specify length of IR register for device\n"); + printf("\t , override autodetect (if any)\n"); + printf("\t-c [hex cmd] : Debug command for target TAP, override autodetect\n"); + printf("\t (ignored for Altera targets)\n"); + printf("\t-v [hex cmd] : VIR command for target TAP, override autodetect\n"); + printf("\t (Altera virtual JTAG targets only)\n"); + printf("\t-r [hex cmd] : VDR for target TAP, override autodetect\n"); + printf("\t (Altera virtual JTAG targets only)\n"); + printf("\t-b [dirname] : Add a directory to search for BSDL files\n"); + printf("\t-t : perform CPU / memory self-test before starting server\n"); + printf("\t-h : show help\n\n"); + cable_print_help(); +} + + +void parse_args(int argc, char **argv) +{ + int c; + int i; + int idx, val; + const char *valid_cable_args = NULL; + port = NULL; +#ifdef ENABLE_JSP + jspport = NULL; +#endif + force_alt_vjtag = 0; + cmd_line_cmd_debug = -1; + + /* Parse the global arguments (if-any) */ + while((c = getopt(argc, argv, "+g:j:w:x:a:l:c:v:r:b:th")) != -1) { + switch(c) { + case 'h': + print_usage(argv[0]); + exit(0); + break; + case 'g': + port = optarg; + break; +#ifdef ENABLE_JSP + case 'j': + jspport = optarg; + break; +#endif + case 'w': + hwpport = optarg; + break; + case 'x': + target_dev_pos = atoi(optarg); + break; + case 'l': + get_ir_opts(optarg, &idx, &val); // parse the option + if(num_ir_sets >= (IR_START_SETS< 0) && (retval != cmd_line_ir_sizes[i].ir_length)) + printf("Warning: overriding autoprobed IR length (%i) with command line value (%i) for device %i\n", retval, + cmd_line_ir_sizes[i].ir_length, devidx); + retval = cmd_line_ir_sizes[i].ir_length; + } + } + + if(retval < 0) { // Make sure we have a value + printf("ERROR! Unable to autoprobe IR length for device index %i; Must set IR size on command line. Aborting.\n", devidx); + exit(1); + } + + return retval; +} + + +uint32_t get_debug_cmd(int devidx) +{ + int retval = TAP_CMD_INVALID; + uint32_t manuf_id = (idcodes[devidx] >> 1) & 0x7FF; + + if(idcodes[devidx] != IDCODE_INVALID) { + if(manuf_id == XILINX_MANUFACTURER_ID) { + retval = bsdl_get_user1_cmd(idcodes[devidx]); + if(cmd_line_cmd_debug < 0) printf("Xilinx IDCODE, assuming internal BSCAN mode\n\t(using USER1 instead of DEBUG TAP command)\n"); + } else { + retval = bsdl_get_debug_cmd(idcodes[devidx]); + } + } + + if(cmd_line_cmd_debug >= 0) { + if(retval != TAP_CMD_INVALID) { + printf("Warning: overriding autoprobe debug command (0x%X) with command line value (0x%X)\n", retval, cmd_line_cmd_debug); + } else { + printf("Using command-line debug command 0x%X\n", cmd_line_cmd_debug); + } + retval = cmd_line_cmd_debug; + } + + if(retval == TAP_CMD_INVALID) { + printf("ERROR! Unable to find DEBUG command for device index %i, device ID 0x%0X\n", devidx, idcodes[devidx]); + } + + return retval; +} + + +// Extracts two values from an option string +// of the form ":", where both args +// are in base 10 +void get_ir_opts(char *optstr, int *idx, int *val) +{ + char *ptr; + + ptr = strstr(optstr, ":"); + if(ptr == NULL) { + printf("Error: badly formatted IR length option. Use format \':\', without spaces, where both args are in base 10\n"); + exit(1); + } + + *ptr = '\0'; + ptr++; // This now points to the second (value) arg string + + *idx = strtoul(optstr, NULL, 10); + *val = strtoul(ptr, NULL, 10); + // ***CHECK FOR SUCCESS +} + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.classic =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.classic (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.classic (revision 66) @@ -0,0 +1,183 @@ +prefix = /usr/local + +# Your build environment. selects libs, lib dirs, and include dirs +# Supported: linux, cygwin, freebsd +BUILD_ENVIRONMENT=cygwin + +# Set this to 'true' if you want to build for the legacy debug unit ('debug_if' core), +# leave 'false' if you are building for the Advanced Debug Unit. +SUPPORT_LEGACY=false + +# Set this to 'true' to include support for parallel cables +SUPPORT_PARALLEL_CABLES=true + +# Set this to 'true' to include support for cables which require libusb +# currently includes Altera USB-Blaster and Xilinx XPC DLC8 +SUPPORT_USB_CABLES=true + +# Set this to 'true' to support cables which require libFTDI +# SUPPORT_USB_CABLES must also be set to 'true' to support FTDI-based cables. +SUPPORT_FTDI_CABLES=true + +# Some Xilinx Parallel Cable IIIs will work just as fast as we can drive them. +# Some (clones) require us to limit their clock rate. Three schemes are defined: +# "sleep_wait": tries not to use CPU, but may sleep much longer than desired +# "timer_wait": does busy-wait polling on a timer +# "no_wait": does not wait, runs as fast as possible +XPC3_LIMIT_SCHEME=timer_wait + +# Normal error-checking on every word of a burst write can cause a significant +# slowdown, especially when using the USB-Blaster cable. Setting this option +# true will eliminate this slowdown, at the cost of per-word error checking. +# Note that this option must also be defined in the hardware HDL. +USE_HISPEED=true + +# If you have the JTAG Serial Port (JSP) included in you hardware, set +# the following to true to compile the JSP server +INCLUDE_JSP_SERVER=true + +# The JTAG serial port is normally compatible with multi-device JTAG chains. +# However, this can hurt performance when using USB JTAG cables. If you are +# using a USB JTAG cable and your JTAG chain has only one device on it, +# set this false to use a performance-optimized version. Note this must also +# be defined in the hardware HDL. +JSP_MULTI_DEVICE_CHAIN=true + +# Different optimizations have been implemented for different JTAG cables in +# the JSP driver. The default implementation transfers the least number of +# bits, which works well for parallel JTAG cables. When using a USB JTAG +# cable, set this to true to use a version of the driver that instead uses +# the smallest number of USB transactions. +JSP_OPTIMIZE_FOR_USB=true + +# ---------------------------------------------------------------------------- +# Most people shouldn't have to change anything below this line + +ifeq ($(BUILD_ENVIRONMENT),linux) +# These are for native Linux. You may need to put the path to libusb into the LIBS variable +# with the -L command. +CFLAGS = -g -O2 -Wall +CC = gcc +LIBS = -lpthread -lrt +INCLUDEDIRS = -I/usr/local/include/libusb-1.0/ -I/usr/include/ -I/usr/local/include/ +endif + +ifeq ($(BUILD_ENVIRONMENT),cygwin) +# These are for cygwin. It assumes libusb.a is in the current directory. +CFLAGS = -g -O2 -Wall +CC = gcc +LIBS = -L. -lioperm -lpthread -lrt +INCLUDEDIRS = -I/usr/local/include/ +endif + +ifeq ($(BUILD_ENVIRONMENT),freebsd) +# These are for FreeBSD. Only FreeBSD >= 8 is supported (assumes, that +# libusb(8) is present in the base system (/usr/lib/libusb* exists). +CFLAGS = -g -O2 -Wall +CC = gcc +LIBS = -L. -L/usr/local/lib -lpthread -lrt +INCLUDEDIRS = -I/usr/local/include/ +# We don't have a support for parallel cables on FreeBSD yet. +SUPPORT_PARALLEL_CABLES=false +endif + +ifeq ($(SUPPORT_LEGACY),true) +CFLAGS += -D__LEGACY__ +endif + +ifeq ($(USE_HISPEED),true) +CFLAGS += -DADBG_OPT_HISPEED +endif + +ifeq ($(JSP_MULTI_DEVICE_CHAIN),true) +CFLAGS += -DENABLE_JSP_MULTI +endif + +ifeq ($(JSP_OPTIMIZE_FOR_USB),true) +CFLAGS += -DOPTIMIZE_JSP_FOR_USB +endif + +ifeq ($(XPC3_LIMIT_SCHEME),sleep_wait) +CFLAGS += -D__PARALLEL_SLEEP_WAIT__ +else +ifeq ($(XPC3_LIMIT_SCHEME),timer_wait) +CFLAGS += -D__PARALLEL_TIMER_BUSY_WAIT__ +else +# no_wait is the default, nothing to define +endif +endif + + +PROGRAMS = adv_jtag_bridge + +HEADERS = adv_jtag_bridge.h chain_commands.h opencores_tap.h \ + altera_virtual_jtag.h rsp-server.h bsdl.h or32_selftest.c cable_common.h \ + cable_sim.h \ + bsdl_parse.h errcodes.h spr-defs.h except.h adv_dbg_commands.h dbg_api.h \ + legacy_dbg_commands.h utilities.h hardware_monitor.h hwp_server.h + +SOURCES = adv_jtag_bridge.c rsp-server.c chain_commands.c cable_common.c bsdl.c \ + or32_selftest.c cable_sim.c utilities.c \ + bsdl_parse.c errcodes.c adv_dbg_commands.c dbg_api.c legacy_dbg_commands.c \ + hardware_monitor.c hwp_server.c + +OBJECTS = adv_jtag_bridge.o rsp-server.o chain_commands.o cable_common.o bsdl.o \ + or32_selftest.o cable_sim.o utilities.o \ + bsdl_parse.o errcodes.o adv_dbg_commands.o dbg_api.o legacy_dbg_commands.o \ + hardware_monitor.o hwp_server.o + + +ifeq ($(SUPPORT_PARALLEL_CABLES),true) +CFLAGS += -D__SUPPORT_PARALLEL_CABLES__ +HEADERS += cable_parallel.h +SOURCES += cable_parallel.c +OBJECTS += cable_parallel.o +endif + +ifeq ($(SUPPORT_USB_CABLES),true) +CFLAGS += -D__SUPPORT_USB_CABLES__ +HEADERS += cable_xpc_dlc9.h cable_usbblaster.h +SOURCES += cable_xpc_dlc9.c cable_usbblaster.c +OBJECTS += cable_xpc_dlc9.o cable_usbblaster.o + +ifeq ($(SUPPORT_FTDI_CABLES),true) +CFLAGS += -D__SUPPORT_FTDI_CABLES__ +LIBS += -lftdi +HEADERS += cable_ft2232.h cable_ft245.h +SOURCES += cable_ft2232.c cable_ft245.c +OBJECTS += cable_ft2232.o cable_ft245.o +endif + +# libusb must follow libftdi in the list of libraries +LIBS += -lusb +endif + +ifeq ($(INCLUDE_JSP_SERVER),true) +CFLAGS += -DENABLE_JSP +HEADERS += jsp_server.h +SOURCES += jsp_server.c +OBJECTS += jsp_server.o +endif + + +all: $(PROGRAMS) + +default: $(PROGRAMS) + +.c.o: + $(CC) $(CFLAGS) -c $< + +adv_jtag_bridge: Makefile $(OBJECTS) $(HEADERS) + rm -f $@ + $(CC) -o $@ $(CFLAGS) $(INCLUDEDIRS) $(OBJECTS) $(LIBS) + + +install: all + [ -d $(prefix)/bin ] || mkdir -p $(prefix)/bin + for p in $(PROGRAMS) ; do \ + /bin/rm -f $(prefix)/bin/$$p; \ + /bin/cp -p $$p $(prefix)/bin/$$p; \ + done + +clean: Makefile + rm -f $(PROGRAMS) *.o *~
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.classic Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING (revision 66) @@ -0,0 +1,18 @@ +Thanks to R. Diez for contributing the autotools support patch: + +./autogen.sh +./configure +./make +./make install + +The autogen.sh script only needs to be run once after the initial +checkout. The configure script only needs to be run before the +first build, or when changing build options. Note that a 'make +clean' should also be done when changing build options. + +Note that there are many options. The defaults match a typical use +scenario, and the defaults of the adv_dbg_if hardware. Type +"./configure --help" to get a list of all the options. The options +are also described in more detail in the BUILDING.classic file, +and to some extent in the adv_jtag_bridge documentation. +
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/dbg_api.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/dbg_api.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/dbg_api.c (revision 66) @@ -0,0 +1,687 @@ +/* dbg_api.c -- JTAG protocol bridge between GDB and Advanced debug module. + Copyright(C) 2009 - 2011 Nathan Yawn, nyawn@opencores.net + based on code from jp2 by Marko Mlinar, markom@opencores.org + + This file contains API functions which may be called from the GDB + interface server. These functions call the appropriate hardware- + specific functions for the advanced debug interface or the legacy + debug interface, depending on which is selected. + + 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 // for mutexes +#include // for ntohl() + +#include "adv_dbg_commands.h" +#include "legacy_dbg_commands.h" +#include "cable_common.h" +#include "errcodes.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +#define DBG_HW_ADVANCED 1 +#define DBG_HW_LEGACY 2 +#ifdef __LEGACY__ +#define DEBUG_HARDWARE DBG_HW_LEGACY +#else +#define DEBUG_HARDWARE DBG_HW_ADVANCED +#endif + +pthread_mutex_t dbg_access_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* read a word from wishbone */ +int dbg_wb_read32(uint32_t adr, uint32_t *data) { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(4, 1, adr, (void *)data); // All WB reads / writes are bursts + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x6, adr, 4))) + err = legacy_dbg_go((unsigned char*)data, 4, 1); + *data = ntohl(*data); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +/* write a word to wishbone */ +int dbg_wb_write32(uint32_t adr, uint32_t data) { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)&data, 4, 1, adr); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + data = ntohl(data); + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x2, adr, 4))) + err = legacy_dbg_go((unsigned char*)&data, 4, 0); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +// write a word to wishbone +// Never actually called from the GDB interface +int dbg_wb_write16(uint32_t adr, uint16_t data) { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)&data, 2, 1, adr); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + data = ntohs(data); + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x1, adr, 2))) + err = legacy_dbg_go((unsigned char*)&data, 2, 0); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +// write a word to wishbone +// Never actually called from the GDB interface +int dbg_wb_write8(uint32_t adr, uint8_t data) { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)&data, 1, 1, adr); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x0, adr, 1))) + err = legacy_dbg_go((unsigned char*)&data, 1, 0); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +int dbg_wb_read_block32(uint32_t adr, uint32_t *data, int len) { + int err; + + if(!len) + return APP_ERR_NONE; // GDB may issue a 0-length transaction to test if a feature is supported + + pthread_mutex_lock(&dbg_access_mutex); + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(4, len, adr, (void *)data); // 'len' is words. + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int i; + int bytelen = len<<2; + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x6, adr, bytelen))) + if (APP_ERR_NONE == (err = legacy_dbg_go((unsigned char*)data, bytelen, 1))) // 'len' is words, call wants bytes + for (i = 0; i < len; i ++) data[i] = ntohl(data[i]); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +// Never actually called from the GDB interface +int dbg_wb_read_block16(uint32_t adr, uint16_t *data, int len) { + int err; + + if(!len) + return APP_ERR_NONE; // GDB may issue a 0-length transaction to test if a feature is supported + + pthread_mutex_lock(&dbg_access_mutex); + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(2, len, adr, (void *)data); // 'len' is 16-bit halfwords + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int i; + int bytelen = len<<1; + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x5, adr, bytelen))) + if (APP_ERR_NONE == (err = legacy_dbg_go((unsigned char*)data, bytelen, 1))) // 'len' is halfwords, call wants bytes + for (i = 0; i < len; i ++) data[i] = ntohs(data[i]); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +// Never actually called from the GDB interface +int dbg_wb_read_block8(uint32_t adr, uint8_t *data, int len) { + int err; + + if(!len) + return APP_ERR_NONE; // GDB may issue a 0-length transaction to test if a feature is supported + + pthread_mutex_lock(&dbg_access_mutex); + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(1, len, adr, (void *)data); // *** is 'len' bits or words?? Call wants words... + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x4, adr, len))) + err = legacy_dbg_go((unsigned char*)data, len, 1); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +// write a block to wishbone +int dbg_wb_write_block32(uint32_t adr, uint32_t *data, int len) { + int err; + + if(!len) + return APP_ERR_NONE; // GDB may issue a 0-length transaction to test if a feature is supported + + pthread_mutex_lock(&dbg_access_mutex); + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)data, 4, len, adr); // 'len' is words. + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int i; + int bytelen = len << 2; + for (i = 0; i < len; i ++) data[i] = ntohl(data[i]); + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x2, adr, bytelen))) + err = legacy_dbg_go((unsigned char*)data, bytelen, 0); // 'len' is words, call wants bytes + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +// write a block to wishbone +// Never actually called from the GDB interface +int dbg_wb_write_block16(uint32_t adr, uint16_t *data, int len) { + int err; + + if(!len) + return APP_ERR_NONE; // GDB may issue a 0-length transaction to test if a feature is supported + + pthread_mutex_lock(&dbg_access_mutex); + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)data, 2, len, adr); // 'len' is (half)words + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int i; + int bytelen = len<<1; + for (i = 0; i < len; i ++) data[i] = ntohs(data[i]); + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x1, adr, bytelen))) + err = legacy_dbg_go((unsigned char*)data, bytelen, 0); // 'len' is 16-bit halfwords, call wants bytes + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +// write a block to wishbone +int dbg_wb_write_block8(uint32_t adr, uint8_t *data, int len) { + int err; + + if(!len) + return APP_ERR_NONE; // GDB may issue a 0-length transaction to test if a feature is supported + + pthread_mutex_lock(&dbg_access_mutex); + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_WISHBONE))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)data, 1, len, adr); // 'len' is in words... + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_WISHBONE))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x0, adr, len))) + err = legacy_dbg_go((unsigned char*)data, len, 0); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +/* read a register from cpu0. This is assumed to be an OR32 CPU, with 32-bit regs. */ +int dbg_cpu0_read(uint32_t adr, uint32_t *data) { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU0))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(4, 1, adr, (void *) data); // All CPU register reads / writes are bursts + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU0))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x6, adr, 4))) + if (APP_ERR_NONE == (err = legacy_dbg_go((unsigned char*)data, 4, 1))) + *data = ntohl(*data); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + debug("dbg_cpu_read(), addr 0x%X, data[0] = 0x%X\n", adr, data[0]); + return err; +} + +/* read multiple registers from cpu0. This is assumed to be an OR32 CPU, with 32-bit regs. */ +int dbg_cpu0_read_block(uint32_t adr, uint32_t *data, int count) { + int err; + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + pthread_mutex_lock(&dbg_access_mutex); + if ((err = adbg_select_module(DC_CPU0))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(4, count, adr, (void *) data); // All CPU register reads / writes are bursts + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int i; + unsigned long readaddr = adr; + err = APP_ERR_NONE; + for(i = 0; i < count; i++) { + err |= dbg_cpu0_read(readaddr++, &data[i]); + } + } + + debug("dbg_cpu_read_block(), addr 0x%X, count %i, data[0] = 0x%X\n", adr, count, data[0]); + return err; +} + +/* write a cpu register to cpu0. This is assumed to be an OR32 CPU, with 32-bit regs. */ +int dbg_cpu0_write(uint32_t adr, uint32_t data) { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU0))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)&data, 4, 1, adr); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + data = ntohl(data); + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU0))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x2, adr, 4))) + err = legacy_dbg_go((unsigned char*)&data, 4, 0); + } + debug("cpu0_write, adr 0x%X, data 0x%X, ret %i\n", adr, data, err); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +/* write multiple cpu registers to cpu0. This is assumed to be an OR32 CPU, with 32-bit regs. */ +int dbg_cpu0_write_block(uint32_t adr, uint32_t *data, int count) { + int err; + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + pthread_mutex_lock(&dbg_access_mutex); + if ((err = adbg_select_module(DC_CPU0))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)data, 4, count, adr); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int i; + unsigned long writeaddr = adr; + err = APP_ERR_NONE; + for(i = 0; i < count; i++) { + err |= dbg_cpu0_write(writeaddr++, data[i]); + } + } + debug("cpu0_write_block, adr 0x%X, data[0] 0x%X, count %i, ret %i\n", adr, data[0], count, err); + + return err; +} + +/* write a debug unit cpu module register + * Since OR32 debug module has only 1 register, + * adr is ignored (for now) */ +int dbg_cpu0_write_ctrl(uint32_t adr, uint8_t data) { + int err = APP_ERR_NONE; + uint32_t dataword = data; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU0))) { + printf("Failed to set chain to 0x%X\n", DC_CPU0); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + if((err = adbg_ctrl_write(DBG_CPU0_REG_STATUS, &dataword, 2))) { + printf("Failed to write chain to 0x%X control reg 0x%X\n", DC_CPU0,DBG_CPU0_REG_STATUS ); // Only 2 bits: Reset, Stall + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU0))) + err = legacy_dbg_ctrl(data & 2, data &1); + } + debug("cpu0_write_ctrl(): set reg to 0x%X\n", data); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +/* read a register from cpu module of the debug unit. + * Currently, there is only 1 register, so we do not need to select it, adr is ignored + */ +int dbg_cpu0_read_ctrl(uint32_t adr, uint8_t *data) { + int err = APP_ERR_NONE; + uint32_t dataword; + pthread_mutex_lock(&dbg_access_mutex); + + // reset is bit 1, stall is bit 0 in *data + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU0))) { + printf("Failed to set chain to 0x%X\n", DC_CPU0); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + if ((err = adbg_ctrl_read(DBG_CPU0_REG_STATUS, &dataword, 2))) { + printf("Failed to read chain 0x%X control reg 0x%X\n", DC_CPU0, DBG_CPU0_REG_STATUS); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + *data = dataword; + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int r, s; + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU0))) + err = legacy_dbg_ctrl_read(&r, &s); + *data = (r << 1) | s; + debug("api cpu0 read ctrl: r = %i, s = %i, data = %i\n", r, s, *data); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +// CPU1 Functions. Note that 2 CPUs are not currently supported by GDB, so these are never actually +// called from the GDB interface. They are included for completeness and future use. +// read a register from cpu1 +int dbg_cpu1_read(uint32_t adr, uint32_t *data) + { + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU1))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_read(4, 1, adr, (void *) data); // All CPU register reads / writes are bursts + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU1))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x6, adr, 4))) + err = legacy_dbg_go((unsigned char*)data, 4, 1); + *data = ntohl(*data); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +// write a cpu register +int dbg_cpu1_write(uint32_t adr, uint32_t data) +{ + int err; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU0))) + { + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + err = adbg_wb_burst_write((void *)&data, 4, 1, adr); + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + data = ntohl(data); + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU1))) + if (APP_ERR_NONE == (err = legacy_dbg_command(0x2, adr, 4))) + err = legacy_dbg_go((unsigned char*)&data, 4, 0); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +// write a debug unit cpu module register +int dbg_cpu1_write_ctrl(uint32_t adr, uint8_t data) { + int err; + uint32_t dataword = data; + pthread_mutex_lock(&dbg_access_mutex); + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU1))) { + printf("Failed to set chain to 0x%X\n", DC_CPU1); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + if((err = adbg_ctrl_write(DBG_CPU1_REG_STATUS, &dataword, 2))) { + printf("Failed to write chain to 0x%X control reg 0x%X\n", DC_CPU1,DBG_CPU0_REG_STATUS ); // Only 2 bits: Reset, Stall + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU1))) + err = legacy_dbg_ctrl(data & 2, data & 1); + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + + +// read a debug unit cpu module register +int dbg_cpu1_read_ctrl(uint32_t adr, uint8_t *data) { + int err; + uint32_t dataword; + pthread_mutex_lock(&dbg_access_mutex); + + // reset is bit 1, stall is bit 0 in *data + + if(DEBUG_HARDWARE == DBG_HW_ADVANCED) + { + if ((err = adbg_select_module(DC_CPU1))) { + printf("Failed to set chain to 0x%X\n", DC_CPU1); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + if ((err = adbg_ctrl_read(DBG_CPU1_REG_STATUS, &dataword, 2))) { + printf("Failed to read chain 0x%X control reg 0x%X\n", DC_CPU0, DBG_CPU1_REG_STATUS); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + *data = dataword; + } + else if(DEBUG_HARDWARE == DBG_HW_LEGACY) + { + int r, s; + if (APP_ERR_NONE == (err = legacy_dbg_set_chain(DC_CPU1))) + err = legacy_dbg_ctrl_read(&r, &s); + *data = (r << 1) | s; + } + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; +} + +int dbg_serial_sndrcv(unsigned int *bytes_to_send, const uint8_t *data_to_send, unsigned int *bytes_received, uint8_t *data_received) { + int err; + + pthread_mutex_lock(&dbg_access_mutex); + + if ((err = adbg_select_module(DC_JSP))) { + printf("Failed to set chain to 0x%X\n", DC_JSP); + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + return err; + } + + err = adbg_jsp_transact(bytes_to_send, data_to_send, bytes_received, data_received); + + cable_flush(); + pthread_mutex_unlock(&dbg_access_mutex); + + return err; +} + + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_rtl/dbg_comm.v =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_rtl/dbg_comm.v (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_rtl/dbg_comm.v (revision 66) @@ -0,0 +1,177 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// dbg_comm.v //// +//// //// +//// //// +//// This file is part of the SoC/OpenRISC Development Interface //// +//// http://www.opencores.org/cores/DebugInterface/ //// +//// //// +//// //// +//// Author(s): //// +//// Igor Mohor (igorm@opencores.org) //// +//// Nathan Yawn (nathan.yawn@opencores.org) //// +//// //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2008 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: dbg_comm.v,v $ +// Revision 1.4 2011-10-28 01:13:26 natey +// Ran through dos2unix. +// +// Revision 1.3 2009-05-17 20:55:57 Nathan +// Changed email address to opencores.org +// +// Revision 1.2 2008/07/22 18:23:25 Nathan +// Added clock and reset outputs to make simulation system simpler. Fixed P_TRST signal name. Added fflush calls to make file IO work as quickly as possible. Write the data out bit on falling clock edge. Cleanup. +// +// Revision 1.1 2002/03/28 19:59:54 lampret +// Added bench directory +// +// Revision 1.1.1.1 2001/11/04 18:51:07 lampret +// First import. +// +// Revision 1.3 2001/09/24 14:06:13 mohor +// Changes connected to the OpenRISC access (SPR read, SPR write). +// +// Revision 1.2 2001/09/20 10:10:30 mohor +// Working version. Few bugs fixed, comments added. +// +// Revision 1.1.1.1 2001/09/13 13:49:19 mohor +// Initial official release. +// +// +// +// +// + + + +`define GDB_IN "e:/tmp/gdb_in.dat" +`define GDB_OUT "e:/tmp/gdb_out.dat" + + +module dbg_comm( + SYS_CLK, + SYS_RSTN, + P_TMS, + P_TCK, + P_TRST, + P_TDI, + P_TDO + ); + +parameter Tp = 20; + +output SYS_CLK; +output SYS_RSTN; +output P_TMS; +output P_TCK; +output P_TRST; +output P_TDI; +input P_TDO; + +// Signal for the whole system +reg SYS_CLK; +reg SYS_RSTN; + +// For handling data from the input file +integer handle1, handle2; +reg [4:0] memory[0:0]; + +wire P_TCK; +wire P_TRST; +wire P_TDI; +wire P_TMS; +wire P_TDO; + +// Temp. signal +reg [3:0] in_word_r; + + + +// Provide the wishbone / CPU / system clock +initial +begin + SYS_CLK = 1'b0; + forever #5 SYS_CLK = ~SYS_CLK; +end + +// Provide the system reset +initial +begin + SYS_RSTN = 1'b1; + #200 SYS_RSTN = 1'b0; + #5000 SYS_RSTN = 1'b1; +end + +// Set the initial state of the JTAG pins +initial +begin + in_word_r = 4'h0; // This sets the TRSTN output active... +end + +// Handle input from a file for the JTAG pins +initial +begin + #5500; // Wait until reset is complete + while(1) + begin + #Tp; + $readmemh(`GDB_OUT, memory); + if(!(memory[0] & 5'b10000)) + begin + in_word_r = memory[0][3:0]; + handle1 = $fopen(`GDB_OUT); + $fwrite(handle1, "%h", 5'b10000 | memory[0]); // To ack that we read dgb_out.dat + $fflush(handle1); + $fclose(handle1); + end + end +end + +// Send the current state of the JTAG output to a file +always @ (P_TDO or negedge P_TCK) +begin + handle2 = $fopen(`GDB_IN); + $fdisplay(handle2, "%b", P_TDO); + $fflush(handle2); + $fclose(handle2); +end + +// Note these must match the bit definitions in the JTAG bridge program (adv_jtag_bridge) +assign P_TCK = in_word_r[0]; +assign P_TRST = in_word_r[1]; +assign P_TDI = in_word_r[2]; +assign P_TMS = in_word_r[3]; + + +endmodule // TAP + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_rtl/dbg_comm_vpi.v =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_rtl/dbg_comm_vpi.v (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_rtl/dbg_comm_vpi.v (revision 66) @@ -0,0 +1,178 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// dbg_comm_vpi.v //// +//// //// +//// //// +//// This file is part of the SoC/OpenRISC Development Interface //// +//// http://www.opencores.org/cores/DebugInterface/ //// +//// //// +//// //// +//// Author(s): //// +//// Igor Mohor (igorm@opencores.org) //// +//// Gyorgy Jeney (nog@sdf.lonestar.net) //// +//// Nathan Yawn (nathan.yawn@opencores.org) //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2008 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: dbg_comm_vpi.v,v $ +// Revision 1.2 2009-05-17 20:55:57 Nathan +// Changed email address to opencores.org +// +// Revision 1.1 2008/07/26 17:33:20 Nathan +// Added debug comm module for use with VPI / network communication. +// +// Revision 1.1 2002/03/28 19:59:54 lampret +// Added bench directory +// +// Revision 1.1.1.1 2001/11/04 18:51:07 lampret +// First import. +// +// Revision 1.3 2001/09/24 14:06:13 mohor +// Changes connected to the OpenRISC access (SPR read, SPR write). +// +// Revision 1.2 2001/09/20 10:10:30 mohor +// Working version. Few bugs fixed, comments added. +// +// Revision 1.1.1.1 2001/09/13 13:49:19 mohor +// Initial official release. +// +// +// +// +// + + +`define JP_PORT "4567" +`define TIMEOUT_COUNT 6'd20 // 1/2 of a TCK clock will be this many SYS_CLK ticks. Must be less than 6 bits. + + module dbg_comm_vpi ( + SYS_CLK, + SYS_RSTN, + P_TMS, + P_TCK, + P_TRST, + P_TDI, + P_TDO + ); + + //parameter Tp = 20; + + output SYS_CLK; + output SYS_RSTN; + output P_TMS; + output P_TCK; + output P_TRST; + output P_TDI; + input P_TDO; + + reg SYS_CLK; + reg SYS_RSTN; + + + reg [4:0] memory; // [0:0]; + + + wire P_TCK; + wire P_TRST; + wire P_TDI; + wire P_TMS; + wire P_TDO; + + reg [3:0] in_word_r; + reg [5:0] clk_count; + + + // Provide the wishbone / CPU / system clock + initial + begin + SYS_CLK = 1'b0; + clk_count[5:0] <= `TIMEOUT_COUNT + 1; // Start with the timeout clock stopped + forever #5 SYS_CLK = ~SYS_CLK; + end + + // Provide the system reset + initial + begin + SYS_RSTN = 1'b1; + #200 SYS_RSTN = 1'b0; + #5000 SYS_RSTN = 1'b1; + end + + + // Handle commands from the upper level + initial + begin + in_word_r = 5'b0; + memory = 5'b0; + $jp_init(`JP_PORT); + #5500; // Wait until reset is complete + + while(1) + begin + #1; + $jp_in(memory); // This will not change memory[][] if no command has been sent from jp + if(memory[4]) // was memory[0][4] + begin + in_word_r = memory[3:0]; + memory = memory & 4'b1111; + clk_count = 6'b000000; // Reset the timeout clock in case jp wants to wait for a timeout / half TCK period + end + end + end + + + + // Send the output bit to the upper layer + always @ (P_TDO) + begin + $jp_out(P_TDO); + end + + + assign P_TCK = in_word_r[0]; + assign P_TRST = in_word_r[1]; + assign P_TDI = in_word_r[2]; + assign P_TMS = in_word_r[3]; + + + // Send timeouts / wait periods to the upper layer + always @ (posedge SYS_CLK) + begin + if(clk_count < `TIMEOUT_COUNT) clk_count[5:0] = clk_count[5:0] + 1; + else if(clk_count == `TIMEOUT_COUNT) begin + $jp_wait_time(); + clk_count[5:0] = clk_count[5:0] + 1; + end + // else it's already timed out, don't do anything + end + +endmodule + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.am =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.am (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.am (revision 66) @@ -0,0 +1,80 @@ +AUTOMAKE_OPTIONS = foreign + +# Without the ACLOCAL_AMFLAGS line below, you get this warning: +# libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am. +# However, with it, autoreconf does not work if you don't manually create +# the m4 subdirectory beforehand, even if you add the --install flag here. +# I have tested with autoconf 2.65 and automake 1.11.1 . +# ACLOCAL_AMFLAGS = -I m4 + +bin_PROGRAMS = adv_jtag_bridge + +adv_jtag_bridge_CPPFLAGS = + +my_headers = \ + adv_dbg_commands.h \ + cable_common.h \ + cable_usbblaster.h \ + except.h \ + opencores_tap.h \ + adv_jtag_bridge.h \ + cable_xpc_dlc9.h \ + hardware_monitor.h \ + or32_selftest.h \ + altera_virtual_jtag.h \ + chain_commands.h \ + hwp_server.h \ + rsp-server.h \ + bsdl.h \ + dbg_api.h \ + jsp_server.h \ + spr-defs.h \ + bsdl_parse.h \ + cable_sim.h \ + errcodes.h \ + legacy_dbg_commands.h \ + utilities.h + +adv_jtag_bridge_SOURCES = \ + $(my_headers) \ + adv_jtag_bridge.c \ + rsp-server.c \ + chain_commands.c \ + cable_common.c bsdl.c \ + or32_selftest.c \ + cable_sim.c \ + utilities.c \ + bsdl_parse.c \ + errcodes.c \ + adv_dbg_commands.c \ + dbg_api.c \ + legacy_dbg_commands.c \ + hardware_monitor.c \ + hwp_server.c + +adv_jtag_bridge_LDFLAGS = -lpthread -lrt + + +if SUPPORT_PARALLEL_CABLES + adv_jtag_bridge_CPPFLAGS += -D__SUPPORT_PARALLEL_CABLES__ + adv_jtag_bridge_SOURCES += cable_parallel.h cable_parallel.c +endif + +if SUPPORT_FTDI_CABLES + adv_jtag_bridge_CPPFLAGS += -D__SUPPORT_FTDI_CABLES__ + adv_jtag_bridge_LDFLAGS += -lftdi + adv_jtag_bridge_SOURCES += cable_ft2232.h cable_ft245.h cable_ft2232.c cable_ft245.c +endif + +# Must come after SUPPORT_FTDI_CABLES, see below. +if SUPPORT_USB_CABLES + adv_jtag_bridge_CPPFLAGS += -D__SUPPORT_USB_CABLES__ + adv_jtag_bridge_SOURCES += cable_xpc_dlc9.h cable_usbblaster.h cable_xpc_dlc9.c cable_usbblaster.c + # libusb must follow libftdi in the list of libraries + adv_jtag_bridge_LDFLAGS += -lusb +endif + +if INCLUDE_JSP_SERVER + adv_jtag_bridge_CPPFLAGS += -DENABLE_JSP + adv_jtag_bridge_SOURCES += jsp_server.h jsp_server.c +endif
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/Makefile.am Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_xpc_dlc9.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_xpc_dlc9.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_xpc_dlc9.c (revision 66) @@ -0,0 +1,856 @@ +/* cable_xpc_dlc9.c - Xilinx Platform Cable (DLC9) driver for the Advanced JTAG Bridge + Copyright (C) 2008 - 2010 Nathan Yawn, nathan.yawn@opencores.org + Copyright (C) 2008 Kolja Waschk (UrJTAG project) + + CPLD mode for burst transfers added by: + Copyright (C) 2011 Raul Fajardo, rfajardo@opencores.org + adapted from xc3sprog/ioxpc.cpp: + Copyright (C) 2009-2011 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de + +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 // for sleep() +#include +#include + +#include "usb.h" // libusb header + +#include "cable_xpc_dlc9.h" +#include "utilities.h" +#include "errcodes.h" + +/* + * The dynamic switch between FX2 and CPLD modes works fine. If a switch is required, the functions: + * static int cable_xpcusb_fx2_init(); + * static int cable_xpcusb_cpld_init(); + * can be called. The variable cpld_ctrl can tell if the CPLD is active (1) or FX2 (0). + * + * The functions accessing the cable in this driver always check the cpld_ctrl variable and adapt the + * cable mode accordingly. + * + * Therefore, we can arbitrarily define bit and stream functionality from different modes without + * concern. Out_func and inout_func are not provided under CPLD mode because it always complete + * a bit transfer by toggling the clock twice 0-1-0 providing a write and a read. + * + * When using stream functionality of the CPLD, and bit functionality of FX2, also cable_common_read_write_bit + * works. The cable_xpcusb_read_write_bit is not necessary then. However, it is still necessary when using: + * cable_common_write_stream + * cable_common_read_stream + */ + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +//#define CLASSIC +#define CPLDBITFUNC + +#ifdef CLASSIC +jtag_cable_t dlc9_cable_driver = { + .name ="xpc_usb" , + .inout_func = cable_xpcusb_inout, + .out_func = cable_xpcusb_out, + .init_func = cable_xpcusb_init, + .opt_func = cable_xpcusb_opt, + .bit_out_func = cable_common_write_bit, + .bit_inout_func = cable_xpcusb_read_write_bit, + .stream_out_func = cable_common_write_stream, + .stream_inout_func = cable_common_read_stream, + .flush_func = NULL, + .opts = "", + .help = "no options\n", + }; +#else +jtag_cable_t dlc9_cable_driver = { + .name ="xpc_usb" , + .inout_func = cable_xpcusb_inout, + .out_func = cable_xpcusb_out, + .init_func = cable_xpcusb_init, + .opt_func = cable_xpcusb_opt, +#ifdef CPLDBITFUNC + .bit_out_func = cable_xpcusb_cpld_write_bit, + .bit_inout_func = cable_xpcusb_cpld_readwrite_bit, +#else + .bit_out_func = cable_common_write_bit, + .bit_inout_func = cable_common_read_write_bit, +#endif + .stream_out_func = cable_xpcusb_write_stream, + .stream_inout_func = cable_xpcusb_readwrite_stream, + .flush_func = NULL, + .opts = "", + .help = "no options\n", + }; +#endif + +#define USB_TIMEOUT 500 + +// USB constants for the DLC9 +#define XPCUSB_VID 0x3fd +#define XPCUSB_PID 0x08 + +// Bit meanings in the command byte sent to the DLC9 +// DLC9 has no TRST bit +#define XPCUSB_CMD_TDI 0x01 +#define XPCUSB_CMD_TDO 0x01 +#define XPCUSB_CMD_TMS 0x02 +#define XPCUSB_CMD_TCK 0x04 +#define XPCUSB_CMD_PROG 0x08 + +/* + * send max 4096 bytes to CPLD + * this is equal to 8192 TDI plus 8192 TDO bits + */ +#define CPLD_MAX_BYTES (1<<12) + +/* + * Buffer has to hold 8192 bits for write, each 2 bytes hold 4 bits for write, so this has to be 4096 + * Buffer has to hold 8192 bits for read, each byte holds 8 bits for read, so this has to be 1024 + * Therefore, buffer size -> CPLD_MAX_BYTES + */ +typedef struct +{ + int in_bits; + int out_bits; + uint8_t buf[CPLD_MAX_BYTES]; +} xpc_ext_transfer_state_t; + + +static struct usb_device *device = NULL; +static usb_dev_handle *h_device = NULL; +static int cpld_ctrl = 0; + +static const uint32_t endianess_test = 1; +#define is_bigendian() ( (*(uint8_t*)&endianess_test) == 0 ) + +static int cable_xpcusb_open_cable(void); +static void cable_xpcusb_close_cable(void); +static int cable_xpcusb_fx2_init(); +static int cable_xpcusb_cpld_init(); + + + + +/////////////////////////////////////////////////////////////////////////////// +/*----- Functions for the Xilinx Platform Cable USB (Model DLC9) */ +///////////////////////////////////////////////////////////////////////////// + +static int xpcu_request_28(struct usb_dev_handle *xpcu, int value) +{ + /* Typical values seen during autodetection of chain configuration: 0x11, 0x12 */ + + if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0028, value, NULL, 0, 1000)<0) + { + perror("usb_control_msg(0x28.x)"); + return -1; + } + + return 0; +} + +static int xpcu_select_gpio(struct usb_dev_handle *xpcu, int chain) +{ + if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0052, chain, NULL, 0, USB_TIMEOUT)<0) + { + fprintf(stderr, "Error sending usb_control_msg(0x52.x) (select gpio)\n"); + return APP_ERR_USB; + } + + return APP_ERR_NONE; +} + +static int xpcu_write_gpio(struct usb_dev_handle *xpcu, uint8_t bits) +{ + if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0030, bits, NULL, 0, 1000)<0) + { + perror("usb_control_msg(0x30.0x00) (write port E)"); + return -1; + } + + return 0; +} + + +static int xpcu_read_cpld_version(struct usb_dev_handle *xpcu, uint16_t *buf) +{ + if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0001, (char*)buf, 2, 1000)<0) + { + perror("usb_control_msg(0x50.1) (read_cpld_version)"); + return -1; + } + return 0; +} + + +static int xpcu_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf) +{ + if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0000, (char*)buf, 2, 1000)<0) + { + perror("usb_control_msg(0x50.0) (read_firmware_version)"); + return -1; + } + + return 0; +} + +static int xpcu_output_enable(struct usb_dev_handle *xpcu, int enable) +{ + if(usb_control_msg(xpcu, 0x40, 0xB0, enable ? 0x18 : 0x10, 0, NULL, 0, 1000)<0) + { + perror("usb_control_msg(0x10/0x18)"); + return -1; + } + + return 0; +} + +/* + * === A6 transfer (TDI/TMS/TCK/RDO) === + * + * Vendor request 0xA6 initiates a quite universal shift operation. The data + * is passed directly to the CPLD as 16-bit words. + * + * The argument N in the request specifies the number of state changes/bits. + * + * State changes are described by the following bulk write. It consists + * of ceil(N/4) little-endian 16-bit words, each describing up to 4 changes. + * (see xpcusb_add_bit_for_ext_transfer) + * + * After the bulk write, if any of the bits 12..15 was set in any word + * (see xpcusb_add_bit_for_ext_transfer), a bulk_read shall follow to collect + * the TDO data. + */ +static int xpcu_shift(struct usb_dev_handle *xpcu, int reqno, int bits, int in_len, uint8_t *in, int out_len, uint8_t *out ) +{ + if(usb_control_msg(xpcu, 0x40, 0xB0, reqno, bits, NULL, 0, 1000)<0) + { + perror("usb_control_msg(x.x) (shift)"); + return -1; + } + +#if VERBOSE + { + int i; + printf("\n###\n"); + printf("reqno = %02X\n", reqno); + printf("bits = %d\n", bits); + printf("in_len = %d, in_len*2 = %d\n", in_len, in_len * 2); + printf("out_len = %d, out_len*8 = %d\n", out_len, out_len * 8); + + printf("a6_display(\"%02X\", \"", bits); + for(i=0;i 0 && out != NULL) + { + if(usb_bulk_read(xpcu, 0x86, (char*)out, out_len, 1000)<0) + { + printf("\nusb_bulk_read error(shift): %s\n", strerror(errno)); + return -1; + } + } + +#if VERBOSE + { + int i; + printf("\""); + for(i=0;iin_bits & 3); + int buf_idx = (xts->in_bits - bit_idx) >> 1; + + debug("add_bit, in = %i, bit_idx = %i, buf_idx = %i\n", tdi, bit_idx, buf_idx); + + if(bit_idx == 0) + { + xts->buf[buf_idx] = 0; + xts->buf[buf_idx+1] = 0; + } + + xts->in_bits++; + + if(tdi) xts->buf[buf_idx] |= (0x01<buf[buf_idx] |= (0x10<buf[buf_idx+1] |= (0x01<buf[buf_idx+1] |= (0x10<out_bits++; + } +} + +/* + * TDO data is shifted in from MSB to LSB and transferred 32-bit little-endian. + * In a "full" word with 32 TDO bits, the earliest one reached bit 0. + * The earliest of 31 bits however would be bit 1. A 17 bit transfer has the LSB + * as the MSB of uint16_t[0], other bits are in uint16_t[1]. + * + * However, if the last packet is smaller than 16, only 2 bytes are transferred. + * If there's only one TDO bit, it arrives as the MSB of the 16-bit word, uint16_t[0]. + * uint16_t[1] is then skipped. + * + * For full 32 bits blocks, the data is aligned. The last non 32-bits block arrives + * non-aligned and has to be re-aligned. Half-words (16-bits) transfers have to be + * re-aligned too. + */ +static int xpcusb_do_ext_transfer(xpc_ext_transfer_state_t *xts, uint32_t * tdostream) +{ + int i, r; + int in_len, out_len; + int shift, bit_num, bit_val; + uint32_t aligned_32bitwords, aligned_bytes; + uint32_t out_done; + + //cpld expects data (tdi) to be in 16 bit words + in_len = 2 * (xts->in_bits >> 2); + if ((xts->in_bits & 3) != 0) in_len += 2; + + //cpld returns the read data (tdo) in 32 bit words + out_len = 2 * (xts->out_bits >> 4); + if ((xts->out_bits & 15) != 0) out_len += 2; + + r = xpcu_shift (h_device, 0xA6, xts->in_bits, in_len, xts->buf, out_len, xts->buf); + + if(r >= 0 && xts->out_bits > 0 && tdostream != NULL) + { + aligned_32bitwords = xts->out_bits/32; + aligned_bytes = aligned_32bitwords*4; + if ( is_bigendian() ) //these data is aligned as little-endian + { + for (i=0; ibuf[i] << (i%4)*8; + } + } + else + memcpy(tdostream, xts->buf, aligned_bytes); //these data is already little-endian + + out_done = aligned_bytes*8; + + //This data is not aligned + if (xts->out_bits % 32) + { + shift = xts->out_bits % 16; //we can also receive a 16-bit word in which case + if (shift) //the MSB starts in the least significant 16 bit word + shift = 16 - shift; //and it shifts the same way for 32 bit if + //out_bits > 16 and ( shift = 32 - out_bits % 32 ) + + debug("out_done %d shift %d\n", out_done, shift); + for (i= aligned_bytes*8; i out_bits; i++) + { + bit_num = i + shift; + bit_val = xts->buf[bit_num/8] & (1<<(bit_num%8)); + if(!(out_done % 32)) + tdostream[out_done/32] = 0; + if (bit_val) + tdostream[out_done/32] |= (1<<(out_done%32)); + out_done++; + } + } + } + + xts->in_bits = 0; + xts->out_bits = 0; + + return r; +} + + + +int cable_xpcusb_out(uint8_t value) +{ + int rv; // to catch return values of functions + //usb_dev_handle *h_device; // handle on the ubs device + uint8_t out; + + // open the device, if necessary + if(h_device == NULL) { + rv = cable_xpcusb_open_cable(); + if(rv != APP_ERR_NONE) return rv; + } + + if ( cpld_ctrl ) + { + rv = cable_xpcusb_fx2_init(); + if ( rv != APP_ERR_NONE) return rv; + } + + // send the buffer + // Translate to USB blaster protocol + out = 0; + if(value & TCLK_BIT) + out |= XPCUSB_CMD_TCK; + if(value & TDI_BIT) + out |= XPCUSB_CMD_TDI; + if(value & TMS_BIT) + out |= XPCUSB_CMD_TMS; + + out |= XPCUSB_CMD_PROG; // Set output PROG (always necessary) + + rv = usb_control_msg(h_device, 0x40, 0xB0, 0x0030, out, NULL, 0, USB_TIMEOUT); + if (rv < 0){ + fprintf(stderr, "\nFailed to send a write control message (rv = %d):\n%s\n", rv, usb_strerror()); + cable_xpcusb_close_cable(); + return APP_ERR_USB; + } + + return APP_ERR_NONE; +} + +int cable_xpcusb_inout(uint8_t value, uint8_t *inval) +{ + int rv; // to catch return values of functions + //usb_dev_handle *h_device; // handle on the usb device + char ret = 0; + uint8_t out; + + // open the device, if necessary + if(h_device == NULL) { + rv = cable_xpcusb_open_cable(); + if(rv != APP_ERR_NONE) return rv; + } + + if ( cpld_ctrl ) + { + rv = cable_xpcusb_fx2_init(); + if ( rv != APP_ERR_NONE) return rv; + } + + // Translate to USB blaster protocol + out = 0; + if(value & TCLK_BIT) + out |= XPCUSB_CMD_TCK; + if(value & TDI_BIT) + out |= XPCUSB_CMD_TDI; + if(value & TMS_BIT) + out |= XPCUSB_CMD_TMS; + + out |= XPCUSB_CMD_PROG; // Set output PROG (always necessary) + + // Send the output + rv = usb_control_msg(h_device, 0x40, 0xB0, 0x0030, out, NULL, 0, USB_TIMEOUT); + if (rv < 0){ + fprintf(stderr, "\nFailed to send a write control message (rv = %x):\n%s\n", rv, usb_strerror()); + cable_xpcusb_close_cable(); + return APP_ERR_USB; + } + + // receive the response + rv = usb_control_msg(h_device, 0xC0, 0xB0, 0x0038, 0, (char*)&ret, 1, USB_TIMEOUT); + if (rv < 0){ + fprintf(stderr, "\nFailed to execute a read control message:\n%s\n", usb_strerror()); + cable_xpcusb_close_cable(); + return APP_ERR_USB; + } + + if(ret & XPCUSB_CMD_TDO) + *inval = 1; + else + *inval = 0; + + return APP_ERR_NONE; +} + +// Xilinx couldn't be like everyone else. Oh, no. +// For some reason, "set data/drop TCK" then "read data/raise TCK" won't work. +// So we have our very own bit read/write function. @whee. +int cable_xpcusb_read_write_bit(uint8_t packet_out, uint8_t *bit_in) { + uint8_t data = TRST_BIT; // TRST is active low, don't clear unless /set/ in 'packet' + int err = APP_ERR_NONE; + + /* Write data, drop clock */ + if(packet_out & TDO) data |= TDI_BIT; + if(packet_out & TMS) data |= TMS_BIT; + if(packet_out & TRST) data &= ~TRST_BIT; + + err |= cable_xpcusb_inout(data, bit_in); // read in bit, set data, drop clock + err |= cable_xpcusb_out(data|TCLK_BIT); // clk hi + + return err; +} + + +int cable_xpcusb_cpld_write_bit(uint8_t value) +{ + uint32_t out; + out = (value & TDO) ? 1:0; + return cable_xpcusb_write_stream(&out, 1, value & TMS); +} + +int cable_xpcusb_cpld_readwrite_bit(uint8_t value, uint8_t *inval) +{ + int r; + uint32_t out; + uint32_t in; + out = (value & TDO) ? 1:0; + r = cable_xpcusb_readwrite_stream(&out, &in, 1, value & TMS); + if ( r < 0 ) + return r; + *inval = in & 0x1; + return APP_ERR_NONE; +} + +int cable_xpcusb_write_stream(uint32_t *outstream, int len_bits, int set_last_bit) +{ + return cable_xpcusb_readwrite_stream(outstream, NULL, len_bits, set_last_bit); +} + +/* + * Care has to be taken that the number of bits to be transferred + * is NOT a multiple of 4. The CPLD doesn't seem to handle that well. + */ +int cable_xpcusb_readwrite_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) +{ + int i; + int ret = APP_ERR_NONE; + uint32_t bitval; + xpc_ext_transfer_state_t xts; + uint8_t tms, tdi, sample_tdo, toggle_clock; + + // open the device, if necessary + if(h_device == NULL) { + ret = cable_xpcusb_open_cable(); + if(ret != APP_ERR_NONE) return ret; + } + + if ( !cpld_ctrl ) + { + ret = cable_xpcusb_cpld_init(); + if ( ret != APP_ERR_NONE) return ret; + } + + debug("cable_xpcusb_write_stream(), len_bits = 0x%X, set_last_bit = %i\n", len_bits, set_last_bit); + + xts.in_bits = 0; + xts.out_bits = 0; + + tms = 0; + tdi = 0; + toggle_clock = 1; + sample_tdo = 1; //automatically ignored if xts.out == NULL + + for (i = 0; i < len_bits && ret == APP_ERR_NONE; i++) + { + if ( outstream ) + bitval = outstream[i/32] & (1<<(i%32)); + else + bitval = 0; + + tms = ( i == len_bits - 1 ) ? set_last_bit:0; + tdi = bitval ? 1:0; + + debug("Adding bit for transfer, bitval = %i, set_tms = %i\n", tdi, tms); + xpcusb_add_bit_for_ext_transfer(&xts, toggle_clock, tms, tdi, sample_tdo); + + if ( xts.in_bits == (2*CPLD_MAX_BYTES - 1) ) + { + debug("Reached %i bits, doing transfer\n", (2*CPLD_MAX_BYTES - 1)); + ret = xpcusb_do_ext_transfer(&xts, instream); + } + } + + if((xts.in_bits > 0) && (ret == APP_ERR_NONE)) + { + /* CPLD doesn't like multiples of 4; add one dummy bit */ + if((xts.in_bits & 3) == 0) + { + debug("Adding dummy bit\n"); + xpcusb_add_bit_for_ext_transfer(&xts, 0, 0, 0, 0); + } + debug("Doing final transfer of sequence\n"); + ret = xpcusb_do_ext_transfer(&xts, instream); + } + + if(ret != APP_ERR_NONE) + { + fprintf(stderr, "Cable will block until next power reset\n"); + fprintf(stderr, "Closing connection to cable.\n"); + cable_xpcusb_close_cable(); + fprintf(stderr, "Aborting adv_jtag_bridge.\n"); + exit(1); + } + + return ret; +} + + +static int cable_xpcusb_open_cable(void) +{ + int if_not_claimed = 1; + timeout_timer timer; + + fprintf(stderr, "XPC USB driver opening cable\n"); + // open the device (assumes 'device' has already been set/populated) + h_device = usb_open(device); + if (h_device == NULL){ + fprintf(stderr, "XPC USB driver failed to open device\n"); + return APP_ERR_USB; + } + + // set the configuration + if (usb_set_configuration(h_device, device->config->bConfigurationValue)) + { + usb_close(h_device); + h_device = NULL; + fprintf(stderr, "XPC USB driver failed to set configuration\n"); + return APP_ERR_USB; + } + + if ( create_timer(&timer) ) + { + fprintf(stderr, "Failed to create timer\n"); + // fall back to infinite wait + while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)); + } + else + { + + while (if_not_claimed && !timedout(&timer) ) + if_not_claimed = usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber); + + if ( timedout(&timer) ) + { + fprintf(stderr, "Claiming interface timed out...\n"); + return APP_ERR_USB; + } + } + + return APP_ERR_NONE; +} + + +static void cable_xpcusb_close_cable(void) +{ + fprintf(stderr, "XPC USB driver closing cable\n"); + if(h_device != NULL) { + // release the interface cleanly + if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){ + fprintf(stderr, "Warning: failed to release usb interface\n"); + } + + // close the device + usb_close(h_device); + h_device = NULL; + } + + return; +} + +int cable_xpcusb_opt(int c, char *str) +{ + fprintf(stderr, "Unknown parameter '%c'\n", c); + return APP_ERR_BAD_PARAM; +} + +jtag_cable_t *cable_xpcusb_get_driver(void) +{ + return &dlc9_cable_driver; +} + +static int xpcusb_enumerate_bus(void) +{ + int flag; // for USB bus scanning stop condition + struct usb_bus *bus; // pointer on the USB bus + + // board detection + usb_init(); + usb_find_busses(); + usb_find_devices(); + + flag = 0; + + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (device = bus->devices; device; device = device->next) + { + if (device->descriptor.idVendor == XPCUSB_VID && + device->descriptor.idProduct == XPCUSB_PID) + { + flag = 1; + fprintf(stderr, "Found Xilinx Platform Cable USB (DLC9)\n"); + return APP_ERR_NONE; + } + } + if (flag) + break; + } + + fprintf(stderr, "Failed to find Xilinx Platform Cable USB\n"); + return APP_ERR_CABLENOTFOUND; +} + + + +static int xpcu_common_init( struct usb_dev_handle *xpcu ) +{ + int r; + + r = xpcu_request_28(xpcu, 0x11); + if (r>=0) + r = xpcu_write_gpio(xpcu, 8); + + if (r<0) + cable_xpcusb_close_cable(); + + return r; +} + + +static int cable_xpcusb_fx2_init() +{ + int r; + + r = xpcu_select_gpio(h_device, 0); + if ( r < 0 ) fprintf(stderr, "Error setting FX2 mode\n"); + cpld_ctrl = 0; + + return APP_ERR_NONE; +} + +static int cable_xpcusb_cpld_init() +{ + int r; + uint8_t zero[2] = {0,0}; + + r = xpcu_request_28(h_device, 0x11); + if (r >= 0) r = xpcu_output_enable(h_device, 1); + else fprintf(stderr, "First xpcu_request_28 failed!\n"); + if (r >= 0) r = xpcu_shift(h_device, 0xA6, 2, 2, zero, 0, NULL); + else fprintf(stderr, "xpcu_output_enable failed!\n"); + if (r >= 0) r = xpcu_request_28(h_device, 0x12); + else fprintf(stderr, "xpcu_shift for init failed!\n"); + if(r < 0) fprintf(stderr, "second xpcu_request_28 failed!\n"); + + cpld_ctrl = 1; + + return APP_ERR_NONE; +} + + +int cable_xpcusb_init() +{ + int r = APP_ERR_NONE; + uint16_t buf; + // Process to reset the XPC USB (DLC9) + if(r |= xpcusb_enumerate_bus()) { + return r; + } + + //usb_dev_handle * + h_device = usb_open(device); + + if(h_device == NULL) + { + fprintf(stderr, "Init failed to open USB device for reset\n"); + return APP_ERR_USB; + } + + if(usb_reset(h_device) != APP_ERR_NONE) + fprintf(stderr, "Failed to reset XPC-USB\n"); + + usb_close(h_device); + h_device = NULL; + + // Wait for reset!!! + sleep(1); + + // Do device initialization + if(r |= xpcusb_enumerate_bus()) + return r; + + r = cable_xpcusb_open_cable(); + if ( r ) + { + fprintf(stderr, "Open cable failed\n"); + return APP_ERR_USB; + } + + r = xpcu_common_init(h_device); + + /* Read firmware version (constant embedded in firmware) */ + + if (r>=0) r = xpcu_read_firmware_version(h_device, &buf); + if (r>=0) + { + printf("firmware version = 0x%04X (%u)\n", buf, buf); + } + + /* Read CPLD version (via GPIF) */ + + if (r>=0) r = xpcu_read_cpld_version(h_device, &buf); + if (r>=0) + { + printf("cable CPLD version = 0x%04X (%u)\n", buf, buf); + if(buf == 0) + { + printf("Warning: version '0' can't be correct. Please try resetting the cable\n"); + r = -1; + } + } + + if (r<0) + cable_xpcusb_close_cable(); + + r = cable_xpcusb_cpld_init(); + if (r<0) + cable_xpcusb_close_cable(); + + return r; +} + + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_usbblaster.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_usbblaster.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_usbblaster.c (revision 66) @@ -0,0 +1,646 @@ +/* cable_usbblaster.c - Altera USB Blaster driver for the Advanced JTAG Bridge + Copyright (C) 2008 - 2010 Nathan Yawn, nathan.yawn@opencores.org + + 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 // for usleep() +#include // for sleep() +#include // for htons() +#include // for memcpy() + +#include "usb.h" // libusb header + +#include "cable_usbblaster.h" +#include "utilities.h" +#include "errcodes.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +jtag_cable_t usbblaster_cable_driver = { + .name = "usbblaster", + .inout_func = cable_usbblaster_inout, + .out_func = cable_usbblaster_out, + .init_func = cable_usbblaster_init , + .opt_func = cable_usbblaster_opt, + .bit_out_func = cable_common_write_bit, + .bit_inout_func = cable_common_read_write_bit, + .stream_out_func = cable_usbblaster_write_stream, + .stream_inout_func = cable_usbblaster_read_stream, + .flush_func = NULL, + .opts = "p:v:", + .help = "-p [PID] Alteranate PID for USB device (hex value)\n\t-v [VID] Alternate VID for USB device (hex value)\n", + }; + +// USB constants for the USB Blaster +// Valid endpoints: 0x81, 0x02, 0x06, 0x88 +#define EP2 0x02 +#define EP1 0x81 + +// These are the Altera defaults, but can be changed on the command line +static uint32_t ALTERA_VID = 0x09FB; +static uint32_t ALTERA_PID = 0x6001; + +//#define USB_TIMEOUT 500 +#define USB_TIMEOUT 10000 + + +// Bit meanings in the command byte sent to the USB-Blaster +#define USBBLASTER_CMD_TCK 0x01 +#define USBBLASTER_CMD_TMS 0x02 +#define USBBLASTER_CMD_nCE 0x04 /* should be left low */ +#define USBBLASTER_CMD_nCS 0x08 /* must be set for byte-shift mode reads to work */ +#define USBBLASTER_CMD_TDI 0x10 +#define USBBLASTER_CMD_OE 0x20 /* appears necessary to set it to make everything work */ +#define USBBLASTER_CMD_READ 0x40 +#define USBBLASTER_CMD_BYTESHIFT 0x80 + + +static struct usb_device *usbblaster_device; +static usb_dev_handle *h_device; + +// libusb seems to give an error if we ask for a transfer larger than 64 bytes +// USBBlaster also has a max. single transaction of 63 bytes. +// So, size the max read and write to create 64-byte USB packets (reads have 2 useless bytes prepended) +#define USBBLASTER_MAX_WRITE 63 +static char data_out_scratchpad[USBBLASTER_MAX_WRITE+1]; +#define USBBLASTER_MAX_READ 62 +static char data_in_scratchpad[USBBLASTER_MAX_READ+2]; + +// Flag used to avoid unnecessary transfers +// Since clock is lowered if high (and never the other way around), +// 1 is a safe default value. +static unsigned char clock_is_high = 1; + +int cable_usbblaster_open_cable(void); +void cable_usbblaster_close_cable(void); +//int cable_usbblaster_reopen_cable(void); + +/////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------[ USB Blaster specific functions ]---*/ +///////////////////////////////////////////////////////////////////////////// + + +static int usbblaster_start_interface(struct usb_dev_handle *xpcu) +{ + // Need to send a VENDOR request OUT, request = GET_STATUS + // Other parameters are ignored + if(usb_control_msg(xpcu, (USB_ENDPOINT_OUT | USB_TYPE_VENDOR), USB_REQ_GET_STATUS, + 0, 0, NULL, 0, 1000)<0) + { + perror("usb_control_msg(start interface)"); + return APP_ERR_USB; + } + + return APP_ERR_NONE; +} + + +static int usbblaster_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf) +{ + if(usb_control_msg(xpcu, 0xC0, 0x90, 0, 3, (char*)buf, 2, USB_TIMEOUT)<0) + { + perror("usb_control_msg(0x90.0) (read_firmware_version)"); + return APP_ERR_USB; + } + + // Swap endian + *buf = htons(*buf); + //*buf = (*buf << 8) | (*buf >> 8); + + return APP_ERR_NONE; +} + + + +static int usbblaster_enumerate_bus(void) +{ + int flag; // for USB bus scanning stop condition + struct usb_bus *bus; // pointer on the USB bus + + // board detection + usb_init(); + usb_find_busses(); + usb_find_devices(); + + flag = 0; + + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (usbblaster_device = bus->devices; usbblaster_device; usbblaster_device = usbblaster_device->next) + { + if (usbblaster_device->descriptor.idVendor == ALTERA_VID && + usbblaster_device->descriptor.idProduct == ALTERA_PID) + { + flag = 1; + fprintf(stderr, "Found Altera USB-Blaster\n"); + return APP_ERR_NONE; + } + } + if (flag) + break; + } + + fprintf(stderr, "Failed to find USB-Blaster with VID 0x%0X, PID 0x%0X\n", ALTERA_VID, ALTERA_PID); + return APP_ERR_CABLENOTFOUND; +} + + +int cable_usbblaster_init(){ + int err = APP_ERR_NONE; + + // Process to reset the usb blaster + if(err |= usbblaster_enumerate_bus()) { + return err; + } + + h_device = usb_open(usbblaster_device); + + if(h_device == NULL) + { + fprintf(stderr, "Init failed to open USB device for reset\n"); + return APP_ERR_USB; + } + + if(usb_reset(h_device) != APP_ERR_NONE) + fprintf(stderr, "Failed to reset USB Blaster\n"); + + usb_close(h_device); + + // Wait for reset!!! + sleep(1); + + // Do device initialization + if(err |= usbblaster_enumerate_bus()) + return err; + + err = cable_usbblaster_open_cable(); + if(err != APP_ERR_NONE) return err; + + //usb_clear_halt(h_device, EP1); + //usb_clear_halt(h_device, EP2); + + // IMPORTANT: DO NOT SEND A REQUEST TYPE "CLASS" OR TYPE "RESERVED". This may stall the EP. + + // Some clones need this before they will start processing IN/OUT requests + if(usbblaster_start_interface(h_device) != APP_ERR_NONE) + fprintf(stderr, "Failed to start remote interface\n"); + + uint16_t buf; + if(err |= usbblaster_read_firmware_version(h_device, &buf)) + { + usb_close(h_device); + fprintf(stderr, "Failed to read firmware version\n"); + return err; + } + else + { + printf("firmware version = 0x%04X (%u)\n", buf, buf); + } + + + // USB blaster is expecting us to read 2 bytes, which are useless to us... + char ret[2]; + int rv = usb_bulk_read(h_device, EP1, ret, 2, USB_TIMEOUT); + if (rv < 0){ // But if we fail, who cares? + fprintf(stderr, "\nWarning: Failed to read post-init bytes from the EP1 FIFO (%i):\n%s", rv, usb_strerror()); + } + + return APP_ERR_NONE; +} + + +int cable_usbblaster_out(uint8_t value) +{ + int rv; // to catch return values of functions + char out; + int err = APP_ERR_NONE; + + // open the device, if necessary + if(h_device == NULL) { + rv = cable_usbblaster_open_cable(); + if(rv != APP_ERR_NONE) return rv; + } + + out = (USBBLASTER_CMD_OE | USBBLASTER_CMD_nCS); // Set output enable (appears necessary) and nCS (necessary for byte-shift reads) + + // Translate to USB blaster protocol + // USB-Blaster has no TRST pin + if(value & TCLK_BIT) + out |= USBBLASTER_CMD_TCK; + if(value & TDI_BIT) + out |= USBBLASTER_CMD_TDI; + if(value & TMS_BIT) + out |= USBBLASTER_CMD_TMS; + + + rv = usb_bulk_write(h_device, EP2, &out, 1, USB_TIMEOUT); + if (rv != 1){ + fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror()); + err |= APP_ERR_USB; + } + + if(value & TCLK_BIT) + { + clock_is_high = 1; + } + else + { + clock_is_high = 0; + } + + return err; +} + + +int cable_usbblaster_inout(uint8_t value, uint8_t *in_bit) +{ + int rv; // to catch return values of functions + char ret[3] = {0,0,0}; // Two useless bytes (0x31,0x60) always precede the useful byte + char out; + + out = (USBBLASTER_CMD_OE | USBBLASTER_CMD_nCS); // Set output enable (?) and nCS (necessary for byte-shift reads) + out |= USBBLASTER_CMD_READ; + + // Translate to USB blaster protocol + // USB-Blaster has no TRST pin + if(value & TCLK_BIT) + out |= USBBLASTER_CMD_TCK; + if(value & TDI_BIT) + out |= USBBLASTER_CMD_TDI; + if(value & TMS_BIT) + out |= USBBLASTER_CMD_TMS; + + // open the device, if necessary + if(h_device == NULL) { + rv = cable_usbblaster_open_cable(); + if(rv != APP_ERR_NONE) return rv; + } + + // Send a read request + rv = usb_bulk_write(h_device, EP2, &out, 1, USB_TIMEOUT); + if (rv != 1){ + fprintf(stderr, "\nFailed to write a read request to the EP2 FIFO:\n%s", usb_strerror()); + cable_usbblaster_close_cable(); + return APP_ERR_USB; + } + + if(value & TCLK_BIT) + { + clock_is_high = 1; + } + else + { + clock_is_high = 0; + } + + // receive the response + // Sometimes, we do a read but just get the useless 0x31,0x60 chars... + // retry until we get a 3rd byte (with real data), for a reasonable number of retries. + int retries = 0; + do { + rv = usb_bulk_read(h_device, EP1, ret, 3, USB_TIMEOUT); + if (rv < 0){ + fprintf(stderr, "\nFailed to read from the EP1 FIFO (%i):\n%s", rv, usb_strerror()); + cable_usbblaster_close_cable(); + return APP_ERR_USB; + } + + // fprintf(stderr, "Read %i bytes: 0x%X, 0x%X, 0x%X\n", rv, ret[0], ret[1], ret[2]); + retries++; + } + while((rv < 3) && (retries < 20)); + + *in_bit = (ret[2] & 0x01); /* TDO is bit 0. USB-Blaster may also set bit 1. */ + return APP_ERR_NONE; +} + + +// The usbblaster transfers the bits in the stream in the following order: +// bit 0 of the first byte received ... bit 7 of the first byte received +// bit 0 of second byte received ... etc. +int cable_usbblaster_write_stream(uint32_t *stream, int len_bits, int set_last_bit) { + int rv; // to catch return values of functions + unsigned int bytes_to_transfer, leftover_bit_length; + uint32_t leftover_bits; + int bytes_remaining; + char *xfer_ptr; + int err = APP_ERR_NONE; + + debug("cable_usbblaster_write_stream(0x%X, %d, %i)\n", stream, len, set_last_bit); + + // This routine must transfer at least 8 bits. Additionally, TMS (the last bit) + // cannot be set by 'byte shift mode'. So we need at least 8 bits to transfer, + // plus one bit to send along with TMS. + bytes_to_transfer = len_bits / 8; + leftover_bit_length = len_bits - (bytes_to_transfer * 8); + + if((!leftover_bit_length) && set_last_bit) { + bytes_to_transfer -= 1; + leftover_bit_length += 8; + } + + debug("bytes_to_transfer: %d. leftover_bit_length: %d\n", bytes_to_transfer, leftover_bit_length); + + // Not enough bits for high-speed transfer. bit-bang. + if(bytes_to_transfer == 0) { + return cable_common_write_stream(stream, len_bits, set_last_bit); + } + + // Bitbang functions leave clock high. USBBlaster assumes clock low at the start of a burst. + if(clock_is_high) + { + err |= cable_usbblaster_out(0); // Lower the clock. + } + + // Set leftover bits + leftover_bits = (stream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF; + + debug("leftover_bits: 0x%X, LSB_first_xfer = %d\n", leftover_bits, LSB_first_xfer); + + // open the device, if necessary + if(h_device == NULL) { + rv = cable_usbblaster_open_cable(); + if(rv != APP_ERR_NONE) return rv; + } + + bytes_remaining = bytes_to_transfer; + xfer_ptr = (char *) stream; + while(bytes_remaining > 0) + { + int bytes_this_xfer = (bytes_remaining > USBBLASTER_MAX_WRITE) ? USBBLASTER_MAX_WRITE:bytes_remaining; + + data_out_scratchpad[0] = USBBLASTER_CMD_BYTESHIFT | (bytes_this_xfer & 0x3F); + memcpy(&data_out_scratchpad[1], xfer_ptr, bytes_this_xfer); + + /* printf("Data packet: "); + for(i = 0; i <= bytes_to_transfer; i++) + printf("0x%X ", out[i]); + printf("\n"); */ + + rv = usb_bulk_write(h_device, EP2, data_out_scratchpad, bytes_this_xfer+1, USB_TIMEOUT); + if (rv != (bytes_this_xfer+1)){ + fprintf(stderr, "\nFailed to write to the FIFO (rv = %d):\n%s", rv, usb_strerror()); + err |= APP_ERR_USB; + break; + } + + bytes_remaining -= bytes_this_xfer; + xfer_ptr += bytes_this_xfer; + } + + clock_is_high = 0; + + // if we have a number of bits not divisible by 8, or we need to set TMS... + if(leftover_bit_length != 0) { + //printf("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit); + return cable_common_write_stream(&leftover_bits, leftover_bit_length, set_last_bit); + } + + return err; +} + + +int cable_usbblaster_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) { + int rv; // to catch return values of functions + unsigned int bytes_received = 0, total_bytes_received = 0; + unsigned int bytes_to_transfer, leftover_bit_length; + uint32_t leftover_bits, leftovers_received = 0; + unsigned char i; + int bytes_remaining; + char *xfer_ptr; + int retval = APP_ERR_NONE; + + debug("cable_usbblaster_read_stream(0x%X, %d, %i)\n", outstream[0], len_bits, set_last_bit); + + // This routine must transfer at least 8 bits. Additionally, TMS (the last bit) + // cannot be set by 'byte shift mode'. So we need at least 8 bits to transfer, + // plus one bit to send along with TMS. + bytes_to_transfer = len_bits / 8; + leftover_bit_length = len_bits - (bytes_to_transfer * 8); + + if((!leftover_bit_length) && set_last_bit) { + bytes_to_transfer -= 1; + leftover_bit_length += 8; + } + + debug("RD bytes_to_transfer: %d. leftover_bit_length: %d\n", bytes_to_transfer, leftover_bit_length); + + // Not enough bits for high-speed transfer. bit-bang. + if(bytes_to_transfer == 0) { + return cable_common_read_stream(outstream, instream, len_bits, set_last_bit); + } + + // Bitbang functions leave clock high. USBBlaster assumes clock low at the start of a burst. + if(clock_is_high) + { + // Lower the clock. + retval |= cable_usbblaster_out(0); + } + + // Zero the input, since we add new data by logical-OR + for(i = 0; i < (len_bits/32); i++) instream[i] = 0; + if(len_bits % 32) instream[i] = 0; + + // Set leftover bits + leftover_bits = (outstream[bytes_to_transfer>>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF; + debug("leftover_bits: 0x%X\n", leftover_bits); + + // open the device, if necessary + if(h_device == NULL) { + rv = cable_usbblaster_open_cable(); + if(rv != APP_ERR_NONE) return rv; + } + + // Transfer the data. USBBlaster has a max transfer size of 64 bytes. + bytes_remaining = bytes_to_transfer; + xfer_ptr = (char *) outstream; + total_bytes_received = 0; + while(bytes_remaining > 0) + { + int bytes_this_xfer = (bytes_remaining > USBBLASTER_MAX_READ) ? USBBLASTER_MAX_READ:bytes_remaining; + data_out_scratchpad[0] = USBBLASTER_CMD_BYTESHIFT | USBBLASTER_CMD_READ | (bytes_this_xfer & 0x3F); + memcpy(&data_out_scratchpad[1], xfer_ptr, bytes_this_xfer); + + /* debug("Data packet: "); + for(i = 0; i <= bytes_to_transfer; i++) debug("0x%X ", data_out_scratchpad[i]); + debug("\n"); */ + + rv = usb_bulk_write(h_device, EP2, data_out_scratchpad, bytes_this_xfer+1, USB_TIMEOUT); + if (rv != (bytes_this_xfer+1)){ + fprintf(stderr, "\nFailed to write to the EP2 FIFO (rv = %d):\n%s", rv, usb_strerror()); + cable_usbblaster_close_cable(); + return APP_ERR_USB; + } + + // receive the response + // Sometimes, we do a read but just get the useless 0x31,0x60 chars... + // retry until we get at least 3 bytes (with real data), for a reasonable number of retries. + int retries = 0; + bytes_received = 0; + do { + debug("stream read, bytes_this_xfer = %i, bytes_received = %i\n", bytes_this_xfer, bytes_received); + rv = usb_bulk_read(h_device, EP1, data_in_scratchpad, (bytes_this_xfer-bytes_received)+2, USB_TIMEOUT); + if (rv < 0){ + fprintf(stderr, "\nFailed to read stream from the EP1 FIFO (%i):\n%s", rv, usb_strerror()); + cable_usbblaster_close_cable(); + return APP_ERR_USB; + } + + /* debug("Read %i bytes: ", rv); + for(i = 0; i < rv; i++) + debug("0x%X ", data_in_scratchpad[i]); + debug("\n"); */ + + if(rv > 2) retries = 0; + else retries++; + + /* Put the received bytes into the return stream. Works for either endian. */ + for(i = 0; i < (rv-2); i++) { + // Do size/type promotion before shift. Must cast to unsigned, else the value may be + // sign-extended through the upper 16 bits of the uint32_t. + uint32_t tmp = (unsigned char) data_in_scratchpad[2+i]; + instream[(total_bytes_received+i)>>2] |= (tmp << ((i & 0x3)*8)); + } + + bytes_received += (rv-2); + total_bytes_received += (rv-2); + } + while((bytes_received < bytes_this_xfer) && (retries < 15)); + + bytes_remaining -= bytes_this_xfer; + xfer_ptr += bytes_this_xfer; + } + + clock_is_high = 0; + + // if we have a number of bits not divisible by 8 + if(leftover_bit_length != 0) { + debug("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit); + retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit); + instream[bytes_to_transfer>>2] |= (leftovers_received & 0xFF) << (8*(bytes_to_transfer & 0x3)); + } + + return retval; +} + +jtag_cable_t *cable_usbblaster_get_driver(void) +{ + return &usbblaster_cable_driver; +} + +int cable_usbblaster_opt(int c, char *str) +{ + uint32_t newvid; + uint32_t newpid; + + switch(c) { + case 'p': + if(!sscanf(str, "%x", &newpid)) { + fprintf(stderr, "p parameter must have a hex number as parameter\n"); + return APP_ERR_BAD_PARAM; + } + else { + ALTERA_PID = newpid; + } + break; + + case 'v': + if(!sscanf(str, "%x", &newvid)) { + fprintf(stderr, "v parameter must have a hex number as parameter\n"); + return APP_ERR_BAD_PARAM; + } + else { + ALTERA_VID = newvid; + } + break; + + default: + fprintf(stderr, "Unknown parameter '%c'\n", c); + return APP_ERR_BAD_PARAM; + } + return APP_ERR_NONE; +} + + +int cable_usbblaster_open_cable(void) +{ + int if_not_claimed = 1; + timeout_timer timer; + + // open the device + h_device = usb_open(usbblaster_device); + if (h_device == NULL){ + fprintf(stderr, "USBBlaster driver failed to open device\n"); + return APP_ERR_USB; + } + + // set the configuration + if (usb_set_configuration(h_device, usbblaster_device->config->bConfigurationValue)) + { + usb_close(h_device); + h_device = NULL; + fprintf(stderr, "USBBlaster driver failed to set configuration\n"); + return APP_ERR_USB; + } + + // wait until device is ready + if ( create_timer(&timer) ) + { + fprintf(stderr, "Failed to create timer\n"); + // fall back to infinite wait + while (usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)); + } + else + { + while (if_not_claimed && !timedout(&timer) ) + if_not_claimed = usb_claim_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber); + + if ( timedout(&timer) ) + { + fprintf(stderr, "Claiming interface timed out...\n"); + return APP_ERR_USB; + } + } + + return APP_ERR_NONE; +} + + +void cable_usbblaster_close_cable(void) +{ + if(h_device != NULL) { + // release the interface cleanly + if (usb_release_interface(h_device, usbblaster_device->config->interface->altsetting->bInterfaceNumber)){ + fprintf(stderr, "Warning: failed to release usb interface\n"); + } + + // close the device + usb_close(h_device); + h_device = NULL; + } + + return; +} + +/* +int cable_usbblaster_reopen_cable(void) +{ + cable_usbblaster_close_cable(); + return cable_usbblaster_open_cable(); +} +*/ Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING.classic =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING.classic (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING.classic (revision 66) @@ -0,0 +1,126 @@ +These are the notes for building the Advanced JTAG Bridge program +using the original Makefile.classic (non-autotools) method. This +method is deprecated, but this file remains as a reference. + +Nathan Yawn, nathan.yawn@opencores.org + +BUILDING + +This program doesn't use automake. It has been developed using the cygwin +environment under winXP, and should also compile under various GNU/Linux +distributions. It has been tested and is known to work with Ubuntu 9.04. +There are two sets of build flags defined in the Makefile, +one for cygwin and one for Linux - one set is used, one is commented out. +Edit the Makefile for your system: set BUILD_ENVIRONMENT to either "cygwin" +or "linux" (no quotes). + +The program may be built with support for the Advanced Debug Interface +(the default), or the legacy "debug_if" interface. To compile for the +legacy interface, __LEGACY__ should be added to CFLAGS in the Makefile +(the line is present but commented out by default). This is done via +the SUPPORT_LEGACY flag; set true to build for the legacy debug system, +false (to build for the adv_dbg_if) is the default. Note that support +for the two different debug hardware units is mutually exclusive; both +cannot be supported in the same build. + +If you are only going to use a parallel JTAG cable, and you don't want +to bother with libusb, you can set SUPPORT_USB_CABLES to false. Default +is true. Similarly, you can set SUPPORT_FTDI_CABLES false if you don't +intend to use FT2232-based JTAG cables, and don't want to bother with +libftdi. + +Some users have reported problems getting their USB-Blaster cables to +work using the standard driver. In this case, try the "ft245" driver, +as this appears to work for these users. The "ft245" driver supports +all of the same high-speed transfers that the "usbblaster" driver +supports. + +In release 2.0 and later, the adv_dbg_if core includes a "hi-speed" +mode, which is used by default. This requires a protocol change, +and so the adv_jtag_bridge must be built to match the build options +used when synthesizing the adv_dbg_if. For hi-speed mode, set +USE_HISPEED true (this is the default). For the older mode, set +USE_HISPEED to false. + +Release 2.5 added the JTAG serial port (JSP). There are three compile- +time options related to this feature. The first is +INCLUDE_JSP_SERVER, set true by default. If you synthesize the +adv_dbg_if without JSP support, or you don't intend to use it, +this may be set false. This will prevent the JSP server thread +from starting, and from polling constantly any time the target +system is running, which can take significant system resources +on the host system running adv_jtag_bridge. + +The second JSP-related option is JSP_MULTI_DEVICE_CHAIN, set true +by default. The adv_dbg_if core JSP hardware is synthesized with +support for multi-device JTAG chains by default, as this is safe +to use on any system. However, this can slow JSP performance +somewhat, particularly with USB-based cables. The hardware core may +therefore be synthesized with multi-device chain support disabled. +If your adv_dbg_if core has been synthesized with this disabled, +then you should set this option to false. Note this causes a +change in the JSP communication protocol used, so the options you +compile adv_jtag_bridge with must match the options used to +synthesize the adv_dbg_if core. This option will be ignored if +the INCLUDE_JSP_SERVER option is set false. + +The third JSP-related option is JSP_OPTIMIZE_FOR_USB, set true by +default. The JSP hardware will ignore extra bytes during read/ +write transactions. This makes it safe to transfer the maximum of +8 data bytes (plus the counts byte) on every transaction, regardless +of the number of valid data bytes. When this option is set true, +all 9 bytes are sent as a single USB transaction each time a JSP +transaction is performed, giving maximum performance using USB +cables. When this option is set false, then the counts word is +transferred first, then used to determine the minimum number of +bytes to transfer. The minimum is then transferred, which gives +better performance when using parallel JTAG cables (or bit-banging +USB cables). Note that this option does NOT change the communication +protocol used. Therefore, either setting is safe for any system - +this option affects only performance. + +DEPENDENCIES + +Adv_jtag_bridge has three (or four) dependencies: + +- The pthreads library (probably already installed) +- Cygwin only: libioperm (for parallel port device access permissions) +- libusb +- libftdi + +Since adv_jtag_bridge was written, a newer version of libusb has been +released (1.0), which used a different interface. We still use the old +interface (0.1), so be sure you install the "compatibility layer" if you +install the latest libusb. As of December 2008, libUSB-Win32 still used +v0.1, so cygwin users may not need to install any additional compatibility +layer. + +The libftdi library is optional, and only required if you are building +support for FT2232-based cables (SUPPORT_FTDI_CABLES is true). Note that +if you are installing libftdi using the software downloader / installer +that came with your OS, you may need to get two packages, "libftdi" and +"libftdi-dev." This is true for Ubuntu 10.04, and possibly other +distributions as well. + +BUGS + +GDB 6.8 has a bug which prevents it from working when no stack frame is +present (such as at start-up on a bare-metal debugger, such as this one). +A simple patch applied to GDB 6.8 will work around the problem (a general +solution is not yet available). This patch can be found in the source +directory of adv_jtag_bridge as "gdb-6.8-bz436037-reg-no-longer-active.patch", +and also in Patches/ directory at the top level of the Advanced Debug +System. + +LICENSE + +This code is based on "jp2", which was distributed under the GNU Public +License, version 2. Adv_jtag_bridge is therefore also distributed under +this license. + +WARRANTY + +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.
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/BUILDING.classic Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/src/jp-io-vpi.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/src/jp-io-vpi.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/src/jp-io-vpi.c (revision 66) @@ -0,0 +1,370 @@ +/* jp-io-vpi.c -- JTAG communications vpi plugin + Copyright (C) 2004 György Jeney, nog@sdf.lonestar.org + Modifications copyright (C) 2008 Nathan Yawn, nathan.yawn@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. */ + +/* This plugs into an rtl simulator via vpi */ + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#else +#include +#include +#include +#include +#include +#endif + +#include + +/* The vpi<->jp connection is `mastered' by jp1. Therefore we just sit doing + * `nothing', waiting for jp1 to request or send us some data */ +static uint8_t vpi_out; /* data that the sim gives to us */ + +#ifdef WIN32 +SOCKET jp_comm_m; +SOCKET jp_comm; +char msgbuf[64]; +char * get_ws_error(void); +#define GET_ERR_MSG get_ws_error() +#ifndef EAGAIN +#define EAGAIN WSAEWOULDBLOCK +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#else +static int jp_comm_m; /* The listening socket */ +static int jp_comm; /* The socket for communitateing with jp1 */ +#define GET_ERR_MSG strerror(errno) +#endif + +#ifndef SOCKET_ERROR +#define SOCKET_ERROR -1 +#endif + + +static int jp_got_con; /* Have we got a connection ? */ + +static int count_comp; /* Has the predetermined cycle-count been reached ? */ +static int jp_waiting; /* Is jp-waiting for count_comp ? */ + +int jp_check_con(); + +/*---------------------------------------------[ VPI interface to the sim ]---*/ +/* Sends a byte from the sim */ +int vpi_jp_out(char *xx) +{ + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + s_vpi_value value; + + if(!argv) { + vpi_printf("$jp_out: missing destination argument\n"); + vpi_free_object(argv); + return 0; + } + vpiHandle dat_to = vpi_scan(argv); + if(vpi_get(vpiType, dat_to) != vpiNet) { + vpi_printf("$jp_out: Must have a net as argument!!\n"); + vpi_free_object(argv); + return 0; + } + + value.format = vpiVectorVal; + vpi_get_value(dat_to, &value); + + if((value.value.vector->bval & 1)) { + vpi_free_object(argv); + return 0; + } + vpi_out = value.value.vector->aval & 1; + + vpi_free_object(argv); + + return 0; +} + +/* Sends a byte to the sim */ +int vpi_jp_in(char *xx) +{ + int ret; + uint8_t dat; + s_vpi_vecval vec; + + s_vpi_value value; + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv; + vpiHandle dat_to; + + if(!jp_got_con) { + if(!jp_check_con()) + return 0; + } + + ret = recv(jp_comm, &dat, 1, 0); + if(!ret) + return 0; + if(ret == SOCKET_ERROR) + { +#ifdef WIN32 + if(WSAGetLastError() == WSAEWOULDBLOCK) +#else + if(errno == EAGAIN) +#endif + { + return 0; + } + else { + vpi_printf("Socket recv error: %s\n", GET_ERR_MSG); + return 0; + } + +} + + + if(dat & 0x80) { + switch(dat & 0x7f) { + case 0: + /* jp1 wants the TDO */ + send(jp_comm, &vpi_out, 1, 0); + return 0; + case 1: + /* jp wants a time-out */ + if(count_comp) { + dat = 0xFF; /* A value of 0xFF is expected, but not required */ + send(jp_comm, &dat, 1, 0); + } + else { + jp_waiting = 1; + } + return 0; + } + } + + argv = vpi_iterate(vpiArgument, sys); + + /* We got the data, acknowledge it and send it on to the sim */ + if(!argv) { + vpi_printf("$jp_in: missing destination argument\n"); + vpi_free_object(argv); + return 0; + } + dat_to = vpi_scan(argv); + if(vpi_get(vpiType, dat_to) != vpiReg) { + vpi_printf("$jp_in: Must have a register (vpiReg) as argument (type is %d)!!\n", vpi_get(vpiType, dat_to)); + vpi_free_object(argv); + return 0; + } + + value.format = vpiVectorVal; + + vec.aval = (dat & 0xf) | 0x10; + vec.bval = 0; + value.value.vector = &vec; + vpi_put_value(dat_to, &value, 0, vpiNoDelay); + + vpi_free_object(argv); + + dat |= 0x10; + ret = send(jp_comm, &dat, 1, 0); + + count_comp = 0; + + return 0; +} + +/* tells us that we reached a predetermined cycle count */ +int jp_wait_time(char *xx) +{ + uint8_t dat = 0xFF; + if(jp_waiting) { + send(jp_comm, &dat, 1, 0); + jp_waiting = 0; + } + + count_comp = 1; + return 0; +} + +/*---------------------------------------------------[ VPI<->jp functions ]---*/ +int init_sock(char *xx) +{ + + struct sockaddr_in addr; + int ret; + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + s_vpi_value value; + + if(!argv) { + vpi_printf("$jp_init: missing port argument\n"); + return 0; + } + vpiHandle sock = vpi_scan(argv); +/* orig + if(vpi_get(vpiConstType, sock) != vpiStringConst) { + vpi_printf("$jp_init: Must have a string as argument!!\n"); + vpi_free_object(argv); + return 0; + } +*/ + +#ifdef WIN32 + WSADATA wsaData; + ret = WSAStartup(MAKEWORD(2,2), &wsaData); // must be called before all socket operations + if(ret != 0) { + vpi_printf("$jp_init: Winsock startup failed."); + return 0; + } +#endif + + value.format = vpiStringVal; + vpi_get_value(sock, &value); + + addr.sin_family = AF_INET; + addr.sin_port = htons((uint16_t)atoi(value.value.str)); + addr.sin_addr.s_addr = INADDR_ANY; + memset(addr.sin_zero, '\0', sizeof(addr.sin_zero)); + + jp_comm_m = socket(PF_INET, SOCK_STREAM, 0); +#ifdef WIN32 + if(jp_comm_m == INVALID_SOCKET) +#else + if(jp_comm_m < 0) +#endif + { + fprintf(stderr, "Unable to create comm socket: %s\n", GET_ERR_MSG); + return 0; + } + + if(bind(jp_comm_m, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) { + fprintf(stderr, "Unable to bind the socket: %s\n", GET_ERR_MSG); + return 0; + } + + if(listen(jp_comm_m, 1) == SOCKET_ERROR) { + fprintf(stderr, "Unable to listen: %s\n", GET_ERR_MSG); + return 0; + } + +#ifdef WIN32 + u_long arg = 1; + ioctlsocket(jp_comm_m, FIONBIO, &arg); +#else + ret = fcntl(jp_comm_m, F_GETFL); + ret |= O_NONBLOCK; + fcntl(jp_comm_m, F_SETFL, ret); +#endif + + jp_got_con = 0; + jp_waiting = 0; + return 0; +} + +/* Checks to see if we got a connection */ +int jp_check_con() +{ + int ret; + + if((jp_comm = accept(jp_comm_m, NULL, NULL)) == SOCKET_ERROR) { +#ifdef WIN32 + if(WSAGetLastError() == WSAEWOULDBLOCK) +#else + if(errno == EAGAIN) +#endif + return 0; + fprintf(stderr, "Unable to accept connection: %s\n", GET_ERR_MSG); + return 0; + } + + + // Set the comm socket to non-blocking. + // Close the server socket, so that the port can be taken again + // if the simulator is reset. +#ifdef WIN32 + u_long arg = 1; + ioctlsocket(jp_comm, FIONBIO, &arg); + closesocket(jp_comm_m); +#else + ret = fcntl(jp_comm, F_GETFL); + ret |= O_NONBLOCK; + fcntl(jp_comm, F_SETFL, ret); + close(jp_comm_m); +#endif + + vpi_printf("JTAG communication connected!\n"); + jp_got_con = 1; + return 1; +} + +/*------------------------------------------------------------[ VPI stuff ]---*/ +static void jtag_register() +{ + s_vpi_systf_data tf_data; + + tf_data.type = vpiSysTask; + tf_data.tfname = "$jp_in"; + tf_data.calltf = vpi_jp_in; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$jp_out"; + tf_data.calltf = vpi_jp_out; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$jp_init"; + tf_data.calltf = init_sock; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$jp_wait_time"; + tf_data.calltf = jp_wait_time; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + vpi_register_systf(&tf_data); +} + +void (*vlog_startup_routines[])() = { + jtag_register, + 0 +}; + + +#ifdef WIN32 +char *get_ws_error(void) +{ + snprintf(msgbuf, 64, "%d", WSAGetLastError()); + return msgbuf; +} +#endif + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_linux_x86/Makefile =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_linux_x86/Makefile (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_linux_x86/Makefile (revision 66) @@ -0,0 +1,20 @@ + +SRCDIR=../src/ +CC = gcc + +# The location of the ModelSim installation, used +# to build the C lib for VPI. Must contain a subdir with +# vpi_user.h. +MODEL=/opt/altera10/modelsim_ase + + + +default: vpi + +# This is for ModelSim under Linux (x86/32) +# If RH v7.1 or lower, add -noinhibit-exec +jp-io-vpi.so: $(SRCDIR)jp-io-vpi.c Makefile + $(CC) -fPIC -c -I$(MODEL)/include $(SRCDIR)jp-io-vpi.c -o jp-io-vpi.o + $(CC) -shared -Bsymbolic -o jp-io-vpi.so jp-io-vpi.o -lc + +vpi: jp-io-vpi.so Makefile Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/jp-io-vpi.dll =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/jp-io-vpi.dll =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/jp-io-vpi.dll (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/jp-io-vpi.dll (revision 66)
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/jp-io-vpi.dll Property changes : Added: svn:executable Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/Makefile =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/Makefile (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/modelsim_win32/Makefile (revision 66) @@ -0,0 +1,27 @@ + +SRCDIR=../src/ + +# The location of the ModelSim installation, used +# to build the C lib for VPI. Used by MinGW, so use windows dir name, not /cygdrive/... +MODEL=c:/altera/90/modelsim_ase + +# Different installs of Modelsim keep their libraries in different +# directories (e.g. the version that comes with the Altera web version). +# This directory must contain mtipli.dll +MODEL_LIB=$(MODEL)/win32aloem + +# If building under windows, Modelsim requires that the VPI +# library be compiled with MinGW, NOT cygwin GCC. The location +# here is the default used by the auto-installer. +MINGW_CC = c:/MinGW/bin/mingw32-gcc.exe + + +default: vpi + +# This is for ModelSim under cygwin. Modelsim requires the shared lib +# to be compiled with MinGW, not cygwin GCC. +jp-io-vpi.dll: $(SRCDIR)jp-io-vpi.c Makefile + $(MINGW_CC) -DWIN32 -c -I$(MODEL)/include $(SRCDIR)jp-io-vpi.c -o jp-io-vpi.o + $(MINGW_CC) -DWIN32 -shared -Bsymbolic -o jp-io-vpi.dll jp-io-vpi.o -L$(MODEL_LIB) -lmtipli -lws2_32 + +vpi: jp-io-vpi.dll Makefile \ No newline at end of file Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/Makefile =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/Makefile (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/Makefile (revision 66) @@ -0,0 +1,18 @@ + + +modelsim_win32: modelsim_win32/jp-io-vpi.dll + +modelsim_linux_x86: modelsim_linux_x86/jp-io-vpi.so + +icarus: icarus/jp-io-vpi.vpi + + + +modelsim_win32/jp-io-vpi.dll: src/jp-io-vpi.c + cd modelsim_win32 && make + +modelsim_linux_x86/jp-io-vpi.so: src/jp-io-vpi.c + cd modelsim_linux_x86 && make + +icarus/jp-io-vpi.vpi: src/jp-io-vpi.c + cd icarus && make \ No newline at end of file Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/icarus/Makefile =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/icarus/Makefile (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/sim_lib/icarus/Makefile (revision 66) @@ -0,0 +1,12 @@ + +SRCDIR=../src/ + + + +default: vpi + +# This is for the Icarus simulator. +jp-io-vpi.vpi: $(SRCDIR)jp-io-vpi.c + iverilog-vpi $(SRCDIR)jp-io-vpi.c + +vpi: jp-io-vpi.vpi Makefile \ No newline at end of file Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.c (revision 66) @@ -0,0 +1,513 @@ +/* cable_usbblaster_ftdi.c - Alternate, libFTDI-based Altera USB Blaster driver + for the Advanced JTAG Bridge. Originally by Xianfeng Zheng. + Copyright (C) 2009 Xianfeng Zeng + 2009 - 2010 Nathan Yawn, nathan.yawn@opencores.org + + 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 // for usleep() +#include // for sleep() +#include // for htons() +#include +#include +#include + +#include "ftdi.h" // libftdi header + +#include "cable_ft245.h" +#include "errcodes.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +jtag_cable_t ft245_cable_driver = { + .name = "ft245", + .inout_func = cable_ft245_inout, + .out_func = cable_ft245_out, + .init_func =cable_ft245_init , + .opt_func = cable_ft245_opt, + .bit_out_func = cable_common_write_bit, + .bit_inout_func = cable_common_read_write_bit, +#if 1 + .stream_out_func = cable_ft245_write_stream , + .stream_inout_func = cable_ft245_read_stream, +#else + .stream_out_func = cable_common_write_stream , + .stream_inout_func = cable_common_read_stream, +#endif + .flush_func = NULL, + .opts = "p:v:", + .help = "-p [PID] Alteranate PID for USB device (hex value)\n\t-v [VID] Alternate VID for USB device (hex value)\n", +}; + +// USBBlaster has a max. single transaction of 63 bytes. We assume +// the FT245 has the same limit. +// So, size the max read and write to create 64-byte USB packets +#define USBBLASTER_MAX_WRITE 63 +static uint8_t data_out_scratchpad[USBBLASTER_MAX_WRITE+1]; +#define USBBLASTER_MAX_READ 62 +static uint8_t data_in_scratchpad[USBBLASTER_MAX_READ+2]; + +// USB constants for the USB Blaster, can be changed on the command line +static uint32_t ALTERA_VID = 0X09FB; +static uint32_t ALTERA_PID = 0x6001; + + +static struct ftdi_context ftdic; + +/////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------[ USB Blaster specific functions ]---*/ +///////////////////////////////////////////////////////////////////////////// + +// +// libusb does not work with my 3C25, but it works with libfdti. +// Following code is ported from http://www.ixo.de/info/usb_jtag/ +// ZXF, 2009-10-22 +// + +int usb_blaster_buf_write(uint8_t *buf, int size, uint32_t* bytes_written) +{ + int retval; + + debug("ft245 usb_blaster_buf_write %02X (%d)\n", buf[0], size); + + if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0) { + *bytes_written = 0; + printf("ftdi_write_data: %s\n", ftdi_get_error_string(&ftdic)); + return -1; + } else { + *bytes_written = retval; + return 0; + } +} + +int usb_blaster_buf_read(uint8_t* buf, int size, uint32_t* bytes_read) +{ + int retval; + int timeout = 100; + *bytes_read = 0; + + while ((*bytes_read < size) && timeout--) { + if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0) { + *bytes_read = 0; + printf("ftdi_read_data: %s\n", ftdi_get_error_string(&ftdic)); + return -1; + } + *bytes_read += retval; + } + + debug("ft245 usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read); + + return 0; +} + +/* The following code doesn't fully utilize the possibilities of the USB-Blaster. It + * writes one byte per JTAG pin state change at a time; it doesn't even try to buffer + * data up to the maximum packet size of 64 bytes. + * + * The USB-Blaster offers a byte-shift mode to transmit up to 504 data bits + * (bidirectional) in a single USB packet. A header byte has to be sent as the first + * byte in a packet with the following meaning: + * + * Bit 7 (0x80): Must be set to indicate byte-shift mode. + * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write. + * Bit 5..0: Define the number N of following bytes + * + * All N following bytes will then be clocked out serially on TDI. If Bit 6 was set, + * it will afterwards return N bytes with TDO data read while clocking out the TDI data. + * LSB of the first byte after the header byte will appear first on TDI. + */ + +/* Simple bit banging mode: + * + * Bit 7 (0x80): Must be zero (see byte-shift mode above) + * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO in return. + * Bit 5 (0x20): Unknown; for now, set to one. + * Bit 4 (0x10): TDI Output. + * Bit 3 (0x08): Unknown; for now, set to one. + * Bit 2 (0x04): Unknown; for now, set to one. + * Bit 1 (0x02): TMS Output. + * Bit 0 (0x01): TCK Output. + * + * For transmitting a single data bit, you need to write two bytes. Up to 64 bytes can be + * combined in a single USB packet (but this is not done in the code below). It isn't + * possible to read a data without transmitting data. + */ + +#define FTDI_TCK 0 +#define FTDI_TMS 1 +#define FTDI_TDI 4 +#define FTDI_READ 6 +#define FTDI_SHMODE 7 +#define FTDI_OTHERS ((1<<2)|(1<<3)|(1<<5)) + +void usb_blaster_write(int tck, int tms, int tdi) +{ + uint8_t buf[1]; + uint32_t count; + + debug("---- usb_blaster_write(%d,%d,%d)\n", tck,tms,tdi); + + buf[0] = FTDI_OTHERS | (tck?(1<>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF; + + debug("leftover_bits: 0x%X, LSB_first_xfer = %d\n", leftover_bits, LSB_first_xfer); + + bytes_remaining = bytes_to_transfer; + xfer_ptr = (char *) stream; + while(bytes_remaining > 0) + { + int bytes_this_xfer = (bytes_remaining > USBBLASTER_MAX_WRITE) ? USBBLASTER_MAX_WRITE:bytes_remaining; + + data_out_scratchpad[0] = (1<>2] >> ((bytes_to_transfer & 0x3) * 8)) & 0xFF; + debug("leftover_bits: 0x%X\n", leftover_bits); + + // Transfer the data. USBBlaster has a max transfer size of 64 bytes. + bytes_remaining = bytes_to_transfer; + xfer_ptr = (char *) outstream; + total_bytes_received = 0; + while(bytes_remaining > 0) + { + int bytes_this_xfer = (bytes_remaining > USBBLASTER_MAX_READ) ? USBBLASTER_MAX_READ:bytes_remaining; + data_out_scratchpad[0] = (1< 0) retries = 0; + else retries++; + + /* Put the received bytes into the return stream. Works for either endian. */ + for(i = 0; i < count; i++) { + // Do size/type promotion before shift. Must cast to unsigned, else the value may be + // sign-extended through the upper 16 bits of the uint32_t. + uint32_t tmp = (unsigned char) data_in_scratchpad[i]; + instream[(total_bytes_received+i)>>2] |= (tmp << ((i & 0x3)*8)); + } + + bytes_received += count; + total_bytes_received += count; + } + while((bytes_received < bytes_this_xfer) && (retries < 15)); + + bytes_remaining -= bytes_this_xfer; + xfer_ptr += bytes_this_xfer; + } + + // if we have a number of bits not divisible by 8 + if(leftover_bit_length != 0) { + debug("Doing leftovers: (0x%X, %d, %d)\n", leftover_bits, leftover_bit_length, set_last_bit); + retval |= cable_common_read_stream(&leftover_bits, &leftovers_received, leftover_bit_length, set_last_bit); + instream[bytes_to_transfer>>2] |= (leftovers_received & 0xFF) << (8*(bytes_to_transfer & 0x3)); + } + + return retval; +} + + +int cable_ft245_out(uint8_t value) +{ + int tck = 0; + int tms = 0; + int tdi = 0; + + // Translate to USB blaster protocol + // USB-Blaster has no TRST pin + if(value & TCLK_BIT) + tck = 1; + if(value & TDI_BIT) + tdi = 1;; + if(value & TMS_BIT) + tms = 1; + + usb_blaster_write(tck, tms, tdi); + + return 0; +} + +int cable_ft245_inout(uint8_t value, uint8_t *in_bit) +{ + int tck = 0; + int tms = 0; + int tdi = 0; + + // Translate to USB blaster protocol + // USB-Blaster has no TRST pin + if(value & TCLK_BIT) + tck = 1; + if(value & TDI_BIT) + tdi = 1; + if(value & TMS_BIT) + tms = 1; + + *in_bit = usb_blaster_write_read(tck, tms, tdi); + + return 0; +} + +int cable_ft245_init(void) +{ + uint8_t latency_timer; + + printf("'usb_blaster' interface using libftdi\n"); + + if (ftdi_init(&ftdic) < 0) { + printf("ftdi_init failed!"); + return -1; + } + + /* context, vendor id, product id */ + if (ftdi_usb_open(&ftdic, ALTERA_VID, ALTERA_PID) < 0) { + printf("unable to open ftdi device with VID 0x%0X, PID 0x%0X: %s\n", ALTERA_VID, ALTERA_PID, ftdic.error_str); + return -1; + } + + if (ftdi_usb_reset(&ftdic) < 0) { + printf("unable to reset ftdi device\n"); + return -1; + } + + if (ftdi_set_latency_timer(&ftdic, 2) < 0) { + printf("unable to set latency timer\n"); + return -1; + } + + if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) { + printf("unable to get latency timer\n"); + return -1; + } else { + printf("current latency timer: %i\n", latency_timer); + } + + ftdi_disable_bitbang(&ftdic); + + usb_blaster_speed(300000); + + return 0; +} + +jtag_cable_t *cable_ft245_get_driver(void) +{ + return &ft245_cable_driver; +} + + +int cable_ft245_opt(int c, char *str) +{ + uint32_t newvid; + uint32_t newpid; + + switch(c) { + case 'p': + if(!sscanf(str, "%x", &newpid)) { + fprintf(stderr, "p parameter must have a hex number as parameter\n"); + return APP_ERR_BAD_PARAM; + } + else { + ALTERA_PID = newpid; + } + break; + + case 'v': + if(!sscanf(str, "%x", &newvid)) { + fprintf(stderr, "v parameter must have a hex number as parameter\n"); + return APP_ERR_BAD_PARAM; + } + else { + ALTERA_VID = newvid; + } + break; + + default: + fprintf(stderr, "Unknown parameter '%c'\n", c); + return APP_ERR_BAD_PARAM; + } + return APP_ERR_NONE; +} + +
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft2232.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft2232.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft2232.c (revision 66) @@ -0,0 +1,948 @@ +/* cable_ft2232.c - FT2232 based cable driver for the Advanced JTAG Bridge + Copyright (C) 2008 Arnim Laeuger, arniml@opencores.org + Copyright (C) 2009 José Ignacio Villar, jose@dte.us.es + + 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 "cable_ft2232.h" +#include "errcodes.h" +int debug = 0; + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +jtag_cable_t ft2232_cable_driver = { + .name = "ft2232", + .inout_func = NULL, + .out_func = NULL, + .init_func = cable_ftdi_init, + .opt_func = cable_ftdi_opt, + .bit_out_func = cable_ftdi_write_bit, + .bit_inout_func = cable_ftdi_read_write_bit, + .stream_out_func = cable_ftdi_write_stream, + .stream_inout_func = cable_ftdi_read_stream, + .flush_func = cable_ftdi_flush, + .opts = "p:v:", + .help = "-p [PID] Alteranate PID for USB device (hex value)\n\t-v [VID] Alternate VID for USB device (hex value)\n", +}; + +usbconn_t * usbconn_ftdi_connect(); +int my_ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size); +char *my_ftdi_get_error_string (struct ftdi_context *ftdi); +int my_ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size); +int my_ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, const char* description, const char* serial); +void my_ftdi_deinit(struct ftdi_context *ftdi); +int my_ftdi_usb_purge_buffers(struct ftdi_context *ftdi); +int my_ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi); +int my_ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi); +int my_ftdi_usb_reset(struct ftdi_context *ftdi); +int my_ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency); +int my_ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate); +int my_ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize); +int my_ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize); +int my_ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable); +int my_ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable); +int my_ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode); +int my_ftdi_usb_close(struct ftdi_context *ftdi); + +static int usbconn_ftdi_common_open( usbconn_t *conn); +static void usbconn_ftdi_free( usbconn_t *conn ); +static int seq_purge(struct ftdi_context *ftdic, int purge_rx, int purge_tx); +static int seq_reset(struct ftdi_context *ftdic); +static int usbconn_ftdi_flush( ftdi_param_t *params ); +static int usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len ); +static int usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv ); +static int usbconn_ftdi_mpsse_open( usbconn_t *conn ); +static int usbconn_ftdi_close(usbconn_t *conn); + +usbconn_driver_t usbconn_ft2232_mpsse_driver = { + "ftdi-mpsse", + usbconn_ftdi_connect, + usbconn_ftdi_free, + usbconn_ftdi_mpsse_open, + usbconn_ftdi_close, + usbconn_ftdi_read, + usbconn_ftdi_write +}; + +usbconn_cable_t usbconn_ft2232_mpsse_CableID2= { + "CableID2", /* cable name */ + "CableID2", /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0x6010 /* PID */ +}; + +static usbconn_t *ft2232_device; + + + +/// ---------------------------------------------------------------------------------------------- +/// libftdi wrappers for debugging purposes. +/// ---------------------------------------------------------------------------------------------- + +void print_buffer(unsigned char *buf, int size) { + int i=0; + for(i=0; i 1) print_buffer(buf, size); + return ftdi_write_data(ftdi, buf, size); +} + +char *my_ftdi_get_error_string (struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_get_error_string(ftdi);\n"); + return ftdi_get_error_string (ftdi); +} + +int my_ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) { + int ret = 0; + debug("[MYDBG] ftdi_read_data(ftdi, buf=BUFFER[%d], size=%d);\n", size, size); + ret = ftdi_read_data(ftdi, buf, size); + if(debug) print_buffer(buf, size); + return ret; +} + +int my_ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, const char* description, const char* serial) { + debug("[MYDBG] ftdi_usb_open_desc(ftdi, vendor=%d, product=%d, description=DESCRIPTION, serial=SERIAL);\n", vendor, product); + return ftdi_usb_open_desc(ftdi, vendor, product, description, serial); +} + +void my_ftdi_deinit(struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_deinit(ftdi);\n"); + ftdi_deinit(ftdi); +} + +int my_ftdi_usb_purge_buffers(struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_usb_purge_buffers(ftdi);\n"); + return ftdi_usb_purge_buffers(ftdi); +} + +int my_ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_usb_purge_rx_buffer(ftdi);\n"); + return ftdi_usb_purge_rx_buffer(ftdi); +} + +int my_ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_usb_purge_tx_buffer(ftdi);\n"); + return ftdi_usb_purge_tx_buffer(ftdi); +} + +int my_ftdi_usb_reset(struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_usb_reset(ftdi);\n"); + return ftdi_usb_reset(ftdi); +} + +int my_ftdi_set_latency_timer(struct ftdi_context *ftdi, unsigned char latency) { + debug("[MYDBG] ftdi_set_latency_timer(ftdi, latency=0x%02x);\n", latency); + return ftdi_set_latency_timer(ftdi, latency); +} + +int my_ftdi_set_baudrate(struct ftdi_context *ftdi, int baudrate) { + debug("[MYDBG] ftdi_set_baudrate(ftdi, baudrate=%d);\n", baudrate); + return ftdi_set_baudrate(ftdi, baudrate); +} + +int my_ftdi_read_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) { + debug("[MYDBG] ftdi_read_data_set_chunksize(ftdi, chunksize=%u);\n", chunksize); + return ftdi_read_data_set_chunksize(ftdi, chunksize); +} + +int my_ftdi_write_data_set_chunksize(struct ftdi_context *ftdi, unsigned int chunksize) { + debug("[MYDBG] ftdi_write_data_set_chunksize(ftdi, chunksize=%u);\n", chunksize); + return ftdi_write_data_set_chunksize(ftdi, chunksize); +} + +int my_ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch, unsigned char enable) { + debug("[MYDBG] ftdi_set_event_char(ftdi, eventch=0x%02x, enable=0x%02x);\n", eventch, enable); + return ftdi_set_event_char(ftdi, eventch, enable); +} + +int my_ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch, unsigned char enable) { + debug("[MYDBG] ftdi_set_error_char(ftdi, errorch=0x%02x, enable=0x%02x);\n", errorch, enable); + return ftdi_set_error_char(ftdi, errorch, enable); +} + +int my_ftdi_set_bitmode(struct ftdi_context *ftdi, unsigned char bitmask, unsigned char mode) { + debug("[MYDBG] ftdi_set_bitmode(ftdi, bitmask=0x%02x, mode=0x%02x);\n", bitmask, mode); + return ftdi_set_bitmode(ftdi, bitmask, mode); +} + +int my_ftdi_usb_close(struct ftdi_context *ftdi) { + debug("[MYDBG] ftdi_usb_close(ftdi);\n"); + return ftdi_usb_close(ftdi); +} + + + +/// ---------------------------------------------------------------------------------------------- +/// USBconn FTDI MPSSE subsystem +/// ---------------------------------------------------------------------------------------------- + + +static int usbconn_ftdi_common_open(usbconn_t *conn) { + ftdi_param_t *params = conn->params; + struct ftdi_context * ftdic = params->ftdic; + int error; + + printf("Initializing USB device\n"); + + if ((error = my_ftdi_usb_open_desc(ftdic, conn->cable->vid, conn->cable->pid, NULL, NULL))) { + if (error == -1) printf("usb_find_busses() failed\n"); + else if (error == -2) printf("usb_find_devices() failed\n"); + else if (error == -3) printf("usb device not found with VID 0x%0X, PID 0x%0X\n", conn->cable->vid, conn->cable->pid); + else if (error == -4) printf("unable to open device\n"); + else if (error == -5) printf("unable to claim device\n"); + else if (error == -6) printf("reset failed\n"); + else if (error == -7) printf("set baudrate failed\n"); + else if (error == -8) printf("get product description failed\n"); + else if (error == -9) printf("get serial number failed\n"); + else if (error == -10) printf("unable to close device\n"); + + my_ftdi_deinit(ftdic); + ftdic = NULL; + + printf("Can't open FTDI usb device\n"); + return(-1); + } + + return 0; +} + +static int seq_purge(struct ftdi_context *ftdic, int purge_rx, int purge_tx) { + int r = 0; + unsigned char buf; + + if ((r = my_ftdi_usb_purge_buffers( ftdic )) < 0) + printf("my_ftdi_usb_purge_buffers() failed\n"); + if (r >= 0) if ((r = my_ftdi_read_data( ftdic, &buf, 1 )) < 0) + printf("my_ftdi_read_data() failed\n"); + + return r < 0 ? -1 : 0; +} + +static int seq_reset(struct ftdi_context *ftdic) { + + if (my_ftdi_usb_reset( ftdic ) < 0) { + printf("my_ftdi_usb_reset() failed\n"); + return -1; + } + + if(seq_purge(ftdic, 1, 1) < 0) + return -1; + + return 0; +} + +static int usbconn_ftdi_flush( ftdi_param_t *params ) + { + int xferred; + int recvd = 0; + + if (!params->ftdic) + return -1; + + if (params->send_buffered == 0) + return 0; + + if ((xferred = my_ftdi_write_data( params->ftdic, params->send_buf, params->send_buffered )) < 0) + printf("my_ftdi_write_data() failed\n"); + + if (xferred < params->send_buffered) { + printf("Written fewer bytes than requested.\n"); + return -1; + } + + params->send_buffered = 0; + + /* now read all scheduled receive bytes */ + if (params->to_recv) { + if (params->recv_write_idx + params->to_recv > params->recv_buf_len) { + /* extend receive buffer */ + params->recv_buf_len = params->recv_write_idx + params->to_recv; + if (params->recv_buf) + params->recv_buf = (uint8_t *)realloc( params->recv_buf, params->recv_buf_len ); + } + + if (!params->recv_buf) { + printf("Receive buffer does not exist.\n"); + return -1; + } + + while (recvd == 0) + if ((recvd = my_ftdi_read_data( params->ftdic, &(params->recv_buf[params->recv_write_idx]), params->to_recv )) < 0) + printf("Error from my_ftdi_read_data()\n"); + + if (recvd < params->to_recv) + printf("Received less bytes than requested.\n"); + + params->to_recv -= recvd; + params->recv_write_idx += recvd; + } + + debug("[MYDBG] FLUSHING xferred=%u\n", xferred); + return xferred < 0 ? -1 : xferred; +} + +static int usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len ) { + ftdi_param_t *params = conn->params; + int cpy_len; + int recvd = 0; + + if (!params->ftdic) + return -1; + + /* flush send buffer to get all scheduled receive bytes */ + if (usbconn_ftdi_flush( params ) < 0) + return -1; + + if (len == 0) + return 0; + + /* check for number of remaining bytes in receive buffer */ + cpy_len = params->recv_write_idx - params->recv_read_idx; + if (cpy_len > len) + cpy_len = len; + len -= cpy_len; + + if (cpy_len > 0) { + /* get data from the receive buffer */ + memcpy( buf, &(params->recv_buf[params->recv_read_idx]), cpy_len ); + params->recv_read_idx += cpy_len; + if (params->recv_read_idx == params->recv_write_idx) + params->recv_read_idx = params->recv_write_idx = 0; + } + + if (len > 0) { + /* need to get more data directly from the device */ + while (recvd == 0) + if ((recvd = my_ftdi_read_data( params->ftdic, &(buf[cpy_len]), len )) < 0) + printf("Error from my_ftdi_read_data()\n"); + } + debug("[MYDBG] READ cpy_len=%u ; len=%u\n", cpy_len, len); + return recvd < 0 ? -1 : cpy_len + len; +} + +static int usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv ) { + + ftdi_param_t *params = conn->params; + int xferred = 0; + + if (!params->ftdic) + return -1; + + /* this write function will try to buffer write data + buffering will be ceased and a flush triggered in two cases. */ + + /* Case A: max number of scheduled receive bytes will be exceeded + with this write + Case B: max number of scheduled send bytes has been reached */ + if ((params->to_recv + recv > FTDI_MAXRECV) || ((params->send_buffered > FTDX_MAXSEND) && (params->to_recv == 0))) + xferred = usbconn_ftdi_flush(params); + + if (xferred < 0) + return -1; + + /* now buffer this write */ + if (params->send_buffered + len > params->send_buf_len) { + params->send_buf_len = params->send_buffered + len; + if (params->send_buf) + params->send_buf = (uint8_t *)realloc( params->send_buf, params->send_buf_len); + } + + if (params->send_buf) { + memcpy( &(params->send_buf[params->send_buffered]), buf, len ); + params->send_buffered += len; + if (recv > 0) + params->to_recv += recv; + + if (recv < 0) { + /* immediate write requested, so flush the buffered data */ + xferred = usbconn_ftdi_flush( params ); + } + + debug("[MYDBG] WRITE inmediate=%s ; xferred=%u ; len=%u\n", ((recv < 0) ? "TRUE" : "FALSE"), xferred, len); + return xferred < 0 ? -1 : len; + } + else { + printf("Send buffer does not exist.\n"); + return -1; + } +} + +static int usbconn_ftdi_mpsse_open( usbconn_t *conn ) { + ftdi_param_t *params = conn->params; + struct ftdi_context *ftdic = params->ftdic; + + int r = 0; + + if (usbconn_ftdi_common_open(conn) < 0) { + printf("Connection failed\n"); + return -1; + } + + /* This sequence might seem weird and containing superfluous stuff. + However, it's built after the description of JTAG_InitDevice + Ref. FTCJTAGPG10.pdf + Intermittent problems will occur when certain steps are skipped. */ + + r = seq_reset( ftdic ); + if (r >= 0) + r = seq_purge( ftdic, 1, 0 ); + + if (r >= 0) + if ((r = my_ftdi_write_data_set_chunksize( ftdic, FTDX_MAXSEND_MPSSE )) < 0) + puts( my_ftdi_get_error_string( ftdic ) ); + + if (r >= 0) + if ((r = my_ftdi_read_data_set_chunksize( ftdic, FTDX_MAXSEND_MPSSE )) < 0) + puts( my_ftdi_get_error_string( ftdic ) ); + + /* set a reasonable latency timer value + if this value is too low then the chip will send intermediate result data + in short packets (suboptimal performance) */ + if (r >= 0) + if ((r = my_ftdi_set_latency_timer( ftdic, 16 )) < 0) + printf("my_ftdi_set_latency_timer() failed\n"); + + if (r >= 0) + if ((r = my_ftdi_set_bitmode( ftdic, 0x0b, BITMODE_MPSSE )) < 0) + printf("my_ftdi_set_bitmode() failed\n"); + + if (r >= 0) + if ((r = my_ftdi_usb_reset( ftdic )) < 0) + printf("my_ftdi_usb_reset() failed\n"); + + if (r >= 0) + r = seq_purge( ftdic, 1, 0 ); + + /* set TCK Divisor */ + if (r >= 0) { + uint8_t buf[3] = {TCK_DIVISOR, 0x00, 0x00}; + r = usbconn_ftdi_write( conn, buf, 3, 0 ); + } + + /* switch off loopback */ + if (r >= 0) { + uint8_t buf[1] = {LOOPBACK_END}; + r = usbconn_ftdi_write( conn, buf, 1, 0 ); + } + + if (r >= 0) + r = usbconn_ftdi_read( conn, NULL, 0 ); + + if (r >= 0) + if ((r = my_ftdi_usb_reset( ftdic )) < 0) + printf("my_ftdi_usb_reset() failed\n"); + + if (r >= 0) + r = seq_purge( ftdic, 1, 0 ); + + if (r < 0) { + ftdi_usb_close( ftdic ); + ftdi_deinit( ftdic ); + /* mark ftdi layer as not initialized */ + params->ftdic = NULL; + } + + return r < 0 ? -1 : 0; +} + +static int usbconn_ftdi_close(usbconn_t *conn) { + ftdi_param_t *params = conn->params; + + if (params->ftdic) { + my_ftdi_usb_close(params->ftdic); + my_ftdi_deinit(params->ftdic); + params->ftdic = NULL; + } + + return 0; +} + +static void usbconn_ftdi_free( usbconn_t *conn ) +{ + ftdi_param_t *params = conn->params; + + if (params->send_buf) free( params->send_buf ); + if (params->recv_buf) free( params->recv_buf ); + if (params->ftdic) free( params->ftdic ); + if (params->serial) free( params->serial ); + + free( conn->params ); + free( conn ); +} + +usbconn_t * usbconn_ftdi_connect() { + + usbconn_t *conn = malloc( sizeof( usbconn_t ) ); + ftdi_param_t *params = malloc( sizeof( ftdi_param_t ) ); + struct ftdi_context *ftdic = malloc( sizeof( struct ftdi_context ) ); + + if (params) { + params->send_buf_len = FTDX_MAXSEND; + params->send_buffered = 0; + params->send_buf = (uint8_t *) malloc( params->send_buf_len ); + params->recv_buf_len = FTDI_MAXRECV; + params->to_recv = 0; + params->recv_write_idx = 0; + params->recv_read_idx = 0; + params->recv_buf = (uint8_t *) malloc( params->recv_buf_len ); + } + + if (!conn || !params || !ftdic || !params->send_buf || !params->recv_buf) { + printf("Can't allocate memory for ftdi context structures\n"); + + if (conn) free( conn ); + if (params) free( params ); + if (ftdic) free( ftdic ); + if (params->send_buf) free( params->send_buf ); + if (params->recv_buf) free( params->recv_buf ); + return NULL; + } + + conn->driver = &usbconn_ft2232_mpsse_driver; + conn->cable = &usbconn_ft2232_mpsse_CableID2; + + ftdi_init( ftdic ); + params->ftdic = ftdic; + params->pid = conn->cable->pid; + params->vid = conn->cable->vid; + params->serial = NULL; + + conn->params = params; + + printf("Structs successfully initialized\n"); + + /* do a test open with the specified cable paramters, + alternatively we could use libusb to detect the presence of the + specified USB device */ + if (usbconn_ftdi_common_open(conn) != 0) { + printf("Connection failed\n"); + usbconn_ftdi_free(conn); + printf("Freeing structures.\n"); + return NULL; + } + + my_ftdi_usb_close( ftdic ); + + printf("Connected to libftdi driver.\n"); + + return conn; +} + + + +/// ---------------------------------------------------------------------------------------------- +/// High level functions to generate Tx/Rx commands +/// ---------------------------------------------------------------------------------------------- + +int cable_ft2232_write_bytes(usbconn_t *conn, unsigned char *buf, int len, int postread) { + + int cur_command_size; + int max_command_size; + int cur_chunk_len; + int recv; + int xferred; + int i; + unsigned char *mybuf; + + if(len == 0) + return 0; + debug("write_bytes(length=%d, postread=%s)\n", len, ((postread > 0) ? "TRUE" : "FALSE")); + recv = 0; + max_command_size = min(len, 65536)+3; + mybuf = (unsigned char *) malloc( max_command_size ); + + /// Command OPCODE: write bytes + mybuf[0] = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_WRITE_NEG; + if(postread) // if postread is enabled it will buffer incoming bytes + mybuf[0] = mybuf[0] | MPSSE_DO_READ; + + // We divide the transmitting stream of bytes in chunks with a maximun length of 65536 bytes each. + while(len > 0) { + cur_chunk_len = min(len, 65536); + len = len - cur_chunk_len; + cur_command_size = cur_chunk_len + 3; + + /// Low and High bytes of the length field + mybuf[1] = (unsigned char) ( cur_chunk_len - 1); + mybuf[2] = (unsigned char) ((cur_chunk_len - 1) >> 8); + + debug("\tOPCODE: 0x%x\n", mybuf[0]); + debug("\tLENGTL: 0x%02x\n", mybuf[1]); + debug("\tLENGTH: 0x%02x\n", mybuf[2]); + + /// The rest of the command is filled with the bytes that will be transferred + memcpy(&(mybuf[3]), buf, cur_chunk_len ); + buf = buf + cur_chunk_len; + for(i = 0; i< cur_chunk_len; i++) + if(debug>1) debug("\tBYTE%3d: 0x%02x\n", i, mybuf[3+i]); + + /// Finally we can ransmit the command + xferred = usbconn_ftdi_write( conn, mybuf, cur_command_size, (postread ? cur_chunk_len : 0) ); + if(xferred != cur_command_size) + return -1; + + // If OK, the update the number of incoming bytes that are being buffered for a posterior read + if(postread) + recv = recv + cur_chunk_len; + } + debug("\tPOSTREAD: %u bytes\n", recv); + + // Returns the number of buffered incoming bytes + return recv; +} + +int cable_ft2232_write_bits(usbconn_t *conn, unsigned char *buf, int len, int postread, int with_tms) +{ + int max_command_size; + int max_chunk_len; + int cur_chunk_len; + int recv; + int xferred; + int i; + unsigned char *mybuf; + + if(len == 0) + return 0; + + max_command_size = 3; + mybuf = (unsigned char *) malloc( max_command_size ); + + if(!with_tms) { + /// Command OPCODE: write bits (can write up to 8 bits in a single command) + max_chunk_len = 8; + mybuf[0] = MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_WRITE_NEG | MPSSE_BITMODE; + } + else { + /// Command OPCODE: 0x4B write bit with tms (can write up to 1 bits in a single command) + max_chunk_len = 1; + mybuf[0] = MPSSE_WRITE_TMS|MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG; + } + + if(postread) // (OPCODE += 0x20) if postread is enabled it will buffer incoming bits + mybuf[0] = mybuf[0] | MPSSE_DO_READ; + + // We divide the transmitting stream of bytes in chunks with a maximun length of max_chunk_len bits each. + i=0; + recv = 0; + while(len > 0) { + cur_chunk_len = min(len, max_chunk_len); + len = len - cur_chunk_len; + + /// Bits length field + mybuf[1] = (unsigned char) ( cur_chunk_len - 1); + + debug("\tOPCODE: 0x%x\n", mybuf[0]); + debug("\tLENGTH: 0x%02x\n", mybuf[1]); + + if(!with_tms) { + /// The last byte of the command is filled with the bits that will be transferred + debug("\tDATA[%d] 0x%02x\n", (i/8), buf[i/8]); + mybuf[2] = buf[i/8]; + i=i+8; + } + else { + //TODO: seleccionar el bit a transmitir + mybuf[2] = 0x01 | ((buf[(i/8)] >> (i%8)) << 7); + i++; + } + + debug("\tBYTE%3d: 0x%02x\n", i, mybuf[2]); + + /// Finally we can transmmit the command + xferred = usbconn_ftdi_write( conn, mybuf, max_command_size, (postread ? 1 : 0) ); + if(xferred != max_command_size) + return -1; + + // If OK, the update the number of incoming bytes that are being buffered for a posterior read + if(postread) + recv = recv + 1; + } + debug("\tPOSTREAD: %u bytes\n", recv); + + return recv; +} + +int cable_ft2232_read_packed_bits(usbconn_t *conn, uint8_t *buf, int packet_len, int bits_per_packet, int offset) +{ + unsigned char *mybuf; + unsigned char dst_mask; + unsigned char src_mask; + int row_offset; + int dst_row; + int dst_col; + int src_row; + int src_col; + int i; + int r; + + if(packet_len == 0 || bits_per_packet == 0) + return 0; + + mybuf = (unsigned char *) malloc( packet_len ); + if((r=usbconn_ftdi_read( conn, mybuf, packet_len )) < 0) { + debug("Read failed\n"); + return -1; + } + + if(bits_per_packet < 8) { + for(i=0; i < packet_len; i++){ // rotate bits to the left side +// debug("[MYDBG] unaligned bits[%d]=%02x\n", i, mybuf[i]); + mybuf[i] = (mybuf[i] >> (8-bits_per_packet)); +// debug("[MYDBG] aligned bits[%d]=%02x\n", i, mybuf[i]); + } + for(i=offset; i < (packet_len*bits_per_packet+offset); i++) { + dst_row = i / 8; + dst_col = i % 8; + src_row = (i-offset) / bits_per_packet; + src_col = (i-offset) % bits_per_packet; + dst_mask = ~(1 << dst_col); + src_mask = (1 << src_col); +// debug("[MYDBG] i=%4d dst[%3d][%3d] dst_mask=%02x dst_val=%02x dst_masked=%02x\n", i, dst_row, dst_col, dst_mask, buf[dst_row], (buf[dst_row] & dst_mask)); +// debug("[MYDBG] i=%4d src[%3d][%3d] src_mask=%02x src_val=%02x src_masked=%02x\n", i, src_row, src_col, src_mask, mybuf[src_row], (mybuf[src_row] & src_mask)); + if(dst_col >= src_col) + buf[dst_row] = (buf[dst_row] & dst_mask) | ((mybuf[src_row] & src_mask) << (dst_col - src_col)); + else + buf[dst_row] = (buf[dst_row] & dst_mask) | ((mybuf[src_row] & src_mask) >> (dst_col - src_col)); + } + + } + else if(bits_per_packet == 8){ + row_offset = offset / 8; +// debug("[MYDBG] Row offset=%d\n", row_offset); + memcpy( &(buf[row_offset]), mybuf, packet_len); + } + else { + return -1; + } + +// debug("read_bits()-> %x\n", *buf); + return ((r < 1) ? -1 : 0); +} + +int cable_ft2232_write_stream(usbconn_t *conn, unsigned char *buf, int len, int postread, int with_tms) { + int len_bytes; + int len_bits; + int len_tms_bits; + unsigned char mybuf; + + len_tms_bits = ((with_tms) ? 1 : 0); + len_bytes = ((len -len_tms_bits) / 8); + len_bits = ((len -len_tms_bits) % 8); + + debug("[MYDBG] cable_ft2232_write_stream(len=%d postread=%d tms=%d) = %d bytes %dbits %dtms_bits\n", len, postread, with_tms, len_bytes, len_bits, len_tms_bits); + + if(len_bytes > 0) + cable_ft2232_write_bytes(conn, buf, len_bytes, postread); + + if(len_bits > 0) + cable_ft2232_write_bits(conn, &(buf[len_bytes]), len_bits, postread, 0); + + if(len_tms_bits > 0) { + mybuf = (buf[len_bytes] >> len_bits); + cable_ft2232_write_bits(conn, &mybuf, 1, postread, 1); + } + + return 0; +} + +int cable_ft2232_read_stream(usbconn_t *conn, unsigned char *buf, int len, int with_tms) { + int len_bytes; + int len_bits; + int len_tms_bits; + + len_tms_bits = ((with_tms) ? 1 : 0); + len_bytes = ((len -len_tms_bits) / 8); + len_bits = ((len -len_tms_bits) % 8); + + debug("[MYDBG] cable_ft2232_read_stream(len=%d tms=%d) = %d bytes %dbits %dtms_bits\n", len, with_tms, len_bytes, len_bits, len_tms_bits); + + if(len_bytes > 0) + cable_ft2232_read_packed_bits(conn, buf, len_bytes, 8, 0); + + if(len_bits > 0) + cable_ft2232_read_packed_bits(conn, buf, 1, len_bits, (len_bytes * 8)); + + if(len_tms_bits > 0) + cable_ft2232_read_packed_bits(conn, buf, 1, 1, (len_bits + (len_bytes * 8))); + + return 0; +} + + + +/// ---------------------------------------------------------------------------------------------- +/// Advanced Jtag debugger driver interface. +/// ---------------------------------------------------------------------------------------------- + +jtag_cable_t *cable_ftdi_get_driver(void) +{ + return &ft2232_cable_driver; +} + +int cable_ftdi_init() { + int err = APP_ERR_NONE; + int res = 0; + unsigned char *buf = malloc(10); + + ft2232_device = usbconn_ftdi_connect(); + + if((res = usbconn_ftdi_mpsse_open(ft2232_device)) != 0) + err |= APP_ERR_USB; + printf("Open MPSSE mode returned: %s\n", ((res != 0) ? "FAIL" : "OK") ); + + ftdi_param_t *params = ft2232_device->params; + //struct ftdi_context * ftdic = params->ftdic; + + buf[0]= SET_BITS_LOW; // Set value & direction of ADBUS lines + buf[1]= 0x00; // values + buf[2]= 0x1b; // direction (1 == output) + buf[3]= TCK_DIVISOR; + buf[4]= 0x01; + buf[5]= 0x00; + buf[6]= SET_BITS_HIGH; + buf[7]= ~0x04; + buf[8]= 0x04; + buf[9]= SEND_IMMEDIATE; + if(usbconn_ftdi_write( ft2232_device , buf, 10, 0) != 10) { + err |= APP_ERR_USB; + printf("Initial write failed\n"); + } + + usbconn_ftdi_flush( params ); + + return err; +} + +int cable_ftdi_close() { + usbconn_ftdi_close(ft2232_device); + usbconn_ftdi_free(ft2232_device); + + return APP_ERR_NONE; +} + +int cable_ftdi_flush() { + ftdi_param_t *params = ft2232_device->params; + usbconn_ftdi_flush( params ); + + return APP_ERR_NONE; +} + +int cable_ftdi_write_bit(uint8_t packet) { + int err = APP_ERR_NONE; + unsigned char buf; + int tms; + + buf = ((packet & TDO) ? 0x01 : 0x00); + tms = ((packet & TMS) ? 1 : 0); + + if(cable_ft2232_write_stream(ft2232_device, &buf, 1, 0, tms) < 0) + err |= APP_ERR_COMM; + + cable_ftdi_flush(); + + return err; + +} + +int cable_ftdi_read_write_bit(uint8_t packet_out, uint8_t *bit_in) { + + int err = APP_ERR_NONE; + unsigned char buf; + int tms; + + buf = ((packet_out & TDO) ? 0x01 : 0x00); + tms = ((packet_out & TMS) ? 1 : 0); + + if(cable_ft2232_write_stream(ft2232_device, &buf, 1, 1, tms) < 0) + err = APP_ERR_COMM; + + if(cable_ft2232_read_stream(ft2232_device, ((unsigned char *)bit_in), 1, tms) < 0) + err = APP_ERR_COMM; + + return err; +} + +int cable_ftdi_write_stream(uint32_t *stream, int len_bits, int set_last_bit) { + int err = APP_ERR_NONE; + + if(cable_ft2232_write_stream(ft2232_device, ((unsigned char *)stream), len_bits, 0, set_last_bit) < 0) + err |= APP_ERR_COMM; + + cable_ftdi_flush(); + + return err; +} + +int cable_ftdi_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) { + int err = APP_ERR_NONE; + if(cable_ft2232_write_stream(ft2232_device, ((unsigned char *)outstream), len_bits, 1, set_last_bit) < 0) + err |= APP_ERR_COMM; + if(cable_ft2232_read_stream(ft2232_device, ((unsigned char *)instream), len_bits, set_last_bit) < 0) + err |= APP_ERR_COMM; + + return err; +} + +int cable_ftdi_opt(int c, char *str) { + uint32_t newvid; + uint32_t newpid; + + switch(c) { + case 'p': + if(!sscanf(str, "%x", &newpid)) { + fprintf(stderr, "p parameter must have a hex number as parameter\n"); + return APP_ERR_BAD_PARAM; + } + else { + usbconn_ft2232_mpsse_CableID2.pid = newpid; + } + break; + + case 'v': + if(!sscanf(str, "%x", &newvid)) { + fprintf(stderr, "v parameter must have a hex number as parameter\n"); + return APP_ERR_BAD_PARAM; + } + else { + usbconn_ft2232_mpsse_CableID2.vid = newvid; + } + break; + + default: + fprintf(stderr, "Unknown parameter '%c'\n", c); + return APP_ERR_BAD_PARAM; + } + return APP_ERR_NONE; +} + +/// ---------------------------------------------------------------------------------------------- + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl_parse.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl_parse.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl_parse.c (revision 66) @@ -0,0 +1,492 @@ +/* bsdl_parse.c - BSDL parser for the advanced JTAG bridge + Copyright(C) 2008 - 2010 Nathan Yawn + + 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 // isspace(), etc. +#include // malloc(), strtoul(), etc. +#include "bsdl.h" // has constants + + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +char * strtoupper(char *str); +int get_line(char *filedata, int startpos, char **linedata, int filesize); +char * strchr_s(char *str, char *chars); +void parse_opcodes(char *cmdbuf, uint32_t *debug_cmd, uint32_t *user1_cmd, uint32_t *idcode_cmd); + +// We assume that no value will be more than 128 chars +char tmpbuf[128]; + + + ///////////////////////////////////////////////////////////////// + // API call: extract desired info from 1 BSDL fise + +bsdlinfo *parse_extract_values(char *bsdlfilename) +{ + FILE *fd; + int filesize; + bsdlinfo *ret; + char *filedata; + char *linedata; + char *token; + char *last; + char *cmdbuf; + int filepos = 0; + int i,j; + char done,valid,opens; + + int IR_size = -1; + uint8_t found_IR_size = 0; + uint32_t debug_cmd = TAP_CMD_INVALID; + uint32_t user1_cmd = TAP_CMD_INVALID; + uint32_t idcode_cmd = TAP_CMD_INVALID; + uint8_t found_cmds = 0; + uint32_t idcode = 0; + uint32_t idcode_mask = 0xFFFFFFFF; // 'X' is a valid char in an IDCODE, set 0's here for X's. + uint8_t found_idcode = 0; + char *entityname = NULL; + + // Open the file + fd = fopen(bsdlfilename, "r"); + if(fd == NULL) { + printf("ERROR: failed to open BSDL file %s\n", bsdlfilename); + return NULL; + } + + fseek(fd, 0, SEEK_END); + filesize = ftell(fd); + fseek(fd, 0, SEEK_SET); + + filedata = (char *) malloc(filesize); + if(filedata == NULL) { + printf("ERROR: failed to allocate memory for BSDL file %s\n", bsdlfilename); + return NULL; + } + + if(fread(filedata, 1, filesize, fd) < filesize) { // 1 long read will be faster than many short ones + printf("Warning: failed to read entire BSDL file %s\n", bsdlfilename); + } + + fclose(fd); + + + // while there's more data and not all values have been found + while((filepos < filesize) && (!found_IR_size || !found_cmds || !found_idcode)) + { + // Get a line. Replace any "--" with a \0 char + filepos = get_line(filedata, filepos, &linedata, filesize); + + // look for each value + token = strtok_r(linedata, " \t", &last); + if(token == NULL) { + printf("ERROR: End of file reached before END statement is BSDL file \'%s\'\n", bsdlfilename); + break; + } + + if(!strcmp(strtoupper(token), "ENTITY")) { + // Parse an entity line + token = strtok_r(NULL, " \t", &last); + if(token != NULL) { + entityname = strdup(token); + if(entityname != NULL) + { + debug("Found entity \'%s\'\n", entityname); + } + } else { + printf("Parse error near ENTITY token in file %s\n", bsdlfilename); + } + } + else if(!strcmp(strtoupper(token), "CONSTANT")) { + // Parse a constant declaration...we ignore them, just get lines until we find a ';' char + // assume nothing else useful comes on the line after the ';' + // Slightly awkward, since we have to search the rest of the line after the strtok, then possible + // new lines as well. + token = strtok_r(NULL, " \t", &last); // debug...don't worry about error, token only used in printf + debug("Ignoring constant \'%s\'\n", token); // debug + while(strchr(last, ';') == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); + } + } + else if(!strcmp(strtoupper(token), "GENERIC")) { + // Parse a generic declaration...we ignore them, just get lines until we find a ';' char + // assume nothing else useful comes on the line after the ';' + // Slightly awkward, since we have to search the rest of the line after the strtok, then possible + // new lines as well. + token = strtok_r(NULL, " \t", &last); // debug...don't worry about error, token only used in printf + debug("Ignoring generic \'%s\'\n", token); // debug + while(strchr(last, ';') == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); + } + } + else if(!strcmp(strtoupper(token), "USE")) { + // Parse a 'use' declaration...we ignore them, just get lines until we find a ';' char + // assume nothing else useful comes on the line after the ';' + // Note that there may be no space after the token, so add ';' to the tokenizing list in the debug bits. + // Slightly awkward, since we have to search the rest of the line after the strtok, then possible + // new lines as well. + token = strtok_r(NULL, " \t;", &last); // debug ...don't worry about error, token only used in printf + debug("Ignoring use \'%s\'\n", token); // debug + while(strchr(last, ';') == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); + } + } + else if(!strcmp(strtoupper(token), "END")) { + // We're done, whether we've found what we want or not. Eject eject eject... + debug("Found END token, stopping parser\n"); + break; + } + else if(!strcmp(strtoupper(token), "PORT")) { + // Parse a port list. Find a '(', find a ')', find a ';'. + // Note that "()" pairs may occur in between. + // 'last' must be set in the first two strchr() calls so that the next strchr() call will + // begin parsing after the previous char position. Otherwise, e.g. a ';' before the ')' but on the same + // line would (incorrectly) satisfy the search. + while((last = strchr(last, '(')) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); + } + opens = 1; + last++; // don't leave 'last' pointing at the '(' char, since we're looking for another + + do { + while((last = strchr_s(last, "()")) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** abort if new line is empty + } + if(*last == '(') opens++; + else if(*last == ')') opens--; + last++; // don't leave last pointing at the same "()" char, since we're looking for another + } while(opens); + + + while(strchr(last, ';') == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); + } + debug("Ignored port statement\n"); + } + else if(!strcmp(strtoupper(token), "ATTRIBUTE")) { + // Parse an attribute + token = strtok_r(NULL, " \t", &last); // *** check for error + if(!strcmp(strtoupper(token), "INSTRUCTION_LENGTH")) { + // Find ':', then "entity", then "is", then take anything before the ';' as the value + while((last = strchr(last, ':')) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + while((last = strstr(last, "entity")) == NULL) { // don't do strtoupper() here, that would do the entire line + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + while((last = strstr(last, "is")) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + + // scan until the end of the line looking for data + j = 0; + done = 0; + while(*last != '\0') { + if(isdigit(*last)) tmpbuf[j++] = *last; + else if(*last == ';') { done = 1; break;} + last++; + } + // May need to go to additional lines + while(!done) { + filepos = get_line(filedata, filepos, &linedata, filesize); // *** break if linedata has no data + while(*linedata != '\0') { + if(isdigit(*linedata)) tmpbuf[j++] = *linedata; + else if(*linedata == ';') { done = 1; break;} + linedata++; + } + } + + tmpbuf[j] = '\0'; + IR_size = strtoul(tmpbuf, NULL, 0); + found_IR_size = 1; + debug("Found IR size %i (%s)\n", IR_size, tmpbuf); + } // end if INSTRUCTION_LENGTH + + else if(!strcmp(strtoupper(token), "INSTRUCTION_OPCODE")) { + // Find ": entity is" + while((last = strchr(last, ':')) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + while((last = strstr(last, "entity")) == NULL) { // don't do strtoupper() here, that would do the entire line + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + while((last = strstr(last, "is")) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + + // We're going to copy the entire attribute (all commands) into a temp. buffer. We need a big enough buffer, + // and we can't just scan for ';' to find out because there's a '\0' at the end of this line. + // But, it can't be bigger than the entire rest of the file, so... + cmdbuf = (char *) malloc(filesize-filepos); + debug("Malloc'd %i bytes for INSTRUCTION_OPCODE\n", filesize-filepos); + + // Parse until ';', and grab everything between each pair of "" found + // Note that 'last' still points at "is" + j = 0; + done = 0; + valid = 0; + while(*last != '\0') { + if(*last == ';') { done = 1; break;} // Put this first in case of badly formed BSDL files + else if(valid && (*last != '\"')) cmdbuf[j++] = *last; + else if(*last == '\"') valid = !valid; + last++; + } + // May need to go to additional lines + while(!done) { + filepos = get_line(filedata, filepos, &linedata, filesize); // *** break if linedata has no data + while(*linedata != '\0') { + if(valid && (*linedata != '\"')) cmdbuf[j++] = *linedata; + else if(*linedata == '\"') valid = !valid; + else if(*linedata == ';') { done = 1; break;} + linedata++; + } + } + cmdbuf[j] = '\0'; + debug("Finished copying INSTRUCTION_OPCODE, copied %i bytes", j+1); + + // Parse the opcodes attribute. This is an exercise unto itself, so do it in another function. + parse_opcodes(cmdbuf, &debug_cmd, &user1_cmd, &idcode_cmd); + found_cmds = 1; + free(cmdbuf); + + } // end if INSTRUCTION_OPCODE + + else if(!strcmp(strtoupper(token), "IDCODE_REGISTER")) { + // Find : entity is + while((last = strchr(last, ':')) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + while((last = strstr(last, "entity")) == NULL) { // don't do strtoupper() here, that would do the entire line + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + while((last = strstr(last, "is")) == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); // *** check last actually has data? + } + + // Parse until ';', and grab everything between each pair of "" found + // Note that 'last' still points at "is" + j = 0; + done = 0; + valid = 0; + while(*last != '\0') { + if(*last == ';') { done = 1; break;} // Put this first in case of badly formed BSDL files + else if(valid && (*last != '\"')) tmpbuf[j++] = *last; + else if(*last == '\"') valid = !valid; + last++; + } + // May need to go to additional lines + while(!done) { + filepos = get_line(filedata, filepos, &linedata, filesize); // *** break if linedata has no data + while(*linedata != '\0') { + if(valid && (*linedata != '\"')) tmpbuf[j++] = *linedata; + else if(*linedata == '\"') valid = !valid; + else if(*linedata == ';') { done = 1; break;} + linedata++; + } + } + tmpbuf[j] = '\0'; + + // Parse the tmpbuf + if(j != 32) printf("Warning: found %i chars (expected 32) while getting IDCODE in BSDL file %s.\n", j, bsdlfilename); // Sanity check + debug("Got IDCODE string \'%s\'\n", tmpbuf); + for(i = 0; i < j; i++) { + if(tmpbuf[i] == '1') idcode |= 0x1<<(31-i); + else if(toupper(tmpbuf[i]) == 'X') idcode_mask &= ~(0x1<<(31-i)); + } + debug("Found IDCODE 0x%08X (%s), mask is 0x%08X\n", idcode, tmpbuf, idcode_mask); + found_idcode = 1; + + } // end if IDCODE_REGISTER + + else { + debug("Ignoring attribute \'%s\'\n", token); + // Consume chars until ';' found + while(strchr(last, ';') == NULL) { + filepos = get_line(filedata, filepos, &last, filesize); + } + } + } + else { + debug("Unknown token \'%s\' found in BSDL file %s\n", token, bsdlfilename); + } + } + + free(filedata); + + // Put the data in a struct for return and storage + ret = (bsdlinfo *) malloc(sizeof(bsdlinfo)); + if(ret == NULL) { + printf("Error: out of memory, unable to store BSDL info for file %s\n", bsdlfilename); + return NULL; + } + + ret->name = entityname; // this was malloc'd, so it's persistant, this is safe + ret->idcode = idcode; + ret->idcode_mask = idcode_mask; + ret->IR_size = IR_size; + ret->cmd_debug = debug_cmd; + ret->cmd_user1 = user1_cmd; + ret->cmd_idcode = idcode_cmd; + ret->next = NULL; + + return ret; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Local / helper functions + + +// Returns 1 line from a complete file buffer pointed to by *filedata. Removes leading +// whitespace, ignores comment lines, removes trailing comments (comments denoted by "--") +// startpos: index in filedata[] to start looking for a new line. +// linedata: set to point to the first char of the new line. +// filesize: used so we don't go past the end of filedata[] +// The return value is the first index after the returned line. This may be 1 past the end of the buffer. +int get_line(char *filedata, int startpos, char **linedata, int filesize) +{ + int lineidx = startpos; + unsigned char loop; + char *commentptr; + + do { + loop = 0; + while(isspace(filedata[lineidx]) && (lineidx < filesize)) lineidx++; // burn leading whitespace chars + + if(lineidx >= (filesize-1)) { // We look at the data at lineidx and lineidx+1...don't look at invalid offsets. + lineidx = filesize-1; + break; + } + + if((filedata[lineidx] == '-') && (filedata[lineidx+1] == '-')) + { // then this is a full-line comment, with no useful data + while(((filedata[lineidx] != '\n') && (filedata[lineidx] != '\r')) && (lineidx < filesize)) + lineidx++; // burn comment line up to CR/LF + loop = 1; + } + } while(loop); + + // Set the line pointer + *linedata = &filedata[lineidx]; + + // Put a NULL char at the newline + while(!iscntrl(filedata[lineidx]) && (lineidx < filesize)) lineidx++; + if(lineidx >= filesize) { // Don't write past the end of the array. + lineidx = filesize-1; + } + filedata[lineidx] = '\0'; + + // Put a NULL at the first "--" string, if any + commentptr = strstr(*linedata, "--"); + if(commentptr != NULL) *commentptr = '\0'; + + return lineidx+1; +} + + +// In-place string capitalizer +char * strtoupper(char *str) +{ + int i = 0; + + while(str[i] != '\0') { + str[i] = toupper(str[i]); + i++; + } + + return str; +} + +// Searches a string 'str' for the first occurance of any +// character in the string 'chars'. Returns a pointer to +// the char in 'str' if one is found, returns NULL if +// none of the chars in 'chars' are present in 'str'. +char * strchr_s(char *str, char *chars) +{ + int slen = strlen(chars); + char *ptr = str; + int i; + + while(*ptr != '\0') { + for(i = 0; i < slen; i++) { + if(*ptr == chars[i]) + return ptr; + } + ptr++; + } + + return NULL; +} + + +// Parses a string with command name / opcode pairs of the format +// EXTEST (1111000000),SAMPLE (1111000001), [...] +// There may or may not be a space between the name and the open paren. +// We do not assume a comma after the last close paren. +#define TARGET_DEBUG 1 +#define TARGET_USER1 2 +#define TARGET_IDCODE 3 +void parse_opcodes(char *cmdbuf, uint32_t *debug_cmd, uint32_t *user1_cmd, uint32_t *idcode_cmd) +{ + char *saveptr = NULL; + char *cmd; + char *token; + char *saveptr2; + int target; + int opcode; + + cmd = strtok_r(cmdbuf, ",", &saveptr); + while(cmd != NULL) + { + // 'cmd' should now have one pair in the form "EXTEST (1111000000)" + target = 0; + token = strtok_r(cmd, " \t(", &saveptr2); + if(!strcmp(strtoupper(token), "DEBUG")) { + target = TARGET_DEBUG; + debug("Found DEBUG opcode: "); + } + else if(!strcmp(strtoupper(token), "USER1")) { + target = TARGET_USER1; + debug("Found USER1 opcode:"); + } + else if(!strcmp(strtoupper(token), "IDCODE")) { + target = TARGET_IDCODE; + debug("Found IDCODE opcode: "); + } + + if(target) { // don't parse opcode number unless necessary + token = strtok_r(NULL, " \t()", &saveptr2); + if(token != NULL) { + opcode = strtoul(token, NULL, 2); // *** Test for errors + debug("0x%X (%s)\n", opcode, token); + + if(target == TARGET_DEBUG) *debug_cmd = opcode; + else if(target == TARGET_USER1) *user1_cmd = opcode; + else if(target == TARGET_IDCODE) *idcode_cmd = opcode; + } + else { + printf("Error: failed to find opcode value after identifier.\n"); + } + } + + cmd = strtok_r(NULL, ",", &saveptr); + } + + +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/or32_selftest.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/or32_selftest.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/or32_selftest.c (revision 66) @@ -0,0 +1,634 @@ +/* or32_selftest.c -- JTAG protocol bridge between GDB and Advanced debug module. + Copyright(C) 2001 Marko Mlinar, markom@opencores.org + Code for TCP/IP copied from gdb, by Chris Ziomkowski + Refactoring and USB support by Nathan Yawn, (C) 2008-2010 + + This file contains functions which perform high-level transactions + on a JTAG chain and debug unit, such as setting a value in the TAP IR + or doing a burst write through the wishbone module of the debug unit. + It uses the protocol for the Advanced Debug Interface (adv_dbg_if). + + 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 // for exit() +#include + +#include "or32_selftest.h" +#include "dbg_api.h" +#include "errcodes.h" + + +// Define your system parameters here +//#define HAS_CPU1 // stall cpu1 (as well as cpu0) +//#define HAS_MEMORY_CONTROLLER // init the SDRAM controller +#define MC_BASE_ADDR 0x93000000 +#define SDRAM_BASE 0x00000000 +//#define SDRAM_SIZE 0x04000000 +#define SDRAM_SIZE 0x400 +#define SRAM_BASE 0x00000000 +#define SRAM_SIZE 0x04000000 +#define FLASH_BASE_ADDR 0xf0000000 + +// Define the tests to be performed here +#define TEST_SRAM +//#define TEST_SDRAM +#define TEST_OR1K +//#define TEST_8051 // run a test on an 8051 on CPU1 + + +// Defines which depend on user-defined values, don't change these +#define FLASH_BAR_VAL FLASH_BASE_ADDR +#define SDRAM_BASE_ADDR SDRAM_BASE +#define SDRAM_BAR_VAL SDRAM_BASE_ADDR +#define SDRAM_AMR_VAL (~(SDRAM_SIZE -1)) + +#define CHECK(x) check(__FILE__, __LINE__, (x)) +void check(char *fn, int l, int i); + +void check(char *fn, int l, int i) { + if (i != 0) { + fprintf(stderr, "%s:%d: Jtag error %d occured; exiting.\n", fn, l, i); + exit(1); + } +} + + +//////////////////////////////////////////////////////////// +// Self-test functions +/////////////////////////////////////////////////////////// +int dbg_test() +{ + int success; + + success = stall_cpus(); + if(success == APP_ERR_NONE) { + +#ifdef HAS_MEMORY_CONTROLLER + // Init the memory contloller + init_mc(); + // Init the SRAM addresses in the MC + init_sram(); +#endif + + + +#ifdef TEST_SDRAM + success |= test_sdram(); + success |= test_sdram_2(); +#endif + +#ifdef TEST_SRAM + success |= test_sram(); +#endif + +#ifdef TEST_OR1K + success |= test_or1k_cpu0(); +#endif + +#if ((defined TEST_8051) && (defined HAS_CPU1)) + success |= test_8051_cpu1(); +#endif + + return success; + } + + return APP_ERR_TEST_FAIL; +} + + +int stall_cpus(void) +{ + unsigned char stalled; + +#ifdef HAS_CPU1 + printf("Stall 8051 - "); + CHECK(dbg_cpu1_write_reg(0, 0x01)); // stall 8051 +#endif + + printf("Stall or1k - "); + CHECK(dbg_cpu0_write_ctrl(0, 0x01)); // stall or1k + + +#ifdef HAS_CPU1 + CHECK(dbg_cpu1_read_ctrl(0, &stalled)); + if (!(stalled & 0x1)) { + printf("8051 is not stalled!\n"); // check stall 8051 + return APP_ERR_TEST_FAIL; + } +#endif + + CHECK(dbg_cpu0_read_ctrl(0, &stalled)); + if (!(stalled & 0x1)) { + printf("or1k is not stalled!\n"); // check stall or1k + return APP_ERR_TEST_FAIL; + } + + printf("CPU(s) stalled.\n"); + + return APP_ERR_NONE; +} + + +void init_mc(void) +{ + uint32_t insn; + + printf("Initialize Memory Controller (SDRAM)\n"); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_0, FLASH_BAR_VAL & 0xffff0000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_0, FLASH_AMR_VAL & 0xffff0000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_WTR_0, FLASH_WTR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RTR_0, FLASH_RTR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x40000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_4, SDRAM_BAR_VAL & 0xffff0000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_4, SDRAM_AMR_VAL & 0xffff0000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_4, 0x00bf0005)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RATR, SDRAM_RATR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RCDR, SDRAM_RCDR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RCTR, SDRAM_RCTR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_REFCTR, SDRAM_REFCTR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_PTR, SDRAM_PTR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RRDR, SDRAM_RRDR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_RIR, SDRAM_RIR_VAL)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x5e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x5e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x6e000000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_OSR, 0x7e000033)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_ORR, 0x7e000033)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_4, 0xc0bf0005)); + + CHECK(dbg_wb_read32(MC_BASE_ADDR+MC_CCR_4, &insn)); + printf("expected %x, read %x\n", 0xc0bf0005, insn); +} + + +void init_sram(void) +{ + // SRAM initialized to 0x40000000 + printf("Initialize Memory Controller (SRAM)\n"); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_BAR_1, SRAM_BASE & 0xffff0000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_AMR_1, ~(SRAM_SIZE - 1) & 0xffff0000)); + CHECK(dbg_wb_write32(MC_BASE_ADDR + MC_CCR_1, 0xc020001f)); +} + + + +int test_sdram(void) +{ + uint32_t insn; + unsigned long i; + uint32_t data4_out[0x08]; + uint32_t data4_in[0x08]; + uint16_t data2_out[0x10]; + uint16_t data2_in[0x10]; + uint8_t data1_out[0x20]; + uint8_t data1_in[0x20]; + + printf("Start SDRAM WR\n"); + for (i=0x10; i<(SDRAM_SIZE+SDRAM_BASE); i=i<<1) { + //printf("0x%x: 0x%x\n", SDRAM_BASE+i, i); + CHECK(dbg_wb_write32(SDRAM_BASE+i, i)); + } + + printf("Start SDRAM RD\n"); + for (i=0x10; i<(SDRAM_SIZE+SDRAM_BASE); i=i<<1) { + CHECK(dbg_wb_read32(SDRAM_BASE+i, &insn)); + //printf("0x%x: 0x%x\n", SDRAM_BASE+i, insn); + if (i != insn) { + printf("SDRAM test FAIL\n"); + return APP_ERR_TEST_FAIL; + } + } + + printf("32-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); + for (i=0; i<(0x20/4); i++) { + data4_out[i] = data4_in[i] = ((4*i+3)<<24) | ((4*i+2)<<16) | ((4*i+1)<<8) | (4*i); + //printf("data_out = %0x\n", data4_out[i]); + } + + //printf("Press a key for write\n"); getchar(); + CHECK(dbg_wb_write_block32(SDRAM_BASE, &data4_out[0], 0x20)); + + // 32-bit block read is used for checking + printf("32-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); + CHECK(dbg_wb_read_block32(SDRAM_BASE, &data4_out[0], 0x20)); + for (i=0; i<(0x20/4); i++) { + //printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]); + if (data4_in[i] != data4_out[i]) { + printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data4_in[i], data4_out[i]); + return APP_ERR_TEST_FAIL; + } + } + + + printf("16-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); + for (i=0; i<(0x20/2); i++) { + data2_out[i] = data2_in[i] = ((4*i+1)<<8) | (4*i); + //printf("data_out = %0x\n", data_out[i]); + } + CHECK(dbg_wb_write_block16(SDRAM_BASE, &data2_out[0], 0x20)); + + // 16-bit block read is used for checking + printf("16-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); + CHECK(dbg_wb_read_block16(SDRAM_BASE, &data2_out[0], 0x20)); + for (i=0; i<(0x20/2); i++) { + //printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]); + if (data2_in[i] != data2_out[i]) { + printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data2_in[i], data2_out[i]); + return APP_ERR_TEST_FAIL; + } + } + + printf("8-bit block write from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); + for (i=0; i<(0x20/1); i++) { + data1_out[i] = data1_in[i] = (4*i); + //printf("data_out = %0x\n", data_out[i]); + } + CHECK(dbg_wb_write_block8(SDRAM_BASE, &data1_out[0], 0x20)); + + // 32-bit block read is used for checking + printf("8-bit block read from %x to %x\n", SDRAM_BASE, SDRAM_BASE + 0x20); + CHECK(dbg_wb_read_block8(SDRAM_BASE, &data1_out[0], 0x20)); + for (i=0; i<(0x20/1); i++) { + //printf("0x%x: 0x%x\n", SDRAM_BASE+(i*4), data_out[i]); + if (data1_in[i] != data1_out[i]) { + printf("SDRAM data differs. Expected: 0x%0x, read: 0x%0x\n", data1_in[i], data1_out[i]); + return APP_ERR_TEST_FAIL; + } + } + + printf("SDRAM OK!\n"); + return APP_ERR_NONE; +} + + +int test_sdram_2(void) +{ + uint32_t insn; + + printf("SDRAM test 2: \n"); + CHECK(dbg_wb_write32(SDRAM_BASE+0x00, 0x12345678)); + CHECK(dbg_wb_read32(SDRAM_BASE+0x00, &insn)); + printf("expected %x, read %x\n", 0x12345678, insn); + if (insn != 0x12345678) return APP_ERR_TEST_FAIL; + + CHECK(dbg_wb_write32(SDRAM_BASE+0x0000, 0x11112222)); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0000, &insn)); + printf("expected %x, read %x\n", 0x11112222, insn); + if (insn != 0x11112222) return APP_ERR_TEST_FAIL; + + CHECK(dbg_wb_write32(SDRAM_BASE+0x0004, 0x33334444)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x0008, 0x55556666)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x000c, 0x77778888)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x0010, 0x9999aaaa)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x0014, 0xbbbbcccc)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x0018, 0xddddeeee)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x001c, 0xffff0000)); + CHECK(dbg_wb_write32(SDRAM_BASE+0x0020, 0xdeadbeef)); + + CHECK(dbg_wb_read32(SDRAM_BASE+0x0000, &insn)); + printf("expected %x, read %x\n", 0x11112222, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0004, &insn)); + printf("expected %x, read %x\n", 0x33334444, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0008, &insn)); + printf("expected %x, read %x\n", 0x55556666, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x000c, &insn)); + printf("expected %x, read %x\n", 0x77778888, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0010, &insn)); + printf("expected %x, read %x\n", 0x9999aaaa, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0014, &insn)); + printf("expected %x, read %x\n", 0xbbbbcccc, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0018, &insn)); + printf("expected %x, read %x\n", 0xddddeeee, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x001c, &insn)); + printf("expected %x, read %x\n", 0xffff0000, insn); + CHECK(dbg_wb_read32(SDRAM_BASE+0x0020, &insn)); + printf("expected %x, read %x\n", 0xdeadbeef, insn); + + if (insn != 0xdeadbeef) { + printf("SDRAM test 2 FAILED\n"); + return APP_ERR_TEST_FAIL; + } + else + printf("SDRAM test 2 passed\n"); + + return APP_ERR_NONE; +} + + +int test_sram(void) +{ + //unsigned long insn; + uint32_t ins; + uint32_t insn[9]; + insn[0] = 0x11112222; + insn[1] = 0x33334444; + insn[2] = 0x55556666; + insn[3] = 0x77778888; + insn[4] = 0x9999aaaa; + insn[5] = 0xbbbbcccc; + insn[6] = 0xddddeeee; + insn[7] = 0xffff0000; + insn[8] = 0xdedababa; + + printf("SRAM test: \n"); + //dbg_wb_write_block32(0x0, insn, 9); + + CHECK(dbg_wb_write32(SRAM_BASE+0x0000, 0x11112222)); + CHECK(dbg_wb_write32(SRAM_BASE+0x0004, 0x33334444)); + CHECK(dbg_wb_write32(SRAM_BASE+0x0008, 0x55556666)); + CHECK(dbg_wb_write32(SRAM_BASE+0x000c, 0x77778888)); + CHECK(dbg_wb_write32(SRAM_BASE+0x0010, 0x9999aaaa)); + CHECK(dbg_wb_write32(SRAM_BASE+0x0014, 0xbbbbcccc)); + CHECK(dbg_wb_write32(SRAM_BASE+0x0018, 0xddddeeee)); + CHECK(dbg_wb_write32(SRAM_BASE+0x001c, 0xffff0000)); + CHECK(dbg_wb_write32(SRAM_BASE+0x0020, 0xdedababa)); + + + CHECK(dbg_wb_read32(SRAM_BASE+0x0000, &ins)); + printf("expected %x, read %x\n", 0x11112222, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x0004, &ins)); + printf("expected %x, read %x\n", 0x33334444, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x0008, &ins)); + printf("expected %x, read %x\n", 0x55556666, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x000c, &ins)); + printf("expected %x, read %x\n", 0x77778888, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x0010, &ins)); + printf("expected %x, read %x\n", 0x9999aaaa, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x0014, &ins)); + printf("expected %x, read %x\n", 0xbbbbcccc, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x0018, &ins)); + printf("expected %x, read %x\n", 0xddddeeee, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x001c, &ins)); + printf("expected %x, read %x\n", 0xffff0000, ins); + CHECK(dbg_wb_read32(SRAM_BASE+0x0020, &ins)); + printf("expected %x, read %x\n", 0xdedababa, ins); + + if (ins != 0xdedababa) { + printf("SRAM test failed!!!\n"); + return APP_ERR_TEST_FAIL; + } + else + printf("SRAM test passed\n"); + + return APP_ERR_NONE; +} + + + +int test_or1k_cpu0(void) +{ + uint32_t npc, ppc, r1, insn; + uint8_t stalled; + uint32_t result; + int i; + + printf("Testing CPU0 (or1k) - writing instructions\n"); + CHECK(dbg_wb_write32(SDRAM_BASE+0x00, 0xe0000005)); /* l.xor r0,r0,r0 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x04, 0x9c200000)); /* l.addi r1,r0,0x0 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x08, 0x18400000)); /* l.movhi r2,0x0000 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x0c, 0xa8420030)); /* l.ori r2,r2,0x30 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x10, 0x9c210001)); /* l.addi r1,r1,1 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x14, 0x9c210001)); /* l.addi r1,r1,1 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x18, 0xd4020800)); /* l.sw 0(r2),r1 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x1c, 0x9c210001)); /* l.addi r1,r1,1 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x20, 0x84620000)); /* l.lwz r3,0(r2) */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x24, 0x03fffffb)); /* l.j loop2 */ + CHECK(dbg_wb_write32(SDRAM_BASE+0x28, 0xe0211800)); /* l.add r1,r1,r3 */ + + printf("Setting up CPU0\n"); + CHECK(dbg_cpu0_write((0 << 11) + 17, 0x01)); /* Enable exceptions */ + CHECK(dbg_cpu0_write((6 << 11) + 20, 0x2000)); /* Trap causes stall */ + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE)); /* Set PC */ + CHECK(dbg_cpu0_write((6 << 11) + 16, 1 << 22)); /* Set step bit */ + printf("Starting CPU0!\n"); + for(i = 0; i < 11; i++) { + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* 11x Unstall */ + //printf("Starting CPU, waiting for trap...\n"); + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + //printf("Got trap.\n"); + } + + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000010, 0x00000028, 5); + result = npc + ppc + r1; + + CHECK(dbg_cpu0_write((6 << 11) + 16, 0)); // Reset step bit + CHECK(dbg_wb_read32(SDRAM_BASE + 0x28, &insn)); // Set trap insn in delay slot + CHECK(dbg_wb_write32(SDRAM_BASE + 0x28, 0x21000001)); + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); // Unstall + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); // Read NPC + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); // Read PPC + CHECK(dbg_cpu0_read(0x401, &r1)); // Read R1 + CHECK(dbg_wb_write32(SDRAM_BASE + 0x28, insn)); // Set back original insn + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000010, 0x00000028, 8); + result = npc + ppc + r1 + result; + + CHECK(dbg_wb_read32(SDRAM_BASE + 0x24, &insn)); // Set trap insn in place of branch insn + CHECK(dbg_wb_write32(SDRAM_BASE + 0x24, 0x21000001)); + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x10)); // Set PC + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); // Unstall + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); // Read NPC + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); // Read PPC + CHECK(dbg_cpu0_read(0x401, &r1)); // Read R1 + CHECK(dbg_wb_write32(SDRAM_BASE + 0x24, insn)); // Set back original insn + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000028, 0x00000024, 11); + result = npc + ppc + r1 + result; + + CHECK(dbg_wb_read32(SDRAM_BASE + 0x20, &insn)); /* Set trap insn before branch insn */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, 0x21000001)); + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x24)); /* Set PC */ + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, insn)); /* Set back original insn */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000024, 0x00000020, 24); + result = npc + ppc + r1 + result; + + CHECK(dbg_wb_read32(SDRAM_BASE + 0x1c, &insn)); /* Set trap insn behind lsu insn */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x1c, 0x21000001)); + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x20)); /* Set PC */ + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x1c, insn)); /* Set back original insn */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000020, 0x0000001c, 49); + result = npc + ppc + r1 + result; + + CHECK(dbg_wb_read32(SDRAM_BASE + 0x20, &insn)); /* Set trap insn very near previous one */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, 0x21000001)); + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x1c)); /* Set PC */ + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x20, insn)); /* Set back original insn */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000024, 0x00000020, 50); + result = npc + ppc + r1 + result; + + CHECK(dbg_wb_read32(SDRAM_BASE + 0x10, &insn)); /* Set trap insn to the start */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x10, 0x21000001)); + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x20) /* Set PC */); + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + CHECK(dbg_wb_write32(SDRAM_BASE + 0x10, insn)); /* Set back original insn */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000014, 0x00000010, 99); + result = npc + ppc + r1 + result; + + CHECK(dbg_cpu0_write((6 << 11) + 16, 1 << 22)); /* Set step bit */ + for(i = 0; i < 5; i++) { + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ + //printf("Waiting for trap..."); + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + //printf("got trap.\n"); + } + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000028, 0x00000024, 101); + result = npc + ppc + r1 + result; + + CHECK(dbg_cpu0_write((0 << 11) + 16, SDRAM_BASE + 0x24)); /* Set PC */ + for(i = 0; i < 2; i++) { + CHECK(dbg_cpu0_write_ctrl(CPU_OP_ADR, 0x00)); /* Unstall */ + //printf("Waiting for trap...\n"); + do CHECK(dbg_cpu0_read_ctrl(CPU_OP_ADR, &stalled)); while (!(stalled & 1)); + //printf("Got trap.\n"); + } + CHECK(dbg_cpu0_read((0 << 11) + 16, &npc)); /* Read NPC */ + CHECK(dbg_cpu0_read((0 << 11) + 18, &ppc)); /* Read PPC */ + CHECK(dbg_cpu0_read(0x401, &r1)); /* Read R1 */ + printf("Read npc = %.8x ppc = %.8x r1 = %.8x\n", npc, ppc, r1); + printf("Expected npc = %.8x ppc = %.8x r1 = %.8x\n", 0x00000010, 0x00000028, 201); + result = npc + ppc + r1 + result; + printf("result = %.8x\n", result ^ 0xdeaddae1); + + if((result ^ 0xdeaddae1) != 0xdeaddead) + return APP_ERR_TEST_FAIL; + + return APP_ERR_NONE; +} + + +// This function does not currently return a useful value +/* +unsigned char test_8051_cpu1(void) +{ + int retval = 1; + unsigned long result = 0; + unsigned long npc[3], tmp; + + printf("Testing CPU1 (8051)\n"); + + // WRITE ACC + CHECK(dbg_cpu1_write(0x20e0, 0xa6)); + + // READ ACC + CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space + printf("Read 8051 ACC = %0x (expected a6)\n", tmp); + result = result + tmp; + + // set exception to single step to jump over a loop + CHECK(dbg_cpu1_write(0x3010, 0xa0)); // set single step and global enable in EER + CHECK(dbg_cpu1_write(0x3011, 0x40)); // set evec = 24'h000040 + CHECK(dbg_cpu1_write(0x3012, 0x00)); // (already reset value) + CHECK(dbg_cpu1_write(0x3013, 0x00)); // (already reset value) + + // set HW breakpoint at PC == 0x41 + CHECK(dbg_cpu1_write(0x3020, 0x41)); // DVR0 = 24'h000041 + CHECK(dbg_cpu1_write(0x3023, 0x39)); // DCR0 = valid, == PC + CHECK(dbg_cpu1_write(0x3001, 0x04)); // DSR = watchpoint + + // flush 8051 instruction cache + CHECK(dbg_cpu1_write(0x209f, 0x00)); + + // Put some instructions in ram (8-bit mode on wishbone) + CHECK(dbg_wb_write8 (0x40, 0x04)); // inc a + CHECK(dbg_wb_write8 (0x41, 0x03)); // rr a; + CHECK(dbg_wb_write8 (0x42, 0x14)); // dec a; + CHECK(dbg_wb_write8 (0x43, 0xf5)); // mov 0e5h, a; + CHECK(dbg_wb_write8 (0x44, 0xe5)); + + // unstall just 8051 + CHECK(dbg_cpu1_write_reg(0, 0)); + + // read PC + CHECK(dbg_cpu1_read(0, &npc[0])); + CHECK(dbg_cpu1_read(1, &npc[1])); + CHECK(dbg_cpu1_read(2, &npc[2])); + printf("Read 8051 npc = %02x%02x%02x (expected 41)\n", npc[2], npc[1], npc[0]); + result = result + (npc[2] << 16) + (npc[1] << 8) + npc[0]; + + // READ ACC + CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space + printf("Read 8051 ACC = %0x (expected a7)\n", tmp); + result = result + tmp; + + // set sigle step to stop execution + CHECK(dbg_cpu1_write(0x3001, 0x20)); // set single step and global enable in DSR + + // clear DRR + CHECK(dbg_cpu1_write(0x3000, 0x00)); // set single step and global enable in DRR + + // unstall just 8051 + CHECK(dbg_cpu1_write_reg(0, 0)); + + // read PC + CHECK(dbg_cpu1_read(0, &npc[0])); + CHECK(dbg_cpu1_read(1, &npc[1])); + CHECK(dbg_cpu1_read(2, &npc[2])); + printf("Read 8051 npc = %02x%02x%02x (expected 42)\n", npc[2], npc[1], npc[0]); + result = result + (npc[2] << 16) + (npc[1] << 8) + npc[0]; + + // READ ACC + CHECK(dbg_cpu1_read(0x20e0, &tmp)); // select SFR space + printf("Read 8051 ACC = %0x (expected d3)\n", tmp); + result = result + tmp; + + printf("report (%x)\n", result ^ 0x6c1 ^ 0xdeaddead); + + return APP_ERR_NONE; +} +*/ Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl.c (revision 66) @@ -0,0 +1,268 @@ +/* bsdl.c - BSDL file handler for the advanced JTAG bridge + Copyright(C) 2008 - 2010 Nathan Yawn + + 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 "bsdl.h" +#include "bsdl_parse.h" + + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +// Globals to deal with directory names +#define MAX_BSDL_DIRS 64 // Any more than this would take a looooong time... +static char *bsdl_dirs[MAX_BSDL_DIRS]; +static int bsdl_current_dir = 0; // We try them in reverse order + +// Globals to hold the current, open directory +DIR *bsdl_open_dir = NULL; + +// Globals to hold BSDL info +static bsdlinfo *bsdl_head = NULL; +static bsdlinfo *bsdl_tail = NULL; +static bsdlinfo *bsdl_last = NULL; // optimization: pointer to the last struct we used (not necessarily the last in the linked list) + +// Scratchpad for full pathname +int bsdl_scratchpad_size = 0; +char *bsdl_scratchpad = NULL; + +// Prototypes for local functions +bsdlinfo *get_bsdl_info(uint32_t idcode); + + + +////////////////////////////////////////////////////////////////////// +// API for init and config + +void bsdl_init(void) +{ + bsdl_dirs[0] = strdup("/opt/bsdl"); + bsdl_dirs[1] = strdup("/usr/share/bsdl"); + bsdl_dirs[2] = strdup("~/.bsdl"); + bsdl_dirs[3] = strdup("."); + bsdl_current_dir = 3; + bsdl_scratchpad = (char *) malloc(64); + bsdl_scratchpad_size = 64; +} + +void bsdl_add_directory(const char *dirname) +{ + if(bsdl_current_dir >= (MAX_BSDL_DIRS-1)) { + printf("Max BSDL dirs (%d) exceeded; failed to add directory %s\n", MAX_BSDL_DIRS, dirname); + return; + } + + bsdl_current_dir++; + bsdl_dirs[bsdl_current_dir] = strdup(dirname); +} + + +/////////////////////////////////////////////////////////////////// +// API to get device info from BSDL files, if available + + +const char * bsdl_get_name(uint32_t idcode) +{ + bsdlinfo *info; + info = get_bsdl_info(idcode); + if(info != NULL) + return info->name; + + return NULL; + + +} + +// Return the IR length of the device with the given IDCODE, +// if its BSDL file is available. Returns -1 on +// error, which is an invalid size. + +int bsdl_get_IR_size(uint32_t idcode) +{ + bsdlinfo *info; + info = get_bsdl_info(idcode); + if(info != NULL) + return info->IR_size; + + return -1; +} + + +// Returns the DEBUG command for the device with the gived IDCODE, +// if its BSDL file is available. Returns 0xFFFFFFFF on error, +// which is as invalid command (because it's the BYPASS command) +uint32_t bsdl_get_debug_cmd(uint32_t idcode) +{ + bsdlinfo *info; + info = get_bsdl_info(idcode); + if(info != NULL) + return info->cmd_debug; + return TAP_CMD_INVALID; +} + +// Returns the USER1 command for the device with the gived IDCODE, +// if its BSDL file is available. Returns 0xFFFFFFFF on error, +// which is as invalid command (because it's the BYPASS command) +uint32_t bsdl_get_user1_cmd(uint32_t idcode) +{ + bsdlinfo *info; + info = get_bsdl_info(idcode); + if(info != NULL) + return info->cmd_user1; + return TAP_CMD_INVALID; +} + +// Returns the IDCODE command for the device with the gived IDCODE, +// if its BSDL file is available. Returns 0xFFFFFFFF on error, +// which is as invalid command (because it's the BYPASS command) +uint32_t bsdl_get_idcode_cmd(uint32_t idcode) +{ + bsdlinfo *info; + info = get_bsdl_info(idcode); + if(info != NULL) + return info->cmd_idcode; + return TAP_CMD_INVALID; +} + +///////////////////////////////////////////////////////////////////////////// +// Internal routines + + +// This uses a lazy algorithm...first, search data we already have. +// Then, parse new files (storing all data) only until we find +// the data we want. +bsdlinfo *get_bsdl_info(uint32_t idcode) +{ + struct dirent *direntry = NULL; + bsdlinfo *ptr = bsdl_head; + char *c; + + // Check the last place we looked + if(bsdl_last != NULL) + if((bsdl_last->idcode & bsdl_last->idcode_mask) == (idcode & bsdl_last->idcode_mask)) + return bsdl_last; + + // First, search through the info already parsed + while(ptr != NULL) + { + if((ptr->idcode & ptr->idcode_mask) == (idcode & ptr->idcode_mask)) + { + bsdl_last = ptr; + return ptr; + } + ptr = ptr->next; + } + + // Parse files until we get the IDCODE we want + while(1) + { + // Find and open a valid directory + while(bsdl_open_dir == NULL) + { + if(bsdl_current_dir < 0) + return NULL; // There are no more directories to check + debug("Trying BSDL dir \'%s\'\n", bsdl_dirs[bsdl_current_dir]); + bsdl_open_dir = opendir(bsdl_dirs[bsdl_current_dir]); + if((bsdl_open_dir == NULL) && (bsdl_current_dir > 2)) // Don't warn if default dirs not found + printf("Warning: unable to open BSDL directory \'%s\': %s\n", bsdl_dirs[bsdl_current_dir], strerror(errno)); + bsdl_current_dir--; + direntry = NULL; + } + + // Find a BSDL file + do + { + direntry = readdir(bsdl_open_dir); + if(direntry == NULL) + { // We've exhausted this directory + debug("Next bsdl directory\n"); + closedir(bsdl_open_dir); + bsdl_open_dir = NULL; + break; + } + + // *** If a subdirectory, continue!! + + // Check if it's a BSDL file: .bsd, .bsdl, .BSD, .BSDL + debug("Checking file \'%s\'\n", direntry->d_name); + c = strrchr(direntry->d_name, '.'); + debug("File extension is \'%s\'\n", c); + if(c == NULL) + continue; + if(!strcmp(c, ".bsd") || !strcmp(c, ".bsdl") || !strcmp(c, ".BSD") || !strcmp(c, ".BSDL")) + break; + + } + while(1); + + if(direntry == NULL) // We need a new directory + continue; + + // Make sure we can hold the full path (+2 for a '/' and the trailing NULL) + if((strlen(direntry->d_name) + strlen(bsdl_dirs[bsdl_current_dir+1])+2) >= bsdl_scratchpad_size) + { + char *tmp = (char *) realloc(bsdl_scratchpad, (bsdl_scratchpad_size*2)); + if(tmp != NULL) + { + debug("Extending bsdl scratchpad to size %i", bsdl_scratchpad_size); + bsdl_scratchpad_size *= 2; + bsdl_scratchpad = tmp; + } + else + { + fprintf(stderr, "Warning: failed to reallocate BSDL scratchpad to size %i", bsdl_scratchpad_size*2); + continue; + } + } + + strcpy(bsdl_scratchpad, bsdl_dirs[bsdl_current_dir+1]); + strcat(bsdl_scratchpad, "/"); + strcat(bsdl_scratchpad, direntry->d_name); + + // Parse the BSDL file we found + debug("Parsing file \'%s\'\n", bsdl_scratchpad); + ptr = parse_extract_values(bsdl_scratchpad); + + // If we got good data... + if(ptr != NULL) + { + // Store the values... + if(bsdl_head == NULL) { + bsdl_head = ptr; + bsdl_tail = ptr; + } else { + bsdl_tail->next = ptr; + bsdl_tail = ptr; + } + + // ...and return if we got an IDCODE match + if((ptr->idcode & ptr->idcode_mask) == (idcode & ptr->idcode_mask)) { + bsdl_last = ptr; + return ptr; + } + } + } // while(1), parse files until we find a match or run out of dirs / files + + + // If no more files to parse and not found, return NULL + return NULL; +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/rsp-server.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/rsp-server.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/rsp-server.c (revision 66) @@ -0,0 +1,2986 @@ +/* rsp-server.c -- Remote Serial Protocol server for GDB + +Copyright (C) 2008 Embecosm Limited +Copyright (C) 2008-2010 Nathan Yawn + +Contributor Jeremy Bennett + +This file was part of Or1ksim, the OpenRISC 1000 Architectural Simulator. +Adapted for adv_jtag_bridge by Nathan Yawn + +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 3 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, see . +*/ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + +/* System includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Package includes */ +#include "except.h" +#include "spr-defs.h" +#include "dbg_api.h" +#include "errcodes.h" +#include "hardware_monitor.h" +#include "hwp_server.h" + +/* Define to log each packet */ +#define RSP_TRACE 0 + +/*! Name of the RSP service */ +#define OR1KSIM_RSP_SERVICE "jtag-rsp" + +/*! Protocol used by Or1ksim */ +#define OR1KSIM_RSP_PROTOCOL "tcp" + +/* Indices of GDB registers that are not GPRs. Must match GDB settings! */ +#define PPC_REGNUM (MAX_GPRS + 0) /*!< Previous PC */ +#define NPC_REGNUM (MAX_GPRS + 1) /*!< Next PC */ +#define SR_REGNUM (MAX_GPRS + 2) /*!< Supervision Register */ +#define NUM_REGS (MAX_GRPS + 3) /*!< Total GDB registers */ + +/*! Trap instruction for OR32 */ +#define OR1K_TRAP_INSTR 0x21000001 + +/*! Definition of GDB target signals. Data taken from the GDB 6.8 + source. Only those we use defined here. */ +enum target_signal { + TARGET_SIGNAL_NONE = 0, + TARGET_SIGNAL_INT = 2, + TARGET_SIGNAL_ILL = 4, + TARGET_SIGNAL_TRAP = 5, + TARGET_SIGNAL_FPE = 8, + TARGET_SIGNAL_BUS = 10, + TARGET_SIGNAL_SEGV = 11, + TARGET_SIGNAL_ALRM = 14, + TARGET_SIGNAL_USR2 = 31, + TARGET_SIGNAL_PWR = 32 +}; + +/*! The maximum number of characters in inbound/outbound buffers. + * The max is 16kB, and larger buffers make for faster + * transfer times, so use the max. If your setup is prone + * to JTAG communication errors, you may want to use a smaller + * size. + */ +#define GDB_BUF_MAX (16*1024) // ((NUM_REGS) * 8 + 1) + +/*! Size of the matchpoint hash table. Largest prime < 2^10 */ +#define MP_HASH_SIZE 1021 + +/*! String to map hex digits to chars */ +static const char hexchars[]="0123456789abcdef"; + +/*! Data structure for RSP buffers. Can't be null terminated, since it may + include zero bytes */ +struct rsp_buf +{ + char data[GDB_BUF_MAX]; + int len; +}; + +/*! Enumeration of different types of matchpoint. These have explicit values + matching the second digit of 'z' and 'Z' packets. */ +enum mp_type { + BP_MEMORY = 0, + BP_HARDWARE = 1, + WP_WRITE = 2, + WP_READ = 3, + WP_ACCESS = 4 +}; + +/*! Data structure for a matchpoint hash table entry */ +struct mp_entry +{ + enum mp_type type; /*!< Type of matchpoint */ + unsigned long int addr; /*!< Address with the matchpoint */ + unsigned long int instr; /*!< Substituted instruction */ + struct mp_entry *next; /*!< Next entry with this hash */ +}; + +/* Data to interface the GDB handler thread with the target handler thread */ +int pipe_fds[2]; // Descriptors for the pipe from the poller thread to the GDB interface thread + +// Work-around for the current OR1200 implementation; After setting the NPC, +// it always reads back 0 until the next instruction is executed. This +// is a problem with the way we handle memory breakpoints (resetting the NPC), +// so we cache the last value we set the NPC to, incase we need it. +unsigned char use_cached_npc = 0; +unsigned int cached_npc = 0; + +/*! Central data for the RSP connection */ +static struct +{ + int client_waiting; /*!< Is client waiting a response? */ + int target_running; /*!< Is target hardware running? --NAY */ + int single_step_mode; + int proto_num; /*!< Number of the protocol used */ + int server_fd; /*!< FD for new connections */ + int client_fd; /*!< FD for talking to GDB */ + int sigval; /*!< GDB signal for any exception */ + unsigned long int start_addr; /*!< Start of last run */ + struct mp_entry *mp_hash[MP_HASH_SIZE]; /*!< Matchpoint hash table */ +} rsp; + +/* Forward declarations of static functions */ +void rsp_exception (unsigned long int except); +static void rsp_server_request (); +static void rsp_client_request (); +static void rsp_server_close (); +static void rsp_client_close (); +static void put_packet (struct rsp_buf *buf); +static void put_str_packet (const char *str); +static struct rsp_buf *get_packet (); +static void put_rsp_char (char c); +static int get_rsp_char (); +static int rsp_unescape (char *data, + int len); +static void mp_hash_init (); +static void mp_hash_add (enum mp_type type, + unsigned long int addr, + unsigned long int instr); +static struct mp_entry *mp_hash_lookup (enum mp_type type, + unsigned long int addr); +static struct mp_entry *mp_hash_delete (enum mp_type type, + unsigned long int addr); +static int hex (int c); +static void reg2hex (unsigned long int val, + char *buf); +static unsigned long int hex2reg (char *buf); +static void ascii2hex (char *dest, + char *src); +static void hex2ascii (char *dest, + char *src); +static unsigned int set_npc (unsigned long int addr); +static void rsp_report_exception (); +static void rsp_continue (struct rsp_buf *buf); +static void rsp_continue_with_signal (struct rsp_buf *buf); +static void rsp_continue_generic (unsigned long int except); +static void rsp_read_all_regs (); +static void rsp_write_all_regs (struct rsp_buf *buf); +static void rsp_read_mem (struct rsp_buf *buf); +static void rsp_write_mem (struct rsp_buf *buf); +static void rsp_read_reg (struct rsp_buf *buf); +static void rsp_write_reg (struct rsp_buf *buf); +static void rsp_query (struct rsp_buf *buf); +static void rsp_command (struct rsp_buf *buf); +static void rsp_set (struct rsp_buf *buf); +static void rsp_restart (); +static void rsp_step (struct rsp_buf *buf); +static void rsp_step_with_signal (struct rsp_buf *buf); +static void rsp_step_generic (unsigned long int except); +static void rsp_vpkt (struct rsp_buf *buf); +static void rsp_write_mem_bin (struct rsp_buf *buf); +static void rsp_remove_matchpoint (struct rsp_buf *buf); +static void rsp_insert_matchpoint (struct rsp_buf *buf); + +void set_stall_state(int stall); + +/*---------------------------------------------------------------------------*/ +/*!Initialize the Remote Serial Protocol connection + + This involves setting up a socket to listen on a socket for attempted + connections from a single GDB instance (we couldn't be talking to multiple + GDBs at once!). + + The service is specified either as a port number in the Or1ksim configuration + (parameter rsp_port in section debug, default 51000) or as a service name + in the constant OR1KSIM_RSP_SERVICE. + + The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */ +/*---------------------------------------------------------------------------*/ +void +rsp_init (int portNum) +{ + struct protoent *protocol; /* Protocol number */ + struct hostent *host_entry; /* Our host entry */ + struct sockaddr_in sock_addr; /* Socket address */ + + int optval; /* Socket options */ + int flags; /* Socket flags */ + char name[256]; /* Our name */ + + + /* Clear out the central data structure */ + rsp.client_waiting = 0; /* GDB client is not waiting for us */ + rsp.proto_num = -1; /* i.e. invalid */ + rsp.server_fd = -1; /* i.e. invalid */ + rsp.client_fd = -1; /* i.e. invalid */ + rsp.sigval = 0; /* No exception */ + rsp.start_addr = EXCEPT_RESET; /* Default restart point */ + + /* Set up the matchpoint hash table */ + mp_hash_init (); + + /* Get the protocol number of TCP and save it for future use */ + protocol = getprotobyname (OR1KSIM_RSP_PROTOCOL); + if (NULL == protocol) + { + fprintf (stderr, "Warning: RSP unable to load protocol \"%s\": %s\n", + OR1KSIM_RSP_PROTOCOL, strerror (errno)); + return; + } + + rsp.proto_num = protocol->p_proto; /* Saved for future client use */ + + /* 0 is used as the RSP port number to indicate that we should use the + service name instead. */ + if (0 == portNum) + { + struct servent *service = + getservbyname (OR1KSIM_RSP_SERVICE, protocol->p_name); + + if (NULL == service) + { + fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s\n", + OR1KSIM_RSP_SERVICE, strerror (errno)); + return; + } + + portNum = ntohs (service->s_port); + } + + /* Create the socket using the TCP protocol */ + rsp.server_fd = socket (PF_INET, SOCK_STREAM, protocol->p_proto); + if (rsp.server_fd < 0) + { + fprintf (stderr, "Warning: RSP could not create server socket: %s\n", + strerror (errno)); + return; + } + + /* Set this socket to reuse its address. This allows the server to keep + trying before a GDB session has got going. */ + optval = 1; + if (setsockopt(rsp.server_fd, SOL_SOCKET, + SO_REUSEADDR, &optval, sizeof (optval)) < 0) + { + fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: " + "%s\n", rsp.server_fd, strerror (errno)); + rsp_server_close(); + return; + } + + /* The server should be non-blocking. Get the current flags and then set the + non-blocking flags */ + flags = fcntl (rsp.server_fd, F_GETFL); + if (flags < 0) + { + fprintf (stderr, "Warning: Unable to get flags for RSP server socket " + "%d: %s\n", rsp.server_fd, strerror (errno)); + rsp_server_close(); + return; + } + + flags |= O_NONBLOCK; + if (fcntl (rsp.server_fd, F_SETFL, flags) < 0) + { + fprintf (stderr, "Warning: Unable to set flags for RSP server socket " + "%d to 0x%08x: %s\n", rsp.server_fd, flags, strerror (errno)); + rsp_server_close(); + return; + } + + /* Find out what our name is */ + if (gethostname (name, sizeof (name)) < 0) + { + fprintf (stderr, "Warning: Unable to get hostname for RSP server: %s\n", + strerror (errno)); + rsp_server_close(); + return; + } + + /* Find out what our address is */ + host_entry = gethostbyname (name); + if (NULL == host_entry) + { + fprintf (stderr, "Warning: Unable to get host entry for RSP server: " + "%s\n", strerror (errno)); + rsp_server_close(); + return; + } + + /* Bind our socket to the appropriate address */ + memset (&sock_addr, 0, sizeof (sock_addr)); + sock_addr.sin_family = host_entry->h_addrtype; + sock_addr.sin_port = htons (portNum); + + if (bind (rsp.server_fd, + (struct sockaddr *)&sock_addr, sizeof (sock_addr)) < 0) + { + fprintf (stderr, "Warning: Unable to bind RSP server socket %d to port " + "%d: %s\n", rsp.server_fd, portNum, + strerror (errno)); + rsp_server_close(); + return; + } + + /* Mark us as a passive port, with a maximum backlog of 1 connection (we + never connect simultaneously to more than one RSP client!) */ + if (listen (rsp.server_fd, 1) < 0) + { + fprintf (stderr, "Warning: Unable to set RSP backlog on server socket " + "%d to %d: %s\n", rsp.server_fd, 1, strerror (errno)); + rsp_server_close(); + return; + } + +} /* rsp_init () */ + + +/*---------------------------------------------------------------------------*/ +/*!Look for action on RSP + + This function is called when the processor has stalled, which, except for + initialization, must be due to an interrupt. + + If we have no RSP client, we poll the RSP server for a client requesting to + join. We can make no progress until the client is available. + + Then if the cause is an interrupt, and the interrupt not been notified to + GDB, a packet reporting the cause of the interrupt is sent. + + The function then polls the RSP client port (if open) + for available input. It then processes the GDB RSP request and return. + + If an error occurs when polling the RSP server, other than an interrupt, a + warning message is printed out and the RSP server and client (if open) + connections are closed. + + If an error occurs when polling the RSP client, other than an interrupt, a + warning message is printed out and the RSP client connection is closed. + + Polling is always blocking (i.e. timeout -1). */ +/*---------------------------------------------------------------------------*/ +int handle_rsp (void) +{ + struct pollfd fds[2]; /* The FD to poll for */ + char monitor_status; + uint32_t drrval; + uint32_t ppcval; + int ret; + + /* Give up if no RSP server port (this should not occur) */ + if (-1 == rsp.server_fd) + { + fprintf (stderr, "Warning: No RSP server port open\n"); + return 0; + } + + /* If we have no RSP client, poll the server until we get one. */ + while (-1 == rsp.client_fd) + { + /* Poll for a client on the RSP server socket */ + fds[0].fd = rsp.server_fd; /* FD for the server socket */ + fds[0].events = POLLIN; /* Poll for input activity */ + + /* Poll is always blocking. We can't do anything more until something + happens here. */ + switch (poll (fds, 1, -1)) + { + case -1: + /* Error. Only one we ignore is an interrupt */ + if (EINTR != errno) + { + fprintf (stderr, "Warning: poll for RSP failed: closing " + "server connection: %s\n", strerror (errno)); + rsp_client_close(); + rsp_server_close(); + return 0; + } + break; + + case 0: + /* Timeout. This can't occur! */ + fprintf (stderr, "Warning: Unexpected RSP server poll timeout\n"); + break; + + default: + /* Is the poll due to input available? If we succeed ignore any + outstanding reports of exceptions. */ + if (POLLIN == (fds[0].revents & POLLIN)) + { + rsp_server_request (); + rsp.client_waiting = 0; /* No longer waiting */ + } + else + { + /* Error leads to closing the client and server */ + fprintf (stderr, "Warning: RSP server received flags " + "0x%08x: closing server connection\n", fds[0].revents); + rsp_client_close(); + rsp_server_close(); + return 0; + } + } + } + + + /* Poll the RSP client socket for a message from GDB */ + /* Also watch for a message from the hardware poller thread. + This might be easier if we used ppoll() and sent a Signal, instead + of using a pipe? */ + + fds[0].fd = rsp.client_fd; /* FD for the client socket */ + fds[0].events = POLLIN; /* Poll for input activity */ + + fds[1].fd = pipe_fds[1]; + fds[1].events = POLLIN; + + /* Poll is always blocking. We can't do anything more until something + happens here. */ + //fprintf(stderr, "Polling...\n"); + switch (poll (fds, 2, -1)) + { + case -1: + /* Error. Only one we ignore is an interrupt */ + if (EINTR != errno) + { + fprintf (stderr, "Warning: poll for RSP failed: closing " + "server connection: %s\n", strerror (errno)); + rsp_client_close(); + rsp_server_close(); + return 0; + } + + return 1; + + case 0: + /* Timeout. This can't occur! */ + fprintf (stderr, "Warning: Unexpected RSP client poll timeout\n"); + return 1; + + default: + /* Is the client activity due to input available? */ + if (POLLIN == (fds[0].revents & POLLIN)) + { + rsp_client_request (); + } + else if(POLLIN == (fds[1].revents & POLLIN)) + { + //fprintf(stderr, "Got pipe event from monitor thread\n"); + ret = read(pipe_fds[1], &monitor_status, 1); // Read the monitor status + // *** TODO: Check return value of read() + if(monitor_status == 'H') + { + if(rsp.target_running) // ignore if a duplicate event + { + rsp.target_running = 0; + // Log the exception so it can be sent back to GDB + dbg_cpu0_read(SPR_DRR, &drrval); // Read the DRR, find out why we stopped + rsp_exception(drrval); // Send it to be translated and stored + + /* If we have an unacknowledged exception and a client is available, tell + GDB. If this exception was a trap due to a memory breakpoint, then + adjust the NPC. */ + if (rsp.client_waiting) + { + // Read the PPC + dbg_cpu0_read(SPR_PPC, &ppcval); + + // This is structured the way it is to avoid the read of DMR2 unless it's necessary. + if (TARGET_SIGNAL_TRAP == rsp.sigval) + { + if(NULL != mp_hash_lookup (BP_MEMORY, ppcval)) // Is this a breakpoint we set? (we also get a TRAP on single-step) + { + //fprintf(stderr, "Resetting NPC to PPC\n"); + set_npc(ppcval); + } + else + { + uint32_t dmr2val; + dbg_cpu0_read(SPR_DMR2, &dmr2val); // We need this to check for a hardware breakpoint + if((dmr2val & SPR_DMR2_WBS) != 0) // Is this a hardware breakpoint? + { + //fprintf(stderr, "Resetting NPC to PPC\n"); + set_npc(ppcval); + } + } + } + + rsp_report_exception(); + rsp.client_waiting = 0; /* No longer waiting */ + } + } + } + else if(monitor_status == 'R') + { + rsp.target_running = 1; + // If things are added here, be sure to ignore if this event is a duplicate + } + else + { + fprintf(stderr, "RSP server got unknown status \'%c\' (0x%X) from target monitor!\n", monitor_status, monitor_status); + } + } + else + { + /* Error leads to closing the client, but not the server. */ + fprintf (stderr, "Warning: RSP client received flags " + "0x%08x: closing client connection\n", fds[0].revents); + rsp_client_close(); + } + } + + return 1; +} /* handle_rsp () */ + + +//--------------------------------------------------------------------------- +//!Note an exception for future processing +// +// The simulator has encountered an exception. Record it here, so that a +// future call to handle_exception will report it back to the client. The +// signal is supplied in Or1ksim form and recorded in GDB form. + +// We flag up a warning if an exception is already pending, and ignore the +// earlier exception. + +// @param[in] except The exception +//--------------------------------------------------------------------------- + +void rsp_exception (unsigned long int except) +{ + int sigval; // GDB signal equivalent to exception + + switch (except) + { + case SPR_DRR_RSTE: sigval = TARGET_SIGNAL_PWR; break; + case SPR_DRR_BUSEE: sigval = TARGET_SIGNAL_BUS; break; + case SPR_DRR_DPFE: sigval = TARGET_SIGNAL_SEGV; break; + case SPR_DRR_IPFE: sigval = TARGET_SIGNAL_SEGV; break; + case SPR_DRR_TTE: sigval = TARGET_SIGNAL_ALRM; break; + case SPR_DRR_AE: sigval = TARGET_SIGNAL_BUS; break; + case SPR_DRR_IIE: sigval = TARGET_SIGNAL_ILL; break; + case SPR_DRR_IE: sigval = TARGET_SIGNAL_INT; break; + case SPR_DRR_DME: sigval = TARGET_SIGNAL_SEGV; break; + case SPR_DRR_IME: sigval = TARGET_SIGNAL_SEGV; break; + case SPR_DRR_RE: sigval = TARGET_SIGNAL_FPE; break; + case SPR_DRR_SCE: sigval = TARGET_SIGNAL_USR2; break; + case SPR_DRR_FPE: sigval = TARGET_SIGNAL_FPE; break; + case SPR_DRR_TE: sigval = TARGET_SIGNAL_TRAP; break; + + // In the current OR1200 hardware implementation, a single-step does not create a TRAP, + // the DSR reads back 0. GDB expects a TRAP, so... + case 0: sigval = TARGET_SIGNAL_TRAP; break; + + default: + fprintf (stderr, "Warning: Unknown RSP exception %lu: Ignored\n", except); + return; + } + + if ((0 != rsp.sigval) && (sigval != rsp.sigval)) + { + fprintf (stderr, "Warning: RSP signal %d received while signal " + "%d pending: Pending exception replaced\n", sigval, rsp.sigval); + } + + rsp.sigval = sigval; // Save the signal value + +} // rsp_exception () + + + +/*---------------------------------------------------------------------------*/ +/*!Handle a request to the server for a new client + + We may already have a client. If we do, we will accept an immediately close + the new client. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_server_request () +{ + struct sockaddr_in sock_addr; /* The socket address */ + socklen_t len; /* Size of the socket address */ + int fd; /* The client FD */ + int flags; /* fcntl () flags */ + int optval; /* Option value for setsockopt () */ + uint32_t tmp; + + /* Get the client FD */ + len = sizeof (sock_addr); + fd = accept (rsp.server_fd, (struct sockaddr *)&sock_addr, &len); + if (fd < 0) + { + /* This is can happen, because a connection could have started, and then + terminated due to a protocol error or user initiation before the + accept could take place. + + Two of the errors we can ignore (a retry is permissible). All other + errors, we assume the server port has gone tits up and close. */ + + if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) + { + fprintf (stderr, "Warning: RSP server error creating client: " + "closing connection %s\n", strerror (errno)); + rsp_client_close (); + rsp_server_close (); + } + + return; + } + + /* If we already have a client, then immediately close the new one */ + if (-1 != rsp.client_fd) + { + fprintf (stderr, "Warning: Additional RSP client request refused\n"); + close (fd); + return; + } + + /* We have a new client, which should be non-blocking. Get the current flags + and then set the non-blocking flags */ + flags = fcntl (fd, F_GETFL); + if (flags < 0) + { + fprintf (stderr, "Warning: Unable to get flags for RSP client socket " + "%d: %s\n", fd, strerror (errno)); + close (fd); + return; + } + + flags |= O_NONBLOCK; + if (fcntl (fd, F_SETFL, flags) < 0) + { + fprintf (stderr, "Warning: Unable to set flags for RSP client socket " + "%d to 0x%08x: %s\n", fd, flags, strerror (errno)); + close (fd); + return; + } + + /* Turn of Nagel's algorithm for the client socket. This means the client + sends stuff immediately, it doesn't wait to fill up a packet. */ + optval = 0; + len = sizeof (optval); + if (setsockopt (fd, rsp.proto_num, TCP_NODELAY, &optval, len) < 0) + { + fprintf (stderr, "Warning: Unable to disable Nagel's algorithm for " + "RSP client socket %d: %s\n", fd, strerror (errno)); + close (fd); + return; + } + + /* Register for stall/unstall events from the target monitor thread. Also creates pipe + * for sending stall/unstall command to the target monitor. */ + if(0 > register_with_monitor_thread(pipe_fds)) { // pipe_fds[0] is for writing to monitor, [1] is to read from it + fprintf(stderr, "RSP server failed to register with monitor thread, exiting"); + rsp_server_close(); + close (fd); + return; + } + + /* We have a new client socket */ + rsp.client_fd = fd; + + /* Now that we have a valid client connection, set up the CPU for GDB + * Stall the CPU...it starts off running. */ + set_stall_state(1); + rsp.target_running = 0; // This prevents an initial exception report to GDB (which it's not expecting) + rsp.single_step_mode = 0; + + /* Set up the CPU to break to the debug unit on exceptions. */ + dbg_cpu0_read(SPR_DSR, &tmp); + dbg_cpu0_write(SPR_DSR, tmp|SPR_DSR_TE|SPR_DSR_FPE|SPR_DSR_RE|SPR_DSR_IIE|SPR_DSR_AE|SPR_DSR_BUSEE); + + /* Enable TRAP exception, but don't otherwise change the SR */ + dbg_cpu0_read(SPR_SR, &tmp); + dbg_cpu0_write(SPR_SR, tmp|SPR_SR_SM); // We set 'supervisor mode', which also enables TRAP exceptions + +} /* rsp_server_request () */ + + +/*---------------------------------------------------------------------------*/ +/*!Deal with a request from the GDB client session + + In general, apart from the simplest requests, this function replies on + other functions to implement the functionality. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_client_request () +{ + struct rsp_buf *buf = get_packet (); /* Message sent to us */ + + // Null packet means we hit EOF or the link was closed for some other + // reason. Close the client and return + if (NULL == buf) + { + rsp_client_close (); + return; + } + +#if RSP_TRACE + printf ("Packet received %s: %d chars\n", buf->data, buf->len ); + fflush (stdout); +#endif + + // Check if target is running. + // If running, only process async BREAK command + if(rsp.target_running) + { + if(buf->data[0] == 0x03) // 0x03 is the ctrl-C "break" command from GDB + { + // Send the STALL command to the target + set_stall_state (1); + } + else + { + // Send a response to GDB indicating the target is not stalled: "Target not stopped" + put_str_packet("O6154677274656e20746f73206f74707064650a0d"); // Need to hex-encode warning string (I think...) + fprintf(stderr, "WARNING: Received GDB command 0x%X (%c) while target running!\n", buf->data[0], buf->data[0]); + } + return; + } + + switch (buf->data[0]) + { + case 0x03: + fprintf(stderr, "Warning: asynchronous BREAK received while target stopped.\n"); + return; + + case '!': + /* Request for extended remote mode */ + put_str_packet ("OK"); + return; + + case '?': + /* Return last signal ID */ + rsp_report_exception(); + return; + + case 'A': + /* Initialization of argv not supported */ + fprintf (stderr, "Warning: RSP 'A' packet not supported: ignored\n"); + put_str_packet ("E01"); + return; + + case 'b': + /* Setting baud rate is deprecated */ + fprintf (stderr, "Warning: RSP 'b' packet is deprecated and not " + "supported: ignored\n"); + return; + + case 'B': + /* Breakpoints should be set using Z packets */ + fprintf (stderr, "Warning: RSP 'B' packet is deprecated (use 'Z'/'z' " + "packets instead): ignored\n"); + return; + + case 'c': + /* Continue */ + rsp_continue (buf); + return; + + case 'C': + /* Continue with signal */ + rsp_continue_with_signal (buf); + return; + + case 'd': + /* Disable debug using a general query */ + fprintf (stderr, "Warning: RSP 'd' packet is deprecated (define a 'Q' " + "packet instead: ignored\n"); + return; + + case 'D': + /* Detach GDB. Do this by closing the client. The rules say that + execution should continue. TODO. Is this really then intended + meaning? Or does it just mean that only vAttach will be recognized + after this? */ + put_str_packet ("OK"); + rsp_client_close (); + set_stall_state (0); + return; + + case 'F': + /* File I/O is not currently supported */ + fprintf (stderr, "Warning: RSP file I/O not currently supported: 'F' " + "packet ignored\n"); + return; + + case 'g': + rsp_read_all_regs (); + return; + + case 'G': + rsp_write_all_regs (buf); + return; + + case 'H': + /* Set the thread number of subsequent operations. For now ignore + silently and just reply "OK" */ + put_str_packet ("OK"); + return; + + case 'i': + /* Single instruction step */ + rsp_step (buf); + return; + + case 'I': + /* Single instruction step with signal */ + rsp_step_with_signal (buf); + return; + + case 'k': + /* Kill request. Do nothing for now. */ + return; + + case 'm': + /* Read memory (symbolic) */ + rsp_read_mem (buf); + return; + + case 'M': + /* Write memory (symbolic) */ + rsp_write_mem (buf); + return; + + case 'p': + /* Read a register */ + rsp_read_reg (buf); + return; + + case 'P': + /* Write a register */ + rsp_write_reg (buf); + return; + + case 'q': + /* Any one of a number of query packets */ + rsp_query (buf); + return; + + case 'Q': + /* Any one of a number of set packets */ + rsp_set (buf); + return; + + case 'r': + /* Reset the system. Deprecated (use 'R' instead) */ + fprintf (stderr, "Warning: RSP 'r' packet is deprecated (use 'R' " + "packet instead): ignored\n"); + return; + + case 'R': + /* Restart the program being debugged. */ + rsp_restart (); + return; + + case 's': + /* Single step (one high level instruction). This could be hard without + DWARF2 info */ + rsp_step (buf); + return; + + case 'S': + /* Single step (one high level instruction) with signal. This could be + hard without DWARF2 info */ + rsp_step_with_signal (buf); + return; + + case 't': + /* Search. This is not well defined in the manual and for now we don't + support it. No response is defined. */ + fprintf (stderr, "Warning: RSP 't' packet not supported: ignored\n"); + return; + + case 'T': + /* Is the thread alive. We are bare metal, so don't have a thread + context. The answer is always "OK". */ + put_str_packet ("OK"); + return; + + case 'v': + /* Any one of a number of packets to control execution */ + rsp_vpkt (buf); + return; + + case 'X': + /* Write memory (binary) */ + rsp_write_mem_bin (buf); + return; + + case 'z': + /* Remove a breakpoint/watchpoint. */ + rsp_remove_matchpoint (buf); + return; + + case 'Z': + /* Insert a breakpoint/watchpoint. */ + rsp_insert_matchpoint (buf); + return; + + default: + /* Unknown commands are ignored */ + fprintf (stderr, "Warning: Unknown RSP request %s\n", buf->data); + return; + } +} /* rsp_client_request () */ + + +/*---------------------------------------------------------------------------*/ +/*!Close the server if it is open */ +/*---------------------------------------------------------------------------*/ +static void +rsp_server_close () +{ + if (-1 != rsp.server_fd) + { + close (rsp.server_fd); + rsp.server_fd = -1; + } +} /* rsp_server_close () */ + + +/*---------------------------------------------------------------------------*/ +/*!Close the client if it is open */ +/*---------------------------------------------------------------------------*/ +static void +rsp_client_close () +{ + // If target is running, stop it so we can modify SPRs + if(rsp.target_running) { + set_stall_state(1); + } + + // Clear the DSR: don't transfer control to the debug unit for any reason + dbg_cpu0_write(SPR_DSR, 0); + + // If target was running, restart it. + // rsp.target_running is changed in this thread, so it won't have changed due to the above stall command. + if(rsp.target_running) { + set_stall_state(0); + } + + // Unregister with the target handler thread. MUST BE DONE AFTER THE LAST set_stall_state()! + unregister_with_monitor_thread(pipe_fds); + + if (-1 != rsp.client_fd) + { + close (rsp.client_fd); + rsp.client_fd = -1; + } +} /* rsp_client_close () */ + + +/*---------------------------------------------------------------------------*/ +/*!Send a packet to the GDB client + + Modeled on the stub version supplied with GDB. Put out the data preceded by + a '$', followed by a '#' and a one byte checksum. '$', '#', '*' and '}' are + escaped by preceding them with '}' and then XORing the character with + 0x20. + + @param[in] buf The data to send */ +/*---------------------------------------------------------------------------*/ +static void +put_packet (struct rsp_buf *buf) +{ + int ch; /* Ack char */ + + /* Construct $#. Repeat until the GDB client + acknowledges satisfactory receipt. */ + do + { + unsigned char checksum = 0; /* Computed checksum */ + int count = 0; /* Index into the buffer */ + +#if RSP_TRACE + printf ("Putting %s\n", buf->data); + fflush (stdout); +#endif + + put_rsp_char ('$'); /* Start char */ + + /* Body of the packet */ + for (count = 0; count < buf->len; count++) + { + unsigned char ch = buf->data[count]; + + /* Check for escaped chars */ + if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch)) + { + ch ^= 0x20; + checksum += (unsigned char)'}'; + put_rsp_char ('}'); + } + + checksum += ch; + put_rsp_char (ch); + } + + put_rsp_char ('#'); /* End char */ + + /* Computed checksum */ + put_rsp_char (hexchars[checksum >> 4]); + put_rsp_char (hexchars[checksum % 16]); + + /* Check for ack of connection failure */ + ch = get_rsp_char (); + if (-1 == ch) + { + return; /* Fail the put silently. */ + } + } + while ('+' != ch); + +} /* put_packet () */ + + +/*---------------------------------------------------------------------------*/ +/*!Convenience to put a constant string packet + + param[in] str The text of the packet */ +/*---------------------------------------------------------------------------*/ +static void +put_str_packet (const char *str) +{ + struct rsp_buf buf; + int len = strlen (str); + + /* Construct the packet to send, so long as string is not too big, + otherwise truncate. Add EOS at the end for convenient debug printout */ + + if (len >= GDB_BUF_MAX) + { + fprintf (stderr, "Warning: String %s too large for RSP packet: " + "truncated\n", str); + len = GDB_BUF_MAX - 1; + } + + strncpy (buf.data, str, len); + buf.data[len] = 0; + buf.len = len; + + put_packet (&buf); + +} /* put_str_packet () */ + + +/*---------------------------------------------------------------------------*/ +/*!Get a packet from the GDB client + + Modeled on the stub version supplied with GDB. The data is in a static + buffer. The data should be copied elsewhere if it is to be preserved across + a subsequent call to get_packet(). + + Unlike the reference implementation, we don't deal with sequence + numbers. GDB has never used them, and this implementation is only intended + for use with GDB 6.8 or later. Sequence numbers were removed from the RSP + standard at GDB 5.0. + + @return A pointer to the static buffer containing the data */ +/*---------------------------------------------------------------------------*/ +static struct rsp_buf * +get_packet () +{ + static struct rsp_buf buf; /* Survives the return */ + + /* Keep getting packets, until one is found with a valid checksum */ + while (1) + { + unsigned char checksum; /* The checksum we have computed */ + int count; /* Index into the buffer */ + int ch; /* Current character */ + + /* Wait around for the start character ('$'). Ignore all other + characters */ + ch = get_rsp_char (); + while (ch != '$') + { + if (-1 == ch) + { + return NULL; /* Connection failed */ + } + + // 0x03 is a special case, an out-of-band break when running + if(ch == 0x03) + { + buf.data[0] = ch; + buf.len = 1; + return &buf; + } + + ch = get_rsp_char (); + } + + /* Read until a '#' or end of buffer is found */ + checksum = 0; + count = 0; + while (count < GDB_BUF_MAX - 1) + { + ch = get_rsp_char (); + + /* Check for connection failure */ + if (-1 == ch) + { + return NULL; + } + + /* If we hit a start of line char begin all over again */ + if ('$' == ch) + { + checksum = 0; + count = 0; + + continue; + } + + /* Break out if we get the end of line char */ + if ('#' == ch) + { + break; + } + + /* Update the checksum and add the char to the buffer */ + + checksum = checksum + (unsigned char)ch; + buf.data[count] = (char)ch; + count = count + 1; + } + + /* Mark the end of the buffer with EOS - it's convenient for non-binary + data to be valid strings. */ + buf.data[count] = 0; + buf.len = count; + + /* If we have a valid end of packet char, validate the checksum */ + if ('#' == ch) + { + unsigned char xmitcsum; /* The checksum in the packet */ + + ch = get_rsp_char (); + if (-1 == ch) + { + return NULL; /* Connection failed */ + } + xmitcsum = hex (ch) << 4; + + ch = get_rsp_char (); + if (-1 == ch) + { + return NULL; /* Connection failed */ + } + + xmitcsum += hex (ch); + + /* If the checksums don't match print a warning, and put the + negative ack back to the client. Otherwise put a positive ack. */ + if (checksum != xmitcsum) + { + fprintf (stderr, "Warning: Bad RSP checksum: Computed " + "0x%02x, received 0x%02x\n", checksum, xmitcsum); + + put_rsp_char ('-'); /* Failed checksum */ + } + else + { + put_rsp_char ('+'); /* successful transfer */ + break; + } + } + else + { + fprintf (stderr, "Warning: RSP packet overran buffer\n"); + } + } + + return &buf; /* Success */ + +} /* get_packet () */ + + +/*---------------------------------------------------------------------------*/ +/*!Put a single character out onto the client socket + + This should only be called if the client is open, but we check for safety. + + @param[in] c The character to put out */ +/*---------------------------------------------------------------------------*/ +static void +put_rsp_char (char c) +{ + if (-1 == rsp.client_fd) + { + fprintf (stderr, "Warning: Attempt to write '%c' to unopened RSP " + "client: Ignored\n", c); + return; + } + + /* Write until successful (we retry after interrupts) or catastrophic + failure. */ + while (1) + { + switch (write (rsp.client_fd, &c, sizeof (c))) + { + case -1: + /* Error: only allow interrupts or would block */ + if ((EAGAIN != errno) && (EINTR != errno)) + { + fprintf (stderr, "Warning: Failed to write to RSP client: " + "Closing client connection: %s\n", + strerror (errno)); + rsp_client_close (); + return; + } + + break; + + case 0: + break; /* Nothing written! Try again */ + + default: + return; /* Success, we can return */ + } + } +} /* put_rsp_char () */ + + +/*---------------------------------------------------------------------------*/ +/*!Get a single character from the client socket + + This should only be called if the client is open, but we check for safety. + + @return The character read, or -1 on failure */ +/*---------------------------------------------------------------------------*/ +static int +get_rsp_char () +{ + unsigned char c; /* The character read */ + + if (-1 == rsp.client_fd) + { + fprintf (stderr, "Warning: Attempt to read from unopened RSP " + "client: Ignored\n"); + return -1; + } + + /* Read until successful (we retry after interrupts) or catastrophic + failure. */ + while (1) + { + switch (read (rsp.client_fd, &c, sizeof (c))) + { + case -1: + /* Error: only allow interrupts or would block */ + if ((EAGAIN != errno) && (EINTR != errno)) + { + fprintf (stderr, "Warning: Failed to read from RSP client: " + "Closing client connection: %s\n", + strerror (errno)); + rsp_client_close (); + return -1; + } + + break; + + case 0: + // EOF + rsp_client_close (); + return -1; + + default: + return c & 0xff; /* Success, we can return (no sign extend!) */ + } + } +} /* get_rsp_char () */ + + +/*---------------------------------------------------------------------------*/ +/*!"Unescape" RSP binary data + + '#', '$' and '}' are escaped by preceding them by '}' and oring with 0x20. + + This function reverses that, modifying the data in place. + + @param[in] data The array of bytes to convert + @para[in] len The number of bytes to be converted + + @return The number of bytes AFTER conversion */ +/*---------------------------------------------------------------------------*/ +static int +rsp_unescape (char *data, + int len) +{ + int from_off = 0; /* Offset to source char */ + int to_off = 0; /* Offset to dest char */ + + while (from_off < len) + { + /* Is it escaped */ + if ( '}' == data[from_off]) + { + from_off++; + data[to_off] = data[from_off] ^ 0x20; + } + else + { + data[to_off] = data[from_off]; + } + + from_off++; + to_off++; + } + + return to_off; + +} /* rsp_unescape () */ + + +/*---------------------------------------------------------------------------*/ +/*!Initialize the matchpoint hash table + + This is an open hash table, so this function clears all the links to + NULL. */ +/*---------------------------------------------------------------------------*/ +static void +mp_hash_init () +{ + int i; + + for (i = 0; i < MP_HASH_SIZE; i++) + { + rsp.mp_hash[i] = NULL; + } +} /* mp_hash_init () */ + + +/*---------------------------------------------------------------------------*/ +/*!Add an entry to the matchpoint hash table + + Add the entry if it wasn't already there. If it was there do nothing. The + match just be on type and addr. The instr need not match, since if this is + a duplicate insertion (perhaps due to a lost packet) they will be + different. + + @param[in] type The type of matchpoint + @param[in] addr The address of the matchpoint + @para[in] instr The instruction to associate with the address */ +/*---------------------------------------------------------------------------*/ +static void +mp_hash_add (enum mp_type type, + unsigned long int addr, + unsigned long int instr) +{ + int hv = addr % MP_HASH_SIZE; + struct mp_entry *curr; + + /* See if we already have the entry */ + for(curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next) + { + if ((type == curr->type) && (addr == curr->addr)) + { + return; /* We already have the entry */ + } + } + + /* Insert the new entry at the head of the chain */ + curr = malloc (sizeof (*curr)); + + curr->type = type; + curr->addr = addr; + curr->instr = instr; + curr->next = rsp.mp_hash[hv]; + + rsp.mp_hash[hv] = curr; + +} /* mp_hash_add () */ + + +/*---------------------------------------------------------------------------*/ +/*!Look up an entry in the matchpoint hash table + + The match must be on type AND addr. + + @param[in] type The type of matchpoint + @param[in] addr The address of the matchpoint + + @return The entry deleted, or NULL if the entry was not found */ +/*---------------------------------------------------------------------------*/ +static struct mp_entry * +mp_hash_lookup (enum mp_type type, + unsigned long int addr) +{ + int hv = addr % MP_HASH_SIZE; + struct mp_entry *curr; + + /* Search */ + for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next) + { + if ((type == curr->type) && (addr == curr->addr)) + { + return curr; /* The entry found */ + } + } + + /* Not found */ + return NULL; + +} /* mp_hash_lookup () */ + + +/*---------------------------------------------------------------------------*/ +/*!Delete an entry from the matchpoint hash table + + If it is there the entry is deleted from the hash table. If it is not + there, no action is taken. The match must be on type AND addr. + + The usual fun and games tracking the previous entry, so we can delete + things. + + @note The deletion DOES NOT free the memory associated with the entry, + since that is returned. The caller should free the memory when they + have used the information. + + @param[in] type The type of matchpoint + @param[in] addr The address of the matchpoint + + @return The entry deleted, or NULL if the entry was not found */ +/*---------------------------------------------------------------------------*/ +static struct mp_entry * +mp_hash_delete (enum mp_type type, + unsigned long int addr) +{ + int hv = addr % MP_HASH_SIZE; + struct mp_entry *prev = NULL; + struct mp_entry *curr; + + /* Search */ + for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next) + { + if ((type == curr->type) && (addr == curr->addr)) + { + /* Found - delete. Method depends on whether we are the head of + chain. */ + if (NULL == prev) + { + rsp.mp_hash[hv] = curr->next; + } + else + { + prev->next = curr->next; + } + + return curr; /* The entry deleted */ + } + + prev = curr; + } + + /* Not found */ + return NULL; + +} /* mp_hash_delete () */ + + +/*---------------------------------------------------------------------------*/ +/*!Utility to give the value of a hex char + + @param[in] ch A character representing a hexadecimal digit. Done as -1, + for consistency with other character routines, which can use + -1 as EOF. + + @return The value of the hex character, or -1 if the character is + invalid. */ +/*---------------------------------------------------------------------------*/ +static int +hex (int c) +{ + return ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 : + ((c >= '0') && (c <= '9')) ? c - '0' : + ((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1; + +} /* hex () */ + + +/*---------------------------------------------------------------------------*/ +/*!Convert a register to a hex digit string + + The supplied 32-bit value is converted to an 8 digit hex string according + the target endianism. It is null terminated for convenient printing. + + @param[in] val The value to convert + @param[out] buf The buffer for the text string */ +/*---------------------------------------------------------------------------*/ +static void +reg2hex (unsigned long int val, + char *buf) +{ + int n; /* Counter for digits */ + + for (n = 0; n < 8; n++) + { +#ifdef WORDSBIGENDIAN + int nyb_shift = n * 4; +#else + int nyb_shift = 28 - (n * 4); +#endif + buf[n] = hexchars[(val >> nyb_shift) & 0xf]; + } + + buf[8] = 0; /* Useful to terminate as string */ + +} /* reg2hex () */ + + +/*---------------------------------------------------------------------------*/ +/*!Convert a hex digit string to a register value + + The supplied 8 digit hex string is converted to a 32-bit value according + the target endianism + + @param[in] buf The buffer with the hex string + + @return The value to convert */ +/*---------------------------------------------------------------------------*/ +static unsigned long int +hex2reg (char *buf) +{ + int n; /* Counter for digits */ + unsigned long int val = 0; /* The result */ + + for (n = 0; n < 8; n++) + { +#ifdef WORDSBIGENDIAN + int nyb_shift = n * 4; +#else + int nyb_shift = 28 - (n * 4); +#endif + val |= hex (buf[n]) << nyb_shift; + } + + return val; + +} /* hex2reg () */ + + +/*---------------------------------------------------------------------------*/ +/*!Convert an ASCII character string to pairs of hex digits + + Both source and destination are null terminated. + + @param[out] dest Buffer to store the hex digit pairs (null terminated) + @param[in] src The ASCII string (null terminated) */ +/*---------------------------------------------------------------------------*/ +static void ascii2hex (char *dest, + char *src) +{ + int i; + + /* Step through converting the source string */ + for (i = 0; src[i] != '\0'; i++) + { + char ch = src[i]; + + dest[i * 2] = hexchars[ch >> 4 & 0xf]; + dest[i * 2 + 1] = hexchars[ch & 0xf]; + } + + dest[i * 2] = '\0'; + +} /* ascii2hex () */ + + +/*---------------------------------------------------------------------------*/ +/*!Convert pairs of hex digits to an ASCII character string + + Both source and destination are null terminated. + + @param[out] dest The ASCII string (null terminated) + @param[in] src Buffer holding the hex digit pairs (null terminated) */ +/*---------------------------------------------------------------------------*/ +static void hex2ascii (char *dest, + char *src) +{ + int i; + + /* Step through convering the source hex digit pairs */ + for (i = 0; src[i * 2] != '\0' && src[i * 2 + 1] != '\0'; i++) + { + dest[i] = ((hex (src[i * 2]) & 0xf) << 4) | (hex (src[i * 2 + 1]) & 0xf); + } + + dest[i] = '\0'; + +} /* hex2ascii () */ + + +/*---------------------------------------------------------------------------*/ +/*!Set the program counter + + This sets the value in the NPC SPR. Not completely trivial, since this is + actually cached in cpu_state.pc. Any reset of the NPC also involves + clearing the delay state and setting the pcnext global. + + Only actually do this if the requested address is different to the current + NPC (avoids clearing the delay pipe). + + @param[in] addr The address to use */ +/*---------------------------------------------------------------------------*/ +static unsigned int set_npc (unsigned long int addr) +{ + int errcode; + + errcode = dbg_cpu0_write(SPR_NPC, addr); + cached_npc = addr; + use_cached_npc = 1; + + /* This was done in the simulator. Is any of this necessary on the hardware? --NAY + if (cpu_state.pc != addr) + { + cpu_state.pc = addr; + cpu_state.delay_insn = 0; + pcnext = addr + 4; + } + */ + return errcode; +} /* set_npc () */ + + +/*---------------------------------------------------------------------------*/ +/*!Send a packet acknowledging an exception has occurred + + This is only called if there is a client FD to talk to */ +/*---------------------------------------------------------------------------*/ +static void +rsp_report_exception () +{ + struct rsp_buf buf; + + /* Construct a signal received packet */ + buf.data[0] = 'S'; + buf.data[1] = hexchars[rsp.sigval >> 4]; + buf.data[2] = hexchars[rsp.sigval % 16]; + buf.data[3] = 0; + buf.len = strlen (buf.data); + + put_packet (&buf); + +} /* rsp_report_exception () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP continue request + + Parse the command to see if there is an address. Uses the underlying + generic continue function, with EXCEPT_NONE. + + @param[in] buf The full continue packet */ +/*---------------------------------------------------------------------------*/ +static void +rsp_continue (struct rsp_buf *buf) +{ + unsigned long int addr; /* Address to continue from, if any */ + + if (strncmp(buf->data, "c", 2)) + { + if(1 != sscanf (buf->data, "c%lx", &addr)) + { + fprintf (stderr, + "Warning: RSP continue address %s not recognized: ignored\n", + buf->data); + } + else + { + /* Set the address as the value of the next program counter */ + // TODO Is support for this really that simple? --NAY + set_npc (addr); + } + } + + rsp_continue_generic (EXCEPT_NONE); + +} /* rsp_continue () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP continue with signal request + + Currently null. Will use the underlying generic continue function. + + @param[in] buf The full continue with signal packet */ +/*---------------------------------------------------------------------------*/ +static void +rsp_continue_with_signal (struct rsp_buf *buf) +{ + printf ("RSP continue with signal '%s' received\n", buf->data); + +} /* rsp_continue_with_signal () */ + + +/*---------------------------------------------------------------------------*/ +/*!Generic processing of a continue request + + The signal may be EXCEPT_NONE if there is no exception to be + handled. Currently the exception is ignored. + + The single step flag is cleared in the debug registers and then the + processor is unstalled. + + @param[in] addr Address from which to step + @param[in] except The exception to use (if any) */ +/*---------------------------------------------------------------------------*/ +static void +rsp_continue_generic (unsigned long int except) +{ + uint32_t tmp; + + /* Clear Debug Reason Register */ + dbg_cpu0_write(SPR_DRR, 0); + + /* Clear any watchpoints indicated in DMR2. Any write to DMR2 will clear this (undocumented feature). */ + dbg_cpu0_read(SPR_DMR2, &tmp); + if(tmp & SPR_DMR2_WBS) { // don't waste the time writing if no hw breakpoints set + dbg_cpu0_write(SPR_DMR2, tmp); + } + + /* Clear the single step trigger in Debug Mode Register 1 and set traps to be + handled by the debug unit in the Debug Stop Register */ + dbg_cpu0_read(SPR_DMR1, &tmp); + tmp &= ~(SPR_DMR1_ST|SPR_DMR1_BT); // clear single-step and trap-on-branch + dbg_cpu0_write(SPR_DMR1, tmp); + + // *** TODO Is there ever a situation where the DSR will not be set to give us control on a TRAP? --NAY + + /* Unstall the processor (also starts the target handler thread) */ + set_stall_state (0); + + /* Note the GDB client is now waiting for a reply. */ + rsp.client_waiting = 1; + rsp.single_step_mode = 0; + +} /* rsp_continue_generic () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP read all registers request + + The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PPC + (i.e. SPR PPC), NPC (i.e. SPR NPC) and SR (i.e. SPR SR). Each register is + returned as a sequence of bytes in target endian order. + + Each byte is packed as a pair of hex digits. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_read_all_regs () +{ + struct rsp_buf buf; /* Buffer for the reply */ + int r; /* Register index */ + uint32_t regbuf[MAX_GPRS]; + unsigned int errcode = APP_ERR_NONE; + + // Read all the GPRs in a single burst, for efficiency + errcode = dbg_cpu0_read_block(SPR_GPR_BASE, regbuf, MAX_GPRS); + + /* Format the GPR data for output */ + for (r = 0; r < MAX_GPRS; r++) + { + reg2hex(regbuf[r], &(buf.data[r * 8])); + } + + /* PPC, NPC and SR have consecutive addresses, read in one burst */ + errcode |= dbg_cpu0_read_block(SPR_NPC, regbuf, 3); + + // Note that reg2hex adds a NULL terminator; as such, they must be + // put in buf.data in numerical order: PPC, NPC, SR + reg2hex(regbuf[2], &(buf.data[PPC_REGNUM * 8])); + + if(use_cached_npc == 1) { // Hackery to work around CPU hardware quirk + reg2hex(cached_npc, &(buf.data[NPC_REGNUM * 8])); + } + else { + reg2hex(regbuf[0], &(buf.data[NPC_REGNUM * 8])); + } + + reg2hex(regbuf[1], &(buf.data[SR_REGNUM * 8])); + + //fprintf(stderr, "Read SPRs: 0x%08X, 0x%08X, 0x%08X\n", regbuf[0], regbuf[1], regbuf[2]); + + if(errcode == APP_ERR_NONE) { + /* Finalize the packet and send it */ + buf.data[NUM_REGS * 8] = 0; + buf.len = NUM_REGS * 8; + put_packet (&buf); + } + else { + fprintf(stderr, "Error while reading all registers: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_read_all_regs () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP write all registers request + + The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PPC + (i.e. SPR PPC), NPC (i.e. SPR NPC) and SR (i.e. SPR SR). Each register is + supplied as a sequence of bytes in target endian order. + + Each byte is packed as a pair of hex digits. + + @todo There is no error checking at present. Non-hex chars will generate a + warning message, but there is no other check that the right amount + of data is present. The result is always "OK". + + @param[in] buf The original packet request. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_write_all_regs (struct rsp_buf *buf) +{ + int r; /* Register index */ + uint32_t regbuf[MAX_GPRS]; + unsigned int errcode; + + /* The GPRs */ + for (r = 0; r < MAX_GPRS; r++) + { + // Set up the data for a burst access + regbuf[r] = hex2reg (&(buf->data[r * 8])); + } + + errcode = dbg_cpu0_write_block(SPR_GPR_BASE, regbuf, MAX_GPRS); + + /* PPC, NPC and SR */ + regbuf[0] = hex2reg (&(buf->data[NPC_REGNUM * 8])); + regbuf[1] = hex2reg (&(buf->data[SR_REGNUM * 8])); + regbuf[2] = hex2reg (&(buf->data[PPC_REGNUM * 8])); + + errcode |= dbg_cpu0_write_block(SPR_NPC, regbuf, 3); + + /* + tmp = hex2reg (&(buf->data[PPC_REGNUM * 8])); + dbg_cpu0_write(SPR_PPC, tmp); + + tmp = hex2reg (&(buf->data[SR_REGNUM * 8])); + dbg_cpu0_write(SPR_SR, tmp); + + tmp = hex2reg (&(buf->data[NPC_REGNUM * 8])); + dbg_cpu0_write(SPR_NPC, tmp); + */ + + if(errcode == APP_ERR_NONE) + put_str_packet ("OK"); + else { + fprintf(stderr, "Error while writing all registers: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_write_all_regs () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP read memory (symbolic) request + + Syntax is: + + m,: + + The response is the bytes, lowest address first, encoded as pairs of hex + digits. + + The length given is the number of bytes to be read. + + @note This function reuses buf, so trashes the original command. + + @param[in] buf The command received */ +/*---------------------------------------------------------------------------*/ +static void +rsp_read_mem (struct rsp_buf *buf) +{ + unsigned int addr; /* Where to read the memory */ + int len; /* Number of bytes to read */ + int off; /* Offset into the memory */ + unsigned int errcode = APP_ERR_NONE; + + if (2 != sscanf (buf->data, "m%x,%x:", &addr, &len)) + { + fprintf (stderr, "Warning: Failed to recognize RSP read memory " + "command: %s\n", buf->data); + put_str_packet ("E01"); + return; + } + + /* Make sure we won't overflow the buffer (2 chars per byte) */ + if ((len * 2) >= GDB_BUF_MAX) + { + fprintf (stderr, "Warning: Memory read %s too large for RSP packet: " + "truncated\n", buf->data); + len = (GDB_BUF_MAX - 1) / 2; + } + + // Do the memory read into a temporary buffer + unsigned char *tmpbuf = (unsigned char *) malloc(len); // *** TODO check return, don't always malloc (use realloc) + errcode = dbg_wb_read_block8(addr, tmpbuf, len); + + + /* Refill the buffer with the reply */ + for (off = 0; off < len; off++) + { + unsigned char ch; /* The byte at the address */ + + /* Check memory area is valid. Not really possible without knowing hardware configuration. */ + + // Get the memory direct - no translation. + ch = tmpbuf[off]; + buf->data[off * 2] = hexchars[ch >> 4]; + buf->data[off * 2 + 1] = hexchars[ch & 0xf]; + } + + free(tmpbuf); + + if(errcode == APP_ERR_NONE) { + buf->data[off * 2] = 0; /* End of string */ + buf->len = strlen (buf->data); + put_packet (buf); + } + else { + fprintf(stderr, "Error reading memory: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_read_mem () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP write memory (symbolic) request + + Syntax is: + + m,: + + The data is the bytes, lowest address first, encoded as pairs of hex + digits. + + The length given is the number of bytes to be written. + + @note This function reuses buf, so trashes the original command. + + @param[in] buf The command received */ +/*---------------------------------------------------------------------------*/ +static void +rsp_write_mem (struct rsp_buf *buf) +{ + unsigned int addr; /* Where to write the memory */ + int len; /* Number of bytes to write */ + char *symdat; /* Pointer to the symboli data */ + int datlen; /* Number of digits in symbolic data */ + int off; /* Offset into the memory */ + unsigned int errcode; + + if (2 != sscanf (buf->data, "M%x,%x:", &addr, &len)) + { + fprintf (stderr, "Warning: Failed to recognize RSP write memory " + "command: %s\n", buf->data); + put_str_packet ("E01"); + return; + } + + /* Find the start of the data and check there is the amount we expect. */ + symdat = memchr ((const void *)buf->data, ':', GDB_BUF_MAX) + 1; + datlen = buf->len - (symdat - buf->data); + + /* Sanity check */ + if (len * 2 != datlen) + { + fprintf (stderr, "Warning: Write of %d digits requested, but %d digits " + "supplied: packet ignored\n", len * 2, datlen ); + put_str_packet ("E01"); + return; + } + + /* Write the bytes to memory */ + // Put all the data into a single buffer, so it can be burst-written via JTAG. + // One burst is much faster than many single-byte transactions. + unsigned char *tmpbuf = (unsigned char *) malloc(len); + for (off = 0; off < len; off++) + { + unsigned char nyb1 = hex (symdat[off * 2]); + unsigned char nyb2 = hex (symdat[off * 2 + 1]); + tmpbuf[off] = (nyb1 << 4) | nyb2; + } + + errcode = dbg_wb_write_block8(addr, tmpbuf, len); + free(tmpbuf); + + /* Can't really check if the memory addresses are valid on hardware. */ + if(errcode == APP_ERR_NONE) { + put_str_packet ("OK"); + } + else { + fprintf(stderr, "Error writing memory: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_write_mem () */ + + +/*---------------------------------------------------------------------------*/ +/*!Read a single register + + The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC + (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a + sequence of bytes in target endian order. + + Each byte is packed as a pair of hex digits. + + @param[in] buf The original packet request. Reused for the reply. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_read_reg (struct rsp_buf *buf) +{ + unsigned int regnum; + uint32_t tmp; + unsigned int errcode = APP_ERR_NONE; + + /* Break out the fields from the data */ + if (1 != sscanf (buf->data, "p%x", ®num)) + { + fprintf (stderr, "Warning: Failed to recognize RSP read register " + "command: \'%s\'\n", buf->data); + put_str_packet ("E01"); + return; + } + + /* Get the relevant register */ + if (regnum < MAX_GPRS) + { + errcode = dbg_cpu0_read(SPR_GPR_BASE+regnum, &tmp); + } + else if (PPC_REGNUM == regnum) + { + errcode = dbg_cpu0_read(SPR_PPC, &tmp); + } + else if (NPC_REGNUM == regnum) + { + if(use_cached_npc) { + tmp = cached_npc; + } else { + errcode = dbg_cpu0_read(SPR_NPC, &tmp); + } + } + else if (SR_REGNUM == regnum) + { + errcode = dbg_cpu0_read(SPR_SR, &tmp); + } + else + { + /* Error response if we don't know the register */ + fprintf (stderr, "Warning: Attempt to read unknown register 0x%x: " + "ignored\n", regnum); + put_str_packet ("E01"); + return; + } + + if(errcode == APP_ERR_NONE) { + reg2hex(tmp, buf->data); + buf->len = strlen (buf->data); + put_packet (buf); + } + else { + fprintf(stderr, "Error reading register: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_read_reg () */ + + +/*---------------------------------------------------------------------------*/ +/*!Write a single register + + The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC + (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a + sequence of bytes in target endian order. + + Each byte is packed as a pair of hex digits. + + @param[in] buf The original packet request. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_write_reg (struct rsp_buf *buf) +{ + unsigned int regnum; + char valstr[9]; /* Allow for EOS on the string */ + unsigned int errcode = APP_ERR_NONE; + + /* Break out the fields from the data */ + if (2 != sscanf (buf->data, "P%x=%8s", ®num, valstr)) + { + fprintf (stderr, "Warning: Failed to recognize RSP write register " + "command: %s\n", buf->data); + put_str_packet ("E01"); + return; + } + + /* Set the relevant register. Must translate between GDB register numbering and hardware reg. numbers. */ + if (regnum < MAX_GPRS) + { + errcode = dbg_cpu0_write(SPR_GPR_BASE+regnum, hex2reg(valstr)); + } + else if (PPC_REGNUM == regnum) + { + errcode = dbg_cpu0_write(SPR_PPC, hex2reg(valstr)); + } + else if (NPC_REGNUM == regnum) + { + errcode = set_npc (hex2reg (valstr)); + } + else if (SR_REGNUM == regnum) + { + errcode = dbg_cpu0_write(SPR_SR, hex2reg(valstr)); + } + else + { + /* Error response if we don't know the register */ + fprintf (stderr, "Warning: Attempt to write unknown register 0x%x: " + "ignored\n", regnum); + put_str_packet ("E01"); + return; + } + + if(errcode == APP_ERR_NONE) { + put_str_packet ("OK"); + } + else { + fprintf(stderr, "Error writing register: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_write_reg () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP query request + + @param[in] buf The request */ +/*---------------------------------------------------------------------------*/ +static void +rsp_query (struct rsp_buf *buf) +{ + if (0 == strcmp ("qC", buf->data)) + { + /* Return the current thread ID (unsigned hex). A null response + indicates to use the previously selected thread. Since we do not + support a thread concept, this is the appropriate response. */ + put_str_packet (""); + } + else if (0 == strncmp ("qCRC", buf->data, strlen ("qCRC"))) + { + /* Return CRC of memory area */ + fprintf (stderr, "Warning: RSP CRC query not supported\n"); + put_str_packet ("E01"); + } + else if (0 == strcmp ("qfThreadInfo", buf->data)) + { + /* Return info about active threads. We return just '-1' */ + put_str_packet ("m-1"); + } + else if (0 == strcmp ("qsThreadInfo", buf->data)) + { + /* Return info about more active threads. We have no more, so return the + end of list marker, 'l' */ + put_str_packet ("l"); + } + else if (0 == strncmp ("qGetTLSAddr:", buf->data, strlen ("qGetTLSAddr:"))) + { + /* We don't support this feature */ + put_str_packet (""); + } + else if (0 == strncmp ("qL", buf->data, strlen ("qL"))) + { + /* Deprecated and replaced by 'qfThreadInfo' */ + fprintf (stderr, "Warning: RSP qL deprecated: no info returned\n"); + put_str_packet ("qM001"); + } + else if (0 == strcmp ("qOffsets", buf->data)) + { + /* Report any relocation */ + put_str_packet ("Text=0;Data=0;Bss=0"); + } + else if (0 == strncmp ("qP", buf->data, strlen ("qP"))) + { + /* Deprecated and replaced by 'qThreadExtraInfo' */ + fprintf (stderr, "Warning: RSP qP deprecated: no info returned\n"); + put_str_packet (""); + } + else if (0 == strncmp ("qRcmd,", buf->data, strlen ("qRcmd,"))) + { + /* This is used to interface to commands to do "stuff" */ + rsp_command (buf); + } + else if (0 == strncmp ("qSupported", buf->data, strlen ("qSupported"))) + { + /* Report a list of the features we support. For now we just ignore any + supplied specific feature queries, but in the future these may be + supported as well. Note that the packet size allows for 'G' + all the + registers sent to us, or a reply to 'g' with all the registers and an + EOS so the buffer is a well formed string. */ + + char reply[GDB_BUF_MAX]; + + sprintf (reply, "PacketSize=%x", GDB_BUF_MAX); + put_str_packet (reply); + } + else if (0 == strncmp ("qSymbol:", buf->data, strlen ("qSymbol:"))) + { + /* Offer to look up symbols. Nothing we want (for now). TODO. This just + ignores any replies to symbols we looked up, but we didn't want to + do that anyway! */ + put_str_packet ("OK"); + } + else if (0 == strncmp ("qThreadExtraInfo,", buf->data, + strlen ("qThreadExtraInfo,"))) + { + /* Report that we are runnable, but the text must be hex ASCI + digits. For now do this by steam, reusing the original packet */ + sprintf (buf->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", + 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); + buf->len = strlen (buf->data); + put_packet (buf); + } + else if (0 == strncmp ("qXfer:", buf->data, strlen ("qXfer:"))) + { + /* For now we support no 'qXfer' requests, but these should not be + expected, since they were not reported by 'qSupported' */ + fprintf (stderr, "Warning: RSP 'qXfer' not supported: ignored\n"); + put_str_packet (""); + } + else if (0 == strncmp ("qAttached", buf->data, strlen ("qAttached"))) + { + /* GDB is inquiring whether it created a process or attached to an + * existing one. We don't support this feature. Note this packet + * may have a ':' and a PID included. */ + put_str_packet (""); + } + else if (0 == strcmp ("qTStatus", buf->data)) + { + /* GDB is inquiring whether a trace is running. + * We don't support the trace feature, so respond with an + * empty packet. Note that if we respond 'no' with a "T0" + * packet, GDB will send us further queries about tracepoints. + */ + put_str_packet (""); + } + else + { + fprintf (stderr, "Unrecognized RSP query: ignored\n"); + } +} /* rsp_query () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP qRcmd request + + The actual command follows the "qRcmd," in ASCII encoded to hex + + @param[in] buf The request in full */ +/*---------------------------------------------------------------------------*/ +static void +rsp_command (struct rsp_buf *buf) +{ + char cmd[GDB_BUF_MAX]; + uint32_t tmp; + + hex2ascii (cmd, &(buf->data[strlen ("qRcmd,")])); + + /* Work out which command it is */ + if (0 == strncmp ("readspr ", cmd, strlen ("readspr"))) + { + unsigned int regno; + + /* Parse and return error if we fail */ + if( 1 != sscanf (cmd, "readspr %4x", ®no)) + { + fprintf (stderr, "Warning: qRcmd %s not recognized: ignored\n", + cmd); + put_str_packet ("E01"); + return; + } + + /* SPR out of range */ + if (regno > MAX_SPRS) + { + fprintf (stderr, "Warning: qRcmd readspr %x too large: ignored\n", + regno); + put_str_packet ("E01"); + return; + } + + /* Construct the reply */ + dbg_cpu0_read(regno, &tmp); // TODO Check return value of all hardware accesses + sprintf (cmd, "%8x", tmp); + ascii2hex (buf->data, cmd); + buf->len = strlen (buf->data); + put_packet (buf); + } + else if (0 == strncmp ("writespr ", cmd, strlen ("writespr"))) + { + unsigned int regno; + unsigned long int val; + + /* Parse and return error if we fail */ + if( 2 != sscanf (cmd, "writespr %4x %8lx", ®no, &val)) + { + fprintf (stderr, "Warning: qRcmd %s not recognized: ignored\n", + cmd); + put_str_packet ("E01"); + return; + } + + /* SPR out of range */ + if (regno > MAX_SPRS) + { + fprintf (stderr, "Warning: qRcmd writespr %x too large: ignored\n", + regno); + put_str_packet ("E01"); + return; + } + + /* Update the SPR and reply "OK" */ + dbg_cpu0_write(regno, val); + put_str_packet ("OK"); + } + +} /* rsp_command () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP set request + + @param[in] buf The request */ +/*---------------------------------------------------------------------------*/ +static void +rsp_set (struct rsp_buf *buf) +{ + if (0 == strncmp ("QPassSignals:", buf->data, strlen ("QPassSignals:"))) + { + /* Passing signals not supported */ + put_str_packet (""); + } + else if ((0 == strncmp ("QTDP", buf->data, strlen ("QTDP"))) || + (0 == strncmp ("QFrame", buf->data, strlen ("QFrame"))) || + (0 == strcmp ("QTStart", buf->data)) || + (0 == strcmp ("QTStop", buf->data)) || + (0 == strcmp ("QTinit", buf->data)) || + (0 == strncmp ("QTro", buf->data, strlen ("QTro")))) + { + /* All tracepoint features are not supported. This reply is really only + needed to 'QTDP', since with that the others should not be + generated. */ + put_str_packet (""); + } + else + { + fprintf (stderr, "Unrecognized RSP set request: ignored\n"); + } +} /* rsp_set () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP restart request + + For now we just put the program counter back to the one used with the last + vRun request. */ +/*---------------------------------------------------------------------------*/ +static void +rsp_restart () +{ + set_npc (rsp.start_addr); + +} /* rsp_restart () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP step request + + Parse the command to see if there is an address. Uses the underlying + generic step function, with EXCEPT_NONE. + + @param[in] buf The full step packet */ +/*---------------------------------------------------------------------------*/ +static void +rsp_step (struct rsp_buf *buf) +{ + unsigned long int addr; /* The address to step from, if any */ + + if(strncmp(buf->data, "s", 2)) + { + if(1 != sscanf (buf->data, "s%lx", &addr)) + { + fprintf (stderr, + "Warning: RSP step address %s not recognized: ignored\n", + buf->data); + } + else + { + /* Set the address as the value of the next program counter */ + // TODO Is implementing this really just this simple? + //set_npc (addr); + } + } + + rsp_step_generic (EXCEPT_NONE); + +} /* rsp_step () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP step with signal request + + Currently null. Will use the underlying generic step function. + + @param[in] buf The full step with signal packet */ +/*---------------------------------------------------------------------------*/ +static void +rsp_step_with_signal (struct rsp_buf *buf) +{ + int val; + printf ("RSP step with signal '%s' received\n", buf->data); + val = strtoul(&buf->data[1], NULL, 10); + rsp_step_generic(val); +} /* rsp_step_with_signal () */ + + +/*---------------------------------------------------------------------------*/ +/*!Generic processing of a step request + + The signal may be EXCEPT_NONE if there is no exception to be + handled. Currently the exception is ignored. + + The single step flag is set in the debug registers and then the processor + is unstalled. + + @param[in] addr Address from which to step + @param[in] except The exception to use (if any) */ +/*---------------------------------------------------------------------------*/ +static void +rsp_step_generic (unsigned long int except) +{ + uint32_t tmp; + + /* Clear Debug Reason Register */ + tmp = 0; + dbg_cpu0_write(SPR_DRR, tmp); // *** TODO Check return value of all hardware accesses + + /* Clear any watchpoint indicators in DMR2. Any write to DMR2 will do this (undocumented feature) */ + dbg_cpu0_read(SPR_DMR2, &tmp); + if(tmp & SPR_DMR2_WBS) { // If no HW breakpoints, don't waste time writing + dbg_cpu0_write(SPR_DMR2, tmp); + } + + /* Set the single step trigger in Debug Mode Register 1 and set traps to be + handled by the debug unit in the Debug Stop Register */ + if(!rsp.single_step_mode) + { + dbg_cpu0_read(SPR_DMR1, &tmp); + tmp |= SPR_DMR1_ST|SPR_DMR1_BT; + dbg_cpu0_write(SPR_DMR1, tmp); + dbg_cpu0_read(SPR_DSR, &tmp); + if(!(tmp & SPR_DSR_TE)) { + tmp |= SPR_DSR_TE; + dbg_cpu0_write(SPR_DSR, tmp); + } + rsp.single_step_mode = 1; + } + + /* Unstall the processor */ + set_stall_state (0); + + /* Note the GDB client is now waiting for a reply. */ + rsp.client_waiting = 1; + +} /* rsp_step_generic () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP 'v' packet + + These are commands associated with executing the code on the target + + @param[in] buf The request */ +/*---------------------------------------------------------------------------*/ +static void +rsp_vpkt (struct rsp_buf *buf) +{ + if (0 == strncmp ("vAttach;", buf->data, strlen ("vAttach;"))) + { + /* Attaching is a null action, since we have no other process. We just + return a stop packet (using TRAP) to indicate we are stopped. */ + put_str_packet ("S05"); + return; + } + else if (0 == strcmp ("vCont?", buf->data)) + { + /* For now we don't support this. */ + put_str_packet (""); + return; + } + else if (0 == strncmp ("vCont", buf->data, strlen ("vCont"))) + { + /* This shouldn't happen, because we've reported non-support via vCont? + above */ + fprintf (stderr, "Warning: RSP vCont not supported: ignored\n" ); + return; + } + else if (0 == strncmp ("vFile:", buf->data, strlen ("vFile:"))) + { + /* For now we don't support this. */ + fprintf (stderr, "Warning: RSP vFile not supported: ignored\n" ); + put_str_packet (""); + return; + } + else if (0 == strncmp ("vFlashErase:", buf->data, strlen ("vFlashErase:"))) + { + /* For now we don't support this. */ + fprintf (stderr, "Warning: RSP vFlashErase not supported: ignored\n" ); + put_str_packet ("E01"); + return; + } + else if (0 == strncmp ("vFlashWrite:", buf->data, strlen ("vFlashWrite:"))) + { + /* For now we don't support this. */ + fprintf (stderr, "Warning: RSP vFlashWrite not supported: ignored\n" ); + put_str_packet ("E01"); + return; + } + else if (0 == strcmp ("vFlashDone", buf->data)) + { + /* For now we don't support this. */ + fprintf (stderr, "Warning: RSP vFlashDone not supported: ignored\n" ); + put_str_packet ("E01"); + return; + } + else if (0 == strncmp ("vRun;", buf->data, strlen ("vRun;"))) + { + /* We shouldn't be given any args, but check for this */ + if (buf->len > strlen ("vRun;")) + { + fprintf (stderr, "Warning: Unexpected arguments to RSP vRun " + "command: ignored\n"); + } + + /* Restart the current program. However unlike a "R" packet, "vRun" + should behave as though it has just stopped. We use signal + 5 (TRAP). */ + rsp_restart (); + put_str_packet ("S05"); + } + else + { + fprintf (stderr, "Warning: Unknown RSP 'v' packet type %s: ignored\n", + buf->data); + put_str_packet ("E01"); + return; + } +} /* rsp_vpkt () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP write memory (binary) request + + Syntax is: + + X,: + + Followed by the specified number of bytes as raw binary. Response should be + "OK" if all copied OK, E if error has occurred. + + The length given is the number of bytes to be written. However the number + of data bytes may be greater, since '#', '$' and '}' are escaped by + preceding them by '}' and oring with 0x20. + + @param[in] buf The command received */ +/*---------------------------------------------------------------------------*/ +static void +rsp_write_mem_bin (struct rsp_buf *buf) +{ + unsigned int addr; /* Where to write the memory */ + int len; /* Number of bytes to write */ + char *bindat; /* Pointer to the binary data */ + int off; /* Offset to start of binary data */ + int newlen; /* Number of bytes in bin data */ + unsigned int errcode; + + if (2 != sscanf (buf->data, "X%x,%x:", &addr, &len)) + { + fprintf (stderr, "Warning: Failed to recognize RSP write memory " + "command: %s\n", buf->data); + put_str_packet ("E01"); + return; + } + + /* Find the start of the data and "unescape" it */ + bindat = memchr ((const void *)buf->data, ':', GDB_BUF_MAX) + 1; + off = bindat - buf->data; + newlen = rsp_unescape (bindat, buf->len - off); + + /* Sanity check */ + if (newlen != len) + { + int minlen = len < newlen ? len : newlen; + + fprintf (stderr, "Warning: Write of %d bytes requested, but %d bytes " + "supplied. %d will be written\n", len, newlen, minlen); + len = minlen; + } + + /* Write the bytes to memory */ + errcode = dbg_wb_write_block8(addr, (uint8_t *) bindat, len); + + // We can't really verify if the memory target address exists or not. + // Don't write to non-existant memory unless your system wishbone implementation + // has a hardware bus timeout. + if(errcode == APP_ERR_NONE) { + put_str_packet ("OK"); + } + else { + fprintf(stderr, "Error writing memory: %s\n", get_err_string(errcode)); + put_str_packet("E01"); + } + +} /* rsp_write_mem_bin () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP remove breakpoint or matchpoint request + + For now only memory breakpoints are implemented, which are implemented by + substituting a breakpoint at the specified address. The implementation must + cope with the possibility of duplicate packets. + + @todo This doesn't work with icache/immu yet + + @param[in] buf The command received */ +/*---------------------------------------------------------------------------*/ +static void +rsp_remove_matchpoint (struct rsp_buf *buf) +{ + enum mp_type type; /* What sort of matchpoint */ + uint32_t addr; /* Address specified */ + int len; /* Matchpoint length (not used) */ + struct mp_entry *mpe; /* Info about the replaced instr */ + uint32_t instbuf[1]; + uint32_t hwp, regaddr, regdata; /* used to clear HWP bit */ + + /* Break out the instruction */ + if (3 != sscanf (buf->data, "z%1d,%x,%1d", (int *)&type, &addr, &len)) + { + fprintf (stderr, "Warning: RSP matchpoint deletion request not " + "recognized: ignored\n"); + put_str_packet ("E01"); + return; + } + + /* Sanity check that the length is 4 */ + if (4 != len) + { + fprintf (stderr, "Warning: RSP matchpoint deletion length %d not " + "valid: 4 assumed\n", len); + len = 4; + } + + /* Sort out the type of matchpoint */ + switch (type) + { + case BP_MEMORY: + /* Memory breakpoint - replace the original instruction. */ + mpe = mp_hash_delete (type, addr); + + /* If the BP hasn't yet been deleted, put the original instruction + back. Don't forget to free the hash table entry afterwards. */ + if (NULL != mpe) + { + instbuf[0] = mpe->instr; + dbg_wb_write_block32(addr, instbuf, 1); // *** TODO Check return value + free (mpe); + } + + put_str_packet ("OK"); + break;; + + case BP_HARDWARE: + case WP_WRITE: + case WP_READ: + case WP_ACCESS: + mpe = mp_hash_delete (type, addr); + /* The wp we used is stored in mpe->instr */ + if(NULL != mpe) + { + hwp = mpe->instr; + free (mpe); + /* Clear enable bit in DMR2 */ + regaddr = SPR_DMR2; + dbg_cpu0_read(regaddr, ®data); // *** TODO Check return value + regdata &= ~((0x1 << hwp) << 12); /* Clear the correct WGB bit */ + dbg_cpu0_write(regaddr, regdata); // *** TODO Check return value + + /* This isn't strictly necessary, but it makes things easier for HWP clients. This way, + * they can read regs and write them back with no changes, and the HWP server won't mark + * this watchpoint as 'in use'. Small performance hit. */ + regaddr = SPR_DCR(hwp); + regdata = 0x01; /* Disabled */ + dbg_cpu0_write(regaddr, regdata); + + hwp_return_watchpoint(hwp); /* mark the wp as unused again */ + put_str_packet ("OK"); + } + else + { + /* GDB has been observed to disable the same watchpoint twice, then give an error message + * "conflicting enabled responses" after it tries to re-disable a watchpoint that no + * longer exists. So, if GDB tries to disable a HWP that doesn't exist, tell it it has + * succeeded - it doesn't exist, so it's certainly disabled now. */ + put_str_packet ("OK"); + } + break; + + default: + fprintf (stderr, "Warning: RSP matchpoint type %d not " + "recognized: ignored\n", type); + put_str_packet ("E01"); + return; + + } +} /* rsp_remove_matchpoint () */ + + +/*---------------------------------------------------------------------------*/ +/*!Handle a RSP insert breakpoint or matchpoint request + + For now only memory breakpoints are implemented, which are implemented by + substituting a breakpoint at the specified address. The implementation must + cope with the possibility of duplicate packets. + + @todo This doesn't work with icache/immu yet + + @param[in] buf The command received */ +/*---------------------------------------------------------------------------*/ +static void +rsp_insert_matchpoint (struct rsp_buf *buf) +{ + enum mp_type type; /* What sort of matchpoint */ + uint32_t addr; /* Address specified */ + int len; /* Matchpoint length (not used) */ + uint32_t instbuf[1]; + int hwp; /* Which hardware watchpoint we use */ + uint32_t regaddr; /* Used to set HW watchpoints */ + uint32_t regdata; /* ditto */ + + /* Break out the instruction */ + if (3 != sscanf (buf->data, "Z%1d,%x,%1d", (int *)&type, &addr, &len)) + { + fprintf (stderr, "Warning: RSP matchpoint insertion request not " + "recognized: ignored\n"); + put_str_packet ("E01"); + return; + } + + /* Sanity check that the length is 4 */ + if (4 != len) + { + fprintf (stderr, "Warning: RSP matchpoint insertion length %d not " + "valid: 4 assumed\n", len); + len = 4; + } + + /* Sort out the type of matchpoint */ + switch (type) + { + case BP_MEMORY: + /* Memory breakpoint - substitute a TRAP instruction */ + dbg_wb_read_block32(addr, instbuf, 1); // Get the old instruction. *** TODO Check return value + mp_hash_add (type, addr, instbuf[0]); + instbuf[0] = OR1K_TRAP_INSTR; // Set the TRAP instruction + dbg_wb_write_block32(addr, instbuf, 1); // *** TODO Check return value + put_str_packet ("OK"); + break; + + case BP_HARDWARE: + //fprintf(stderr, "Setting BP_HARDWARE breakpoint\n"); + hwp = hwp_get_available_watchpoint(); + //fprintf(stderr, "Got wp %i from HWP\n", hwp); + if(hwp == -1) /* No HWP available */ + { + fprintf(stderr, "Warning: no hardware watchpoints available to satisfy GDB request for hardware breakpoint"); + put_str_packet (""); + } + else + { + mp_hash_add(type, addr, hwp); /* Use the HWP number instead of the instruction data */ + //fprintf(stderr, "Added MP hash\n"); + /* Set DVR */ + regaddr = SPR_DVR(hwp); + dbg_cpu0_write(regaddr, addr); // *** TODO Check return value + /* Set DCR */ + regaddr = SPR_DCR(hwp); + regdata = 0x23; /* Compare to Instr fetch EA, unsigned, == */ + dbg_cpu0_write(regaddr, regdata); // *** TODO Check return value + /* Set enable bit in DMR2 */ + regaddr = SPR_DMR2; + dbg_cpu0_read(regaddr, ®data); // *** TODO Check return value + regdata |= (0x1 << hwp) << 12; /* Set the correct WGB bit */ + dbg_cpu0_write(regaddr, regdata); // *** TODO Check return value + /* Clear chain in DMR1 */ + regaddr = SPR_DMR1; + dbg_cpu0_read(regaddr, ®data); // *** TODO Check return value + regdata &= ~(0x3 << (2*hwp)); + dbg_cpu0_write(regaddr, regdata); // *** TODO Check return value + put_str_packet("OK"); + } + break; + + case WP_WRITE: + hwp = hwp_get_available_watchpoint(); + if(hwp == -1) /* No HWP available */ + { + fprintf(stderr, "Warning: no hardware watchpoints available to satisfy GDB request for write watchpoint"); + put_str_packet (""); + } + else + { + mp_hash_add(type, addr, hwp); /* Use the HWP number instead of the instruction data */ + /* Set DVR */ + regaddr = SPR_DVR(hwp); + dbg_cpu0_write(regaddr, addr); + /* Set DCR */ + regaddr = SPR_DCR(hwp); + regdata = 0x63; /* Compare to Store EA, unsigned, == */ + dbg_cpu0_write(regaddr, regdata); + /* Set enable bit in DMR2 */ + regaddr = SPR_DMR2; + dbg_cpu0_read(regaddr, ®data); + regdata |= (0x1 << hwp) << 12; /* Set the correct WGB bit */ + dbg_cpu0_write(regaddr, regdata); + /* Clear chain in DMR1 */ + regaddr = SPR_DMR1; + dbg_cpu0_read(regaddr, ®data); + regdata &= ~(0x3 << (2*hwp)); + dbg_cpu0_write(regaddr, regdata); + put_str_packet("OK"); + } + break; + + case WP_READ: + hwp = hwp_get_available_watchpoint(); + if(hwp == -1) /* No HWP available */ + { + fprintf(stderr, "Warning: no hardware watchpoints available to satisfy GDB request for read watchpoint"); + put_str_packet (""); + } + else + { + mp_hash_add(type, addr, hwp); /* Use the HWP number instead of the instruction data */ + /* Set DVR */ + regaddr = SPR_DVR(hwp); + dbg_cpu0_write(regaddr, addr); + /* Set DCR */ + regaddr = SPR_DCR(hwp); + regdata = 0x43; /* Compare to Load EA, unsigned, == */ + dbg_cpu0_write(regaddr, regdata); + /* Set enable bit in DMR2 */ + regaddr = SPR_DMR2; + dbg_cpu0_read(regaddr, ®data); + regdata |= (0x1 << hwp) << 12; /* Set the correct WGB bit */ + dbg_cpu0_write(regaddr, regdata); + /* Clear chain in DMR1 */ + regaddr = SPR_DMR1; + dbg_cpu0_read(regaddr, ®data); + regdata &= ~(0x3 << (2*hwp)); + dbg_cpu0_write(regaddr, regdata); + put_str_packet("OK"); + } + break; + + case WP_ACCESS: + hwp = hwp_get_available_watchpoint(); + if(hwp == -1) /* No HWP available */ + { + fprintf(stderr, "Warning: no hardware watchpoints available to satisfy GDB request for access watchpoint"); + put_str_packet (""); + } + else + { + mp_hash_add(type, addr, hwp); /* Use the HWP number instead of the instruction data */ + /* Set DVR */ + regaddr = SPR_DVR(hwp); + dbg_cpu0_write(regaddr, addr); + /* Set DCR */ + regaddr = SPR_DCR(hwp); + regdata = 0xC3; /* Compare to Load or Store EA, unsigned, == */ + dbg_cpu0_write(regaddr, regdata); + /* Set enable bit in DMR2 */ + regaddr = SPR_DMR2; + dbg_cpu0_read(regaddr, ®data); + regdata |= (0x1 << hwp) << 12; /* Set the correct WGB bit */ + dbg_cpu0_write(regaddr, regdata); + /* Clear chain in DMR1 */ + regaddr = SPR_DMR1; + dbg_cpu0_read(regaddr, ®data); + regdata &= ~(0x3 << (2*hwp)); + dbg_cpu0_write(regaddr, regdata); + put_str_packet("OK"); + } + break; + + default: + fprintf (stderr, "Warning: RSP matchpoint type %d not " + "recognized: ignored\n", type); + put_str_packet ("E01"); + break; + + } + +} /* rsp_insert_matchpoint () */ + + +// Additions from this point on were added solely to handle hardware, +// and did not come from simulator interface code. + +void set_stall_state(int stall) +{ + int ret; + + if(stall == 0) + { + use_cached_npc = 0; + } + + //fprintf(stderr, "RSP server sending stall command 0x%X\n", stall); + + // Actually start or stop the CPU hardware + if(stall) ret = write(pipe_fds[0], "S", 1); + else ret = write(pipe_fds[0], "U", 1); + + if(!ret) { + fprintf(stderr, "Warning: target monitor write() to pipe returned 0\n"); + } + else if(ret < 0) { + perror("Error in target monitor write to pipe"); + } + + return; +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_usbblaster.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_usbblaster.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_usbblaster.h (revision 66) @@ -0,0 +1,17 @@ + +#ifndef _CABLE_USBBLASTER_H_ +#define _CABLE_USBBLASTER_H_ + +#include +#include "cable_common.h" + +jtag_cable_t *cable_usbblaster_get_driver(void); +int cable_usbblaster_init(); +int cable_usbblaster_out(uint8_t value); +int cable_usbblaster_inout(uint8_t value, uint8_t *in_bit); +int cable_usbblaster_write_stream(uint32_t *stream, int len_bits, int set_last_bit); +int cable_usbblaster_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit); +int cable_usbblaster_opt(int c, char *str); +void cable_usbblaster_wait(); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_sim.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_sim.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_sim.h (revision 66) @@ -0,0 +1,23 @@ + +#ifndef _CABLE_SIM_H_ +#define _CABLE_SIM_H_ + +#include +#include "cable_common.h" + +jtag_cable_t *cable_rtl_get_driver(void); +int cable_rtl_sim_init(); +int cable_rtl_sim_out(uint8_t value); +int cable_rtl_sim_inout(uint8_t value, uint8_t *inval); +void cable_rtl_sim_wait(); +int cable_rtl_sim_opt(int c, char *str); + +jtag_cable_t *cable_vpi_get_driver(void); +int cable_vpi_init(); +int cable_vpi_out(uint8_t value); +int cable_vpi_inout(uint8_t value, uint8_t *inval); +void cable_vpi_wait(); +int cable_vpi_opt(int c, char *str); + + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_common.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_common.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_common.h (revision 66) @@ -0,0 +1,61 @@ + +#ifndef _CABLE_COMMON_H_ +#define _CABLE_COMMON_H_ + +#include + + +typedef struct { + const char *name; + int (*inout_func)(uint8_t, uint8_t *); + int (*out_func)(uint8_t); + int (*init_func)(); + int (*opt_func)(int, char *); + int (*bit_out_func)(uint8_t); + int (*bit_inout_func)(uint8_t, uint8_t *); + int (*stream_out_func)(uint32_t *, int, int); + int (*stream_inout_func)(uint32_t *, uint32_t *, int, int); + int (*flush_func)(); + const char *opts; + const char *help; +} jtag_cable_t; + +// Defines to use in the 'packet' args of cable_write_bit() +// and cable_read_write_bit(). Note that while TRST is +// active low for JTAG hardware, here the TRST bit +// should be set when you want the TRST wire active +// (JTAG TAP to be reset). +#define TRST (0x04) +#define TMS (0x02) +#define TDO (0x01) + +// These should only be used in the cable_* files. +#define TCLK_BIT (0x01) +#define TRST_BIT (0x02) +#define TDI_BIT (0x04) +#define TMS_BIT (0x08) +#define TDO_BIT (0x20) + +// Cable subsystem / init routines +void cable_setup(void); +int cable_select(const char *cable); +int cable_init(); +int cable_parse_opt(int c, char *str); +const char *cable_get_args(); +void cable_print_help(); + + +// Cable API routines +int cable_write_bit(uint8_t packet); +int cable_read_write_bit(uint8_t packet_out, uint8_t *bit_in); +int cable_write_stream(uint32_t *stream, int len_bits, int set_last_bit); +int cable_read_write_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit); +int cable_flush(void); + +// Common functions for lower-level drivers to use as desired +int cable_common_write_bit(uint8_t packet); +int cable_common_read_write_bit(uint8_t packet_out, uint8_t *bit_in); +int cable_common_write_stream(uint32_t *stream, int len_bits, int set_last_bit); +int cable_common_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.h (revision 66) @@ -0,0 +1,18 @@ + +#ifndef _CABLE_FT245_H_ +#define _CABLE_FT245_H_ + +#include +#include "cable_common.h" + + +jtag_cable_t *cable_ft245_get_driver(void); +int cable_ft245_init(); +int cable_ft245_out(uint8_t value); +int cable_ft245_inout(uint8_t value, uint8_t *in_bit); +int cable_ft245_write_stream(uint32_t *stream, int len_bits, int set_last_bit); +int cable_ft245_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit); +int cable_ft245_opt(int c, char *str); +void cable_ft245_wait(); + +#endif
tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft245.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/chain_commands.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/chain_commands.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/chain_commands.c (revision 66) @@ -0,0 +1,491 @@ +/* chain_commands.c -- JTAG protocol bridge between GDB and Advanced debug module. + Copyright(C) 2008 - 2010 Nathan Yawn, nyawn@opencores.net + based on code from jp2 by Marko Mlinar, markom@opencores.org + + This file contains functions which perform mid-level transactions + on a JTAG, such as setting a value in the TAP IR + or doing a burst write on the JTAG chain. + + 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 // for malloc() +#include // for usleep() +//#include // for mutexes + +#include "chain_commands.h" // For the return error codes +#include "altera_virtual_jtag.h" // hardware-specifg defines for the Altera Virtual JTAG interface +#include "cable_common.h" // low-level JTAG IO routines +#include "adv_dbg_commands.h" // for the kludge in tap_reset() +#include "errcodes.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +// How many tries before an abort +#define NUM_SOFT_RETRIES 0 + +// for the klugde in tap_reset() +extern int current_reg_idx[DBG_MAX_MODULES]; + +/* Currently selected scan chain in the debug unit - just to prevent unnecessary + transfers. */ +int current_chain = -1; +int desired_chain = -1; + +// wait for 100ms +#define JTAG_RETRY_WAIT() usleep(100000); + +// Retry data +int soft_retry_no = 0; +//static int hard_retry_no = 0; + +// Configuration data +int global_IR_size = 0; +int global_IR_prefix_bits = 0; +int global_IR_postfix_bits = 0; +int global_DR_prefix_bits = 0; +int global_DR_postfix_bits = 0; +unsigned int global_jtag_cmd_debug = 0; // Value to be shifted into the TAP IR to select the debug unit (unused for virtual jtag) +unsigned char global_altera_virtual_jtag = 0; // Set true to use virtual jtag mode +unsigned int vjtag_cmd_vir = ALTERA_CYCLONE_CMD_VIR; // virtual IR-shift command for altera devices, may be configured on command line +unsigned int vjtag_cmd_vdr = ALTERA_CYCLONE_CMD_VDR; // virtual DR-shift, ditto +unsigned char global_xilinx_bscan = 0; // Set true if the hardware uses a Xilinx BSCAN_* device. + + +/////////////////////////////////////////////////////////////////////// +// Configuration + +void config_set_IR_size(int size) { + global_IR_size = size; +} + +void config_set_IR_prefix_bits(int bits) { + global_IR_prefix_bits = bits; +} + +void config_set_IR_postfix_bits(int bits) { + global_IR_postfix_bits = bits; +} + +void config_set_DR_prefix_bits(int bits) { + global_DR_prefix_bits = bits; +} + +void config_set_DR_postfix_bits(int bits) { + global_DR_postfix_bits = bits; +} + +void config_set_debug_cmd(unsigned int cmd) { + global_jtag_cmd_debug = cmd; +} + +void config_set_alt_vjtag(unsigned char enable) { + global_altera_virtual_jtag = (enable) ? 1:0; +} + +// At present, all devices which support virtual JTAG use the same VIR/VDR +// commands. But, if they ever change, these can be changed on the command line. +void config_set_vjtag_cmd_vir(unsigned int cmd) { + vjtag_cmd_vir = cmd; +} + +void config_set_vjtag_cmd_vdr(unsigned int cmd) { + vjtag_cmd_vdr = cmd; +} + +void config_set_xilinx_bscan(unsigned char enable) { + global_xilinx_bscan = (enable) ? 1:0; +} + +////////////////////////////////////////////////////////////////////// +// Functions which operate on the JTAG TAP + + +/* Resets JTAG - Writes TRST=1, and TRST=0. Sends 8 TMS to put the TAP + * in test_logic_reset mode, for good measure. + */ +int tap_reset(void) { + int i; + int err = APP_ERR_NONE; + + debug("\nreset("); + err |= jtag_write_bit(0); + JTAG_RETRY_WAIT(); + /* In case we don't have TRST reset it manually */ + for(i = 0; i < 8; i++) err |= jtag_write_bit(TMS); + err |= jtag_write_bit(TRST); // if TRST not supported, this puts us in test logic/reset + JTAG_RETRY_WAIT(); + err |= jtag_write_bit(0); // run test / idle + debug(")\n"); + + // Reset data on current module/register selections + current_chain = -1; + + // (this is only for the adv. debug i/f...bit of a kludge) + for(i = 0; i < DBG_MAX_MODULES; i++) + current_reg_idx[i] = -1; + + return err; +} + + // Set the IR with the DEBUG command, one way or the other +int tap_enable_debug_module(void) +{ + uint32_t data; + int err = APP_ERR_NONE; + + if(global_altera_virtual_jtag) { + /* Set for virtual IR shift */ + err |= tap_set_ir(vjtag_cmd_vir); // This is the altera virtual IR scan command + err |= jtag_write_bit(TMS); /* SELECT_DR SCAN */ + err |= jtag_write_bit(0); /* CAPTURE_DR */ + err |= jtag_write_bit(0); /* SHIFT_DR */ + + /* Select debug scan chain in virtual IR */ + data = (0x1< 32) { // Deal with spill into the next word + ir_chain[startoffset+1] &= ir >> (32-startshift); + ir_chain[startoffset+1] |= (0xFFFFFFFF << (global_IR_size - (32-startshift))); // Put the 1's back in the MSB positions + } + + // Do the actual JTAG transaction + debug("Set IR 0x%X\n", ir); + err |= jtag_write_bit(TMS); /* SELECT_DR SCAN */ + err |= jtag_write_bit(TMS); /* SELECT_IR SCAN */ + + err |= jtag_write_bit(0); /* CAPTURE_IR */ + err |= jtag_write_bit(0); /* SHIFT_IR */ + + /* write data, EXIT1_IR */ + debug("Setting IR, size %i, IR_size = %i, pre_size = %i, post_size = %i, data 0x%X\n", chain_size, global_IR_size, global_IR_prefix_bits, global_IR_postfix_bits, ir); + err |= cable_write_stream(ir_chain, chain_size, 1); // Use cable_ call directly (not jtag_), so we don't add DR prefix bits + debug("Done setting IR\n"); + + err |= jtag_write_bit(TMS); /* UPDATE_IR */ + err |= jtag_write_bit(0); /* IDLE */ + current_chain = -1; + return err; +} + + +// This assumes we are in the IDLE state, and we want to be in the SHIFT_DR state. +int tap_set_shift_dr(void) +{ + int err = APP_ERR_NONE; + + err |= jtag_write_bit(TMS); /* SELECT_DR SCAN */ + err |= jtag_write_bit(0); /* CAPTURE_DR */ + err |= jtag_write_bit(0); /* SHIFT_DR */ + + return err; +} + +// This transitions from EXIT1 to IDLE. It should be the last thing called +// in any debug unit transaction. +int tap_exit_to_idle(void) +{ + int err = APP_ERR_NONE; + + err |= jtag_write_bit(TMS); /* UPDATE_DR */ + err |= jtag_write_bit(0); /* IDLE */ + + return err; +} + +//////////////////////////////////////////////////////////////////// +// Operations to read / write data over JTAG + + +/* Writes TCLK=0, TRST=1, TMS=bit1, TDI=bit0 + and TCLK=1, TRST=1, TMS=bit1, TDI=bit0 +*/ +int jtag_write_bit(uint8_t packet) { + debug("Wbit(%i)\n", packet); + return cable_write_bit(packet); +} + +int jtag_read_write_bit(uint8_t packet, uint8_t *in_bit) { + int retval = cable_read_write_bit(packet, in_bit); + debug("RWbit(%i,%i)", packet, *in_bit); + return retval; +} + +// This automatically adjusts for the DR length (other devices on scan chain) +// when the set_TMS flag is true. +int jtag_write_stream(uint32_t *out_data, int length_bits, unsigned char set_TMS) +{ + int i; + int err = APP_ERR_NONE; + + if(!set_TMS) + err |= cable_write_stream(out_data, length_bits, 0); + else if(global_DR_prefix_bits == 0) + err |= cable_write_stream(out_data, length_bits, 1); + else { + err |= cable_write_stream(out_data, length_bits, 0); + // It could be faster to do a cable_write_stream for all the prefix bits (if >= 8 bits), + // but we'd need a data array of unknown (and theoretically unlimited) + // size to hold the 0 bits to write. TODO: alloc/realloc one. + for(i = 0; i < (global_DR_prefix_bits-1); i++) + err |= jtag_write_bit(0); + err |= jtag_write_bit(TMS); + } + return err; +} + +// When set_TMS is true, this function insures the written data is in the desired position (past prefix bits) +// before sending TMS. When 'adjust' is true, this function insures that the data read in accounts for postfix +// bits (they are shifted through before the read starts). +int jtag_read_write_stream(uint32_t *out_data, uint32_t *in_data, int length_bits, unsigned char adjust, unsigned char set_TMS) +{ + int i; + int err = APP_ERR_NONE; + + if(adjust && (global_DR_postfix_bits > 0)) { + // It would be faster to do a cable_write_stream for all the postfix bits, + // but we'd need a data array of unknown (and theoretically unlimited) + // size to hold the '0' bits to write. + for(i = 0; i < global_DR_postfix_bits; i++) + err |= cable_write_bit(0); + } + + // If there are both prefix and postfix bits, we may shift more bits than strictly necessary. + // If we shifted out the data while burning through the postfix bits, these shifts could be subtracted + // from the number of prefix shifts. However, that way leads to madness. + if(!set_TMS) + err |= cable_read_write_stream(out_data, in_data, length_bits, 0); + else if(global_DR_prefix_bits == 0) + err |= cable_read_write_stream(out_data, in_data, length_bits, 1); + else { + err |= cable_read_write_stream(out_data, in_data, length_bits, 0); + // It would be faster to do a cable_write_stream for all the prefix bits, + // but we'd need a data array of unknown (and theoretically unlimited) + // size to hold the '0' bits to write. + for(i = 0; i < (global_DR_prefix_bits-1); i++) + err |= jtag_write_bit(0); + err |= jtag_write_bit(TMS); + } + return err; +} + + + +// This function attempts to determine the structure of the JTAG chain +// It can determine how many devices are present. +// If the devices support the IDCODE command, it will be read and stored. +// There is no way to automatically determine the length of the IR registers - +// this must be read from a BSDL file, if IDCODE is supported. +// When IDCODE is not supported, IR length of the target device must be entered on the command line. + +#define ALLOC_SIZE 64 +#define MAX_DEVICES 1024 +int jtag_enumerate_chain(uint32_t **id_array, int *num_devices) +{ + uint32_t invalid_code = 0x7f; // Shift this out, we know we're done when we get it back + const unsigned int done_code = 0x3f; // invalid_code is altered, we keep this for comparison (minus the start bit) + int devindex = 0; // which device we are currently trying to detect + uint32_t tempID; + uint32_t temp_manuf_code; + uint32_t temp_rest_code; + uint8_t start_bit = 0; + uint32_t *idcodes; + int reallocs = 0; + int err = APP_ERR_NONE; + + // Malloc a reasonable number of entries, we'll expand if we must. Linked lists are overrated. + idcodes = (uint32_t *) malloc(ALLOC_SIZE*sizeof(uint32_t)); + if(idcodes == NULL) { + printf("Failed to allocate memory for device ID codes!\n"); + return APP_ERR_MALLOC; + } + + // Put in SHIFT-DR mode + err |= jtag_write_bit(TMS); /* SELECT_DR SCAN */ + err |= jtag_write_bit(0); /* CAPTURE_DR */ + err |= jtag_write_bit(0); /* SHIFT_DR */ + + printf("Enumerating JTAG chain...\n"); + + // Putting a limit on the # of devices supported has the useful side effect + // of insuring we still exit in error cases (we never get the 0x7f manuf. id) + while(devindex < MAX_DEVICES) { + // get 1 bit. 0 = BYPASS, 1 = start of IDCODE + err |= jtag_read_write_bit(invalid_code&0x01, &start_bit); + invalid_code >>= 1; + + if(start_bit == 0) { + if(devindex >= (ALLOC_SIZE << reallocs)) { // Enlarge the memory array if necessary, double the size each time + idcodes = (uint32_t *) realloc(idcodes, (ALLOC_SIZE << ++reallocs)*sizeof(uint32_t)); + if(idcodes == NULL) { + printf("Failed to allocate memory for device ID codes during enumeration!\n"); + return APP_ERR_MALLOC; + } + } + idcodes[devindex] = -1; + devindex++; + } + else { + // get 11 bit manufacturer code + err |= jtag_read_write_stream(&invalid_code, &temp_manuf_code, 11, 0, 0); + invalid_code >>= 11; + + if(temp_manuf_code != done_code) { + // get 20 more bits, rest of ID + err |= jtag_read_write_stream(&invalid_code, &temp_rest_code, 20, 0, 0); + invalid_code >>= 20; + tempID = (temp_rest_code << 12) | (temp_manuf_code << 1) | 0x01; + if(devindex >= (ALLOC_SIZE << reallocs)) { // Enlarge the memory array if necessary, double the size each time + idcodes = (uint32_t *) realloc(idcodes, (ALLOC_SIZE << ++reallocs)*sizeof(unsigned long)); + if(idcodes == NULL) { + printf("Failed to allocate memory for device ID codes during enumeration!\n"); + return APP_ERR_MALLOC; + } + } + idcodes[devindex] = tempID; + devindex++; + } else { + break; + } + } + + if(err) // Don't try to keep probing if we get a comm. error + return err; + } + + if(devindex >= MAX_DEVICES) + printf("WARNING: maximum supported devices on JTAG chain (%i) exceeded.\n", MAX_DEVICES); + + // Put in IDLE mode + err |= jtag_write_bit(TMS); /* EXIT1_DR */ + err |= jtag_write_bit(TMS); /* UPDATE_DR */ + err |= jtag_write_bit(0); /* IDLE */ + + *id_array = idcodes; + *num_devices = devindex; + + return err; +} + + + +int jtag_get_idcode(uint32_t cmd, uint32_t *idcode) +{ + uint32_t data_out = 0; + int err = APP_ERR_NONE; + unsigned char saveconfig = global_altera_virtual_jtag; + global_altera_virtual_jtag = 0; // We want the actual IDCODE, not the virtual device IDCODE + + err |= tap_set_ir(cmd); + err |= tap_set_shift_dr(); + err |= jtag_read_write_stream(&data_out, idcode, 32, 1, 1); /* EXIT1_DR */ + + if(err) + printf("Error getting ID code!\n"); + + // Put in IDLE mode + err |= jtag_write_bit(TMS); /* UPDATE_DR */ + err |= jtag_write_bit(0); /* IDLE */ + + global_altera_virtual_jtag = saveconfig; + return err; +} + + +///////////////////////////////////////////////////////////////// +// Helper functions + +/* counts retries and returns zero if we should abort */ +/* TODO: dynamically adjust timings */ +int retry_do() { + int err = APP_ERR_NONE; + + if (soft_retry_no >= NUM_SOFT_RETRIES) { + return 0; + + // *** TODO: Add a 'hard retry', which re-initializes the cable, re-enumerates the bus, etc. + + } else { /* quick reset */ + if(err |= tap_reset()) { + printf("Error %s while resetting for retry.\n", get_err_string(err)); + return 0; + } + + // Put us back into DEBUG mode + if(err |= tap_enable_debug_module()) { + printf("Error %s enabling debug module during retry.\n", get_err_string(err)); + return 0; + } + + soft_retry_no++; + printf("Retry...\n"); + } + + return 1; +} + +/* resets retry counter */ +void retry_ok() { + soft_retry_no = 0; +} + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_dbg_commands.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_dbg_commands.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_dbg_commands.c (revision 66) @@ -0,0 +1,908 @@ +/* adv_dbg_commands.c -- JTAG protocol bridge between GDB and Advanced debug module. + Copyright (C) 2008-2010 Nathan Yawn, nyawn@opencores.net + + This file contains functions which perform high-level transactions + on a JTAG chain and debug unit, such as setting a value in the TAP IR + or doing a burst write through the wishbone module of the debug unit. + It uses the protocol for the Advanced Debug Interface (adv_dbg_if). + + 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 // for malloc() +#include // for exit() +#include // for memcpy() + +#include "chain_commands.h" +#include "adv_dbg_commands.h" // hardware-specific defines for the debug module +#include "cable_common.h" // low-level JTAG IO routines +#include "errcodes.h" +#include "utilities.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +// How many '0' status bits to get during a burst read +// before giving up +#define MAX_READ_STATUS_WAIT 100 + +// Currently selected internal register in each module +// - cuts down on unnecessary transfers +int current_reg_idx[DBG_MAX_MODULES]; + +// Scratchpad I/O buffers +static char *input_scratchpad = NULL; +static char *output_scratchpad = NULL; +static int input_scratchpad_size = 0; +static int output_scratchpad_size = 0; + +// Prototypes for local functions +uint32_t adbg_compute_crc(uint32_t crc_in, uint32_t data_in, int length_bits); + + + +//////////////////////////////////////////////////////////////////////// +// Helper functions + +uint32_t adbg_compute_crc(uint32_t crc_in, uint32_t data_in, int length_bits) +{ + int i; + unsigned int d, c; + uint32_t crc_out = crc_in; + + for(i = 0; i < length_bits; i = i+1) + { + d = ((data_in >> i) & 0x1) ? 0xffffffff : 0; + c = (crc_out & 0x1) ? 0xffffffff : 0; + crc_out = crc_out >> 1; + crc_out = crc_out ^ ((d ^ c) & ADBG_CRC_POLY); + } + return crc_out; +} + +////////////////////////////////////////////////////////////////// +// Functions which operate on the advanced debug unit + +/* Selects one of the modules in the debug unit (e.g. wishbone unit, CPU0, etc.) + */ +int adbg_select_module(int chain) +{ + uint32_t data; + int err = APP_ERR_NONE; + + if (current_chain == chain) + return err; + + current_chain = -1; + desired_chain = chain; + + // MSB of the data out must be set to 1, indicating a module select command + data = chain | (1<> 16) | ((opcode & 0xf) << 16)) & ~(0x1<<20); // MSB must be 0 to access modules + + err |= tap_set_shift_dr(); /* SHIFT_DR */ + + /* write data, EXIT1_DR */ + err |= jtag_write_stream(data, 53, 1); // When TMS is set (last parameter), DR length is also adjusted; EXIT1_DR + + err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE + + /* reset retry counter */ + retry_ok(); + + if(err) + printf("Error %s sending burst command to module %i\n", get_err_string(err), desired_chain); + + return err; +} + +// Set up and execute a burst read from a contiguous block of addresses. +// Note that there is a minor weakness in the CRC algorithm in case of retries: +// the CRC is only checked for the final burst read. Thus, if errors/partial retries +// break up a transfer into multiple bursts, only the last burst will be CRC protected. +#define MAX_BUS_ERRORS 10 +int adbg_wb_burst_read(int word_size_bytes, int word_count, unsigned long start_address, void *data) +{ + unsigned char opcode; + uint8_t status; + unsigned long instream; + int i, j; + uint32_t crc_calc; + uint32_t crc_read; + unsigned char word_size_bits; + uint32_t out_data = 0; + uint32_t in_data = 0; + unsigned long addr; + uint32_t err_data[2]; + int bus_error_retries = 0; + int err = APP_ERR_NONE; + + // Silence GCC + (void)in_data; + (void)out_data; + + debug("Doing burst read, word size %d, word count %d, start address 0x%lX\n", word_size_bytes, word_count, start_address); + + if(word_count <= 0) { + debug("Ignoring illegal read burst length (%d)\n", word_count); + return 0; + } + + instream = 0; + word_size_bits = word_size_bytes << 3; + + // Select the appropriate opcode + switch(current_chain) { + case DC_WISHBONE: + if (word_size_bytes == 1) opcode = DBG_WB_CMD_BREAD8; + else if(word_size_bytes == 2) opcode = DBG_WB_CMD_BREAD16; + else if(word_size_bytes == 4) opcode = DBG_WB_CMD_BREAD32; + else { + printf("Tried burst read with invalid word size (%0x), defaulting to 4-byte words\n", word_size_bytes); + opcode = DBG_WB_CMD_BREAD32; + } + break; + case DC_CPU0: + if(word_size_bytes == 4) opcode = DBG_CPU0_CMD_BREAD32; + else { + printf("Tried burst read with invalid word size (%0x), defaulting to 4-byte words\n", word_size_bytes); + opcode = DBG_CPU0_CMD_BREAD32; + } + break; + case DC_CPU1: + if(word_size_bytes == 4) opcode = DBG_CPU1_CMD_BREAD32; + else { + printf("Tried burst read with invalid word size (%0x), defaulting to 4-byte words\n", word_size_bytes); + opcode = DBG_CPU0_CMD_BREAD32; + } + break; + default: + printf("ERROR! Illegal debug chain selected while doing burst read!\n"); + return 1; + } + + wb_burst_read_retry_full: + i = 0; + addr = start_address; + wb_burst_read_retry_partial: + crc_calc = 0xffffffff; + + + // Send the BURST READ command, returns TAP to idle state + if(err |= adbg_burst_command(opcode, addr, (word_count-i))) // word_count-i in case of partial retry + return err; + + // This is a kludge to work around oddities in the Xilinx BSCAN_* devices, and the + // adv_dbg_if state machine. The debug FSM needs 1 TCK between UPDATE_DR above, and + // the CAPTURE_DR below, and the BSCAN_* won't provide it. So, we force it, by putting the TAP + // in BYPASS, which makes the debug_select line inactive, which is AND'ed with the TCK line (in the xilinx_internal_jtag module), + // which forces it low. Then we re-enable USER1/debug_select to make TCK high. One TCK + // event, the hard way. + if(global_xilinx_bscan) { + err |= tap_set_ir(0xFFFFFFFF); + err |= tap_enable_debug_module(); + } + + // Get us back to shift_dr mode to read a burst + err |= tap_set_shift_dr(); + + // We do not adjust for the DR length here. BYPASS regs are loaded with 0, + // and the debug unit waits for a '1' status bit before beginning to read data. + +#ifdef ADBG_OPT_HISPEED + // Get 1 status bit, then word_size_bytes*8 bits + status = 0; + j = 0; + while(!status) { // Status indicates whether there is a word available to read. Wait until it returns true. + err |= jtag_read_write_bit(0, &status); + j++; + // If max count exceeded, retry + if(j > MAX_READ_STATUS_WAIT) { + printf("Burst read timed out.\n"); + if(!retry_do()) { + printf("Retry count exceeded in burst read!\n"); + return err|APP_ERR_MAX_RETRY; + } + err = APP_ERR_NONE; // on retry, errors cleared + goto wb_burst_read_retry_full; + } + } + + // Check we have enough space for the (zero) output data + int total_size_bytes = (word_count*word_size_bytes)+4; + err |= check_buffer_size(&input_scratchpad, &input_scratchpad_size, total_size_bytes); + err |= check_buffer_size(&output_scratchpad, &output_scratchpad_size, total_size_bytes); + if(err != APP_ERR_NONE) return err; + memset(output_scratchpad, 0, total_size_bytes); + + // Get the data in one shot, including the CRC. This requires two memcpy(), which take time, + // but it's still faster than an added USB transaction (assuming a USB cable). + err |= jtag_read_write_stream((uint32_t *)output_scratchpad, (uint32_t *)input_scratchpad, (total_size_bytes*8), 0, 1); + memcpy(data, input_scratchpad, (word_count*word_size_bytes)); + memcpy(&crc_read, &input_scratchpad[(word_count*word_size_bytes)], 4); + for(i = 0; i < (word_count*word_size_bytes); i++) + { + crc_calc = adbg_compute_crc(crc_calc, ((uint8_t *)data)[i], 8); + } + +#else + + // Repeat for each word: wait until ready = 1, then read word_size_bits bits. + for(; i < word_count; i++) + { + // Get 1 status bit, then word_size_bytes*8 bits + status = 0; + j = 0; + while(!status) { // Status indicates whether there is a word available to read. Wait until it returns true. + err |= jtag_read_write_bit(0, &status); + j++; + // If max count exceeded, retry starting with the failure address + if(j > MAX_READ_STATUS_WAIT) { + printf("Burst read timed out.\n"); + if(!retry_do()) { + printf("Retry count exceeded in burst read!\n"); + return err|APP_ERR_MAX_RETRY; + } + err = APP_ERR_NONE; // on retry, errors cleared + addr = start_address + (i*word_size_bytes); + goto wb_burst_read_retry_partial; + } + } + + if(j > 1) { // It's actually normal for the first read of a burst to take 2 tries, even with a fast WB clock - 3 with a Xilinx BSCAN + debug("Took %0d tries before good status bit during burst read", j); + } + + // Get one word of data + err |= jtag_read_write_stream(&out_data, &in_data, word_size_bits, 0, 0); + debug("Read 0x%0lx", in_data); + + if(err) { // Break and retry as soon as possible on error + printf("Error %s during burst read.\n", get_err_string(err)); + if(!retry_do()) { + printf("Retry count exceeded in burst read!\n"); + return err|APP_ERR_MAX_RETRY; + } + err = APP_ERR_NONE; // on retry, errors cleared + addr = start_address + (i*word_size_bytes); + goto wb_burst_read_retry_partial; + } + + crc_calc = adbg_compute_crc(crc_calc, in_data, word_size_bits); + + if(word_size_bytes == 1) ((unsigned char *)data)[i] = in_data & 0xFF; + else if(word_size_bytes == 2) ((unsigned short *)data)[i] = in_data & 0xFFFF; + else ((unsigned long *)data)[i] = in_data; + } + + // All bus data was read. Read the data CRC from the debug module. + err |= jtag_read_write_stream(&out_data, &crc_read, 32, 0, 1); + +#endif + + err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE + + if(crc_calc != crc_read) { + printf("CRC ERROR! Computed 0x%x, read CRC 0x%x\n", crc_calc, crc_read); + if(!retry_do()) { + printf("Retry count exceeded! Abort!\n\n"); + return err|APP_ERR_CRC; + } + goto wb_burst_read_retry_full; + } + else debug("CRC OK!\n"); + + + // Now, read the error register, and retry/recompute as necessary. + if(current_chain == DC_WISHBONE) + { + err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 1); // First, just get 1 bit...read address only if necessary, + if(err_data[0] & 0x1) { // Then we have a problem. + err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 33); + addr = (err_data[0] >> 1) | (err_data[1] << 31); + i = (addr - start_address) / word_size_bytes; + printf("ERROR! WB bus error during burst read, address 0x%lX (index 0x%X), retrying!\n", addr, i); + bus_error_retries++; + if(bus_error_retries > MAX_BUS_ERRORS) { + printf("Max WB bus errors reached during burst read\n"); + return err|APP_ERR_MAX_BUS_ERR; + } + // Don't call retry_do(), a JTAG reset won't help a WB bus error + err_data[0] = 1; + err |= adbg_ctrl_write(DBG_WB_REG_ERROR, err_data, 1); // Write 1 bit, to reset the error register, + goto wb_burst_read_retry_partial; + } + } + + retry_ok(); + return err; +} + +// Set up and execute a burst write to a contiguous set of addresses +int adbg_wb_burst_write(void *data, int word_size_bytes, int word_count, unsigned long start_address) +{ + unsigned char opcode; + uint32_t datawords[2] = {0,0}; + int i; + uint32_t crc_calc; + uint32_t crc_match; + unsigned int word_size_bits; + unsigned long addr; + int bus_error_retries = 0; + uint32_t err_data[2]; + int loopct, successes; +#ifndef ADBG_OPT_HISPEED + uint8_t status; + uint32_t statuswords[2] = {0,0}; + int first_status_loop = 1; +#endif + int err = APP_ERR_NONE; + + debug("Doing burst write, word size %d, word count %d, start address 0x%lx\n", word_size_bytes, word_count, start_address); + word_size_bits = word_size_bytes << 3; + + if(word_count <= 0) { + printf("Ignoring illegal burst write size (%d)\n", word_count); + return 0; + } + + // Select the appropriate opcode + switch(current_chain) { + case DC_WISHBONE: + if (word_size_bytes == 1) opcode = DBG_WB_CMD_BWRITE8; + else if(word_size_bytes == 2) opcode = DBG_WB_CMD_BWRITE16; + else if(word_size_bytes == 4) opcode = DBG_WB_CMD_BWRITE32; + else { + printf("Tried WB burst write with invalid word size (%0x), defaulting to 4-byte words", word_size_bytes); + opcode = DBG_WB_CMD_BWRITE32; + } + break; + case DC_CPU0: + if(word_size_bytes == 4) opcode = DBG_CPU0_CMD_BWRITE32; + else { + printf("Tried CPU0 burst write with invalid word size (%0x), defaulting to 4-byte words", word_size_bytes); + opcode = DBG_CPU0_CMD_BWRITE32; + } + break; + case DC_CPU1: + if(word_size_bytes == 4) opcode = DBG_CPU1_CMD_BWRITE32; + else { + printf("Tried CPU1 burst write with invalid word size (%0X), defaulting to 4-byte words", word_size_bytes); + opcode = DBG_CPU0_CMD_BWRITE32; + } + break; + default: + printf("ERROR! Illegal debug chain selected while doing burst WRITE!\n"); + return 1; + } + +#ifndef ADBG_OPT_HISPEED + // Compute which loop iteration in which to expect the first status bit + first_status_loop = 1 + ((global_DR_prefix_bits + global_DR_postfix_bits)/(word_size_bits+1)); +#endif + + wb_burst_write_retry_full: + i = 0; + addr = start_address; + wb_burst_write_retry_partial: + crc_calc = 0xffffffff; + successes = 0; + + + // Send burst command, return to idle state + if(err |= adbg_burst_command(opcode, addr, (word_count-i))) // word_count-i in case of partial retry + return err; + + // Get us back to shift_dr mode to write a burst + err |= tap_set_shift_dr(); + + // Write a start bit (a 1) so it knows when to start counting + err |= jtag_write_bit(TDO); + +#ifdef ADBG_OPT_HISPEED + // If compiled for "hi-speed" mode, we don't read a status bit after every + // word written. This saves a lot of complication! + // We send the CRC at the same time, so we have to compute it first. + for(loopct = 0; loopct < word_count; loopct++) { + if(word_size_bytes == 4) datawords[0] = ((unsigned long *)data)[loopct]; + else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[loopct]; + else datawords[0] = ((unsigned char *)data)[loopct]; + crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits); + } + + int total_size_bytes = (word_count * word_size_bytes) + 4; + err |= check_buffer_size(&output_scratchpad, &output_scratchpad_size, total_size_bytes); + if(err != APP_ERR_NONE) return err; + + memcpy(output_scratchpad, data, (word_count * word_size_bytes)); + memcpy(&output_scratchpad[(word_count*word_size_bytes)], &crc_calc, 4); + + err |= jtag_write_stream((uint32_t *) output_scratchpad, total_size_bytes*8, 0); // Write data + +#else + + // Or, repeat... + for(loopct = 0; i < word_count; i++,loopct++) // loopct only used to check status... + { + // Write word_size_bytes*8 bits, then get 1 status bit + if(word_size_bytes == 4) datawords[0] = ((unsigned long *)data)[i]; + else if(word_size_bytes == 2) datawords[0] = ((unsigned short *)data)[i]; + else datawords[0] = ((unsigned char *)data)[i]; + + crc_calc = adbg_compute_crc(crc_calc, datawords[0], word_size_bits); + + // This is an optimization + if((global_DR_prefix_bits + global_DR_postfix_bits) == 0) { + //#endif + err |= jtag_write_stream(datawords, word_size_bits, 0); // Write data + //#ifndef ADBG_OPT_HISPEED + err |= jtag_read_write_bit(0, &status); // Read status bit + if(!status) { + addr = start_address + (i*word_size_bytes); + printf("Write before bus ready, retrying (idx %i, addr 0x%08lX).\n", i, addr); + if(!retry_do()) { printf("Retry count exceeded! Abort!\n\n"); exit(1);} + // Don't bother going to TAP idle state, we're about to reset the TAP + goto wb_burst_write_retry_partial; + } + } + else { // This is slower (for a USB cable anyway), because a read takes 1 more USB transaction than a write. + err |= jtag_read_write_stream(datawords, statuswords, word_size_bits+1, 0, 0); + debug("St. 0x%08lX 0x%08lX\n", statuswords[0], statuswords[1]); + status = (statuswords[0] || statuswords[1]); + if(loopct > first_status_loop) { + if(status) successes++; + else { + i = successes; + addr = start_address + (i*word_size_bytes); + printf("Write before bus ready, retrying (idx %i, addr 0x%08lX).\n", i, addr); + if(!retry_do()) { printf("Retry count exceeded! Abort!\n\n"); exit(1);} + // Don't bother going to TAP idle state, we're about to reset the TAP + goto wb_burst_write_retry_partial; + } + } + } + + if(err) { + printf("Error %s during burst write, retrying.\n", get_err_string(err)); + if(!retry_do()) { + printf("Retry count exceeded!\n"); + return err|APP_ERR_MAX_RETRY; + } + err = APP_ERR_NONE; + addr = start_address + (i*word_size_bytes); + // Don't bother going to TAP idle state, we're about to reset the TAP + goto wb_burst_write_retry_partial; + } + + debug("Wrote 0x%0lx", datawords[0]); + } + + // *** If this is a multi-device chain (and we're not in hi-speed mode), at least one status bit will be lost. + // *** If we want to check for it, we'd have to look while sending the CRC, and + // *** maybe while burning bits to get the match bit. So, for now, there is a + // *** hole here. + + // Done sending data, Send the CRC we computed + err |= jtag_write_stream(&crc_calc, 32, 0); + +#endif + + for(i = 0; i < global_DR_prefix_bits; i++) // Push the CRC data all the way to the debug unit + err |= jtag_write_bit(0); // Can't do this with a stream command without setting TMS on the last bit + + // Read the 'CRC match' bit, and go to exit1_dr + // May need to adjust for other devices in chain! + datawords[0] = 0; + err |= jtag_read_write_stream(datawords, &crc_match, 1, 1, 0); // set 'adjust' to pull match bit all the way in + // But don't set TMS above, that would shift prefix bits (again), wasting time. + err |= jtag_write_bit(TMS); // exit1_dr + err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE + + if(!crc_match) { + printf("CRC ERROR! match bit after write is %i (computed CRC 0x%x)", crc_match, crc_calc); + if(!retry_do()) { printf("Retry count exceeded! Abort!\n\n"); exit(1);} + goto wb_burst_write_retry_full; + } + else debug("CRC OK!\n"); + + + // Now, read the error register and retry/recompute as needed + if (current_chain == DC_WISHBONE) + { + err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 1); // First, just get 1 bit...read address only if necessary + if(err_data[0] & 0x1) { // Then we have a problem. + err |= adbg_ctrl_read(DBG_WB_REG_ERROR, err_data, 33); + addr = (err_data[0] >> 1) | (err_data[1] << 31); + i = (addr - start_address) / word_size_bytes; + printf("ERROR! WB bus error during burst write, address 0x%lX (index 0x%X), retrying!\n", addr, i); + bus_error_retries++; + if(bus_error_retries > MAX_BUS_ERRORS) { + printf("Max WB bus errors reached!\n"); + return err|APP_ERR_MAX_BUS_ERR; + } + // Don't call retry_do(), a JTAG reset won't help a WB bus error + err |= adbg_ctrl_write(DBG_WB_REG_ERROR, err_data, 1); // Write 1 bit, to reset the error register. + goto wb_burst_write_retry_partial; + } + } + + retry_ok(); + return err; +} + +/*--------------------------------------------------------------------------------------------*/ + +// This does a simultaneous read/write to the JTAG serial port. It will send/receive at most 8 bytes, +// so data_received must be at least 8 bytes long. It is not guaranteed that all data (or any data) +// will be sent. On return, bytes_to_send will be set to the number of bytes actually senet. + +int adbg_jsp_transact(unsigned int *bytes_to_send, const char *data_to_send, unsigned int *bytes_received, char *data_received) +{ + int err = APP_ERR_NONE; + unsigned int xmitsize; + char outdata[10]; // These must 10 bytes: 1 for counts, 8 for data, and 1 (possible) start and end bits + char indata[10]; + unsigned char stopbit = 0, startbit = 0, wrapbit; + int bytes_free; + int i; + + if(*bytes_to_send > 8) + xmitsize = 8; + else + xmitsize = *bytes_to_send; + + if(err |= adbg_select_module(desired_chain)) + return err; + + // Put us in shift_dr mode + err |= tap_set_shift_dr(); + + // There are two independant compile-time options here, making four different ways to do this transaction. + // If OPTIMIZE_FOR_USB is not defined, then one byte will be transacted to get the 'bytes available' and + // 'bytes free' counts, then the minimum number of bytes will be transacted to get all available bytes + // and put as many bytes as possible. If OPTIMIZE_FOR_USB is defined, then 9 bytes will always be transacted, + // the JSP will ignore extras, and user code will have to check to see how many bytes were written. + // + // if ENABLE_JSP_MULTI is enabled, then a '1' bit will be pre-pended to the data being sent (before the 'count' + // byte). This is for compatibility with multi-device JTAG chains. + +#ifdef OPTIMIZE_JSP_FOR_USB + + // Simplest case: do everything in 1 burst transaction + memset(outdata, 0, 10); // Clear to act as 'stopbits'. [8] may be overwritten in the following memcpy(). + + #ifdef ENABLE_JSP_MULTI + + startbit = 1; + wrapbit = (xmitsize >> 3) & 0x1; + outdata[0] = (xmitsize << 5) | 0x1; // set the start bit + + for(i = 0; i < xmitsize; i++) // don't copy off the end of the input array + { + outdata[i+1] = (data_to_send[i] << 1) | wrapbit; + wrapbit = (data_to_send[i] >> 7) & 0x1; + } + + if(i < 8) + outdata[i+1] = wrapbit; + else + outdata[9] = wrapbit; + + // If the last data bit is a '1', then we need to append a '0' so the top-level module + // won't treat the burst as a 'module select' command. + if(outdata[9] & 0x01) stopbit = 1; + else stopbit = 0; + + #else + + startbit = 0; + outdata[0] = 0x0 | (xmitsize << 4); // First byte out has write count in upper nibble + if (xmitsize > 0) memcpy(&outdata[1], data_to_send, xmitsize); + + // If the last data bit is a '1', then we need to append a '0' so the top-level module + // won't treat the burst as a 'module select' command. + if(outdata[8] & 0x80) stopbit = 1; + else stopbit = 0; + + #endif + + debug("jsp doing 9 bytes, xmitsize %i\n", xmitsize); + + // 72 bits: 9 bytes * 8 bits + err |= jtag_read_write_stream((uint32_t *) outdata, (uint32_t *) indata, 72+startbit+stopbit, 1, 1); + + debug("jsp got remote sizes 0x%X\n", indata[0]); + + *bytes_received = (indata[0] >> 4) & 0xF; // bytes available is in the upper nibble + memcpy(data_received, &indata[1], *bytes_received); + + bytes_free = indata[0] & 0x0F; + *bytes_to_send = (bytes_free < xmitsize) ? bytes_free : xmitsize; + +#else // !OPTIMIZE_JSP_FOR_USB + + #ifdef ENABLE_JSP_MULTI + indata[0] = indata[1] = 0; + outdata[1] = (xmitsize >> 3) & 0x1; + outdata[0] = (xmitsize << 5) | 0x1; // set the start bit + startbit = 1; + + #else + outdata[0] = 0x0 | (xmitsize << 4); // First byte out has write count in upper nibble + startbit = 0; + #endif + + err |= jtag_read_write_stream((uint32_t *) outdata, (uint32_t *) indata, 8+startbit, 1, 0); + + wrapbit = indata[1] & 0x1; // only used if ENABLE_JSP_MULTI is defined + bytes_free = indata[0] & 0x0F; + *bytes_received = (indata[0] >> 4) & 0xF; // bytes available is in the upper nibble + + // Number of bytes to transact is max(bytes_available, min(bytes_to_send,bytes_free)) + if(bytes_free < xmitsize) xmitsize = bytes_free; + if((*bytes_received) > xmitsize) xmitsize = *bytes_received; + + memset(outdata, 0, 10); + memcpy(outdata, data_to_send, xmitsize); // use larger array in case we need to send stopbit + + // If the last data bit is a '1', then we need to append a '0' so the top-level module + // won't treat the burst as a 'module select' command. + if(xmitsize && (outdata[xmitsize - 1] & 0x80)) stopbit = 2; + else stopbit = 1; + + err |= jtag_read_write_stream((uint32_t *) outdata, (uint32_t *) indata, (xmitsize*8)+stopbit, 0, 1); + + #ifdef ENABLE_JSP_MULTI + + for(i = 0; i < (*bytes_received); i++) + { + data_received[i] = (indata[i] << 1) | wrapbit; + wrapbit = (indata[i] >> 7) & 0x1; + } + #else + memcpy(data_received, indata, xmitsize); + #endif + + if(bytes_free < *bytes_to_send) *bytes_to_send = bytes_free; + +#endif // !OPTIMIZE_JSP_FOR_USB + + err |= tap_exit_to_idle(); // Go from EXIT1 to IDLE + + return err; +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft2232.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft2232.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/cable_ft2232.h (revision 66) @@ -0,0 +1,86 @@ + +#ifndef _CABLE_FT2232_H_ +#define _CABLE_FT2232_H_ + +#include "cable_common.h" + +#ifndef min +#define min(X,Y) ((X) < (Y) ? (X) : (Y)) +#endif + +#define FTDX_MAXSEND 4096 +#define FTDX_MAXSEND_MPSSE (64 * 1024) +#define FTDI_MAXRECV ( 4 * 64) + +#define BIT_CABLEID2_TCK 0 /* ADBUS0 */ +#define BIT_CABLEID2_TDIDO 1 /* ADBUS1 */ +#define BIT_CABLEID2_TDODI 2 /* ADBUS2 */ +#define BIT_CABLEID2_TMS 3 /* ADBUS3 */ +#define BITMASK_CABLEID2_TCK (1 << BIT_CABLEID2_TCK) +#define BITMASK_CABLEID2_TDIDO (1 << BIT_CABLEID2_TDIDO) +#define BITMASK_CABLEID2_TDODI (1 << BIT_CABLEID2_TDODI) +#define BITMASK_CABLEID2_TMS (1 << BIT_CABLEID2_TMS) + +#define BIT_CABLEID2_OE 1 /* ACBUS1 */ +#define BIT_CABLEID2_RXLED 2 /* ACBUS2 */ +#define BIT_CABLEID2_TXLED 3 /* ACBUS3 */ +#define BITMASK_CABLEID2_OE (1 << BIT_CABLEID2_OE) +#define BITMASK_CABLEID2_RXLED (1 << BIT_CABLEID2_RXLED) +#define BITMASK_CABLEID2_TXLED (1 << BIT_CABLEID2_TXLED) + +typedef struct usbconn_t usbconn_t; + +typedef struct { + char *name; + char *desc; + char *driver; + int32_t vid; + int32_t pid; +} usbconn_cable_t; + +typedef struct { + const char *type; + usbconn_t *(*connect)( const char **, int, usbconn_cable_t *); + void (*free)( usbconn_t * ); + int (*open)( usbconn_t * ); + int (*close)( usbconn_t * ); + int (*read)( usbconn_t *, uint8_t *, int ); + int (*write)( usbconn_t *, uint8_t *, int, int ); +} usbconn_driver_t; + +struct usbconn_t { + usbconn_driver_t *driver; + void *params; + usbconn_cable_t *cable; +}; + +typedef struct { + /* USB device information */ + unsigned int vid; + unsigned int pid; + struct ftdi_context *ftdic; + char *serial; + /* send and receive buffer handling */ + uint32_t send_buf_len; + uint32_t send_buffered; + uint8_t *send_buf; + uint32_t recv_buf_len; + uint32_t to_recv; + uint32_t recv_write_idx; + uint32_t recv_read_idx; + uint8_t *recv_buf; +} ftdi_param_t; + +jtag_cable_t *cable_ftdi_get_driver(void); +int cable_ftdi_init(); +int cable_ftdi_write_bit(uint8_t packet); +int cable_ftdi_read_write_bit(uint8_t packet_out, uint8_t *bit_in); +int cable_ftdi_write_stream(uint32_t *stream, int len_bits, int set_last_bit); +int cable_ftdi_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit); +int cable_ftdi_opt(int c, char *str); +int cable_ftdi_flush(); +int cable_ftdi_close(); + +#endif + + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/jsp_server.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/jsp_server.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/jsp_server.c (revision 66) @@ -0,0 +1,567 @@ +/* jsp_server.c -- Server for the JTAG serial port + Copyright(C) 2010 Nathan Yawn + + This file is part the advanced debug unit / bridge. It acts as a + telnet server, to send and receive data for the JTAG Serial Port + (JSP) + + 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 "dbg_api.h" +#include "hardware_monitor.h" +#include "errcodes.h" + + +#define debug(...) // fprintf(stderr, __VA_ARGS__ ) + +int jsp_server_fd = -1; +int jsp_client_fd = -1; +int jsp_pipe_fds[2]; + +/* Some convenient net address info to have around */ +char jsp_ipstr[INET6_ADDRSTRLEN]; +char *jsp_ipver; +int jsp_portnum; +char jsp_hostname[256]; + +/* Buffers for network data. Simple, static char arrays. */ +#define JSP_BUFFER_SIZE 256 +char jsp_tohw_buf[JSP_BUFFER_SIZE]; +int jsp_tohw_rd_idx = 0; +int jsp_tohw_wr_idx = 0; +int jsp_tohw_count = 0; + +char jsp_fromhw_buf[JSP_BUFFER_SIZE]; +int jsp_fromhw_rd_idx = 0; +int jsp_fromhw_wr_idx = 0; +int jsp_fromhw_count = 0; + +/* Other local data */ +int jsp_server_running = 0; +int jsp_target_is_running = 0; + +pthread_t jsp_server_thread; +void *jsp_server(void *arg); + +void jsp_server_close(void); +void jsp_client_close(void); + +void jsp_print_welcome(int fd); +void jsp_queue_data_from_client(int fd); +void jsp_send_data_to_client(int fd); +void jsp_hardware_transact(void); +void jsp_send_all(int fd, char *buf, int len); + +/*----------------------------------------------------------*/ +/* Public API */ +/*----------------------------------------------------------*/ + +void jsp_init(int portNum) +{ + int status; + struct addrinfo hints; + struct addrinfo *servinfo; // will point to the results of getaddrinfo + int optval; /* Socket options */ + char portnum[6]; /* portNum as a string */ + void *addr; + + debug("JSP Server initializing\n"); + + jsp_server_fd = -1; + jsp_client_fd = -1; + jsp_portnum = portNum; + + memset(portnum, '\0', sizeof(portnum)); + snprintf(portnum, 5, "%i", portNum); + + /* Get the address info for the local host */ + memset(&hints, 0, sizeof hints); // make sure the struct is empty + hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; // TCP stream sockets + hints.ai_flags = AI_PASSIVE; // fill in my IP for me + + if ((status = getaddrinfo(NULL, portnum, &hints, &servinfo)) != 0) { + fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); + return; + } + + + /* *** TODO: Select the appropriate servinfo in the linked list + * For now, we just use the first entry in servinfo. + struct addrinfo *servinfo, *p; + for(p = servinfo;p != NULL; p = p->ai_next) { + if (p->ai_family == AF_INET) { // IPv4 + } else { // IPv6 + } + } + */ + + + /* Save the IP address, for convenience (different fields in IPv4 and IPv6) */ + if (servinfo->ai_family == AF_INET) { // IPv4 + struct sockaddr_in *ipv4 = (struct sockaddr_in *)servinfo->ai_addr; + addr = &(ipv4->sin_addr); + jsp_ipver = "IPv4"; + } else { // IPv6 + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr; + addr = &(ipv6->sin6_addr); + jsp_ipver = "IPv6"; + } + + /* convert the IP to a string */ + inet_ntop(servinfo->ai_family, addr, jsp_ipstr, sizeof(jsp_ipstr)); + + /* Find out what our name is, save for convenience */ + if (gethostname (jsp_hostname, sizeof(jsp_hostname)) < 0) + { + fprintf (stderr, "Warning: Unable to get hostname for JSP server: %s\n", strerror(errno)); + jsp_hostname[0] = '\0'; /* This is not a fatal error. */ + } + + /* Create the socket */ + jsp_server_fd = socket (servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); + if (jsp_server_fd < 0) + { + fprintf (stderr, "Error: JSP could not create server socket: %s\n", strerror(errno)); + return; + } + + /* Set this socket to reuse its address. */ + optval = 1; + if (setsockopt(jsp_server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval)) == -1) + { + fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: %s\n", jsp_server_fd, strerror(errno)); + jsp_server_close(); + return; + } + + /* Bind the socket to the local address */ + if (bind (jsp_server_fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) + { + fprintf (stderr, "Error: Unable to bind JSP server socket %d to port %d: %s\n", jsp_server_fd, portNum, strerror(errno)); + jsp_server_close(); + return; + } + + /* Set us up as a server, with a maximum backlog of 1 connection */ + if (listen (jsp_server_fd, 1) < 0) + { + fprintf (stderr, "Warning: Unable to set JSP backlog on server socket %d to %d: %s\n", jsp_server_fd, 1, strerror(errno)); + jsp_server_close(); + return; + } + + fprintf(stderr, "JSP server listening on host %s (%s), port %i, address family %s\n", + jsp_hostname, jsp_ipstr, jsp_portnum, jsp_ipver); + + /* Register for stall/unstall events from the target monitor thread. Also creates pipe + * for sending stall/unstall command to the target monitor, unused by us. */ + if(0 > register_with_monitor_thread(jsp_pipe_fds)) { // pipe_fds[0] is for writing to monitor, [1] is to read from it + fprintf(stderr, "JSP server failed to register with monitor thread, exiting"); + jsp_server_close(); + return; + } + +} + + +int jsp_server_start(void) +{ + + jsp_server_running = 1; + + debug("Starting JSP server\n"); + + // Create the JSP server thread + if(pthread_create(&jsp_server_thread, NULL, jsp_server, NULL)) + { + fprintf(stderr, "Failed to create JSP server thread!\n"); + return 0; + } + + return 1; +} + + +int jsp_server_stop(void) +{ + /*** NOTE: Since we currently don't use select() in front of the accept() + *** in the server thread, this won't actually work unless/until a client + *** is connected. Otherwise, the server thread will be blocked on the + *** accept() (though closing the server socket may break it out.) + ***/ + + jsp_server_running = 0; + jsp_server_close(); + return 1; +} + +/*--------------------------------------------------------------------*/ +/* Main server thread */ +/*--------------------------------------------------------------------*/ + + +void *jsp_server(void *arg) +{ + struct sockaddr_storage their_addr; + struct timeval tv, *tvp; + fd_set readset; + socklen_t addr_size; + int nfds, flags; + int ret; + char cmd; + + fprintf(stderr, "JSP server thread running!\n"); + + while(jsp_server_running) + { + /* Listen for an incoming connection */ + addr_size = sizeof their_addr; + jsp_client_fd = accept(jsp_server_fd, (struct sockaddr *)&their_addr, &addr_size); + + if(jsp_client_fd == -1) + { + perror("Error in accept() in JSP server thread"); + } + else + { + debug("JSP server got connection!\n"); + + // Clear the in/out buffers + jsp_tohw_rd_idx = 0; + jsp_tohw_wr_idx = 0; + jsp_tohw_count = 0; + jsp_fromhw_rd_idx = 0; + jsp_fromhw_wr_idx = 0; + jsp_fromhw_count = 0; + + /* New client should be non-blocking. */ + flags = fcntl (jsp_client_fd, F_GETFL); + if (flags < 0) + { + fprintf (stderr, "Warning: Unable to get flags for JSP client socket %d: %s\n", jsp_client_fd, strerror(errno)); + // Not really fatal. + } + else { + flags |= O_NONBLOCK; + if (fcntl (jsp_client_fd, F_SETFL, flags) < 0) + { + fprintf (stderr, "Warning: Unable to set flags for JSP client socket %d to 0x%08x: %s\n", jsp_client_fd, flags, strerror(errno)); + // Also not really fatal. + } + } + + jsp_print_welcome(jsp_client_fd); + } + + /* Send/receive data on the new connection for as long as it's valid */ + while(jsp_server_running && (jsp_client_fd != -1)) + { + /* if target not running, block on data from client or monitor thread */ + /* if target running, just poll (don't block */ + if(jsp_target_is_running) { + tv.tv_sec = 0; // Set this each loop, it may be changed by the select() call + tv.tv_usec = 0; // instant timeout when polling + tvp = &tv; + } else { + tvp = NULL; + } + + FD_ZERO(&readset); + FD_SET(jsp_client_fd, &readset); + FD_SET(jsp_pipe_fds[1], &readset); + nfds = jsp_client_fd; + if(jsp_pipe_fds[1] > nfds) nfds = jsp_pipe_fds[1]; + nfds++; + + ret = select(nfds, &readset, NULL, NULL, tvp); + + if(ret == -1) // error + { + perror("select()"); + } + else if(ret != 0) // fd ready (ret == 0 on timeout) + { + debug("JSP thread got data\n"); + + if(FD_ISSET(jsp_pipe_fds[1], &readset)) + { + ret = read(jsp_pipe_fds[1], &cmd, 1); + debug("JSP server got monitor status \'%c\' (0x%X)\n", cmd, cmd); + if(ret == 1) + { + if(cmd == 'H') + { + jsp_target_is_running = 0; + } + else if(cmd == 'R') + { + jsp_target_is_running = 1; + } + else + { + fprintf(stderr, "JSP server got unknown monitor status \'%c\' (0x%X)\n", cmd, cmd); + } + } + else + { + fprintf(stderr, "JSP server failed to read from ready monitor pipe!\n"); + } + } // if FD_ISSET(jsp_pipe_fds[1]) + + if(FD_ISSET(jsp_client_fd, &readset)) + { + jsp_queue_data_from_client(jsp_client_fd); + } + } // else if (ret != 0) + + + /* Send any buffered output data to the client */ + jsp_send_data_to_client(jsp_client_fd); + + /* If target running, transact with the JSP to send/receive buffered data */ + if(jsp_target_is_running) + { + jsp_hardware_transact(); + } + + } /* while client connection is valid */ + + } /* while(jsp_server_running) */ + + jsp_client_close(); + + return arg; // unused +} + +/*--------------------------------------------------------------------*/ +/* Helper functions */ +/*--------------------------------------------------------------------*/ + +void jsp_server_close(void) +{ + if (jsp_server_fd != -1) + { + close(jsp_server_fd); + jsp_server_fd = -1; + } +} + + +void jsp_client_close(void) +{ + if (jsp_client_fd != -1) + { + close (jsp_client_fd); + jsp_client_fd = -1; + } +} /* jsp_client_close () */ + + +void jsp_print_welcome(int fd) +{ + char msg[] = "Advanced Debug System JTAG Serial Port Server\n\r"; + char msg2[] = " ("; + char msg3[] = "), port "; + char portnum[24]; + + jsp_send_all(fd, msg, sizeof(msg)); + jsp_send_all(fd, jsp_hostname, strlen(jsp_hostname)); + jsp_send_all(fd, msg2, sizeof(msg2)); + jsp_send_all(fd, jsp_ipstr, strlen(jsp_ipstr)); + jsp_send_all(fd, msg3, sizeof(msg3)); + + memset(portnum, '\0', sizeof(portnum)); + snprintf(portnum, 23, "%i\n\n\r", jsp_portnum); + jsp_send_all(fd, portnum, strlen(portnum)); +} + + +void jsp_queue_data_from_client(int fd) +{ + int space_available; + int bytes_received; + + debug("JSP queueing data from client; Tohw count now %i\n", jsp_tohw_count); + + // First, try to fill from the write index to the end of the array, or the read index, whichever is less + // This keeps the buffer that recv() writes to linear + space_available = JSP_BUFFER_SIZE - jsp_tohw_wr_idx; + if(space_available > (JSP_BUFFER_SIZE - jsp_tohw_count)) + space_available = JSP_BUFFER_SIZE - jsp_tohw_count; + + bytes_received = recv(fd, &jsp_tohw_buf[jsp_tohw_wr_idx], space_available, 0); + if(bytes_received < 0) + { + perror("JSP client socket read failed"); + return; + } + else if(bytes_received > 0) + { + jsp_tohw_wr_idx = (jsp_tohw_wr_idx + bytes_received) % JSP_BUFFER_SIZE; // modulo will only happen if wrapping to 0 + jsp_tohw_count += bytes_received; + } + + // Now, do the same thing again, potentially filling the buffer from index 0 to the read index + space_available = JSP_BUFFER_SIZE - jsp_tohw_wr_idx; + if(space_available > (JSP_BUFFER_SIZE - jsp_tohw_count)) + space_available = JSP_BUFFER_SIZE - jsp_tohw_count; + + bytes_received = recv(fd, &jsp_tohw_buf[jsp_tohw_wr_idx], space_available, 0); + if(bytes_received < 0) + { + if(errno != EAGAIN) { + perror("JSP client socket read failed"); + } else { + debug("Second JSP client socket read got EAGAIN.\n"); + } + return; + } + else if(bytes_received > 0) + { + jsp_tohw_wr_idx = (jsp_tohw_wr_idx + bytes_received) % JSP_BUFFER_SIZE; // modulo will only happen if wrapping to 0 + jsp_tohw_count += bytes_received; + } + + debug("JSP queued data from client; Tohw count now %i\n", jsp_tohw_count); +} + +void jsp_send_data_to_client(int fd) +{ + int bytes_written; + int bytes_available; + + // *** TODO: use sendvec() + debug("JSP will send data to client. Fromhw count now %i\n", jsp_fromhw_count); + + if(jsp_fromhw_count > 0) + { + bytes_available = jsp_fromhw_count; + if(bytes_available > (JSP_BUFFER_SIZE - jsp_fromhw_rd_idx)) + bytes_available = JSP_BUFFER_SIZE - jsp_fromhw_rd_idx; + + bytes_written = send(fd, &jsp_fromhw_buf[jsp_fromhw_rd_idx], bytes_available, 0); + if(bytes_written < 0) + { + perror("JSP server failed client socket write"); + } + else + { + jsp_fromhw_count -= bytes_written; + jsp_fromhw_rd_idx = (jsp_fromhw_rd_idx + bytes_written) % JSP_BUFFER_SIZE; + } + } + + // Now do it again, in case of buffer wraparound + if(jsp_fromhw_count > 0) + { + bytes_available = jsp_fromhw_count; + if(bytes_available > (JSP_BUFFER_SIZE - jsp_fromhw_rd_idx)) + bytes_available = JSP_BUFFER_SIZE - jsp_fromhw_rd_idx; + + bytes_written = send(fd, &jsp_fromhw_buf[jsp_fromhw_rd_idx], bytes_available, 0); + if(bytes_written < 0) + { + perror("JSP server failed client socket write"); + } + else + { + jsp_fromhw_count -= bytes_written; + jsp_fromhw_rd_idx = (jsp_fromhw_rd_idx + bytes_written) % JSP_BUFFER_SIZE; + } + } + + debug("JSP sent data to client. Fromhw count now %i\n", jsp_fromhw_count); +} + + +void jsp_hardware_transact(void) +{ + unsigned int bytes_to_send; + unsigned int bytes_received = 8; // can receive up to 8 bytes + unsigned char sendbuf[8]; + unsigned char rcvbuf[8]; + int i,j; + int ret; + + debug("JSP about to transact; Tohw buf size now %i, fromhw buf size %i\n", jsp_tohw_count, jsp_fromhw_count); + + // Get data to send, if any + bytes_to_send = jsp_tohw_count; + if(bytes_to_send > 8) bytes_to_send = 8; + + j = jsp_tohw_rd_idx; + for(i = 0; i < bytes_to_send; i++) + { + sendbuf[i] = jsp_tohw_buf[j]; + j = (j+1) % JSP_BUFFER_SIZE; + } + + // Do the transaction + ret = dbg_serial_sndrcv(&bytes_to_send, sendbuf, &bytes_received, rcvbuf); + if(ret != APP_ERR_NONE) + { + fprintf(stderr, "Error in JSP transaction: %s\n", get_err_string(ret)); + } + else + { + debug("Transacted, bytes sent = %i, received = %i\n", bytes_to_send, bytes_received); + + // Adjust send buffer pointers as necessary - we may not have sent all 8 bytes + jsp_tohw_count -= bytes_to_send; + jsp_tohw_rd_idx = (jsp_tohw_rd_idx + bytes_to_send) % JSP_BUFFER_SIZE; + + // Queue data received, if any, and adjust the pointers + for(i = 0; i < bytes_received; i++) + { + jsp_fromhw_buf[jsp_fromhw_wr_idx] = rcvbuf[i]; + jsp_fromhw_wr_idx = (jsp_fromhw_wr_idx + 1) % JSP_BUFFER_SIZE; + jsp_fromhw_count++; + } + + debug("JSP transacted; Tohw buf size now %i, fromhw buf size %i\n", jsp_tohw_count, jsp_fromhw_count); + } +} + +void jsp_send_all(int fd, char *buf, int len) +{ + int total_sent = 0; + int bytes_sent; + + while(total_sent < len) + { + bytes_sent = send(fd, buf, len, 0); + if(bytes_sent < 0) + { + perror("JSP server socket send failed"); + break; + } + total_sent += bytes_sent; + } +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/dbg_api.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/dbg_api.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/dbg_api.h (revision 66) @@ -0,0 +1,32 @@ +#ifndef _DBG_API_H_ +#define _DBG_API_H_ + +#include +#include + + + +// API for GDB +int dbg_wb_read32(uint32_t adr, uint32_t *data); +int dbg_wb_write32(uint32_t adr, uint32_t data); +int dbg_wb_write16(uint32_t adr, uint16_t data); +int dbg_wb_write8(uint32_t adr, uint8_t data); +int dbg_wb_read_block32(uint32_t adr, uint32_t *data, int len); +int dbg_wb_read_block16(uint32_t adr, uint16_t *data, int len); +int dbg_wb_read_block8(uint32_t adr, uint8_t *data, int len); +int dbg_wb_write_block32(uint32_t adr, uint32_t *data, int len); +int dbg_wb_write_block16(uint32_t adr, uint16_t *data, int len); +int dbg_wb_write_block8(uint32_t adr, uint8_t *data, int len); +int dbg_cpu0_read(uint32_t adr, uint32_t *data); +int dbg_cpu0_read_block(uint32_t adr, uint32_t *data, int count); +int dbg_cpu0_write(uint32_t adr, uint32_t data); +int dbg_cpu0_write_block(uint32_t adr, uint32_t *data, int count); +int dbg_cpu0_write_ctrl(uint32_t adr, uint8_t data); +int dbg_cpu0_read_ctrl(uint32_t adr, uint8_t *data); +//int dbg_cpu1_read(uint32_t adr, uint32_t *data); +//int dbg_cpu1_write(uint32_t adr, uint32_t data); +//int dbg_cpu1_write_reg(uint32_t adr, uint8_t data); +//int dbg_cpu1_read_ctrl(uint32_t adr, uint8_t *data); +int dbg_serial_sndrcv(unsigned int *bytes_to_send, const uint8_t *data_to_send, unsigned int *bytes_received, uint8_t *data_received); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hardware_monitor.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hardware_monitor.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hardware_monitor.c (revision 66) @@ -0,0 +1,327 @@ +/* hardware_monitor.c -- Monitors and controls CPU stall state + Copyright(C) 2010 Nathan Yawn + + This file was part the advanced debug unit / bridge. It coordinates + the CPU stall activity for the RSP server, the JSP server, and anything + else that wants to stall the CPU, or know when it's running. + + 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 // for memcpy() +#include + +#include "dbg_api.h" +#include "errcodes.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +#define MAX_MONITOR_CONNECTIONS 5 + +int monitor_thread_running = 0; +int target_is_running = 0; + +typedef struct fdstruct +{ + int server_to_monitor_fds[2]; + int monitor_to_server_fds[2]; +} fdstruct_t; + +int num_monitor_connections = 0; +fdstruct_t connections[MAX_MONITOR_CONNECTIONS]; + +/* This mutex must be held when modify num_monitor_connections or the connections[] array. + * The lock should no be released until the two are consistent with each other. */ +pthread_mutex_t pipes_mutex = PTHREAD_MUTEX_INITIALIZER; + +pthread_t target_handler_thread; +void *target_handler(void *arg); + +void stall_cpu(int stall); +void notify_listeners(char *outstr, int length); + +/*----------------------------------------------------------------------------*/ +/* Public API functions */ + +int start_monitor_thread(void) +{ + // The target usually starts off running. If it's not, then we'll just poll in the monitor thread, + // detect it's stalled, and set this correctly + target_is_running = 1; + + // Create the harware target polling thread + if(pthread_create(&target_handler_thread, NULL, target_handler, NULL)) + { + fprintf(stderr, "Failed to create target handler thread!\n"); + return 0; + } + + // Set a variable that shows we're running + monitor_thread_running = 1; + + return 1; +} + + +int register_with_monitor_thread(int pipe_fds[2]) +{ + + // Fail if monitor thread not running + if(!monitor_thread_running) + return 0; + + if(num_monitor_connections >= MAX_MONITOR_CONNECTIONS) + return 0; + + + pthread_mutex_lock(&pipes_mutex); + + // We need two pairs of pipes, one for each direction of communication + if(0 > pipe(connections[num_monitor_connections].server_to_monitor_fds)) { // pipe_fds[0] is for reading, [1] is for writing + perror("Error creating pipes: "); + return 0; + } + + if(0 > pipe(connections[num_monitor_connections].monitor_to_server_fds)) { // pipe_fds[0] is for reading, [1] is for writing + perror("Error creating second pipes: "); + return 0; + } + + pipe_fds[0] = connections[num_monitor_connections].server_to_monitor_fds[1]; + pipe_fds[1] = connections[num_monitor_connections].monitor_to_server_fds[0]; + + num_monitor_connections++; + pthread_mutex_unlock(&pipes_mutex); + + return 1; +} + +void unregister_with_monitor_thread(int pipe_fds[2]) +{ + int i; + int found = 0; + + // Don't bother with invalid pipe IDs. + if((pipe_fds[0] < 0) || (pipe_fds[1] < 0)) + return; + + pthread_mutex_lock(&pipes_mutex); + + for(i = 0; i < num_monitor_connections; i++) + { + if(connections[i].server_to_monitor_fds[1] == pipe_fds[0] && + connections[i].monitor_to_server_fds[0] == pipe_fds[1]) + { + found = 1; + close(connections[i].server_to_monitor_fds[0]); + close(connections[i].server_to_monitor_fds[1]); + close(connections[i].monitor_to_server_fds[0]); + close(connections[i].monitor_to_server_fds[1]); + pipe_fds[0] = -1; + pipe_fds[1] = -1; // in case of multiple unregister attempts + // Because we just add new connections to the end of the array, we have to + // reshuffle when we delete one out of the middle. We do this by taking + // the last entry and moving it to the newly vacated spot. Don't bother + // if we're removing the last entry. + if(i != (num_monitor_connections-1)) + { + memcpy(&connections[i], &connections[num_monitor_connections-1], sizeof(fdstruct_t)); + } + num_monitor_connections--; + break; + } + } + + pthread_mutex_unlock(&pipes_mutex); + + if(!found) + { + fprintf(stderr, "Warning: monitor thread did not find pipe set for unregistration! fd[0] is 0x%X, fd[1] is 0x%X\n", pipe_fds[0], pipe_fds[1]); + } + +} + + + +/////////////////////////////////////////////////////////////////////////// +// Thread to poll for break on remote processor. + +// Polling algorithm: +// Set timeout to 1/4 second. This allows new pipe sets to be registered easily. +// poll/select on all valid incoming pipe fds +// If data, run all commands, send feedback to all registered servers, loop back to timeout determination +// if no data and target running, poll target state, send feedback if stopped + + +void *target_handler(void *arg) +{ + struct timeval tv; + fd_set readset; + int i, fd, ret, nfds; + char cmd; + unsigned char target_status; + + debug("Target handler thread started!\n"); + + while(1) + { + // Set this each loop, it may be changed by the select() call + tv.tv_sec = 0; + tv.tv_usec = 250000; // 1/4 second timeout when polling + + FD_ZERO(&readset); + nfds = 0; + + pthread_mutex_lock(&pipes_mutex); + for(i = 0; i < num_monitor_connections; i++) + { + fd = connections[i].server_to_monitor_fds[0]; + FD_SET(fd, &readset); + if(fd > nfds) + nfds = fd; + } + pthread_mutex_unlock(&pipes_mutex); + nfds++; + + // We do not hold the pipes_mutex during the select(), so it is possible that some of + // the pipes in the readset will go away while we block. This is fine, as we re-take + // the lock below and iterate through the (changed) connections[] array, which will + // ignore any pipes which have closed, even if they are in the readset. + + ret = select(nfds, &readset, NULL, NULL, &tv); + + if(ret == -1) // error + { + // We may get an EBADF if a server un-registers its pipes while we're in the select() + // (very likely). So, ignore EBADF unless there's a problem that needs debugged. + if(errno != EBADF) + perror("select()"); + else + { + debug("Monitor thread got EBADF in select(). Server unregistration, or real problem?"); + } + } + else if(ret != 0) // fd ready (ret == 0 on timeout) + { + debug("Monitor thread got data\n"); + pthread_mutex_lock(&pipes_mutex); + for(i = 0; i < num_monitor_connections; i++) + { + debug("Monitor checking incoming connection %i\n", i); + fd = connections[i].server_to_monitor_fds[0]; + if(FD_ISSET(fd, &readset)) + { + ret = read(fd, &cmd, 1); + debug("Target monitor thread got command \'%c\' (0x%X)\n", cmd, cmd); + if(ret == 1) + { + if(cmd == 'S') + { + if(target_is_running) stall_cpu(1); + notify_listeners("H", 1); + } + else if(cmd == 'U') + { + if(!target_is_running) stall_cpu(0); + notify_listeners("R", 1); + } + else + { + fprintf(stderr, "Target monitor thread got unknown command \'%c\' (0x%X)\n", cmd, cmd); + } + } + else + { + fprintf(stderr, "Monitor thread failed to read from ready descriptor!\n"); + } + } // if FD_ISSET() + } // for i = 0 to num_monitor_connections + pthread_mutex_unlock(&pipes_mutex); + + // We got a command. Either the target is now stalled and we don't need to poll, + // or the target just started and we should wait a bit before polling. + continue; + + } // else if (ret != 0) + + + if(target_is_running) + { + debug("Monitor polling hardware!\n"); + // Poll target hardware + ret = dbg_cpu0_read_ctrl(0, &target_status); + if(ret != APP_ERR_NONE) + fprintf(stderr, "ERROR 0x%X while polling target CPU status\n", ret); + else { + if(target_status & 0x01) // Did we get the stall bit? Bit 0 is STALL bit. + { + debug("Monitor poll found CPU stalled!\n"); + target_is_running = 0; + pthread_mutex_lock(&pipes_mutex); + notify_listeners("H", 1); + pthread_mutex_unlock(&pipes_mutex); + } + } + } // if(target_is_running) + + + } // while(1), main loop + + fprintf(stderr, "Target monitor thread exiting!!"); + + return arg; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Helper functions for the monitor thread + +void stall_cpu(int stall) +{ + int retval = 0; + unsigned char data = (stall>0)? 1:0; + + // Actually start or stop the CPU hardware + retval = dbg_cpu0_write_ctrl(0, data); // 0x01 is the STALL command bit + if(retval != APP_ERR_NONE) + fprintf(stderr, "ERROR 0x%X sending async STALL to target.\n", retval); + + target_is_running = !data; + + return; +} + +/* Lock the pipes_mutex before calling this! */ +void notify_listeners(char *outstr, int length) +{ + int i; + int ret; + + for(i = 0; i < num_monitor_connections; i++) + { + ret = write(connections[i].monitor_to_server_fds[1], outstr, length); + if(ret < 0) { + perror("Error notifying listener in target monitor"); + } + else if(ret == 0) { + fprintf(stderr, "Monitor thread wrote 0 bytes attempting to notify server\n"); + } + } +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/jsp_server.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/jsp_server.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/jsp_server.h (revision 66) @@ -0,0 +1,31 @@ +/* jsp_server.h -- Header for the JTAG serial port + Copyright(C) 2010 Nathan Yawn + + This file is part the advanced debug unit / bridge. The JSP server + acts as a telnet server, to send and receive data for the JTAG Serial + Port (JSP). + + 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 _JSP_SERVER_H_ +#define _JSP_SERVER_H_ + + +void jsp_init(int portNum); +int jsp_server_start(void); +void jsp_server_stop(void); + + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hardware_monitor.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hardware_monitor.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/hardware_monitor.h (revision 66) @@ -0,0 +1,34 @@ + +#ifndef _HARDWARE_MONITOR_H_ +#define _HARDWARE_MONITOR_H_ + +/* Communication between servers (such as the RSP server) and the target + * monitor is done via 2 pipes, created using pipe(). One pipe, pipe_fds[0], + * is used by the server to command the target monitor thread to stall or + * unstall the CPU. This is done by sending single-letter commands; sending "S" + * commands the monitor thread to stall the CPU, sending "U" commands the monitor + * to unstall the CPU. + * + * Feedback is sent back to servers using pipe_fds[1]. When the CPU transitions + * from the stalled state to the run state, an "R" is sent to all registered + * servers. When the CPU goes from running to stopped, an "H" is sent to indicate + * the halt state. + */ + +/* This should be called once at initialization */ +int start_monitor_thread(void); + +/* This is called to create a pair of shared pipes with the monitor thread. + * The pipes should NOT have already been created before calling this function, + * but the pipe_fds array must be already allocated. pipe_fds[0] is for + * communicating server->monitor, pipe_fds[1] is for monitor->server. + */ +int register_with_monitor_thread(int pipe_fds[2]); + +/* Un-share a set of pipes with the monitor. The pipes may be closed + * after this call returns. + */ +void unregister_with_monitor_thread(int pipe_fds[2]); + + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_dbg_commands.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_dbg_commands.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_dbg_commands.h (revision 66) @@ -0,0 +1,75 @@ + +#ifndef _ADV_DBG_COMMANDS_H_ +#define _ADV_DBG_COMMANDS_H_ + + +// Definitions for the top-level debug unit. This really just consists +// of a single register, used to select the active debug module ("chain"). +#define DBG_MODULE_SELECT_REG_SIZE 2 +#define DBG_MAX_MODULES 4 // used to size an array + +#define DC_WISHBONE 0 +#define DC_CPU0 1 +#define DC_CPU1 2 +#define DC_JSP 3 + +// Polynomial for the CRC calculation +// Yes, it's backwards. Yes, this is on purpose. +// The hardware is designed this way to save on logic and routing, +// and it's really all the same to us here. +#define ADBG_CRC_POLY 0xedb88320 + +// These are for the internal registers in the Wishbone module +// The first is the length of the index register, +// the indexes of the various registers are defined after that +#define DBG_WB_REG_SEL_LEN 1 +#define DBG_WB_REG_ERROR 0 + +// Opcode definitions for the Wishbone module +#define DBG_WB_OPCODE_LEN 4 +#define DBG_WB_CMD_NOP 0x0 +#define DBG_WB_CMD_BWRITE8 0x1 +#define DBG_WB_CMD_BWRITE16 0x2 +#define DBG_WB_CMD_BWRITE32 0x3 +#define DBG_WB_CMD_BREAD8 0x5 +#define DBG_WB_CMD_BREAD16 0x6 +#define DBG_WB_CMD_BREAD32 0x7 +#define DBG_WB_CMD_IREG_WR 0x9 // This is both a select and a write +#define DBG_WB_CMD_IREG_SEL 0xd // There is no 'read', the current register is always read. Use a NOP to read. + + +// Internal register definitions for the CPU0 module +#define DBG_CPU0_REG_SEL_LEN 1 +#define DBG_CPU0_REG_STATUS 0 + +// Opcode definitions for the first CPU module +#define DBG_CPU0_OPCODE_LEN 4 +#define DBG_CPU0_CMD_NOP 0x0 +#define DBG_CPU0_CMD_BWRITE32 0x3 +#define DBG_CPU0_CMD_BREAD32 0x7 +#define DBG_CPU0_CMD_IREG_WR 0x9 // This is both a select and a write +#define DBG_CPU0_CMD_IREG_SEL 0xd // There is no 'read', the current register is always read. Use a NOP to read. + +// Internal register definitions for the CPU1 module +#define DBG_CPU1_REG_SEL_LEN 1 +#define DBG_CPU1_REG_STATUS 0 + +// Opcode definitions for the second CPU module +#define DBG_CPU1_OPCODE_LEN 4 +#define DBG_CPU1_CMD_NOP 0x0 +#define DBG_CPU1_CMD_BWRITE32 0x3 +#define DBG_CPU1_CMD_BREAD32 0x7 +#define DBG_CPU1_CMD_IREG_WR 0x9 // This is both a select and a write +#define DBG_CPU1_CMD_IREG_SEL 0xd // There is no 'read', the current register is always read. Use a NOP to read. + +// API to do transactions on the advanced debug interface +int adbg_select_module(int chain); +int adbg_select_ctrl_reg(unsigned long regidx); +int adbg_ctrl_write(unsigned long regidx, uint32_t *cmd_data, int length_bits); +int adbg_ctrl_read(unsigned long regidx, uint32_t *data, int databits); +int adbg_burst_command(unsigned int opcode, unsigned long address, int length_words); +int adbg_wb_burst_read(int word_size_bytes, int word_count, unsigned long start_address, void *data); +int adbg_wb_burst_write(void *data, int word_size_bytes, int word_count, unsigned long start_address); +int adbg_jsp_transact(unsigned int *bytes_to_send, const char *data_to_send, unsigned int *bytes_received, char *data_received); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/errcodes.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/errcodes.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/errcodes.c (revision 66) @@ -0,0 +1,54 @@ +/* errcodes.c - Error code to plaintext translator for the advanced JTAG bridge + Copyright(C) 2008 - 2010 Nathan Yawn + + 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 "errcodes.h" + +// We can declare the error string with a fixed size, because it can't +// have more than ALL of the error strings in it. Be sure to expand it +// as more errors are added. Also, put a space at the end of each +// error string, as there may be multiple errors. +char errstr[256]; +char *get_err_string(int err) +{ + errstr[0] = '\0'; + + if(err & APP_ERR_COMM) + strcat(errstr, "\'JTAG comm error\' "); + if(err & APP_ERR_MALLOC) + strcat(errstr, "\'malloc failed\' "); + if(err & APP_ERR_MAX_RETRY) + strcat(errstr, "\'max retries\' "); + if(err & APP_ERR_CRC) + strcat(errstr, "\'CRC mismatch\' "); + if(err & APP_ERR_MAX_BUS_ERR) + strcat(errstr, "\'max WishBone bus errors\' "); + if(err & APP_ERR_CABLE_INVALID) + strcat(errstr, "\'Invalid cable\' "); + if(err & APP_ERR_INIT_FAILED) + strcat(errstr, "\'init failed\' "); + if(err & APP_ERR_BAD_PARAM) + strcat(errstr, "\'bad command line parameter\' "); + if(err & APP_ERR_CONNECT) + strcat(errstr, "\'connection failed\' "); + if(err & APP_ERR_USB) + strcat(errstr, "\'USB\' "); + if(err & APP_ERR_CABLENOTFOUND) + strcat(errstr, "\'cable not found\' "); + return errstr; +} Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_jtag_bridge.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_jtag_bridge.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/adv_jtag_bridge.h (revision 66) @@ -0,0 +1,14 @@ +#ifndef _ADV_JTAG_BRIDGE_H_ +#define _ADV_JTAG_BRIDGE_H_ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +#endif /* _ADV_JTAG_BRIDGE_H_ */ + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/legacy_dbg_commands.c =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/legacy_dbg_commands.c (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/legacy_dbg_commands.c (revision 66) @@ -0,0 +1,393 @@ +/* legacy_dbg_commands.c -- JTAG protocol bridge between GDB and OpenCores debug module. + Copyright(C) 2001 Marko Mlinar, markom@opencores.org + Code for TCP/IP copied from gdb, by Chris Ziomkowski + Adapted for the Advanced JTAG Bridge by Nathan Yawn, (C) 2009-2010 + + This file was part of the OpenRISC 1000 Architectural Simulator. + It is now also used to connect GDB to a running hardware OpenCores / OR1200 + debug unit. + + 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 // for htonl + +#include "chain_commands.h" +#include "cable_common.h" +#include "errcodes.h" +#include "legacy_dbg_commands.h" + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +#define LEGACY_CRC_POLY 0x04c11db7 +#define DBG_CRC_SIZE 32 + +/* Crc of current read or written data. */ +static int legacy_crc_r, legacy_crc_w = 0; + + +/*----------------------------------------------------------------------------------*/ +// Helper Functions + +/* Generates new crc, sending in new bit input_bit */ +static unsigned long legacy_crc_calc(unsigned long crc, int input_bit) { + unsigned long d = (input_bit&1) ? 0xfffffff : 0x0000000; + unsigned long crc_32 = ((crc >> 31)&1) ? 0xfffffff : 0x0000000; + crc <<= 1; + return crc ^ ((d ^ crc_32) & LEGACY_CRC_POLY); +} + +/* Writes bitstream. LS bit first if len < 0, MS bit first if len > 0. */ +static void legacy_write_stream(uint32_t stream, int len, int set_last_bit) { + int i; + uint32_t err; + uint32_t outdata = 0; + uint32_t datacpy = stream; + + // MSB needs to be transferred first, lower levels do LSB first. Reverse. + for(i = 0; i < len; i++) { + outdata |= stream & 0x1; + if(i < (len-1)) { + outdata <<= 1; + stream >>= 1; + } + } + + // Call the lower level, in case the driver has a high-speed transfer capability. + // *** This always transfers LS bit first. + err = jtag_write_stream(&outdata, len, set_last_bit); + + debug("legacy_write_stream, stream = 0x%X (0x%X), len = %d, set_last_bit = %d, ret = 0x%X\n", datacpy, outdata, len, set_last_bit, err); + + if(err != APP_ERR_NONE) { + fprintf(stderr, "Error in legacy_write_stream: %s\n", get_err_string(err)); + } + + // The low level call does not compute + // a CRC. Do so here. Remember, CRC is only calculated using data bits. + if(len < 0) { + fprintf(stderr, "Program error: legacy debug JTAG read with negative length!\n"); + /* + len = -len; + for(i = 0; i < len; i++) { + legacy_crc_w = legacy_crc_calc(legacy_crc_w, stream&1); + datacpy >>= 1; + } + */ + } + else { + for(i = len-1; i >= 0; i--) { + legacy_crc_w = legacy_crc_calc(legacy_crc_w, (datacpy>>i)&1); + } + } + +} + +/* Gets bitstream. LS bit first if len < 0, MS bit first if len > 0. */ +static uint32_t legacy_read_stream(unsigned long stream, int len, int set_last_bit) { + int i; + uint32_t data = 0, datacpy = 0; + uint32_t outdata = stream; + uint32_t indata; + uint32_t err; + + // *** WARNING: We assume that the input ("stream") will always be 0. + // If it's ever not, then we probably need to reverse the bit order (as + // is done in legacy_write_stream) before sending. + + // Call the lower level, in case the driver has a high-speed transfer capability. + // This always transfers LS bit first. + err = jtag_read_write_stream(&outdata, &indata, len, 0, set_last_bit); + + // Data comes from the legacy debug unit MSB first, so we need to + // reverse the bit order. + for(i = 0; i < len; i++) { + data |= indata & 0x1; + if(i < (len-1)) { + data <<= 1; + indata >>= 1; + } + } + + datacpy = data; + + debug("legacy_read_stream: write 0x%X, read 0x%X, len %i, set_last_bit = %d\n", outdata, data, len, set_last_bit); + + if(err != APP_ERR_NONE) { + fprintf(stderr, "Error in legacy_read_stream: %s\n", get_err_string(err)); + } + + // The low level call does not compute + // a CRC. Do so here. Remember, CRC is only calculated using data bits. + if(len < 0) { + fprintf(stderr, "Program error: legacy debug JTAG read with negative length!\n"); + /* + len = -len; + for(i = 0; i < len; i++) { + legacy_crc_w = legacy_crc_calc(legacy_crc_w, stream&1); + stream >>= 1; + legacy_crc_r = legacy_crc_calc(legacy_crc_r, datacpy&1); + datacpy >>= 1; + } + */ + } + else { + for(i = len-1; i >= 0; i--) { + legacy_crc_w = legacy_crc_calc(legacy_crc_w, (stream>>i)&1); + legacy_crc_r = legacy_crc_calc(legacy_crc_r, (datacpy>>i)&1); + } + } + + return data; +} + +////////////////////////////////////////////////////////////////////////// +// Actual operations on the legacy debug unit + +/* Sets scan chain. */ +int legacy_dbg_set_chain(int chain) { + int status, crc_generated, legacy_crc_read; + desired_chain = chain; + +try_again: + if (current_chain == chain) return APP_ERR_NONE; + current_chain = -1; + debug("\nset_chain %i\n", chain); + tap_set_shift_dr(); /* SHIFT_DR */ + + /* write data, EXIT1_DR */ + legacy_crc_w = 0xffffffff; + legacy_write_stream(((chain & 0xf) | (1<= 0 */ +int legacy_dbg_command(int type, unsigned long adr, int len) { + int status, crc_generated, legacy_crc_read; + +try_again: + legacy_dbg_set_chain(desired_chain); + debug("\ncomm %i\n", type); + + /***** WRITEx *****/ + tap_set_shift_dr(); /* SHIFT_DR */ + + /* write data, EXIT1_DR */ + legacy_crc_w = 0xffffffff; + legacy_write_stream(((DI_WRITE_CMD & 0xf) | (0< 0); + legacy_write_stream(len - 1, 16, 0); + legacy_write_stream(legacy_crc_w, DBG_CRC_SIZE, 0); + + legacy_crc_r = 0xffffffff; + status = legacy_read_stream(0, DC_STATUS_SIZE, 0); + crc_generated = legacy_crc_r; + legacy_crc_read = legacy_read_stream(0, DBG_CRC_SIZE, 1); + + /* CRCs must match, otherwise retry */ + if (legacy_crc_read != crc_generated) { + if (retry_do()) goto try_again; + else return APP_ERR_CRC; + } + /* we should read expected status value, otherwise retry */ + if (status != 0) { + if (retry_do()) goto try_again; + else return APP_ERR_BAD_PARAM; + } + + tap_exit_to_idle(); // Transition the TAP back to state IDLE + + /* reset retry counter */ + retry_ok(); + return APP_ERR_NONE; +} + +/* writes a ctrl reg */ +int legacy_dbg_ctrl(int reset, int stall) { + int status, crc_generated, legacy_crc_read; + +try_again: + legacy_dbg_set_chain(desired_chain); + debug("\nctrl\n"); + + /***** WRITEx *****/ + tap_set_shift_dr(); /* SHIFT_DR */ + + /* write data, EXIT1_DR */ + legacy_crc_w = 0xffffffff; + legacy_write_stream(((DI_WRITE_CTRL & 0xf) | (0< +#include +#include // for usleep() +#include // for sleep() +#include // for htons() +#include +#include + +#include "ftdi.h" // libftdi header + +#include "cable_common.h" +#include "errcodes.h" + +#warning Compiling alternate (FTDI-based) USB-Blaster driver -- LOW SPEED! + +#define debug(...) //fprintf(stderr, __VA_ARGS__ ) + +// USB constants for the USB Blaster +#define ALTERA_VID 0x09FB +#define ALTERA_PID 0x6001 + +static struct ftdi_context ftdic; + +/////////////////////////////////////////////////////////////////////////////// +/*-------------------------------------[ USB Blaster specific functions ]---*/ +///////////////////////////////////////////////////////////////////////////// + +// +// libusb does not work with my 3C25, but it works with libfdti. +// Following code is ported from http://www.ixo.de/info/usb_jtag/ +// ZXF, 2009-10-22 +// + +int usb_blaster_buf_write(uint8_t *buf, int size, uint32_t* bytes_written) +{ + int retval; + + debug("usb_blaster_buf_write %02X (%d)\n", buf[0], size); + + if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0) { + *bytes_written = 0; + printf("ftdi_write_data: %s\n", ftdi_get_error_string(&ftdic)); + return -1; + } else { + *bytes_written = retval; + return 0; + } +} + +int usb_blaster_buf_read(uint8_t* buf, int size, uint32_t* bytes_read) +{ + int retval; + int timeout = 100; + *bytes_read = 0; + + while ((*bytes_read < size) && timeout--) { + if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0) { + *bytes_read = 0; + printf("ftdi_read_data: %s\n", ftdi_get_error_string(&ftdic)); + return -1; + } + *bytes_read += retval; + } + + debug("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read); + + return 0; +} + +/* The following code doesn't fully utilize the possibilities of the USB-Blaster. It + * writes one byte per JTAG pin state change at a time; it doesn't even try to buffer + * data up to the maximum packet size of 64 bytes. + * + * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data bits + * (bidirectional) in a single USB packet. A header byte has to be sent as the first + * byte in a packet with the following meaning: + * + * Bit 7 (0x80): Must be set to indicate byte-shift mode. + * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write. + * Bit 5..0: Define the number N of following bytes + * + * All N following bytes will then be clocked out serially on TDI. If Bit 6 was set, + * it will afterwards return N bytes with TDO data read while clocking out the TDI data. + * LSB of the first byte after the header byte will appear first on TDI. + */ + +/* Simple bit banging mode: + * + * Bit 7 (0x80): Must be zero (see byte-shift mode above) + * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO in return. + * Bit 5 (0x20): Unknown; for now, set to one. + * Bit 4 (0x10): TDI Output. + * Bit 3 (0x08): Unknown; for now, set to one. + * Bit 2 (0x04): Unknown; for now, set to one. + * Bit 1 (0x02): TMS Output. + * Bit 0 (0x01): TCK Output. + * + * For transmitting a single data bit, you need to write two bytes. Up to 64 bytes can be + * combined in a single USB packet (but this is not done in the code below). It isn't + * possible to read a data without transmitting data. + */ + +#define FTDI_TCK 0 +#define FTDI_TMS 1 +#define FTDI_TDI 4 +#define FTDI_READ 6 +#define FTDI_SHMODE 7 +#define FTDI_OTHERS ((1<<2)|(1<<3)|(1<<5)) + +void usb_blaster_write(int tck, int tms, int tdi) +{ + uint8_t buf[1]; + uint32_t count; + + debug("---- usb_blaster_write(%d,%d,%d)\n", tck,tms,tdi); + + buf[0] = FTDI_OTHERS | (tck?(1<> bits_this_index) & 1; + err |= cable_write_bit(out); + debug("%i", out); + bits_this_index++; + if(bits_this_index >= 32) { + index++; + bits_this_index = 0; + } + } + + out = (stream[index] >>(len_bits - 1)) & 0x1; + if(set_last_bit) out |= TMS; + err |= cable_write_bit(out); + debug("%i)\n", out); + return err; +} + +/* Gets bitstream via bit-bang. Copied directly from cable_common.c, for function-level compatibility + * with the standard / high-speed usbblaster driver. + */ +int cable_usbblaster_read_stream(uint32_t *outstream, uint32_t *instream, int len_bits, int set_last_bit) { + int i; + int index = 0; + int bits_this_index = 0; + uint8_t inval, outval; + int err = APP_ERR_NONE; + + instream[0] = 0; + + debug("readStrm%d(", len_bits); + for(i = 0; i < (len_bits - 1); i++) { + outval = (outstream[index] >> bits_this_index) & 0x1; + err |= cable_read_write_bit(outval, &inval); + debug("%i", inval); + instream[index] |= (inval << bits_this_index); + bits_this_index++; + if(bits_this_index >= 32) { + index++; + bits_this_index = 0; + instream[index] = 0; // It's safe to do this, because there's always at least one more bit + } + } + + if (set_last_bit) + outval = ((outstream[index] >> (len_bits - 1)) & 1) | TMS; + else + outval = (outstream[index] >> (len_bits - 1)) & 1; + + err |= cable_read_write_bit(outval, &inval); + debug("%i", inval); + instream[index] |= (inval << bits_this_index); + + debug(") = 0x%lX\n", instream[0]); + + return err; +} + + + + +int cable_usbblaster_opt(int c, char *str) +{ + fprintf(stderr, "Unknown parameter '%c'\n", c); + return APP_ERR_BAD_PARAM; +} + + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/or32_selftest.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/or32_selftest.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/or32_selftest.h (revision 66) @@ -0,0 +1,78 @@ + +#ifndef _OR32_SELFTEST_H_ +#define _OR32_SELFTEST_H_ + +// Static memory controller defines +#define MC_BAR_0 0x00 +#define MC_AMR_0 0x04 +#define MC_WTR_0 0x30 +#define MC_RTR_0 0x34 +#define MC_OSR 0xe8 +#define MC_BAR_1 0x08 +#define MC_BAR_4 0x80 +#define MC_AMR_1 0x0c +#define MC_AMR_4 0x84 +#define MC_CCR_1 0x24 +#define MC_CCR_4 0xa0 +#define MC_RATR 0xb0 +#define MC_RCDR 0xc8 +#define MC_RCTR 0xb4 +#define MC_REFCTR 0xc4 +#define MC_PTR 0xbc +#define MC_RRDR 0xb8 +#define MC_RIR 0xcc +#define MC_ORR 0xe4 + +// Static flash defines +#define FLASH_AMR_VAL 0xf0000000 +#define FLASH_WTR_VAL 0x00011009 +#define FLASH_RTR_VAL 0x01002009 + +// Static SDRAM defines +#define SDRAM_RATR_VAL 0x00000006 +#define SDRAM_RCDR_VAL 0x00000002 +#define SDRAM_RCTR_VAL 0x00000006 +#define SDRAM_REFCTR_VAL 0x00000006 +#define SDRAM_PTR_VAL 0x00000001 +#define SDRAM_RRDR_VAL 0x00000000 +#define SDRAM_RIR_VAL 0x000000C0 + +// CPU defines +#define CPU_OP_ADR 0 +#define CPU_SEL_ADR 1 + + + +// None of the TC_* defines are currently used +#define TC_RESET 0 +#define TC_BRIGHT 1 +#define TC_DIM 2 +#define TC_UNDERLINE 3 +#define TC_BLINK 4 +#define TC_REVERSE 7 +#define TC_HIDDEN 8 + +#define TC_BLACK 0 +#define TC_RED 1 +#define TC_GREEN 2 +#define TC_YELLOW 3 +#define TC_BLUE 4 +#define TC_MAGENTA 5 +#define TC_CYAN 6 +#define TC_WHITE 7 + + + +// Prototypes //////////////////////////////////////////// +int dbg_test(); +int stall_cpus(void); +void init_mc(void); +void init_sram(void); +int test_sdram (void); +int test_sdram_2(void); +int test_sram(void); +int test_or1k_cpu0(void); +//int test_8051_cpu1(void); + +#endif // _OR32_SELFTEST_H_ + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/legacy_dbg_commands.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/legacy_dbg_commands.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/legacy_dbg_commands.h (revision 66) @@ -0,0 +1,26 @@ + +#ifndef _LEGACY_DBG_COMMANDS_H_ +#define _LEGACY_DBG_COMMANDS_H_ + +#define DC_SIZE 4 +#define DC_STATUS_SIZE 4 + +#define DC_WISHBONE 0 +#define DC_CPU0 1 +#define DC_CPU1 2 + +#define DI_GO 0 +#define DI_READ_CMD 1 +#define DI_WRITE_CMD 2 +#define DI_READ_CTRL 3 +#define DI_WRITE_CTRL 4 + + +// Interface to send commands to the legacy debug interface +int legacy_dbg_set_chain(int chain); +int legacy_dbg_command(int type, unsigned long adr, int len); +int legacy_dbg_ctrl(int reset, int stall); +int legacy_dbg_ctrl_read(int *reset, int *stall); +int legacy_dbg_go(unsigned char *data, unsigned short len, int read); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/chain_commands.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/chain_commands.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/chain_commands.h (revision 66) @@ -0,0 +1,49 @@ +#ifndef _CHAIN_COMMANDS_H_ +#define _CHAIN_COMMANDS_H_ + +#include + +// These two are used by both debug modules +extern int current_chain; +extern int desired_chain; + +// These are needed by the advanced debug module +extern int global_DR_prefix_bits; +extern int global_DR_postfix_bits; +extern unsigned char global_xilinx_bscan; + +// Discover devices on JTAG chain +int jtag_enumerate_chain(uint32_t **id_array, int *num_devices); +int jtag_get_idcode(uint32_t cmd, uint32_t *idcode); + +// Functions to set configuration for the JTAG chain +void config_set_IR_size(int size); +void config_set_IR_prefix_bits(int bits); +void config_set_IR_postfix_bits(int bits); +void config_set_DR_prefix_bits(int bits); +void config_set_DR_postfix_bits(int bits); +void config_set_debug_cmd(unsigned int cmd); +void config_set_alt_vjtag(unsigned char enable); +void config_set_vjtag_cmd_vir(unsigned int cmd); +void config_set_vjtag_cmd_vdr(unsigned int cmd); +void config_set_xilinx_bscan(unsigned char enable); + +// Operations on the JTAG TAP +int tap_reset(void); +int tap_enable_debug_module(void); +int tap_set_ir(int ir); +int tap_set_shift_dr(void); +int tap_exit_to_idle(void); + +// Functions to Send/receive bitstreams via JTAG +// These functions are aware of other devices in the chain, and may adjust for them. +int jtag_write_bit(uint8_t packet); +int jtag_read_write_bit(uint8_t packet, uint8_t *in_bit); +int jtag_write_stream(uint32_t *out_data, int length_bits, unsigned char set_TMS); +int jtag_read_write_stream(uint32_t *out_data, uint32_t *in_data, int length_bits, + unsigned char adjust, unsigned char set_TMS); + +int retry_do(void); +void retry_ok(void); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl.h (revision 66) @@ -0,0 +1,36 @@ +#ifndef _BSDL_H_ +#define _BSDL_H_ + +#include + +// Used by lower levels. +// should not be used by higher levels (i.e. anything that calls +// the API functions). +struct bsdlinfo_node { + char *name; + uint32_t idcode; + uint32_t idcode_mask; + int IR_size; + uint32_t cmd_debug; + uint32_t cmd_user1; + uint32_t cmd_idcode; + struct bsdlinfo_node *next; +}; + +typedef struct bsdlinfo_node bsdlinfo; + + +#define IDCODE_INVALID 0xFFFFFFFF +#define TAP_CMD_INVALID 0XFFFFFFFF + + +void bsdl_init(void); +void bsdl_add_directory(const char *dirname); + +const char * bsdl_get_name(uint32_t idcode); +int bsdl_get_IR_size(uint32_t idcode); +uint32_t bsdl_get_debug_cmd(uint32_t idcode); +uint32_t bsdl_get_user1_cmd(uint32_t idcode); +uint32_t bsdl_get_idcode_cmd(uint32_t idcode); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/opencores_tap.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/opencores_tap.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/opencores_tap.h (revision 66) @@ -0,0 +1,24 @@ +#ifndef _OPENCORES_TAP_H_ +#define _OPENCODER_TAP_H_ + + +// Information on the OpenCores JTAG TAP +// Included as a default, in place of a BSDL file +// with the data. + +#define JI_SIZE (4) +enum jtag_instr + { + JI_EXTEST = 0x0, + JI_SAMPLE_PRELOAD = 0x1, + JI_IDCODE = 0x2, + JI_CHAIN_SELECT = 0x3, + JI_INTEST = 0x4, + JI_CLAMP = 0x5, + JI_CLAMPZ = 0x6, + JI_HIGHZ = 0x7, + JI_DEBUG = 0x8, + JI_BYPASS = 0xF + }; + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/errcodes.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/errcodes.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/errcodes.h (revision 66) @@ -0,0 +1,22 @@ +#ifndef _ERRCODES_H_ +#define _ERRCODES_H_ + +// Errors in high-level chain transactions +// An error is a 32-bit bit-encoded value +#define APP_ERR_NONE 0x0 +#define APP_ERR_COMM 0x1 +#define APP_ERR_MALLOC 0x2 +#define APP_ERR_MAX_RETRY 0x4 +#define APP_ERR_CRC 0x08 +#define APP_ERR_MAX_BUS_ERR 0x10 +#define APP_ERR_CABLE_INVALID 0x20 +#define APP_ERR_INIT_FAILED 0x40 +#define APP_ERR_BAD_PARAM 0x080 +#define APP_ERR_CONNECT 0x100 +#define APP_ERR_USB 0x200 +#define APP_ERR_CABLENOTFOUND 0x400 +#define APP_ERR_TEST_FAIL 0x0800 + +char *get_err_string(int errval); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl_parse.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl_parse.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/bsdl_parse.h (revision 66) @@ -0,0 +1,9 @@ +#ifndef _BSDL_PARSE_H_ +#define _BSDL_PARSE_H_ + +#include "bsdl.h" // need definition of bsdlinfo here + + +bsdlinfo * parse_extract_values(char *bsdlfilename); + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/spr-defs.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/spr-defs.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/spr-defs.h (revision 66) @@ -0,0 +1,581 @@ +/* spr-defs.h -- Defines OR1K architecture specific special-purpose registers + + Copyright (C) 1999 Damjan Lampret, lampret@opencores.org + Copyright (C) 2008 Embecosm Limited + + Contributor Jeremy Bennett + + 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 3 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, see . */ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef SPR_DEFS__H +#define SPR_DEFS__H + +/* Definition of special-purpose registers (SPRs). */ + +#define MAX_GRPS (32) +#define MAX_SPRS_PER_GRP_BITS (11) +#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS) +#define MAX_SPRS (0x10000) + +/* Base addresses for the groups */ +#define SPRGROUP_SYS (0<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_DMMU (1<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_IMMU (2<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_DC (3<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_IC (4<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_MAC (5<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_D (6<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PC (7<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PM (8<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_PIC (9<< MAX_SPRS_PER_GRP_BITS) +#define SPRGROUP_TT (10<< MAX_SPRS_PER_GRP_BITS) + +/* System control and status group */ +#define SPR_VR (SPRGROUP_SYS + 0) +#define SPR_UPR (SPRGROUP_SYS + 1) +#define SPR_CPUCFGR (SPRGROUP_SYS + 2) +#define SPR_DMMUCFGR (SPRGROUP_SYS + 3) +#define SPR_IMMUCFGR (SPRGROUP_SYS + 4) +#define SPR_DCCFGR (SPRGROUP_SYS + 5) +#define SPR_ICCFGR (SPRGROUP_SYS + 6) +#define SPR_DCFGR (SPRGROUP_SYS + 7) +#define SPR_PCCFGR (SPRGROUP_SYS + 8) +#define SPR_NPC (SPRGROUP_SYS + 16) /* CZ 21/06/01 */ +#define SPR_SR (SPRGROUP_SYS + 17) /* CZ 21/06/01 */ +#define SPR_PPC (SPRGROUP_SYS + 18) /* CZ 21/06/01 */ +#define SPR_EPCR_BASE (SPRGROUP_SYS + 32) /* CZ 21/06/01 */ +#define SPR_EPCR_LAST (SPRGROUP_SYS + 47) /* CZ 21/06/01 */ +#define SPR_EEAR_BASE (SPRGROUP_SYS + 48) +#define SPR_EEAR_LAST (SPRGROUP_SYS + 63) +#define SPR_ESR_BASE (SPRGROUP_SYS + 64) +#define SPR_ESR_LAST (SPRGROUP_SYS + 79) +#define SPR_GPR_BASE (SPRGROUP_SYS + 1024) +#define SPR_GPR_LAST (SPRGROUP_SYS + 1535) +#define MAX_GPRS 32 // Does this really belong here? No. --NAY + +/* Data MMU group */ +#define SPR_DMMUCR (SPRGROUP_DMMU + 0) +#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x100) +#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x27f + (WAY) * 0x100) +#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x280 + (WAY) * 0x100) +#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x100) + +/* Instruction MMU group */ +#define SPR_IMMUCR (SPRGROUP_IMMU + 0) +#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x100) +#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x27f + (WAY) * 0x100) +#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x280 + (WAY) * 0x100) +#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x100) + +/* Data cache group */ +#define SPR_DCCR (SPRGROUP_DC + 0) +#define SPR_DCBPR (SPRGROUP_DC + 1) +#define SPR_DCBFR (SPRGROUP_DC + 2) +#define SPR_DCBIR (SPRGROUP_DC + 3) +#define SPR_DCBWR (SPRGROUP_DC + 4) +#define SPR_DCBLR (SPRGROUP_DC + 5) +#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200) +#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200) + +/* Instruction cache group */ +#define SPR_ICCR (SPRGROUP_IC + 0) +#define SPR_ICBPR (SPRGROUP_IC + 1) +#define SPR_ICBIR (SPRGROUP_IC + 2) +#define SPR_ICBLR (SPRGROUP_IC + 3) +#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200) +#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200) + +/* MAC group */ +#define SPR_MACLO (SPRGROUP_MAC + 1) +#define SPR_MACHI (SPRGROUP_MAC + 2) + +/* Debug group */ +#define SPR_DVR(N) (SPRGROUP_D + (N)) +#define SPR_DCR(N) (SPRGROUP_D + 8 + (N)) +#define SPR_DMR1 (SPRGROUP_D + 16) +#define SPR_DMR2 (SPRGROUP_D + 17) +#define SPR_DWCR0 (SPRGROUP_D + 18) +#define SPR_DWCR1 (SPRGROUP_D + 19) +#define SPR_DSR (SPRGROUP_D + 20) +#define SPR_DRR (SPRGROUP_D + 21) + +/* Performance counters group */ +#define SPR_PCCR(N) (SPRGROUP_PC + (N)) +#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N)) + +/* Power management group */ +#define SPR_PMR (SPRGROUP_PM + 0) + +/* PIC group */ +#define SPR_PICMR (SPRGROUP_PIC + 0) +#define SPR_PICPR (SPRGROUP_PIC + 1) +#define SPR_PICSR (SPRGROUP_PIC + 2) + +/* Tick Timer group */ +#define SPR_TTMR (SPRGROUP_TT + 0) +#define SPR_TTCR (SPRGROUP_TT + 1) + +/* + * Bit definitions for the Version Register + * + */ +#define SPR_VR_VER 0xff000000 /* Processor version */ +#define SPR_VR_CFG 0x00ff0000 /* Processor configuration */ +#define SPR_VR_RES 0x00ff0000 /* Reserved */ +#define SPR_VR_REV 0x0000003f /* Processor revision */ + +#define SPR_VR_VER_OFF 24 +#define SPR_VR_CFG_OFF 16 +#define SPR_VR_REV_OFF 0 + +/* + * Bit definitions for the Unit Present Register + * + */ +#define SPR_UPR_UP 0x00000001 /* UPR present */ +#define SPR_UPR_DCP 0x00000002 /* Data cache present */ +#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */ +#define SPR_UPR_DMP 0x00000008 /* Data MMU present */ +#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */ +#define SPR_UPR_MP 0x00000020 /* MAC present */ +#define SPR_UPR_DUP 0x00000040 /* Debug unit present */ +#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */ +#define SPR_UPR_PMP 0x00000100 /* Power management present */ +#define SPR_UPR_PICP 0x00000200 /* PIC present */ +#define SPR_UPR_TTP 0x00000400 /* Tick timer present */ +#define SPR_UPR_RES 0x00fe0000 /* Reserved */ +#define SPR_UPR_CUP 0xff000000 /* Context units present */ + +/* + * JPB: Bit definitions for the CPU configuration register + * + */ +#define SPR_CPUCFGR_NSGF 0x0000000f /* Number of shadow GPR files */ +#define SPR_CPUCFGR_CGF 0x00000010 /* Custom GPR file */ +#define SPR_CPUCFGR_OB32S 0x00000020 /* ORBIS32 supported */ +#define SPR_CPUCFGR_OB64S 0x00000040 /* ORBIS64 supported */ +#define SPR_CPUCFGR_OF32S 0x00000080 /* ORFPX32 supported */ +#define SPR_CPUCFGR_OF64S 0x00000100 /* ORFPX64 supported */ +#define SPR_CPUCFGR_OV64S 0x00000200 /* ORVDX64 supported */ +#define SPR_CPUCFGR_RES 0xfffffc00 /* Reserved */ + +/* + * JPB: Bit definitions for the Debug configuration register and other + * constants. + * + */ + +#define SPR_DCFGR_NDP 0x00000007 /* Number of matchpoints mask */ +#define SPR_DCFGR_NDP1 0x00000000 /* One matchpoint supported */ +#define SPR_DCFGR_NDP2 0x00000001 /* Two matchpoints supported */ +#define SPR_DCFGR_NDP3 0x00000002 /* Three matchpoints supported */ +#define SPR_DCFGR_NDP4 0x00000003 /* Four matchpoints supported */ +#define SPR_DCFGR_NDP5 0x00000004 /* Five matchpoints supported */ +#define SPR_DCFGR_NDP6 0x00000005 /* Six matchpoints supported */ +#define SPR_DCFGR_NDP7 0x00000006 /* Seven matchpoints supported */ +#define SPR_DCFGR_NDP8 0x00000007 /* Eight matchpoints supported */ +#define SPR_DCFGR_WPCI 0x00000008 /* Watchpoint counters implemented */ + +#define MATCHPOINTS_TO_NDP(n) (1 == n ? SPR_DCFGR_NDP1 : \ + 2 == n ? SPR_DCFGR_NDP2 : \ + 3 == n ? SPR_DCFGR_NDP3 : \ + 4 == n ? SPR_DCFGR_NDP4 : \ + 5 == n ? SPR_DCFGR_NDP5 : \ + 6 == n ? SPR_DCFGR_NDP6 : \ + 7 == n ? SPR_DCFGR_NDP7 : SPR_DCFGR_NDP8) +#define MAX_MATCHPOINTS 8 +#define MAX_WATCHPOINTS (MAX_MATCHPOINTS + 2) + +/* + * Bit definitions for the Supervision Register + * + */ +#define SPR_SR_SM 0x00000001 /* Supervisor Mode */ +#define SPR_SR_TEE 0x00000002 /* Tick timer Exception Enable */ +#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */ +#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */ +#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */ +#define SPR_SR_DME 0x00000020 /* Data MMU Enable */ +#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */ +#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */ +#define SPR_SR_CE 0x00000100 /* CID Enable */ +#define SPR_SR_F 0x00000200 /* Condition Flag */ +#define SPR_SR_CY 0x00000400 /* Carry flag */ +#define SPR_SR_OV 0x00000800 /* Overflow flag */ +#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */ +#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */ +#define SPR_SR_EPH 0x00004000 /* Exception Prefix High */ +#define SPR_SR_FO 0x00008000 /* Fixed one */ +#define SPR_SR_SUMRA 0x00010000 /* Supervisor SPR read access */ +#define SPR_SR_RES 0x0ffe0000 /* Reserved */ +#define SPR_SR_CID 0xf0000000 /* Context ID */ + +/* + * Bit definitions for the Data MMU Control Register + * + */ +#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */ +#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */ +#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */ +#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */ + +/* + * Bit definitions for the Instruction MMU Control Register + * + */ +#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */ +#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */ +#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */ +#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */ + +/* + * Bit definitions for the Data TLB Match Register + * + */ +#define SPR_DTLBMR_V 0x00000001 /* Valid */ +#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */ +#define SPR_DTLBMR_CID 0x0000003c /* Context ID */ +#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */ +#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */ + +/* + * Bit definitions for the Data TLB Translate Register + * + */ +#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */ +#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */ +#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */ +#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */ +#define SPR_DTLBTR_A 0x00000010 /* Accessed */ +#define SPR_DTLBTR_D 0x00000020 /* Dirty */ +#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */ +#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */ +#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */ +#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */ +#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */ + +/* + * Bit definitions for the Instruction TLB Match Register + * + */ +#define SPR_ITLBMR_V 0x00000001 /* Valid */ +#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */ +#define SPR_ITLBMR_CID 0x0000003c /* Context ID */ +#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */ +#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */ + +/* + * Bit definitions for the Instruction TLB Translate Register + * + */ +#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */ +#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */ +#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */ +#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */ +#define SPR_ITLBTR_A 0x00000010 /* Accessed */ +#define SPR_ITLBTR_D 0x00000020 /* Dirty */ +#define SPR_ITLBTR_SXE 0x00000040 /* User Read Enable */ +#define SPR_ITLBTR_UXE 0x00000080 /* User Write Enable */ +#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */ + +/* + * Bit definitions for Data Cache Control register + * + */ +#define SPR_DCCR_EW 0x000000ff /* Enable ways */ + +/* + * Bit definitions for Insn Cache Control register + * + */ +#define SPR_ICCR_EW 0x000000ff /* Enable ways */ + +/* + * Bit definitions for Data Cache Configuration Register + * + */ + +#define SPR_DCCFGR_NCW 0x00000007 +#define SPR_DCCFGR_NCS 0x00000078 +#define SPR_DCCFGR_CBS 0x00000080 +#define SPR_DCCFGR_CWS 0x00000100 +#define SPR_DCCFGR_CCRI 0x00000200 +#define SPR_DCCFGR_CBIRI 0x00000400 +#define SPR_DCCFGR_CBPRI 0x00000800 +#define SPR_DCCFGR_CBLRI 0x00001000 +#define SPR_DCCFGR_CBFRI 0x00002000 +#define SPR_DCCFGR_CBWBRI 0x00004000 + +#define SPR_DCCFGR_NCW_OFF 0 +#define SPR_DCCFGR_NCS_OFF 3 +#define SPR_DCCFGR_CBS_OFF 7 + +/* + * Bit definitions for Instruction Cache Configuration Register + * + */ +#define SPR_ICCFGR_NCW 0x00000007 +#define SPR_ICCFGR_NCS 0x00000078 +#define SPR_ICCFGR_CBS 0x00000080 +#define SPR_ICCFGR_CCRI 0x00000200 +#define SPR_ICCFGR_CBIRI 0x00000400 +#define SPR_ICCFGR_CBPRI 0x00000800 +#define SPR_ICCFGR_CBLRI 0x00001000 + +#define SPR_ICCFGR_NCW_OFF 0 +#define SPR_ICCFGR_NCS_OFF 3 +#define SPR_ICCFGR_CBS_OFF 7 + +/* + * Bit definitions for Data MMU Configuration Register + * + */ + +#define SPR_DMMUCFGR_NTW 0x00000003 +#define SPR_DMMUCFGR_NTS 0x0000001C +#define SPR_DMMUCFGR_NAE 0x000000E0 +#define SPR_DMMUCFGR_CRI 0x00000100 +#define SPR_DMMUCFGR_PRI 0x00000200 +#define SPR_DMMUCFGR_TEIRI 0x00000400 +#define SPR_DMMUCFGR_HTR 0x00000800 + +#define SPR_DMMUCFGR_NTW_OFF 0 +#define SPR_DMMUCFGR_NTS_OFF 2 + +/* + * Bit definitions for Instruction MMU Configuration Register + * + */ + +#define SPR_IMMUCFGR_NTW 0x00000003 +#define SPR_IMMUCFGR_NTS 0x0000001C +#define SPR_IMMUCFGR_NAE 0x000000E0 +#define SPR_IMMUCFGR_CRI 0x00000100 +#define SPR_IMMUCFGR_PRI 0x00000200 +#define SPR_IMMUCFGR_TEIRI 0x00000400 +#define SPR_IMMUCFGR_HTR 0x00000800 + +#define SPR_IMMUCFGR_NTW_OFF 0 +#define SPR_IMMUCFGR_NTS_OFF 2 + +/* + * Bit definitions for Debug Control registers + * + */ +#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */ +#define SPR_DCR_CC 0x0000000e /* Compare condition */ +#define SPR_DCR_SC 0x00000010 /* Signed compare */ +#define SPR_DCR_CT 0x000000e0 /* Compare to */ + +/* Bit results with SPR_DCR_CC mask */ +#define SPR_DCR_CC_MASKED 0x00000000 +#define SPR_DCR_CC_EQUAL 0x00000002 +#define SPR_DCR_CC_LESS 0x00000004 +#define SPR_DCR_CC_LESSE 0x00000006 +#define SPR_DCR_CC_GREAT 0x00000008 +#define SPR_DCR_CC_GREATE 0x0000000a +#define SPR_DCR_CC_NEQUAL 0x0000000c + +/* Bit results with SPR_DCR_CT mask */ +#define SPR_DCR_CT_DISABLED 0x00000000 +#define SPR_DCR_CT_IFEA 0x00000020 +#define SPR_DCR_CT_LEA 0x00000040 +#define SPR_DCR_CT_SEA 0x00000060 +#define SPR_DCR_CT_LD 0x00000080 +#define SPR_DCR_CT_SD 0x000000a0 +#define SPR_DCR_CT_LSEA 0x000000c0 +#define SPR_DCR_CT_LSD 0x000000e0 +/* SPR_DCR_CT_LSD doesn't seem to be implemented anywhere in or1ksim. 2004-1-30 HP */ + +/* + * Bit definitions for Debug Mode 1 register + * + */ +#define SPR_DMR1_CW 0x000fffff /* Chain register pair data */ +#define SPR_DMR1_CW0_AND 0x00000001 +#define SPR_DMR1_CW0_OR 0x00000002 +#define SPR_DMR1_CW0 (SPR_DMR1_CW0_AND | SPR_DMR1_CW0_OR) +#define SPR_DMR1_CW1_AND 0x00000004 +#define SPR_DMR1_CW1_OR 0x00000008 +#define SPR_DMR1_CW1 (SPR_DMR1_CW1_AND | SPR_DMR1_CW1_OR) +#define SPR_DMR1_CW2_AND 0x00000010 +#define SPR_DMR1_CW2_OR 0x00000020 +#define SPR_DMR1_CW2 (SPR_DMR1_CW2_AND | SPR_DMR1_CW2_OR) +#define SPR_DMR1_CW3_AND 0x00000040 +#define SPR_DMR1_CW3_OR 0x00000080 +#define SPR_DMR1_CW3 (SPR_DMR1_CW3_AND | SPR_DMR1_CW3_OR) +#define SPR_DMR1_CW4_AND 0x00000100 +#define SPR_DMR1_CW4_OR 0x00000200 +#define SPR_DMR1_CW4 (SPR_DMR1_CW4_AND | SPR_DMR1_CW4_OR) +#define SPR_DMR1_CW5_AND 0x00000400 +#define SPR_DMR1_CW5_OR 0x00000800 +#define SPR_DMR1_CW5 (SPR_DMR1_CW5_AND | SPR_DMR1_CW5_OR) +#define SPR_DMR1_CW6_AND 0x00001000 +#define SPR_DMR1_CW6_OR 0x00002000 +#define SPR_DMR1_CW6 (SPR_DMR1_CW6_AND | SPR_DMR1_CW6_OR) +#define SPR_DMR1_CW7_AND 0x00004000 +#define SPR_DMR1_CW7_OR 0x00008000 +#define SPR_DMR1_CW7 (SPR_DMR1_CW7_AND | SPR_DMR1_CW7_OR) +#define SPR_DMR1_CW8_AND 0x00010000 +#define SPR_DMR1_CW8_OR 0x00020000 +#define SPR_DMR1_CW8 (SPR_DMR1_CW8_AND | SPR_DMR1_CW8_OR) +#define SPR_DMR1_CW9_AND 0x00040000 +#define SPR_DMR1_CW9_OR 0x00080000 +#define SPR_DMR1_CW9 (SPR_DMR1_CW9_AND | SPR_DMR1_CW9_OR) +#define SPR_DMR1_RES1 0x00300000 /* Reserved */ +#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/ +#define SPR_DMR1_BT 0x00800000 /* Branch trace */ +#define SPR_DMR1_RES2 0xff000000 /* Reserved */ + +/* + * Bit definitions for Debug Mode 2 register. AWTC and WGB corrected by JPB + * + */ +#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */ +#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */ +#define SPR_DMR2_AWTC 0x00000ffc /* Assign watchpoints to counters */ +#define SPR_DMR2_AWTC_OFF 2 /* Bit offset to AWTC field */ +#define SPR_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */ +#define SPR_DMR2_WGB_OFF 12 /* Bit offset to WGB field */ +#define SPR_DMR2_WBS 0xffc00000 /* JPB: Watchpoint status */ +#define SPR_DMR2_WBS_OFF 22 /* Bit offset to WBS field */ + +/* + * Bit definitions for Debug watchpoint counter registers + * + */ +#define SPR_DWCR_COUNT 0x0000ffff /* Count */ +#define SPR_DWCR_MATCH 0xffff0000 /* Match */ +#define SPR_DWCR_MATCH_OFF 16 /* Match bit offset */ + +/* + * Bit definitions for Debug stop register + * + */ +#define SPR_DSR_RSTE 0x00000001 /* Reset exception */ +#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */ +#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */ +#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */ +#define SPR_DSR_TTE 0x00000010 /* Tick Timer exception */ +#define SPR_DSR_AE 0x00000020 /* Alignment exception */ +#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */ +#define SPR_DSR_IE 0x00000080 /* Interrupt exception */ +#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */ +#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */ +#define SPR_DSR_RE 0x00000400 /* Range exception */ +#define SPR_DSR_SCE 0x00000800 /* System call exception */ +#define SPR_DSR_FPE 0x00001000 /* Floating point Exception */ +#define SPR_DSR_TE 0x00002000 /* Trap exception */ + +/* + * Bit definitions for Debug reason register + * + */ +#define SPR_DRR_RSTE 0x00000001 /* Reset exception */ +#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */ +#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */ +#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */ +#define SPR_DRR_TTE 0x00000010 /* Tick Timer exception */ +#define SPR_DRR_AE 0x00000020 /* Alignment exception */ +#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */ +#define SPR_DRR_IE 0x00000080 /* Interrupt exception */ +#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */ +#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */ +#define SPR_DRR_RE 0x00000400 /* Range exception */ +#define SPR_DRR_SCE 0x00000800 /* System call exception */ +#define SPR_DRR_FPE 0x00001000 /* Floating point exception */ +#define SPR_DRR_TE 0x00002000 /* Trap exception */ + +/* + * Bit definitions for Performance counters mode registers + * + */ +#define SPR_PCMR_CP 0x00000001 /* Counter present */ +#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */ +#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */ +#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */ +#define SPR_PCMR_LA 0x00000010 /* Load access event */ +#define SPR_PCMR_SA 0x00000020 /* Store access event */ +#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/ +#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */ +#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */ +#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */ +#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */ +#define SPR_PCMR_BS 0x00000800 /* Branch stall event */ +#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */ +#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */ +#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */ +#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */ + +/* + * Bit definitions for the Power management register + * + */ +#define SPR_PMR_SDF 0x0000000f /* Slow down factor */ +#define SPR_PMR_DME 0x00000010 /* Doze mode enable */ +#define SPR_PMR_SME 0x00000020 /* Sleep mode enable */ +#define SPR_PMR_DCGE 0x00000040 /* Dynamic clock gating enable */ +#define SPR_PMR_SUME 0x00000080 /* Suspend mode enable */ + +/* + * Bit definitions for PICMR + * + */ +#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */ + +/* + * Bit definitions for PICPR + * + */ +#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */ + +/* + * Bit definitions for PICSR + * + */ +#define SPR_PICSR_IS 0xffffffff /* Interrupt status */ + +/* + * Bit definitions for Tick Timer Control Register + * + */ +#define SPR_TTCR_PERIOD 0x0fffffff /* Time Period */ +#define SPR_TTMR_PERIOD SPR_TTCR_PERIOD +#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */ +#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */ +#define SPR_TTMR_RT 0x40000000 /* Restart tick */ +#define SPR_TTMR_SR 0x80000000 /* Single run */ +#define SPR_TTMR_CR 0xc0000000 /* Continuous run */ +#define SPR_TTMR_M 0xc0000000 /* Tick mode */ + +/* + * l.nop constants + * + */ +#define NOP_NOP 0x0000 /* Normal nop instruction */ +#define NOP_EXIT 0x0001 /* End of simulation */ +#define NOP_REPORT 0x0002 /* Simple report */ +#define NOP_PRINTF 0x0003 /* Simprintf instruction */ +#define NOP_PUTC 0x0004 /* JPB: Simputc instruction */ +#define NOP_CNT_RESET 0x0005 /* Reset statistics counters */ +#define NOP_REPORT_FIRST 0x0400 /* Report with number */ +#define NOP_REPORT_LAST 0x03ff /* Report with number */ + +#endif /* SPR_DEFS__H */ Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/except.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/except.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/except.h (revision 66) @@ -0,0 +1,52 @@ +/* except.h -- OR1K architecture specific exceptions + +Copyright (C) 1999 Damjan Lampret, lampret@opencores.org +Copyright (C) 2008 Embecosm Limited + +Contributor Jeremy Bennett + +This file is part of Or1ksim, the 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 3 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, see . +*/ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef EXCEPT__H +#define EXCEPT__H + + +/* Package includes */ +//#include "arch.h" + +/* Definition of OR1K exceptions */ +#define EXCEPT_NONE 0x0000 +#define EXCEPT_RESET 0x0100 +#define EXCEPT_BUSERR 0x0200 +#define EXCEPT_DPF 0x0300 +#define EXCEPT_IPF 0x0400 +#define EXCEPT_TICK 0x0500 +#define EXCEPT_ALIGN 0x0600 +#define EXCEPT_ILLEGAL 0x0700 +#define EXCEPT_INT 0x0800 +#define EXCEPT_DTLBMISS 0x0900 +#define EXCEPT_ITLBMISS 0x0a00 +#define EXCEPT_RANGE 0x0b00 +#define EXCEPT_SYSCALL 0x0c00 +#define EXCEPT_FPE 0x0d00 +#define EXCEPT_TRAP 0x0e00 + +#endif /* EXCEPT__H */ Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/gdb-6.8-bz436037-reg-no-longer-active.patch =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/gdb-6.8-bz436037-reg-no-longer-active.patch (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/gdb-6.8-bz436037-reg-no-longer-active.patch (revision 66) @@ -0,0 +1,24 @@ +diff -d -urpN src.0/gdb/valops.c src.1/gdb/valops.c +--- src.0/gdb/valops.c 2008-07-27 04:00:03.000000000 +0200 ++++ src.1/gdb/valops.c 2008-07-31 15:17:42.000000000 +0200 +@@ -813,10 +813,18 @@ value_assign (struct value *toval, struc + struct frame_info *frame; + int value_reg; + +- /* Figure out which frame this is in currently. */ +- frame = frame_find_by_id (VALUE_FRAME_ID (toval)); + value_reg = VALUE_REGNUM (toval); + ++ /* Figure out which frame this is in currently. */ ++ frame = frame_find_by_id (VALUE_FRAME_ID (toval)); ++ /* "set $reg+=1" should work on programs with no debug info, ++ but frame_find_by_id returns NULL here (RH bug 436037). ++ Use current frame, it represents CPU state in this case. ++ If frame_find_by_id is changed to do it internally ++ (it is contemplated there), remove this. */ ++ if (!frame) ++ frame = get_current_frame (); ++ /* Probably never happens. */ + if (!frame) + error (_("Value being assigned to is no longer active.")); + Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/rsp-server.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/rsp-server.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/rsp-server.h (revision 66) @@ -0,0 +1,36 @@ +/* rsp-server.c -- Remote Serial Protocol server for GDB + +Copyright (C) 2008 Embecosm Limited + +Contributor Jeremy Bennett + +This file was part of Or1ksim, the OpenRISC 1000 Architectural Simulator. +Was actually purchased by Mom when I decided it was nice, but not affordable after two other recent pen purchases. + +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 3 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, see . +*/ + +/* This program is commented throughout in a fashion suitable for processing + with Doxygen. */ + + +#ifndef RSP_SERVER__H +#define RSP_SERVER__H + + +/* Function prototypes for external use */ +void rsp_init (int portNum); +int handle_rsp (void); // returns 1 normally, 0 for an unrecoverable error + +#endif /* RSP_SERVER__H */ Index: tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/altera_virtual_jtag.h =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/altera_virtual_jtag.h (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/adv_jtag_bridge/altera_virtual_jtag.h (revision 66) @@ -0,0 +1,19 @@ +#ifndef _ALTERA_VIRTUAL_JTAG_H_ +#define _ALTERA_VIRTUAL_JTAG_H_ + +// Contains constants relevant to the Altera Virtual JTAG +// device, which are not included in the BSDL. +// As of this writing, these are constant across every +// device which supports virtual JTAG. + +// These are commands for the FPGA's IR +#define ALTERA_CYCLONE_CMD_VIR 0x0E +#define ALTERA_CYCLONE_CMD_VDR 0x0C + +// These defines are for the virtual IR (not the FPGA's) +// The virtual TAP was defined in hardware to match the OpenCores native +// TAP in both IR size and DEBUG command. +#define ALT_VJTAG_IR_SIZE 4 +#define ALT_VJTAG_CMD_DEBUG 0x8 + +#endif Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/AdvancedWatchpointControl.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/AdvancedWatchpointControl.jar =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/AdvancedWatchpointControl.jar (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/AdvancedWatchpointControl.jar (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/AdvancedWatchpointControl.jar Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/AdvancedWatchpointControl.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/AdvancedWatchpointControl.pdf =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/AdvancedWatchpointControl.pdf (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/AdvancedWatchpointControl.pdf (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/AdvancedWatchpointControl.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/AdvancedWatchpointControl.odt =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/AdvancedWatchpointControl.odt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/AdvancedWatchpointControl.odt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/AdvancedWatchpointControl.odt (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/AdvancedWatchpointControl.odt Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_serverconnection.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_serverconnection.png =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_serverconnection.png (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_serverconnection.png (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_serverconnection.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_block_diagram.odg =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_block_diagram.odg =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_block_diagram.odg (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_block_diagram.odg (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_block_diagram.odg Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_countersubgroup.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_countersubgroup.png =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_countersubgroup.png (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_countersubgroup.png (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_countersubgroup.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_wpsubgroup.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_wpsubgroup.png =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_wpsubgroup.png (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_wpsubgroup.png (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_wpsubgroup.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_controlgroup.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_controlgroup.png =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_controlgroup.png (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_controlgroup.png (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_controlgroup.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_full.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_full.png =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_full.png (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_full.png (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/src/awc_ui_full.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/EPL-v1.0.txt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/EPL-v1.0.txt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/EPL-v1.0.txt (revision 66) @@ -0,0 +1,84 @@ +Eclipse Public License - v 1.0 + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and + b) in the case of each subsequent Contributor: + + i)changes to the Program, and + + ii)additions to the Program; + + where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor’s behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient’s responsibility to acquire that license before distributing the Program. + +d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and + + iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within the Program. + +Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor’s responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient’s patent(s), then such Recipient’s rights granted under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient’s rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient’s rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient’s obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/License_FDL-1.2.txt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/License_FDL-1.2.txt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/License_FDL-1.2.txt (revision 66) @@ -0,0 +1,397 @@ + GNU Free Documentation License + Version 1.2, November 2002 + + + Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (Thus, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/gpl-2.0.txt =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/gpl-2.0.txt (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/doc/gpl-2.0.txt (revision 66) @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/registerInterpreter.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/registerInterpreter.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/registerInterpreter.java (revision 66) @@ -0,0 +1,411 @@ +//////////////////////////////////////////////////////////////// +// +// registerInterpreter.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class wraps the basic register set cache. It adds +// convenience methods so that the UI classes do not need to +// interpret the various bit meanings in the registers. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + + +public class registerInterpreter { + + public enum compareSource { DISABLED, INSTR_FETCH_ADDR, LOAD_ADDR, STORE_ADDR, LOAD_DATA, STORE_DATA, + LOAD_STORE_ADDR, LOAD_STORE_DATA } + public enum compareType { MASKED, EQ, LT, LE, GT, GE, NE } + public enum chainType { NONE, AND, OR } + + private targetDebugRegisterSet registers; + + public registerInterpreter(targetDebugRegisterSet regs) { + registers = regs; + } + + + public boolean isWPImplemented(int whichWP) { + long exists = registers.getDCR(whichWP) & 0x1; + if(exists != 0) return true; + else return false; + } + + public boolean getWPBreakEnabled(int whichWP) { + long enabled = (registers.getDMR2() >> (12+whichWP)) & 0x1; + if(enabled != 0) return true; + else return false; + } + + public void setWPBreakEnabled(int whichWP, boolean enabled) { + long maskval = 0x1 << (12+whichWP); + if(enabled) { + registers.setDMR2(registers.getDMR2() | maskval); + } + else { + registers.setDMR2(registers.getDMR2() & (~maskval)); + } + } + + public compareSource getWPCompareSource(int whichWP) { + int src = (int)((registers.getDCR(whichWP) >> 5) & 0x7); + compareSource ret = compareSource.DISABLED; + switch(src) { + case 0: + ret = compareSource.DISABLED; + break; + case 1: + ret = compareSource.INSTR_FETCH_ADDR; + break; + case 2: + ret = compareSource.LOAD_ADDR; + break; + case 3: + ret = compareSource.STORE_ADDR; + break; + case 4: + ret = compareSource.LOAD_DATA; + break; + case 5: + ret = compareSource.STORE_DATA; + break; + case 6: + ret = compareSource.LOAD_STORE_ADDR; + break; + case 7: + ret = compareSource.LOAD_STORE_DATA; + break; + } + return ret; + } + + public void setWPCompareSource(int whichWP, compareSource src) { + long val = 0; + switch(src) { + case DISABLED: + val = 0; + break; + case INSTR_FETCH_ADDR: + val = 1; + break; + case LOAD_ADDR: + val = 2; + break; + case STORE_ADDR: + val = 3; + break; + case LOAD_DATA: + val = 4; + break; + case STORE_DATA: + val = 5; + break; + case LOAD_STORE_ADDR: + val = 6; + break; + case LOAD_STORE_DATA: + val = 7; + break; + } + val = val << 5; + long mask = 7 << 5; + long tmp = registers.getDCR(whichWP); + tmp &= (~mask); + tmp |= val; + registers.setDCR(whichWP, tmp); + } + + public compareType getWPCompareType(int whichWP) { + int src = (int)((registers.getDCR(whichWP) >> 1) & 0x7); + compareType ret = compareType.MASKED; + switch(src) { + case 0: + ret = compareType.MASKED; + break; + case 1: + ret = compareType.EQ; + break; + case 2: + ret = compareType.LT; + break; + case 3: + ret = compareType.LE; + break; + case 4: + ret = compareType.GT; + break; + case 5: + ret = compareType.GE; + break; + case 6: + ret = compareType.NE; + break; + } + return ret; + } + + public void setWPCompareType(int whichWP, compareType type) { + long val = 0; + switch(type) { + case MASKED: + val = 0; + break; + case EQ: + val = 1; + break; + case LT: + val = 2; + break; + case LE: + val = 3; + break; + case GT: + val = 4; + break; + case GE: + val = 5; + break; + case NE: + val = 6; + break; + + } + val = val << 1; + long mask = 7 << 1; + long tmp = registers.getDCR(whichWP); + tmp &= (~mask); + tmp |= val; + registers.setDCR(whichWP, tmp); + } + + public boolean getWPSignedCompare(int whichWP) { + long enabled = registers.getDCR(whichWP) & 0x10; + if(enabled != 0) return true; + else return false; + } + + public void setWPSignedCompare(int whichWP, boolean signed) { + long maskval = 0x10; + long tmp = registers.getDCR(whichWP); + if(signed) tmp |= maskval; + else tmp &= (~maskval); + registers.setDCR(whichWP, tmp); + } + + public chainType getWPChainType(int whichWP) { + int src = (int)((registers.getDMR1() >> (2*whichWP)) & 0x3); + chainType ret = chainType.NONE; + switch(src) { + case 0: + ret = chainType.NONE; + break; + case 1: + ret = chainType.AND; + break; + case 2: + ret = chainType.OR; + break; + } + return ret; + } + + public void setWPChainType(int whichWP, chainType type) { + long val = 0; + switch(type) { + case NONE: + val = 0; + break; + case AND: + val = 1; + break; + case OR: + val = 2; + break; + } + val = val << (2*whichWP); + long mask = 3 << (2*whichWP); + long tmp = registers.getDMR1() & (~mask); + tmp |= val; + registers.setDMR1(tmp); + } + + public int getWPCounterAssign(int whichWP) { + int val = (int)((registers.getDMR2() >> (2 + whichWP)) & 0x1); + return val; + } + + // Note that for this method, indexes 8 and 9 are valid + // (they indicate counter 0 and counter 1, respectively). + public void setWPCounterAssign(int whichWP, int counter) { + long val = (counter & 0x1) << (2+whichWP); + long mask = 0x1 << (2+whichWP); + long tmp = registers.getDMR2(); + tmp &= (~mask); + tmp |= val; + registers.setDMR2(tmp); + } + + public boolean didWPCauseBreak(int whichWP) { + int val = (int)((registers.getDMR2() >> (22+whichWP)) & 0x1); + if(val == 0) return false; + else return true; + } + + public boolean getCounterEnabled(int whichCounter) { + int enabled = (int)((registers.getDMR2() >> (whichCounter&0x1)) & 0x1); + if(enabled != 0) return true; + else return false; + } + + + public void setCounterEnabled(int whichCounter, boolean enabled) { + long maskval = 0x1 << (whichCounter & 0x1); + long tmp = registers.getDMR2(); + if(enabled) tmp |= maskval; + else tmp &= (~maskval); + registers.setDMR2(tmp); + } + + + public boolean getCounterBreakEnabled(int whichCounter) { + int enabled = (int)((registers.getDMR2() >> (20+whichCounter)) & 0x1); + if(enabled != 0) return true; + else return false; + } + + + public void setCounterBreakEnabled(int whichCounter, boolean enabled) { + long maskval = 0x1 << (20+whichCounter); + long tmp = registers.getDMR2(); + if(enabled) tmp |= maskval; + else tmp &= (~maskval); + registers.setDMR2(tmp); + } + + public boolean didCounterCauseBreak(int whichCounter) { + int val = (int)((registers.getDMR2() >> (30+whichCounter)) & 0x1); + if(val == 0) return false; + else return true; + } + + public int getCounterWatchValue(int whichCounter) { + int val = 0; + if(whichCounter == 0) val = (int)((registers.getDWCR0() >> 16) & 0xFFFF); + else val = (int)((registers.getDWCR1() >> 16) & 0xFFFF); + return val; + } + + public void setCounterWatchValue(int whichCounter, int value) { + long val = (value & 0xFFFF) << 16; + long mask = 0x0000FFFF; + long tmp; + if(whichCounter == 0) { + tmp = registers.getDWCR0(); + tmp &= mask; + tmp |= val; + registers.setDWCR0(tmp); + } else { + tmp = registers.getDWCR1(); + tmp &= mask; + tmp |= val; + registers.setDWCR1(tmp); + } + } + + public int getCounterCountValue(int whichCounter) { + int val = 0; + if(whichCounter == 0) val = (int)(registers.getDWCR0() & 0xFFFF); + else val = (int)(registers.getDWCR1() & 0xFFFF); + return val; + } + + public void setCounterCountValue(int whichCounter, int value) { + long val = value & 0xFFFF; + long mask = 0xFFFF0000; + long tmp; + if(whichCounter == 0) { + tmp = registers.getDWCR0(); + tmp &= mask; + tmp |= val; + registers.setDWCR0(tmp); + } else { + tmp = registers.getDWCR1(); + tmp &= mask; + tmp |= val; + registers.setDWCR1(tmp); + } + } + + + public chainType getCounterChainType(int whichCounter) { + int src = (int)((registers.getDMR1() >> (16+(2*whichCounter))) & 0x3); + chainType ret = chainType.NONE; + switch(src) { + case 0: + ret = chainType.NONE; + break; + case 1: + ret = chainType.AND; + break; + case 2: + ret = chainType.OR; + break; + } + return ret; + } + + public void setCounterChainType(int whichCounter, chainType type) { + long val = 0; + switch(type) { + case NONE: + val = 0; + break; + case AND: + val = 1; + break; + case OR: + val = 2; + break; + } + val = val << (16+(2*whichCounter)); + long mask = 3 << (16+(2*whichCounter)); + long tmp = registers.getDMR1(); + tmp &= (~mask); + tmp |= val; + registers.setDMR1(tmp); + } + + public void setDVR(int which, long val) { + registers.setDVR(which, val); + } + + public long getDVR(int which) { + return registers.getDVR(which); + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiControlGroup.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiControlGroup.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiControlGroup.java (revision 66) @@ -0,0 +1,125 @@ +//////////////////////////////////////////////////////////////// +// +// guiControlGroup.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class holds the GUI elements for the control group, +// which includes the read and write button, along with the +// message output window. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import java.text.SimpleDateFormat; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; + +public class guiControlGroup implements LogMessageObserver { + + private Group miscGroup = null; + private Button applyButton = null; + private Button rereadButton = null; + private Group messagesGroup = null; + private Text notifyMessageLabel = null; + private mainControl mCtrl = null; + + public guiControlGroup(Composite parent, mainControl mc) { + mCtrl = mc; + GridLayout gridLayout2 = new GridLayout(); + gridLayout2.numColumns = 2; + gridLayout2.horizontalSpacing = 10; + gridLayout2.makeColumnsEqualWidth = false; + miscGroup = new Group(parent, SWT.NONE); + miscGroup.setText("Control"); + applyButton = new Button(miscGroup, SWT.NONE); + applyButton.setText("Write Registers"); + applyButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { + public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { + mCtrl.doWriteAllRegisters(); + } + }); + createMessagesGroup(); + rereadButton = new Button(miscGroup, SWT.NONE); + rereadButton.setText("Read Registers"); + rereadButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { + public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { + mCtrl.doReadAllRegisters(); + } + }); + miscGroup.setLayout(gridLayout2); + mCtrl.registerForLogMessages(this); + } + + + private void createMessagesGroup() { + GridData gridData6 = new GridData(); + gridData6.verticalSpan = 2; + gridData6.grabExcessHorizontalSpace = true; + gridData6.horizontalAlignment = GridData.FILL; + gridData6.verticalAlignment = GridData.FILL; + gridData6.grabExcessVerticalSpace = true; + messagesGroup = new Group(miscGroup, SWT.NONE); + messagesGroup.setLayout(new GridLayout()); + messagesGroup.setLayoutData(gridData6); + messagesGroup.setText("Messages"); + + notifyMessageLabel = new Text(messagesGroup, SWT.MULTI|SWT.READ_ONLY); + java.util.Date today = new java.util.Date(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS "); + notifyMessageLabel.setText(sdf.format(today) + "Ready"); + + int columns = 100; + int rows = 4; + GC gc = new GC (notifyMessageLabel); + FontMetrics fm = gc.getFontMetrics (); + int width = columns * fm.getAverageCharWidth (); + int height = rows * fm.getHeight (); + gc.dispose (); + + gridData6 = new GridData(); + gridData6.widthHint = width; + gridData6.heightHint = height; + notifyMessageLabel.setLayoutData(gridData6); + } + + public void notifyLogMessage() { + String msg = mCtrl.getLogMessage(); + java.util.Date today = new java.util.Date(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS "); + notifyMessageLabel.append("\n" + sdf.format(today) + msg); + System.out.print(sdf.format(today) + msg + "\n"); + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/NetworkStatusObserver.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/NetworkStatusObserver.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/NetworkStatusObserver.java (revision 66) @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////////// +// +// NetworkStatusObserver.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This interface is implemented by classes that wish to +// register to be notified when the network status changes. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +public interface NetworkStatusObserver { + public void notifyNetworkStatus(); +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/WriteRegisterTransaction.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/WriteRegisterTransaction.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/WriteRegisterTransaction.java (revision 66) @@ -0,0 +1,83 @@ +//////////////////////////////////////////////////////////////// +// +// WriteRegisterTransaction.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class defines a transaction object which is passed to +// the RSP coder in order to perform a register write +// transaction. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// + +package advancedWatchpointControl; + + +public class WriteRegisterTransaction implements TargetTransaction { + + private String packetString = null; + + public WriteRegisterTransaction(targetDebugRegisterSet.regType reg, long val) { + packetString = new String("P"); // 'P' is write one register + int regAddr = targetDebugRegisterSet.getRegisterAddress(reg); + + packetString += Integer.toHexString(regAddr); + packetString += "="; + + String valueStr = Long.toHexString(val); + + // There must be 8 bytes of 'value' + if(valueStr.length() > 8) { + // Use the last 8 bytes, the first 8 may just be a sign extension + valueStr = valueStr.substring(valueStr.length() - 8, valueStr.length()); + } + + int padsize = 8 - valueStr.length(); + for(int i = 0; i < padsize; i++) { + packetString += '0'; + } + + packetString += valueStr; + } + + @Override + public String getDataToSend() { + return packetString; + } + + @Override + public boolean receivePacket(String pkt) { + + // Only one valid response from a register write: "OK" + if(pkt.charAt(0) == 'O' && pkt.charAt(1) == 'K') { + return true; + } + + return false; + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/AdvancedWatchpointControl.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/AdvancedWatchpointControl.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/AdvancedWatchpointControl.java (revision 66) @@ -0,0 +1,117 @@ +//////////////////////////////////////////////////////////////// +// +// AdvancedWatchpointControl.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This is the main class in the AdvancedWatchpointControl +// program. It creates all the worker classes, then passes +// control off to the SWT to listen for events. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.RowLayout; + + + +public class AdvancedWatchpointControl { + + private static Display mainDisplay = null; + private static Shell mainShell = null; + private static guiServerGroup gServerGroup = null; + private static guiDCRGroup gDCRGroup = null; + private static guiCountRegsGroup gCountGroup = null; + private static guiControlGroup gControlGroup = null; + private static mainControl mCtrl = null; + private static ScrolledComposite mainSC = null; + private static Composite mainComposite = null; + + /** + * This method initializes mainShell + * + */ + private static void createMainShell(Display disp, mainControl mc) { + RowLayout mainLayout = new RowLayout(); + mainLayout.center = true; + mainLayout.fill = true; + mainLayout.spacing = 5; + mainLayout.wrap = false; + mainLayout.pack = true; + mainLayout.type = SWT.VERTICAL; + + mainShell = new Shell(); + mainShell.setText("Advanced Watchpoint Control"); + mainShell.setLayout(new FillLayout()); + + mainSC = new ScrolledComposite(mainShell, SWT.H_SCROLL|SWT.V_SCROLL); + mainComposite = new Composite(mainSC, SWT.NONE); + mainComposite.setLayout(mainLayout); + + gServerGroup = new guiServerGroup(mainComposite, mc); + gDCRGroup = new guiDCRGroup(mainComposite, mainDisplay, mc); + gCountGroup = new guiCountRegsGroup(mainComposite, mainDisplay, mc); + gControlGroup = new guiControlGroup(mainComposite, mc); + + mainSC.setContent(mainComposite); + // Set the minimum size + mainSC.setMinSize(770, 950); + // Expand both horizontally and vertically + mainSC.setExpandHorizontal(true); + mainSC.setExpandVertical(true); + } + + + /** + * @param args + */ + public static void main(String[] args) { + + // Create the main control. + // This also creates the network and RSP subsystems + mCtrl = new mainControl(); + + // Create the GUI. Must be done after main control creation. + mainDisplay = new Display(); + createMainShell(mainDisplay, mCtrl); + + // All ready, show the UI + mainShell.pack(); + mainShell.open(); + while (!mainShell.isDisposed()) { + if (!mainDisplay.readAndDispatch()) mainDisplay.sleep(); + } + mainDisplay.dispose(); + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/targetDebugRegisterSet.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/targetDebugRegisterSet.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/targetDebugRegisterSet.java (revision 66) @@ -0,0 +1,173 @@ +//////////////////////////////////////////////////////////////// +// +// targetDebugRegisterSet.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class holds a direct, cached copy of the debug registers +// on the OR1000 target CPU. It relies on other classes to +// interpret the meanings of the values. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +public class targetDebugRegisterSet { + + public enum regType { DCR0, DVR0, DCR1, DVR1, DCR2, DVR2, DCR3, DVR3, + DCR4, DVR4, DCR5, DVR5, DCR6, DVR6, DCR7, DVR7, DMR1, DMR2, DWCR0, DWCR1 } + + // These reflect the values of the registers on the target + // They must be 'long's, because they're unsigned ints. + private long dcr[] = { 1, 1, 0, 0, 1, 1, 1, 1 }; + private long dvr[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + private long dmr1 = 0; + private long dmr2 = 0; + private long dwcr0 = 0; + private long dwcr1 = 0; + + + public void setDCR(int which, long val) { + dcr[which] = val; + } + + public long getDCR(int which) { + return dcr[which]; + } + + public void setDVR(int which, long val) { + dvr[which] = val; + } + + public long getDVR(int which) { + return dvr[which]; + } + + public void setDMR1(long val) { + dmr1 = val; + } + + public long getDMR1() { + return dmr1; + } + + public void setDMR2(long val) { + dmr2 = val; + } + + public long getDMR2() { + return dmr2; + } + + public void setDWCR0(long val) { + dwcr0 = val; + } + + public long getDWCR0() { + return dwcr0; + } + + public void setDWCR1(long val) { + dwcr1 = val; + } + + public long getDWCR1() { + return dwcr1; + } + + public static int getRegisterAddress(regType reg) { + int retval = 0; + int dgroup = 6 << 11; // DEBUG group is 6, 11 bits is the group offset + + switch(reg) { + case DCR0: + retval = dgroup | 8; + break; + case DVR0: + retval = dgroup | 0; + break; + case DCR1: + retval = dgroup | 9; + break; + case DVR1: + retval = dgroup | 1; + break; + case DCR2: + retval = dgroup | 10; + break; + case DVR2: + retval = dgroup | 2; + break; + case DCR3: + retval = dgroup | 11; + break; + case DVR3: + retval = dgroup | 3; + break; + case DCR4: + retval = dgroup | 12; + break; + case DVR4: + retval = dgroup | 4; + break; + case DCR5: + retval = dgroup | 13; + break; + case DVR5: + retval = dgroup | 5; + break; + case DCR6: + retval = dgroup | 14; + break; + case DVR6: + retval = dgroup | 6; + break; + case DCR7: + retval = dgroup | 15; + break; + case DVR7: + retval = dgroup | 7; + break; + case DMR1: + retval = dgroup | 16; + break; + case DMR2: + retval = dgroup | 17; + break; + case DWCR0: + retval = dgroup | 18; + break; + case DWCR1: + retval = dgroup | 19; + break; + default: + break; // Register address 0 is the version register...read-only and harmless. + } + + return retval; + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/rspCoder.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/rspCoder.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/rspCoder.java (revision 66) @@ -0,0 +1,242 @@ +//////////////////////////////////////////////////////////////// +// +// rspCoder.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class handles formatting, escaping, and checksumming +// for packets sent to and received from the network layer. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import java.io.IOException; + + +public class rspCoder { + + + + public enum rcvStateType { WAITING_FOR_START, RECEIVING_DATA, RECEIVING_CSUM1, + RECEIVING_CSUM2, FINISHED } + + private networkSystem netSys = null; + private rcvStateType rcvState = rcvStateType.WAITING_FOR_START; + private StringBuilder rcvPacketStringBuilder = null; + + public rspCoder(networkSystem ns) { + rcvPacketStringBuilder = new StringBuilder(); + netSys = ns; + } + + public void Transact(TargetTransaction t) throws IOException { + int retries_remaining = 3; + int rcvchar; + boolean ret = false; + + // Send the packet and look for an RSP ack ("+") + do { + escapePacketAndSend(t.getDataToSend()); + rcvchar = netSys.getChar(); // Get +/- + // If -, retry up to 3 times + } while((rcvchar != '+') && ((retries_remaining--) >= 0)); + + if(retries_remaining < 0) { + throw new IOException("Retries exceeded sending data"); + } + + retries_remaining = 3; + + do { + ret = false; + // Get one complete packet + String dataPacket = getDataPacket(); + // Unescape, un-RLE, and test the checksum. Returns null if bad checksum + String decodedPacket = decodeRSPPacket(dataPacket); + if(decodedPacket != null) { + // Let the transaction object parse the specific packet type + ret = t.receivePacket(decodedPacket); + } + if(!ret) { + sendNak(); + } + + } while ((!ret)&& ((retries_remaining--) >= 0)); + + if(retries_remaining < 0) { + throw new IOException("Retries exceeded parsing data"); + } + + sendAck(); + + } // Transact() + + + private boolean escapePacketAndSend(String packetString) { + //System.out.println("Sending packet: \"" + packetString + "\""); + String protocolString = new String("$"); + + // Escape the packet data. '}' is 0x7d, the escape char. + // Escaped char must be XOR'd with 0x20. + packetString.replace("}", "}"+('}'^0x20)); // This must be escaped first! + packetString.replace("#", "}"+('#'^0x20)); // '#' is 0x23 + packetString.replace("$", "}"+('$'^0x20)); // '$' is 0x24 + + // Add the packet data + protocolString += packetString; + + // Add the separator + protocolString += "#"; + + // Create the checksum (from packetString, not protocolString) + int checksum = getChecksum(packetString); + + // Add the checksum + if(checksum < 0x10) + protocolString += "0"; + protocolString += Integer.toHexString(checksum); + + // Send it. + return netSys.sendData(protocolString); + } + + + // This reads one complete data packet from the network, including checksum + public String getDataPacket() throws IOException { + int rcvChar; + rcvState = rcvStateType.WAITING_FOR_START; + + do { + rcvChar = netSys.getChar(); + //System.out.println("parseData: " + rcvChar); + switch(rcvState) { + case WAITING_FOR_START: + if(rcvChar == '$') { + // discard the '$' character + rcvState = rcvStateType.RECEIVING_DATA; + rcvPacketStringBuilder = new StringBuilder(); + } + break; + case RECEIVING_DATA: + if(rcvChar == '#') { + rcvState = rcvStateType.RECEIVING_CSUM1; + } + rcvPacketStringBuilder.append((char)rcvChar); + break; + case RECEIVING_CSUM1: + rcvPacketStringBuilder.append((char)rcvChar); + rcvState = rcvStateType.RECEIVING_CSUM2; + break; + case RECEIVING_CSUM2: + rcvPacketStringBuilder.append((char)rcvChar); + rcvState = rcvStateType.FINISHED; + break; + } + } while(rcvState != rcvStateType.FINISHED); + + return rcvPacketStringBuilder.toString(); + } // parseData() + + + // This looks like it modifies the input String. But since a String + // is actually constant, a new String object should be created each + // time we "modify" the String, so the original input parameter + // should remain intact. + private String decodeRSPPacket(String packet) { + + //System.out.println("Parsing packet: \"" + packet + "\"\n"); + + // Test the checksum + int checksum = 0; + try { + //System.out.println("Checksum substring: " + packet.substring(packet.length()-2)); + checksum = Integer.parseInt(packet.substring(packet.length()-2), 16); + } catch (NumberFormatException e) { + // TODO Log the error + sendNak(); + System.out.println("Got bad checksum: calculated " + getChecksum(packet) + ", read " + checksum); + return null; + } + // Cut off the '#' and checksum + packet = packet.substring(0, packet.length()-3); + + if(checksum != getChecksum(packet)) { + // TODO Log the error + sendNak(); + System.out.println("Got bad checksum: calculated " + getChecksum(packet) + ", read " + checksum); + return null; + } + + // Un-escape + packet.replace("}"+('#'^0x20), "#"); + packet.replace("}"+('$'^0x20), "$"); + packet.replace("}"+('}'^0x20), "}"); + + // Undo any run-length encoding. This code is so ugly. + if(packet.indexOf("*") != -1) { + StringBuffer sb = new StringBuffer(packet); + int thisIndex = 0; + int lastIndex = 0; + + while(-1 != (thisIndex = sb.indexOf("*", lastIndex))) { + int runlength = sb.charAt(thisIndex+1) - 28; + sb.deleteCharAt(thisIndex+1); + sb.deleteCharAt(thisIndex); + char c = sb.charAt(thisIndex-1); + for(int i = 0; i < runlength; i++) { + sb.insert(thisIndex, c); + } + lastIndex = thisIndex; + } + + packet = sb.toString(); + } + + return packet; + } // handleRSPPacket() + + + public void sendAck() { + netSys.sendData("+"); + } + + public void sendNak() { + netSys.sendData("-"); + } + + + private int getChecksum(String packet) { + int csum = 0; + for(int i = 0; i < packet.length(); i++) { + csum += packet.charAt(i); + //System.out.println("checksum adding char: " + packet.charAt(i) + ", checksum " + csum); + } + csum = csum & 0xFF; + //System.out.println("Final checksum: " + csum); + return csum; + } +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/mainControl.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/mainControl.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/mainControl.java (revision 66) @@ -0,0 +1,235 @@ +//////////////////////////////////////////////////////////////// +// +// mainControl.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This is the central control in the program. It oversees +// the processes of reading and writing the target hardware. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + + +public class mainControl { + + public enum connectionStatus { NOT_CONNECTED, CONNECTING, CONNECTED, CONNECT_ERROR } + + private targetDebugRegisterSet regSet = null; + private networkSystem netSys = null; + private targetTransactor transactor = null; + private rspCoder rsp = null; + // Yes, there really need to have three different observer interfaces, + // in case a single UI class wants to be more than one. + private List registerObserverList = null; + private List networkStatusObserverList = null; + private List logmsgObserverList = null; + private String networkStatus = ""; + private String logMessage = ""; + + public mainControl() { + registerObserverList = new LinkedList(); + networkStatusObserverList = new LinkedList(); + logmsgObserverList = new LinkedList(); + regSet = new targetDebugRegisterSet(); // Create the object to hold the debug registers + netSys = new networkSystem(this); + rsp = new rspCoder(netSys); + transactor = new targetTransactor(rsp); + } + + public void setNetworkSystem(networkSystem ns) { + netSys = ns; + } + + public void registerForRegsetUpdates(RegisterObserver obs) { + registerObserverList.add(obs); + } + + public void registerForNetworkStatusUpdates(NetworkStatusObserver obs) { + networkStatusObserverList.add(obs); + } + + public void registerForLogMessages(LogMessageObserver obs) { + logmsgObserverList.add(obs); + } + + public targetDebugRegisterSet getRegSet() { + return regSet; + } + + public void doNetworkConnect(String serverHostname, int port) { + if(netSys != null) { + netSys.connect(serverHostname, port); + } + } + + public synchronized void doReadAllRegisters() { + try { // Any target interaction may throw an IOException. + + if(transactor.isTargetRunning()) { + setLogMessage("Cannot read registers while target is running"); + return; + } + + // get all (debug) registers (we use) from the target + regSet.setDCR(0, transactor.readRegister(targetDebugRegisterSet.regType.DCR0)); + regSet.setDCR(1, transactor.readRegister(targetDebugRegisterSet.regType.DCR1)); + regSet.setDCR(2, transactor.readRegister(targetDebugRegisterSet.regType.DCR2)); + regSet.setDCR(3, transactor.readRegister(targetDebugRegisterSet.regType.DCR3)); + regSet.setDCR(4, transactor.readRegister(targetDebugRegisterSet.regType.DCR4)); + regSet.setDCR(5, transactor.readRegister(targetDebugRegisterSet.regType.DCR5)); + regSet.setDCR(6, transactor.readRegister(targetDebugRegisterSet.regType.DCR6)); + regSet.setDCR(7, transactor.readRegister(targetDebugRegisterSet.regType.DCR7)); + regSet.setDVR(0, transactor.readRegister(targetDebugRegisterSet.regType.DVR0)); + regSet.setDVR(1, transactor.readRegister(targetDebugRegisterSet.regType.DVR1)); + regSet.setDVR(2, transactor.readRegister(targetDebugRegisterSet.regType.DVR2)); + regSet.setDVR(3, transactor.readRegister(targetDebugRegisterSet.regType.DVR3)); + regSet.setDVR(4, transactor.readRegister(targetDebugRegisterSet.regType.DVR4)); + regSet.setDVR(5, transactor.readRegister(targetDebugRegisterSet.regType.DVR5)); + regSet.setDVR(6, transactor.readRegister(targetDebugRegisterSet.regType.DVR6)); + regSet.setDVR(7, transactor.readRegister(targetDebugRegisterSet.regType.DVR7)); + regSet.setDWCR0(transactor.readRegister(targetDebugRegisterSet.regType.DWCR0)); + regSet.setDWCR1(transactor.readRegister(targetDebugRegisterSet.regType.DWCR1)); + regSet.setDMR1(transactor.readRegister(targetDebugRegisterSet.regType.DMR1)); + regSet.setDMR2(transactor.readRegister(targetDebugRegisterSet.regType.DMR2)); + } catch (IOException e) { + setLogMessage("Network error: " + e.getMessage()); + // *** TODO Disconnect?? Retry? + } + + // Notify observers to set GUI elements accordingly + try { + for(RegisterObserver obs : registerObserverList) { + obs.notifyRegisterUpdate(RegisterObserver.updateDirection.REGS_TO_GUI); + } + } catch(NumberFormatException e) { + // Since we're going long->String, this should never happen. + setLogMessage("Impossible exception while updating GUI!"); + } + } + + public synchronized void doWriteAllRegisters() { + + try { + + if(transactor.isTargetRunning()) { + setLogMessage("Cannot write registers while target is running"); + return; + } + + // Notify observers to set registers from GUI elements + try { + for(RegisterObserver obs : registerObserverList) { + obs.notifyRegisterUpdate(RegisterObserver.updateDirection.GUI_TO_REGS); + } + } catch (NumberFormatException e) { + // DVRs must be converted from Strings. This may fail and throw the exception. + setLogMessage("Illegal DVR value, registers not written"); + return; + } + + transactor.writeRegister(targetDebugRegisterSet.regType.DCR0, regSet.getDCR(0)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR1, regSet.getDCR(1)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR2, regSet.getDCR(2)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR3, regSet.getDCR(3)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR4, regSet.getDCR(4)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR5, regSet.getDCR(5)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR6, regSet.getDCR(6)); + transactor.writeRegister(targetDebugRegisterSet.regType.DCR7, regSet.getDCR(7)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR0, regSet.getDVR(0)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR1, regSet.getDVR(1)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR2, regSet.getDVR(2)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR3, regSet.getDVR(3)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR4, regSet.getDVR(4)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR5, regSet.getDVR(5)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR6, regSet.getDVR(6)); + transactor.writeRegister(targetDebugRegisterSet.regType.DVR7, regSet.getDVR(7)); + transactor.writeRegister(targetDebugRegisterSet.regType.DWCR0, regSet.getDWCR0()); + transactor.writeRegister(targetDebugRegisterSet.regType.DWCR1, regSet.getDWCR1()); + // Note that DMR2 must be written AFTER the DWCR registers. If + // DMR2 is written first, then the trap condition will be cleared, + // but it will still exist because count still equals match val + // in the DWCR. + transactor.writeRegister(targetDebugRegisterSet.regType.DMR1, regSet.getDMR1()); + transactor.writeRegister(targetDebugRegisterSet.regType.DMR2, regSet.getDMR2()); + } catch (IOException e) { + setLogMessage("Network error: " + e.getMessage()); + // TODO *** Disconnect? Retry?? + } + } + + + // This is thread-safe for the GUI. It must be used by the network thread (receiveResponse() + // and anything called from it) to log messages to the GUI. + public void setLogMessage(final String msg) { + + logMessage = msg; + + // Tell the display(s) to fetch and show the status + for(LogMessageObserver obs : logmsgObserverList) { + obs.notifyLogMessage(); + } + } + + public String getLogMessage() { + return logMessage; + } + + // This just puts the status into a member variable, + // for the network status observers to retrieve. + public void setNetworkStatus(connectionStatus cStatus) { + switch(cStatus) { + case NOT_CONNECTED: + networkStatus = "Not Connected"; + break; + case CONNECTING: + networkStatus = "Connecting..."; + break; + case CONNECTED: + networkStatus = "Connected"; + break; + case CONNECT_ERROR: + networkStatus = "Error Connecting"; + break; + default: + networkStatus = "Unknown Error"; + } + + // Tell the display(s) to fetch and show the status + for(NetworkStatusObserver obs : networkStatusObserverList) { + obs.notifyNetworkStatus(); + } + } + + public String getNetworkStatus() { + return networkStatus; + } +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/ReadRegisterTransaction.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/ReadRegisterTransaction.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/ReadRegisterTransaction.java (revision 66) @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////// +// +// ReadRegisterTransaction.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class defines a transaction object which is passed to +// the RSP coder in order to perform an RSP 'read' command. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +public class ReadRegisterTransaction implements TargetTransaction { + + private String packetString = null; + private long dataValueRead = 0; + + public ReadRegisterTransaction(targetDebugRegisterSet.regType reg) { + packetString = new String("p"); // 'p' is read one register + int regAddr = targetDebugRegisterSet.getRegisterAddress(reg); + packetString += Integer.toHexString(regAddr); + } + + @Override + public String getDataToSend() { + return packetString; + } + + @Override + public boolean receivePacket(String pkt) { + + // A register read response has no leading header / char... + // so just parse the number. + long val; + try { + val = Long.parseLong(pkt, 16); // data comes back as a hex string + } catch (Exception e) { + // TODO logMessageGUI("Got invalid read data (size " + pkt.length() + "): " + pkt + ": " + e); + dataValueRead = 0; + return false; + } + + dataValueRead = val; + return true; + } + + public long getDataValueRead() { + return dataValueRead; + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/targetTransactor.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/targetTransactor.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/targetTransactor.java (revision 66) @@ -0,0 +1,74 @@ +//////////////////////////////////////////////////////////////// +// +// targetTransactor.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class handles the top-level target transactions. +// Its methods are specific transactions (read register, +// is target running, etc.). It constructs an appropriate +// transaction object, then gives it to the RSP algorithm +// for processing. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import java.io.IOException; + +public class targetTransactor { + + rspCoder rsp = null; + + public targetTransactor(rspCoder r) { + rsp = r; + } + + // Succeeds or throws an IOException. + public void writeRegister(targetDebugRegisterSet.regType reg, long val) throws IOException { + WriteRegisterTransaction xact = new WriteRegisterTransaction(reg, val); + rsp.Transact(xact); + } + + // Returns a valid value or throws an IOException. + public long readRegister(targetDebugRegisterSet.regType reg) throws IOException { + long ret; + ReadRegisterTransaction xact = new ReadRegisterTransaction(reg); + rsp.Transact(xact); + ret = xact.getDataValueRead(); + return ret; + } + + // Returns a valid boolean indicator or throws an IOException. + public boolean isTargetRunning() throws IOException { + boolean ret; + TargetRunningTransaction xact = new TargetRunningTransaction(); + rsp.Transact(xact); + ret = xact.getIsTargetRunning(); + return ret; + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiServerGroup.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiServerGroup.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiServerGroup.java (revision 66) @@ -0,0 +1,154 @@ +//////////////////////////////////////////////////////////////// +// +// guiServerGroup.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class contains the GUI elements related to the server +// connection. This includes the server address and port +// number, the connect button, and the network status message +// display. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + + +public class guiServerGroup implements NetworkStatusObserver { + + private Group serverGroup = null; + private GridLayout serverGroupLayout = null; + private Button serverConnectButton = null; + private Group serverHostnameGroup = null; + private Text serverHostnameText = null; + private Group tcpPortGroup = null; + private Text tcpPortText = null; + private Group networkStatusGroup = null; + private Label connectionStatusLabel = null; + private mainControl mCtrl = null; + + public guiServerGroup(Composite parent, mainControl mc) { + mCtrl = mc; + serverGroup = new Group(parent, SWT.NONE); + serverGroupLayout = new GridLayout(); + + serverGroupLayout.numColumns = 4; + + serverGroup.setLayout(serverGroupLayout); + serverGroup.setText("Server Connection"); + + createServerHostnameGroup(); + createTcpPortGroup(); + serverConnectButton = new Button(serverGroup, SWT.NONE); + serverConnectButton.setText("Connect"); + serverConnectButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { + public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { + int port = Integer.parseInt(tcpPortText.getText()); + if(mCtrl != null) { + mCtrl.doNetworkConnect(serverHostnameText.getText(), port); + } + } + }); + createNetworkStatusGroup(); + + mCtrl.registerForNetworkStatusUpdates(this); + } + + private void createServerHostnameGroup() { + serverHostnameGroup = new Group(serverGroup, SWT.NONE); + serverHostnameGroup.setLayout(new GridLayout()); + serverHostnameGroup.setText("Server Hostname"); + serverHostnameText = new Text(serverHostnameGroup, SWT.BORDER); + serverHostnameText.setText("localhost"); + + // Make the Text box a bit bigger than default + int columns = 20; + GC gc = new GC (serverHostnameText); + FontMetrics fm = gc.getFontMetrics (); + int width = columns * fm.getAverageCharWidth (); + int height = fm.getHeight (); + gc.dispose (); + // This doesn't seem to work, need to use gd.widthHint/heightHint below + + GridData gd = new GridData(); + gd.grabExcessHorizontalSpace = true; + gd.verticalAlignment = GridData.CENTER; + gd.horizontalAlignment = GridData.FILL; + gd.widthHint = width; + gd.heightHint = height; + serverHostnameText.setLayoutData(gd); + } + + private void createTcpPortGroup() { + tcpPortGroup = new Group(serverGroup, SWT.NONE); + tcpPortGroup.setLayout(new GridLayout()); + tcpPortGroup.setText("Server Port"); + tcpPortText = new Text(tcpPortGroup, SWT.BORDER); + tcpPortText.setText("9928"); + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = true; + gd.verticalAlignment = GridData.CENTER; + tcpPortText.setLayoutData(gd); + } + + private void createNetworkStatusGroup() { + networkStatusGroup = new Group(serverGroup, SWT.NONE); + networkStatusGroup.setText("Connection Status"); + GridLayout gl = new GridLayout(); + gl.makeColumnsEqualWidth = false; + networkStatusGroup.setLayout(gl); + + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = true; + networkStatusGroup.setLayoutData(gd); + + connectionStatusLabel = new Label(networkStatusGroup, SWT.NONE); + connectionStatusLabel.setText("Not Connected"); // cheating - doesn't through mainControl + gd = new GridData(); + gd.grabExcessHorizontalSpace = true; + gd.verticalAlignment = GridData.CENTER; + gd.horizontalAlignment = GridData.FILL; + connectionStatusLabel.setLayoutData(gd); + } + + public void notifyNetworkStatus() { + // *** Limit length? + connectionStatusLabel.setText(mCtrl.getNetworkStatus()); + } +} \ No newline at end of file Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiDCRGroup.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiDCRGroup.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiDCRGroup.java (revision 66) @@ -0,0 +1,438 @@ +//////////////////////////////////////////////////////////////// +// +// guiDCRGroup.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class holds the GUI elements related to the DCR registers +// (the main watchpoint control registers) in the watchpoint +// unit. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + + +public class guiDCRGroup implements RegisterObserver { + + public Group dcrRegsGroup = null; + private Group dcrGroup[] = {null, null, null, null, null, null, null, null}; + private Button dcrBPCheckbox[] = {null, null, null, null, null, null, null, null}; + private Label dcrBPcbLabel[] = {null, null, null, null, null, null, null, null}; + // The Spinner only uses a signed int as its max, so we use a Text element instead + private Text dvrValText[] = {null, null, null, null, null, null, null, null}; + private Button dcrSignedCheckBox[] = {null, null, null, null, null, null, null, null}; + private Label dcrSignedCheckboxLabel[] = {null, null, null, null, null, null, null, null}; + private Combo dcrCmpSource[] = {null, null, null, null, null, null, null, null}; + private Combo dcrCmpType[] = {null, null, null, null, null, null, null, null}; + private Combo dcrChainCombo[] = {null, null, null, null, null, null, null, null}; + private Combo dcrCountLinkCombo[] = {null, null, null, null, null, null, null, null}; + private Label dcrBPActiveLabel[] = {null, null, null, null, null, null, null, null}; + private registerInterpreter regSet = null; + private Image activeImage = null; + private Image inactiveImage = null; + + public guiDCRGroup(Composite parent, Device display, mainControl mCtrl) { + + // Wrap the register set with an interpreter that knows the bit meanings + regSet = new registerInterpreter(mCtrl.getRegSet()); + + // Register with main control for register set updates + mCtrl.registerForRegsetUpdates(this); + + // Create images for active interrupt indicators + activeImage = new Image (display, 16, 16); + Color color = display.getSystemColor (SWT.COLOR_RED); + GC gc = new GC (activeImage); + gc.setBackground (color); + gc.fillRectangle (activeImage.getBounds ()); + gc.dispose (); + + inactiveImage = new Image (display, 16, 16); + color = display.getSystemColor (SWT.COLOR_DARK_GRAY); + gc = new GC (inactiveImage); + gc.setBackground (color); + gc.fillRectangle (inactiveImage.getBounds ()); + gc.dispose (); + + // Create Watchpoint GUI elements + dcrRegsGroup = new Group(parent, SWT.NONE); + dcrRegsGroup.setText("Watchpoints"); + + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + dcrRegsGroup.setLayout(gridLayout); + + for (int i = 7; i >= 0; i--) { + createDcrGroup(i); + } + } + + private void createDcrGroup(int groupnum) { + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 10; + dcrGroup[groupnum] = new Group(dcrRegsGroup, SWT.NONE); + dcrGroup[groupnum].setLayout(gridLayout); + String dcrLabel = "Watchpoint " + groupnum + ": "; + dcrGroup[groupnum].setText(dcrLabel); + + dcrBPActiveLabel[groupnum] = new Label(dcrGroup[groupnum], SWT.NONE); + dcrBPActiveLabel[groupnum].setImage(inactiveImage); + dcrBPCheckbox[groupnum] = new Button(dcrGroup[groupnum], SWT.CHECK); + dcrBPcbLabel[groupnum] = new Label(dcrGroup[groupnum], SWT.NONE); + dcrBPcbLabel[groupnum].setText("Break on"); + createDcrCmpSource(groupnum); + createDcrCmpType(groupnum); + dvrValText[groupnum] = new Text(dcrGroup[groupnum], SWT.BORDER); + dvrValText[groupnum].setTextLimit(10); + dcrSignedCheckBox[groupnum] = new Button(dcrGroup[groupnum], SWT.CHECK); + dcrSignedCheckboxLabel[groupnum] = new Label(dcrGroup[groupnum], SWT.NONE); + dcrSignedCheckboxLabel[groupnum].setText("Signed"); + createDcrChainCombo(groupnum); + createDcrCountLinkCombo(groupnum); + } + + /** + * This method initializes dcrCmpSource + * + */ + private void createDcrCmpSource(int groupnum) { + dcrCmpSource[groupnum] = new Combo(dcrGroup[groupnum], SWT.DROP_DOWN|SWT.READ_ONLY); + dcrCmpSource[groupnum].add("Disabled", 0); + dcrCmpSource[groupnum].add("Instruction Fetch Addr", 1); + dcrCmpSource[groupnum].add("Load Addr", 2); + dcrCmpSource[groupnum].add("Store Addr", 3); + dcrCmpSource[groupnum].add("Load Data Value", 4); + dcrCmpSource[groupnum].add("Store Data Value", 5); + dcrCmpSource[groupnum].add("Load or Store Addr", 6); + dcrCmpSource[groupnum].add("Load or Store Data", 7); + dcrCmpSource[groupnum].select(0); + } + + /** + * This method initializes drcCmpType + * + */ + private void createDcrCmpType(int groupnum) { + dcrCmpType[groupnum] = new Combo(dcrGroup[groupnum], SWT.DROP_DOWN|SWT.READ_ONLY); + dcrCmpType[groupnum].add("(disabled)", 0); + dcrCmpType[groupnum].add("==", 1); + dcrCmpType[groupnum].add("<", 2); + dcrCmpType[groupnum].add("<=", 3); + dcrCmpType[groupnum].add(">", 4); + dcrCmpType[groupnum].add(">=", 5); + dcrCmpType[groupnum].add("!=", 6); + dcrCmpType[groupnum].select(0); + } + + private void createDcrChainCombo(int groupnum) { + dcrChainCombo[groupnum] = new Combo(dcrGroup[groupnum], SWT.DROP_DOWN|SWT.READ_ONLY); + dcrChainCombo[groupnum].add("No chain", 0); + String andStr; + if(groupnum == 0) { + andStr = "AND EXT"; + } else { + andStr = "AND WP" + (groupnum-1); + } + dcrChainCombo[groupnum].add(andStr, 1); + String orStr; + if(groupnum == 0) { + orStr = "OR EXT"; + } else { + orStr = "OR WP" + (groupnum-1); + } + dcrChainCombo[groupnum].add(orStr, 2); + dcrChainCombo[groupnum].select(0); + } + + private void createDcrCountLinkCombo(int groupnum) { + dcrCountLinkCombo[groupnum] = new Combo(dcrGroup[groupnum], SWT.DROP_DOWN|SWT.READ_ONLY); + dcrCountLinkCombo[groupnum].add("counter 0", 0); + dcrCountLinkCombo[groupnum].add("counter 1", 1); + dcrCountLinkCombo[groupnum].select(0); + } + + + public void notifyRegisterUpdate(updateDirection dir) throws NumberFormatException { + + if(dir == RegisterObserver.updateDirection.REGS_TO_GUI) { + // We do this in descending order so that absent DCR/DVR pairs can + // correctly disable the chain on the previous + for(int i = 7; i >= 0; i--) { + // Go left-to-right, updating UI elements + + // If this DCR/DVR isn't implemented, disable all controls for this WP + if(!regSet.isWPImplemented(i)) { // disable everything + dcrBPActiveLabel[i].setImage(inactiveImage); + dcrBPcbLabel[i].setText("Not Implemented"); + // TODO *** Resize so the entire "Not Implemented" text is visible + dcrBPCheckbox[i].setVisible(false); + dcrCmpSource[i].setVisible(false); + dcrCmpType[i].setVisible(false); + dvrValText[i].setVisible(false); + dcrSignedCheckBox[i].setVisible(false); + dcrChainCombo[i].setVisible(false); + if(i < 7) { // Disable the next chain type too + dcrChainCombo[i+1].setVisible(false); + } + dcrCountLinkCombo[i].setVisible(false); + dcrSignedCheckboxLabel[i].setVisible(false); + continue; + } else { // enable everything + dcrBPcbLabel[i].setText("Break on"); + dcrBPCheckbox[i].setVisible(true); + dcrCmpSource[i].setVisible(true); + dcrCmpType[i].setVisible(true); + dvrValText[i].setVisible(true); + dcrSignedCheckBox[i].setVisible(true); + dcrChainCombo[i].setVisible(true); + dcrCountLinkCombo[i].setVisible(true); + dcrSignedCheckboxLabel[i].setVisible(true); + } + + + // 'caused break' indicator + if(regSet.didWPCauseBreak(i)) { + dcrBPActiveLabel[i].setImage(activeImage); + } else { + dcrBPActiveLabel[i].setImage(inactiveImage); + } + + // 'break enabled' indicator + if(regSet.getWPBreakEnabled(i)) { + dcrBPCheckbox[i].setSelection(true); + } else { + dcrBPCheckbox[i].setSelection(false); + } + + // compare source + switch(regSet.getWPCompareSource(i)) { + case DISABLED: + dcrCmpSource[i].select(0); + break; + case INSTR_FETCH_ADDR: + dcrCmpSource[i].select(1); + break; + case LOAD_ADDR: + dcrCmpSource[i].select(2); + break; + case STORE_ADDR: + dcrCmpSource[i].select(3); + break; + case LOAD_DATA: + dcrCmpSource[i].select(4); + break; + case STORE_DATA: + dcrCmpSource[i].select(5); + break; + case LOAD_STORE_ADDR: + dcrCmpSource[i].select(6); + break; + case LOAD_STORE_DATA: + dcrCmpSource[i].select(7); + break; + } + + // compare type + switch(regSet.getWPCompareType(i)) { + case MASKED: + dcrCmpType[i].select(0); + break; + case EQ: + dcrCmpType[i].select(1); + break; + case LT: + dcrCmpType[i].select(2); + break; + case LE: + dcrCmpType[i].select(3); + break; + case GT: + dcrCmpType[i].select(4); + break; + case GE: + dcrCmpType[i].select(5); + break; + case NE: + dcrCmpType[i].select(6); + break; + } + + // compare value + dvrValText[i].setText("0x" + Long.toHexString(regSet.getDVR(i))); + + // signed indicator + if(regSet.getWPSignedCompare(i)) { + dcrSignedCheckBox[i].setSelection(true); + } else { + dcrSignedCheckBox[i].setSelection(false); + } + + // chain type + switch(regSet.getWPChainType(i)) { + case NONE: + dcrChainCombo[i].select(0); + break; + case AND: + dcrChainCombo[i].select(1); + break; + case OR: + dcrChainCombo[i].select(2); + break; + } + + // counter assignment + if(regSet.getWPCounterAssign(i) == 0) { + dcrCountLinkCombo[i].select(0); + } else { + dcrCountLinkCombo[i].select(1); + } + } // for each DCR + } + else { // dir == GUI_TO_REGS + + for(int i = 0; i < 8; i++) { + + // Don't bother to set values for un-implemented DVR/DCR pairs. + if(!regSet.isWPImplemented(i)) { + continue; + } + + // Go left-to-right, putting value into the regSet + // Break enabled + regSet.setWPBreakEnabled(i, dcrBPCheckbox[i].getSelection()); + + // Compare Source + switch(dcrCmpSource[i].getSelectionIndex()) { + case 0: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.DISABLED); + break; + case 1: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.INSTR_FETCH_ADDR); + break; + case 2: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.LOAD_ADDR); + break; + case 3: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.STORE_ADDR); + break; + case 4: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.LOAD_DATA); + break; + case 5: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.STORE_DATA); + break; + case 6: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.LOAD_STORE_ADDR); + break; + case 7: + regSet.setWPCompareSource(i, registerInterpreter.compareSource.LOAD_STORE_DATA); + break; + } + + // Compare Type + switch(dcrCmpType[i].getSelectionIndex()) { + case 0: + regSet.setWPCompareType(i, registerInterpreter.compareType.MASKED); + break; + case 1: + regSet.setWPCompareType(i, registerInterpreter.compareType.EQ); + break; + case 2: + regSet.setWPCompareType(i, registerInterpreter.compareType.LT); + break; + case 3: + regSet.setWPCompareType(i, registerInterpreter.compareType.LE); + break; + case 4: + regSet.setWPCompareType(i, registerInterpreter.compareType.GT); + break; + case 5: + regSet.setWPCompareType(i, registerInterpreter.compareType.GE); + break; + case 6: + regSet.setWPCompareType(i, registerInterpreter.compareType.NE); + break; + } + + // Compare Value + //try { + long cval; + String str = dvrValText[i].getText(); + if(str.startsWith("0x") || str.startsWith("0X")) { + cval = Long.parseLong(str.substring(2), 16); // substr(2) skips the "0x" + } + else { + cval = Long.parseLong(str); + } + + regSet.setDVR(i, cval); + + //} catch(NumberFormatException e) { + // return false; + //} + + + // Signed indicator + regSet.setWPSignedCompare(i, dcrSignedCheckBox[i].getSelection()); + + // Chain type + switch(dcrChainCombo[i].getSelectionIndex()) { + case 0: + regSet.setWPChainType(i, registerInterpreter.chainType.NONE); + break; + case 1: + regSet.setWPChainType(i, registerInterpreter.chainType.AND); + break; + case 2: + regSet.setWPChainType(i, registerInterpreter.chainType.OR); + break; + } + + // Counter assignment + if(dcrCountLinkCombo[i].getSelectionIndex() == 0) { + regSet.setWPCounterAssign(i, 0); + } else { + regSet.setWPCounterAssign(i, 1); + } + } + } // else dir == GUI_TO_REGS + } // notifyRegisterUpdate() + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiCountRegsGroup.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiCountRegsGroup.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/guiCountRegsGroup.java (revision 66) @@ -0,0 +1,448 @@ +//////////////////////////////////////////////////////////////// +// +// guiCountRegsGroup.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class holds the GUI elements related to the hardware +// counters in the watchpoint unit. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Device; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Spinner; +import org.eclipse.swt.widgets.Combo; + + +public class guiCountRegsGroup implements RegisterObserver { + + private Combo count1ChainCombo; + private Group countRegGroup = null; + private Group count1Composite; + private Button count1EnableCheckBox; + private Label count1EnableLabel; + private Button count1BPCheckBox; + private Label count1EnableBPLabel; + private Group count2Composite; + private Button count2EnableCheckBox; + private Label count2EnableLabel; + private Button count2BPCheckBox; + private Label count2EnableBPLabel; + private Spinner matchValueEnteredSpinner; + private Group matchValueActualGroup; + private Spinner matchValueActualSpinner; + private Combo count2ChainCombo; + private Group matchValueEnteredGroup2; + private Spinner matchValueEnteredSpinner2; + private Group matchValueActualGroup2; + private Spinner match2ValueActualSpinner; + private registerInterpreter regSet = null; + private Image activeImage = null; + private Image inactiveImage = null; + private Label count1BPActiveLabel = null; + private Label count2BPActiveLabel = null; + private Combo ctrCountLinkCombo[] = {null, null}; + + public guiCountRegsGroup(Composite parent, Device display, mainControl mCtrl) { + + // Create images for active interrupt indicators + activeImage = new Image (display, 16, 16); + Color color = display.getSystemColor (SWT.COLOR_RED); + GC gc = new GC (activeImage); + gc.setBackground (color); + gc.fillRectangle (activeImage.getBounds ()); + gc.dispose (); + + inactiveImage = new Image (display, 16, 16); + color = display.getSystemColor (SWT.COLOR_DARK_GRAY); + gc = new GC (inactiveImage); + gc.setBackground (color); + gc.fillRectangle (inactiveImage.getBounds ()); + gc.dispose (); + + // Create the Count registers GUI elements + countRegGroup = new Group(parent, SWT.NONE); + countRegGroup.setLayout(new GridLayout()); + createCount1Composite(); + createCount2Composite(); + countRegGroup.setText("Counters"); + + // Register with main control for register set updates + mCtrl.registerForRegsetUpdates(this); + + // Wrap the register set with an interpreter that knows the bit meanings + regSet = new registerInterpreter(mCtrl.getRegSet()); + } + + private void createCount1Composite() { + GridData gridData4 = new GridData(); + gridData4.horizontalAlignment = SWT.FILL; + gridData4.grabExcessHorizontalSpace = true; + + GridLayout gridLayout1 = new GridLayout(); + gridLayout1.numColumns = 7; + count1Composite = new Group(countRegGroup, SWT.NONE); + count1Composite.setText("Count 0"); + + count1BPActiveLabel = new Label(count1Composite, SWT.NONE); + count1BPActiveLabel.setImage(inactiveImage); + GridData gd = new GridData(); + gd.verticalSpan = 2; + count1BPActiveLabel.setLayoutData(gd); + + count1EnableCheckBox = new Button(count1Composite, SWT.CHECK); + count1EnableLabel = new Label(count1Composite, SWT.NONE); + count1EnableLabel.setText("Enable"); + + createMatchValue1EnteredGroup(); + createMatchValue1ActualGroup(); + createCount1ChainCombo(); + createCtr1CountLinkCombo(); + + count1BPCheckBox = new Button(count1Composite, SWT.CHECK); + count1EnableBPLabel = new Label(count1Composite, SWT.NONE); + count1EnableBPLabel.setText("Break on Match"); + count1Composite.setLayout(gridLayout1); + count1Composite.setLayoutData(gridData4); + } + + private void createCount2Composite() { + GridData gridData5 = new GridData(); + gridData5.horizontalAlignment = SWT.FILL; + gridData5.grabExcessHorizontalSpace = true; + + GridLayout gridLayout1 = new GridLayout(); + gridLayout1.numColumns = 7; + count2Composite = new Group(countRegGroup, SWT.NONE); + count2Composite.setText("Count 1"); + + count2BPActiveLabel = new Label(count2Composite, SWT.NONE); + count2BPActiveLabel.setImage(inactiveImage); + GridData gd = new GridData(); + gd.verticalSpan = 2; + count2BPActiveLabel.setLayoutData(gd); + + count2EnableCheckBox = new Button(count2Composite, SWT.CHECK); + count2EnableLabel = new Label(count2Composite, SWT.NONE); + count2EnableLabel.setText("Enable"); + + createMatchValue2EnteredGroup(); + createMatchValue2ActualGroup(); + createCount2ChainCombo(); + createCtr2CountLinkCombo(); + + count2BPCheckBox = new Button(count2Composite, SWT.CHECK); + count2EnableBPLabel = new Label(count2Composite, SWT.NONE); + count2EnableBPLabel.setText("Break on Match"); + count2Composite.setLayout(gridLayout1); + count2Composite.setLayoutData(gridData5); + } + + private void createMatchValue1EnteredGroup() { + GridData gridData = new GridData(); + gridData.verticalSpan = 2; + gridData.verticalAlignment = GridData.CENTER; + gridData.horizontalAlignment = GridData.CENTER; + Group matchValueEnteredGroup = new Group(count1Composite, SWT.NONE); + matchValueEnteredGroup.setLayout(new GridLayout()); + matchValueEnteredGroup.setLayoutData(gridData); + matchValueEnteredGroup.setText("Match Value"); + matchValueEnteredSpinner = new Spinner(matchValueEnteredGroup, SWT.BORDER); + matchValueEnteredSpinner.setValues(0, 0, 0xFFFF, 0, 1, 100); + } + + /** + * This method initializes matchValue1ActualGroup + * + */ + private void createMatchValue1ActualGroup() { + GridData gridData2 = new GridData(); + gridData2.horizontalAlignment = GridData.CENTER; + gridData2.verticalAlignment = GridData.CENTER; + GridData gridData1 = new GridData(); + gridData1.verticalSpan = 2; + matchValueActualGroup = new Group(count1Composite, SWT.NONE); + matchValueActualGroup.setLayout(new GridLayout()); + matchValueActualGroup.setLayoutData(gridData1); + matchValueActualGroup.setText("Current Count Value"); + matchValueActualSpinner = new Spinner(matchValueActualGroup, SWT.NONE); + matchValueActualSpinner.setValues(0, 0, 0xFFFF, 0, 1, 100); + matchValueActualSpinner.setLayoutData(gridData2); + } + + private void createCount1ChainCombo() { + GridData gridData = new GridData(); + gridData.verticalSpan = 2; + count1ChainCombo = new Combo(count1Composite, SWT.DROP_DOWN|SWT.READ_ONLY); + count1ChainCombo.setLayoutData(gridData); + count1ChainCombo.add("No chain", 0); + count1ChainCombo.add("AND WP3", 1); + count1ChainCombo.add("OR WP3", 2); + count1ChainCombo.select(0); + } + + private void createMatchValue2EnteredGroup() { + GridData gridData = new GridData(); + gridData.verticalSpan = 2; + gridData.verticalAlignment = GridData.CENTER; + gridData.horizontalAlignment = GridData.CENTER; + matchValueEnteredGroup2 = new Group(count2Composite, SWT.NONE); + matchValueEnteredGroup2.setLayout(new GridLayout()); + matchValueEnteredGroup2.setLayoutData(gridData); + matchValueEnteredGroup2.setText("Match Value"); + matchValueEnteredSpinner2 = new Spinner(matchValueEnteredGroup2, SWT.BORDER); + matchValueEnteredSpinner2.setValues(0, 0, 0xFFFF, 0, 1, 100); + } + + private void createMatchValue2ActualGroup() { + GridData gridData2 = new GridData(); + gridData2.horizontalAlignment = GridData.CENTER; + gridData2.verticalSpan = 2; + gridData2.verticalAlignment = GridData.CENTER; + GridData gridData1 = new GridData(); + gridData1.verticalSpan = 2; + matchValueActualGroup2 = new Group(count2Composite, SWT.NONE); + matchValueActualGroup2.setLayout(new GridLayout()); + matchValueActualGroup2.setLayoutData(gridData2); + matchValueActualGroup2.setText("Current Count Value"); + match2ValueActualSpinner = new Spinner(matchValueActualGroup2, SWT.NONE); + match2ValueActualSpinner.setValues(0, 0, 0xFFFF, 0, 1, 100); + } + + private void createCount2ChainCombo() { + GridData gridData = new GridData(); + gridData.verticalSpan = 2; + count2ChainCombo = new Combo(count2Composite, SWT.DROP_DOWN|SWT.READ_ONLY); + count2ChainCombo.setLayoutData(gridData); + count2ChainCombo.add("No chain", 0); + count2ChainCombo.add("AND WP7", 1); + count2ChainCombo.add("OR WP7", 2); + count2ChainCombo.select(0); + } + + private void createCtr1CountLinkCombo() { + GridData gridData = new GridData(); + gridData.verticalSpan = 2; + ctrCountLinkCombo[0] = new Combo(count1Composite, SWT.DROP_DOWN|SWT.READ_ONLY); + ctrCountLinkCombo[0].setLayoutData(gridData); + ctrCountLinkCombo[0].add("counter 0", 0); + ctrCountLinkCombo[0].add("counter 1", 1); + ctrCountLinkCombo[0].select(0); + } + + private void createCtr2CountLinkCombo() { + GridData gridData = new GridData(); + gridData.verticalSpan = 2; + ctrCountLinkCombo[1] = new Combo(count2Composite, SWT.DROP_DOWN|SWT.READ_ONLY); + ctrCountLinkCombo[1].setLayoutData(gridData); + ctrCountLinkCombo[1].add("counter 0", 0); + ctrCountLinkCombo[1].add("counter 1", 1); + ctrCountLinkCombo[1].select(0); + } + + public void notifyRegisterUpdate(updateDirection dir) throws NumberFormatException { + + if(dir == RegisterObserver.updateDirection.REGS_TO_GUI) { + // Set GUI elements based on values in regSet + // Counter 0 -- go left-to-right + // 'caused break' indicator + if(regSet.didCounterCauseBreak(0)) { + count1BPActiveLabel.setImage(activeImage); + } else { + count1BPActiveLabel.setImage(inactiveImage); + } + + // 'enabled' checkbox + if(regSet.getCounterEnabled(0)) { + count1EnableCheckBox.setSelection(true); + } else { + count1EnableCheckBox.setSelection(false); + } + + // 'break on match' checkbox + if(regSet.getCounterBreakEnabled(0)) { + count1BPCheckBox.setSelection(true); + } else { + count1BPCheckBox.setSelection(false); + } + + // Match value + matchValueEnteredSpinner.setSelection(regSet.getCounterWatchValue(0)); + + // Count value + matchValueActualSpinner.setSelection(regSet.getCounterCountValue(0)); + + // Chain type + switch(regSet.getCounterChainType(0)) { + case NONE: + count1ChainCombo.select(0); + break; + case AND: + count1ChainCombo.select(1); + break; + case OR: + count1ChainCombo.select(2); + break; + } + + // counter assignment + if(regSet.getWPCounterAssign(8) == 0) { + ctrCountLinkCombo[0].select(0); + } else { + ctrCountLinkCombo[0].select(1); + } + + // Counter 1 + // 'caused break' indicator + if(regSet.didCounterCauseBreak(1)) { + count2BPActiveLabel.setImage(activeImage); + } else { + count2BPActiveLabel.setImage(inactiveImage); + } + + // 'enabled' checkbox + if(regSet.getCounterEnabled(1)) { + count2EnableCheckBox.setSelection(true); + } else { + count2EnableCheckBox.setSelection(false); + } + + // 'break on match' checkbox + if(regSet.getCounterBreakEnabled(1)) { + count2BPCheckBox.setSelection(true); + } else { + count2BPCheckBox.setSelection(false); + } + + // Match value + matchValueEnteredSpinner2.setSelection(regSet.getCounterWatchValue(1)); + + // Count value + match2ValueActualSpinner.setSelection(regSet.getCounterCountValue(1)); + + // Chain type + switch(regSet.getCounterChainType(1)) { + case NONE: + count2ChainCombo.select(0); + break; + case AND: + count2ChainCombo.select(1); + break; + case OR: + count2ChainCombo.select(2); + break; + } + + // counter assignment + if(regSet.getWPCounterAssign(9) == 0) { + ctrCountLinkCombo[1].select(0); + } else { + ctrCountLinkCombo[1].select(1); + } + } + else { // direction = GUI_TO_REGS + // Set values in regSet based on GUI elements + // Counter 0 -- go left-to-right + // 'enabled' checkbox + regSet.setCounterEnabled(0, count1EnableCheckBox.getSelection()); + + // 'break on match' checkbox + regSet.setCounterBreakEnabled(0, count1BPCheckBox.getSelection()); + + // Match value + regSet.setCounterWatchValue(0, matchValueEnteredSpinner.getSelection()); + + // Count value + regSet.setCounterCountValue(0, matchValueActualSpinner.getSelection()); + + // Chain type + switch(count1ChainCombo.getSelectionIndex()) { + case 0: + regSet.setCounterChainType(0, registerInterpreter.chainType.NONE); + break; + case 1: + regSet.setCounterChainType(0, registerInterpreter.chainType.AND); + break; + case 2: + regSet.setCounterChainType(0, registerInterpreter.chainType.OR); + break; + } + + // Counter assignment + if(ctrCountLinkCombo[0].getSelectionIndex() == 0) { + regSet.setWPCounterAssign(8, 0); + } else { + regSet.setWPCounterAssign(8, 1); + } + + // Counter 1 + // 'enabled' checkbox + regSet.setCounterEnabled(1, count2EnableCheckBox.getSelection()); + + // 'break on match' checkbox + regSet.setCounterBreakEnabled(1, count2BPCheckBox.getSelection()); + + // Match value + regSet.setCounterWatchValue(1, matchValueEnteredSpinner2.getSelection()); + + // Count value + regSet.setCounterCountValue(1, match2ValueActualSpinner.getSelection()); + + // Chain type + switch(count2ChainCombo.getSelectionIndex()) { + case 0: + regSet.setCounterChainType(1, registerInterpreter.chainType.NONE); + break; + case 1: + regSet.setCounterChainType(1, registerInterpreter.chainType.AND); + break; + case 2: + regSet.setCounterChainType(1, registerInterpreter.chainType.OR); + break; + } + + // Counter assignment + if(ctrCountLinkCombo[1].getSelectionIndex() == 0) { + regSet.setWPCounterAssign(9, 0); + } else { + regSet.setWPCounterAssign(9, 1); + } + } // else dir == GUI_TO_REGS + } // notifyRegisterUpdate() + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/RegisterObserver.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/RegisterObserver.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/RegisterObserver.java (revision 66) @@ -0,0 +1,43 @@ +//////////////////////////////////////////////////////////////// +// +// RegisterObserver.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This interface is implemented by (display) classes that +// wish to be notified either when the register cache has +// changed due to an RSP read, or when their values should be +// written to the cache in preparation for an RSP write. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +public interface RegisterObserver { + public enum updateDirection { GUI_TO_REGS, REGS_TO_GUI } + + void notifyRegisterUpdate(updateDirection dir) throws NumberFormatException; +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/TargetTransaction.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/TargetTransaction.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/TargetTransaction.java (revision 66) @@ -0,0 +1,50 @@ +//////////////////////////////////////////////////////////////// +// +// TargetTransaction.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This interface is implemented by objects which define +// specific RSP transactions, such as register read and write. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +public interface TargetTransaction { + + // The RSP (or other encoding / sending algorithm) can + // call this method to get the pre-formatted packet which should be + // encoded and sent + public String getDataToSend(); + + // This should be called by the receiving portion of the RSP + // algorithm each time a new character is received from the + // network and decoded. It returns true so long as it wants + // another character. It + public boolean receivePacket(String pkt); + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/TargetRunningTransaction.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/TargetRunningTransaction.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/TargetRunningTransaction.java (revision 66) @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////// +// +// targetDebugRegisterSet.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class defines a transaction object which is passed +// to the RSP coder in order to determine whether the target +// CPU is running. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + + +public class TargetRunningTransaction implements TargetTransaction { + + private boolean isTargetRunning = false; + + public TargetRunningTransaction() { + } + + @Override + public String getDataToSend() { + return new String("?"); + } + + @Override + public boolean receivePacket(String pkt) { + + // 'S##' means it's stopped, 'R' means it's running, + // anything else is an error. + if(pkt.charAt(0) == 'R') { + // target is running, disallow accesses + isTargetRunning = true; + } + else if(pkt.charAt(0) == 'S') { + // We got a stop packet + isTargetRunning = false; + } + else { + return false; + } + + return true; + } + + public boolean getIsTargetRunning() { + return isTargetRunning; + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/networkSystem.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/networkSystem.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/networkSystem.java (revision 66) @@ -0,0 +1,144 @@ +//////////////////////////////////////////////////////////////// +// +// networkSystem.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This class performs the low-level network I/O. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// + +package advancedWatchpointControl; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.charset.Charset; + + +public class networkSystem { + + private Socket sockfd = null; + private DataOutputStream ostream = null; + private BufferedReader istream = null; + private boolean isValid = false; + // We use mainControl for logging / displaying network state + private mainControl mCtrl = null; + + + public networkSystem(mainControl mc) { + mCtrl = mc; + } + + protected void finalize() throws Throwable { + disconnect(true); + } + + public void connect(String hostname, int portNumber) { + disconnect(true); + System.out.println("Network connecting"); + try { + sockfd = new Socket(hostname, portNumber); + sockfd.setSoLinger(false, 1); + istream = new BufferedReader(new InputStreamReader(sockfd.getInputStream(), Charset.forName("US-ASCII"))); + ostream = new DataOutputStream(sockfd.getOutputStream()); + } + catch (UnknownHostException e) { + disconnect(false); + mCtrl.setNetworkStatus(mainControl.connectionStatus.CONNECT_ERROR); + mCtrl.setLogMessage("Unknown host: " + e); + return; + } + catch (IOException e) { + disconnect(false); + mCtrl.setNetworkStatus(mainControl.connectionStatus.CONNECT_ERROR); + mCtrl.setLogMessage("Connect error: " + e.getMessage()); + return; + } + + isValid = true; + mCtrl.setNetworkStatus(mainControl.connectionStatus.CONNECTED); + String msg = "Connected to server \"" + hostname + "\", port " + portNumber; + mCtrl.setLogMessage(msg); + System.out.println("Network connected"); + mCtrl.doReadAllRegisters(); // Gets regs from target, sets GUI + } + + public void disconnect(boolean waitForReaderExit) { + System.out.println("Network disconnecting"); + isValid = false; + + try { + if(sockfd != null) + sockfd.shutdownInput(); + if(sockfd != null) + sockfd.close(); + } + catch (IOException e) { + // Ignore errors when closing socket + } + + sockfd = null; + istream = null; + ostream = null; + } + + public boolean isConnected() { + return isValid; + } + + public boolean sendData(String outdata) { + if(isValid) { + try { + ostream.writeBytes(outdata); + } + catch (IOException e) { + mCtrl.setNetworkStatus(mainControl.connectionStatus.CONNECT_ERROR); + mCtrl.setLogMessage(e.getMessage()); + disconnect(true); + return false; + } + } + else { + mCtrl.setLogMessage("Not connected: connect to server first."); + return false; + } + return true; + } + + public int getChar() throws IOException { + + if(istream != null) + return istream.read(); + + throw(new IOException("Network reader is null!")); + } + +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/LogMessageObserver.java =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/LogMessageObserver.java (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/src/advancedWatchpointControl/LogMessageObserver.java (revision 66) @@ -0,0 +1,40 @@ +//////////////////////////////////////////////////////////////// +// +// LogMessageObserver.java +// +// Copyright (C) 2010 Nathan Yawn +// (nyawn@opencores.org) +// +// This interface is used by any class that wants to register +// to receive notifications when a new log message is +// created. +// +//////////////////////////////////////////////////////////////// +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file 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 3.0 of the License, or (at your option) any +// later version. +// +// This source 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU General +// Public License along with this source; if not, download it +// from http://www.gnu.org/licenses/gpl.html +// +//////////////////////////////////////////////////////////////// +package advancedWatchpointControl; + +public interface LogMessageObserver { + public void notifyLogMessage(); +} Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/manifest =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/manifest (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/manifest (revision 66) @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: swt.jar +Main-Class: advancedWatchpointControl.AdvancedWatchpointControl
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/manifest Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/bin/advancedWatchpointControl/.keepme =================================================================== Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/swt.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/swt.jar =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/swt.jar (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/swt.jar (revision 66)
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/swt.jar Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/Makefile =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/Makefile (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/Makefile (revision 66) @@ -0,0 +1,40 @@ + +JC = javac +JAVA = java +SRCPATH = src/advancedWatchpointControl/ +DSTPATH = bin/advancedWatchpointControl/ +JFLAGS = -g -d $(DSTPATH) -cp swt.jar + + +CLASSES = \ + $(SRCPATH)AdvancedWatchpointControl.java \ + $(SRCPATH)ReadRegisterTransaction.java \ + $(SRCPATH)registerInterpreter.java \ + $(SRCPATH)guiControlGroup.java \ + $(SRCPATH)RegisterObserver.java \ + $(SRCPATH)guiCountRegsGroup.java \ + $(SRCPATH)rspCoder.java \ + $(SRCPATH)guiDCRGroup.java \ + $(SRCPATH)targetDebugRegisterSet.java \ + $(SRCPATH)guiServerGroup.java \ + $(SRCPATH)TargetRunningTransaction.java \ + $(SRCPATH)LogMessageObserver.java \ + $(SRCPATH)TargetTransaction.java \ + $(SRCPATH)mainControl.java \ + $(SRCPATH)targetTransactor.java \ + $(SRCPATH)NetworkStatusObserver.java \ + $(SRCPATH)WriteRegisterTransaction.java \ + $(SRCPATH)networkSystem.java + +default: AdvancedWatchpointControl.jar + +run: AdvancedWatchpointControl.jar + $(JAVA) -jar AdvancedWatchpointControl.jar & + +AdvancedWatchpointControl.jar: $(CLASSES) + $(JC) $(JFLAGS) $(CLASSES) + jar cvfm AdvancedWatchpointControl.jar manifest -C bin/advancedWatchpointControl/ . + +clean: + $(RM) $(DSTPATH)*.class + $(RM) AdvancedWatchpointControl.jar
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/Makefile Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/README =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/README (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/README (revision 66) @@ -0,0 +1,54 @@ +The AdvancedWatchpointControl program is a Java-language program distributed +as an Eclipse project. These instructions assume you have both the +Eclipse platform and the JDT Java development plugins installed. These +instructions were written for Eclipse version 3.5.2, though other versions +should be similar. + +To build the project in Eclipse, you must first import it into your workspace. +From the 'File' menu, select 'Import...'. In the Import menu, under the +'General' folder, select 'Existing Projects into Workspace', then click 'Next'. +On the next screen, select 'Select root directory', then enter (or browse to) +the adv_debug_sys/Software/AdvancedWatchpointControl directory. Finally, +click the 'Finish' button to import the project. + +AdvancedWatchpointControl depends on the SWT GUI widget toolkit from the +Eclipse project. This can be downloaded directly from the Eclipse project, +at http://www.eclipse.org/swt/. Download the version appropriate for your +operating system. + +There are (at least) two ways to satisfy the dependancy on SWT. As shipped, +AdvancedWatchpointControl is configured to depend on a project in the +workspace called org.eclipse.swt To create this project, you may import the +SWT project into the workspace from the downloaded archive file in the same +way you imported AdvancedWatchpointControl. + +In some versions of the SWT archive, there is a bug which prevents Eclipse +from importing the project. If this is the case, you must work around. +Extract the SWT archive, and find the swt.jar file. In Eclipse, right-click +on the AdvancedWatchpointControl, and click on 'Properties.' Under the +'Projects' tab, remove the dependancy on org.eclipse.swt. Under the +'Libraries' tab, remove SWT_CONTAINER/PLATFORM. Then click the 'Add +External JARs...' button. This will open the 'JAR Selection' dialog. Select +the swt.jar file from the archive, and click OK. + +You should now be able to build AdvancedWatchpointControl, and run it as a +Java application via the Eclipse GUI. + +If you do not have or wish to install Eclipse, a simple Makefile has been +included which should be able to build AdvancedWatchpointControl as an +executable JAR file. Simply type "make" in the project's root directory +to build the program, which will be called AdvancedWatchpointControl.jar. +Typing "make run" will build the program, then execute it. + +A pre-compiled executable JAR file has been included in the root directory of +AdvancedWatchpointControl, called AdvancedWatchpointControl.jar. To run this +file using the Sun JVM in Linux, use the command line: + +>java -jar AdvancedWatchpointControl.jar + +Other JVMs and operating systems may use different syntax. Note that the +AdvancedWatchpointControl.jar file includes the SWT library, which is +distributed under the terms of the Eclipse Public License v1.0. A copy of +this license may be found in the doc/ subdirectory. + +
tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/README Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/.classpath =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/.classpath (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/.classpath (revision 66) @@ -0,0 +1,8 @@ + + + + + + + + Index: tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/.project =================================================================== --- tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/.project (nonexistent) +++ tags/ADS_RELEASE_3_0_0/Software/AdvancedWatchpointControl/.project (revision 66) @@ -0,0 +1,19 @@ + + + AdvancedWatchpointControl + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.jem.beaninfo.BeanInfoNature + +

powered by: WebSVN 2.1.0

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