reorganize core files
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 4 Feb 2015 18:57:20 +0000 (19:57 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 4 Feb 2015 18:57:20 +0000 (19:57 +0100)
13 files changed:
liteeth/__init__.py
liteeth/arp/__init__.py [deleted file]
liteeth/core/__init__.py [new file with mode: 0644]
liteeth/core/arp.py [new file with mode: 0644]
liteeth/core/ip.py [new file with mode: 0644]
liteeth/core/udp.py [new file with mode: 0644]
liteeth/etherbone/__init__.py [deleted file]
liteeth/frontend/__init__.py [new file with mode: 0644]
liteeth/frontend/etherbone.py [new file with mode: 0644]
liteeth/ip/__init__.py [deleted file]
liteeth/test/arp_tb.py
liteeth/test/ip_tb.py
liteeth/udp/__init__.py [deleted file]

index 3a218059862918223bed014a76804cd0cb55e4ec..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,12 +0,0 @@
-from liteeth.common import *
-from liteeth.mac import LiteEthMAC
-from liteeth.arp import LiteEthARP
-from liteeth.ip import LiteEthIP
-
-class LiteEthIPStack(Module, AutoCSR):
-       def __init__(self, phy, mac_address, ip_address):
-               self.phy = phy
-               self.submodules.mac = mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
-               self.submodules.arp = arp = LiteEthARP(mac, mac_address, ip_address)
-               self.submodules.ip = ip = LiteEthIP(mac, mac_address, ip_address, arp.table)
-               self.sink, self.source = self.ip.sink, self.ip.source
diff --git a/liteeth/arp/__init__.py b/liteeth/arp/__init__.py
deleted file mode 100644 (file)
index 49d1af9..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-from liteeth.common import *
-from liteeth.generic.depacketizer import LiteEthDepacketizer
-from liteeth.generic.packetizer import LiteEthPacketizer
-
-_arp_table_layout = [
-               ("reply", 1),
-               ("request", 1),
-               ("ip_address", 32),
-               ("mac_address", 48)
-       ]
-
-class LiteEthARPDepacketizer(LiteEthDepacketizer):
-       def __init__(self):
-               LiteEthDepacketizer.__init__(self,
-                       eth_mac_description(8),
-                       eth_arp_description(8),
-                       arp_header,
-                       arp_header_len)
-
-class LiteEthARPPacketizer(LiteEthPacketizer):
-       def __init__(self):
-               LiteEthPacketizer.__init__(self,
-                       eth_arp_description(8),
-                       eth_mac_description(8),
-                       arp_header,
-                       arp_header_len)
-
-class LiteEthARPTX(Module):
-       def __init__(self, mac_address, ip_address):
-               self.sink = sink = Sink(_arp_table_layout)
-               self.source = Source(eth_mac_description(8))
-               ###
-               packetizer = LiteEthARPPacketizer()
-               self.submodules += packetizer
-               source = packetizer.sink
-
-               counter = Counter(max=arp_packet_length)
-               self.submodules += counter
-
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += fsm
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       counter.reset.eq(1),
-                       If(sink.stb,
-                               sink.ack.eq(0),
-                               NextState("SEND")
-                       )
-               )
-               self.comb += [
-                       source.hardware_type.eq(arp_hwtype_ethernet),
-                       source.protocol_type.eq(arp_proto_ip),
-                       source.hardware_address_length.eq(6),
-                       source.protocol_address_length.eq(4),
-                       source.source_mac_address.eq(mac_address),
-                       source.source_ip_address.eq(ip_address),
-                       If(sink.reply,
-                               source.operation.eq(arp_opcode_reply),
-                               source.destination_mac_address.eq(sink.mac_address),
-                               source.destination_ip_address.eq(sink.ip_address)
-                       ).Elif(sink.request,
-                               source.operation.eq(arp_opcode_request),
-                               source.destination_mac_address.eq(0xffffffffffff),
-                               source.destination_ip_address.eq(sink.ip_address)
-                       )
-               ]
-               fsm.act("SEND",
-                       source.stb.eq(1),
-                       source.sop.eq(counter.value == 0),
-                       source.eop.eq(counter.value == arp_packet_length-1),
-                       Record.connect(packetizer.source, self.source),
-                       self.source.destination_mac_address.eq(source.destination_mac_address),
-                       self.source.source_mac_address.eq(mac_address),
-                       self.source.ethernet_type.eq(ethernet_type_arp),
-                       If(self.source.stb & self.source.ack,
-                               sink.ack.eq(source.eop),
-                               counter.ce.eq(1),
-                               If(self.source.eop,
-                                       NextState("IDLE")
-                               )
-                       )
-               )
-
-class LiteEthARPRX(Module):
-       def __init__(self, mac_address, ip_address):
-               self.sink = Sink(eth_mac_description(8))
-               self.source = source = Source(_arp_table_layout)
-               ###
-               depacketizer = LiteEthARPDepacketizer()
-               self.submodules += depacketizer
-               self.comb += Record.connect(self.sink, depacketizer.sink)
-               sink = depacketizer.source
-
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += fsm
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("CHECK")
-                       )
-               )
-               valid = Signal()
-               self.comb += valid.eq(
-                       sink.stb &
-                       (sink.hardware_type == arp_hwtype_ethernet) &
-                       (sink.protocol_type == arp_proto_ip) &
-                       (sink.hardware_address_length == 6) &
-                       (sink.protocol_address_length == 4) &
-                       (sink.destination_ip_address == ip_address)
-               )
-               reply = Signal()
-               request = Signal()
-               self.comb += Case(sink.operation, {
-                       arp_opcode_request      :       [request.eq(1)],
-                       arp_opcode_reply        :       [reply.eq(1)],
-                       "default"                       :       []
-                       })
-               self.comb += [
-                       source.ip_address.eq(sink.source_ip_address),
-                       source.mac_address.eq(sink.source_mac_address)
-               ]
-               fsm.act("CHECK",
-                       If(valid,
-                               source.stb.eq(1),
-                               source.reply.eq(reply),
-                               source.request.eq(request)
-                       ),
-                       NextState("TERMINATE")
-               ),
-               fsm.act("TERMINATE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.eop,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthARPTable(Module):
-       def __init__(self):
-               self.sink = sink = Sink(_arp_table_layout)              # from arp_rx
-               self.source = source = Source(_arp_table_layout)        # to arp_tx
-
-               # Request/Response interface
-               self.request = request = Sink(arp_table_request_layout)
-               self.response = response = Source(arp_table_response_layout)
-               ###
-               request_timeout = Timeout(512)  # XXX fix me 100ms?
-               request_pending = FlipFlop()
-               request_ip_address = FlipFlop(32, reset=0xffffffff) # XXX add cached_valid?
-               self.submodules += request_timeout, request_pending, request_ip_address
-               self.comb += [
-                       request_timeout.ce.eq(request_pending.q),
-                       request_pending.d.eq(1),
-                       request_ip_address.d.eq(request.ip_address)
-               ]
-
-               # Note: Store only one ip/mac couple, replace this with
-               # a real ARP table
-               update = Signal()
-               cached_ip_address = Signal(32)
-               cached_mac_address = Signal(48)
-
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += fsm
-               fsm.act("IDLE",
-                       # Note: for simplicicy, if APR table is busy response from arp_rx
-                       # is lost. This is compensated by the protocol (retrys)
-                       If(sink.stb & sink.request,
-                               NextState("SEND_REPLY")
-                       ).Elif(sink.stb & sink.reply & request_pending.q,
-                               NextState("UPDATE_TABLE"),
-                       ).Elif(request.stb | (request_pending.q & request_timeout.reached),
-                               NextState("CHECK_TABLE")
-                       )
-               )
-               fsm.act("SEND_REPLY",
-                       source.stb.eq(1),
-                       source.reply.eq(1),
-                       source.ip_address.eq(sink.ip_address),
-                       If(source.ack,
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("UPDATE_TABLE",
-                       request_pending.reset.eq(1),
-                       update.eq(1),
-                       NextState("CHECK_TABLE")
-               )
-               self.sync += [
-                       If(update,
-                               cached_ip_address.eq(sink.ip_address),
-                               cached_mac_address.eq(sink.mac_address)
-                       )
-               ]
-               found = Signal()
-               fsm.act("CHECK_TABLE",
-                       # XXX: add a live time for cached_mac_address
-                       If(request_ip_address.q == cached_ip_address,
-                               request_ip_address.reset.eq(1),
-                               NextState("PRESENT_RESPONSE"),
-                       ).Elif(request.ip_address == cached_ip_address,
-                               request.ack.eq(request.stb),
-                               NextState("PRESENT_RESPONSE"),
-                       ).Else(
-                               request_ip_address.ce.eq(1),
-                               NextState("SEND_REQUEST")
-                       )
-               )
-               fsm.act("SEND_REQUEST",
-                       source.stb.eq(1),
-                       source.request.eq(1),
-                       source.ip_address.eq(request.ip_address),
-                       If(source.ack,
-                               request_timeout.reset.eq(1),
-                               request_pending.ce.eq(1),
-                               request.ack.eq(1),
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("PRESENT_RESPONSE",
-                       response.stb.eq(1),
-                       response.failed.eq(0), # XXX add timeout to trigger failed
-                       response.mac_address.eq(cached_mac_address),
-                       If(response.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthARP(Module):
-       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()
-               self.comb += [
-                       Record.connect(self.rx.source, self.table.sink),
-                       Record.connect(self.table.source, self.tx.sink)
-               ]
-               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)
-               ]
diff --git a/liteeth/core/__init__.py b/liteeth/core/__init__.py
new file mode 100644 (file)
index 0000000..fa0aaa9
--- /dev/null
@@ -0,0 +1,12 @@
+from liteeth.common import *
+from liteeth.mac import LiteEthMAC
+from liteeth.core.arp import LiteEthARP
+from liteeth.core.ip import LiteEthIP
+
+class LiteEthIPCore(Module, AutoCSR):
+       def __init__(self, phy, mac_address, ip_address):
+               self.phy = phy
+               self.submodules.mac = mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
+               self.submodules.arp = arp = LiteEthARP(mac, mac_address, ip_address)
+               self.submodules.ip = ip = LiteEthIP(mac, mac_address, ip_address, arp.table)
+               self.sink, self.source = self.ip.sink, self.ip.source
diff --git a/liteeth/core/arp.py b/liteeth/core/arp.py
new file mode 100644 (file)
index 0000000..49d1af9
--- /dev/null
@@ -0,0 +1,242 @@
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+_arp_table_layout = [
+               ("reply", 1),
+               ("request", 1),
+               ("ip_address", 32),
+               ("mac_address", 48)
+       ]
+
+class LiteEthARPDepacketizer(LiteEthDepacketizer):
+       def __init__(self):
+               LiteEthDepacketizer.__init__(self,
+                       eth_mac_description(8),
+                       eth_arp_description(8),
+                       arp_header,
+                       arp_header_len)
+
+class LiteEthARPPacketizer(LiteEthPacketizer):
+       def __init__(self):
+               LiteEthPacketizer.__init__(self,
+                       eth_arp_description(8),
+                       eth_mac_description(8),
+                       arp_header,
+                       arp_header_len)
+
+class LiteEthARPTX(Module):
+       def __init__(self, mac_address, ip_address):
+               self.sink = sink = Sink(_arp_table_layout)
+               self.source = Source(eth_mac_description(8))
+               ###
+               packetizer = LiteEthARPPacketizer()
+               self.submodules += packetizer
+               source = packetizer.sink
+
+               counter = Counter(max=arp_packet_length)
+               self.submodules += counter
+
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       counter.reset.eq(1),
+                       If(sink.stb,
+                               sink.ack.eq(0),
+                               NextState("SEND")
+                       )
+               )
+               self.comb += [
+                       source.hardware_type.eq(arp_hwtype_ethernet),
+                       source.protocol_type.eq(arp_proto_ip),
+                       source.hardware_address_length.eq(6),
+                       source.protocol_address_length.eq(4),
+                       source.source_mac_address.eq(mac_address),
+                       source.source_ip_address.eq(ip_address),
+                       If(sink.reply,
+                               source.operation.eq(arp_opcode_reply),
+                               source.destination_mac_address.eq(sink.mac_address),
+                               source.destination_ip_address.eq(sink.ip_address)
+                       ).Elif(sink.request,
+                               source.operation.eq(arp_opcode_request),
+                               source.destination_mac_address.eq(0xffffffffffff),
+                               source.destination_ip_address.eq(sink.ip_address)
+                       )
+               ]
+               fsm.act("SEND",
+                       source.stb.eq(1),
+                       source.sop.eq(counter.value == 0),
+                       source.eop.eq(counter.value == arp_packet_length-1),
+                       Record.connect(packetizer.source, self.source),
+                       self.source.destination_mac_address.eq(source.destination_mac_address),
+                       self.source.source_mac_address.eq(mac_address),
+                       self.source.ethernet_type.eq(ethernet_type_arp),
+                       If(self.source.stb & self.source.ack,
+                               sink.ack.eq(source.eop),
+                               counter.ce.eq(1),
+                               If(self.source.eop,
+                                       NextState("IDLE")
+                               )
+                       )
+               )
+
+class LiteEthARPRX(Module):
+       def __init__(self, mac_address, ip_address):
+               self.sink = Sink(eth_mac_description(8))
+               self.source = source = Source(_arp_table_layout)
+               ###
+               depacketizer = LiteEthARPDepacketizer()
+               self.submodules += depacketizer
+               self.comb += Record.connect(self.sink, depacketizer.sink)
+               sink = depacketizer.source
+
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("CHECK")
+                       )
+               )
+               valid = Signal()
+               self.comb += valid.eq(
+                       sink.stb &
+                       (sink.hardware_type == arp_hwtype_ethernet) &
+                       (sink.protocol_type == arp_proto_ip) &
+                       (sink.hardware_address_length == 6) &
+                       (sink.protocol_address_length == 4) &
+                       (sink.destination_ip_address == ip_address)
+               )
+               reply = Signal()
+               request = Signal()
+               self.comb += Case(sink.operation, {
+                       arp_opcode_request      :       [request.eq(1)],
+                       arp_opcode_reply        :       [reply.eq(1)],
+                       "default"                       :       []
+                       })
+               self.comb += [
+                       source.ip_address.eq(sink.source_ip_address),
+                       source.mac_address.eq(sink.source_mac_address)
+               ]
+               fsm.act("CHECK",
+                       If(valid,
+                               source.stb.eq(1),
+                               source.reply.eq(reply),
+                               source.request.eq(request)
+                       ),
+                       NextState("TERMINATE")
+               ),
+               fsm.act("TERMINATE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.eop,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthARPTable(Module):
+       def __init__(self):
+               self.sink = sink = Sink(_arp_table_layout)              # from arp_rx
+               self.source = source = Source(_arp_table_layout)        # to arp_tx
+
+               # Request/Response interface
+               self.request = request = Sink(arp_table_request_layout)
+               self.response = response = Source(arp_table_response_layout)
+               ###
+               request_timeout = Timeout(512)  # XXX fix me 100ms?
+               request_pending = FlipFlop()
+               request_ip_address = FlipFlop(32, reset=0xffffffff) # XXX add cached_valid?
+               self.submodules += request_timeout, request_pending, request_ip_address
+               self.comb += [
+                       request_timeout.ce.eq(request_pending.q),
+                       request_pending.d.eq(1),
+                       request_ip_address.d.eq(request.ip_address)
+               ]
+
+               # Note: Store only one ip/mac couple, replace this with
+               # a real ARP table
+               update = Signal()
+               cached_ip_address = Signal(32)
+               cached_mac_address = Signal(48)
+
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       # Note: for simplicicy, if APR table is busy response from arp_rx
+                       # is lost. This is compensated by the protocol (retrys)
+                       If(sink.stb & sink.request,
+                               NextState("SEND_REPLY")
+                       ).Elif(sink.stb & sink.reply & request_pending.q,
+                               NextState("UPDATE_TABLE"),
+                       ).Elif(request.stb | (request_pending.q & request_timeout.reached),
+                               NextState("CHECK_TABLE")
+                       )
+               )
+               fsm.act("SEND_REPLY",
+                       source.stb.eq(1),
+                       source.reply.eq(1),
+                       source.ip_address.eq(sink.ip_address),
+                       If(source.ack,
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("UPDATE_TABLE",
+                       request_pending.reset.eq(1),
+                       update.eq(1),
+                       NextState("CHECK_TABLE")
+               )
+               self.sync += [
+                       If(update,
+                               cached_ip_address.eq(sink.ip_address),
+                               cached_mac_address.eq(sink.mac_address)
+                       )
+               ]
+               found = Signal()
+               fsm.act("CHECK_TABLE",
+                       # XXX: add a live time for cached_mac_address
+                       If(request_ip_address.q == cached_ip_address,
+                               request_ip_address.reset.eq(1),
+                               NextState("PRESENT_RESPONSE"),
+                       ).Elif(request.ip_address == cached_ip_address,
+                               request.ack.eq(request.stb),
+                               NextState("PRESENT_RESPONSE"),
+                       ).Else(
+                               request_ip_address.ce.eq(1),
+                               NextState("SEND_REQUEST")
+                       )
+               )
+               fsm.act("SEND_REQUEST",
+                       source.stb.eq(1),
+                       source.request.eq(1),
+                       source.ip_address.eq(request.ip_address),
+                       If(source.ack,
+                               request_timeout.reset.eq(1),
+                               request_pending.ce.eq(1),
+                               request.ack.eq(1),
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("PRESENT_RESPONSE",
+                       response.stb.eq(1),
+                       response.failed.eq(0), # XXX add timeout to trigger failed
+                       response.mac_address.eq(cached_mac_address),
+                       If(response.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthARP(Module):
+       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()
+               self.comb += [
+                       Record.connect(self.rx.source, self.table.sink),
+                       Record.connect(self.table.source, self.tx.sink)
+               ]
+               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)
+               ]
diff --git a/liteeth/core/ip.py b/liteeth/core/ip.py
new file mode 100644 (file)
index 0000000..e495972
--- /dev/null
@@ -0,0 +1,183 @@
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+class LiteEthIPV4Depacketizer(LiteEthDepacketizer):
+       def __init__(self):
+               LiteEthDepacketizer.__init__(self,
+                       eth_mac_description(8),
+                       eth_ipv4_description(8),
+                       ipv4_header,
+                       ipv4_header_len)
+
+class LiteEthIPV4Packetizer(LiteEthPacketizer):
+       def __init__(self):
+               LiteEthPacketizer.__init__(self,
+                       eth_ipv4_description(8),
+                       eth_mac_description(8),
+                       ipv4_header,
+                       ipv4_header_len)
+
+class LiteEthIPV4Checksum(Module):
+       def __init__(self, skip_header=False):
+               self.header = Signal(ipv4_header_len*8)
+               self.value = Signal(16)
+
+               s = Signal(17)
+               r = Signal(17)
+               for i in range(ipv4_header_len//2):
+                       if skip_header and i == 5:
+                               pass
+                       else:
+                               s_next = Signal(17)
+                               r_next = Signal(17)
+                               self.comb += [
+                                       s_next.eq(r + self.header[i*16:(i+1)*16]),
+                                       r_next.eq(Cat(s_next[:16]+s_next[16], Signal()))
+                               ]
+                               s, r = s_next, r_next
+               self.comb += self.value.eq(~Cat(r[8:16], r[:8]))
+
+class LiteEthIPTX(Module):
+       def __init__(self, mac_address, ip_address, arp_table):
+               self.sink = Sink(eth_ipv4_user_description(8))
+               self.source = Source(eth_mac_description(8))
+               ###
+               packetizer = LiteEthIPV4Packetizer()
+               self.submodules += packetizer
+               self.comb += [
+                       packetizer.sink.stb.eq(self.sink.stb),
+                       packetizer.sink.sop.eq(self.sink.sop),
+                       packetizer.sink.eop.eq(self.sink.eop),
+                       self.sink.eq(packetizer.sink.ack),
+                       packetizer.sink.destination_ip_address.eq(ip_address),
+                       packetizer.sink.protocol.eq(self.sink.protocol),
+                       packetizer.sink.total_length.eq(self.sink.length + (0x5*4)),
+                       packetizer.sink.version.eq(0x4),        # ipv4
+                       packetizer.sink.ihl.eq(0x5),            # 20 bytes
+                       packetizer.sink.dscp.eq(0),
+                       packetizer.sink.ecn.eq(0),
+                       packetizer.sink.identification.eq(0),
+                       packetizer.sink.flags.eq(0),
+                       packetizer.sink.fragment_offset.eq(0),
+                       packetizer.sink.time_to_live.eq(0x80),
+                       packetizer.sink.source_ip_address.eq(ip_address)
+               ]
+               sink = packetizer.source
+
+               checksum = LiteEthIPV4Checksum(skip_header=True)
+               self.submodules += checksum
+               self.comb += [
+                       checksum.header.eq(packetizer.header),
+                       packetizer.sink.header_checksum.eq(checksum.value)
+               ]
+
+               destination_mac_address = Signal(48)
+
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("SEND_MAC_ADDRESS_REQUEST")
+                       )
+               )
+               fsm.act("SEND_MAC_ADDRESS_REQUEST",
+                       arp_table.request.stb.eq(1),
+                       arp_table.request.ip_address.eq(self.sink.ip_address),
+                       If(arp_table.request.stb & arp_table.request.ack,
+                               NextState("WAIT_MAC_ADDRESS_RESPONSE")
+                       )
+               )
+               fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
+                       # XXX add timeout
+                       If(arp_table.response.stb,
+                               arp_table.response.ack.eq(1),
+                               # XXX manage failed
+                               NextState("SEND")
+                       )
+               )
+               self.sync += If(arp_table.response.stb, destination_mac_address.eq(arp_table.response.mac_address))
+               fsm.act("SEND",
+                       Record.connect(packetizer.source, self.source),
+                       self.source.ethernet_type.eq(ethernet_type_ip),
+                       self.source.destination_mac_address.eq(destination_mac_address),
+                       self.source.source_mac_address.eq(mac_address),
+                       # XXX compute check sum
+                       If(self.source.stb & self.source.eop & self.source.ack,
+                               # XXX manage failed
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthIPRX(Module):
+       def __init__(self, mac_address, ip_address):
+               self.sink = Sink(eth_mac_description(8))
+               self.source = source = Source(eth_ipv4_user_description(8))
+               ###
+               depacketizer = LiteEthIPV4Depacketizer()
+               self.submodules += depacketizer
+               self.comb += Record.connect(self.sink, depacketizer.sink)
+               sink = depacketizer.source
+
+               checksum = LiteEthIPV4Checksum(skip_header=False)
+               self.submodules += checksum
+               self.comb += checksum.header.eq(depacketizer.header)
+
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       sink.ack.eq(1),
+                       If(sink.stb & sink.sop,
+                               sink.ack.eq(0),
+                               NextState("CHECK")
+                       )
+               )
+               valid = Signal()
+               self.comb += valid.eq(
+                       sink.stb &
+                       (sink.destination_ip_address == ip_address) &
+                       (sink.version == 0x4) &
+                       (sink.ihl == 0x5) &
+                       (checksum.value == 0)
+               )
+
+               fsm.act("CHECK",
+                       If(valid,
+                               NextState("PRESENT")
+                       ).Else(
+                               NextState("DROP")
+                       )
+               ),
+               fsm.act("PRESENT",
+                       source.stb.eq(sink.stb),
+                       source.sop.eq(sink.sop),
+                       source.eop.eq(sink.eop),
+                       sink.ack.eq(source.ack),
+                       source.length.eq(sink.total_length - (sink.ihl*4)),
+                       source.protocol.eq(sink.protocol),
+                       source.ip_address.eq(sink.destination_ip_address),
+                       source.data.eq(sink.data),
+                       source.error.eq(sink.error),
+                       If(source.stb & source.eop & source.ack,
+                               NextState("IDLE")
+                       )
+               )
+               fsm.act("DROP",
+                       sink.ack.eq(1),
+                       If(source.stb & source.eop & source.ack,
+                               NextState("IDLE")
+                       )
+               )
+
+class LiteEthIP(Module):
+       def __init__(self, mac, mac_address, ip_address, arp_table):
+               self.submodules.tx = LiteEthIPTX(mac_address, ip_address, arp_table)
+               self.submodules.rx = LiteEthIPRX(mac_address, ip_address)
+               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
diff --git a/liteeth/core/udp.py b/liteeth/core/udp.py
new file mode 100644 (file)
index 0000000..296abe6
--- /dev/null
@@ -0,0 +1,19 @@
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+class LiteEthUDPDepacketizer(LiteEthDepacketizer):
+       def __init__(self):
+               LiteEthDepacketizer.__init__(self,
+                       eth_ipv4_description(8),
+                       eth_udp_description(8),
+                       udp_header,
+                       udp_header_len)
+
+class LiteEthUDPPacketizer(LiteEthPacketizer):
+       def __init__(self):
+               LiteEthPacketizer.__init__(self,
+                       eth_udp_description(8),
+                       eth_ipv4_description(8),
+                       udp_header,
+                       udp_header_len)
diff --git a/liteeth/etherbone/__init__.py b/liteeth/etherbone/__init__.py
deleted file mode 100644 (file)
index f84348a..0000000
+++ /dev/null
@@ -1,581 +0,0 @@
-# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
-# License: BSD
-
-import struct
-from collections import namedtuple
-
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.record import Record
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.fifo import SyncFIFO
-from migen.genlib.misc import optree
-from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
-from migen.actorlib.sim import SimActor
-from migen.bus.transactions import TRead, TWrite
-from migen.flow.transactions import Token
-from migen.flow.actor import Source, Sink
-from migen.flow.network import DataFlowGraph, CompositeActor
-
-
-_eb_width = 32 # addr and data
-_eb_queue_len = 32
-_eb_magic = 0x4e6f
-_eb_ver = 1
-_eb_hdr = [
-               ("magic", 16),
-               ("ver", 4),
-               ("res1", 1),
-               ("no_response", 1),
-               ("probe_res", 1),
-               ("probe", 1),
-               ("addr_size", 4),
-               ("data_size", 4),
-       ][::-1] # big-endian
-
-_eb_rec_hdr = [
-               ("bca_cfg", 1),
-               ("rca_cfg", 1),
-               ("rd_fifo", 1),
-               ("res1", 1),
-               ("drop_cyc", 1),
-               ("wca_cfg", 1),
-               ("wr_fifo", 1),
-               ("res2", 1),
-               ("sel", 8),
-               ("wr_cnt", 8),
-               ("rd_cnt", 8),
-       ][::-1] # big-endian
-
-_eb_layout = [("data", _eb_width)]
-
-
-class Config(Module):
-       def __init__(self, sdb_addr):
-               self.errreg = Signal(8*8)
-               mach = Signal(4*8, reset=0xd15e)
-               macl = Signal(4*8, reset=0xa5edbeef)
-               self.mac = Signal(6*8)
-               self.comb += self.mac.eq(Cat(macl, mach))
-               self.ip = Signal(4*8, reset=0xc0a80064)
-               self.port = Signal(4*8, reset=0xebd0)
-
-               self.bus = bus = wishbone.Interface()
-               self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
-
-               read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
-                       sdb_addr, mach, macl, self.ip, self.port])
-               write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
-
-               self.dout = read_mux[self.fifo.dout]
-               self.comb += [
-                               bus.ack.eq(bus.cyc & bus.stb),
-                               bus.dat_r.eq(read_mux[bus.adr[:3]]),
-                               ]
-               self.sync += [
-                               If(bus.cyc & bus.stb & bus.we & optree("|",
-                                               [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
-                                       write_mux.eq(bus.dat_w),
-                               )]
-
-class WishboneMaster(Module):
-       def __init__(self, timeout):
-               self.bus = bus = wishbone.Interface()
-               self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
-
-               self.active = Signal()
-               inflight = Signal(max=_eb_queue_len)
-               queued = Signal(max=_eb_queue_len)
-               self.sync += [
-                               inflight.eq(inflight + self.active - self.fifo.we),
-                               queued.eq(queued + self.active - self.fifo.re),
-                               ]
-
-               self.busy = Signal()
-               self.full = Signal()
-               self.comb += [
-                               self.busy.eq(inflight != 0),
-                               self.full.eq(queued == _eb_queue_len - 1),
-                               ]
-
-               kill_ack = Signal()
-               time = Signal(max=timeout)
-               self.comb += kill_ack.eq(time == timeout - 1)
-               self.sync += [
-                               If(self.fifo.we | ~self.busy,
-                                       time.eq(0),
-                               ).Else(
-                                       time.eq(time + 1),
-                               )]
-
-               self.comb += [
-                               self.fifo.we.eq(bus.ack | bus.err | kill_ack),
-                               self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
-                               ]
-
-               self.errreg = Signal(64)
-               self.sync += [
-                               If(self.fifo.re,
-                                       self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
-                               )]
-
-class Transmit(Module):
-       def __init__(self, pas, cfg, wbm, tag, tags):
-               self.tx = Source(_eb_layout)
-
-               data = Signal(_eb_width)
-               re = Signal(4)
-               self.tx_cyc = Signal()
-               self.tx_skip = Signal()
-               last_tx_cyc = Signal()
-               last_tx_skip = Signal()
-               readable = Signal()
-
-               self.sync += [
-                               last_tx_cyc.eq(self.tx_cyc),
-                               last_tx_skip.eq(self.tx_skip),
-                               ]
-
-               self.comb += [
-                               readable.eq(Cat(tag.readable, pas.readable,
-                                       cfg.fifo.readable, wbm.readable) & re == re),
-                               self.tx.stb.eq(readable & (re[1:] != 0)),
-                               self.tx.payload.data.eq(data),
-                               Case(tag.dout, {
-                                       tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
-                                       tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
-                                       tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
-                                       tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
-                                       tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
-                                       tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
-                                       "default": [re.eq(0b0001)],
-                                       }),
-                               If(readable & (self.tx.ack | (re[1:] == 0)),
-                                       Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
-                               ),
-                               If(tag.readable,
-                                       If(tag.dout == tags["PASS_TX"],
-                                               self.tx_cyc.eq(1),
-                                               self.tx_skip.eq(0),
-                                       ).Elif(tag.dout == tags["SKIP_TX"],
-                                               self.tx_cyc.eq(0),
-                                               self.tx_skip.eq(1),
-                                       ).Elif(tag.dout == tags["DROP_TX"],
-                                               self.tx_cyc.eq(0),
-                                               self.tx_skip.eq(0),
-                                       ).Else(
-                                               self.tx_cyc.eq(last_tx_cyc),
-                                               self.tx_skip.eq(last_tx_skip),
-                                       ),
-                               ).Else(
-                                       self.tx_cyc.eq(last_tx_cyc),
-                                       self.tx_skip.eq(last_tx_skip),
-                               ),
-                               ]
-
-class Receive(Module):
-       def __init__(self, pas, cfg, wbm, tag, tags):
-               self.rx = Sink(_eb_layout)
-
-               rx_rec_hdr = Record(_eb_rec_hdr)
-               tx_rec_hdr = Record(_eb_rec_hdr)
-               rx_eb_hdr = Record(_eb_hdr)
-               tx_eb_hdr = Record(_eb_hdr)
-               self.comb += [
-                               rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
-                               tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
-                               tx_eb_hdr.ver.eq(_eb_ver),
-                               tx_eb_hdr.no_response.eq(1),
-                               tx_eb_hdr.addr_size.eq(4),
-                               tx_eb_hdr.data_size.eq(4),
-                               tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
-
-                               rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
-                               tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
-                               tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
-                               tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
-                               tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
-                               tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
-                               ]
-
-               do_rx = Signal()
-               self.rx_cyc = Signal()
-               self.comb += [
-                               wbm.bus.sel.eq(rx_rec_hdr.sel),
-                               do_rx.eq(tag.writable & # tag is always written/read
-                                       self.rx_cyc & self.rx.stb & # have data
-                                       (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
-                                       (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
-                               self.rx.ack.eq(do_rx),
-                               cfg.fifo.din.eq(wbm.bus.adr),
-                               # no eb-cfg write support yet
-                               #cfg.dat_w.eq(wbm.bus.dat_w),
-                               #cfg.we.eq(wbm.bus.we),
-                               cfg.errreg.eq(wbm.errreg),
-                               ]
-
-               cur_rx_rec_hdr = Record(_eb_rec_hdr)
-               cur_tx_rec_hdr = Record(_eb_rec_hdr)
-               do_rec = Signal()
-               do_adr = Signal()
-               do_write = Signal()
-               do_read = Signal()
-               wr_adr = Signal(flen(wbm.bus.adr))
-               old_rx_cyc = Signal()
-               self.sync += [
-                               wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
-                               wbm.bus.cyc.eq(wbm.bus.cyc & (
-                                       ~cur_rx_rec_hdr.drop_cyc |
-                                       (cur_rx_rec_hdr.wr_cnt > 0) |
-                                       (cur_rx_rec_hdr.rd_cnt > 0))),
-                               If(do_rec,
-                                       cur_rx_rec_hdr.eq(rx_rec_hdr),
-                                       cur_tx_rec_hdr.eq(tx_rec_hdr),
-                               ),
-                               If(do_adr,
-                                       wr_adr.eq(self.rx.payload.data[2:]),
-                               ),
-                               If(do_write,
-                                       If(cur_rx_rec_hdr.wca_cfg,
-                                               cfg.fifo.we.eq(1),
-                                       ).Else(
-                                               wbm.bus.cyc.eq(1),
-                                               wbm.bus.stb.eq(1),
-                                       ),
-                                       wbm.bus.we.eq(1),
-                                       wbm.bus.adr.eq(wr_adr),
-                                       wbm.bus.dat_w.eq(self.rx.payload.data),
-                                       If(~cur_rx_rec_hdr.wr_fifo,
-                                               wr_adr.eq(wr_adr + 1),
-                                       ),
-                                       cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
-                               ),
-                               If(do_read,
-                                       If(cur_rx_rec_hdr.rca_cfg,
-                                               cfg.fifo.we.eq(1),
-                                       ).Else(
-                                               wbm.bus.cyc.eq(1),
-                                               wbm.bus.stb.eq(1),
-                                       ),
-                                       wbm.bus.we.eq(0),
-                                       wbm.bus.adr.eq(self.rx.payload.data[2:]),
-                                       cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
-                               ),
-                               If(~self.rx_cyc,
-                                       wbm.bus.cyc.eq(0),
-                               ),
-                               old_rx_cyc.eq(self.rx_cyc),
-                               ]
-
-               fsm = self.submodules.fsm = FSM()
-               fsm.reset_state = "EB_HDR"
-               fsm.act("EB_HDR",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       If((rx_eb_hdr.magic != _eb_magic) |
-                                                       (rx_eb_hdr.ver !=_eb_ver),
-                                               tag.din.eq(tags["SKIP_TX"]),
-                                               NextState("DROP"),
-                                       ).Else(
-                                               If(rx_eb_hdr.no_response,
-                                                       tag.din.eq(tags["SKIP_TX"]),
-                                               ).Else(
-                                                       tag.din.eq(tags["PASS_TX"]),
-                                                       pas.we.eq(1),
-                                                       pas.din.eq(tx_eb_hdr.raw_bits()),
-                                               ),
-                                               If(rx_eb_hdr.probe,
-                                                       If(rx_eb_hdr.addr_size[2] &
-                                                                       rx_eb_hdr.data_size[2],
-                                                               NextState("PROBE_ID"),
-                                                       ).Else(
-                                                               NextState("PROBE_DROP"),
-                                                       ),
-                                               ).Else(
-                                                       If((rx_eb_hdr.addr_size == 4) &
-                                                                       (rx_eb_hdr.data_size == 4),
-                                                               NextState("CYC_HDR"),
-                                                       ).Else(
-                                                               NextState("DROP"),
-                                                       ),
-                                               ),
-                                       ),
-                               ))
-               fsm.act("PROBE_DROP",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       pas.din.eq(self.rx.payload.data),
-                                       NextState("DROP"),
-                               ))
-               fsm.act("PROBE_ID",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       pas.din.eq(self.rx.payload.data),
-                                       NextState("CYC_HDR"),
-                               ))
-               fsm.act("CYC_HDR",
-                               If(do_rx,
-                                       do_rec.eq(1),
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       If(rx_rec_hdr.wr_cnt != 0,
-                                               NextState("WR_ADR"),
-                                       ).Else(
-                                               pas.din.eq(tx_rec_hdr.raw_bits()),
-                                               If(rx_rec_hdr.rd_cnt != 0,
-                                                       NextState("RD_ADR"),
-                                               ).Else(
-                                                       NextState("CYC_HDR"),
-                                               ),
-                                       ),
-                               ))
-               fsm.act("WR_ADR",
-                               If(do_rx,
-                                       do_adr.eq(1),
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       NextState("WRITE"),
-                               ))
-               fsm.act("WRITE",
-                               If(do_rx,
-                                       do_write.eq(1),
-                                       tag.we.eq(1),
-                                       If(cur_rx_rec_hdr.wca_cfg,
-                                               tag.din.eq(tags["CFG_IGN"]),
-                                       ).Else(
-                                               wbm.active.eq(1),
-                                               tag.din.eq(tags["WBM_IGN"]),
-                                       ),
-                                       pas.we.eq(1),
-                                       If(cur_rx_rec_hdr.wr_cnt == 1,
-                                               pas.din.eq(cur_tx_rec_hdr.raw_bits()),
-                                               If(cur_rx_rec_hdr.rd_cnt != 0,
-                                                       NextState("RD_ADR"),
-                                               ).Else(
-                                                       NextState("CYC_HDR"),
-                                               ),
-                                       ),
-                               ))
-               fsm.act("RD_ADR",
-                               If(do_rx,
-                                       tag.we.eq(1),
-                                       tag.din.eq(tags["PASS_ON"]),
-                                       pas.we.eq(1),
-                                       pas.din.eq(self.rx.payload.data),
-                                       NextState("READ"),
-                               ))
-               fsm.act("READ",
-                               If(do_rx,
-                                       do_read.eq(1),
-                                       tag.we.eq(1),
-                                       If(cur_rx_rec_hdr.rca_cfg,
-                                               tag.din.eq(tags["CFG_REQ"]),
-                                       ).Else(
-                                               wbm.active.eq(1),
-                                               tag.din.eq(tags["WBM_REQ"]),
-                                       ),
-                                       If(cur_rx_rec_hdr.rd_cnt == 1,
-                                               NextState("CYC_HDR"),
-                                       ),
-                               ))
-               fsm.act("DROP",
-                               #If(do_rx,
-                               #       tag.we.eq(1),
-                               #       tag.din.eq(tags["PASS_ON"]),
-                               #       pas.we.eq(1),
-                               #)
-                               )
-               for state in fsm.actions:
-                       fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
-               self.comb += [
-                               If(~self.rx_cyc,
-                                       Cat(do_rec, do_adr, do_write, do_read).eq(0),
-                                       Cat(wbm.active, pas.we).eq(0),
-                                       If(old_rx_cyc,
-                                               tag.we.eq(1),
-                                               tag.din.eq(tags["DROP_TX"]),
-                                       ),
-                               )]
-
-class Slave(Module):
-       def __init__(self, sdb_addr, timeout):
-               tags = dict((k, i) for i, k in enumerate(
-                       "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
-                       "CFG_IGN WBM_REQ WBM_IGN".split()))
-               tag_width = flen(Signal(max=len(tags)))
-
-               self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
-               self.submodules.cfg = Config(sdb_addr)
-               self.submodules.wbm = WishboneMaster(timeout)
-               self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
-
-               self.submodules.rxfsm = Receive(self.pas, self.cfg,
-                               self.wbm, self.tag, tags)
-               self.rx = self.rxfsm.rx
-               self.rx_cyc = self.rxfsm.rx_cyc
-               self.submodules.txmux = Transmit(self.pas, self.cfg,
-                               self.wbm.fifo, self.tag, tags)
-               self.tx = self.txmux.tx
-               self.tx_skip = self.txmux.tx_skip
-               self.tx_cyc = self.txmux.tx_cyc
-               self.busy = self.wbm.busy
-
-class Converter(Module):
-       def __init__(self, raw_width, graph, **slave_kwargs):
-               raw_layout = [("data", raw_width)]
-               pack_factor = _eb_width//raw_width
-
-               self.rx = Sink(raw_layout)
-               rx_pack = Pack(raw_layout, pack_factor)
-               rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
-               self.submodules.slave = Slave(**slave_kwargs)
-               tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
-               tx_unpack = Unpack(pack_factor, raw_layout)
-               self.tx = Source(raw_layout)
-
-               graph.add_connection(self.rx, rx_pack)
-               graph.add_connection(rx_pack, rx_cast)
-               graph.add_connection(rx_cast, self.slave.rx)
-               graph.add_connection(self.slave.tx, tx_cast)
-               graph.add_connection(tx_cast, tx_unpack)
-               graph.add_connection(tx_unpack, self.tx)
-
-class SimTx(SimActor):
-       def __init__(self, data):
-               self.tx = Source(_eb_layout)
-               SimActor.__init__(self, self.gen(data))
-
-       def gen(self, data):
-               for i in data:
-                       yield Token("tx", {"data": i})
-                       print("eb tx", hex(i))
-
-class SimRx(SimActor):
-       def __init__(self):
-               self.rx = Sink(_eb_layout)
-               self.recv = []
-               SimActor.__init__(self, self.gen())
-
-       def gen(self):
-               while True:
-                       t = Token("rx")
-                       yield t
-                       print("eb rx", hex(t.value["data"]))
-                       self.recv.append(t.value["data"])
-
-class TB(Module):
-       def __init__(self, data):
-               ebm_tx = SimTx(data)
-               ebm_rx = SimRx()
-               self.slave = Slave(0x200, 10)
-               g = DataFlowGraph()
-               g.add_connection(ebm_tx, self.slave)
-               g.add_connection(self.slave, ebm_rx)
-               self.submodules.graph = CompositeActor(g)
-               self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
-               self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
-                               lambda l: print("cfg", l))
-               self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
-                               lambda l: print("wbm", l))
-               self.submodules.xbar = wishbone.Crossbar(
-                               [self.cfg_master.bus, self.slave.wbm.bus],
-                               [
-                                       (lambda a: a[6:] == 0x0, wishbone.Target(
-                                               wishbone.TargetModel()).bus),
-                                       (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
-                               ])
-
-       def gen_cfg_reads(self):
-               for a in range(0x40, 0x40+4):
-                       t = TRead(a)
-                       yield t
-
-       def do_simulation(self, s):
-               #s.interrupt = self.cfg_master.done
-               s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
-
-class MyStruct(object):
-       _data = None
-       _fmt = "!"
-
-       def __init__(self, **kwargs):
-               self.data = self._data(**kwargs)
-
-       def __bytes__(self):
-               return struct.pack(self._fmt, *self.data)
-
-class EbHeader(MyStruct):
-       _data = namedtuple("eb_hdr", "magic ver size")
-       _fmt = "!HBB"
-
-       def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
-               no_response = not any(r.read for r in records)
-               probe = probe_id is not None
-               probe_res = False
-               MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
-                               (no_response<<2) | (probe_res<<1) | (probe<<0),
-                               size=(addr_size<<4) | (data_size<<0))
-               self.probe = struct.pack("!I", probe_id) if probe else b""
-               self.records = records
-
-       def __bytes__(self):
-               return (MyStruct.__bytes__(self) + self.probe +
-                               b"".join(map(bytes, self.records)))
-
-class EbRecord(MyStruct):
-       _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
-       _fmt = "!BBBB"
-
-       def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
-                       bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
-                       wca_cfg=False, wr_fifo=False):
-               MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
-                               rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
-                                       (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
-                                       (wr_fifo>>1))
-               self.wr_adr = wr_adr
-               self.write = write
-               self.rd_adr = rd_adr
-               self.read = read
-
-       def __bytes__(self):
-               b = MyStruct.__bytes__(self)
-               if self.write:
-                       b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
-                                       *self.write)
-               if self.read:
-                       b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
-                                       *self.read)
-               return b
-
-def main():
-       from migen.sim.generic import Simulator, TopLevel
-
-       #from migen.fhdl import verilog
-       #s = Slave(0, 10)
-       #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
-       #       s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
-
-       eb_pkt = EbHeader(records=[
-                               EbRecord(wr_adr=0x10, write=[0x20, 0x21],
-                                       rd_adr=0x30, read=range(0, 8, 4)),
-                               EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
-                                       drop_cyc=True),
-                               EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
-                                       read=range(0, 0+8, 4), drop_cyc=True),
-                               ])
-       eb_pkt = bytes(eb_pkt)
-       eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
-       tb = TB(eb_pkt)
-       sim = Simulator(tb, TopLevel("etherbone.vcd"))
-       sim.run(500)
-
-
-if __name__ == "__main__":
-       main()
\ No newline at end of file
diff --git a/liteeth/frontend/__init__.py b/liteeth/frontend/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/liteeth/frontend/etherbone.py b/liteeth/frontend/etherbone.py
new file mode 100644 (file)
index 0000000..f84348a
--- /dev/null
@@ -0,0 +1,581 @@
+# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
+# License: BSD
+
+import struct
+from collections import namedtuple
+
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.record import Record
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.fifo import SyncFIFO
+from migen.genlib.misc import optree
+from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
+from migen.actorlib.sim import SimActor
+from migen.bus.transactions import TRead, TWrite
+from migen.flow.transactions import Token
+from migen.flow.actor import Source, Sink
+from migen.flow.network import DataFlowGraph, CompositeActor
+
+
+_eb_width = 32 # addr and data
+_eb_queue_len = 32
+_eb_magic = 0x4e6f
+_eb_ver = 1
+_eb_hdr = [
+               ("magic", 16),
+               ("ver", 4),
+               ("res1", 1),
+               ("no_response", 1),
+               ("probe_res", 1),
+               ("probe", 1),
+               ("addr_size", 4),
+               ("data_size", 4),
+       ][::-1] # big-endian
+
+_eb_rec_hdr = [
+               ("bca_cfg", 1),
+               ("rca_cfg", 1),
+               ("rd_fifo", 1),
+               ("res1", 1),
+               ("drop_cyc", 1),
+               ("wca_cfg", 1),
+               ("wr_fifo", 1),
+               ("res2", 1),
+               ("sel", 8),
+               ("wr_cnt", 8),
+               ("rd_cnt", 8),
+       ][::-1] # big-endian
+
+_eb_layout = [("data", _eb_width)]
+
+
+class Config(Module):
+       def __init__(self, sdb_addr):
+               self.errreg = Signal(8*8)
+               mach = Signal(4*8, reset=0xd15e)
+               macl = Signal(4*8, reset=0xa5edbeef)
+               self.mac = Signal(6*8)
+               self.comb += self.mac.eq(Cat(macl, mach))
+               self.ip = Signal(4*8, reset=0xc0a80064)
+               self.port = Signal(4*8, reset=0xebd0)
+
+               self.bus = bus = wishbone.Interface()
+               self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
+
+               read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
+                       sdb_addr, mach, macl, self.ip, self.port])
+               write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
+
+               self.dout = read_mux[self.fifo.dout]
+               self.comb += [
+                               bus.ack.eq(bus.cyc & bus.stb),
+                               bus.dat_r.eq(read_mux[bus.adr[:3]]),
+                               ]
+               self.sync += [
+                               If(bus.cyc & bus.stb & bus.we & optree("|",
+                                               [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
+                                       write_mux.eq(bus.dat_w),
+                               )]
+
+class WishboneMaster(Module):
+       def __init__(self, timeout):
+               self.bus = bus = wishbone.Interface()
+               self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
+
+               self.active = Signal()
+               inflight = Signal(max=_eb_queue_len)
+               queued = Signal(max=_eb_queue_len)
+               self.sync += [
+                               inflight.eq(inflight + self.active - self.fifo.we),
+                               queued.eq(queued + self.active - self.fifo.re),
+                               ]
+
+               self.busy = Signal()
+               self.full = Signal()
+               self.comb += [
+                               self.busy.eq(inflight != 0),
+                               self.full.eq(queued == _eb_queue_len - 1),
+                               ]
+
+               kill_ack = Signal()
+               time = Signal(max=timeout)
+               self.comb += kill_ack.eq(time == timeout - 1)
+               self.sync += [
+                               If(self.fifo.we | ~self.busy,
+                                       time.eq(0),
+                               ).Else(
+                                       time.eq(time + 1),
+                               )]
+
+               self.comb += [
+                               self.fifo.we.eq(bus.ack | bus.err | kill_ack),
+                               self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
+                               ]
+
+               self.errreg = Signal(64)
+               self.sync += [
+                               If(self.fifo.re,
+                                       self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
+                               )]
+
+class Transmit(Module):
+       def __init__(self, pas, cfg, wbm, tag, tags):
+               self.tx = Source(_eb_layout)
+
+               data = Signal(_eb_width)
+               re = Signal(4)
+               self.tx_cyc = Signal()
+               self.tx_skip = Signal()
+               last_tx_cyc = Signal()
+               last_tx_skip = Signal()
+               readable = Signal()
+
+               self.sync += [
+                               last_tx_cyc.eq(self.tx_cyc),
+                               last_tx_skip.eq(self.tx_skip),
+                               ]
+
+               self.comb += [
+                               readable.eq(Cat(tag.readable, pas.readable,
+                                       cfg.fifo.readable, wbm.readable) & re == re),
+                               self.tx.stb.eq(readable & (re[1:] != 0)),
+                               self.tx.payload.data.eq(data),
+                               Case(tag.dout, {
+                                       tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
+                                       tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
+                                       tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
+                                       tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
+                                       tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
+                                       tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
+                                       "default": [re.eq(0b0001)],
+                                       }),
+                               If(readable & (self.tx.ack | (re[1:] == 0)),
+                                       Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
+                               ),
+                               If(tag.readable,
+                                       If(tag.dout == tags["PASS_TX"],
+                                               self.tx_cyc.eq(1),
+                                               self.tx_skip.eq(0),
+                                       ).Elif(tag.dout == tags["SKIP_TX"],
+                                               self.tx_cyc.eq(0),
+                                               self.tx_skip.eq(1),
+                                       ).Elif(tag.dout == tags["DROP_TX"],
+                                               self.tx_cyc.eq(0),
+                                               self.tx_skip.eq(0),
+                                       ).Else(
+                                               self.tx_cyc.eq(last_tx_cyc),
+                                               self.tx_skip.eq(last_tx_skip),
+                                       ),
+                               ).Else(
+                                       self.tx_cyc.eq(last_tx_cyc),
+                                       self.tx_skip.eq(last_tx_skip),
+                               ),
+                               ]
+
+class Receive(Module):
+       def __init__(self, pas, cfg, wbm, tag, tags):
+               self.rx = Sink(_eb_layout)
+
+               rx_rec_hdr = Record(_eb_rec_hdr)
+               tx_rec_hdr = Record(_eb_rec_hdr)
+               rx_eb_hdr = Record(_eb_hdr)
+               tx_eb_hdr = Record(_eb_hdr)
+               self.comb += [
+                               rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
+                               tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
+                               tx_eb_hdr.ver.eq(_eb_ver),
+                               tx_eb_hdr.no_response.eq(1),
+                               tx_eb_hdr.addr_size.eq(4),
+                               tx_eb_hdr.data_size.eq(4),
+                               tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
+
+                               rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
+                               tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
+                               tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
+                               tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
+                               tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
+                               tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
+                               ]
+
+               do_rx = Signal()
+               self.rx_cyc = Signal()
+               self.comb += [
+                               wbm.bus.sel.eq(rx_rec_hdr.sel),
+                               do_rx.eq(tag.writable & # tag is always written/read
+                                       self.rx_cyc & self.rx.stb & # have data
+                                       (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
+                                       (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
+                               self.rx.ack.eq(do_rx),
+                               cfg.fifo.din.eq(wbm.bus.adr),
+                               # no eb-cfg write support yet
+                               #cfg.dat_w.eq(wbm.bus.dat_w),
+                               #cfg.we.eq(wbm.bus.we),
+                               cfg.errreg.eq(wbm.errreg),
+                               ]
+
+               cur_rx_rec_hdr = Record(_eb_rec_hdr)
+               cur_tx_rec_hdr = Record(_eb_rec_hdr)
+               do_rec = Signal()
+               do_adr = Signal()
+               do_write = Signal()
+               do_read = Signal()
+               wr_adr = Signal(flen(wbm.bus.adr))
+               old_rx_cyc = Signal()
+               self.sync += [
+                               wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
+                               wbm.bus.cyc.eq(wbm.bus.cyc & (
+                                       ~cur_rx_rec_hdr.drop_cyc |
+                                       (cur_rx_rec_hdr.wr_cnt > 0) |
+                                       (cur_rx_rec_hdr.rd_cnt > 0))),
+                               If(do_rec,
+                                       cur_rx_rec_hdr.eq(rx_rec_hdr),
+                                       cur_tx_rec_hdr.eq(tx_rec_hdr),
+                               ),
+                               If(do_adr,
+                                       wr_adr.eq(self.rx.payload.data[2:]),
+                               ),
+                               If(do_write,
+                                       If(cur_rx_rec_hdr.wca_cfg,
+                                               cfg.fifo.we.eq(1),
+                                       ).Else(
+                                               wbm.bus.cyc.eq(1),
+                                               wbm.bus.stb.eq(1),
+                                       ),
+                                       wbm.bus.we.eq(1),
+                                       wbm.bus.adr.eq(wr_adr),
+                                       wbm.bus.dat_w.eq(self.rx.payload.data),
+                                       If(~cur_rx_rec_hdr.wr_fifo,
+                                               wr_adr.eq(wr_adr + 1),
+                                       ),
+                                       cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
+                               ),
+                               If(do_read,
+                                       If(cur_rx_rec_hdr.rca_cfg,
+                                               cfg.fifo.we.eq(1),
+                                       ).Else(
+                                               wbm.bus.cyc.eq(1),
+                                               wbm.bus.stb.eq(1),
+                                       ),
+                                       wbm.bus.we.eq(0),
+                                       wbm.bus.adr.eq(self.rx.payload.data[2:]),
+                                       cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
+                               ),
+                               If(~self.rx_cyc,
+                                       wbm.bus.cyc.eq(0),
+                               ),
+                               old_rx_cyc.eq(self.rx_cyc),
+                               ]
+
+               fsm = self.submodules.fsm = FSM()
+               fsm.reset_state = "EB_HDR"
+               fsm.act("EB_HDR",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       If((rx_eb_hdr.magic != _eb_magic) |
+                                                       (rx_eb_hdr.ver !=_eb_ver),
+                                               tag.din.eq(tags["SKIP_TX"]),
+                                               NextState("DROP"),
+                                       ).Else(
+                                               If(rx_eb_hdr.no_response,
+                                                       tag.din.eq(tags["SKIP_TX"]),
+                                               ).Else(
+                                                       tag.din.eq(tags["PASS_TX"]),
+                                                       pas.we.eq(1),
+                                                       pas.din.eq(tx_eb_hdr.raw_bits()),
+                                               ),
+                                               If(rx_eb_hdr.probe,
+                                                       If(rx_eb_hdr.addr_size[2] &
+                                                                       rx_eb_hdr.data_size[2],
+                                                               NextState("PROBE_ID"),
+                                                       ).Else(
+                                                               NextState("PROBE_DROP"),
+                                                       ),
+                                               ).Else(
+                                                       If((rx_eb_hdr.addr_size == 4) &
+                                                                       (rx_eb_hdr.data_size == 4),
+                                                               NextState("CYC_HDR"),
+                                                       ).Else(
+                                                               NextState("DROP"),
+                                                       ),
+                                               ),
+                                       ),
+                               ))
+               fsm.act("PROBE_DROP",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       pas.din.eq(self.rx.payload.data),
+                                       NextState("DROP"),
+                               ))
+               fsm.act("PROBE_ID",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       pas.din.eq(self.rx.payload.data),
+                                       NextState("CYC_HDR"),
+                               ))
+               fsm.act("CYC_HDR",
+                               If(do_rx,
+                                       do_rec.eq(1),
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       If(rx_rec_hdr.wr_cnt != 0,
+                                               NextState("WR_ADR"),
+                                       ).Else(
+                                               pas.din.eq(tx_rec_hdr.raw_bits()),
+                                               If(rx_rec_hdr.rd_cnt != 0,
+                                                       NextState("RD_ADR"),
+                                               ).Else(
+                                                       NextState("CYC_HDR"),
+                                               ),
+                                       ),
+                               ))
+               fsm.act("WR_ADR",
+                               If(do_rx,
+                                       do_adr.eq(1),
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       NextState("WRITE"),
+                               ))
+               fsm.act("WRITE",
+                               If(do_rx,
+                                       do_write.eq(1),
+                                       tag.we.eq(1),
+                                       If(cur_rx_rec_hdr.wca_cfg,
+                                               tag.din.eq(tags["CFG_IGN"]),
+                                       ).Else(
+                                               wbm.active.eq(1),
+                                               tag.din.eq(tags["WBM_IGN"]),
+                                       ),
+                                       pas.we.eq(1),
+                                       If(cur_rx_rec_hdr.wr_cnt == 1,
+                                               pas.din.eq(cur_tx_rec_hdr.raw_bits()),
+                                               If(cur_rx_rec_hdr.rd_cnt != 0,
+                                                       NextState("RD_ADR"),
+                                               ).Else(
+                                                       NextState("CYC_HDR"),
+                                               ),
+                                       ),
+                               ))
+               fsm.act("RD_ADR",
+                               If(do_rx,
+                                       tag.we.eq(1),
+                                       tag.din.eq(tags["PASS_ON"]),
+                                       pas.we.eq(1),
+                                       pas.din.eq(self.rx.payload.data),
+                                       NextState("READ"),
+                               ))
+               fsm.act("READ",
+                               If(do_rx,
+                                       do_read.eq(1),
+                                       tag.we.eq(1),
+                                       If(cur_rx_rec_hdr.rca_cfg,
+                                               tag.din.eq(tags["CFG_REQ"]),
+                                       ).Else(
+                                               wbm.active.eq(1),
+                                               tag.din.eq(tags["WBM_REQ"]),
+                                       ),
+                                       If(cur_rx_rec_hdr.rd_cnt == 1,
+                                               NextState("CYC_HDR"),
+                                       ),
+                               ))
+               fsm.act("DROP",
+                               #If(do_rx,
+                               #       tag.we.eq(1),
+                               #       tag.din.eq(tags["PASS_ON"]),
+                               #       pas.we.eq(1),
+                               #)
+                               )
+               for state in fsm.actions:
+                       fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
+               self.comb += [
+                               If(~self.rx_cyc,
+                                       Cat(do_rec, do_adr, do_write, do_read).eq(0),
+                                       Cat(wbm.active, pas.we).eq(0),
+                                       If(old_rx_cyc,
+                                               tag.we.eq(1),
+                                               tag.din.eq(tags["DROP_TX"]),
+                                       ),
+                               )]
+
+class Slave(Module):
+       def __init__(self, sdb_addr, timeout):
+               tags = dict((k, i) for i, k in enumerate(
+                       "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
+                       "CFG_IGN WBM_REQ WBM_IGN".split()))
+               tag_width = flen(Signal(max=len(tags)))
+
+               self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
+               self.submodules.cfg = Config(sdb_addr)
+               self.submodules.wbm = WishboneMaster(timeout)
+               self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
+
+               self.submodules.rxfsm = Receive(self.pas, self.cfg,
+                               self.wbm, self.tag, tags)
+               self.rx = self.rxfsm.rx
+               self.rx_cyc = self.rxfsm.rx_cyc
+               self.submodules.txmux = Transmit(self.pas, self.cfg,
+                               self.wbm.fifo, self.tag, tags)
+               self.tx = self.txmux.tx
+               self.tx_skip = self.txmux.tx_skip
+               self.tx_cyc = self.txmux.tx_cyc
+               self.busy = self.wbm.busy
+
+class Converter(Module):
+       def __init__(self, raw_width, graph, **slave_kwargs):
+               raw_layout = [("data", raw_width)]
+               pack_factor = _eb_width//raw_width
+
+               self.rx = Sink(raw_layout)
+               rx_pack = Pack(raw_layout, pack_factor)
+               rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
+               self.submodules.slave = Slave(**slave_kwargs)
+               tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
+               tx_unpack = Unpack(pack_factor, raw_layout)
+               self.tx = Source(raw_layout)
+
+               graph.add_connection(self.rx, rx_pack)
+               graph.add_connection(rx_pack, rx_cast)
+               graph.add_connection(rx_cast, self.slave.rx)
+               graph.add_connection(self.slave.tx, tx_cast)
+               graph.add_connection(tx_cast, tx_unpack)
+               graph.add_connection(tx_unpack, self.tx)
+
+class SimTx(SimActor):
+       def __init__(self, data):
+               self.tx = Source(_eb_layout)
+               SimActor.__init__(self, self.gen(data))
+
+       def gen(self, data):
+               for i in data:
+                       yield Token("tx", {"data": i})
+                       print("eb tx", hex(i))
+
+class SimRx(SimActor):
+       def __init__(self):
+               self.rx = Sink(_eb_layout)
+               self.recv = []
+               SimActor.__init__(self, self.gen())
+
+       def gen(self):
+               while True:
+                       t = Token("rx")
+                       yield t
+                       print("eb rx", hex(t.value["data"]))
+                       self.recv.append(t.value["data"])
+
+class TB(Module):
+       def __init__(self, data):
+               ebm_tx = SimTx(data)
+               ebm_rx = SimRx()
+               self.slave = Slave(0x200, 10)
+               g = DataFlowGraph()
+               g.add_connection(ebm_tx, self.slave)
+               g.add_connection(self.slave, ebm_rx)
+               self.submodules.graph = CompositeActor(g)
+               self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
+               self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
+                               lambda l: print("cfg", l))
+               self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
+                               lambda l: print("wbm", l))
+               self.submodules.xbar = wishbone.Crossbar(
+                               [self.cfg_master.bus, self.slave.wbm.bus],
+                               [
+                                       (lambda a: a[6:] == 0x0, wishbone.Target(
+                                               wishbone.TargetModel()).bus),
+                                       (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
+                               ])
+
+       def gen_cfg_reads(self):
+               for a in range(0x40, 0x40+4):
+                       t = TRead(a)
+                       yield t
+
+       def do_simulation(self, s):
+               #s.interrupt = self.cfg_master.done
+               s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
+
+class MyStruct(object):
+       _data = None
+       _fmt = "!"
+
+       def __init__(self, **kwargs):
+               self.data = self._data(**kwargs)
+
+       def __bytes__(self):
+               return struct.pack(self._fmt, *self.data)
+
+class EbHeader(MyStruct):
+       _data = namedtuple("eb_hdr", "magic ver size")
+       _fmt = "!HBB"
+
+       def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
+               no_response = not any(r.read for r in records)
+               probe = probe_id is not None
+               probe_res = False
+               MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
+                               (no_response<<2) | (probe_res<<1) | (probe<<0),
+                               size=(addr_size<<4) | (data_size<<0))
+               self.probe = struct.pack("!I", probe_id) if probe else b""
+               self.records = records
+
+       def __bytes__(self):
+               return (MyStruct.__bytes__(self) + self.probe +
+                               b"".join(map(bytes, self.records)))
+
+class EbRecord(MyStruct):
+       _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
+       _fmt = "!BBBB"
+
+       def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
+                       bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
+                       wca_cfg=False, wr_fifo=False):
+               MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
+                               rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
+                                       (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
+                                       (wr_fifo>>1))
+               self.wr_adr = wr_adr
+               self.write = write
+               self.rd_adr = rd_adr
+               self.read = read
+
+       def __bytes__(self):
+               b = MyStruct.__bytes__(self)
+               if self.write:
+                       b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
+                                       *self.write)
+               if self.read:
+                       b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
+                                       *self.read)
+               return b
+
+def main():
+       from migen.sim.generic import Simulator, TopLevel
+
+       #from migen.fhdl import verilog
+       #s = Slave(0, 10)
+       #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
+       #       s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
+
+       eb_pkt = EbHeader(records=[
+                               EbRecord(wr_adr=0x10, write=[0x20, 0x21],
+                                       rd_adr=0x30, read=range(0, 8, 4)),
+                               EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
+                                       drop_cyc=True),
+                               EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
+                                       read=range(0, 0+8, 4), drop_cyc=True),
+                               ])
+       eb_pkt = bytes(eb_pkt)
+       eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
+       tb = TB(eb_pkt)
+       sim = Simulator(tb, TopLevel("etherbone.vcd"))
+       sim.run(500)
+
+
+if __name__ == "__main__":
+       main()
\ No newline at end of file
diff --git a/liteeth/ip/__init__.py b/liteeth/ip/__init__.py
deleted file mode 100644 (file)
index e495972..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-from liteeth.common import *
-from liteeth.generic.depacketizer import LiteEthDepacketizer
-from liteeth.generic.packetizer import LiteEthPacketizer
-
-class LiteEthIPV4Depacketizer(LiteEthDepacketizer):
-       def __init__(self):
-               LiteEthDepacketizer.__init__(self,
-                       eth_mac_description(8),
-                       eth_ipv4_description(8),
-                       ipv4_header,
-                       ipv4_header_len)
-
-class LiteEthIPV4Packetizer(LiteEthPacketizer):
-       def __init__(self):
-               LiteEthPacketizer.__init__(self,
-                       eth_ipv4_description(8),
-                       eth_mac_description(8),
-                       ipv4_header,
-                       ipv4_header_len)
-
-class LiteEthIPV4Checksum(Module):
-       def __init__(self, skip_header=False):
-               self.header = Signal(ipv4_header_len*8)
-               self.value = Signal(16)
-
-               s = Signal(17)
-               r = Signal(17)
-               for i in range(ipv4_header_len//2):
-                       if skip_header and i == 5:
-                               pass
-                       else:
-                               s_next = Signal(17)
-                               r_next = Signal(17)
-                               self.comb += [
-                                       s_next.eq(r + self.header[i*16:(i+1)*16]),
-                                       r_next.eq(Cat(s_next[:16]+s_next[16], Signal()))
-                               ]
-                               s, r = s_next, r_next
-               self.comb += self.value.eq(~Cat(r[8:16], r[:8]))
-
-class LiteEthIPTX(Module):
-       def __init__(self, mac_address, ip_address, arp_table):
-               self.sink = Sink(eth_ipv4_user_description(8))
-               self.source = Source(eth_mac_description(8))
-               ###
-               packetizer = LiteEthIPV4Packetizer()
-               self.submodules += packetizer
-               self.comb += [
-                       packetizer.sink.stb.eq(self.sink.stb),
-                       packetizer.sink.sop.eq(self.sink.sop),
-                       packetizer.sink.eop.eq(self.sink.eop),
-                       self.sink.eq(packetizer.sink.ack),
-                       packetizer.sink.destination_ip_address.eq(ip_address),
-                       packetizer.sink.protocol.eq(self.sink.protocol),
-                       packetizer.sink.total_length.eq(self.sink.length + (0x5*4)),
-                       packetizer.sink.version.eq(0x4),        # ipv4
-                       packetizer.sink.ihl.eq(0x5),            # 20 bytes
-                       packetizer.sink.dscp.eq(0),
-                       packetizer.sink.ecn.eq(0),
-                       packetizer.sink.identification.eq(0),
-                       packetizer.sink.flags.eq(0),
-                       packetizer.sink.fragment_offset.eq(0),
-                       packetizer.sink.time_to_live.eq(0x80),
-                       packetizer.sink.source_ip_address.eq(ip_address)
-               ]
-               sink = packetizer.source
-
-               checksum = LiteEthIPV4Checksum(skip_header=True)
-               self.submodules += checksum
-               self.comb += [
-                       checksum.header.eq(packetizer.header),
-                       packetizer.sink.header_checksum.eq(checksum.value)
-               ]
-
-               destination_mac_address = Signal(48)
-
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += fsm
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("SEND_MAC_ADDRESS_REQUEST")
-                       )
-               )
-               fsm.act("SEND_MAC_ADDRESS_REQUEST",
-                       arp_table.request.stb.eq(1),
-                       arp_table.request.ip_address.eq(self.sink.ip_address),
-                       If(arp_table.request.stb & arp_table.request.ack,
-                               NextState("WAIT_MAC_ADDRESS_RESPONSE")
-                       )
-               )
-               fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
-                       # XXX add timeout
-                       If(arp_table.response.stb,
-                               arp_table.response.ack.eq(1),
-                               # XXX manage failed
-                               NextState("SEND")
-                       )
-               )
-               self.sync += If(arp_table.response.stb, destination_mac_address.eq(arp_table.response.mac_address))
-               fsm.act("SEND",
-                       Record.connect(packetizer.source, self.source),
-                       self.source.ethernet_type.eq(ethernet_type_ip),
-                       self.source.destination_mac_address.eq(destination_mac_address),
-                       self.source.source_mac_address.eq(mac_address),
-                       # XXX compute check sum
-                       If(self.source.stb & self.source.eop & self.source.ack,
-                               # XXX manage failed
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthIPRX(Module):
-       def __init__(self, mac_address, ip_address):
-               self.sink = Sink(eth_mac_description(8))
-               self.source = source = Source(eth_ipv4_user_description(8))
-               ###
-               depacketizer = LiteEthIPV4Depacketizer()
-               self.submodules += depacketizer
-               self.comb += Record.connect(self.sink, depacketizer.sink)
-               sink = depacketizer.source
-
-               checksum = LiteEthIPV4Checksum(skip_header=False)
-               self.submodules += checksum
-               self.comb += checksum.header.eq(depacketizer.header)
-
-               fsm = FSM(reset_state="IDLE")
-               self.submodules += fsm
-               fsm.act("IDLE",
-                       sink.ack.eq(1),
-                       If(sink.stb & sink.sop,
-                               sink.ack.eq(0),
-                               NextState("CHECK")
-                       )
-               )
-               valid = Signal()
-               self.comb += valid.eq(
-                       sink.stb &
-                       (sink.destination_ip_address == ip_address) &
-                       (sink.version == 0x4) &
-                       (sink.ihl == 0x5) &
-                       (checksum.value == 0)
-               )
-
-               fsm.act("CHECK",
-                       If(valid,
-                               NextState("PRESENT")
-                       ).Else(
-                               NextState("DROP")
-                       )
-               ),
-               fsm.act("PRESENT",
-                       source.stb.eq(sink.stb),
-                       source.sop.eq(sink.sop),
-                       source.eop.eq(sink.eop),
-                       sink.ack.eq(source.ack),
-                       source.length.eq(sink.total_length - (sink.ihl*4)),
-                       source.protocol.eq(sink.protocol),
-                       source.ip_address.eq(sink.destination_ip_address),
-                       source.data.eq(sink.data),
-                       source.error.eq(sink.error),
-                       If(source.stb & source.eop & source.ack,
-                               NextState("IDLE")
-                       )
-               )
-               fsm.act("DROP",
-                       sink.ack.eq(1),
-                       If(source.stb & source.eop & source.ack,
-                               NextState("IDLE")
-                       )
-               )
-
-class LiteEthIP(Module):
-       def __init__(self, mac, mac_address, ip_address, arp_table):
-               self.submodules.tx = LiteEthIPTX(mac_address, ip_address, arp_table)
-               self.submodules.rx = LiteEthIPRX(mac_address, ip_address)
-               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 484230ec70a4016c09c903ef9e253b5bf511a587..1bfd7289bfe0e0d8cfc99c68af39f234fe38cfd4 100644 (file)
@@ -5,7 +5,7 @@ from migen.sim.generic import run_simulation
 
 from liteeth.common import *
 from liteeth.mac import LiteEthMAC
-from liteeth.arp import LiteEthARP
+from liteeth.core.arp import LiteEthARP
 
 from liteeth.test.common import *
 from liteeth.test.model import phy, mac, arp
@@ -15,7 +15,7 @@ mac_address = 0x12345678abcd
 
 class TB(Module):
        def __init__(self):
-               self.submodules.phy_model = phy.PHY(8, debug=True)
+               self.submodules.phy_model = phy.PHY(8, debug=False)
                self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
                self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
 
index 66927654ba450ca77103800054d5a852aa48b0e0..1815c243bced18f60dea678a639d6f1d773c7ad7 100644 (file)
@@ -4,7 +4,7 @@ from migen.bus.transactions import *
 from migen.sim.generic import run_simulation
 
 from liteeth.common import *
-from liteeth import LiteEthIPStack
+from liteeth.core import LiteEthIPCore
 
 from liteeth.test.common import *
 from liteeth.test.model import phy, mac, arp, ip
@@ -19,7 +19,7 @@ class TB(Module):
                self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
                self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True)
 
-               self.submodules.ip = LiteEthIPStack(self.phy_model, mac_address, ip_address)
+               self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address)
 
                # use sys_clk for each clock_domain
                self.clock_domains.cd_eth_rx = ClockDomain()
diff --git a/liteeth/udp/__init__.py b/liteeth/udp/__init__.py
deleted file mode 100644 (file)
index 296abe6..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-from liteeth.common import *
-from liteeth.generic.depacketizer import LiteEthDepacketizer
-from liteeth.generic.packetizer import LiteEthPacketizer
-
-class LiteEthUDPDepacketizer(LiteEthDepacketizer):
-       def __init__(self):
-               LiteEthDepacketizer.__init__(self,
-                       eth_ipv4_description(8),
-                       eth_udp_description(8),
-                       udp_header,
-                       udp_header_len)
-
-class LiteEthUDPPacketizer(LiteEthPacketizer):
-       def __init__(self):
-               LiteEthPacketizer.__init__(self,
-                       eth_udp_description(8),
-                       eth_ipv4_description(8),
-                       udp_header,
-                       udp_header_len)