diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-11-19 19:36:21 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-11-19 19:36:27 -0600 |
| commit | 8ec66f50c64501e30ed6adae94f89b90b48de7f0 (patch) | |
| tree | df0cd1fdd699d179ff87aa40410cabb047f9a9f1 /tb/interval_timer.cpp | |
| parent | 0aabf3cb8e11409506bf90d6cd0c1125f3df7c04 (diff) | |
Implement interval timer simulation
Diffstat (limited to '')
| -rw-r--r-- | tb/interval_timer.cpp | 97 |
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; + } +} |
