17def run(conn: AcceleratorConnection, platform: str =
"cosim") ->
None:
18 mmio = conn.get_service_mmio()
20 assert data == 0x207D98E5E5100E51
22 assert conn.sysinfo().esi_version() == 0
24 assert m.api_version == 0
28 sysinfo = conn.sysinfo()
29 cycle_count = sysinfo.cycle_count()
30 if cycle_count
is not None:
31 print(f
"Cycle count: {cycle_count}")
32 assert cycle_count > 0, f
"Cycle count should be positive, got {cycle_count}"
36 cycle_count2 = sysinfo.cycle_count()
37 print(f
"Cycle count after delay: {cycle_count2}")
38 assert cycle_count2 > cycle_count, \
39 f
"Cycle count should be monotonically increasing: {cycle_count2} <= {cycle_count}"
43 cycle_count3 = sysinfo.cycle_count()
44 print(f
"Cycle count after second delay: {cycle_count3}")
45 assert cycle_count3 > cycle_count2, \
46 f
"Cycle count should be monotonically increasing: {cycle_count3} <= {cycle_count2}"
48 print(
"Cycle count: not available")
50 clock_freq = sysinfo.core_clock_frequency()
51 print(f
"Clock frequency: {clock_freq} Hz")
52 if platform ==
"cosim":
53 assert clock_freq == 20_000_000, \
54 f
"Expected clock frequency 20_000_000 Hz for cosim, got {clock_freq}"
56 if clock_freq
is not None:
57 print(f
"Core clock frequency: {clock_freq} Hz")
58 assert clock_freq > 0, \
59 f
"Clock frequency should be positive, got {clock_freq}"
61 print(
"Core clock frequency: not available")
63 d = conn.build_accelerator()
65 mmio_svc: esi.accelerator.MMIO
66 for svc
in d.services:
67 if isinstance(svc, esi.accelerator.MMIO):
71 for id, region
in mmio_svc.regions.items():
72 print(f
"Region {id}: {region.base} - {region.base + region.size}")
74 def count_telemetry_counters(module) -> int:
76 isinstance(port, MetricPort)
for port
in module.ports.values())
77 return local_count + sum(
78 count_telemetry_counters(child)
for child
in module.children.values())
80 num_telemetry_counters = count_telemetry_counters(d)
81 assert num_telemetry_counters > 0
84 telemetry_region = next((region
for id, region
in mmio_svc.regions.items()
85 if str(id) ==
"__telemetry_mmio"),
None)
86 assert telemetry_region
is not None, \
87 f
"no __telemetry_mmio region in {[str(i) for i in mmio_svc.regions]}"
88 telemetry_bytes = num_telemetry_counters * 8
89 expected_telemetry_allocation = 1 << (telemetry_bytes - 1).bit_length()
90 assert telemetry_region.size == expected_telemetry_allocation
91 assert len(mmio_svc.regions) == 6
97 def read_offset(mmio_x: MMIORegion, offset: int, add_amt: int):
98 data = mmio_x.read(offset)
99 if data == add_amt + offset:
100 print(f
"PASS: read_offset({offset}, {add_amt}) -> {data}")
102 assert False, f
"read_offset({offset}, {add_amt}) -> {data}"
104 mmio4 = d.ports[
esi.AppID(
"mmio_client", 4)]
105 assert mmio4.descriptor.size == 0x100
106 assert mmio4.descriptor.base % mmio4.descriptor.size == 0
107 read_offset(mmio4, 0, 4)
108 read_offset(mmio4, 13, 4)
110 mmio9 = d.ports[
esi.AppID(
"mmio_client", 9)]
111 assert mmio9.descriptor.size == 0x2000
112 assert mmio9.descriptor.base % mmio9.descriptor.size == 0
113 read_offset(mmio9, 0, 9)
114 read_offset(mmio9, 13, 9)
115 read_offset(mmio9, 0x1000, 9)
116 read_offset(mmio9, 0x1200, 9)
118 mmio14 = d.ports[
esi.AppID(
"mmio_client", 14)]
119 assert mmio14.descriptor.size == 0x100
120 assert mmio14.descriptor.base % mmio14.descriptor.size == 0
121 read_offset(mmio14, 0, 14)
122 read_offset(mmio14, 13, 14)
128 mmio_rw = d.ports[
esi.AppID(
"mmio_rw_client")]
129 assert mmio_rw.descriptor.size == 0x200
130 assert mmio_rw.descriptor.base % mmio_rw.descriptor.size == 0
132 def read_offset_check(i: int, add_amt: int):
135 print(f
"PASS: read_offset_check({i}): {d}")
137 assert False, f
": read_offset_check({i}): {d}"
140 mmio_rw.write(8, add_amt)
141 read_offset_check(0, add_amt)
142 read_offset_check(12, add_amt)
143 read_offset_check(0x140, add_amt)
149 loopback = d.children[
esi.AppID(
"loopback")]
150 recv = loopback.ports[
esi.AppID(
"add")].read_port(
"result")
153 send = loopback.ports[
esi.AppID(
"add")].write_port(
"arg")
157 for mod_info
in m.module_infos:
158 if mod_info.name ==
"LoopbackInOutAdd":
159 loopback_info = mod_info
161 assert loopback_info
is not None
162 add_amt = mod_info.constants[
"add_amt"].value
168 callback = d.children[
esi.AppID(
"callback")]
169 cb_port = callback.ports[
esi.AppID(
"cb")]
170 cb_mmio = callback.ports[
esi.AppID(
"cmd")]
172 recv_data: Optional[int] =
None
174 def my_callback(data: int) -> int:
177 print(f
"Callback received data: {data}")
180 cb_port.connect(my_callback)
181 cb_mmio.write(0x10, 5)
182 while recv_data
is None:
184 assert recv_data == 5
195 print(f
"data: {data}")
196 print(f
"resp: {resp}")
197 assert resp == data + add_amt
201 nb_wr_start = time.time()
204 nb_timeout = nb_wr_start + 5
205 write_succeeded =
False
206 while time.time() < nb_timeout:
207 write_succeeded = send.try_write(data)
211 assert write_succeeded,
"Non-blocking write failed"
213 print(f
"data: {data}")
214 print(f
"resp: {resp}")
215 assert resp == data + add_amt
223 producer_bundle = d.ports[
esi.AppID(
"const_producer")]
224 producer = producer_bundle.read_port(
"data")
226 data = producer.read()
227 producer.disconnect()
228 print(f
"data: {data}")
255 print(
"Testing StructToWindowFunc...")
256 struct_to_window_bundle = d.ports[
esi.AppID(
"struct_to_window")]
259 struct_send = struct_to_window_bundle.write_port(
"arg")
260 struct_send.connect()
263 window_recv = struct_to_window_bundle.read_port(
"result")
264 window_recv.connect()
269 "a": bytearray([0x11, 0x11, 0x11, 0x11]),
270 "b": bytearray([0x22, 0x22, 0x22, 0x22]),
271 "c": bytearray([0x33, 0x33, 0x33, 0x33]),
272 "d": bytearray([0x44, 0x44, 0x44, 0x44])
276 struct_send.write(test_struct)
282 result = window_recv.read()
284 print(f
"Sent struct: {test_struct}")
285 print(f
"Received result: {result}")
288 assert result[
"a"] == test_struct[
289 "a"], f
"Field 'a' mismatch: {result['a']} != {test_struct['a']}"
290 assert result[
"b"] == test_struct[
291 "b"], f
"Field 'b' mismatch: {result['b']} != {test_struct['b']}"
292 assert result[
"c"] == test_struct[
293 "c"], f
"Field 'c' mismatch: {result['c']} != {test_struct['c']}"
294 assert result[
"d"] == test_struct[
295 "d"], f
"Field 'd' mismatch: {result['d']} != {test_struct['d']}"
297 print(
"PASS: StructToWindowFunc test passed")
301 "a": bytearray([0xEF, 0xBE, 0xAD, 0xDE]),
302 "b": bytearray([0xBE, 0xBA, 0xFE, 0xCA]),
303 "c": bytearray([0x78, 0x56, 0x34, 0x12]),
305 bytearray([0x21, 0x43, 0x65, 0x87])
307 struct_send.write(test_struct2)
308 result2 = window_recv.read()
310 print(f
"Sent struct: {test_struct2}")
311 print(f
"Received result: {result2}")
313 assert result2[
"a"] == test_struct2[
314 "a"], f
"Field 'a' mismatch: {result2['a']} != {test_struct2['a']}"
315 assert result2[
"b"] == test_struct2[
316 "b"], f
"Field 'b' mismatch: {result2['b']} != {test_struct2['b']}"
317 assert result2[
"c"] == test_struct2[
318 "c"], f
"Field 'c' mismatch: {result2['c']} != {test_struct2['c']}"
319 assert result2[
"d"] == test_struct2[
320 "d"], f
"Field 'd' mismatch: {result2['d']} != {test_struct2['d']}"
322 print(
"PASS: StructToWindowFunc test 2 passed")
324 struct_send.disconnect()
325 window_recv.disconnect()
331 print(
"Testing WindowToStructFunc...")
332 window_to_struct_bundle = d.ports[
esi.AppID(
"struct_from_window")]
335 window_send = window_to_struct_bundle.write_port(
"arg")
336 window_send.connect()
339 struct_recv = window_to_struct_bundle.read_port(
"result")
340 struct_recv.connect()
345 test_window_struct = {
346 "a": bytearray([0xAA, 0xAA, 0xAA, 0xAA]),
347 "b": bytearray([0xBB, 0xBB, 0xBB, 0xBB]),
348 "c": bytearray([0xCC, 0xCC, 0xCC, 0xCC]),
349 "d": bytearray([0xDD, 0xDD, 0xDD, 0xDD])
353 window_send.write(test_window_struct)
356 result = struct_recv.read()
358 print(f
"Sent windowed struct: {test_window_struct}")
359 print(f
"Received complete struct: {result}")
362 assert result[
"a"] == test_window_struct[
363 "a"], f
"Field 'a' mismatch: {result['a']} != {test_window_struct['a']}"
364 assert result[
"b"] == test_window_struct[
365 "b"], f
"Field 'b' mismatch: {result['b']} != {test_window_struct['b']}"
366 assert result[
"c"] == test_window_struct[
367 "c"], f
"Field 'c' mismatch: {result['c']} != {test_window_struct['c']}"
368 assert result[
"d"] == test_window_struct[
369 "d"], f
"Field 'd' mismatch: {result['d']} != {test_window_struct['d']}"
371 print(
"PASS: WindowToStructFunc test passed")
374 test_window_struct2 = {
375 "a": bytearray([0x01, 0x02, 0x03, 0x04]),
376 "b": bytearray([0x05, 0x06, 0x07, 0x08]),
377 "c": bytearray([0x09, 0x0A, 0x0B, 0x0C]),
378 "d": bytearray([0x0D, 0x0E, 0x0F, 0x10])
380 window_send.write(test_window_struct2)
381 result2 = struct_recv.read()
383 print(f
"Sent windowed struct: {test_window_struct2}")
384 print(f
"Received complete struct: {result2}")
386 assert result2[
"a"] == test_window_struct2[
387 "a"], f
"Field 'a' mismatch: {result2['a']} != {test_window_struct2['a']}"
388 assert result2[
"b"] == test_window_struct2[
389 "b"], f
"Field 'b' mismatch: {result2['b']} != {test_window_struct2['b']}"
390 assert result2[
"c"] == test_window_struct2[
391 "c"], f
"Field 'c' mismatch: {result2['c']} != {test_window_struct2['c']}"
392 assert result2[
"d"] == test_window_struct2[
393 "d"], f
"Field 'd' mismatch: {result2['d']} != {test_window_struct2['d']}"
395 print(
"PASS: WindowToStructFunc test 2 passed")
397 window_send.disconnect()
398 struct_recv.disconnect()
401@cosim_test(HW_DIR / "esi_test.py")