From: Florent Kermarrec Date: Wed, 30 Jan 2019 13:01:19 +0000 (+0100) Subject: build/sim: add jtagremote module (thanks LamdaConcept) X-Git-Tag: 24jan2021_ls180~1399 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1d9c55888fc0e2381e560e68b24dc547001dd282;p=litex.git build/sim: add jtagremote module (thanks LamdaConcept) --- diff --git a/litex/build/sim/core/modules/jtagremote/Makefile b/litex/build/sim/core/modules/jtagremote/Makefile new file mode 100644 index 00000000..950d4914 --- /dev/null +++ b/litex/build/sim/core/modules/jtagremote/Makefile @@ -0,0 +1,5 @@ +include ../variables.mak + +all: $(OBJ_DIR)/jtagremote.so + +include ../rules.mak diff --git a/litex/build/sim/core/modules/jtagremote/jtagremote.c b/litex/build/sim/core/modules/jtagremote/jtagremote.c new file mode 100644 index 00000000..6a42b375 --- /dev/null +++ b/litex/build/sim/core/modules/jtagremote/jtagremote.c @@ -0,0 +1,263 @@ +#include +#include +#include +#include "error.h" +#include +#include +#include +#include + +#include +#include "modules.h" + +struct session_s { + char *tdi; + char *tdo; + char *tck; + char *tms; + char *sys_clk; + struct event *ev; + char databuf[2048]; + int data_start; + int datalen; + int cntticks; + int fd; +}; + +struct event_base *base; + +int litex_sim_module_get_args( char *args, char *arg, char **val) +{ + int ret = RC_OK; + json_object *jsobj = NULL; + json_object *obj = NULL; + char *value = NULL; + int r; + + jsobj = json_tokener_parse(args); + if(NULL==jsobj) { + fprintf(stderr, "Error parsing json arg: %s \n", args); + ret=RC_JSERROR; + goto out; + } + if(!json_object_is_type(jsobj, json_type_object)) { + fprintf(stderr, "Arg must be type object! : %s \n", args); + ret=RC_JSERROR; + goto out; + } + obj=NULL; + r = json_object_object_get_ex(jsobj, arg, &obj); + if(!r) { + fprintf(stderr, "Could not find object: \"%s\" (%s)\n", arg, args); + ret=RC_JSERROR; + goto out; + } + value=strdup(json_object_get_string(obj)); + +out: + *val = value; + return ret; +} + +static int litex_sim_module_pads_get( struct pad_s *pads, char *name, void **signal) +{ + int ret; + void *sig = NULL; + int i; + + if(!pads || !name || !signal) { + ret = RC_INVARG; + goto out; + } + + i = 0; + while(pads[i].name) { + if(!strcmp(pads[i].name, name)) { + sig = (void*)pads[i].signal; + break; + } + i++; + } + +out: + *signal = sig; + return ret; +} + +static int jtagremote_start(void *b) +{ + base = (struct event_base *)b; + printf("[jtagremote] loaded (%p)\n", base); + return RC_OK; +} + +void read_handler(int fd, short event, void *arg) +{ + struct session_s *s = (struct session_s*)arg; + char buffer[1024]; + ssize_t read_len; + + int i; + + read_len = read(fd, buffer, 1024); + for(i = 0; i < read_len; i++) + { + s->databuf[(s->data_start + s->datalen ) % 2048] = buffer[i]; + s->datalen++; + } +} + +static void event_handler(int fd, short event, void *arg) +{ + if (event & EV_READ) + read_handler(fd, event, arg); +} + +static void accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx) +{ + struct session_s *s = (struct session_s*)ctx; + struct timeval tv = {1, 0}; + + s->fd = fd; + s->ev = event_new(base, fd, EV_READ | EV_PERSIST , event_handler, s); + event_add(s->ev, &tv); +} + +static void +accept_error_cb(struct evconnlistener *listener, void *ctx) +{ + struct event_base *base = evconnlistener_get_base(listener); + eprintf("ERRROR\n"); + + event_base_loopexit(base, NULL); +} + +static int jtagremote_new(void **sess, char *args) +{ + int ret = RC_OK; + struct session_s *s = NULL; + char *cport = NULL; + int port; + struct evconnlistener *listener; + struct sockaddr_in sin; + + if(!sess) { + ret = RC_INVARG; + goto out; + } + + ret = litex_sim_module_get_args(args, "port", &cport); + if(RC_OK != ret) + goto out; + + printf("Found port %s\n", cport); + sscanf(cport, "%d", &port); + free(cport); + if(!port) { + ret = RC_ERROR; + fprintf(stderr, "Invalid port selected!\n"); + goto out; + } + + s=(struct session_s*)malloc(sizeof(struct session_s)); + if(!s) { + ret = RC_NOENMEM; + goto out; + } + memset(s, 0, sizeof(struct session_s)); + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0); + sin.sin_port = htons(port); + listener = evconnlistener_new_bind(base, accept_conn_cb, s, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1, (struct sockaddr*)&sin, sizeof(sin)); + if (!listener) { + ret=RC_ERROR; + eprintf("Can't bind port %d\n!\n", port); + goto out; + } + evconnlistener_set_error_cb(listener, accept_error_cb); + +out: + *sess=(void*)s; + return ret; +} + +static int jtagremote_add_pads(void *sess, struct pad_list_s *plist) +{ + int ret=RC_OK; + struct session_s *s=(struct session_s*)sess; + struct pad_s *pads; + if(!sess || !plist) { + ret = RC_INVARG; + goto out; + } + pads = plist->pads; + printf("plist name: %s\n", plist->name); + if(!strcmp(plist->name, "jtag")) { + litex_sim_module_pads_get(pads, "tck", (void**)&s->tck); + litex_sim_module_pads_get(pads, "tdi", (void**)&s->tdi); + litex_sim_module_pads_get(pads, "tdo", (void**)&s->tdo); + litex_sim_module_pads_get(pads, "tms", (void**)&s->tms); + } + + if(!strcmp(plist->name, "sys_clk")) + litex_sim_module_pads_get(pads, "sys_clk", (void**)&s->sys_clk); + +out: + return ret; + +} +static int jtagremote_tick(void *sess) +{ + char c, val; + int ret = RC_OK; + + struct session_s *s = (struct session_s*)sess; + if(*s->sys_clk == 0) + return RC_OK; + + s->cntticks++; + if(s->cntticks % 10) + return RC_OK; + + if(s->datalen) + { + c = s->databuf[s->data_start]; + + if((c >= '0') && (c <= '7')){ + *s->tck = ((c - '0') >> 2) & 1; + *s->tms = ((c - '0') >> 1) & 1; + *s->tdi = (c - '0') & 1; + } + if(c == 'R'){ + val = *s->tdo + '0'; + if(-1 == write(s->fd, &val, 1)) { + eprintf("Error writing on socket\n"); + ret = RC_ERROR; + goto out; + } + } + s->data_start = (s->data_start + 1) % 2048; + s->datalen--; + } + +out: + return ret; +} + +static struct ext_module_s ext_mod = { + "jtagremote", + jtagremote_start, + jtagremote_new, + jtagremote_add_pads, + NULL, + jtagremote_tick +}; + +int litex_sim_ext_module_init(int (*register_module)(struct ext_module_s *)) +{ + int ret = RC_OK; + ret = register_module(&ext_mod); + return ret; +}