URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [jtag/] [jp-io-vpi.c] - Rev 1765
Compare with Previous | Blame | View Log
/* jp-io-vpi.c -- JTAG communications vpi plugin Copyright (C) 2004 György Jeney, nog@sdf.lonestar.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 <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <stdint.h> #include <fcntl.h> #include <sys/un.h> #include <errno.h> #include <vpi_user.h> /* 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 */ static int jp_comm_m; /* The listening socket */ static int jp_comm; /* The socket for communitateing with jp1 */ 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; vpiHandle dat_to_index; if(!jp_got_con) { if(!jp_check_con()) return 0; } ret = read(jp_comm, &dat, 1); if(!ret) return 0; if((ret == -1) && (errno == EAGAIN)) return 0; if(dat & 0x80) { switch(dat & 0x7f) { case 0: /* jp1 wants the TDO */ write(jp_comm, &vpi_out, 1); return 0; case 1: /* jp wants a time-out */ if(count_comp) write(jp_comm, &dat, 1); /* The value is irrelevent */ 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) != vpiMemory) { vpi_printf("$jp_in: Must have a memory as argument!!\n"); vpi_free_object(argv); return 0; } value.format = vpiVectorVal; vec.aval = (dat & 0xf) | 0x10; vec.bval = 0; value.value.vector = &vec; dat_to_index = vpi_handle_by_index(dat_to, 0); vpi_put_value(dat_to_index, &value, 0, vpiNoDelay); vpi_free_object(argv); dat |= 0x10; write(jp_comm, &dat, 1); count_comp = 0; return 0; } /* tells us that we reached a predetermined cycle count */ int jp_wait_time(char *xx) { uint8_t dat = 0; if(jp_waiting) { write(jp_comm, &dat, 1); jp_waiting = 0; } count_comp = 1; return 0; } /*---------------------------------------------------[ VPI<->jp functions ]---*/ int init_sock(char *xx) { struct sockaddr_un 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 destination argument\n"); return 0; } vpiHandle sock = vpi_scan(argv); /* if(vpi_get(vpiConstType, sock) != vpiStringConst) { vpi_printf("$jp_init: Must have a string as argument!!\n"); vpi_free_object(argv); return 0; } */ value.format = vpiStringVal; vpi_get_value(sock, &value); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, value.value.str); if((jp_comm_m = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "Unable to create comm socket\n"); return 0; } if(bind(jp_comm_m, (struct sockaddr *)&addr, sizeof(addr)) == -1) { fprintf(stderr, "Unable to bind to the unix socket %s\n", addr.sun_path); return 0; } if(listen(jp_comm_m, 1) == -1) { fprintf(stderr, "Unable to listen on %s (%s)\n", addr.sun_path, strerror(errno)); return 0; } ret = fcntl(jp_comm_m, F_GETFL); ret |= O_NONBLOCK; fcntl(jp_comm_m, F_SETFL, ret); jp_got_con = 0; jp_waiting = 0; printf("Just registered socket!!!\n"); 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)) == -1) { if(errno == EAGAIN) return 0; fprintf(stderr, "Unable to accept connection (%s)\n", strerror(errno)); return 0; } /* Set the comm socket to non-blocking */ ret = fcntl(jp_comm, F_GETFL); ret |= O_NONBLOCK; fcntl(jp_comm, F_SETFL, ret); 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 };