mac: add crossbar to simplify usage
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 30 Jan 2015 15:27:56 +0000 (16:27 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Fri, 30 Jan 2015 15:27:56 +0000 (16:27 +0100)
liteeth/__init__.py
liteeth/arp/__init__.py
liteeth/common.py
liteeth/ip/__init__.py
liteeth/mac/__init__.py
liteeth/mac/frontend/common.py [new file with mode: 0644]
liteeth/mac/frontend/crossbar.py [new file with mode: 0644]
liteeth/test/arp_tb.py
liteeth/test/ip_tb.py

index 38f150cefc947d5ecee3401e458ca725f06782c4..c3fdcb4f763d7d744f6417e1278ad3f35d5b8e67 100644 (file)
@@ -9,16 +9,6 @@ class LiteEthIPStack(Module, AutoCSR):
        def __init__(self, phy, mac_address, ip_address):
                self.phy = phy
                self.submodules.mac = mac = LiteEthMAC(phy, 8, interface="mac", with_hw_preamble_crc=True)
-               self.submodules.arp = arp = LiteEthARP(mac_address, ip_address)
-               self.submodules.ip = ip = LiteEthIP(ip_address, arp.table)
-
-               # MAC dispatch
-               self.submodules.mac_dispatcher = Dispatcher(mac.source, [arp.sink, ip.sink], one_hot=True)
-               self.comb += \
-                       Case(mac.source.ethernet_type, {
-                               ethernet_type_arp       : [self.mac_dispatcher.sel.eq(1)],
-                               ethernet_type_ip        : [self.mac_dispatcher.sel.eq(2)],
-                               "default"                       : [self.mac_dispatcher.sel.eq(0)],
-                       })
-               # MAC arbitrate
-               self.submodules.mac_arbiter = Arbiter([arp.source, ip.source], mac.sink)
+               self.submodules.arp = arp = LiteEthARP(mac, mac_address, ip_address)
+               self.submodules.ip = ip = LiteEthIP(mac, ip_address, arp.table)
+               self.sink, self.source = self.ip.sink, self.ip.source
index 9d6551d2cc9a7d3fc7e91deb99f91cfcd916d2e2..08a406ab7098d6bbd7cff8ad6eb75b62b6e06a06 100644 (file)
@@ -221,7 +221,7 @@ class LiteEthARPTable(Module):
                )
 
 class LiteEthARP(Module):
-       def __init__(self, mac_address, ip_address):
+       def __init__(self, mac, mac_address, ip_address):
                self.submodules.tx = LiteEthARPTX(mac_address, ip_address)
                self.submodules.rx = LiteEthARPRX(mac_address, ip_address)
                self.submodules.table = LiteEthARPTable()
@@ -229,5 +229,8 @@ class LiteEthARP(Module):
                        Record.connect(self.rx.source, self.table.sink),
                        Record.connect(self.table.source, self.tx.sink)
                ]
-               self.sink, self.source = self.rx.sink, self.tx.source
-               self.request, self.response = self.table.request, self.table.response
+               mac_port = mac.crossbar.get_port(ethernet_type_arp)
+               self.comb += [
+                       Record.connect(self.tx.source, mac_port.sink),
+                       Record.connect(mac_port.source, self.rx.sink)
+               ]
index d1ce2cc2b791fc3482c0954e0cfa780c1c034d1a..c9ed17ce989b29140e3e5673fb75b7a170785c19 100644 (file)
@@ -78,7 +78,7 @@ udp_header = {
 }
 
 def reverse_bytes(v):
-       n = math.ceil(flen(v)//8)
+       n = math.ceil(flen(v)/8)
        r = []
        for i in reversed(range(n)):
                r.append(v[i*8:min((i+1)*8, flen(v))])
index 1aa47367b5c085f940fffb37f5ddd519338efe11..8673fe94c3e3217434d9ee141f598e8e252b82ae 100644 (file)
@@ -103,7 +103,12 @@ class LiteEthIPRX(Module):
                )
 
 class LiteEthIP(Module):
-       def __init__(self, ip_address, arp_table):
+       def __init__(self, mac, ip_address, arp_table):
                self.submodules.tx = LiteEthIPTX(ip_address, arp_table)
                self.submodules.rx = LiteEthIPRX(ip_address)
-               self.sink, self.source = self.rx.sink, self.tx.source
+               mac_port = mac.crossbar.get_port(ethernet_type_ip)
+               self.comb += [
+                       Record.connect(self.tx.source, mac_port.sink),
+                       Record.connect(mac_port.source, self.rx.sink)
+               ]
+               self.sink, self.source = self.tx.sink, self.rx.source
index 320f32b106863cf13001dcf51715e09a3cd19ae2..b46b501be381af2eec203107daabb88b47d4bdef 100644 (file)
@@ -1,8 +1,9 @@
 from liteeth.common import *
-from liteeth.mac.core import LiteEthMACCore
-from liteeth.mac.frontend import wishbone
 from liteeth.generic.depacketizer import LiteEthDepacketizer
 from liteeth.generic.packetizer import LiteEthPacketizer
