Add a bus panel to the inspector
Opened this issue · 1 comments
Proposal: Add a new panel to the inspector that visualizes the bus activity of the currently emulated raster line. It would display the data captured by the DMA debugger in a more detailed form. Besides the bus ownership, it would display what's on the address and data buses for each DMA cycle.
Visually, it might resemble the logic analyzer implemented in Tiara:
Update: vAmiga 3.1 will feature a built-in 6-channel logic analyzer:
By default, the logic analyzer visualizes what is happening on the DMA bus. For each cycle, the values on the address bus and the data bus are shown, together with the information about the current bus owner.
Gathering the information comes at almost zero cost, as vAmiga has already collected the data in the past (except for the address bus values).
The logic analyzer runs smoothly in combination with the CPU panel. Since multiple inspectors can run side by side now, we can single-step in one inspector and watch the bus activity in the other. The logic analyzer will automatically update its signal traces after each instruction.
The remaining four channels of the logic analyzer can be mapped to any memory location, such as some address in RAM or a readable chipset register. In addition, the logic analyzer can record the value on the CPU’s IPL line.
The image above shows something strange that needs further investigation (I’ll open up a separate issue). Before switching to interrupt level 3, the IPL value returns to 0 for one DMA cycle. This might be due to some behavior of the IPL signal I’ve forgotten about, a bug in vAmiga, or simply a bug in the logic analyzer (which is brand new).
How does it work internally?
When the user configures the logic analyzer to probe memory contents or other signals, such as IPL, the REG slot in the event scheduler is hijacked. I.e., it lets the REG handler execute in each DMA cycle. The actual recording then happens here:
void
LogicAnalyzer::recordSignals()
{
// Only proceed if this is the main instance
if (isRunAheadInstance()) { return; }
/*
This function records all requested signal values when the logic analyzer
is active. The function is called inside the REG slot handler after all
pending register changes have been performed. As a result, the logic
analyzer sees the Amiga's internal state just as the CPU would see it when
reading from memory. This is fine for memory probing, as the obtained
values are the ones we want to see in the logic analyzer.
However, when examining other signals, we need to pay special attention.
E.g., when probing the CPU's IPL lines, the function getIPL() provides us
with the IPL line the CPU has seen in the previous cycle. This is because
the IPL line is updated by a Paula event, which triggers after this
function has been called but before the CPU queries the signal. The code
below copes with this situation by splitting the recording code into two
separate functions. The first one probes all signals whose values belong
to the current DMA cycle. The second function probes all signals that need
to be recorded with the timestamp of the previous DMA cycle.
The second function is also called when the emulator pauses to complement
the missing signal values.
*/
recordCurrent(agnus.pos.h);
recordDelayed(agnus.pos.hPrev());
}
void
LogicAnalyzer::recordCurrent(isize hpos)
{
for (isize i = 0; i < 4; i++) {
switch (config.channel[i]) {
case PROBE_MEMORY:
record[i][hpos] = isize(mem.spypeek16<ACCESSOR_CPU>(config.addr[i]));
break;
default:
break;
}
}
}
void
LogicAnalyzer::recordDelayed(isize hpos)
{
for (isize i = 0; i < 4; i++) {
switch (config.channel[i]) {
case PROBE_IPL:
record[i][hpos] = cpu.getIPL();
break;
default:
break;
}
}
}