harness: model the 0x5800000/0x5900000 DMA command/data pair

This commit is contained in:
SDD committed 2026-10-16 01:54:37 +03:00
1 parent 66fe15367b
commit a2f19b2d29
3 files changed
+46

No files matched your search

+15
View File
@@ -86,6 +86,20 @@ static void test_switch_mix_only_when_configured(void)
CHECK(b.read(VT1200_WIN3 + VT1200_OFF_SWITCH) == 0x0070); // returned verbatim
}
static void test_dma_pair_command_completes(void)
{
vt1200_board b;
b.set_model_handshake(true);
b.set_dma_ticks(2);
b.write(VT1200_WIN0, 0x0000); // data port first (as the firmware does)
b.write(VT1200_WIN1, 0x0001); // then a command
CHECK(b.read(VT1200_WIN1) == 0x0001); // accepted
b.tick(); b.tick();
CHECK(b.read(VT1200_WIN1) == 0x0000); // completed
}
int main(void)
{
test_default_read();
@@ -95,6 +109,7 @@ int main(void)
test_windows_are_independent();
test_monitor_switch_accepts_raw_bits_or_position();
test_switch_mix_only_when_configured();
test_dma_pair_command_completes();
std::printf(failures ? "%d FAILURE(S)\n" : "all board tests passed\n", failures);
return failures ? 1 : 0;
}
+18
View File
@@ -18,6 +18,11 @@ uint16_t vt1200_board::read(uint32_t addr)
if (st != m_store.end())
value = st->second;
// DMA command port: while a command is in flight the port reads back the
// latched command; once the configured ticks elapse it reads back 0.
if (m_dma_ticks > 0 && (addr & 0xffff0000) == VT1200_WIN1)
return (m_dma_left > 0) ? m_dma_cmd : (uint16_t)0x0000;
if (m_switch_set && is_switch_port(addr))
return (uint16_t)((value & 0xff8f) | (m_switch_bits & 0x0070));
@@ -41,6 +46,15 @@ void vt1200_board::write(uint32_t addr, uint16_t data)
auto ticks = m_busy_ticks_by_win.find(win);
m_busy_left[win] = (ticks != m_busy_ticks_by_win.end()) ? ticks->second : 0;
}
// A command written to the DMA command port (WIN1) is latched and, when the
// DMA model is configured, starts its completion timer.
if ((addr & 0xffff0000) == VT1200_WIN1)
{
m_dma_cmd = data;
if (m_dma_ticks > 0)
m_dma_left = m_dma_ticks;
}
}
void vt1200_board::tick()
@@ -49,4 +63,8 @@ void vt1200_board::tick()
for (auto &entry : m_busy_left)
if (entry.second > 0)
entry.second--;
// Merge the DMA pair's timer into the same tick.
if (m_dma_left > 0)
m_dma_left--;
}
+13
View File
@@ -53,6 +53,12 @@ public:
}
void set_window_busy_ticks(uint32_t window_base, int n) { m_busy_ticks_by_win[window_base] = n; }
// DMA command/data pair at WIN0 (data) / WIN1 (command). A write to the
// command port is accepted and reads back its value for n ticks; after the
// ticks elapse the command port reads back 0. n == 0 (the default) leaves
// the pair with no DMA semantics, so the port just behaves as a latch.
void set_dma_ticks(int n) { m_dma_ticks = n; }
// Monitor switch (bits 4-6 of the switch port). The argument is accepted
// unambiguously as EITHER the raw register bits (e.g. 0x70) OR a small
// position 0-7: a value above 0x07 is taken as the raw bit pattern, any
@@ -82,6 +88,13 @@ private:
// count for the command currently in flight.
std::map<uint32_t, int> m_busy_ticks_by_win;
std::map<uint32_t, int> m_busy_left;
// DMA command/data pair. m_dma_ticks is the configured completion time;
// m_dma_left is how many ticks remain for the command in flight; m_dma_cmd
// is the value written to the command port. All three only have meaning
// when m_dma_ticks > 0.
int m_dma_ticks = 0;
int m_dma_left = 0;
uint16_t m_dma_cmd = 0;
bool m_switch_set = false; // set_monitor_switch was called
uint16_t m_switch_bits = 0;
};