From 42e614550c6f2df5dba1b2c79a8c264c07f228cc Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Wed, 7 Mar 2018 10:53:49 -0800 Subject: [PATCH] JTAGVPI: remove it in favor of remote bitbang --- csrc/jtag_vpi.c | 430 ---------------------------------------------- vsrc/jtag_vpi.tab | 2 - vsrc/jtag_vpi.v | 301 -------------------------------- 3 files changed, 733 deletions(-) delete mode 100644 csrc/jtag_vpi.c delete mode 100644 vsrc/jtag_vpi.tab delete mode 100644 vsrc/jtag_vpi.v diff --git a/csrc/jtag_vpi.c b/csrc/jtag_vpi.c deleted file mode 100644 index b7a2f201..00000000 --- a/csrc/jtag_vpi.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * TCP/IP controlled VPI JTAG Interface. - * Based on Julius Baxter's work on jp_vpi.c - * - * Copyright (C) 2012 Franck Jullien, - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of any - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -// Calling bind with port 0 will return a socket bound to an unused port. -#define RSP_SERVER_PORT 0 -#define XFERT_MAX_SIZE 512 - -const char * cmd_to_string[] = {"CMD_RESET", - "CMD_TMS_SEQ", - "CMD_SCAN_CHAIN"}; - -struct vpi_cmd { - int cmd; - unsigned char buffer_out[XFERT_MAX_SIZE]; - unsigned char buffer_in[XFERT_MAX_SIZE]; - int length; - int nb_bits; -}; - -int listenfd = 0; -int connfd = 0; - -int init_jtag_server(int port) -{ - struct sockaddr_in serv_addr; - int flags; - - listenfd = socket(AF_INET, SOCK_STREAM, 0); - memset(&serv_addr, '0', sizeof(serv_addr)); - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - serv_addr.sin_port = htons(port); - - bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); - - listen(listenfd, 10); - - socklen_t socklen = sizeof(serv_addr); - if (getsockname(listenfd, (struct sockaddr *)&serv_addr, &socklen) == -1) { - perror("init_jtag_server"); - fflush(stderr); - exit(1); - } else { - printf("Listening on port %d\n", ntohs(serv_addr.sin_port)); - fflush(stdout); - } - - printf("Waiting for client connection..."); - fflush(stdout); - connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); - printf("ok\n"); - fflush(stdout); - - flags = fcntl(listenfd, F_GETFL, 0); - fcntl(listenfd, F_SETFL, flags | O_NONBLOCK); - - return 0; -} - -// See if there's anything on the FIFO for us - -void check_for_command(char *userdata) -{ - vpiHandle systfref, args_iter, argh; - struct t_vpi_value argval; - struct vpi_cmd vpi; - int nb; - int loaded_words = 0; - - (void)userdata; - - // Get the command from TCP server - if(!connfd) - init_jtag_server(RSP_SERVER_PORT); - nb = read(connfd, &vpi, sizeof(struct vpi_cmd)); - - if (((nb < 0) && (errno == EAGAIN)) || (nb == 0)) { - // Nothing in the fifo this time, let's return - return; - } else { - if (nb < 0) { - // some sort of error - perror("check_for_command"); - exit(1); - } - } - -/************* vpi.cmd to VPI ******************************/ - - // Obtain a handle to the argument list - systfref = vpi_handle(vpiSysTfCall, NULL); - // Now call iterate with the vpiArgument parameter - args_iter = vpi_iterate(vpiArgument, systfref); - // get a handle on the variable passed to the function - argh = vpi_scan(args_iter); - // now store the command value back in the sim - argval.format = vpiIntVal; - // Now set the command value - vpi_get_value(argh, &argval); - - argval.value.integer = (uint32_t)vpi.cmd; - - // And vpi_put_value() it back into the sim - vpi_put_value(argh, &argval, NULL, vpiNoDelay); - -/************* vpi.length to VPI ******************************/ - - // now get a handle on the next object (memory array) - argh = vpi_scan(args_iter); - // now store the command value back in the sim - argval.format = vpiIntVal; - // Now set the command value - vpi_get_value(argh, &argval); - - argval.value.integer = (uint32_t)vpi.length; - - // And vpi_put_value() it back into the sim - vpi_put_value(argh, &argval, NULL, vpiNoDelay); - -/************* vpi.nb_bits to VPI ******************************/ - - // now get a handle on the next object (memory array) - argh = vpi_scan(args_iter); - // now store the command value back in the sim - argval.format = vpiIntVal; - // Now set the command value - vpi_get_value(argh, &argval); - - argval.value.integer = (uint32_t)vpi.nb_bits; - - // And vpi_put_value() it back into the sim - vpi_put_value(argh, &argval, NULL, vpiNoDelay); - -/*****************vpi.buffer_out to VPI ********/ - - // now get a handle on the next object (memory array) - argh = vpi_scan(args_iter); - vpiHandle array_word; - - // Loop to load the words - while (loaded_words < vpi.length) { - // now get a handle on the current word we want in the array that was passed to us - array_word = vpi_handle_by_index(argh, loaded_words); - - if (array_word != NULL) { - argval.value.integer = (uint32_t)vpi.buffer_out[loaded_words]; - // And vpi_put_value() it back into the sim - vpi_put_value(array_word, &argval, NULL, vpiNoDelay); - } else - return; - - loaded_words++; - } - -/*******************************************/ - - // Cleanup and return - vpi_free_object(args_iter); -} - -void send_result_to_server(char *userdata) -{ - vpiHandle systfref, args_iter, argh; - struct t_vpi_value argval; - ssize_t n; - struct vpi_cmd vpi; - - int32_t length; - int sent_words; - - vpiHandle array_word; - - (void)userdata; - - // Now setup the handles to verilog objects and check things - // Obtain a handle to the argument list - systfref = vpi_handle(vpiSysTfCall, NULL); - - // Now call iterate with the vpiArgument parameter - args_iter = vpi_iterate(vpiArgument, systfref); - - // get a handle on the length variable - argh = vpi_scan(args_iter); - - argval.format = vpiIntVal; - - // get the value for the length object - vpi_get_value(argh, &argval); - - // now set length - length = argval.value.integer; - - // now get a handle on the next object (memory array) - argh = vpi_scan(args_iter); - - // check we got passed a memory (array of regs) - if (!((vpi_get(vpiType, argh) == vpiMemory) -#ifdef MODELSIM_VPI - || (vpi_get(vpiType, argh) == vpiRegArray) -#endif -#ifdef VCS_VPI - || (vpi_get(vpiType, argh) == vpiRegArray) -#endif - )) { - vpi_printf("jtag_vpi: ERROR: did not pass a memory to get_command_block_data\n"); - vpi_printf("jtag_vpi: ERROR: was passed type %d\n", (int)vpi_get(vpiType, argh)); - return; - } - - // check the memory we're writing into is big enough - if (vpi_get(vpiSize, argh) < length ) { - vpi_printf("jtag_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n", - vpi_get(vpiSize, argh), length); - return; - } - - // Loop to load the words - sent_words = 0; - while (sent_words < length) { - // Get a handle on the current word we want in the array that was passed to us - array_word = vpi_handle_by_index(argh, sent_words); - - if (array_word != NULL) { - vpi_get_value(array_word, &argval); - vpi.buffer_in[sent_words] = (uint32_t) argval.value.integer; - } else - return; - - sent_words++; - } - - n = write(connfd, &vpi, sizeof(struct vpi_cmd)); - if (n < (ssize_t)sizeof(struct vpi_cmd)) - vpi_printf("jtag_vpi: ERROR: error during write to server\n"); - - // Cleanup and return - vpi_free_object(args_iter); -} - -void register_check_for_command(void) -{ - s_vpi_systf_data data = { - vpiSysTask, - 0, - "$check_for_command", - (void *)check_for_command, - 0, - 0, - 0 - }; - - vpi_register_systf(&data); -} - -void register_send_result_to_server(void) -{ - s_vpi_systf_data data = { - vpiSysTask, - 0, - "$send_result_to_server", - (void *)send_result_to_server, - 0, - 0, - 0 - }; - - vpi_register_systf(&data); -} - -void sim_reset_callback(void) -{ - // nothing to do! -} - -void setup_reset_callbacks(void) -{ - // here we setup and install callbacks for - // the setup and management of connections to - // the simulator upon simulation start and - // reset - - static s_vpi_time time_s = {vpiScaledRealTime, 0, 0, 0}; - static s_vpi_value value_s = {.format = vpiBinStrVal}; - - static s_cb_data cb_data_s = { - cbEndOfReset, // or start of simulation - initing socket fds etc - (void *)sim_reset_callback, - NULL, - &time_s, - &value_s, - 0, - NULL - }; - - cb_data_s.obj = NULL; /* trigger object */ - - cb_data_s.user_data = NULL; - - // actual call to register the callback - vpi_register_cb(&cb_data_s); -} - -void sim_endofcompile_callback(void) -{ - -} - -void setup_endofcompile_callbacks(void) -{ - // here we setup and install callbacks for - // simulation finish - - static s_vpi_time time_s = {vpiScaledRealTime, 0, 0, 0}; - static s_vpi_value value_s = {.format = vpiBinStrVal}; - - static s_cb_data cb_data_s = { - cbEndOfCompile, // end of compile - (void *)sim_endofcompile_callback, - NULL, - &time_s, - &value_s, - 0, - NULL - }; - - cb_data_s.obj = NULL; /* trigger object */ - - cb_data_s.user_data = NULL; - - // actual call to register the callback - vpi_register_cb(&cb_data_s); -} - -void sim_finish_callback(void) -{ - if(connfd) - printf("Closing RSP server\n"); - close(connfd); - close(listenfd); -} - -void setup_finish_callbacks(void) -{ - // here we setup and install callbacks for - // simulation finish - - static s_vpi_time time_s = {vpiScaledRealTime, 0, 0, 0}; - static s_vpi_value value_s = {.format = vpiBinStrVal}; - - static s_cb_data cb_data_s = { - cbEndOfSimulation, // end of simulation - (void *)sim_finish_callback, - NULL, - &time_s, - &value_s, - 0, - NULL - }; - - cb_data_s.obj = NULL; /* trigger object */ - cb_data_s.user_data = NULL; - - // actual call to register the callback - vpi_register_cb(&cb_data_s); -} - -#ifndef VCS_VPI -// Register the new system task here -void (*vlog_startup_routines[])(void) = { -#ifdef CDS_VPI - // this installs a callback on simulator reset - something which - // icarus does not do, so we only do it for cadence currently - setup_reset_callbacks, -#endif - setup_endofcompile_callbacks, - setup_finish_callbacks, - register_check_for_command, - register_send_result_to_server, - 0 // last entry must be 0 -}; - -// Entry point for testing development of the vpi functions -int main(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - - return 0; -} -#endif diff --git a/vsrc/jtag_vpi.tab b/vsrc/jtag_vpi.tab deleted file mode 100644 index ac5dcdad..00000000 --- a/vsrc/jtag_vpi.tab +++ /dev/null @@ -1,2 +0,0 @@ -$send_result_to_server call=send_result_to_server acc=rw:* -$check_for_command call=check_for_command acc=rw:* diff --git a/vsrc/jtag_vpi.v b/vsrc/jtag_vpi.v deleted file mode 100644 index ab618093..00000000 --- a/vsrc/jtag_vpi.v +++ /dev/null @@ -1,301 +0,0 @@ -// See LICENSE.SiFive for license details. - -/* - * TCP/IP controlled VPI JTAG Interface. - * Based on Julius Baxter's work on jp_vpi.c - * - * Copyright (C) 2012 Franck Jullien, - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of any - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -//VCS coverage exclude_file -`define CMD_RESET 0 -`define CMD_TMS_SEQ 1 -`define CMD_SCAN_CHAIN 2 -`define CMD_SCAN_CHAIN_FLIP_TMS 3 -`define CMD_STOP_SIMU 4 - -module JTAGVPI -#( parameter DEBUG_INFO = 0, - parameter TP = 1, - parameter TCK_HALF_PERIOD = 2,// 50, // Clock half period (Clock period = 100 ns => 10 MHz) - parameter CMD_DELAY = 2, // 1000 - parameter INIT_DELAY = 200 -) -( - output jtag_TMS, - output jtag_TCK, - output jtag_TDI, - input jtag_TDO_data, - input jtag_TDO_driven, - - input enable, - input init_done); - - reg tms; - reg tck; - reg tdi; - wire tdo; - - assign jtag_TMS = tms; - assign jtag_TCK = tck; - assign jtag_TDI = tdi; - assign tdo = jtag_TDO_driven ? jtag_TDO_data : 1'bz; - -integer cmd; -integer length; -integer nb_bits; - -reg [31:0] buffer_out [0:4095]; // Data storage from the jtag server -reg [31:0] buffer_in [0:4095]; // Data storage to the jtag server - -integer flip_tms; - -reg [31:0] data_out; -reg [31:0] data_in; - -integer debug; - -initial -begin - tck <= #TP 1'b0; - tdi <= #TP 1'bz; - tms <= #TP 1'b0; - - data_out <= 32'h0; - data_in <= 32'h0; - - // Small delay to get past reset instability - // before checking for init_done - #INIT_DELAY - - wait(init_done) - if($test$plusargs("jtag_vpi_enable")) main; -end - -task main; -begin - $display("JTAG debug module with VPI interface enabled\n"); - - reset_tap; - goto_run_test_idle_from_reset; - - while (1) begin - - // Check for incoming command - // wait until a command is sent - // poll with a delay here - cmd = -1; - - while (cmd == -1) - begin - #CMD_DELAY $check_for_command(cmd, length, nb_bits, buffer_out); - end - - // now switch on the command - case (cmd) - - `CMD_RESET : - begin - if (DEBUG_INFO) - $display("%t ----> CMD_RESET %h\n", $time, length); - reset_tap; - goto_run_test_idle_from_reset; - end - - `CMD_TMS_SEQ : - begin - if (DEBUG_INFO) - $display("%t ----> CMD_TMS_SEQ\n", $time); - do_tms_seq; - end - - `CMD_SCAN_CHAIN : - begin - if (DEBUG_INFO) - $display("%t ----> CMD_SCAN_CHAIN\n", $time); - flip_tms = 0; - do_scan_chain; - $send_result_to_server(length, buffer_in); - end - - `CMD_SCAN_CHAIN_FLIP_TMS : - begin - if(DEBUG_INFO) - $display("%t ----> CMD_SCAN_CHAIN\n", $time); - flip_tms = 1; - do_scan_chain; - $send_result_to_server(length, buffer_in); - end - - `CMD_STOP_SIMU : - begin - if(DEBUG_INFO) - $display("%t ----> End of simulation\n", $time); - $finish(); - end - - default: - begin - $display("Somehow got to the default case in the command case statement."); - $display("Command was: %x", cmd); - $display("Exiting..."); - $finish(); - end - - endcase // case (cmd) - - end // while (1) -end - -endtask // main - - -// Generation of the TCK signal -task gen_clk; -input [31:0] number; -integer i; - -begin - for (i = 0; i < number; i = i + 1) - begin - #TCK_HALF_PERIOD tck <= 1; - #TCK_HALF_PERIOD tck <= 0; - end -end - -endtask - -// TAP reset -task reset_tap; -begin - if (DEBUG_INFO) - $display("(%0t) Task reset_tap", $time); - tms <= #1 1'b1; - gen_clk(5); -end - -endtask - - -// Goes to RunTestIdle state -task goto_run_test_idle_from_reset; -begin - if (DEBUG_INFO) - $display("(%0t) Task goto_run_test_idle_from_reset", $time); - tms <= #1 1'b0; - gen_clk(1); -end - -endtask - -// -task do_tms_seq; - -integer i,j; -reg [31:0] data; -integer nb_bits_rem; -integer nb_bits_in_this_byte; - -begin - if (DEBUG_INFO) - $display("(%0t) Task do_tms_seq of %d bits (length = %d)", $time, nb_bits, length); - - // Number of bits to send in the last byte - nb_bits_rem = nb_bits % 8; - - for (i = 0; i < length; i = i + 1) - begin - // If we are in the last byte, we have to send only - // nb_bits_rem bits. If not, we send the whole byte. - nb_bits_in_this_byte = (i == (length - 1)) ? nb_bits_rem : 8; - - data = buffer_out[i]; - for (j = 0; j < nb_bits_in_this_byte; j = j + 1) - begin - tms <= #1 1'b0; - if (data[j] == 1) begin - tms <= #1 1'b1; - end - gen_clk(1); - end - end - - tms <= #1 1'b0; -end - -endtask - - -// -task do_scan_chain; - -integer _bit; -integer nb_bits_rem; -integer nb_bits_in_this_byte; -integer index; - -begin - if(DEBUG_INFO) - $display("(%0t) Task do_scan_chain of %d bits (length = %d)", $time, nb_bits, length); - - // Number of bits to send in the last byte - nb_bits_rem = nb_bits % 8; - - for (index = 0; index < length; index = index + 1) - begin - // If we are in the last byte, we have to send only - // nb_bits_rem bits if it's not zero. - // If not, we send the whole byte. - nb_bits_in_this_byte = (index == (length - 1)) ? ((nb_bits_rem == 0) ? 8 : nb_bits_rem) : 8; - - data_out = buffer_out[index]; - for (_bit = 0; _bit < nb_bits_in_this_byte; _bit = _bit + 1) - begin - tdi <= 1'b0; - if (data_out[_bit] == 1'b1) begin - tdi <= 1'b1; - end - - // On the last bit, set TMS to '1' - if (((_bit == (nb_bits_in_this_byte - 1)) && (index == (length - 1))) && (flip_tms == 1)) begin - tms <= 1'b1; - end - - #TCK_HALF_PERIOD tck <= 1; - data_in[_bit] <= tdo; - #TCK_HALF_PERIOD tck <= 0; - end - buffer_in[index] = data_in; - end - - tdi <= 1'b0; - tms <= 1'b0; -end - -endtask - -endmodule