Skip to content

Commit

Permalink
Merge pull request #24 from psychogenic/v2.0-dev
Browse files Browse the repository at this point in the history
V2.0 dev
  • Loading branch information
psychogenic authored Nov 27, 2024
2 parents d5472d7 + 8f3ed80 commit 8035d1e
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 205 deletions.
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ If you know the specific project's official name, great, you can use that. But

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

```
>>> tt.shuttle.find('wokwi')
[ <Design 298: wokwi_2bit_alu_dice>, <Design 102: wokwi_7_segment_display>, <Design 192: wokwi_7_segment_seconds>,
<Design 32: wokwi_7_segment_seconds_verilog_demo>, <Design 99: wokwi_7segment_display_logic_system_>,
<Design 207: wokwi_agl_corticoneuro1>, <Design 101: wokwi_analog_clock>, <Design 41: wokwi_binary_counter>,
<Design 77: wokwi_blinking_a>, <Design 46: wokwi_character_selector>, <Design 40: wokwi_clock_divider>,
[ <Design 298: wokwi_2bit_alu_dice>, <Design 102: wokwi_7_segment_display>,
<Design 192: wokwi_7_segment_seconds>, <Design 32: wokwi_7_segment_seconds_verilog_demo>,
<Design 99: wokwi_7segment_display_logic_system_>, <Design 207: wokwi_agl_corticoneuro1>,
<Design 101: wokwi_analog_clock>, <Design 41: wokwi_binary_counter>,
# etc...
```

