--- /dev/null
--- /dev/null
++#include <arpa/inet.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <algorithm>
++#include <cassert>
++#include <cstdio>
++
++#include "remote_bitbang.h"
++
++#if 1
++# define D(x) x
++#else
++# define D(x)
++#endif
++
++/////////// remote_bitbang_t
++
++remote_bitbang_t::remote_bitbang_t(uint16_t port, jtag_dtm_t *tap) :
++ tap(tap),
++ socket_fd(0),
++ client_fd(0),
++ recv_start(0),
++ recv_end(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();
++ }
++
++ printf("Listening for remote bitbang connection on port %d.\n",
++ ntohs(addr.sin_port));
++ fflush(stdout);
++}
++
++void remote_bitbang_t::accept()
++{
++ 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);
++ abort();
++ }
++ } else {
++ fcntl(client_fd, F_SETFL, O_NONBLOCK);
++ }
++}
++
++void remote_bitbang_t::tick()
++{
++ if (client_fd > 0) {
++ execute_commands();
++ } else {
++ this->accept();
++ }
++}
++
++void remote_bitbang_t::execute_commands()
++{
++ static char send_buf[buf_size];
++ unsigned total_processed = 0;
++ bool quit = false;
++ bool in_rti = tap->state() == RUN_TEST_IDLE;
++ bool entered_rti = false;
++ while (1) {
++ if (recv_start < recv_end) {
++ unsigned send_offset = 0;
++ while (recv_start < recv_end) {
++ uint8_t command = recv_buf[recv_start];
++
++ switch (command) {
++ case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
++ case 'b': /* fprintf(stderr, "_______\n"); */ break;
++ case 'r': tap->reset(); break;
++ case '0': tap->set_pins(0, 0, 0); break;
++ case '1': tap->set_pins(0, 0, 1); break;
++ case '2': tap->set_pins(0, 1, 0); break;
++ case '3': tap->set_pins(0, 1, 1); break;
++ case '4': tap->set_pins(1, 0, 0); break;
++ case '5': tap->set_pins(1, 0, 1); break;
++ case '6': tap->set_pins(1, 1, 0); break;
++ case '7': tap->set_pins(1, 1, 1); break;
++ case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
++ case 'Q': quit = true; break;
++ default:
++ fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
++ command);
++ }
++ recv_start++;
++ total_processed++;
++ if (!in_rti && tap->state() == RUN_TEST_IDLE) {
++ entered_rti = true;
++ break;
++ }
++ in_rti = false;
++ }
++ unsigned sent = 0;
++ while (sent < send_offset) {
++ ssize_t bytes = write(client_fd, send_buf + sent, send_offset);
++ if (bytes == -1) {
++ fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
++ abort();
++ }
++ sent += bytes;
++ }
++ }
++
++ if (total_processed > buf_size || quit || entered_rti) {
++ // Don't go forever, because that could starve the main simulation.
++ break;
++ }
++
++ recv_start = 0;
++ recv_end = read(client_fd, recv_buf, buf_size);
++
++ if (recv_end == -1) {
++ if (errno == EAGAIN) {
++ // We'll try again the next call.
++ } else {
++ fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n",
++ strerror(errno), errno);
++ abort();
++ }
++ }
++ if (recv_end == 0 || quit) {
++ // The remote disconnected.
++ close(client_fd);
++ client_fd = 0;
++ break;
++ }
++ }
++}
--- /dev/null
--- /dev/null
++#ifndef REMOTE_BITBANG_H
++#define REMOTE_BITBANG_H
++
++#include <stdint.h>
++
++#include "jtag_dtm.h"
++
++class remote_bitbang_t
++{
++public:
++ // Create a new server, listening for connections from localhost on the given
++ // port.
++ remote_bitbang_t(uint16_t port, jtag_dtm_t *tap);
++
++ // Do a bit of work.
++ void tick();
++
++private:
++ jtag_dtm_t *tap;
++
++ int socket_fd;
++ int client_fd;
++
++ static const ssize_t buf_size = 64 * 1024;
++ char recv_buf[buf_size];
++ ssize_t recv_start, recv_end;
++
++ // Check for a client connecting, and accept if there is one.
++ void accept();
++ // Execute any commands the client has for us.
++ void execute_commands();
++};
++
++#endif
unsigned csr_priv = get_field((which), 0x300); \
unsigned csr_read_only = get_field((which), 0xC00) == 3; \
if (((write) && csr_read_only) || STATE.prv < csr_priv) \
- throw trap_illegal_instruction(); \
+ throw trap_illegal_instruction(0); \
(which); })
-#define DEBUG_START 0x100
-#define DEBUG_ROM_START 0x800
-#define DEBUG_ROM_RESUME (DEBUG_ROM_START + 4)
-#define DEBUG_ROM_EXCEPTION (DEBUG_ROM_START + 8)
-#define DEBUG_ROM_END (DEBUG_ROM_START + debug_rom_raw_len)
-#define DEBUG_RAM_START 0x400
+#define DEBUG_START 0x20000
+#define DEBUG_ROM_ENTRY DEBUG_START
+#define DEBUG_ROM_ENTRY_SIZE (1024 * 4)
+#define DEBUG_ROM_CODE (DEBUG_ROM_ENTRY + DEBUG_ROM_ENTRY_SIZE)
+#define DEBUG_ROM_CODE_SIZE 256
+#define DEBUG_ROM_EXCEPTION (DEBUG_ROM_CODE + DEBUG_ROM_CODE_SIZE)
+#define DEBUG_ROM_EXCEPTION_SIZE 4
+#define DEBUG_RAM_START (DEBUG_ROM_EXCEPTION + DEBUG_ROM_EXCEPTION_SIZE)
#define DEBUG_RAM_SIZE 64
#define DEBUG_RAM_END (DEBUG_RAM_START + DEBUG_RAM_SIZE)
-#define DEBUG_END 0xfff
-#define DEBUG_CLEARDEBINT 0x100
-#define DEBUG_SETHALTNOT 0x10c
-#define DEBUG_SIZE (DEBUG_END - DEBUG_START + 1)
+#define DEBUG_END DEBUG_RAM_END
+
+#define DEBUG_EXCHANGE 0x400
+#define DEBUG_EXCHANGE_SIZE 0x20
#endif
void processor_t::disasm(insn_t insn)
{
+ static uint64_t last_pc = 1, last_bits;
+ static uint64_t executions = 1;
+
uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
- fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
- id, state.pc, bits, disassembler->disassemble(insn).c_str());
+ if (last_pc != state.pc || last_bits != bits) {
+ if (executions != 1) {
+ fprintf(stderr, "core %3d: Executed %" PRIx64 " times\n", id, executions);
+ }
+
+ fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
+ id, state.pc, bits, disassembler->disassemble(insn).c_str());
+ last_pc = state.pc;
+ last_bits = bits;
+ executions = 1;
+ } else {
+ executions++;
+ }
}
- static bool validate_vm(int max_xlen, reg_t vm)
- {
- if (max_xlen == 64 && (vm == VM_SV39 || vm == VM_SV48))
- return true;
- if (max_xlen == 32 && vm == VM_SV32)
- return true;
- return vm == VM_MBARE;
- }
-
int processor_t::paddr_bits()
{
assert(xlen == max_xlen);
regnames.cc \
devices.cc \
rom.cc \
+ rtc.cc \
+ clint.cc \
+ gdbserver.cc \
debug_module.cc \
+ remote_bitbang.cc \
+ jtag_dtm.cc \
$(riscv_gen_srcs) \
riscv_test_srcs =
void set_log(bool value);
void set_histogram(bool value);
void set_procs_debug(bool value);
- void set_gdbserver(gdbserver_t* gdbserver) { this->gdbserver = gdbserver; }
+ void set_remote_bitbang(remote_bitbang_t* remote_bitbang) {
+ this->remote_bitbang = remote_bitbang;
+ }
- const char* get_config_string() { return config_string.c_str(); }
+ const char* get_dts() { return dts.c_str(); }
processor_t* get_core(size_t i) { return procs.at(i); }
+ unsigned nprocs() const { return procs.size(); }
+
+ debug_module_t debug_module;
private:
char* mem; // main memory
size_t memsz; // memory size in bytes
mmu_t* debug_mmu; // debug port into main memory
std::vector<processor_t*> procs;
- std::string config_string;
+ std::string dts;
std::unique_ptr<rom_device_t> boot_rom;
- std::unique_ptr<rtc_t> rtc;
+ std::unique_ptr<clint_t> clint;
bus_t bus;
- debug_module_t debug_module;
processor_t* get_core(const std::string& i);
void step(size_t n); // step through simulation
fprintf(stderr, " --l2=<S>:<W>:<B> B both powers of 2).\n");
fprintf(stderr, " --extension=<name> Specify RoCC Extension\n");
fprintf(stderr, " --extlib=<name> Shared library to load\n");
- fprintf(stderr, " --gdb-port=<port> Listen on <port> for gdb to connect\n");
+ fprintf(stderr, " --rbb-port=<port> Listen on <port> for remote bitbang connection\n");
- fprintf(stderr, " --dump-config-string Print platform configuration string and exit\n");
+ fprintf(stderr, " --dump-dts Print device tree string and exit\n");
exit(1);
}
auto argv1 = parser.parse(argv);
std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc);
sim_t s(isa, nprocs, mem_mb, halted, htif_args);
- std::unique_ptr<gdbserver_t> gdbserver;
- if (gdb_port) {
- gdbserver = std::unique_ptr<gdbserver_t>(new gdbserver_t(gdb_port, &s));
- s.set_gdbserver(&(*gdbserver));
+ std::unique_ptr<jtag_dtm_t> jtag_dtm(new jtag_dtm_t(&s.debug_module));
+ std::unique_ptr<remote_bitbang_t> remote_bitbang((remote_bitbang_t *) NULL);
+ if (use_rbb) {
+ remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm)));
+ s.set_remote_bitbang(&(*remote_bitbang));
}
- if (dump_config_string) {
- printf("%s", s.get_config_string());
+ if (dump_dts) {
+ printf("%s", s.get_dts());
return 0;
}