Skip to content

Commit 8035d1e

Browse files
authored
Merge pull request #24 from psychogenic/v2.0-dev
V2.0 dev
2 parents d5472d7 + 8f3ed80 commit 8035d1e

File tree

8 files changed

+50
-205
lines changed

8 files changed

+50
-205
lines changed

README.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ If you know the specific project's official name, great, you can use that. But
8585

8686
```
8787
>>> tt.shuttle.find('traffic')
88-
[<Design 71: wokwi_german_traffic_light>, <Design 180: wokwi_traffic_light>, <Design 115: wokwi_traffic_light_1>]
88+
[<Design 71: wokwi_german_traffic_light>,
89+
<Design 180: wokwi_traffic_light>,
90+
<Design 115: wokwi_traffic_light_1>]
8991
>>>
9092
>>> tt.shuttle.find('traffic')[0].enable()
9193
ttboard.project_mux: Enable design wokwi_german_traffic_light
@@ -96,10 +98,10 @@ Wokwi projects have horrible names like *tt_um_wokwi_375288605206694913* by defa
9698

9799
```
98100
>>> tt.shuttle.find('wokwi')
99-
[ <Design 298: wokwi_2bit_alu_dice>, <Design 102: wokwi_7_segment_display>, <Design 192: wokwi_7_segment_seconds>,
100-
<Design 32: wokwi_7_segment_seconds_verilog_demo>, <Design 99: wokwi_7segment_display_logic_system_>,
101-
<Design 207: wokwi_agl_corticoneuro1>, <Design 101: wokwi_analog_clock>, <Design 41: wokwi_binary_counter>,
102-
<Design 77: wokwi_blinking_a>, <Design 46: wokwi_character_selector>, <Design 40: wokwi_clock_divider>,
101+
[ <Design 298: wokwi_2bit_alu_dice>, <Design 102: wokwi_7_segment_display>,
102+
<Design 192: wokwi_7_segment_seconds>, <Design 32: wokwi_7_segment_seconds_verilog_demo>,
103+
<Design 99: wokwi_7segment_display_logic_system_>, <Design 207: wokwi_agl_corticoneuro1>,
104+
<Design 101: wokwi_analog_clock>, <Design 41: wokwi_binary_counter>,
103105
# etc...
104106
```
105107

@@ -345,11 +347,16 @@ tt = DemoBoard() # whatever was in DEFAULT.mode of config.ini
345347
tt = DemoBoard(RPMode.SAFE) # all RP2040 pins are inputs
346348
347349
# or: ASIC on board
348-
tt = DemoBoard(RPMode.ASIC_RP_CONTROL) # ASIC drives the inputs (i.e. in0, in1 etc are OUTPUTS for the RP2040)
350+
# ASIC drives the inputs (i.e. ui_in pins are OUTPUTS
351+
# for the RP2040)
352+
tt = DemoBoard(RPMode.ASIC_RP_CONTROL)
353+
349354
350355
# or: ASIC on board but you want to twiddle inputs and clock
351356
# using on-board DIP switches and buttons
352-
tt = DemoBoard(RPMode.ASIC_MANUAL_INPUTS) # ASIC drives only management pins all else are inputs
357+
# ASIC drives only management pins all else are inputs
358+
tt = DemoBoard(RPMode.ASIC_MANUAL_INPUTS)
359+
353360
354361
355362
```
@@ -388,7 +395,9 @@ attributes you can just looking at to see summary info, or print out to see ever
388395

389396
```
390397
>>> tt.user_config.sections
391-
['tt_um_factory_test', 'tt_um_urish_simon', 'tt_um_psychogenic_neptuneproportional', 'tt_um_test', 'tt_um_loopback', 'tt_um_vga_clock', 'tt_um_algofoogle_solo_squash']
398+
['tt_um_factory_test', 'tt_um_urish_simon',
399+
'tt_um_psychogenic_neptuneproportional', 'tt_um_test', 'tt_um_loopback',
400+
'tt_um_vga_clock', 'tt_um_algofoogle_solo_squash']
392401
>>>
393402
>>> tt.user_config.tt_um_urish_simon
394403
<UserProjectConfig tt_um_urish_simon, 50000Hz, mode: ASIC_MANUAL_INPUTS>
@@ -398,7 +407,9 @@ attributes you can just looking at to see summary info, or print out to see ever
398407
>>>
399408
>>> print(tt.user_config.tt_um_vga_clock)
400409
UserProjectConfig tt_um_vga_clock
401-
{'rp_clock_frequency': 1.26e+08, 'mode': 'ASIC_RP_CONTROL', 'clock_frequency': 3.15e+07}
410+
{'rp_clock_frequency': 1.26e+08,
411+
'mode': 'ASIC_RP_CONTROL',
412+
'clock_frequency': 3.15e+07}
402413
```
403414

404415

src/examples/tt_um_factory_test/tt_um_factory_test.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ def __init__(self):
128128

129129

130130

131-
dut = DUT()
132-
dut._log.info("enabled factory test project, running")
133131
runner = cocotb.get_runner()
132+
133+
dut = DUT()
134+
dut._log.info(f"enabled factory test project. Will test with {runner}")
135+
134136
runner.test(dut)

src/examples/tt_um_psychogenic_neptuneproportional/tt_um_psychogenic_neptuneproportional.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,11 @@ def __init__(self):
186186

187187
tt = DemoBoard.get()
188188
tt.shuttle.tt_um_psychogenic_neptuneproportional.enable()
189-
dut = DUT()
190-
dut._log.info("enabled neptune project")
189+
190+
191191
runner = cocotb.get_runner()
192+
dut = DUT()
193+
dut._log.info(f"enabled neptune project, will test with {runner}")
192194
runner.test(dut)
193195

194196

src/examples/tt_um_psychogenic_shaman/tb.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,10 +610,11 @@ def main():
610610
print("No tt_um_psychogenic_shaman in this shuttle?")
611611
return
612612
tt.shuttle.tt_um_psychogenic_shaman.enable()
613+
613614
dut = DUT()
614615
tt.uio_oe_pico.value = dut.oe_pico_setting
615616

616-
dut._log.info("enabled shaman project, running")
617617
runner = cocotb.get_runner()
618+
dut._log.info(f"enabled shaman project. Will test with\n{runner}")
618619
runner.test(dut)
619620

src/ttboard/cocotb/__init__.py

Lines changed: 1 addition & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,186 +1 @@
1-
import asyncio
2-
import io
3-
import sys
4-
5-
from microcotb.time.value import TimeValue
6-
from ttboard.demoboard import DemoBoard
7-
8-
def start_soon(c):
9-
pass
10-
11-
class TestCase:
12-
def __init__(self,
13-
name:str,
14-
func,
15-
timeout_time: float = None,
16-
timeout_unit: str = '',
17-
expect_fail: bool = False,
18-
expect_error:Exception = None,
19-
skip: bool = False,
20-
stage: int = 0):
21-
self.name = name
22-
self.function = func
23-
self.timeout = None
24-
if timeout_time is not None:
25-
if not len(timeout_unit):
26-
raise ValueError('Must specify a timeout_unit when using timeouts')
27-
self.timeout = TimeValue(timeout_time, timeout_unit)
28-
29-
self.expect_fail = expect_fail
30-
self.expect_error = expect_error
31-
self.skip = skip
32-
self.stage = stage
33-
self.failed = False
34-
self.failed_msg = ''
35-
36-
def run(self, dut):
37-
if self.skip:
38-
dut._log.warn(f"{self.name} skip=True")
39-
return
40-
func = self.function
41-
try:
42-
asyncio.run(func(dut))
43-
except Exception as e:
44-
self.failed = True
45-
if not self.expect_fail:
46-
raise e
47-
48-
buf = io.StringIO()
49-
sys.print_exception(e, buf)
50-
dut._log.error(buf.getvalue())
51-
dut._log.warn("Failure was expected")
52-
53-
_RunnerSingleton = None
54-
class Runner:
55-
56-
@classmethod
57-
def get(cls):
58-
global _RunnerSingleton
59-
if _RunnerSingleton is None:
60-
_RunnerSingleton = cls()
61-
62-
return _RunnerSingleton
63-
64-
@classmethod
65-
def clear_all(cls):
66-
global _RunnerSingleton
67-
# clear the singleton
68-
_RunnerSingleton = None
69-
70-
def __init__(self):
71-
self.tests_to_run = dict()
72-
self.test_names = []
73-
74-
def add_test(self, test:TestCase):
75-
if test.name is None:
76-
test.name = f'test_{test.function.__name__}'
77-
self.test_names.append(test.name)
78-
self.tests_to_run[test.name] = test
79-
80-
81-
def test(self, dut):
82-
from microcotb.time.system import SystemTime
83-
from microcotb.clock import Clock
84-
85-
ttdb = DemoBoard.get()
86-
if ttdb.is_auto_clocking:
87-
dut._log.debug("Stopping ttdb auto-clocking")
88-
ttdb.clock_project_stop()
89-
90-
num_failures = 0
91-
num_tests = len(self.test_names)
92-
#failures = dict()
93-
for test_count in range(num_tests):
94-
nm = self.test_names[test_count]
95-
SystemTime.reset()
96-
Clock.clear_all()
97-
test = self.tests_to_run[nm]
98-
99-
if test.timeout is None:
100-
SystemTime.clear_timeout()
101-
else:
102-
SystemTime.set_timeout(test.timeout)
103-
104-
105-
test.failed = False
106-
try:
107-
dut._log.info(f"*** Running Test {test_count+1}/{num_tests}: {nm} ***")
108-
test.run(dut)
109-
if test.expect_fail:
110-
num_failures += 1
111-
dut._log.error(f"*** {nm} expected fail, so PASS ***")
112-
else:
113-
dut._log.warn(f"*** Test '{nm}' PASS ***")
114-
except Exception as e:
115-
116-
test.failed = True
117-
buf = io.StringIO()
118-
sys.print_exception(e, buf)
119-
dut._log.error(buf.getvalue())
120-
if len(e.args):
121-
dut._log.error(f"T*** Test '{nm}' FAIL: {e.args[0]} ***")
122-
if e.args[0] is None or not e.args[0]:
123-
test.failed_msg = ''
124-
else:
125-
test.failed_msg = e.args[0]
126-
127-
num_failures += 1
128-
129-
130-
if num_failures:
131-
dut._log.warn(f"{num_failures}/{len(self.test_names)} tests failed")
132-
else:
133-
dut._log.info(f"All {len(self.test_names)} tests passed")
134-
135-
dut._log.info("*** Summary ***")
136-
for nm in self.test_names:
137-
test = self.tests_to_run[nm]
138-
if test.failed:
139-
if test.expect_fail:
140-
dut._log.warn(f"\tPASS\t{nm}\tFailed as expected {test.failed_msg}")
141-
else:
142-
dut._log.error(f"\tFAIL\t{nm}\t{test.failed_msg}")
143-
else:
144-
if self.tests_to_run[nm].skip:
145-
dut._log.warn(f"\tSKIP\t{nm}")
146-
else:
147-
if test.expect_fail:
148-
dut._log.error(f"\tFAIL\t{nm}\tpassed but expect_fail = True")
149-
else:
150-
dut._log.warn(f"\tPASS\t{nm}")
151-
152-
153-
154-
def get_runner(sim=None):
155-
return Runner.get()
156-
157-
158-
159-
160-
def test(func=None, *,
161-
timeout_time: float = None,
162-
timeout_unit: str = "step",
163-
expect_fail: bool = False,
164-
expect_error:Exception = None,
165-
skip: bool = False,
166-
stage: int = 0,
167-
name: str = None):
168-
169-
def my_decorator_func(func):
170-
runner = Runner.get()
171-
test_name = func.__name__ if name is None else name
172-
test_case = TestCase(test_name, func,
173-
timeout_time,
174-
timeout_unit,
175-
expect_fail,
176-
expect_error,
177-
skip,
178-
stage)
179-
180-
def wrapper_func(dut):
181-
test_case.run(dut)
182-
183-
runner.add_test(test_case)
184-
return wrapper_func
185-
186-
return my_decorator_func
1+
from microcotb import *

src/ttboard/cocotb/dut.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
'''
77
from ttboard.demoboard import DemoBoard, Pins
88
import microcotb.dut
9-
from microcotb.dut import Wire, NoopSignal
9+
from microcotb.dut import NoopSignal
10+
from microcotb.dut import Wire
1011
import ttboard.log as logging
1112

1213

@@ -26,13 +27,19 @@ def value(self, set_to:int):
2627

2728

2829
class DUTWrapper(microcotb.dut.DUT):
30+
TTIOPortNames = ['uo_out', 'ui_in', 'uio_in',
31+
'uio_out', 'uio_oe_pico']
32+
2933
def __init__(self, name:str='DUT'):
3034
self.tt = DemoBoard.get()
3135
# wrap the bare clock pin
3236
self.clk = PinWrapper(self.tt.pins.rp_projclk)
3337
self.rst_n = PinWrapper(self.tt.rst_n)
34-
ports = ['uo_out', 'ui_in', 'uio_in', 'uio_out', 'uio_oe_pico']
35-
for p in ports:
38+
39+
# provide the I/O ports from DemoBoard
40+
# as attribs here
41+
42+
for p in self.TTIOPortNames:
3643
setattr(self, p, getattr(self.tt, p))
3744
self._log = logging.getLogger(name)
3845
self.ena = NoopSignal(1)
@@ -42,6 +49,14 @@ def testing_will_begin(self):
4249
self.tt.clock_project_stop()
4350

4451

52+
def __setattr__(self, name:str, value):
53+
if hasattr(self, name) and name in self.TTIOPortNames:
54+
port = getattr(self, name)
55+
port.value = value
56+
return
57+
super().__setattr__(name, value)
58+
59+
4560
class DUT(DUTWrapper):
4661

4762
def __init__(self, name:str='DUT'):

src/ttboard/ports/io.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@
66
'''
77
import microcotb.ports.io
88

9-
109
class IO(microcotb.ports.io.IO):
1110
pass

0 commit comments

Comments
 (0)