From dbdd8a5b6b025ce4d454ab439ba7751f53cd9074 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 13 Jan 2024 21:08:42 +0100 Subject: [PATCH 1/2] amaranth_glue: Refactor to improved version from zyp-amaranth-libs. --- .gitmodules | 3 + deps/zyp-amaranth-libs | 1 + orbtrace/amaranth_glue/dfu.py | 14 ++-- orbtrace/amaranth_glue/luna.py | 70 +++++++++---------- orbtrace/amaranth_glue/usb_mem_bridge.py | 36 +++++----- orbtrace/amaranth_glue/wrapper.py | 88 ------------------------ orbtrace/debug/cmsis_dap_wrapper.py | 36 +++++----- orbtrace/debug/dbgIF_wrapper.py | 30 ++++---- orbtrace/soc.py | 40 +++++------ 9 files changed, 116 insertions(+), 202 deletions(-) create mode 160000 deps/zyp-amaranth-libs delete mode 100644 orbtrace/amaranth_glue/wrapper.py diff --git a/.gitmodules b/.gitmodules index 18b3685..69da241 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,6 @@ [submodule "deps/litehyperbus"] path = deps/litehyperbus url = https://github.com/litex-hub/litehyperbus.git +[submodule "deps/zyp-amaranth-libs"] + path = deps/zyp-amaranth-libs + url = https://github.com/zyp/zyp-amaranth-libs.git diff --git a/deps/zyp-amaranth-libs b/deps/zyp-amaranth-libs new file mode 160000 index 0000000..02ff0d7 --- /dev/null +++ b/deps/zyp-amaranth-libs @@ -0,0 +1 @@ +Subproject commit 02ff0d742cbae782778fad04adaad9af29d81608 diff --git a/orbtrace/amaranth_glue/dfu.py b/orbtrace/amaranth_glue/dfu.py index 92af4d8..9c1da50 100644 --- a/orbtrace/amaranth_glue/dfu.py +++ b/orbtrace/amaranth_glue/dfu.py @@ -10,10 +10,10 @@ def __init__(self, if_num, areas): self.handler = dfu.DFUHandler(if_num, areas) - def wrap(self, wrapper): - wrapper.connect(self.source.data, self.handler.source.data) - wrapper.connect(self.source.addr, self.handler.source.addr) - wrapper.connect(self.source.valid, self.handler.source.valid) - wrapper.connect(self.source.ready, self.handler.source.ready) - wrapper.connect(self.source.first, self.handler.source.first) - wrapper.connect(self.source.last, self.handler.source.last) + def wrap(self, glue): + glue.connect(self.source.data, self.handler.source.data) + glue.connect(self.source.addr, self.handler.source.addr) + glue.connect(self.source.valid, self.handler.source.valid) + glue.connect(self.source.ready, self.handler.source.ready) + glue.connect(self.source.first, self.handler.source.first) + glue.connect(self.source.last, self.handler.source.last) diff --git a/orbtrace/amaranth_glue/luna.py b/orbtrace/amaranth_glue/luna.py index 51170be..8d525d0 100644 --- a/orbtrace/amaranth_glue/luna.py +++ b/orbtrace/amaranth_glue/luna.py @@ -1,5 +1,3 @@ -from .wrapper import Wrapper - import amaranth import migen @@ -9,14 +7,14 @@ from litex.soc.interconnect.stream import Endpoint class USBDevice(migen.Module): - def __init__(self, pads, wrapper, *args, **kwargs): - self.wrapper = wrapper + def __init__(self, pads, glue, *args, **kwargs): + self.glue = glue phy_reset_controller = PHYResetController() - wrapper.m.submodules += phy_reset_controller + glue.m.submodules += phy_reset_controller if hasattr(pads, 'clk'): - wrapper.m.d.comb += [ + glue.m.d.comb += [ amaranth.ResetSignal('usb').eq(phy_reset_controller.phy_reset), ] @@ -45,30 +43,30 @@ def __init__(self, pads, wrapper, *args, **kwargs): ], ) - wrapper.connect(ulpi_data.i, ulpi.data.i) - wrapper.connect(ulpi_data.o, ulpi.data.o) - wrapper.connect(ulpi_data.oe, ulpi.data.oe) + glue.connect(ulpi_data.i, ulpi.data.i) + glue.connect(ulpi_data.o, ulpi.data.o) + glue.connect(ulpi_data.oe, ulpi.data.oe) - wrapper.connect(pads.stp, ulpi.stp) - wrapper.connect(pads.nxt, ulpi.nxt.i) - wrapper.connect(pads.dir, ulpi.dir.i) - wrapper.connect(ulpi_rst, ulpi.rst) + glue.connect(pads.stp, ulpi.stp) + glue.connect(pads.nxt, ulpi.nxt.i) + glue.connect(pads.dir, ulpi.dir.i) + glue.connect(ulpi_rst, ulpi.rst) if hasattr(pads, 'clk'): - wrapper.connect(pads.clk, ulpi.clk.i) + glue.connect(pads.clk, ulpi.clk.i) else: - wrapper.connect(pads.clk_o, ulpi.clk.o) + glue.connect(pads.clk_o, ulpi.clk.o) self.usb = luna.usb2.USBDevice(bus = ulpi, *args, **kwargs) - wrapper.m.submodules += self.usb + glue.m.submodules += self.usb - wrapper.m.d.comb += [ + glue.m.d.comb += [ self.usb.connect.eq(1), ] def add_endpoint(self, ep): self.usb.add_endpoint(ep._ep) - ep.wrap(self.wrapper) + ep.wrap(self.glue) class USBStreamOutEndpoint: def __init__(self, *, endpoint_number, **kwargs): @@ -76,12 +74,12 @@ def __init__(self, *, endpoint_number, **kwargs): self.source = Endpoint([('data', 8)]) - def wrap(self, wrapper): - wrapper.connect(self.source.data, self._ep.stream.payload) - wrapper.connect(self.source.first, self._ep.stream.first) - wrapper.connect(self.source.last, self._ep.stream.last) - wrapper.connect(self.source.valid, self._ep.stream.valid) - wrapper.connect(self.source.ready, self._ep.stream.ready) + def wrap(self, glue): + glue.connect(self.source.data, self._ep.stream.payload) + glue.connect(self.source.first, self._ep.stream.first) + glue.connect(self.source.last, self._ep.stream.last) + glue.connect(self.source.valid, self._ep.stream.valid) + glue.connect(self.source.ready, self._ep.stream.ready) class USBStreamInEndpoint: def __init__(self, *, endpoint_number, **kwargs): @@ -89,12 +87,12 @@ def __init__(self, *, endpoint_number, **kwargs): self.sink = Endpoint([('data', 8)]) - def wrap(self, wrapper): - wrapper.connect(self.sink.data, self._ep.stream.payload) - wrapper.connect(self.sink.first, self._ep.stream.first) - wrapper.connect(self.sink.last, self._ep.stream.last) - wrapper.connect(self.sink.valid, self._ep.stream.valid) - wrapper.connect(self.sink.ready, self._ep.stream.ready) + def wrap(self, glue): + glue.connect(self.sink.data, self._ep.stream.payload) + glue.connect(self.sink.first, self._ep.stream.first) + glue.connect(self.sink.last, self._ep.stream.last) + glue.connect(self.sink.valid, self._ep.stream.valid) + glue.connect(self.sink.ready, self._ep.stream.ready) class USBMultibyteStreamInEndpoint: def __init__(self, *, endpoint_number, byte_width, **kwargs): @@ -102,9 +100,9 @@ def __init__(self, *, endpoint_number, byte_width, **kwargs): self.sink = Endpoint([('data', 8 * byte_width)]) - def wrap(self, wrapper): - wrapper.connect(self.sink.data, self._ep.stream.payload) - wrapper.connect(self.sink.first, self._ep.stream.first) - wrapper.connect(self.sink.last, self._ep.stream.last) - wrapper.connect(self.sink.valid, self._ep.stream.valid) - wrapper.connect(self.sink.ready, self._ep.stream.ready) + def wrap(self, glue): + glue.connect(self.sink.data, self._ep.stream.payload) + glue.connect(self.sink.first, self._ep.stream.first) + glue.connect(self.sink.last, self._ep.stream.last) + glue.connect(self.sink.valid, self._ep.stream.valid) + glue.connect(self.sink.ready, self._ep.stream.ready) diff --git a/orbtrace/amaranth_glue/usb_mem_bridge.py b/orbtrace/amaranth_glue/usb_mem_bridge.py index 35b950f..ad180cb 100755 --- a/orbtrace/amaranth_glue/usb_mem_bridge.py +++ b/orbtrace/amaranth_glue/usb_mem_bridge.py @@ -42,25 +42,25 @@ def __init__(self): self.handler = usb_mem_bridge.MemRequestHandler(self._axi_lite) - def wrap(self, wrapper): - wrapper.connect(self.axi_lite.aw.addr, self._axi_lite.aw.addr) - wrapper.connect(self.axi_lite.aw.valid, self._axi_lite.aw.valid) - wrapper.connect(self.axi_lite.aw.ready, self._axi_lite.aw.ready) + def wrap(self, glue): + glue.connect(self.axi_lite.aw.addr, self._axi_lite.aw.addr) + glue.connect(self.axi_lite.aw.valid, self._axi_lite.aw.valid) + glue.connect(self.axi_lite.aw.ready, self._axi_lite.aw.ready) - wrapper.connect(self.axi_lite.w.data, self._axi_lite.w.data) - wrapper.connect(self.axi_lite.w.strb, self._axi_lite.w.strb) - wrapper.connect(self.axi_lite.w.valid, self._axi_lite.w.valid) - wrapper.connect(self.axi_lite.w.ready, self._axi_lite.w.ready) + glue.connect(self.axi_lite.w.data, self._axi_lite.w.data) + glue.connect(self.axi_lite.w.strb, self._axi_lite.w.strb) + glue.connect(self.axi_lite.w.valid, self._axi_lite.w.valid) + glue.connect(self.axi_lite.w.ready, self._axi_lite.w.ready) - wrapper.connect(self.axi_lite.b.resp, self._axi_lite.b.resp) - wrapper.connect(self.axi_lite.b.valid, self._axi_lite.b.valid) - wrapper.connect(self.axi_lite.b.ready, self._axi_lite.b.ready) + glue.connect(self.axi_lite.b.resp, self._axi_lite.b.resp) + glue.connect(self.axi_lite.b.valid, self._axi_lite.b.valid) + glue.connect(self.axi_lite.b.ready, self._axi_lite.b.ready) - wrapper.connect(self.axi_lite.ar.addr, self._axi_lite.ar.addr) - wrapper.connect(self.axi_lite.ar.valid, self._axi_lite.ar.valid) - wrapper.connect(self.axi_lite.ar.ready, self._axi_lite.ar.ready) + glue.connect(self.axi_lite.ar.addr, self._axi_lite.ar.addr) + glue.connect(self.axi_lite.ar.valid, self._axi_lite.ar.valid) + glue.connect(self.axi_lite.ar.ready, self._axi_lite.ar.ready) - wrapper.connect(self.axi_lite.r.resp, self._axi_lite.r.resp) - wrapper.connect(self.axi_lite.r.data, self._axi_lite.r.data) - wrapper.connect(self.axi_lite.r.valid, self._axi_lite.r.valid) - wrapper.connect(self.axi_lite.r.ready, self._axi_lite.r.ready) + glue.connect(self.axi_lite.r.resp, self._axi_lite.r.resp) + glue.connect(self.axi_lite.r.data, self._axi_lite.r.data) + glue.connect(self.axi_lite.r.valid, self._axi_lite.r.valid) + glue.connect(self.axi_lite.r.ready, self._axi_lite.r.ready) diff --git a/orbtrace/amaranth_glue/wrapper.py b/orbtrace/amaranth_glue/wrapper.py deleted file mode 100644 index 02178d8..0000000 --- a/orbtrace/amaranth_glue/wrapper.py +++ /dev/null @@ -1,88 +0,0 @@ -import amaranth -from amaranth.hdl import ir -from amaranth.back import verilog - -import migen - -from pathlib import Path - -class Wrapper(migen.Module): - def __init__(self, platform, name = 'amaranth_wrapper'): - self.platform = platform - self.name = name - - self.m = amaranth.Module() - - self.connections = [] - - def connect(self, migen_sig, amaranth_sig): - self.connections.append((migen_sig, amaranth_sig)) - - def connect_domain(self, name): - n = 'sync' if name == 'sys' else name - - setattr(self.m.domains, n, amaranth.ClockDomain(n)) - - self.connect(migen.ClockSignal(name), amaranth.ClockSignal(n)) - self.connect(migen.ResetSignal(name), amaranth.ResetSignal(n)) - - def from_amaranth(self, amaranth_sig): - shape = amaranth_sig.shape() - migen_sig = migen.Signal((shape.width, shape.signed), name = amaranth_sig.name) - - self.connect(migen_sig, amaranth_sig) - - return migen_sig - - def from_migen(self, migen_sig): - amaranth_sig = amaranth.Signal(amaranth.Shape(migen_sig.nbits, migen_sig.signed)) - - self.connect(migen_sig, amaranth_sig) - - return amaranth_sig - - def get_instance(self): - connections = {} - - for m, n in self.connections: - module, name, *_ = self.amaranth_name_map[n] - direction = self.amaranth_dir_map[n] - s = f'{direction}_{name}' - - assert s not in connections, f'Signal {s} connected multiple times.' - - connections[s] = m - - return migen.Instance(self.name, **connections) - - def generate_verilog(self): - ports = [n for m, n in self.connections] - - fragment = ir.Fragment.get(self.m, None).prepare(ports = ports) - - v, m = verilog.convert_fragment(fragment, name = self.name) - - self.amaranth_dir_map = fragment.ports - self.amaranth_name_map = m - - for name, domain in fragment.domains.items(): - if domain.clk in self.amaranth_name_map: - self.amaranth_name_map[amaranth.ClockSignal(name)] = self.amaranth_name_map[domain.clk] - if domain.clk in self.amaranth_dir_map: - self.amaranth_dir_map[amaranth.ClockSignal(name)] = self.amaranth_dir_map[domain.clk] - if domain.rst in self.amaranth_name_map: - self.amaranth_name_map[amaranth.ResetSignal(name)] = self.amaranth_name_map[domain.rst] - if domain.rst in self.amaranth_dir_map: - self.amaranth_dir_map[amaranth.ResetSignal(name)] = self.amaranth_dir_map[domain.rst] - - return v - - def do_finalize(self): - verilog_filename = str(Path(self.platform.output_dir) / 'gateware' / f'{self.name}.v') - - with open(verilog_filename, 'w') as f: - f.write(self.generate_verilog()) - - self.platform.add_source(verilog_filename) - - self.specials += self.get_instance() diff --git a/orbtrace/debug/cmsis_dap_wrapper.py b/orbtrace/debug/cmsis_dap_wrapper.py index 0d3f4a0..279038d 100644 --- a/orbtrace/debug/cmsis_dap_wrapper.py +++ b/orbtrace/debug/cmsis_dap_wrapper.py @@ -12,7 +12,7 @@ from litex.build.io import SDRInput, DDRInput, SDROutput, SDRTristate class CMSIS_DAP(Module): - def __init__(self, dbgif, wrapper): + def __init__(self, dbgif, glue): self.source = Endpoint([('data', 8)]) self.sink = Endpoint([('data', 8)]) self.is_v2 = Signal() @@ -25,27 +25,27 @@ def __init__(self, dbgif, wrapper): is_v2 = amaranth.Signal() - dbgif_wrapper = dbgIF_wrapper.DBGIF(dbgif, wrapper) - wrapper.m.submodules += dbgif_wrapper + dbgif_wrapper = dbgIF_wrapper.DBGIF(dbgif, glue) + glue.m.submodules += dbgif_wrapper dap = cmsis_dap.CMSIS_DAP(stream_in, stream_out, dbgif_wrapper, is_v2) - wrapper.m.submodules += dap + glue.m.submodules += dap - wrapper.connect(self.source.data, stream_in.payload) - wrapper.connect(self.source.first, stream_in.first) - wrapper.connect(self.source.last, stream_in.last) - wrapper.connect(self.source.valid, stream_in.valid) - wrapper.connect(self.source.ready, stream_in.ready) + glue.connect(self.source.data, stream_in.payload) + glue.connect(self.source.first, stream_in.first) + glue.connect(self.source.last, stream_in.last) + glue.connect(self.source.valid, stream_in.valid) + glue.connect(self.source.ready, stream_in.ready) - wrapper.connect(self.sink.data, stream_out.payload) - wrapper.connect(self.sink.first, stream_out.first) - wrapper.connect(self.sink.last, stream_out.last) - wrapper.connect(self.sink.valid, stream_out.valid) - wrapper.connect(self.sink.ready, stream_out.ready) + glue.connect(self.sink.data, stream_out.payload) + glue.connect(self.sink.first, stream_out.first) + glue.connect(self.sink.last, stream_out.last) + glue.connect(self.sink.valid, stream_out.valid) + glue.connect(self.sink.ready, stream_out.ready) - wrapper.connect(self.is_v2, is_v2) + glue.connect(self.is_v2, is_v2) - wrapper.connect(self.can, dap.can) + glue.connect(self.can, dap.can) - wrapper.connect(self.connected, dap.connected) - wrapper.connect(self.running, dap.running) + glue.connect(self.connected, dap.connected) + glue.connect(self.running, dap.running) diff --git a/orbtrace/debug/dbgIF_wrapper.py b/orbtrace/debug/dbgIF_wrapper.py index d624025..ce03a8a 100644 --- a/orbtrace/debug/dbgIF_wrapper.py +++ b/orbtrace/debug/dbgIF_wrapper.py @@ -1,21 +1,21 @@ from amaranth import * class DBGIF(Elaboratable): - def __init__(self, dbgif, wrapper): - self.addr32 = wrapper.from_migen(dbgif.addr32) - self.rnw = wrapper.from_migen(dbgif.rnw) - self.apndp = wrapper.from_migen(dbgif.apndp) - self.dwrite = wrapper.from_migen(dbgif.dwrite) - self.dread = wrapper.from_migen(dbgif.dread) - self.perr = wrapper.from_migen(dbgif.perr) - self.go = wrapper.from_migen(dbgif.go) - self.done = wrapper.from_migen(dbgif.done) - self.ack = wrapper.from_migen(dbgif.ack) - self.pinsin = wrapper.from_migen(dbgif.pinsin) - self.pinsout = wrapper.from_migen(dbgif.pinsout) - self.command = wrapper.from_migen(dbgif.command) - self.dev = wrapper.from_migen(dbgif.dev) - self.is_jtag = wrapper.from_migen(dbgif.is_jtag) + def __init__(self, dbgif, glue): + self.addr32 = glue.from_migen(dbgif.addr32) + self.rnw = glue.from_migen(dbgif.rnw) + self.apndp = glue.from_migen(dbgif.apndp) + self.dwrite = glue.from_migen(dbgif.dwrite) + self.dread = glue.from_migen(dbgif.dread) + self.perr = glue.from_migen(dbgif.perr) + self.go = glue.from_migen(dbgif.go) + self.done = glue.from_migen(dbgif.done) + self.ack = glue.from_migen(dbgif.ack) + self.pinsin = glue.from_migen(dbgif.pinsin) + self.pinsout = glue.from_migen(dbgif.pinsout) + self.command = glue.from_migen(dbgif.command) + self.dev = glue.from_migen(dbgif.dev) + self.is_jtag = glue.from_migen(dbgif.is_jtag) def elaborate(self, platform): m = Module() diff --git a/orbtrace/soc.py b/orbtrace/soc.py index eb8586a..476a8f3 100644 --- a/orbtrace/soc.py +++ b/orbtrace/soc.py @@ -13,7 +13,7 @@ from .power.usb_handler import PowerUSBHandler -from .amaranth_glue.wrapper import Wrapper +from zyp_amaranth_libs.litex_glue import Glue from .amaranth_glue.luna import USBDevice, USBStreamOutEndpoint, USBStreamInEndpoint, USBMultibyteStreamInEndpoint from .amaranth_glue.usb_mem_bridge import MemRequestHandler from .debug import DBGIF, CMSIS_DAP @@ -105,8 +105,8 @@ def __init__(self, platform, sys_clk_freq, with_debug, with_trace, with_target_p # Flash self.add_flash() - # Amaranth wrapper - self.add_wrapper() + # Amaranth glue + self.add_glue() # LEDs self.add_leds(led_default) @@ -265,10 +265,10 @@ def add_target_power(self): self.add_usb_control_handler(handler) self.comb += [ - pads.vtref_en.eq(self.wrapper.from_amaranth(handler.vtref_en)), - pads.vtref_sel.eq(self.wrapper.from_amaranth(handler.vtref_sel)), - pads.vtpwr_en.eq(self.wrapper.from_amaranth(handler.vtpwr_en)), - pads.vtpwr_sel.eq(self.wrapper.from_amaranth(handler.vtpwr_sel)), + pads.vtref_en.eq(self.glue.from_amaranth(handler.vtref_en)), + pads.vtref_sel.eq(self.glue.from_amaranth(handler.vtref_sel)), + pads.vtpwr_en.eq(self.glue.from_amaranth(handler.vtpwr_en)), + pads.vtpwr_sel.eq(self.glue.from_amaranth(handler.vtpwr_sel)), self.led_vtref.b.eq(pads.vtref_en), self.led_vtref.g.eq(pads.vtref_en & pads.vtref_sel), @@ -280,7 +280,7 @@ def add_target_power(self): def add_debug(self): # PHY clock. self.crg.add_debug() - self.wrapper.connect_domain('debug') + self.glue.connect_domain('debug') # Add verilog sources. self.platform.add_source('verilog/dbgIF.v') @@ -295,7 +295,7 @@ def add_debug(self): def add_cmsis_dap(self, with_v1 = True, with_v2 = True): # CMSIS-DAP. - self.submodules.cmsis_dap = CMSIS_DAP(self.dbgif, wrapper = self.wrapper) + self.submodules.cmsis_dap = CMSIS_DAP(self.dbgif, glue = self.glue) # LEDs if hasattr(self, 'led_debug'): @@ -503,12 +503,12 @@ def add_trace(self): self.add_usb_control_handler(handler) - self.comb += self.trace.input_format.eq(self.wrapper.from_amaranth(handler.input_format)) + self.comb += self.trace.input_format.eq(self.glue.from_amaranth(handler.input_format)) self.submodules.async_baudrate_ps = PulseSynchronizer('usb', 'sys') self.comb += [ - self.trace.async_baudrate.eq(self.wrapper.from_amaranth(handler.async_baudrate)), - self.async_baudrate_ps.i.eq(self.wrapper.from_amaranth(handler.async_baudrate_strobe)), + self.trace.async_baudrate.eq(self.glue.from_amaranth(handler.async_baudrate)), + self.async_baudrate_ps.i.eq(self.glue.from_amaranth(handler.async_baudrate_strobe)), self.trace.async_baudrate_strobe.eq(self.async_baudrate_ps.o), ] @@ -659,7 +659,7 @@ def add_usb_bridge(self): self.add_usb_control_handler(mem_request_handler.handler) # FIXME: wrap - mem_request_handler.wrap(self.usb.wrapper) # FIXME: wrap + mem_request_handler.wrap(self.usb.glue) # FIXME: wrap axi_lite = AXILiteInterface() @@ -704,7 +704,7 @@ def add_dfu(self, mode): self.add_usb_control_handler(dfu_handler.handler) # FIXME: wrap - dfu_handler.wrap(self.wrapper) + dfu_handler.wrap(self.glue) self.submodules.flashwriter = FlashWriter() @@ -726,7 +726,7 @@ def add_usb_serialnumber(self): self.add_usb_control_handler(handler) - self.comb += self.wrapper.from_amaranth(handler.serial).eq(self.flash_uid.uid) + self.comb += self.glue.from_amaranth(handler.serial).eq(self.flash_uid.uid) self.usb_blacklist.append(lambda setup: \ (setup.type == USBRequestType.STANDARD) & \ @@ -787,9 +787,9 @@ def add_usb_control_handler(self, handler): def add_usb(self, vid, pid): self.usb_alloc = USBAllocator() - self.wrapper.connect_domain('usb') + self.glue.connect_domain('usb') - self.submodules.usb = USBDevice(self.platform.request('ulpi'), wrapper = self.wrapper) + self.submodules.usb = USBDevice(self.platform.request('ulpi'), glue = self.glue) self.usb_descriptors = DeviceDescriptorCollection() @@ -834,10 +834,10 @@ def finalize_usb(self): for handler in self.usb_control_handlers: self.usb_control_ep.add_request_handler(handler) - def add_wrapper(self): - self.submodules.wrapper = Wrapper(self.platform) + def add_glue(self): + self.submodules.glue = Glue(self.platform) - self.wrapper.connect_domain('sys') + self.glue.connect_domain('sys') def add_platform_specific(self): if hasattr(self.platform, 'add_platform_specific'): From da6002c04d8cec46074fca7fc9457c16c1e7187c Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 13 Jan 2024 23:36:42 +0100 Subject: [PATCH 2/2] cmsis_dap: Refactor to use amaranth.lib.wiring. --- orbtrace/debug/cmsis_dap.py | 89 ++++++++++++++++------------- orbtrace/debug/cmsis_dap_wrapper.py | 40 ++++++------- orbtrace/debug/dbgIF_wrapper.py | 21 +++++++ 3 files changed, 86 insertions(+), 64 deletions(-) diff --git a/orbtrace/debug/cmsis_dap.py b/orbtrace/debug/cmsis_dap.py index 32b0b4b..f74cbc9 100644 --- a/orbtrace/debug/cmsis_dap.py +++ b/orbtrace/debug/cmsis_dap.py @@ -1,5 +1,11 @@ from amaranth import * -from .dbgIF import DBGIF + +from amaranth.lib.wiring import Component, In, Out + +from zyp_amaranth_libs.stream import StreamSignature + +from .dbgIF_wrapper import dbgIFSignature + from ..git_version import get_version # Principle of operation @@ -147,17 +153,22 @@ def elaborate(self, platform): # This is the CMSIS-DAP handler itself # ==================================== -class CMSIS_DAP(Elaboratable): - def __init__(self, streamIn, streamOut, dbgif, v2Indication): - # External interface (generally LEDs) - self.running = Signal() # Flag for if target is running - self.connected = Signal() # Flag for if target is connected - self.can = Signal() # Canary +class CMSIS_DAP(Component): + # External interface (generally LEDs) + running: Out(1) # Flag for if target is running + connected: Out(1) # Flag for if target is connected + can: Out(1) # Canary - # Nature of the USB connection - self.isV2 = v2Indication - self.streamIn = streamIn - self.streamOut = streamOut + # Nature of the USB connection + isV2: In(1) + streamIn: In(StreamSignature(8, first = True, last = True)) + streamOut: Out(StreamSignature(8, first = True, last = True)) + + # Debug interface + dbgif: Out(dbgIFSignature) + + def __init__(self): + super().__init__() # Receive block construction self.rxBlock = Signal( 7*8 ) # Longest message we pickup is 6 bytes + command @@ -219,8 +230,6 @@ def __init__(self, streamIn, streamOut, dbgif, v2Indication): self.waitRetry = Signal(16,reset=4096) # Number of transfer retries after WAIT response self.matchRetry = Signal(16,reset=16) # Number of retries on reads with Value Match in DAP_Transfer - self.dbgif = dbgif - # ---------------------------------------------------------------------------------- def RESP_Invalid(self, m): # Simply transmit an 'invalid' packet back @@ -424,7 +433,7 @@ def RESP_SWJ_Sequence_Process(self, m): with m.Case(0): with m.If(self.streamOut.valid & self.streamOut.ready): m.d.sync += [ - self.tfrData.eq(self.streamOut.payload), + self.tfrData.eq(self.streamOut.data), self.swj_txb.eq(1) ] with m.Else(): @@ -496,7 +505,7 @@ def RESP_JTAG_Configure_Process(self, m): # Collect octets representing the irlength for each member of the chain with m.If(self.streamOut.valid & self.streamOut.ready): m.d.sync += [ - self.dbgif.dwrite.bit_select( self.jtag_ircount,5 ).eq(self.streamOut.payload.bit_select(0,5)), + self.dbgif.dwrite.bit_select( self.jtag_ircount,5 ).eq(self.streamOut.data.bit_select(0,5)), self.jtag_ircount.eq(self.jtag_ircount+5) ] with m.If(self.streamOut.last): @@ -626,18 +635,18 @@ def RESP_Transfer_Process(self, m): # Rule for JTAG is any read, for SWD it's any AP read # If it doesn't then we need to collect these data before progressing with m.If(self.readDelay & - ((self.isJTAG & (~self.streamOut.payload.bit_select(1,1))) | - (~self.isJTAG & (self.streamOut.payload.bit_select(0,2)!=3)))): + ((self.isJTAG & (~self.streamOut.data.bit_select(1,1))) | + (~self.isJTAG & (self.streamOut.data.bit_select(0,2)!=3)))): m.d.sync += [ self.tfr_txb.eq(6), self.tfrReq.eq(0x0e), self.readDelay.eq(0), self.readAgain.eq(1), - self.PendPayload.eq(self.streamOut.payload), + self.PendPayload.eq(self.streamOut.data), ] with m.Else(): m.d.sync += [ - self.tfrReq.eq(self.streamOut.payload), + self.tfrReq.eq(self.streamOut.data), self.tfr_txb.eq(1) ] @@ -665,14 +674,14 @@ def RESP_Transfer_Process(self, m): with m.If(self.streamOut.valid & self.streamOut.ready): m.d.sync+=[ # Beware, state used to select byte in word construction - self.tfrData.word_select((self.tfr_txb.bit_select(0,3)-2).as_unsigned(),8).eq(self.streamOut.payload), + self.tfrData.word_select((self.tfr_txb.bit_select(0,3)-2).as_unsigned(),8).eq(self.streamOut.data), self.tfr_txb.eq(self.tfr_txb+1) ] with m.If(self.tfrReq.bit_select(5,1) & (self.tfr_txb==6)): # This is a match register write m.d.sync += [ - self.mask.eq(Cat(self.streamOut.payload,self.tfrData.bit_select(0,24))), + self.mask.eq(Cat(self.streamOut.data,self.tfrData.bit_select(0,24))), self.tfr_txb.eq(0) ] with m.Else(): @@ -747,7 +756,7 @@ def RESP_Transfer_Process(self, m): with m.Case(10,11,12): with m.If(self.streamIn.ready): m.d.sync += [ - self.streamIn.payload.eq(self.txBlock.word_select((self.tfr_txb-10).as_unsigned(),8)), + self.streamIn.data.eq(self.txBlock.word_select((self.tfr_txb-10).as_unsigned(),8)), self.streamIn.valid.eq(1), self.tfr_txb.eq(self.tfr_txb+1), self.streamIn.last.eq(self.isV2 & (self.tfr_txb==12) & (self.tfrram.adr==0)) @@ -821,7 +830,7 @@ def RESP_TransferBlock_Process(self, m): with m.Case(0,1,2,3): with m.If(self.streamOut.ready & self.streamOut.valid): m.d.sync+=[ - self.dbgif.dwrite.word_select(self.tfB_txb,8).eq(self.streamOut.payload), + self.dbgif.dwrite.word_select(self.tfB_txb,8).eq(self.streamOut.data), self.tfB_txb.eq(self.tfB_txb+1), ] with m.Else(): @@ -887,7 +896,7 @@ def RESP_TransferBlock_Process(self, m): with m.If(self.streamIn.ready): m.d.sync += [ # Beware, we use the bottom two bits of the state to select the byte to return - self.streamIn.payload.eq(self.txBlock.word_select(self.tfB_txb.bit_select(0,2),8)), + self.streamIn.data.eq(self.txBlock.word_select(self.tfB_txb.bit_select(0,2),8)), self.streamIn.valid.eq(1), self.tfB_txb.eq(self.tfB_txb+1), # End of transfer if there are no data to return @@ -931,7 +940,7 @@ def RESP_Transfer_Complete(self, m): with m.Case(2): m.d.sync += [ self.transferCCount.eq(self.transferCCount-1), - self.streamIn.payload.eq(self.tfrram.dat_r.word_select(0,8)), + self.streamIn.data.eq(self.tfrram.dat_r.word_select(0,8)), self.txb.eq(3) ] @@ -941,7 +950,7 @@ def RESP_Transfer_Complete(self, m): with m.If(self.streamIn.ready & self.streamIn.valid): m.d.sync += [ self.txb.eq(self.txb+1), - self.streamIn.payload.eq(self.tfrram.dat_r.word_select((self.txb-2).as_unsigned(),8)), + self.streamIn.data.eq(self.tfrram.dat_r.word_select((self.txb-2).as_unsigned(),8)), # 5 because of pipeline self.streamIn.last.eq(self.isV2 & (~self.transferCCount.bool()) & (self.txb==5)), self.streamIn.valid.eq(self.txb!=6) @@ -997,7 +1006,7 @@ def RESP_Sequence_PROCESS(self,m): with m.If(self.streamIn.ready): m.d.sync += [ # Send frontmatter for reponse - self.streamIn.payload.eq(Mux(self.isJTAG,DAP_JTAG_Sequence,DAP_SWD_Sequence)), + self.streamIn.data.eq(Mux(self.isJTAG,DAP_JTAG_Sequence,DAP_SWD_Sequence)), self.streamIn.last.eq(0), self.streamIn.valid.eq(1), @@ -1013,19 +1022,19 @@ def RESP_Sequence_PROCESS(self,m): with m.If(self.streamOut.ready & self.streamOut.valid): m.d.sync += [ self.seqCount.eq(self.seqCount-1), - self.seqckCycles.eq(self.streamOut.payload.bit_select(0,6)), + self.seqckCycles.eq(self.streamOut.data.bit_select(0,6)), # If we're reading then we don't want to write to SWD, we do if it's JTAG (TMS) - self.dbgif.pinsin[4].eq(Mux(self.isJTAG,1,~self.streamOut.payload[7])), + self.dbgif.pinsin[4].eq(Mux(self.isJTAG,1,~self.streamOut.data[7])), self.seqIn.eq(0), # Decide on correct state to move to and setup output for read or write condition - self.seqIsRead.eq(self.streamOut.payload[7]), - self.seq_txb.eq(Mux(self.isJTAG,2,Mux(self.streamOut.payload[7],3,2))) + self.seqIsRead.eq(self.streamOut.data[7]), + self.seq_txb.eq(Mux(self.isJTAG,2,Mux(self.streamOut.data[7],3,2))) ] # If this is a JTAG sequence then set TMS with m.If(self.isJTAG): - m.d.sync += self.dbgif.pinsin.bit_select(1,1).eq(self.streamOut.payload[6]) + m.d.sync += self.dbgif.pinsin.bit_select(1,1).eq(self.streamOut.data[6]) with m.Else(): # If we're showing ~valid then this packet is foreshortened with m.If(~self.streamOut.valid): @@ -1037,7 +1046,7 @@ def RESP_Sequence_PROCESS(self,m): with m.Case(2): with m.If(self.streamOut.ready & self.streamOut.valid): m.d.sync += [ - self.seqOut.eq(self.streamOut.payload), + self.seqOut.eq(self.streamOut.data), self.bitCount.eq(0), self.seq_txb.eq(3) ] @@ -1104,7 +1113,7 @@ def RESP_Sequence_PROCESS(self,m): with m.If(self.seqIsRead): m.d.sync += [ - self.streamIn.payload.eq(self.seqPendingTX), + self.streamIn.data.eq(self.seqPendingTX), self.streamIn.valid.eq(1), self.seqPendingTX.eq(self.seqIn), self.txedLen.eq(self.txedLen+1), @@ -1117,7 +1126,7 @@ def RESP_Sequence_PROCESS(self,m): with m.Case(7): with m.If(self.streamIn.ready): m.d.sync += [ - self.streamIn.payload.eq(self.seqPendingTX), + self.streamIn.data.eq(self.seqPendingTX), self.streamIn.last.eq(self.isV2), self.streamIn.valid.eq(1), self.seq_txb.eq(8) @@ -1168,12 +1177,12 @@ def elaborate(self,platform): self.txedLen.eq(0), # Default return is packet name followed by 0 (no error) - self.txBlock.word_select(0,16).eq(Cat(self.streamOut.payload,C(0,8))), + self.txBlock.word_select(0,16).eq(Cat(self.streamOut.data,C(0,8))), self.txLen.eq(2), # Grab incoming from usb self.rxedLen.eq(1), - self.rxBlock.word_select(0,8).eq(self.streamOut.payload), + self.rxBlock.word_select(0,8).eq(self.streamOut.data), ] # Only process if this is the start of a packet (i.e. it's not overrrun or similar) @@ -1229,7 +1238,7 @@ def elaborate(self,platform): # Grab next byte in this packet with m.If(self.streamOut.valid & self.streamOut.ready): m.d.sync += [ - self.rxBlock.word_select(self.rxedLen,8).eq(self.streamOut.payload), + self.rxBlock.word_select(self.rxedLen,8).eq(self.streamOut.data), self.rxedLen.eq(self.rxedLen+1) ] @@ -1377,7 +1386,7 @@ def elaborate(self,platform): with m.State('RESPOND'): m.d.sync += [ self.streamIn.valid.eq(self.txedLen