Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ec0b7fbde4dd
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: bafd6096ed5d
Choose a head ref
  • 4 commits
  • 9 files changed
  • 1 contributor

Commits on Jul 31, 2020

  1. Copy the full SHA
    fa209e5 View commit details
  2. applet: simplify and improve run_lower().

      * We only ever call run_lower() on the topmost applet in the stack
        (and this seems unlikely to change), so remove logic that was
        guarding against other cases.
      * If the topmost applet in the stack has its own run_lower(), e.g.
        because an inheritance-based solution is not a good fit, then
        this method will be called rather than run() of the superclass.
    whitequark committed Jul 31, 2020
    Copy the full SHA
    09698ab View commit details
  3. Copy the full SHA
    a920c3a View commit details
  4. Copy the full SHA
    bafd609 View commit details
32 changes: 19 additions & 13 deletions software/glasgow/applet/__init__.py
Original file line number Diff line number Diff line change
@@ -252,8 +252,9 @@ def _prepare_hardware_target(self, case, fixture, mode):
assert mode in ("record", "replay")

if mode == "record":
self.device = None # in case the next line raises
self.device = GlasgowHardwareDevice()
self.device.demultiplexer = DirectDemultiplexer(self.device)
self.device.demultiplexer = DirectDemultiplexer(self.device, pipe_count=1)
revision = self.device.revision
else:
self.device = None
@@ -266,23 +267,23 @@ def _prepare_hardware_target(self, case, fixture, mode):
self._recording = False
self._recorders = []

old_run_lower = self.applet.run_lower

async def run_lower(cls, device, args):
if cls is type(self.applet):
if mode == "record":
lower_iface = await super(cls, self.applet).run(device, args)
recorder = MockRecorder(case, lower_iface, fixture)
self._recorders.append(recorder)
return recorder
if mode == "record":
lower_iface = await old_run_lower(cls, device, args)
recorder = MockRecorder(case, lower_iface, fixture)
self._recorders.append(recorder)
return recorder

if mode == "replay":
return MockReplayer(case, fixture)

if mode == "replay":
return MockReplayer(case, fixture)
else:
return await super(cls, self.applet).run(device, args)
self.applet.run_lower = run_lower

async def run_hardware_applet(self, mode):
if mode == "record":
await self.device.download_target(self.target)
await self.device.download_target(self.target.build_plan())

return await self.applet.run(self.device, self._parsed_args)

@@ -350,6 +351,10 @@ def run_test():
nonlocal exception
exception = e

finally:
if self.device is not None:
loop.run_until_complete(self.device.demultiplexer.cancel())

thread = threading.Thread(target=run_test)
thread.start()
thread.join()
@@ -363,7 +368,8 @@ def run_test():

finally:
if mode == "record":
self.device.close()
if self.device is not None:
self.device.close()

return wrapper

Original file line number Diff line number Diff line change
@@ -5,9 +5,9 @@
import logging
from nmigen.compat import *

from ...interface.spi_master import SPIMasterSubtarget, SPIMasterInterface
from ... import *
from . import *
from ....interface.spi_master import SPIMasterSubtarget, SPIMasterInterface
from .... import *
from .. import *


class ProgramAVRSPIInterface(ProgramAVRInterface):
@@ -215,15 +215,100 @@ def build(self, target, args):
iface.pads.reset_t.o.eq(~dut_reset)
]

async def run(self, device, args):
async def run_lower(self, cls, device, args):
iface = await device.demultiplexer.claim_interface(self, self.mux_interface, args)
spi_iface = SPIMasterInterface(iface, self.logger)
return SPIMasterInterface(iface, self.logger)

async def run(self, device, args):
spi_iface = await self.run_lower(ProgramAVRSPIApplet, device, args)
avr_iface = ProgramAVRSPIInterface(spi_iface, self.logger, self.__addr_dut_reset)
return avr_iface

# -------------------------------------------------------------------------------------------------

from .....database.microchip.avr import *


class ProgramAVRSPIAppletTestCase(GlasgowAppletTestCase, applet=ProgramAVRSPIApplet):
@synthesis_test
def test_build(self):
self.assertBuilds()

# Device used for testing: ATmega32U4
hardware_args = ["-V", "3.3"]
dut_signature = (0x1e, 0x95, 0x87)
dut_device = devices_by_signature[dut_signature]
dut_gold_fuses = (0b11111111, 0b00011000, 0b11001011)
dut_test_fuses = (0b00000000, 0b11000111, 0b11110100)

async def setup_programming(self, mode):
avr_iface = await self.run_hardware_applet(mode)
if mode == "record":
await avr_iface.programming_enable()
return avr_iface

@applet_hardware_test(setup="setup_programming", args=hardware_args)
async def test_api_signature(self, avr_iface):
signature = await avr_iface.read_signature()
self.assertEqual(signature, self.dut_signature)

@applet_hardware_test(setup="setup_programming", args=hardware_args)
async def test_api_calibration(self, avr_iface):
calibration = await avr_iface.read_calibration_range(
range(self.dut_device.calibration_size))
# could be anything, really