+from liteeth.mac.core import LiteEthMACCore
+from liteeth.mac.frontend.wishbone import LiteEthMACWishboneInterface
+from liteeth.mac.frontend.crossbar import LiteEthMACCrossbar
 
 class LiteEthMACDepacketizer(LiteEthDepacketizer):
        def __init__(self):
@@ -21,20 +22,20 @@ class LiteEthMACPacketizer(LiteEthPacketizer):
                        mac_header_len)
 
 class LiteEthMAC(Module, AutoCSR):
-       def __init__(self, phy, dw, interface="mac", endianness="be",
+       def __init__(self, phy, dw, interface="crossbar", endianness="be",
                        with_hw_preamble_crc=True):
                self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_hw_preamble_crc)
                self.csrs = None
-               if interface == "mac":
-                       packetizer = LiteEthMACPacketizer()
-                       depacketizer = LiteEthMACDepacketizer()
-                       self.submodules += packetizer, depacketizer
+               if interface == "crossbar":
+                       self.submodules.crossbar = LiteEthMACCrossbar()
+                       self.submodules.packetizer = LiteEthMACPacketizer()
+                       self.submodules.depacketizer = LiteEthMACDepacketizer()
                        self.comb += [
-                               Record.connect(packetizer.source, self.core.sink),
-                               Record.connect(self.core.source, depacketizer.sink)
+                               Record.connect(self.crossbar.master.source, self.packetizer.sink),
+                               Record.connect(self.packetizer.source, self.core.sink),
+                               Record.connect(self.core.source, self.depacketizer.sink),
+                               Record.connect(self.depacketizer.source, self.crossbar.master.sink)
                        ]
-                       self.sink, self.source = packetizer.sink, depacketizer.source
-                       pass
                elif interface == "wishbone":
                        self.submodules.interface = wishbone.LiteEthMACWishboneInterface(dw, 2, 2)
                        self.comb += [
diff --git a/liteeth/mac/frontend/common.py b/liteeth/mac/frontend/common.py
new file mode 100644 (file)
index 0000000..b945ded
--- /dev/null
@@ -0,0 +1,27 @@
+from liteeth.common import *
+
+class LiteEthMACMasterPort:
+       def __init__(self, dw):
+               self.source = Source(eth_mac_description(dw))
+               self.sink = Sink(eth_mac_description(dw))
+
+       def connect(self, slave):
+               return [
+                       Record.connect(self.source, slave.sink),
+                       Record.connect(slave.source, self.sink)
+               ]
+
+class LiteEthMACSlavePort:
+       def __init__(self, dw):
+               self.sink = Sink(eth_mac_description(dw))
+               self.source = Source(eth_mac_description(dw))
+
+       def connect(self, master):
+               return [
+                       Record.connect(self.sink, master.source),
+                       Record.connect(master.sink, self.source)
+               ]
+
+class LiteEthMACUserPort(LiteEthMACSlavePort):
+       def __init__(self, dw):
+               LiteEthMACSlavePort.__init__(self, dw)
diff --git a/liteeth/mac/frontend/crossbar.py b/liteeth/mac/frontend/crossbar.py
new file mode 100644 (file)
index 0000000..696e353
--- /dev/null
@@ -0,0 +1,33 @@
+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 {} already used")
+               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)
index 27e34a4aa4cc9b69b0d7c7aa48bab61d30889354..89f6fe9cf9aff7e6337c31b963d7c13002a93be6 100644 (file)
@@ -19,8 +19,8 @@ class TB(Module):
                self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False)
                self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=True)
 
-               self.submodules.core = LiteEthMAC(phy=self.phy_model, dw=8, with_hw_preamble_crc=True)
-               self.submodules.arp = LiteEthARP(mac_address, ip_address)
+               self.submodules.mac = LiteEthMAC(self.phy_model, dw=8, with_hw_preamble_crc=True)
+               self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address)
 
                # use sys_clk for each clock_domain
                self.clock_domains.cd_eth_rx = ClockDomain()
@@ -32,11 +32,6 @@ class TB(Module):
                        self.cd_eth_tx.rst.eq(ResetSignal()),
                ]
 
-               self.comb += [
-                       Record.connect(self.arp.source, self.core.sink),
-                       Record.connect(self.core.source, self.arp.sink)
-               ]
-
        def gen_simulation(self, selfp):
                selfp.cd_eth_rx.rst = 1
                selfp.cd_eth_tx.rst = 1
@@ -55,6 +50,7 @@ class TB(Module):
                while selfp.arp.table.response.stb != 1:
                        selfp.arp.table.response.ack = 1
                        yield
+               print("Model MAC : 0x%12x" %selfp.arp.table.response.mac_address)
 
 
 if __name__ == "__main__":
index fa751b6000b9c47d82bc94a0007c8289f2f36fa9..83a20055aa6b75c15e6df3f1b7335cde72dcd100 100644 (file)
@@ -40,9 +40,9 @@ class TB(Module):
                for i in range(100):
                        yield
 
-               #selfp.ip.sink.stb = 1
-               #selfp.ip.sink.destination_ip_address = 0x12345678
-               #selfp.ip.sink.source_ip_address = ip_address
+               selfp.ip.sink.stb = 1
+               selfp.ip.sink.destination_ip_address = 0x12345678
+               selfp.ip.sink.source_ip_address = ip_address
 
 if __name__ == "__main__":
        run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)