gary/tiler/Tiler_Test.bsv

570 lines
14 KiB
Plaintext

package Tiler_Test;
import Connectable::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import StmtFSM::*;
import LFSR::*;
import Probe::*;
import Testing::*;
import Tiler::*;
import VRAM::*;
interface Test;
method Action start();
method Bool done();
endinterface
(* synthesize *)
module mkTestPixelcoordToTileSubcoord(Test);
let testflags <- mkTestFlags();
Reg#(Bool) run <- mkReg(False);
Reg#(Bool) finished <- mkReg(False);
function Action check_pxc_to_tsc(PixelCoord screen_pixel, TilePixelCount pixels_per_tile, TileCount num_tiles, ExtendedPixelCoord scroll_offset, TileCoord want_tile, TilePixelCoord want_subtile);
return action
let got = pixelcoord_to_tilesubcoord(screen_pixel, pixels_per_tile, num_tiles, scroll_offset);
let want = TileSubcoord{tile: want_tile, pixel: want_subtile};
if (testflags.verbose)
$display("pixelcoord_to_tilesubcoord(", screen_pixel, ", ", pixels_per_tile, ", ", num_tiles, ", ", scroll_offset, ") = ", fshow(got), ", want ", fshow(want));
dynamicAssert(got == want, "wrong output from pixelcoord_to_tilesubcoord");
endaction;
endfunction
rule test (run && !finished);
// Basic conversion with 32x8px tiles
check_pxc_to_tsc(0, 8, 32, 0,
0, 0);
check_pxc_to_tsc(5, 8, 32, 0,
0, 5);
check_pxc_to_tsc(7, 8, 32, 0,
0, 7);
check_pxc_to_tsc(8, 8, 32, 0,
1, 0);
check_pxc_to_tsc(9, 8, 32, 0,
1, 1);
// 32x16px tiles
check_pxc_to_tsc(9, 16, 32, 0,
0, 9);
check_pxc_to_tsc(15, 16, 32, 0,
0, 15);
check_pxc_to_tsc(16, 16, 32, 0,
1, 0);
// Tile wraparound at 32x8
check_pxc_to_tsc(255, 8, 32, 0,
31, 7);
check_pxc_to_tsc(256, 8, 32, 0,
0, 0);
check_pxc_to_tsc(511, 8, 32, 0,
31, 7);
check_pxc_to_tsc(512, 8, 32, 0,
0, 0);
// Tile wraparound at 64x8
check_pxc_to_tsc(256, 8, 64, 0,
32, 0);
check_pxc_to_tsc(511, 8, 64, 0,
63, 7);
check_pxc_to_tsc(512, 8, 64, 0,
0, 0);
// Scroll offset
check_pxc_to_tsc(0, 8, 32, 42,
5, 2);
check_pxc_to_tsc(1, 8, 32, 42,
5, 3);
check_pxc_to_tsc(5, 8, 32, 42,
5, 7);
check_pxc_to_tsc(6, 8, 32, 42,
6, 0);
check_pxc_to_tsc(6, 8, 32, 41,
5, 7);
// Scroll offset vs. wraparound
check_pxc_to_tsc(255, 8, 32, 2,
0, 1);
check_pxc_to_tsc(0, 8, 32, 3072,
0, 0);
check_pxc_to_tsc(0, 8, 32, 3071,
31, 7);
finished <= True;
endrule
method Action start() if (!run);
run <= True;
endmethod
method done = finished._read;
endmodule
(* synthesize *)
module mkTestPaletteExpander(Test);
let testflags <- mkTestFlags();
let cycles <- mkCycleCounter();
let dut <- mkPaletteExpander();
let got_probe <- mkProbe();
let got_done_probe <- mkProbe();
(* no_implicit_conditions,fire_when_enabled *)
rule probe_done;
got_done_probe <= dut.done;
endrule
function Action check_pixel(PaletteIndex want);
return action
let got <- dut.pixel();
got_probe <= got;
if (testflags.verbose)
$display("PaletteExpander.pixel() = %0d, want %0d", got, want);
dynamicAssert(got == want, "wrong PaletteExpander output");
let got_done = dut.done();
let want_done = False;
if (testflags.verbose)
$display("PaletteExpander.done() = ", fshow(got_done), ", want ", fshow(want_done));
dynamicAssert(got_done == want_done, "wrong PaletteExpander done()");
dynamicAssert(cycles == 1, "output took more than 1 cycle");
cycles.reset();
endaction;
endfunction
let fsm <- mkFSM(par
seq
dut.expand('h8e, 8, Bpp1);
dut.expand('ha4, 4, Bpp2);
dut.expand('h6c, 2, Bpp4);
dut.expand('h4d, 1, Bpp8);
dut.expand('h8e, 5, Bpp1);
dut.expand('ha4, 3, Bpp2);
dut.expand('h6c, 1, Bpp4);
endseq
seq
cycles.reset();
// 0x8e, 1bpp
check_pixel(1);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(1);
check_pixel(1);
check_pixel(1);
check_pixel(0);
// 0xa4, 2bpp
check_pixel(2);
check_pixel(2);
check_pixel(1);
check_pixel(0);
// 0x6c, 4bpp
check_pixel(6);
check_pixel(12);
// 0x4d, 8bpp
check_pixel('h4d);
// 0x8d, 1bpp, first 5 only
check_pixel(1);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(1);
// 0xa4, 2bpp, first 3 only
check_pixel(2);
check_pixel(2);
check_pixel(1);
// 0x6c, 4bpp, first only
check_pixel(6);
action
dynamicAssert(dut.done, "PaletteExpander not done after processing all requests");
dynamicAssert(cycles == 1, "done flag took too long to assert");
endaction
endseq
endpar);
method start = fsm.start;
method done = fsm.done;
endmodule
(* synthesize *)
module mkTestTileRenderer(Test);
let testflags <- mkTestFlags();
let cycles <- mkCycleCounter();
let vram <- mkVRAM(4);
let dut <- mkTileRenderer();
mkConnection(dut.vram, vram.tile1);
let got_probe <- mkProbe();
let want_probe <- mkProbe();
let done_probe <- mkProbe();
(* no_implicit_conditions,fire_when_enabled *)
rule set_done_probe;
done_probe <= dut.done();
endrule
function Action check_pixel(PaletteIndex want);
return action
let got <- dut.tiles.response.get();
got_probe <= got;
want_probe <= want;
if (testflags.verbose)
$display("TileRenderer.get() = %02x, want %02x", got, want);
dynamicAssert(got == want, "wrong pixel rendered");
endaction;
endfunction
Reg#(VRAMAddr) i <- mkReg(0);
LFSR#(Bit#(8)) rnd <- mkLFSR_8();
let populate_vram = seq
for (i <= 0; i < 32; i <= i+1) action
let val = rnd.value();
if (testflags.verbose)
$display("VRAM.write(%0d, 0x%02x) (%0d, %08b)", i, val, val, val);
vram.cpu.request.put(VRAMRequest{
addr: i,
data: tagged Valid rnd.value
});
rnd.next();
endaction
endseq;
let test_basic_render = seq
dut.tiles.request.put(TileRequest{
tile_row_addr: 1,
start_col: 0,
end_col: 7,
bpp: Bpp1,
flip: False
});
check_pixel(1);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(1);
check_pixel(1);
check_pixel(1);
check_pixel(0);
dut.tiles.request.put(TileRequest{
tile_row_addr: 0,
start_col: 0,
end_col: 7,
bpp: Bpp1,
flip: False
});
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(1);
dut.tiles.request.put(TileRequest{
tile_row_addr: 2,
start_col: 0,
end_col: 7,
bpp: Bpp2,
flip: False
});
check_pixel(1);
check_pixel(0);
check_pixel(1);
check_pixel(3);
check_pixel(2);
check_pixel(2);
check_pixel(3);
check_pixel(1);
dut.tiles.request.put(TileRequest{
tile_row_addr: 2,
start_col: 0,
end_col: 7,
bpp: Bpp4,
flip: False
});
check_pixel(4);
check_pixel(7);
check_pixel(10);
check_pixel(13);
check_pixel(13);
check_pixel(8);
check_pixel(6);
check_pixel(12);
dut.tiles.request.put(TileRequest{
tile_row_addr: 4,
start_col: 0,
end_col: 7,
bpp: Bpp8,
flip: False
});
check_pixel('hd8);
check_pixel('h6c);
check_pixel('h36);
check_pixel('h1b);
check_pixel('h83);
check_pixel('hcf);
check_pixel('he9);
check_pixel('hfa);
endseq;
let test_stalled_consumer = par
seq
dut.tiles.request.put(TileRequest{
tile_row_addr: 12,
start_col: 0,
end_col: 7,
bpp: Bpp8,
flip: False
});
dut.tiles.request.put(TileRequest{
tile_row_addr: 4,
start_col: 0,
end_col: 7,
bpp: Bpp8,
flip: False
});
endseq
seq
check_pixel('h7d);
check_pixel('hb0);
check_pixel('h58);
check_pixel('h2c);
repeat (10) noAction;
check_pixel('h16);
check_pixel('h0b);
check_pixel('h8b);
check_pixel('hcb);
repeat (5) noAction;
check_pixel('hd8);
check_pixel('h6c);
check_pixel('h36);
repeat (5) noAction;
check_pixel('h1b);
check_pixel('h83);
check_pixel('hcf);
check_pixel('he9);
check_pixel('hfa);
endseq
endpar;
let test_scrolled_start = seq
dut.tiles.request.put(TileRequest{
tile_row_addr: 1,
start_col: 3,
end_col: 7,
bpp: Bpp1,
flip: False
});
check_pixel(0);
check_pixel(1);
check_pixel(1);
check_pixel(1);
check_pixel(0);
dut.tiles.request.put(TileRequest{
tile_row_addr: 2,
start_col: 1,
end_col: 7,
bpp: Bpp4,
flip: False
});
check_pixel(7);
check_pixel(10);
check_pixel(13);
check_pixel(13);
check_pixel(8);
check_pixel(6);
check_pixel(12);
dut.tiles.request.put(TileRequest{
tile_row_addr: 4,
start_col: 3,
end_col: 7,
bpp: Bpp2,
flip: False
});
check_pixel(0);
check_pixel(1);
check_pixel(2);
check_pixel(3);
check_pixel(0);
dut.tiles.request.put(TileRequest{
tile_row_addr: 12,
start_col: 3,
end_col: 7,
bpp: Bpp8,
flip: False
});
check_pixel('h2c);
check_pixel('h16);
check_pixel('h0b);
check_pixel('h8b);
check_pixel('hcb);
endseq;
let test_scrolled_end = seq
dut.tiles.request.put(TileRequest{
tile_row_addr: 1,
start_col: 0,
end_col: 5,
bpp: Bpp1,
flip: False
});
check_pixel(1);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(1);
check_pixel(1);
dut.tiles.request.put(TileRequest{
tile_row_addr: 2,
start_col: 0,
end_col: 4,
bpp: Bpp4,
flip: False
});
check_pixel(4);
check_pixel(7);
check_pixel(10);
check_pixel(13);
check_pixel(13);
dut.tiles.request.put(TileRequest{
tile_row_addr: 4,
start_col: 0,
end_col: 4,
bpp: Bpp2,
flip: False
});
check_pixel(3);
check_pixel(1);
check_pixel(2);
check_pixel(0);
check_pixel(1);
dut.tiles.request.put(TileRequest{
tile_row_addr: 12,
start_col: 0,
end_col: 4,
bpp: Bpp8,
flip: False
});
check_pixel('h7d);
check_pixel('hb0);
check_pixel('h58);
check_pixel('h2c);
check_pixel('h16);
endseq;
let test_flipped_tile = seq
dut.tiles.request.put(TileRequest{
tile_row_addr: 1,
start_col: 0,
end_col: 7,
bpp: Bpp1,
flip: True
});
check_pixel(0);
check_pixel(1);
check_pixel(1);
check_pixel(1);
check_pixel(0);
check_pixel(0);
check_pixel(0);
check_pixel(1);
dut.tiles.request.put(TileRequest{
tile_row_addr: 2,
start_col: 0,
end_col: 7,
bpp: Bpp2,
flip: True
});
check_pixel(1);
check_pixel(3);
check_pixel(2);
check_pixel(2);
check_pixel(3);
check_pixel(1);
check_pixel(0);
check_pixel(1);
dut.tiles.request.put(TileRequest{
tile_row_addr: 2,
start_col: 1,
end_col: 5,
bpp: Bpp2,
flip: True
});
// pixels in VRAM order: 1 0 1 3 2 2 3 1
// unflipped slice : _ 0 1 3 2 2 _ _
// flipped pixels : 1 3 2 2 3 1 0 1
// flipped slice : _ 3 2 2 3 1 _ _
check_pixel(3);
check_pixel(2);
check_pixel(2);
check_pixel(3);
check_pixel(1);
endseq;
let fsm <- mkFSM(seq
populate_vram;
test_basic_render;
test_stalled_consumer;
test_scrolled_start;
test_scrolled_end;
test_flipped_tile;
repeat (10) noAction;
endseq);
method start = fsm.start;
method done = fsm.done;
endmodule
module mkTB();
let test_pxc_to_tsc <- mkTestPixelcoordToTileSubcoord();
let test_palette_expander <- mkTestPaletteExpander();
let test_tile_renderer <- mkTestTileRenderer();
Reg#(Scanline) line <- mkReg(0);
runTest(2000,
mkTest("Tiler", seq
mkTest("Tiler/PixelcoordToTilesubcoord", seq
test_pxc_to_tsc.start();
await(test_pxc_to_tsc.done);
endseq);
mkTest("Tiler/PaletteExpander", seq
test_palette_expander.start();
await(test_palette_expander.done);
endseq);
mkTest("Tiler/TileRenderer", seq
test_tile_renderer.start();
await(test_tile_renderer.done);
endseq);
endseq));
endmodule
endpackage