1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
from array import array
import itertools, struct, random
import cocotb
from cocotb.clock import Clock
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
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)
await ClockCycles(dut.clk, 50000)
img = Image.new('RGB', (W, H))
img.putdata(fb)
img.save('render-frag.png')
|