diff options
Diffstat (limited to '')
| -rw-r--r-- | platform/wavelet3d/main.cpp | 36 | ||||
| -rw-r--r-- | platform/wavelet3d/mod.mk | 4 | ||||
| -rw-r--r-- | platform/wavelet3d/remote_bitbang.cpp | 300 | ||||
| -rw-r--r-- | platform/wavelet3d/remote_bitbang.h | 53 | ||||
| -rw-r--r-- | platform/wavelet3d/remote_jtag.cpp | 106 | ||||
| -rw-r--r-- | platform/wavelet3d/remote_jtag.hpp | 162 |
6 files changed, 290 insertions, 371 deletions
diff --git a/platform/wavelet3d/main.cpp b/platform/wavelet3d/main.cpp index 147bde4..6e33e70 100644 --- a/platform/wavelet3d/main.cpp +++ b/platform/wavelet3d/main.cpp @@ -17,7 +17,7 @@ #include "Vtop.h" -#include "remote_bitbang.h" +#include "remote_jtag.hpp" int main(int argc, char **argv) { @@ -60,17 +60,15 @@ int main(int argc, char **argv) top->dram_arready = 0; top->dram_awready = 0; - top->jtag_tck = 0; - top->jtag_tms = 0; - top->jtag_tdi = 0; + top->jtag_tck = 1; + top->jtag_tms = 1; + top->jtag_tdi = 1; cycle(); top->rst_n = 1; cycle(); - rbs_init(1234); - struct a_req { unsigned id, addr, len; @@ -121,7 +119,8 @@ int main(int argc, char **argv) fclose(flash_img); - do { + auto sys_bus_cycle = [&]() + { cycle(); //FIXME: para respetar AXI hay que top->eval()'ear luedo de levantar valid @@ -219,18 +218,23 @@ int main(int argc, char **argv) .data = top->dram_wdata, .strb = top->dram_wstrb, }); + }; - unsigned char tck = top->jtag_tck; - unsigned char tms = top->jtag_tms; - unsigned char tdi = top->jtag_tdi; - unsigned char trstn = 1; + remote_jtag jtag(1234); - rbs_tick(&tck, &tms, &tdi, &trstn, top->jtag_tdo); + do { + sys_bus_cycle(); + + if (jtag.pending()) { + unsigned char trstn = 1; - top->jtag_tck = tck; - top->jtag_tms = tms; - top->jtag_tdi = tdi; - } while (!(client_fd < 0)); + jtag.process + ( + &top->jtag_tck, &top->jtag_tms, &top->jtag_tdi, &trstn, &top->jtag_tdo, + [&]() { sys_bus_cycle(); } + ); + } + } while (jtag.alive()); #if VM_TRACE trace->close(); diff --git a/platform/wavelet3d/mod.mk b/platform/wavelet3d/mod.mk index 05e435e..77382f1 100644 --- a/platform/wavelet3d/mod.mk +++ b/platform/wavelet3d/mod.mk @@ -1,10 +1,10 @@ define core - $(this)/deps := gfx if_common + $(this)/deps := axixbar if_common gfx $(this)/rtl_top := w3d_top $(this)/rtl_dirs := . $(this)/rtl_files := w3d_top.sv - $(this)/vl_main := main.cpp remote_bitbang.cpp + $(this)/vl_main := main.cpp remote_jtag.cpp $(this)/vl_pkgconfig := sdl2 endef diff --git a/platform/wavelet3d/remote_bitbang.cpp b/platform/wavelet3d/remote_bitbang.cpp deleted file mode 100644 index 5e87233..0000000 --- a/platform/wavelet3d/remote_bitbang.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// https://github.com/pulp-platform/riscv-dbg/blob/master/tb/remote_bitbang/remote_bitbang.c -// See LICENSE.Berkeley for license details. - -#include <arpa/inet.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -#include "remote_bitbang.h" - -//Public globals, declared in remote_bitbang.h - -int rbs_err; - -unsigned char tck; -unsigned char tms; -unsigned char tdi; -unsigned char trstn; -unsigned char tdo; -unsigned char quit; - -int socket_fd; -int client_fd; - -//static const ssize_t buf_size = 64 * 1024; -char recv_buf[64 * 1024]; -ssize_t recv_start, recv_end; - -int rbs_init(uint16_t port) -{ - socket_fd = 0; - client_fd = 0; - recv_start = 0; - recv_end = 0; - rbs_err = 0; - - socket_fd = socket(AF_INET, SOCK_STREAM, 0); - if (socket_fd == -1) { - fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n", - strerror(errno), errno); - abort(); - } - - fcntl(socket_fd, F_SETFL, O_NONBLOCK); - int reuseaddr = 1; - if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, - sizeof(int)) == -1) { - fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n", - strerror(errno), errno); - abort(); - } - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(port); - - if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n", - strerror(errno), errno); - abort(); - } - - if (listen(socket_fd, 1) == -1) { - fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n", - strerror(errno), errno); - abort(); - } - - socklen_t addrlen = sizeof(addr); - if (getsockname(socket_fd, (struct sockaddr *)&addr, &addrlen) == -1) { - fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n", - strerror(errno), errno); - abort(); - } - - tck = 1; - tms = 1; - tdi = 1; - trstn = 1; - quit = 0; - - fprintf(stderr, "JTAG remote bitbang server is ready\n"); - fprintf(stderr, "Listening on port %d\n", ntohs(addr.sin_port)); - return 1; -} - -void rbs_accept() -{ - fprintf(stderr, "Attempting to accept client socket\n"); - int again = 1; - while (again != 0) { - client_fd = accept(socket_fd, NULL, NULL); - if (client_fd == -1) { - if (errno == EAGAIN) { - // No client waiting to connect right now. - } else { - fprintf(stderr, "failed to accept on socket: %s (%d)\n", - strerror(errno), errno); - again = 0; - abort(); - } - } else { - fcntl(client_fd, F_SETFL, O_NONBLOCK); - fprintf(stderr, "Accepted successfully.\n"); - again = 0; - } - } -} - -void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms, - unsigned char *jtag_tdi, unsigned char *jtag_trstn, - unsigned char jtag_tdo) -{ - if (client_fd > 0) { - tdo = jtag_tdo; - rbs_execute_command(); - } else { - rbs_accept(); - } - - *jtag_tck = tck; - *jtag_tms = tms; - *jtag_tdi = tdi; - *jtag_trstn = trstn; -} - -void rbs_reset() -{ - trstn = 0; -} - -void rbs_set() -{ - trstn = 1; -} - -void rbs_set_pins(char _tck, char _tms, char _tdi) -{ - tck = _tck; - tms = _tms; - tdi = _tdi; -} - -void rbs_execute_command() -{ - char command; - int again = 1; - while (again) { - ssize_t num_read = read(client_fd, &command, sizeof(command)); - if (num_read == -1) { - if (errno == EAGAIN) { - // We'll try again the next call. - if (VERBOSE) - fprintf( - stderr, - "Received no command. Will try again on the next call\n"); - } else { - fprintf(stderr, - "remote_bitbang failed to read on socket: %s (%d)\n", - strerror(errno), errno); - again = 0; - abort(); - } - } else if (num_read == 0) { - fprintf(stderr, "No command received. Stopping further reads.\n"); - close(client_fd); - client_fd = -1; - // again = 1; - return; - } else { - again = 0; - } - } - - int dosend = 0; - - char tosend = '?'; - - switch (command) { - case 'B': - if (VERBOSE) - fprintf(stderr, "*BLINK*\n"); - break; - case 'b': - if (VERBOSE) - fprintf(stderr, "blink off\n"); - break; - case 'r': - if (VERBOSE) - fprintf(stderr, "r-reset\n"); - rbs_set(); //r-reset command deasserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt - break; - case 's': - if (VERBOSE) - fprintf(stderr, "s-reset\n"); - rbs_set(); //s-reset command deasserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt - break; - case 't': - if (VERBOSE) - fprintf(stderr, "t-reset\n"); - rbs_reset(); //t-reset command asserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt - break; - case 'u': - if (VERBOSE) - fprintf(stderr, "u-reset\n"); - rbs_reset(); //u-reset command asserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt - break; - case '0': - if (VERBOSE) - fprintf(stderr, "Write 0 0 0\n"); - rbs_set_pins(0, 0, 0); - break; - case '1': - if (VERBOSE) - fprintf(stderr, "Write 0 0 1\n"); - rbs_set_pins(0, 0, 1); - break; - case '2': - if (VERBOSE) - fprintf(stderr, "Write 0 1 0\n"); - rbs_set_pins(0, 1, 0); - break; - case '3': - if (VERBOSE) - fprintf(stderr, "Write 0 1 1\n"); - rbs_set_pins(0, 1, 1); - break; - case '4': - if (VERBOSE) - fprintf(stderr, "Write 1 0 0\n"); - rbs_set_pins(1, 0, 0); - break; - case '5': - if (VERBOSE) - fprintf(stderr, "Write 1 0 1\n"); - rbs_set_pins(1, 0, 1); - break; - case '6': - if (VERBOSE) - fprintf(stderr, "Write 1 1 0\n"); - rbs_set_pins(1, 1, 0); - break; - case '7': - if (VERBOSE) - fprintf(stderr, "Write 1 1 1\n"); - rbs_set_pins(1, 1, 1); - break; - case 'R': - if (VERBOSE) - fprintf(stderr, "Read req\n"); - dosend = 1; - tosend = tdo ? '1' : '0'; - break; - case 'Q': - if (VERBOSE) - fprintf(stderr, "Quit req\n"); - quit = 1; - break; - default: - fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", - command); - } - if (dosend) { - while (1) { - ssize_t bytes = write(client_fd, &tosend, sizeof(tosend)); - if (bytes == -1) { - fprintf(stderr, "failed to write to socket: %s (%d)\n", - strerror(errno), errno); - abort(); - } - if (bytes > 0) { - break; - } - } - } - - if (quit) { - fprintf(stderr, "Remote end disconnected\n"); - close(client_fd); - client_fd = 0; - } -} - -unsigned char rbs_done() -{ - return quit; -} - -int rbs_exit_code() -{ - return rbs_err; -} diff --git a/platform/wavelet3d/remote_bitbang.h b/platform/wavelet3d/remote_bitbang.h deleted file mode 100644 index 0e294e8..0000000 --- a/platform/wavelet3d/remote_bitbang.h +++ /dev/null @@ -1,53 +0,0 @@ -// https://github.com/pulp-platform/riscv-dbg/blob/master/tb/remote_bitbang/remote_bitbang.h -// See LICENSE.Berkeley for license details. - -#ifndef REMOTE_BITBANG_H -#define REMOTE_BITBANG_H - -#include <stdint.h> -#include <sys/types.h> - -#define VERBOSE 0 - -extern int rbs_err; - -extern unsigned char tck; -extern unsigned char tms; -extern unsigned char tdi; -extern unsigned char trstn; -extern unsigned char tdo; -extern unsigned char quit; - -extern int socket_fd; -extern int client_fd; - -//static const ssize_t buf_size = 64 * 1024; -extern char recv_buf[64 * 1024]; -extern ssize_t recv_start, recv_end; - -// Create a new server, listening for connections from localhost on the given -// port. -int rbs_init(uint16_t port); - -// Do a bit of work. -void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms, - unsigned char *jtag_tdi, unsigned char *jtag_trstn, - unsigned char jtag_tdo); - -unsigned char rbs_done(); - -int rbs_exit_code(); - -// Check for a client connecting, and accept if there is one. -void rbs_accept(); -// Execute any commands the client has for us. -// But we only execute 1 because we need time for the -// simulation to run. -void rbs_execute_command(); - -void rbs_reset(); //Assert TRST -void rbs_set(); //Deassert TRST - -void rbs_set_pins(char _tck, char _tms, char _tdi); - -#endif diff --git a/platform/wavelet3d/remote_jtag.cpp b/platform/wavelet3d/remote_jtag.cpp new file mode 100644 index 0000000..26d1835 --- /dev/null +++ b/platform/wavelet3d/remote_jtag.cpp @@ -0,0 +1,106 @@ +// https://github.com/pulp-platform/riscv-dbg/blob/master/tb/remote_bitbang/remote_bitbang.c +// See LICENSE.Berkeley for license details. + +#include <arpa/inet.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#include "remote_jtag.hpp" + +remote_jtag::remote_jtag(uint16_t port) +{ + this->socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 0) { + fprintf(stderr, "remote_bitbang failed to make socket: %m\n"); + abort(); + } + + int reuseaddr = 1; + if (setsockopt(this->socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof reuseaddr) < 0) { + fprintf(stderr, "remote_bitbang failed setsockopt: %m\n"); + abort(); + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); + addr.sin_port = htons(port); + + if (bind(this->socket_fd, (struct sockaddr *)&addr, sizeof addr) < 0) { + fprintf(stderr, "remote_bitbang failed to bind socket: %m\n"); + abort(); + } + + if (listen(this->socket_fd, 1) < -1) { + fprintf(stderr, "remote_bitbang failed to listen on socket: %m\n"); + abort(); + } + + fprintf(stderr, "JTAG remote bitbang server is ready\n"); + fprintf(stderr, "Listening on port %d\n", ntohs(addr.sin_port)); + + this->poll_thread = std::thread([this]() { this->poll_main(); }); +} + +remote_jtag::~remote_jtag() +{ + if (this->poll_thread.joinable()) + this->poll_thread.join(); + + if (this->socket_fd >= 0) { + close(this->socket_fd); + this->socket_fd = -1; + } +} + +void remote_jtag::poll_main() +{ + fprintf(stderr, "Attempting to accept client socket\n"); + + int client_fd = accept(this->socket_fd, NULL, NULL); + if (client_fd < 0) { + fprintf(stderr, "failed to accept on socket: %m\n"); + this->dead.store(true, std::memory_order_relaxed); + return; + } else + fprintf(stderr, "Accepted successfully.\n"); + + std::unique_lock<std::mutex> lock(this->buffer_lock); + while (true) { + this->read_bytes = read(client_fd, this->in_buffer, sizeof this->in_buffer); + this->readable.store(true, std::memory_order_relaxed); + + this->processed_cond.wait + ( + lock, [&] { return !this->readable.load(std::memory_order_relaxed); } + ); + + if (this->read_bytes <= 0 || this->dead.load(std::memory_order_relaxed)) + break; + + unsigned write_size = this->write_bytes; + unsigned write_start = 0; + + while (write_size > 0) { + auto written = write(client_fd, &this->out_buffer[write_start], write_size); + if (written <= 0) { + fprintf(stderr, "jtag write() failed: %m\n"); + break; + } + + write_size -= written; + write_start += written; + } + } + + close(client_fd); + this->dead.store(true, std::memory_order_relaxed); +} diff --git a/platform/wavelet3d/remote_jtag.hpp b/platform/wavelet3d/remote_jtag.hpp new file mode 100644 index 0000000..0e842de --- /dev/null +++ b/platform/wavelet3d/remote_jtag.hpp @@ -0,0 +1,162 @@ +// https://github.com/pulp-platform/riscv-dbg/blob/master/tb/remote_bitbang/remote_bitbang.h +// See LICENSE.Berkeley for license details. + +#ifndef REMOTE_JTAG_HPP +#define REMOTE_JTAG_HPP + +#include <atomic> +#include <cstdint> +#include <condition_variable> +#include <mutex> +#include <thread> + +class remote_jtag +{ + public: + remote_jtag(std::uint16_t port); + ~remote_jtag(); + + inline bool pending() noexcept + { + return this->readable.load(std::memory_order_relaxed); + } + + inline bool alive() noexcept + { + return !this->dead.load(std::memory_order_relaxed); + } + + template<typename F> + void process + ( + unsigned char *tck, + unsigned char *tms, + unsigned char *tdi, + unsigned char *trstn, + unsigned char *tdo, + F &&cycle + ); + + private: + int socket_fd = -1; + std::atomic<bool> readable = false; + std::atomic<bool> dead = false; + char in_buffer[512]; + char out_buffer[512]; + ssize_t read_bytes = 0; + unsigned write_bytes = 0; + std::mutex buffer_lock; + std::condition_variable processed_cond; + std::thread poll_thread; + + void poll_main(); +}; + +template<typename F> +void remote_jtag::process +( + unsigned char *tck, + unsigned char *tms, + unsigned char *tdi, + unsigned char *trstn, + unsigned char *tdo, + F &&cycle +) +{ + std::unique_lock<std::mutex> lock(this->buffer_lock); + + char command; + + if (this->read_bytes > 0) { + this->write_bytes = 0; + for (ssize_t i = 0; i < this->read_bytes; ++i) { + char command = this->in_buffer[i]; + + int dosend = 0; + char tosend = '?'; + + switch (command) { + case 'B': + break; + case 'b': + break; + case 'r': + *trstn = 1; //r-reset command deasserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt + break; + case 's': + *trstn = 1; //s-reset command deasserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt + break; + case 't': + *trstn = 0; //t-reset command asserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt + break; + case 'u': + *trstn = 0; //u-reset command asserts TRST. See: openocd/blob/master/doc/manual/jtag/drivers/remote_bitbang.txt + break; + case '0': + *tck = 0; + *tms = 0; + *tdi = 0; + break; + case '1': + *tck = 0; + *tms = 0; + *tdi = 1; + break; + case '2': + *tck = 0; + *tms = 1; + *tdi = 0; + break; + case '3': + *tck = 0; + *tms = 1; + *tdi = 1; + break; + case '4': + *tck = 1; + *tms = 0; + *tdi = 0; + break; + case '5': + *tck = 1; + *tms = 0; + *tdi = 1; + break; + case '6': + *tck = 1; + *tms = 1; + *tdi = 0; + break; + case '7': + *tck = 1; + *tms = 1; + *tdi = 1; + break; + case 'R': + dosend = 1; + tosend = *tdo ? '1' : '0'; + break; + case 'Q': + fprintf(stderr, "Remote end disconnected\n"); + this->dead.store(true, std::memory_order_relaxed); + break; + default: + fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", command); + break; + } + + if (dosend) + this->out_buffer[this->write_bytes++] = tosend; + + cycle(); + } + } else if (this->read_bytes < 0) + fprintf(stderr, "jtag read() failed\n"); + + this->readable.store(false, std::memory_order_relaxed); + lock.unlock(); + + this->processed_cond.notify_one(); +} + +#endif |
