Add support for overlapping data store optimizations

This commit is contained in:
Lucas Scharenbroich 2016-12-08 21:59:46 -06:00
parent 2d25c5c295
commit 243ff5175c
6 changed files with 42 additions and 29 deletions

View File

@ -22,12 +22,10 @@ namespace SpriteCompiler.Test
// STA 3,s
// PHA = 7 cycles
var state = new SpriteGeneratorState(new[] { new SpriteByte(0x11, 0), new SpriteByte(0x11, 3)})
{
A = Register.Constant(0x0011),
S = Register.INITIAL_OFFSET,
P = SpriteGeneratorState.LONG_I
};
var state = SpriteGeneratorState.Init(new[] { new SpriteByte(0x11, 0), new SpriteByte(0x11, 3)});
state.A = Register.Constant(0x0011);
state.S = Register.INITIAL_OFFSET;
state.P = SpriteGeneratorState.LONG_I;
var h = heuristic.Eval(state);

View File

@ -28,7 +28,7 @@ namespace SpriteCompiler.Test
};
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(sprite));
var solution = search.Search(problem, SpriteGeneratorState.Init(sprite));
// Assert : The initial state IS the goal state
WriteOutSolution(solution);
@ -53,7 +53,7 @@ namespace SpriteCompiler.Test
};
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(sprite));
var solution = search.Search(problem, SpriteGeneratorState.Init(sprite));
// Assert : The initial state IS the goal state
WriteOutSolution(solution);
@ -84,7 +84,7 @@ namespace SpriteCompiler.Test
};
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(sprite));
var solution = search.Search(problem, SpriteGeneratorState.Init(sprite));
// Assert : The initial state IS the goal state
WriteOutSolution(solution);

View File

@ -35,7 +35,7 @@ namespace SpriteCompiler.Test
var search = SpriteGeneratorSearchProblem.Create();
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0xAA }));
var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0xAA }));
// Assert
//
@ -62,7 +62,7 @@ namespace SpriteCompiler.Test
var search = SpriteGeneratorSearchProblem.Create();
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0xAA, 0x55 }));
var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0xAA, 0x55 }));
// Assert
//
@ -87,7 +87,7 @@ namespace SpriteCompiler.Test
var search = SpriteGeneratorSearchProblem.Create();
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0x11, 0x22, 0x22 }));
var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0x11, 0x22, 0x22 }));
// Assert
//
@ -113,7 +113,7 @@ namespace SpriteCompiler.Test
var search = SpriteGeneratorSearchProblem.Create();
// Act : solve the problem
var solution = search.Search(problem, new SpriteGeneratorState(new byte[] { 0xAA, 0x55, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }));
var solution = search.Search(problem, SpriteGeneratorState.Init(new byte[] { 0xAA, 0x55, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }));
// Assert
//

View File

@ -8,6 +8,20 @@
{
// Single static reference to the original data set
public static List<SpriteByte> DATASET = null;
public static IDictionary<int, SpriteByte> DATASET_BY_OFFSET = null;
public static SpriteGeneratorState Init(IEnumerable<SpriteByte> bytes)
{
DATASET = bytes.ToList();
DATASET_BY_OFFSET = DATASET.ToDictionary(x => (int)x.Offset, x => x);
return new SpriteGeneratorState();
}
public static SpriteGeneratorState Init(IEnumerable<byte> bytes)
{
return Init(bytes.Select((x, i) => new SpriteByte(x, (ushort)i)));
}
public SpriteGeneratorState()
{

View File

@ -65,8 +65,9 @@
//
// We always try to return actions that write data since that moves us toward the goal state
// Make it more convenient to get data by offset (this will probably be the representation of the state, eventually)
var bytes = state.Bytes.ToDictionary(x => x.Offset, x => x);
// Get the list of remaining bytes by removing the closed list from the global sprite
var open = SpriteGeneratorState.DATASET.Where(x => !state.Closed.Contains(x.Offset)).ToList();
var bytes = open.ToDictionary(x => x.Offset, x => x);
// Get the current byte and current word that exist at the current stack location
var topByte = state.TryGetStackByte(bytes);
@ -112,23 +113,23 @@
// move to the first or last byte of each span. So , take the first byte and then look for any
if (state.A.IsScreenOffset && !state.S.IsScreenOffset && state.LongA)
{
for (var i = 0; i < state.Bytes.Count; i++)
for (var i = 0; i < open.Count; i++)
{
if (i == 0)
{
yield return state.Apply(new MOVE_STACK(state.Bytes[i].Offset - state.A.Value));
yield return state.Apply(new MOVE_STACK(open[i].Offset - state.A.Value));
continue;
}
if (i == state.Bytes.Count - 1)
if (i == open.Count - 1)
{
yield return state.Apply(new MOVE_STACK(state.Bytes[i].Offset - state.A.Value));
yield return state.Apply(new MOVE_STACK(open[i].Offset - state.A.Value));
continue;
}
if ((state.Bytes[i].Offset - state.Bytes[i-1].Offset) > 1)
if ((open[i].Offset - open[i - 1].Offset) > 1)
{
yield return state.Apply(new MOVE_STACK(state.Bytes[i].Offset - state.A.Value));
yield return state.Apply(new MOVE_STACK(open[i].Offset - state.A.Value));
}
}
}
@ -143,12 +144,11 @@
{
var addr = state.S.Value;
// Look for consecutive bytes
var local = state.Bytes.Where(WithinRangeOf(addr, 257)).ToList(); // 16-bit value can extend to the 256th byte
// Look for consecutive bytes. The second byte can come from the DATASET
var local = open.Where(WithinRangeOf(addr, 256)).ToList();
var words = local
.Skip(1)
.Select((x, i) => new { High = x, Low = local[i] })
.Where(p => p.Low.Offset == (p.High.Offset - 1))
.Where(x => SpriteGeneratorState.DATASET_BY_OFFSET.ContainsKey(x.Offset + 1))
.Select(x => new { Low = x, High = SpriteGeneratorState.DATASET_BY_OFFSET[x.Offset + 1] })
.ToList();
foreach (var word in words)
@ -177,7 +177,7 @@
var addr = state.S.Value;
// We can LDA #$XX / STA X,s for any values within 256 bytes of the current address
foreach (var datum in state.Bytes.Where(WithinRangeOf(addr, 256)))
foreach (var datum in open.Where(WithinRangeOf(addr, 256)))
{
var offset = datum.Offset - addr;
yield return state.Apply(new STACK_REL_8_BIT_IMMEDIATE_STORE(datum.Data, (byte)offset));
@ -190,7 +190,7 @@
if (state.A.IsScreenOffset && state.S.IsScreenOffset && state.LongA)
{
var addr = state.S.Value;
foreach (var datum in state.Bytes.Where(x => (x.Offset - addr) > 255 || (x.Offset - addr) < 0))
foreach (var datum in open.Where(x => (x.Offset - addr) > 255 || (x.Offset - addr) < 0))
{
yield return state.Apply(new MOVE_STACK(datum.Offset - state.A.Value));
}

View File

@ -152,10 +152,11 @@
}
}
// Set the global state
var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
var search = SpriteGeneratorSearchProblem.Create();
var solution = search.Search(problem, new SpriteGeneratorState(sprite));
var solution = search.Search(problem, SpriteGeneratorState.Init(data));
WriteOutSolution(solution);
}