summaryrefslogtreecommitdiff
path: root/tb/interval_timer.cpp
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-11-19 19:36:21 -0600
committerAlejandro Soto <alejandro@34project.org>2022-11-19 19:36:27 -0600
commit8ec66f50c64501e30ed6adae94f89b90b48de7f0 (patch)
treedf0cd1fdd699d179ff87aa40410cabb047f9a9f1 /tb/interval_timer.cpp
parent0aabf3cb8e11409506bf90d6cd0c1125f3df7c04 (diff)
Implement interval timer simulation
Diffstat (limited to '')
-rw-r--r--tb/interval_timer.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/tb/interval_timer.cpp b/tb/interval_timer.cpp
new file mode 100644
index 0000000..f593894
--- /dev/null
+++ b/tb/interval_timer.cpp
@@ -0,0 +1,97 @@
+#include "avalon.hpp"
+#include "interval_timer.hpp"
+
+namespace taller::avalon
+{
+ interval_timer::interval_timer(std::uint32_t base) noexcept
+ : slave(base, 32, 4)
+ {}
+
+ void interval_timer::tick() noexcept
+ {
+ if(!status_run)
+ {
+ return;
+ } else if(count > 0)
+ {
+ --count;
+ } else
+ {
+ count = period;
+ status_to = 1;
+ status_run = control_cont;
+ }
+ }
+
+ bool interval_timer::read(std::uint32_t addr, std::uint32_t &data) noexcept
+ {
+ switch(addr)
+ {
+ case 0:
+ data
+ = status_run << 1
+ | status_to << 0;
+
+ break;
+
+ case 1:
+ data
+ = control_cont << 1
+ | control_ito << 0;
+
+ break;
+
+ case 2:
+ data = period & 0xffff;
+ break;
+
+ case 3:
+ data = period >> 16;
+ break;
+
+ case 4:
+ data = snap & 0xffff;
+ break;
+
+ case 5:
+ data = snap >> 16;
+ break;
+ }
+
+ return true;
+ }
+
+ bool interval_timer::write(std::uint32_t addr, std::uint32_t data, unsigned byte_enable) noexcept
+ {
+ switch(addr)
+ {
+ case 0:
+ status_to = 0;
+ break;
+
+ case 1:
+ control_ito = !!(data & (1 << 0));
+ control_cont = !!(data & (1 << 1));
+
+ status_run = (status_run && !!(data << (1 << 3))) || !!(data << (1 << 2));
+ break;
+
+ case 2:
+ period = (period & 0xffff'0000) | (data & 0xffff);
+ count = period;
+ break;
+
+ case 3:
+ period = (period & 0xffff) | (data & 0xffff) << 16;
+ count = period;
+ break;
+
+ case 4:
+ case 5:
+ snap = count;
+ break;
+ }
+
+ return true;
+ }
+}