interconnect/axi: Switch to LiteXModule.

This commit is contained in:
Florent Kermarrec 2023-07-28 09:15:22 +02:00
parent ed12f8787d
commit 717fb131fd
7 changed files with 75 additions and 66 deletions

View File

@ -1,7 +1,7 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2018-2022 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2018-2023 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Antmicro <www.antmicro.com>
# 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.

View File

@ -1,7 +1,7 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2018-2022 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2018-2023 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Antmicro <www.antmicro.com>
# 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)

View File

@ -1,7 +1,7 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2018-2022 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2018-2023 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Antmicro <www.antmicro.com>
# 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)

View File

@ -1,7 +1,7 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2018-2022 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2018-2023 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Antmicro <www.antmicro.com>
# 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.

View File

@ -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

View File

@ -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),

View File

@ -1,7 +1,7 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2018-2022 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2018-2023 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Antmicro <www.antmicro.com>
# 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 *