summaryrefslogtreecommitdiff
path: root/tb
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-11-19 21:19:18 -0600
committerAlejandro Soto <alejandro@34project.org>2022-11-19 21:19:18 -0600
commit6ebe514137fa41ac015122da4dcaba56af84e531 (patch)
tree0582d0684f130b08ec2b7ea73d57642485245ccf /tb
parent8ec66f50c64501e30ed6adae94f89b90b48de7f0 (diff)
Implement JTAG-UART input
Diffstat (limited to '')
-rw-r--r--tb/interval_timer.cpp2
-rw-r--r--tb/jtag_uart.cpp110
-rw-r--r--tb/jtag_uart.hpp17
-rwxr-xr-xtb/sim/sim.py2
-rw-r--r--tb/top/conspiracion.cpp20
5 files changed, 137 insertions, 14 deletions
diff --git a/tb/interval_timer.cpp b/tb/interval_timer.cpp
index f593894..f790030 100644
--- a/tb/interval_timer.cpp
+++ b/tb/interval_timer.cpp
@@ -1,3 +1,5 @@
+#include <cstdint>
+
#include "avalon.hpp"
#include "interval_timer.hpp"
diff --git a/tb/jtag_uart.cpp b/tb/jtag_uart.cpp
index 78d438e..3bef42e 100644
--- a/tb/jtag_uart.cpp
+++ b/tb/jtag_uart.cpp
@@ -1,3 +1,7 @@
+#include <cstdint>
+
+#include <ncursesw/ncurses.h>
+
#include "avalon.hpp"
#include "jtag_uart.hpp"
@@ -7,22 +11,87 @@ namespace taller::avalon
: slave(base, 8, 4)
{}
+ jtag_uart::~jtag_uart() noexcept
+ {
+ release();
+ }
+
+ void jtag_uart::tick() noexcept
+ {
+ if(!took_over || rx_avail == sizeof rx)
+ {
+ return;
+ }
+
+ if(countdown > 0)
+ {
+ --countdown;
+ return;
+ }
+
+ countdown = 10'000;
+
+ int input = getch();
+ if(input != ERR)
+ {
+ unsigned index = rx_next + rx_avail;
+ if(index >= sizeof rx)
+ {
+ index -= sizeof rx;
+ }
+
+ rx[index] = input;
+ ++rx_avail;
+ }
+
+ ctrl_ac = 1;
+ }
+
bool jtag_uart::read(std::uint32_t addr, std::uint32_t &data) noexcept
{
+ bool valid_read;
+ bool ctrl_ri;
+ bool ctrl_wi;
+ bool ctrl_rrdy;
+
+ std::uint8_t read;
+
switch(addr)
{
case 0:
- data = 0; //TODO
+ read = rx[rx_next];
+ valid_read = rx_avail > 0;
+
+ if(valid_read)
+ {
+ --rx_avail;
+ rx_next = rx_next + 1 < sizeof rx ? rx_next + 1 : 0;
+ }
+
+ data
+ = rx_avail << 16
+ | valid_read << 15
+ | (read & 0xff);
+
break;
case 1:
- data =
- static_cast<std::uint32_t>(ctrl_re) << 0
- | static_cast<std::uint32_t>(ctrl_we) << 1
- //TODO: varios bits
- | static_cast<std::uint32_t>(ctrl_ac) << 10
- //TODO: disponibilidad de tx fifo
- | static_cast<std::uint32_t>(255) << 10;
+ ctrl_ri = ctrl_re && rx_avail > 0;
+
+ // Siempre se puede escribir
+ ctrl_wi = ctrl_we;
+
+ // Este bit no existe pero U-Boot lo espera por alguna razón
+ ctrl_rrdy = rx_avail > 0;
+
+ data
+ = ctrl_re << 0
+ | ctrl_we << 1
+ | ctrl_ri << 8
+ | ctrl_wi << 9
+ | ctrl_ac << 10
+ | ctrl_rrdy << 12
+ | 63 << 16;
break;
}
@@ -36,6 +105,8 @@ namespace taller::avalon
{
case 0:
putchar(data & 0xff);
+ fflush(stdout);
+
ctrl_ac = 1;
break;
@@ -52,4 +123,27 @@ namespace taller::avalon
return true;
}
+
+ void jtag_uart::takeover() noexcept
+ {
+ if(took_over)
+ {
+ return;
+ }
+
+ assert(::initscr() != nullptr);
+ assert(::noecho() != ERR);
+ assert(::nodelay(stdscr, TRUE) != ERR);
+ assert(::cbreak() != ERR);
+
+ took_over = true;
+ }
+
+ void jtag_uart::release() noexcept
+ {
+ if(took_over)
+ {
+ ::endwin();
+ }
+ }
}
diff --git a/tb/jtag_uart.hpp b/tb/jtag_uart.hpp
index 6db50f8..3c378c3 100644
--- a/tb/jtag_uart.hpp
+++ b/tb/jtag_uart.hpp
@@ -11,14 +11,25 @@ namespace taller::avalon
{
public:
jtag_uart(std::uint32_t base) noexcept;
+ ~jtag_uart() noexcept;
+
+ void tick() noexcept;
virtual bool read(std::uint32_t addr, std::uint32_t &data) noexcept final override;
virtual bool write(std::uint32_t addr, std::uint32_t data, unsigned byte_enable) noexcept final override;
+ void takeover() noexcept;
+ void release() noexcept;
+
private:
- bool ctrl_re = false;
- bool ctrl_we = false;
- bool ctrl_ac = true;
+ unsigned countdown = 0;
+ unsigned rx_avail = 0;
+ unsigned rx_next = 0;
+ bool ctrl_re = false;
+ bool ctrl_we = false;
+ bool ctrl_ac = true;
+ bool took_over = false;
+ std::uint8_t rx[64];
};
}
diff --git a/tb/sim/sim.py b/tb/sim/sim.py
index b14e0fd..91fc348 100755
--- a/tb/sim/sim.py
+++ b/tb/sim/sim.py
@@ -249,7 +249,7 @@ mem_dumps = module_get('mem_dumps', [])
if init := module_get('init'):
init()
-exec_args = [verilated, '--headless', '--cycles', str(cycles), '--dump-regs']
+exec_args = [verilated, '--headless', '--no-tty', '--cycles', str(cycles), '--dump-regs']
for rng in mem_dumps:
length = rng.stop - rng.start
diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp
index d710bde..bf0ee89 100644
--- a/tb/top/conspiracion.cpp
+++ b/tb/top/conspiracion.cpp
@@ -192,6 +192,11 @@ int main(int argc, char **argv)
parser, "headless", "Disable video output", {"headless"}
);
+ args::Flag no_tty
+ (
+ parser, "no-tty", "Disable TTY takeoveer", {"no-tty"}
+ );
+
args::ValueFlag<unsigned> cycles
(
parser, "cycles", "Number of core cycles to run", {"cycles"}, 256
@@ -251,7 +256,7 @@ int main(int argc, char **argv)
interconnect<Vconspiracion_vga_domain> avl_vga(*top.conspiracion->plat->vga);
mem<std::uint32_t> hps_ddr3(0x0000'0000, 512 << 20);
- jtag_uart ttyj0(0x3000'0000);
+ jtag_uart ttyJ0(0x3000'0000);
interval_timer timer(0x3002'0000);
mem<std::uint32_t> vram(0x3800'0000, 64 << 20);
null vram_null(0x3800'0000, 64 << 20, 2);
@@ -267,7 +272,7 @@ int main(int argc, char **argv)
bool enable_video = !headless;
avl.attach(hps_ddr3);
- avl.attach(ttyj0);
+ avl.attach(ttyJ0);
avl.attach(timer);
for(auto &slave : consts)
@@ -334,6 +339,7 @@ int main(int argc, char **argv)
if(top.clk_clk)
{
+ ttyJ0.tick();
timer.tick();
}
@@ -364,6 +370,11 @@ int main(int argc, char **argv)
tick();
};
+ if(!no_tty)
+ {
+ ttyJ0.takeover();
+ }
+
top.halt = 0;
top.rst_n = 0;
cycle();
@@ -378,6 +389,11 @@ int main(int argc, char **argv)
}
}
+ if(!no_tty)
+ {
+ ttyJ0.release();
+ }
+
if(enable_trace)
{
trace.close();