570 lines
14 KiB
Plaintext
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
|