mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-02-22 21:29:07 +00:00
Note differing cycle counts in the line profiler output
This commit is contained in:
parent
95fbfb3ccd
commit
68c7d4bfbd
@ -215,7 +215,17 @@ namespace M6502.Test
|
|||||||
private void Profiler_EmitLine(object? sender, ProfileLineEventArgs e)
|
private void Profiler_EmitLine(object? sender, ProfileLineEventArgs e)
|
||||||
{
|
{
|
||||||
var proportion = (double)e.Cycles / this.profiler.TotalCycles;
|
var proportion = (double)e.Cycles / this.profiler.TotalCycles;
|
||||||
Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, e.Cycles, e.Count, e.Source));
|
|
||||||
|
var cycleDistributions = e.CycleDistributions;
|
||||||
|
Debug.Assert(cycleDistributions.Count > 0);
|
||||||
|
var distributions = "\t#";
|
||||||
|
foreach (var (cycles, count) in cycleDistributions)
|
||||||
|
{
|
||||||
|
distributions += $" {cycles}:{count:N0}";
|
||||||
|
}
|
||||||
|
|
||||||
|
var output = $"\t[{proportion:P2}][{e.Cycles:d9}][{e.Count:d9}]\t{Disassembler.DumpWordValue(e.Address)}:{e.Source}{distributions}";
|
||||||
|
Console.Out.WriteLine(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Profiler_EmitInstruction(object? sender, ProfileInstructionEventArgs e)
|
private void Profiler_EmitInstruction(object? sender, ProfileInstructionEventArgs e)
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
namespace EightBit
|
namespace EightBit
|
||||||
{
|
{
|
||||||
public class ProfileLineEventArgs(string source, long cycles, long count) : CycleCountedEventArgs(cycles, count)
|
public class ProfileLineEventArgs(ushort address, string source, long cycles, long count, Dictionary<int, long> cycleDistributions) : CycleCountedEventArgs(cycles, count)
|
||||||
{
|
{
|
||||||
|
public ushort Address { get; } = address;
|
||||||
|
|
||||||
public string Source { get; } = source;
|
public string Source { get; } = source;
|
||||||
|
|
||||||
|
public Dictionary<int, long> CycleDistributions { get; } = cycleDistributions;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,9 +6,7 @@
|
|||||||
{
|
{
|
||||||
private readonly long[] instructionCounts = new long[0x100];
|
private readonly long[] instructionCounts = new long[0x100];
|
||||||
private readonly long[] instructionCycles = new long[0x100];
|
private readonly long[] instructionCycles = new long[0x100];
|
||||||
private readonly long[] addressCycles = new long[0x10000];
|
private readonly Dictionary<int, long>[] addressCycleDistributions = new Dictionary<int, long>[0x10000]; // Addresses -> cycles -> counts
|
||||||
private readonly long[] addressCounts = new long[0x10000];
|
|
||||||
|
|
||||||
private readonly Dictionary<int, long> scopeCycles = []; // ID -> Cycles
|
private readonly Dictionary<int, long> scopeCycles = []; // ID -> Cycles
|
||||||
|
|
||||||
private readonly M6502 processor;
|
private readonly M6502 processor;
|
||||||
@ -105,7 +103,8 @@
|
|||||||
{
|
{
|
||||||
var symbol = this.symbols.LookupLabelByID(id);
|
var symbol = this.symbols.LookupLabelByID(id);
|
||||||
Debug.Assert(symbol != null);
|
Debug.Assert(symbol != null);
|
||||||
var count = this.addressCounts[symbol.Value];
|
var available = this.ExtractCycleDistribution((ushort)symbol.Value, out var _,out var _, out var count);
|
||||||
|
Debug.Assert(available);
|
||||||
this.OnEmitScope(id, cycles, count);
|
this.OnEmitScope(id, cycles, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,18 +122,13 @@
|
|||||||
// For each memory address
|
// For each memory address
|
||||||
for (var i = 0; i < 0x10000; ++i)
|
for (var i = 0; i < 0x10000; ++i)
|
||||||
{
|
{
|
||||||
// If there are any cycles associated
|
|
||||||
var cycles = this.addressCycles[i];
|
|
||||||
if (cycles > 0)
|
|
||||||
{
|
|
||||||
var count = this.addressCounts[i];
|
|
||||||
Debug.Assert(count > 0);
|
|
||||||
var address = (ushort)i;
|
var address = (ushort)i;
|
||||||
|
var available = this.ExtractCycleDistribution(address, out var cycleDistributions, out var cycles, out var count);
|
||||||
|
if (available)
|
||||||
|
{
|
||||||
// Dump a profile/disassembly line
|
// Dump a profile/disassembly line
|
||||||
var source = this.disassembler.Disassemble(address);
|
var source = this.disassembler.Disassemble(address);
|
||||||
var position = Disassembler.DumpWordValue(address);
|
this.OnEmitLine(address, source, cycles, count, cycleDistributions);
|
||||||
this.OnEmitLine($"{position}:{source}", cycles, count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,7 +171,6 @@
|
|||||||
this.executingAddress = this.processor.Bus.Address.Word;
|
this.executingAddress = this.processor.Bus.Address.Word;
|
||||||
this.executingInstruction = this.processor.Bus.Peek(this.executingAddress);
|
this.executingInstruction = this.processor.Bus.Peek(this.executingAddress);
|
||||||
|
|
||||||
++this.addressCounts[this.executingAddress];
|
|
||||||
++this.instructionCounts[this.processor.Bus.Data];
|
++this.instructionCounts[this.processor.Bus.Data];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,9 +178,19 @@
|
|||||||
{
|
{
|
||||||
var cycles = this.processor.Cycles;
|
var cycles = this.processor.Cycles;
|
||||||
|
|
||||||
this.addressCycles[this.executingAddress] += cycles;
|
{
|
||||||
|
var addressDistribution = this.addressCycleDistributions[this.executingAddress];
|
||||||
|
if (addressDistribution == null)
|
||||||
|
{
|
||||||
|
this.addressCycleDistributions[this.executingAddress] = addressDistribution = [];
|
||||||
|
}
|
||||||
|
_ = addressDistribution.TryGetValue(cycles, out var current);
|
||||||
|
addressDistribution[cycles] = ++current;
|
||||||
|
}
|
||||||
|
|
||||||
this.instructionCycles[this.executingInstruction] += cycles;
|
this.instructionCycles[this.executingInstruction] += cycles;
|
||||||
|
|
||||||
|
{
|
||||||
var scope = this.symbols.LookupScopeByAddress(this.executingAddress);
|
var scope = this.symbols.LookupScopeByAddress(this.executingAddress);
|
||||||
if (scope != null)
|
if (scope != null)
|
||||||
{
|
{
|
||||||
@ -197,6 +200,27 @@
|
|||||||
this.scopeCycles[id] = current + cycles;
|
this.scopeCycles[id] = current + cycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ExtractCycleDistribution(ushort address, out Dictionary<int, long> cycleDistribution, out long cycleCount, out long hitCount)
|
||||||
|
{
|
||||||
|
cycleDistribution = addressCycleDistributions[address];
|
||||||
|
if (cycleDistribution == null)
|
||||||
|
{
|
||||||
|
cycleCount = -1;
|
||||||
|
hitCount = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cycleCount = hitCount = 0L;
|
||||||
|
foreach (var (cycle, count) in cycleDistribution)
|
||||||
|
{
|
||||||
|
hitCount += count;
|
||||||
|
cycleCount += (cycle * count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnStartingOutput()
|
private void OnStartingOutput()
|
||||||
{
|
{
|
||||||
@ -238,9 +262,9 @@
|
|||||||
this.FinishedScopeOutput?.Invoke(this, EventArgs.Empty);
|
this.FinishedScopeOutput?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEmitLine(string source, long cycles, long count)
|
private void OnEmitLine(ushort address, string source, long cycles, long count, Dictionary<int, long> cycleDistributions)
|
||||||
{
|
{
|
||||||
this.EmitLine?.Invoke(this, new ProfileLineEventArgs(source, cycles, count));
|
this.EmitLine?.Invoke(this, new ProfileLineEventArgs(address, source, cycles, count, cycleDistributions));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEmitScope(int id, long cycles, long count)
|
private void OnEmitScope(int id, long cycles, long count)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user