Expand Down Expand Up @@ -345,11 +347,16 @@ tt = DemoBoard() # whatever was in DEFAULT.mode of config.ini
tt = DemoBoard(RPMode.SAFE) # all RP2040 pins are inputs
# or: ASIC on board
tt = DemoBoard(RPMode.ASIC_RP_CONTROL) # ASIC drives the inputs (i.e. in0, in1 etc are OUTPUTS for the RP2040)
# ASIC drives the inputs (i.e. ui_in pins are OUTPUTS
# for the RP2040)
tt = DemoBoard(RPMode.ASIC_RP_CONTROL)
# or: ASIC on board but you want to twiddle inputs and clock
# using on-board DIP switches and buttons
tt = DemoBoard(RPMode.ASIC_MANUAL_INPUTS) # ASIC drives only management pins all else are inputs
# ASIC drives only management pins all else are inputs
tt = DemoBoard(RPMode.ASIC_MANUAL_INPUTS)
```
Expand Down Expand Up @@ -388,7 +395,9 @@ attributes you can just looking at to see summary info, or print out to see ever

```
>>> tt.user_config.sections
['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']
['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']
>>>
>>> tt.user_config.tt_um_urish_simon
<UserProjectConfig tt_um_urish_simon, 50000Hz, mode: ASIC_MANUAL_INPUTS>
Expand All @@ -398,7 +407,9 @@ attributes you can just looking at to see summary info, or print out to see ever
>>>
>>> print(tt.user_config.tt_um_vga_clock)
UserProjectConfig tt_um_vga_clock
{'rp_clock_frequency': 1.26e+08, 'mode': 'ASIC_RP_CONTROL', 'clock_frequency': 3.15e+07}
{'rp_clock_frequency': 1.26e+08,
'mode': 'ASIC_RP_CONTROL',
'clock_frequency': 3.15e+07}
```


Expand Down
2 changes: 1 addition & 1 deletion microcotb
6 changes: 4 additions & 2 deletions src/examples/tt_um_factory_test/tt_um_factory_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ def __init__(self):



dut = DUT()
dut._log.info("enabled factory test project, running")
runner = cocotb.get_runner()

dut = DUT()
dut._log.info(f"enabled factory test project. Will test with {runner}")

runner.test(dut)
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,11 @@ def __init__(self):

tt = DemoBoard.get()
tt.shuttle.tt_um_psychogenic_neptuneproportional.enable()
dut = DUT()
dut._log.info("enabled neptune project")


runner = cocotb.get_runner()
dut = DUT()
dut._log.info(f"enabled neptune project, will test with {runner}")
runner.test(dut)


Expand Down
3 changes: 2 additions & 1 deletion src/examples/tt_um_psychogenic_shaman/tb.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,11 @@ def main():
print("No tt_um_psychogenic_shaman in this shuttle?")
return
tt.shuttle.tt_um_psychogenic_shaman.enable()

dut = DUT()
tt.uio_oe_pico.value = dut.oe_pico_setting

dut._log.info("enabled shaman project, running")
runner = cocotb.get_runner()
dut._log.info(f"enabled shaman project. Will test with\n{runner}")
runner.test(dut)

187 changes: 1 addition & 186 deletions src/ttboard/cocotb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,186 +1 @@
import asyncio
import io
import sys

from microcotb.time.value import TimeValue
from ttboard.demoboard import DemoBoard

def start_soon(c):
pass

class TestCase:
def __init__(self,
name:str,
func,
timeout_time: float = None,
timeout_unit: str = '',
expect_fail: bool = False,
expect_error:Exception = None,
skip: bool = False,
stage: int = 0):
self.name = name
self.function = func
self.timeout = None
if timeout_time is not None:
if not len(timeout_unit):
raise ValueError('Must specify a timeout_unit when using timeouts')
self.timeout = TimeValue(timeout_time, timeout_unit)

self.expect_fail = expect_fail
self.expect_error = expect_error
self.skip = skip
self.stage = stage
self.failed = False
self.failed_msg = ''

def run(self, dut):
if self.skip:
dut._log.warn(f"{self.name} skip=True")
return
func = self.function
try:
asyncio.run(func(dut))
except Exception as e:
self.failed = True
if not self.expect_fail:
raise e

buf = io.StringIO()
sys.print_exception(e, buf)
dut._log.error(buf.getvalue())
dut._log.warn("Failure was expected")

_RunnerSingleton = None
class Runner:

@classmethod
def get(cls):
global _RunnerSingleton
if _RunnerSingleton is None:
_RunnerSingleton = cls()

return _RunnerSingleton

@classmethod
def clear_all(cls):
global _RunnerSingleton
# clear the singleton
_RunnerSingleton = None

def __init__(self):
self.tests_to_run = dict()
self.test_names = []

def add_test(self, test:TestCase):
if test.name is None:
test.name = f'test_{test.function.__name__}'
self.test_names.append(test.name)
self.tests_to_run[test.name] = test


def test(self, dut):
from microcotb.time.system import SystemTime
from microcotb.clock import Clock

ttdb = DemoBoard.get()
if ttdb.is_auto_clocking:
dut._log.debug("Stopping ttdb auto-clocking")
ttdb.clock_project_stop()

num_failures = 0
num_tests = len(self.test_names)
#failures = dict()
for test_count in range(num_tests):
nm = self.test_names[test_count]
SystemTime.reset()
Clock.clear_all()
test = self.tests_to_run[nm]

if test.timeout is None:
SystemTime.clear_timeout()
else:
SystemTime.set_timeout(test.timeout)


test.failed = False
try:
dut._log.info(f"*** Running Test {test_count+1}/{num_tests}: {nm} ***")
test.run(dut)
if test.expect_fail:
num_failures += 1
dut._log.error(f"*** {nm} expected fail, so PASS ***")
else:
dut._log.warn(f"*** Test '{nm}' PASS ***")
except Exception as e:

test.failed = True
buf = io.StringIO()
sys.print_exception(e, buf)
dut._log.error(buf.getvalue())
if len(e.args):
dut._log.error(f"T*** Test '{nm}' FAIL: {e.args[0]} ***")
if e.args[0] is None or not e.args[0]:
test.failed_msg = ''
else:
test.failed_msg = e.args[0]

num_failures += 1


if num_failures:
dut._log.warn(f"{num_failures}/{len(self.test_names)} tests failed")
else:
dut._log.info(f"All {len(self.test_names)} tests passed")

dut._log.info("*** Summary ***")
for nm in self.test_names:
test = self.tests_to_run[nm]
if test.failed:
if test.expect_fail:
dut._log.warn(f"\tPASS\t{nm}\tFailed as expected {test.failed_msg}")
else:
dut._log.error(f"\tFAIL\t{nm}\t{test.failed_msg}")
else:
if self.tests_to_run[nm].skip:
dut._log.warn(f"\tSKIP\t{nm}")
else:
if test.expect_fail:
dut._log.error(f"\tFAIL\t{nm}\tpassed but expect_fail = True")
else:
dut._log.warn(f"\tPASS\t{nm}")



def get_runner(sim=None):
return Runner.get()




def test(func=None, *,
timeout_time: float = None,
timeout_unit: str = "step",
expect_fail: bool = False,
expect_error:Exception = None,
skip: bool = False,
stage: int = 0,
name: str = None):

def my_decorator_func(func):
runner = Runner.get()
test_name = func.__name__ if name is None else name
test_case = TestCase(test_name, func,
timeout_time,
timeout_unit,
expect_fail,
expect_error,
skip,
stage)

def wrapper_func(dut):
test_case.run(dut)

runner.add_test(test_case)
return wrapper_func

return my_decorator_func
from microcotb import *
21 changes: 18 additions & 3 deletions src/ttboard/cocotb/dut.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
'''
from ttboard.demoboard import DemoBoard, Pins
import microcotb.dut
from microcotb.dut import Wire, NoopSignal
from microcotb.dut import NoopSignal
from microcotb.dut import Wire
import ttboard.log as logging


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


class DUTWrapper(microcotb.dut.DUT):
TTIOPortNames = ['uo_out', 'ui_in', 'uio_in',
'uio_out', 'uio_oe_pico']

def __init__(self, name:str='DUT'):
self.tt = DemoBoard.get()
# wrap the bare clock pin
self.clk = PinWrapper(self.tt.pins.rp_projclk)
self.rst_n = PinWrapper(self.tt.rst_n)
ports = ['uo_out', 'ui_in', 'uio_in', 'uio_out', 'uio_oe_pico']
for p in ports:

# provide the I/O ports from DemoBoard
# as attribs here

for p in self.TTIOPortNames:
setattr(self, p, getattr(self.tt, p))
self._log = logging.getLogger(name)
self.ena = NoopSignal(1)
Expand All @@ -42,6 +49,14 @@ def testing_will_begin(self):
self.tt.clock_project_stop()


def __setattr__(self, name:str, value):
if hasattr(self, name) and name in self.TTIOPortNames:
port = getattr(self, name)
port.value = value
return
super().__setattr__(name, value)


class DUT(DUTWrapper):

def __init__(self, name:str='DUT'):
Expand Down
1 change: 0 additions & 1 deletion src/ttboard/ports/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@
'''
import microcotb.ports.io


class IO(microcotb.ports.io.IO):
pass

0 comments on commit 8035d1e

Please sign in to comment.