@applet_hardware_test(setup="setup_programming", args=hardware_args)
async def test_api_fuses(self, avr_iface):
for index, gold_fuse, test_fuse in \
zip(range(self.dut_device.fuses_size), self.dut_gold_fuses, self.dut_test_fuses):
# program
await avr_iface.write_fuse(index, test_fuse)
# verify
fuse = await avr_iface.read_fuse(index)
self.assertEqual(fuse, test_fuse)
# revert
await avr_iface.write_fuse(index, gold_fuse)
# verify
fuse = await avr_iface.read_fuse(index)
self.assertEqual(fuse, gold_fuse)

@applet_hardware_test(setup="setup_programming", args=hardware_args)
async def test_api_lock_bits(self, avr_iface):
# erase
await avr_iface.chip_erase()
# verify
lock_bits = await avr_iface.read_lock_bits()
self.assertEqual(lock_bits, 0xff)
# program
await avr_iface.write_lock_bits(0b11111110)
# verify
lock_bits = await avr_iface.read_lock_bits()
self.assertEqual(lock_bits, 0xfe)

@applet_hardware_test(setup="setup_programming", args=hardware_args)
async def test_api_program_memory(self, avr_iface):
page = self.dut_device.program_page
# erase
await avr_iface.chip_erase()
# program
await avr_iface.write_program_memory_range(
page // 2, [n for n in range(page)], page)
# verify
data = await avr_iface.read_program_memory_range(range(page * 2))
self.assertEqual(data,
b"\xff" * (page // 2) + bytes([n for n in range(page)]) + b"\xff" * (page // 2))

@applet_hardware_test(setup="setup_programming", args=hardware_args)
async def test_api_eeprom(self, avr_iface):
page = self.dut_device.eeprom_page
# erase
await avr_iface.write_eeprom_range(
0, b"\xff" * page * 2, page)
# program
await avr_iface.write_eeprom_range(
page // 2, [n for n in range(page)], page)
# verify
data = await avr_iface.read_eeprom_range(range(page * 2))
self.assertEqual(data,
b"\xff" * (page // 2) + bytes([n for n in range(page)]) + b"\xff" * (page // 2))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method": "transfer", "async": true, "args": [[56, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00380063"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{"method": "transfer", "async": true, "args": [[193, 0, 0, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00c10000"}}
{"method": "transfer", "async": true, "args": [[193, 0, 1, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc10001"}}
{"method": "transfer", "async": true, "args": [[193, 0, 2, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc10002"}}
{"method": "transfer", "async": true, "args": [[193, 0, 3, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc10003"}}
{"method": "transfer", "async": true, "args": [[194, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc20000"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[193, 0, 0, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00c10000"}}
{"method": "transfer", "async": true, "args": [[193, 0, 1, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc10001"}}
{"method": "transfer", "async": true, "args": [[193, 0, 2, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc10002"}}
{"method": "transfer", "async": true, "args": [[193, 0, 3, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc10003"}}
{"method": "transfer", "async": true, "args": [[194, 0, 4, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "ffc20004"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[193, 0, 2, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00c10002"}}
{"method": "transfer", "async": true, "args": [[193, 0, 3, 1]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00c10003"}}
{"method": "transfer", "async": true, "args": [[194, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "01c20000"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[193, 0, 0, 2]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00c10000"}}
{"method": "transfer", "async": true, "args": [[193, 0, 1, 3]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "02c10001"}}
{"method": "transfer", "async": true, "args": [[194, 0, 4, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "03c20004"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[160, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a000ff"}}
{"method": "transfer", "async": true, "args": [[160, 0, 1, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a000ff"}}
{"method": "transfer", "async": true, "args": [[160, 0, 2, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a00000"}}
{"method": "transfer", "async": true, "args": [[160, 0, 3, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a00001"}}
{"method": "transfer", "async": true, "args": [[160, 0, 4, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a00002"}}
{"method": "transfer", "async": true, "args": [[160, 0, 5, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a00003"}}
{"method": "transfer", "async": true, "args": [[160, 0, 6, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a000ff"}}
{"method": "transfer", "async": true, "args": [[160, 0, 7, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00a000ff"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{"method": "transfer", "async": true, "args": [[172, 160, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00aca000"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[80, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00500000"}}
{"method": "transfer", "async": true, "args": [[172, 160, 0, 255]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00aca000"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "fff000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[80, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "005000ff"}}
{"method": "transfer", "async": true, "args": [[172, 168, 0, 199]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00aca800"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "c7f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[88, 8, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "005808c7"}}
{"method": "transfer", "async": true, "args": [[172, 168, 0, 24]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00aca800"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "18f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[88, 8, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00580818"}}
{"method": "transfer", "async": true, "args": [[172, 164, 0, 244]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00aca400"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "f4f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[80, 8, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "005008f4"}}
{"method": "transfer", "async": true, "args": [[172, 164, 0, 203]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00aca400"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "cbf000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[80, 8, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "005008cb"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{"method": "transfer", "async": true, "args": [[172, 128, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00ac8000"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[88, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "005800ff"}}
{"method": "transfer", "async": true, "args": [[172, 224, 0, 254]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00ace000"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "fef000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000ff"}}
{"method": "transfer", "async": true, "args": [[240, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "00f000fe"}}
{"method": "transfer", "async": true, "args": [[88, 0, 0, 0]], "kwargs": {}, "result": {"__class__": "bytes", "hex": "005800fe"}}
Loading