From 717fb131fd39a13b27d256becaf50a5b451f31af Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 28 Jul 2023 09:15:22 +0200 Subject: [PATCH] interconnect/axi: Switch to LiteXModule. --- litex/soc/interconnect/axi/axi_full.py | 39 +++++------ .../interconnect/axi/axi_full_to_axi_lite.py | 10 +-- .../interconnect/axi/axi_full_to_wishbone.py | 8 ++- litex/soc/interconnect/axi/axi_lite.py | 64 +++++++++---------- litex/soc/interconnect/axi/axi_lite_to_csr.py | 6 +- .../interconnect/axi/axi_lite_to_wishbone.py | 10 +-- litex/soc/interconnect/axi/axi_stream.py | 4 +- 7 files changed, 75 insertions(+), 66 deletions(-) diff --git a/litex/soc/interconnect/axi/axi_full.py b/litex/soc/interconnect/axi/axi_full.py index f14d94438..e3cdd4af7 100644 --- a/litex/soc/interconnect/axi/axi_full.py +++ b/litex/soc/interconnect/axi/axi_full.py @@ -1,7 +1,7 @@ # # This file is part of LiteX. # -# Copyright (c) 2018-2022 Florent Kermarrec +# Copyright (c) 2018-2023 Florent Kermarrec # Copyright (c) 2020 Antmicro # SPDX-License-Identifier: BSD-2-Clause @@ -10,6 +10,7 @@ from migen import * from migen.genlib import roundrobin +from litex.gen import * from litex.gen.genlib.misc import WaitTimer from litex.build.generic_platform import * @@ -137,7 +138,7 @@ class AXIInterface: # AXI Bursts to Beats ------------------------------------------------------------------------------ -class AXIBurst2Beat(Module): +class AXIBurst2Beat(LiteXModule): def __init__(self, ax_burst, ax_beat, capabilities={BURST_FIXED, BURST_INCR, BURST_WRAP}): assert BURST_FIXED in capabilities @@ -189,7 +190,7 @@ class AXIBurst2Beat(Module): # AXI Data-Width Converter ------------------------------------------------------------------------- -class AXIUpConverter(Module): +class AXIUpConverter(LiteXModule): def __init__(self, axi_from, axi_to): dw_from = len(axi_from.r.data) dw_to = len(axi_to.r.data) @@ -246,7 +247,7 @@ class AXIUpConverter(Module): self.comb += axi_from.r.user.eq(axi_to.r.user) self.comb += axi_from.r.dest.eq(axi_to.r.dest) -class AXIDownConverter(Module): +class AXIDownConverter(LiteXModule): def __init__(self, axi_from, axi_to): dw_from = len(axi_from.r.data) dw_to = len(axi_to.r.data) @@ -338,7 +339,7 @@ class AXIDownConverter(Module): self.sync += axi_from.r.dest.eq(axi_to.r.dest) self.sync += axi_from.r.id.eq(axi_to.r.id) -class AXIConverter(Module): +class AXIConverter(LiteXModule): """AXI data width converter""" def __init__(self, master, slave): self.master = master @@ -359,7 +360,7 @@ class AXIConverter(Module): # AXI Timeout -------------------------------------------------------------------------------------- -class AXITimeout(Module): +class AXITimeout(LiteXModule): """Protect master against slave timeouts (master _has_ to respond correctly)""" def __init__(self, master, cycles): self.error = Signal() @@ -388,7 +389,7 @@ class AXITimeout(Module): fsm.act("RESPOND", *response) return fsm - self.submodules.wr_fsm = channel_fsm( + self.wr_fsm = channel_fsm( timer = wr_timer, wait_cond = (master.aw.valid & ~master.aw.ready) | (master.w.valid & ~master.w.ready), error = wr_error, @@ -402,7 +403,7 @@ class AXITimeout(Module): ) ]) - self.submodules.rd_fsm = channel_fsm( + self.rd_fsm = channel_fsm( timer = rd_timer, wait_cond = master.ar.valid & ~master.ar.ready, error = rd_error, @@ -419,7 +420,7 @@ class AXITimeout(Module): # AXI Interconnect Components ---------------------------------------------------------------------- -class _AXIRequestCounter(Module): +class _AXIRequestCounter(LiteXModule): def __init__(self, request, response, max_requests=256): self.counter = counter = Signal(max=max_requests) self.full = full = Signal() @@ -443,7 +444,7 @@ class _AXIRequestCounter(Module): ), ] -class AXIArbiter(Module): +class AXIArbiter(LiteXModule): """AXI arbiter Arbitrate between master interfaces and connect one to the target. New master will not be @@ -451,8 +452,8 @@ class AXIArbiter(Module): done separately. """ def __init__(self, masters, target): - self.submodules.rr_write = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) - self.submodules.rr_read = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) + self.rr_write = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) + self.rr_read = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) def get_sig(interface, channel, name): return getattr(getattr(interface, channel), name) @@ -477,11 +478,11 @@ class AXIArbiter(Module): self.comb += dest.eq(source) # Allow to change rr.grant only after all requests from a master have been responded to. - self.submodules.wr_lock = wr_lock = _AXIRequestCounter( + self.wr_lock = wr_lock = _AXIRequestCounter( request = target.aw.valid & target.aw.ready, response = target.b.valid & target.b.ready ) - self.submodules.rd_lock = rd_lock = _AXIRequestCounter( + self.rd_lock = rd_lock = _AXIRequestCounter( request = target.ar.valid & target.ar.ready, response = target.r.valid & target.r.ready & target.r.last ) @@ -498,7 +499,7 @@ class AXIArbiter(Module): self.rr_read.request.eq(Cat(*[m.ar.valid | m.r.valid for m in masters])), ] -class AXIDecoder(Module): +class AXIDecoder(LiteXModule): """AXI decoder Decode master access to particular slave based on its decoder function. @@ -611,12 +612,12 @@ class AXIInterconnectShared(Module): def __init__(self, masters, slaves, register=False, timeout_cycles=1e6): data_width = get_check_parameters(ports=masters + [s for _, s in slaves]) shared = AXIInterface(data_width=data_width) - self.submodules.arbiter = AXIArbiter(masters, shared) - self.submodules.decoder = AXIDecoder(shared, slaves) + self.arbiter = AXIArbiter(masters, shared) + self.decoder = AXIDecoder(shared, slaves) if timeout_cycles is not None: - self.submodules.timeout = AXITimeout(shared, timeout_cycles) + self.timeout = AXITimeout(shared, timeout_cycles) -class AXICrossbar(Module): +class AXICrossbar(LiteXModule): """AXI crossbar MxN crossbar for M masters and N slaves. diff --git a/litex/soc/interconnect/axi/axi_full_to_axi_lite.py b/litex/soc/interconnect/axi/axi_full_to_axi_lite.py index 6bb03d5ba..10749a663 100644 --- a/litex/soc/interconnect/axi/axi_full_to_axi_lite.py +++ b/litex/soc/interconnect/axi/axi_full_to_axi_lite.py @@ -1,7 +1,7 @@ # # This file is part of LiteX. # -# Copyright (c) 2018-2022 Florent Kermarrec +# Copyright (c) 2018-2023 Florent Kermarrec # Copyright (c) 2020 Antmicro # SPDX-License-Identifier: BSD-2-Clause @@ -9,6 +9,8 @@ from migen import * +from litex.gen import * + from litex.soc.interconnect import stream from litex.soc.interconnect.axi.axi_common import * @@ -17,7 +19,7 @@ from litex.soc.interconnect.axi.axi_full import * # AXI to AXI-Lite ---------------------------------------------------------------------------------- -class AXI2AXILite(Module): +class AXI2AXILite(LiteXModule): # Note: Since this AXI bridge will mostly be used to target buses that are not supporting # simultaneous writes/reads, to reduce ressource usage the AXIBurst2Beat module is shared # between writes/reads. @@ -37,7 +39,7 @@ class AXI2AXILite(Module): _cmd_done = Signal() _last_ar_aw_n = Signal() - self.submodules.fsm = fsm = FSM(reset_state="IDLE") + self.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", NextValue(_cmd_done, 0), If(axi.ar.valid & axi.aw.valid, @@ -121,7 +123,7 @@ class AXI2AXILite(Module): # AXI-Lite to AXI ---------------------------------------------------------------------------------- -class AXILite2AXI(Module): +class AXILite2AXI(LiteXModule): def __init__(self, axi_lite, axi, write_id=0, read_id=0, prot=0, burst_type="INCR"): assert isinstance(axi_lite, AXILiteInterface) assert isinstance(axi, AXIInterface) diff --git a/litex/soc/interconnect/axi/axi_full_to_wishbone.py b/litex/soc/interconnect/axi/axi_full_to_wishbone.py index 7fe47e28b..d77a3522e 100644 --- a/litex/soc/interconnect/axi/axi_full_to_wishbone.py +++ b/litex/soc/interconnect/axi/axi_full_to_wishbone.py @@ -1,7 +1,7 @@ # # This file is part of LiteX. # -# Copyright (c) 2018-2022 Florent Kermarrec +# Copyright (c) 2018-2023 Florent Kermarrec # Copyright (c) 2020 Antmicro # SPDX-License-Identifier: BSD-2-Clause @@ -9,6 +9,8 @@ from migen import * +from litex.gen import * + from litex.soc.interconnect.axi.axi_common import * from litex.soc.interconnect.axi.axi_lite import * from litex.soc.interconnect.axi.axi_full_to_axi_lite import * @@ -16,7 +18,7 @@ from litex.soc.interconnect.axi.axi_lite_to_wishbone import * # AXI to Wishbone ---------------------------------------------------------------------------------- -class AXI2Wishbone(Module): +class AXI2Wishbone(LiteXModule): def __init__(self, axi, wishbone, base_address=0x00000000): axi_lite = AXILiteInterface(axi.data_width, axi.address_width) axi2axi_lite = AXI2AXILite(axi, axi_lite) @@ -25,7 +27,7 @@ class AXI2Wishbone(Module): # Wishbone to AXI ---------------------------------------------------------------------------------- -class Wishbone2AXI(Module): +class Wishbone2AXI(LiteXModule): def __init__(self, wishbone, axi, base_address=0x00000000): axi_lite = AXILiteInterface(axi.data_width, axi.address_width) wishbone2axi_lite = Wishbone2AXILite(wishbone, axi_lite, base_address) diff --git a/litex/soc/interconnect/axi/axi_lite.py b/litex/soc/interconnect/axi/axi_lite.py index b336efec5..595eaf50a 100644 --- a/litex/soc/interconnect/axi/axi_lite.py +++ b/litex/soc/interconnect/axi/axi_lite.py @@ -1,7 +1,7 @@ # # This file is part of LiteX. # -# Copyright (c) 2018-2022 Florent Kermarrec +# Copyright (c) 2018-2023 Florent Kermarrec # Copyright (c) 2020 Antmicro # SPDX-License-Identifier: BSD-2-Clause @@ -10,6 +10,8 @@ from migen import * from migen.genlib import roundrobin +from litex.gen import * + from litex.gen.genlib.misc import WaitTimer from litex.build.generic_platform import * @@ -184,7 +186,7 @@ def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_we= # AXI-Lite SRAM ------------------------------------------------------------------------------------ -class AXILiteSRAM(Module): +class AXILiteSRAM(LiteXModule): def __init__(self, mem_or_size, read_only=None, init=None, bus=None, name=None): if bus is None: bus = AXILiteInterface() @@ -223,12 +225,12 @@ class AXILiteSRAM(Module): port_dat_r = port.dat_r, port_dat_w = port.dat_w if not read_only else None, port_we = port.we if not read_only else None) - self.submodules.fsm = fsm + self.fsm = fsm self.comb += comb # AXI-Lite Data-Width Converter -------------------------------------------------------------------- -class _AXILiteDownConverterWrite(Module): +class _AXILiteDownConverterWrite(LiteXModule): def __init__(self, master, slave): assert isinstance(master, AXILiteInterface) and isinstance(slave, AXILiteInterface) dw_from = len(master.w.data) @@ -252,9 +254,7 @@ class _AXILiteDownConverterWrite(Module): ] # Control Path - fsm = FSM(reset_state="IDLE") - fsm = ResetInserter()(fsm) - self.submodules.fsm = fsm + self.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE")) # Reset the converter state if master breaks a request, we can do that as # aw.valid and w.valid are kept high in CONVERT and RESPOND-SLAVE, and # acknowledged only when moving to RESPOND-MASTER, and then b.valid is 1. @@ -319,7 +319,7 @@ class _AXILiteDownConverterWrite(Module): ) ) -class _AXILiteDownConverterRead(Module): +class _AXILiteDownConverterRead(LiteXModule): def __init__(self, master, slave): assert isinstance(master, AXILiteInterface) and isinstance(slave, AXILiteInterface) dw_from = len(master.r.data) @@ -344,9 +344,7 @@ class _AXILiteDownConverterRead(Module): ] # Control Path - fsm = FSM(reset_state="IDLE") - fsm = ResetInserter()(fsm) - self.submodules.fsm = fsm + self.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE")) # Reset the converter state if master breaks a request, we can do that as # ar.valid is high in CONVERT and RESPOND-SLAVE, and r.valid in RESPOND-MASTER. self.comb += fsm.reset.eq(~(master.ar.valid | master.r.valid)) @@ -390,12 +388,12 @@ class _AXILiteDownConverterRead(Module): ) ) -class AXILiteDownConverter(Module): +class AXILiteDownConverter(LiteXModule): def __init__(self, master, slave): - self.submodules.write = _AXILiteDownConverterWrite(master, slave) - self.submodules.read = _AXILiteDownConverterRead(master, slave) + self.write = _AXILiteDownConverterWrite(master, slave) + self.read = _AXILiteDownConverterRead(master, slave) -class AXILiteUpConverter(Module): +class AXILiteUpConverter(LiteXModule): # TODO: we could try joining multiple master accesses into single slave access would require # checking if address changes and a way to flush on single access def __init__(self, master, slave): @@ -453,7 +451,7 @@ class AXILiteUpConverter(Module): self.comb += Case(wr_word, wr_cases) self.comb += Case(rd_word, rd_cases) -class AXILiteConverter(Module): +class AXILiteConverter(LiteXModule): """AXILite data width converter""" def __init__(self, master, slave): self.master = master @@ -474,7 +472,7 @@ class AXILiteConverter(Module): # AXI-Lite Clock Domain Crossing ------------------------------------------------------------------- -class AXILiteClockDomainCrossing(Module): +class AXILiteClockDomainCrossing(LiteXModule): """AXILite Clock Domain Crossing""" def __init__(self, master, slave, cd_from="sys", cd_to="sys"): # Same Clock Domain, direct connection. @@ -516,7 +514,7 @@ class AXILiteClockDomainCrossing(Module): # AXI-Lite Timeout --------------------------------------------------------------------------------- -class AXILiteTimeout(Module): +class AXILiteTimeout(LiteXModule): """Protect master against slave timeouts (master _has_ to respond correctly)""" def __init__(self, master, cycles): self.error = Signal() @@ -545,7 +543,7 @@ class AXILiteTimeout(Module): fsm.act("RESPOND", *response) return fsm - self.submodules.wr_fsm = channel_fsm( + self.wr_fsm = channel_fsm( timer = wr_timer, wait_cond = (master.aw.valid & ~master.aw.ready) | (master.w.valid & ~master.w.ready), error = wr_error, @@ -559,7 +557,7 @@ class AXILiteTimeout(Module): ) ]) - self.submodules.rd_fsm = channel_fsm( + self.rd_fsm = channel_fsm( timer = rd_timer, wait_cond = master.ar.valid & ~master.ar.ready, error = rd_error, @@ -575,7 +573,7 @@ class AXILiteTimeout(Module): # AXI-Lite Interconnect Components ----------------------------------------------------------------- -class _AXILiteRequestCounter(Module): +class _AXILiteRequestCounter(LiteXModule): def __init__(self, request, response, max_requests=256): self.counter = counter = Signal(max=max_requests) self.full = full = Signal() @@ -599,7 +597,7 @@ class _AXILiteRequestCounter(Module): ), ] -class AXILiteArbiter(Module): +class AXILiteArbiter(LiteXModule): """AXI Lite arbiter Arbitrate between master interfaces and connect one to the target. New master will not be @@ -607,8 +605,8 @@ class AXILiteArbiter(Module): done separately. """ def __init__(self, masters, target): - self.submodules.rr_write = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) - self.submodules.rr_read = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) + self.rr_write = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) + self.rr_read = roundrobin.RoundRobin(len(masters), roundrobin.SP_CE) def get_sig(interface, channel, name): return getattr(getattr(interface, channel), name) @@ -633,11 +631,11 @@ class AXILiteArbiter(Module): self.comb += dest.eq(source) # Allow to change rr.grant only after all requests from a master have been responded to. - self.submodules.wr_lock = wr_lock = _AXILiteRequestCounter( + self.wr_lock = wr_lock = _AXILiteRequestCounter( request = target.aw.valid & target.aw.ready, response = target.b.valid & target.b.ready ) - self.submodules.rd_lock = rd_lock = _AXILiteRequestCounter( + self.rd_lock = rd_lock = _AXILiteRequestCounter( request = target.ar.valid & target.ar.ready, response = target.r.valid & target.r.ready ) @@ -654,7 +652,7 @@ class AXILiteArbiter(Module): self.rr_read.request.eq(Cat(*[m.ar.valid | m.r.valid for m in masters])), ] -class AXILiteDecoder(Module): +class AXILiteDecoder(LiteXModule): """AXI Lite decoder Decode master access to particular slave based on its decoder function. @@ -757,22 +755,22 @@ def get_check_parameters(ports): return data_width -class AXILiteInterconnectPointToPoint(Module): +class AXILiteInterconnectPointToPoint(LiteXModule): """AXI Lite point to point interconnect""" def __init__(self, master, slave): self.comb += master.connect(slave) -class AXILiteInterconnectShared(Module): +class AXILiteInterconnectShared(LiteXModule): """AXI Lite shared interconnect""" def __init__(self, masters, slaves, register=False, timeout_cycles=1e6): data_width = get_check_parameters(ports=masters + [s for _, s in slaves]) shared = AXILiteInterface(data_width=data_width) - self.submodules.arbiter = AXILiteArbiter(masters, shared) - self.submodules.decoder = AXILiteDecoder(shared, slaves) + self.arbiter = AXILiteArbiter(masters, shared) + self.decoder = AXILiteDecoder(shared, slaves) if timeout_cycles is not None: - self.submodules.timeout = AXILiteTimeout(shared, timeout_cycles) + self.timeout = AXILiteTimeout(shared, timeout_cycles) -class AXILiteCrossbar(Module): +class AXILiteCrossbar(LiteXModule): """AXI Lite crossbar MxN crossbar for M masters and N slaves. diff --git a/litex/soc/interconnect/axi/axi_lite_to_csr.py b/litex/soc/interconnect/axi/axi_lite_to_csr.py index 0508c8775..b21dfa5b8 100644 --- a/litex/soc/interconnect/axi/axi_lite_to_csr.py +++ b/litex/soc/interconnect/axi/axi_lite_to_csr.py @@ -9,6 +9,8 @@ from migen import * +from litex.gen import * + from litex.build.generic_platform import * from litex.soc.interconnect.axi.axi_common import * @@ -16,7 +18,7 @@ from litex.soc.interconnect.axi.axi_lite import * # AXI-Lite to CSR ---------------------------------------------------------------------------------- -class AXILite2CSR(Module): +class AXILite2CSR(LiteXModule): def __init__(self, axi_lite=None, bus_csr=None, register=False): # TODO: unused register argument if axi_lite is None: @@ -33,5 +35,5 @@ class AXILite2CSR(Module): port_dat_r = self.csr.dat_r, port_dat_w = self.csr.dat_w, port_we = self.csr.we) - self.submodules.fsm = fsm + self.fsm = fsm self.comb += comb diff --git a/litex/soc/interconnect/axi/axi_lite_to_wishbone.py b/litex/soc/interconnect/axi/axi_lite_to_wishbone.py index 09ebf08c0..fa56b5c95 100644 --- a/litex/soc/interconnect/axi/axi_lite_to_wishbone.py +++ b/litex/soc/interconnect/axi/axi_lite_to_wishbone.py @@ -9,11 +9,13 @@ from migen import * +from litex.gen import * + from litex.soc.interconnect.axi.axi_lite import * # AXI-Lite to Wishbone ----------------------------------------------------------------------------- -class AXILite2Wishbone(Module): +class AXILite2Wishbone(LiteXModule): def __init__(self, axi_lite, wishbone, base_address=0x00000000): wishbone_adr_shift = log2_int(axi_lite.data_width//8) assert axi_lite.data_width == len(wishbone.dat_r) @@ -26,7 +28,7 @@ class AXILite2Wishbone(Module): self.comb += _r_addr.eq(axi_lite.ar.addr - base_address) self.comb += _w_addr.eq(axi_lite.aw.addr - base_address) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") + self.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", If(axi_lite.ar.valid & axi_lite.aw.valid, # If last access was a read, do a write @@ -88,7 +90,7 @@ class AXILite2Wishbone(Module): # Wishbone to AXI-Lite ----------------------------------------------------------------------------- -class Wishbone2AXILite(Module): +class Wishbone2AXILite(LiteXModule): def __init__(self, wishbone, axi_lite, base_address=0x00000000): wishbone_adr_shift = log2_int(axi_lite.data_width//8) assert axi_lite.data_width == len(wishbone.dat_r) @@ -99,7 +101,7 @@ class Wishbone2AXILite(Module): _addr = Signal(len(wishbone.adr)) self.comb += _addr.eq(wishbone.adr - base_address//4) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") + self.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", NextValue(_cmd_done, 0), NextValue(_data_done, 0), diff --git a/litex/soc/interconnect/axi/axi_stream.py b/litex/soc/interconnect/axi/axi_stream.py index 4e187687c..0b87c4fd0 100644 --- a/litex/soc/interconnect/axi/axi_stream.py +++ b/litex/soc/interconnect/axi/axi_stream.py @@ -1,7 +1,7 @@ # # This file is part of LiteX. # -# Copyright (c) 2018-2022 Florent Kermarrec +# Copyright (c) 2018-2023 Florent Kermarrec # Copyright (c) 2020 Antmicro # SPDX-License-Identifier: BSD-2-Clause @@ -9,6 +9,8 @@ from migen import * +from litex.gen import * + from litex.soc.interconnect import stream from litex.build.generic_platform import *