build/sim: add jtagremote module (thanks LamdaConcept)

This commit is contained in:
Florent Kermarrec 2019-01-30 14:01:19 +01:00
parent 57b8bdd530
commit 1d9c55888f
2 changed files with 268 additions and 0 deletions

View File

@ -0,0 +1,5 @@
include ../variables.mak
all: $(OBJ_DIR)/jtagremote.so
include ../rules.mak

View File

@ -0,0 +1,263 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include <unistd.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#include <json-c/json.h>
#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;
}