diff options
| author | Alejandro Soto <alejandro@34project.org> | 2023-11-22 08:32:10 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2023-11-22 08:32:10 -0600 |
| commit | 7c2700699b6ef4ba6dc413540d23dcc18f437eeb (patch) | |
| tree | 97bf32c6e24e6e10548967372adf4d63a7146aa2 /tb/top/test_fb.py | |
| parent | d6e962d5b4df637adfb706ae18ac70bd67fe28cd (diff) | |
tb/test_fb: update
Diffstat (limited to 'tb/top/test_fb.py')
| -rw-r--r-- | tb/top/test_fb.py | 160 |
1 files changed, 147 insertions, 13 deletions
diff --git a/tb/top/test_fb.py b/tb/top/test_fb.py index 458f2a7..325fbd8 100644 --- a/tb/top/test_fb.py +++ b/tb/top/test_fb.py @@ -1,29 +1,163 @@ -import struct +from array import array +import itertools, struct, random import cocotb from cocotb.clock import Clock -from cocotb.triggers import Combine, ClockCycles, RisingEdge, Timer, with_timeout -from cocotb_bus.drivers.avalon import AvalonMaster +from cocotb.triggers import Combine, ClockCycles, FallingEdge, RisingEdge, Timer, with_timeout +from cocotb_bus.drivers import BitDriver +from cocotb_bus.drivers.avalon import AvalonMaster, AvalonMemory + +from PIL import Image + +W, H = 640, 480 +FILL = (0, 0, 0) +fb = [FILL] * (H * W) @cocotb.test() async def fp_mat_mul(dut): await cocotb.start(Clock(dut.clk, 2).start()) + dut.cmd_read = 0 + dut.cmd_write = 0 + dut.host_read = 0 + dut.host_write = 0 + dut.mem_readdatavalid.value = 0 + dut.mem_waitrequest.value = 0 + BitDriver(dut.scan_ready, dut.clk).start((1 + (i & 1), 2) for i in itertools.count()) + dut.rst_n.value = 1 await Timer(1) dut.rst_n.value = 0 await Timer(1) dut.rst_n.value = 1 - dut.scan_ready.value = 1 - master = AvalonMaster(dut, 'cmd', dut.clk, case_insensitive=False) + cmd = AvalonMaster(dut, 'cmd', dut.clk, case_insensitive=False) + host = AvalonMaster(dut, 'host', dut.clk, case_insensitive=False) + + vram = array('H', (0 for _ in range(1 << (26 - 1)))) + + async def mem_coro(): + cnt = 0 + addr = None + queue = [] + while True: + await RisingEdge(dut.clk) + + #waitrequest = random.randint(0, 1) + + dut.mem_readdatavalid.value = 0 + #dut.mem_waitrequest.value = waitrequest + + if cnt: + cnt -= 1 + if not cnt: + dut.mem_readdata.value = vram[addr] + dut.mem_readdatavalid.value = 1 + + await FallingEdge(dut.clk) + + if True: #not waitrequest: + mem_addr = dut.mem_address.value.integer >> 1 + if dut.mem_read.value: + #delay = random.randint(2, 5) + delay = 1 + queue.append((delay, mem_addr)) + elif dut.mem_write.value: + vram[mem_addr] = dut.mem_writedata.value + + if not cnt and queue: + cnt, addr = queue[0] + del queue[0] + + async def fb_out(): + f = dut.dut.frag_ + p = f.shade.color + l = f.addr_pipes.out + while True: + await FallingEdge(dut.clk) + if not f.out_valid.value: + continue + + v = p.value.integer + r = v >> 16 & 0xff + g = v >> 8 & 0xff + b = v & 0xff + fb[l.value.integer] = (r, g, b) + + async def dump_coro(): + i = 0 + mfb = [] + lim = W * H + limm1 = lim - 1 + while True: + await FallingEdge(dut.clk) + if not dut.scan_ready.value or not dut.scan_valid.value: + continue + + k = len(mfb) + assert bool(dut.scan_endofpacket.value) == (k == limm1) + assert bool(dut.scan_startofpacket.value) == (k == 0) + v = dut.scan_data.value.integer + r = ((v >> 20) >> 2) & 0xff + g = ((v >> 10) >> 2) & 0xff + b = ((v >> 0) >> 2) & 0xff + mfb.append((r,g,b)) + if k == limm1: + img = Image.new('RGB', (W, H)) + img.putdata(mfb) + img.save(f'render-scan-{i}.png') + mfb = [] + i += 1 + + cocotb.start_soon(fb_out()) + cocotb.start_soon(mem_coro()) + cocotb.start_soon(dump_coro()) + + await host.write(0x200000 >> 1, (0x300000) & 0xffff) + await host.write(0x200002 >> 1, (0x300000) >> 16) + await host.write(0x200004 >> 1, (3 - 1) & 0xffff) + await host.write(0x200006 >> 1, (3 - 1) >> 16) + await host.write(0x200008 >> 1, 0x400000 & 0xffff) + await host.write(0x20000a >> 1, 0x400000 >> 16) + await host.write(0x20000c >> 1, 9 & 0xffff) + await host.write(0x20000e >> 1, 9 >> 16) + + # 0x00000120 | recv m1 + # 0x00001010 | send m1 + # 0x00001010 | send m1 + + await host.write(0x300000 >> 1, 0x00000120 & 0xffff) + await host.write(0x300002 >> 1, 0x00000120 >> 16) + await host.write(0x300004 >> 1, 0x00001010 & 0xffff) + await host.write(0x300006 >> 1, 0x00001010 >> 16) + await host.write(0x300008 >> 1, 0x00001010 & 0xffff) + await host.write(0x30000a >> 1, 0x00001010 >> 16) + + await host.write(0x400000 >> 1, 0x3c003c00 & 0xffff) + await host.write(0x400002 >> 1, 0x3c003c00 >> 16) + await host.write(0x400004 >> 1, 0xa400a555 & 0xffff) + await host.write(0x400006 >> 1, 0xa400a555 >> 16) + await host.write(0x400020 >> 1, 0x3c003c00 & 0xffff) + await host.write(0x400022 >> 1, 0x3c003c00 >> 16) + await host.write(0x400024 >> 1, 0xb100a555 & 0xffff) + await host.write(0x400026 >> 1, 0xb100a555 >> 16) + await host.write(0x400040 >> 1, 0x3c003c00 & 0xffff) + await host.write(0x400042 >> 1, 0x3c003c00 >> 16) + await host.write(0x400044 >> 1, 0xac00b4ab & 0xffff) + await host.write(0x400046 >> 1, 0xac00b4ab >> 16) + + await cmd.write(2, 0x200000) + await cmd.write(3, 1 - 1) + + await cmd.write(1, 0x2ff0000) + await RisingEdge(dut.dut.scanout.vsync) + await cmd.write(1, 0x3ff0000) + + for _ in range(2): + await RisingEdge(dut.dut.scanout.vsync) - for i in range(32): - await master.write(i, int.from_bytes(struct.pack('<e', i + 1), 'little')) + await ClockCycles(dut.clk, 50000) - await ClockCycles(dut.clk, 50) - for i in range(4): - for j in range(4): - read, = struct.unpack('<e', (await master.read(i * 4 + j)).integer.to_bytes(2, 'little')) - expected = sum((1 + i * 4 + k) * (17 + k * 4 + j) for k in range(4)) - assert read == expected, f'expected {expected} at ({i}, {j}), got {read}' + img = Image.new('RGB', (W, H)) + img.putdata(fb) + img.save('render-frag.png') |
