summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/wavelet3d/main.cpp36
-rw-r--r--platform/wavelet3d/mod.mk4
-rw-r--r--platform/wavelet3d/remote_bitbang.cpp300
-rw-r--r--platform/wavelet3d/remote_bitbang.h53
-rw-r--r--platform/wavelet3d/remote_jtag.cpp106
-rw-r--r--platform/wavelet3d/remote_jtag.hpp162
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