From: Florent Kermarrec Date: Tue, 10 Feb 2015 14:11:06 +0000 (+0100) Subject: generic: add crossbar and use it in mac/ip/udp X-Git-Tag: 24jan2021_ls180~2604^2~47 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3187a93984046f27b1db94990c48089c213f106c;p=litex.git generic: add crossbar and use it in mac/ip/udp --- diff --git a/liteeth/core/ip/__init__.py b/liteeth/core/ip/__init__.py index 64a386fd..8e522a99 100644 --- a/liteeth/core/ip/__init__.py +++ b/liteeth/core/ip/__init__.py @@ -1,7 +1,8 @@ from liteeth.common import * from liteeth.generic.depacketizer import LiteEthDepacketizer from liteeth.generic.packetizer import LiteEthPacketizer -from liteeth.core.ip.crossbar import LiteEthIPV4Crossbar +from liteeth.generic.crossbar import LiteEthCrossbar +from liteeth.core.ip.common import * class LiteEthIPV4Depacketizer(LiteEthDepacketizer): def __init__(self): @@ -19,6 +20,17 @@ class LiteEthIPV4Packetizer(LiteEthPacketizer): ipv4_header, ipv4_header_len) +class LiteEthIPV4Crossbar(LiteEthCrossbar): + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol") + + def get_port(self, protocol): + if protocol in self.users.keys(): + raise ValueError("Protocol {0:#x} already assigned".format(protocol)) + port = LiteEthIPV4UserPort(8) + self.users[protocol] = port + return port + class LiteEthIPV4Checksum(Module): def __init__(self, words_per_clock_cycle=1, skip_checksum=False): self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog diff --git a/liteeth/core/ip/crossbar.py b/liteeth/core/ip/crossbar.py deleted file mode 100644 index edff815b..00000000 --- a/liteeth/core/ip/crossbar.py +++ /dev/null @@ -1,33 +0,0 @@ -from collections import OrderedDict - -from liteeth.common import * -from liteeth.generic.arbiter import Arbiter -from liteeth.generic.dispatcher import Dispatcher -from liteeth.core.ip.common import * - -class LiteEthIPV4Crossbar(Module): - def __init__(self): - self.users = OrderedDict() - self.master = LiteEthIPV4MasterPort(8) - - def get_port(self, protocol): - if protocol in self.users.keys(): - raise ValueError("Protocol {0:#x} already assigned".format(protocol)) - port = LiteEthIPV4UserPort(8) - self.users[protocol] = port - return port - - def do_finalize(self): - # TX arbitrate - sinks = [port.sink for port in self.users.values()] - self.submodules.ip_arbiter = Arbiter(sinks, self.master.source) - - # RX dispatch - sources = [port.source for port in self.users.values()] - self.submodules.ip_dispatcher = Dispatcher(self.master.sink, sources, one_hot=True) - cases = {} - cases["default"] = self.ip_dispatcher.sel.eq(0) - for i, (k, v) in enumerate(self.users.items()): - cases[k] = self.ip_dispatcher.sel.eq(2**i) - self.comb += \ - Case(self.master.sink.protocol, cases) diff --git a/liteeth/core/udp/__init__.py b/liteeth/core/udp/__init__.py index 7a8ae5f0..55f62414 100644 --- a/liteeth/core/udp/__init__.py +++ b/liteeth/core/udp/__init__.py @@ -1,7 +1,8 @@ from liteeth.common import * from liteeth.generic.depacketizer import LiteEthDepacketizer from liteeth.generic.packetizer import LiteEthPacketizer -from liteeth.core.udp.crossbar import LiteEthUDPCrossbar +from liteeth.generic.crossbar import LiteEthCrossbar +from liteeth.core.udp.common import * class LiteEthUDPDepacketizer(LiteEthDepacketizer): def __init__(self): @@ -19,6 +20,33 @@ class LiteEthUDPPacketizer(LiteEthPacketizer): udp_header, udp_header_len) +class LiteEthUDPCrossbar(LiteEthCrossbar): + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port") + + def get_port(self, udp_port, dw=8): + if udp_port in self.users.keys(): + raise ValueError("Port {0:#x} already assigned".format(udp_port)) + user_port = LiteEthUDPUserPort(dw) + internal_port = LiteEthUDPUserPort(8) + if dw != 8: + converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8)) + self.submodules += converter + self.comb += [ + Record.connect(user_port.sink, converter.sink), + Record.connect(converter.source, internal_port.sink) + ] + converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw)) + self.submodules += converter + self.comb += [ + Record.connect(internal_port.source, converter.sink), + Record.connect(converter.source, user_port.source) + ] + self.users[udp_port] = internal_port + else: + self.users[udp_port] = user_port + return user_port + class LiteEthUDPTX(Module): def __init__(self, ip_address): self.sink = sink = Sink(eth_udp_user_description(8)) diff --git a/liteeth/core/udp/crossbar.py b/liteeth/core/udp/crossbar.py deleted file mode 100644 index ccc7594d..00000000 --- a/liteeth/core/udp/crossbar.py +++ /dev/null @@ -1,49 +0,0 @@ -from collections import OrderedDict - -from liteeth.common import * -from liteeth.generic.arbiter import Arbiter -from liteeth.generic.dispatcher import Dispatcher -from liteeth.core.udp.common import * - -class LiteEthUDPCrossbar(Module): - def __init__(self): - self.users = OrderedDict() - self.master = LiteEthUDPMasterPort(8) - - def get_port(self, udp_port, dw=8): - if udp_port in self.users.keys(): - raise ValueError("Port {0:#x} already assigned".format(udp_port)) - user_port = LiteEthUDPUserPort(dw) - internal_port = LiteEthUDPUserPort(8) - if dw != 8: - converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8)) - self.submodules += converter - self.comb += [ - Record.connect(user_port.sink, converter.sink), - Record.connect(converter.source, internal_port.sink) - ] - converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw)) - self.submodules += converter - self.comb += [ - Record.connect(internal_port.source, converter.sink), - Record.connect(converter.source, user_port.source) - ] - self.users[udp_port] = internal_port - else: - self.users[udp_port] = user_port - return user_port - - def do_finalize(self): - # TX arbitrate - sinks = [port.sink for port in self.users.values()] - self.submodules.udp_arbiter = Arbiter(sinks, self.master.source) - - # RX dispatch - sources = [port.source for port in self.users.values()] - self.submodules.udp_dispatcher = Dispatcher(self.master.sink, sources, one_hot=True) - cases = {} - cases["default"] = self.udp_dispatcher.sel.eq(0) - for i, (k, v) in enumerate(self.users.items()): - cases[k] = self.udp_dispatcher.sel.eq(2**i) - self.comb += \ - Case(self.master.sink.dst_port, cases) diff --git a/liteeth/generic/arbiter.py b/liteeth/generic/arbiter.py index 39f13db7..ca77377e 100644 --- a/liteeth/generic/arbiter.py +++ b/liteeth/generic/arbiter.py @@ -8,7 +8,7 @@ class Arbiter(Module): pass elif len(sources) == 1: self.grant = Signal() - self.comb += Record.connect(sources[0], sink) + self.comb += Record.connect(sources.pop(), sink) else: self.submodules.rr = RoundRobin(len(sources)) self.grant = self.rr.grant diff --git a/liteeth/generic/crossbar.py b/liteeth/generic/crossbar.py new file mode 100644 index 00000000..4f897856 --- /dev/null +++ b/liteeth/generic/crossbar.py @@ -0,0 +1,30 @@ +from collections import OrderedDict + +from liteeth.common import * +from liteeth.generic.arbiter import Arbiter +from liteeth.generic.dispatcher import Dispatcher + +class LiteEthCrossbar(Module): + def __init__(self, master_port, dispatch_param): + self.users = OrderedDict() + self.master = master_port(8) + self.dispatch_param = dispatch_param + + # overload this in derived classes + def get_port(self, *args, **kwargs): + pass + + def do_finalize(self): + # TX arbitrate + sinks = [port.sink for port in self.users.values()] + self.submodules.arbiter = Arbiter(sinks, self.master.source) + + # RX dispatch + sources = [port.source for port in self.users.values()] + self.submodules.dispatcher = Dispatcher(self.master.sink, sources, one_hot=True) + cases = {} + cases["default"] = self.dispatcher.sel.eq(0) + for i, (k, v) in enumerate(self.users.items()): + cases[k] = self.dispatcher.sel.eq(2**i) + self.comb += \ + Case(getattr(self.master.sink, self.dispatch_param), cases) diff --git a/liteeth/generic/dispatcher.py b/liteeth/generic/dispatcher.py index a9ecd5d1..3acb9f90 100644 --- a/liteeth/generic/dispatcher.py +++ b/liteeth/generic/dispatcher.py @@ -6,7 +6,7 @@ class Dispatcher(Module): if len(sinks) == 0: self.sel = Signal() elif len(sinks) == 1: - self.comb += Record.connect(source, sinks[0]) + self.comb += Record.connect(source, sinks.pop()) self.sel = Signal() else: if one_hot: diff --git a/liteeth/mac/__init__.py b/liteeth/mac/__init__.py index 2b9cfb63..e2032d89 100644 --- a/liteeth/mac/__init__.py +++ b/liteeth/mac/__init__.py @@ -1,9 +1,10 @@ from liteeth.common import * from liteeth.generic.depacketizer import LiteEthDepacketizer from liteeth.generic.packetizer import LiteEthPacketizer +from liteeth.generic.crossbar import LiteEthCrossbar from liteeth.mac.core import LiteEthMACCore +from liteeth.mac.frontend.common import * from liteeth.mac.frontend.wishbone import LiteEthMACWishboneInterface -from liteeth.mac.frontend.crossbar import LiteEthMACCrossbar class LiteEthMACDepacketizer(LiteEthDepacketizer): def __init__(self): @@ -21,6 +22,17 @@ class LiteEthMACPacketizer(LiteEthPacketizer): mac_header, mac_header_len) +class LiteEthMACCrossbar(LiteEthCrossbar): + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthMACMasterPort, "ethernet_type") + + def get_port(self, ethernet_type): + port = LiteEthMACUserPort(8) + if ethernet_type in self.users.keys(): + raise ValueError("Ethernet type {0:#x} already assigned".format(ethernet_type)) + self.users[ethernet_type] = port + return port + class LiteEthMAC(Module, AutoCSR): def __init__(self, phy, dw, interface="crossbar", endianness="big", with_hw_preamble_crc=True): diff --git a/liteeth/mac/frontend/crossbar.py b/liteeth/mac/frontend/crossbar.py deleted file mode 100644 index 94fab8ab..00000000 --- a/liteeth/mac/frontend/crossbar.py +++ /dev/null @@ -1,33 +0,0 @@ -from collections import OrderedDict - -from liteeth.common import * -from liteeth.generic.arbiter import Arbiter -from liteeth.generic.dispatcher import Dispatcher -from liteeth.mac.frontend.common import * - -class LiteEthMACCrossbar(Module): - def __init__(self): - self.users = OrderedDict() - self.master = LiteEthMACMasterPort(8) - - def get_port(self, ethernet_type): - port = LiteEthMACUserPort(8) - if ethernet_type in self.users.keys(): - raise ValueError("Ethernet type {0:#x} already assigned".format(ethernet_type)) - self.users[ethernet_type] = port - return port - - def do_finalize(self): - # TX arbitrate - sinks = [port.sink for port in self.users.values()] - self.submodules.mac_arbiter = Arbiter(sinks, self.master.source) - - # RX dispatch - sources = [port.source for port in self.users.values()] - self.submodules.mac_dispatcher = Dispatcher(self.master.sink, sources, one_hot=True) - cases = {} - cases["default"] = self.mac_dispatcher.sel.eq(0) - for i, (k, v) in enumerate(self.users.items()): - cases[k] = self.mac_dispatcher.sel.eq(2**i) - self.comb += \ - Case(self.master.sink.ethernet_type, cases)