From: Florent Kermarrec Date: Mon, 13 Apr 2015 07:53:43 +0000 (+0200) Subject: liteeth: pep8 (replace tabs with spaces) X-Git-Tag: 24jan2021_ls180~2373 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cd43eaffc2498dff6b19a106cde95cc799e9a05f;p=litex.git liteeth: pep8 (replace tabs with spaces) --- diff --git a/misoclib/com/liteeth/common.py b/misoclib/com/liteeth/common.py index 7a0b88bc..8643b3fc 100644 --- a/misoclib/com/liteeth/common.py +++ b/misoclib/com/liteeth/common.py @@ -19,19 +19,19 @@ eth_preamble = 0xD555555555555555 buffer_depth = 2**log2_int(eth_mtu, need_pow2=False) class HField(): - def __init__(self, byte, offset, width): - self.byte = byte - self.offset = offset - self.width = width + def __init__(self, byte, offset, width): + self.byte = byte + self.offset = offset + self.width = width ethernet_type_ip = 0x800 ethernet_type_arp = 0x806 mac_header_len = 14 mac_header = { - "target_mac": HField(0, 0, 48), - "sender_mac": HField(6, 0, 48), - "ethernet_type": HField(12, 0, 16) + "target_mac": HField(0, 0, 48), + "sender_mac": HField(6, 0, 48), + "ethernet_type": HField(12, 0, 16) } arp_hwtype_ethernet = 0x0001 @@ -41,45 +41,45 @@ arp_opcode_reply = 0x0002 arp_header_len = 28 arp_header = { - "hwtype": HField( 0, 0, 16), - "proto": HField( 2, 0, 16), - "hwsize": HField( 4, 0, 8), - "protosize": HField( 5, 0, 8), - "opcode": HField( 6, 0, 16), - "sender_mac": HField( 8, 0, 48), - "sender_ip": HField(14, 0, 32), - "target_mac": HField(18, 0, 48), - "target_ip": HField(24, 0, 32) + "hwtype": HField( 0, 0, 16), + "proto": HField( 2, 0, 16), + "hwsize": HField( 4, 0, 8), + "protosize": HField( 5, 0, 8), + "opcode": HField( 6, 0, 16), + "sender_mac": HField( 8, 0, 48), + "sender_ip": HField(14, 0, 32), + "target_mac": HField(18, 0, 48), + "target_ip": HField(24, 0, 32) } ipv4_header_len = 20 ipv4_header = { - "ihl": HField(0, 0, 4), - "version": HField(0, 4, 4), - "total_length": HField(2, 0, 16), - "identification": HField(4, 0, 16), - "ttl": HField(8, 0, 8), - "protocol": HField(9, 0, 8), - "checksum": HField(10, 0, 16), - "sender_ip": HField(12, 0, 32), - "target_ip": HField(16, 0, 32) + "ihl": HField(0, 0, 4), + "version": HField(0, 4, 4), + "total_length": HField(2, 0, 16), + "identification": HField(4, 0, 16), + "ttl": HField(8, 0, 8), + "protocol": HField(9, 0, 8), + "checksum": HField(10, 0, 16), + "sender_ip": HField(12, 0, 32), + "target_ip": HField(16, 0, 32) } icmp_header_len = 8 icmp_header = { - "msgtype": HField( 0, 0, 8), - "code": HField( 1, 0, 8), - "checksum": HField( 2, 0, 16), - "quench": HField( 4, 0, 32) + "msgtype": HField( 0, 0, 8), + "code": HField( 1, 0, 8), + "checksum": HField( 2, 0, 16), + "quench": HField( 4, 0, 32) } icmp_protocol = 0x01 udp_header_len = 8 udp_header = { - "src_port": HField( 0, 0, 16), - "dst_port": HField( 2, 0, 16), - "length": HField( 4, 0, 16), - "checksum": HField( 6, 0, 16) + "src_port": HField( 0, 0, 16), + "dst_port": HField( 2, 0, 16), + "length": HField( 4, 0, 16), + "checksum": HField( 6, 0, 16) } udp_protocol = 0x11 @@ -88,197 +88,197 @@ etherbone_magic = 0x4e6f etherbone_version = 1 etherbone_packet_header_len = 8 etherbone_packet_header = { - "magic": HField( 0, 0, 16), + "magic": HField( 0, 0, 16), - "version": HField( 2, 4, 4), - "nr": HField( 2, 2, 1), - "pr": HField( 2, 1, 1), - "pf": HField( 2, 0, 1), + "version": HField( 2, 4, 4), + "nr": HField( 2, 2, 1), + "pr": HField( 2, 1, 1), + "pf": HField( 2, 0, 1), - "addr_size": HField( 3, 4, 4), - "port_size": HField( 3, 0, 4) + "addr_size": HField( 3, 4, 4), + "port_size": HField( 3, 0, 4) } etherbone_record_header_len = 4 etherbone_record_header = { - "bca": HField( 0, 0, 1), - "rca": HField( 0, 1, 1), - "rff": HField( 0, 2, 1), - "cyc": HField( 0, 4, 1), - "wca": HField( 0, 5, 1), - "wff": HField( 0, 6, 1), + "bca": HField( 0, 0, 1), + "rca": HField( 0, 1, 1), + "rff": HField( 0, 2, 1), + "cyc": HField( 0, 4, 1), + "wca": HField( 0, 5, 1), + "wff": HField( 0, 6, 1), - "byte_enable": HField( 1, 0, 8), + "byte_enable": HField( 1, 0, 8), - "wcount": HField( 2, 0, 8), + "wcount": HField( 2, 0, 8), - "rcount": HField( 3, 0, 8) + "rcount": HField( 3, 0, 8) } def reverse_bytes(v): - n = math.ceil(flen(v)/8) - r = [] - for i in reversed(range(n)): - r.append(v[i*8:min((i+1)*8, flen(v))]) - return Cat(iter(r)) + n = math.ceil(flen(v)/8) + r = [] + for i in reversed(range(n)): + r.append(v[i*8:min((i+1)*8, flen(v))]) + return Cat(iter(r)) # layouts def _layout_from_header(header): - _layout = [] - for k, v in sorted(header.items()): - _layout.append((k, v.width)) - return _layout + _layout = [] + for k, v in sorted(header.items()): + _layout.append((k, v.width)) + return _layout def _remove_from_layout(layout, *args): - r = [] - for f in layout: - remove = False - for arg in args: - if f[0] == arg: - remove = True - if not remove: - r.append(f) - return r + r = [] + for f in layout: + remove = False + for arg in args: + if f[0] == arg: + remove = True + if not remove: + r.append(f) + return r def eth_phy_description(dw): - payload_layout = [ - ("data", dw), - ("last_be", dw//8), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, packetized=True) + payload_layout = [ + ("data", dw), + ("last_be", dw//8), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, packetized=True) def eth_mac_description(dw): - payload_layout = _layout_from_header(mac_header) + [ - ("data", dw), - ("last_be", dw//8), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, packetized=True) + payload_layout = _layout_from_header(mac_header) + [ + ("data", dw), + ("last_be", dw//8), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, packetized=True) def eth_arp_description(dw): - param_layout = _layout_from_header(arp_header) - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(arp_header) + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) arp_table_request_layout = [ - ("ip_address", 32) + ("ip_address", 32) ] arp_table_response_layout = [ - ("failed", 1), - ("mac_address", 48) + ("failed", 1), + ("mac_address", 48) ] def eth_ipv4_description(dw): - param_layout = _layout_from_header(ipv4_header) - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(ipv4_header) + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_ipv4_user_description(dw): - param_layout = [ - ("length", 16), - ("protocol", 8), - ("ip_address", 32) - ] - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = [ + ("length", 16), + ("protocol", 8), + ("ip_address", 32) + ] + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def convert_ip(s): - ip = 0 - for e in s.split("."): - ip = ip << 8 - ip += int(e) - return ip + ip = 0 + for e in s.split("."): + ip = ip << 8 + ip += int(e) + return ip def eth_icmp_description(dw): - param_layout = _layout_from_header(icmp_header) - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(icmp_header) + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_icmp_user_description(dw): - param_layout = _layout_from_header(icmp_header) + [ - ("ip_address", 32), - ("length", 16) - ] - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(icmp_header) + [ + ("ip_address", 32), + ("length", 16) + ] + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_udp_description(dw): - param_layout = _layout_from_header(udp_header) - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(udp_header) + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_udp_user_description(dw): - param_layout = [ - ("src_port", 16), - ("dst_port", 16), - ("ip_address", 32), - ("length", 16) - ] - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = [ + ("src_port", 16), + ("dst_port", 16), + ("ip_address", 32), + ("length", 16) + ] + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_etherbone_packet_description(dw): - param_layout = _layout_from_header(etherbone_packet_header) - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(etherbone_packet_header) + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_etherbone_packet_user_description(dw): - param_layout = _layout_from_header(etherbone_packet_header) - param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version") - param_layout += eth_udp_user_description(dw).param_layout - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(etherbone_packet_header) + param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version") + param_layout += eth_udp_user_description(dw).param_layout + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_etherbone_record_description(dw): - param_layout = _layout_from_header(etherbone_record_header) - payload_layout = [ - ("data", dw), - ("error", dw//8) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = _layout_from_header(etherbone_record_header) + payload_layout = [ + ("data", dw), + ("error", dw//8) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_etherbone_mmap_description(dw): - param_layout = [ - ("we", 1), - ("count", 8), - ("base_addr", 32), - ("be", dw//8) - ] - payload_layout = [ - ("addr", 32), - ("data", dw) - ] - return EndpointDescription(payload_layout, param_layout, packetized=True) + param_layout = [ + ("we", 1), + ("count", 8), + ("base_addr", 32), + ("be", dw//8) + ] + payload_layout = [ + ("addr", 32), + ("data", dw) + ] + return EndpointDescription(payload_layout, param_layout, packetized=True) def eth_tty_description(dw): - payload_layout = [("data", dw)] - return EndpointDescription(payload_layout, packetized=False) + payload_layout = [("data", dw)] + return EndpointDescription(payload_layout, packetized=False) diff --git a/misoclib/com/liteeth/core/__init__.py b/misoclib/com/liteeth/core/__init__.py index c2bfc8c4..7d14ec32 100644 --- a/misoclib/com/liteeth/core/__init__.py +++ b/misoclib/com/liteeth/core/__init__.py @@ -7,13 +7,13 @@ from misoclib.com.liteeth.core.udp import LiteEthUDP from misoclib.com.liteeth.core.icmp import LiteEthICMP class LiteEthIPCore(Module, AutoCSR): - def __init__(self, phy, mac_address, ip_address, clk_freq): - self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True) - self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq) - self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table) - self.submodules.icmp = LiteEthICMP(self.ip, ip_address) + def __init__(self, phy, mac_address, ip_address, clk_freq): + self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True) + self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq) + self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table) + self.submodules.icmp = LiteEthICMP(self.ip, ip_address) class LiteEthUDPIPCore(LiteEthIPCore): - def __init__(self, phy, mac_address, ip_address, clk_freq): - LiteEthIPCore.__init__(self, phy, mac_address, ip_address, clk_freq) - self.submodules.udp = LiteEthUDP(self.ip, ip_address) + def __init__(self, phy, mac_address, ip_address, clk_freq): + LiteEthIPCore.__init__(self, phy, mac_address, ip_address, clk_freq) + self.submodules.udp = LiteEthUDP(self.ip, ip_address) diff --git a/misoclib/com/liteeth/core/arp/__init__.py b/misoclib/com/liteeth/core/arp/__init__.py index a166665e..6efb2390 100644 --- a/misoclib/com/liteeth/core/arp/__init__.py +++ b/misoclib/com/liteeth/core/arp/__init__.py @@ -4,260 +4,260 @@ from misoclib.com.liteeth.generic.depacketizer import LiteEthDepacketizer from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer _arp_table_layout = [ - ("reply", 1), - ("request", 1), - ("ip_address", 32), - ("mac_address", 48) - ] + ("reply", 1), + ("request", 1), + ("ip_address", 32), + ("mac_address", 48) + ] class LiteEthARPPacketizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_arp_description(8), - eth_mac_description(8), - arp_header, - arp_header_len) + 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 = Source(eth_mac_description(8)) - ### - self.submodules.packetizer = packetizer = LiteEthARPPacketizer() + def __init__(self, mac_address, ip_address): + self.sink = sink = Sink(_arp_table_layout) + self.source = source = Source(eth_mac_description(8)) + ### + self.submodules.packetizer = packetizer = LiteEthARPPacketizer() - counter = Counter(max=max(arp_header_len, eth_min_len)) - self.submodules += counter + counter = Counter(max=max(arp_header_len, eth_min_len)) + self.submodules += counter - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - sink.ack.eq(1), - counter.reset.eq(1), - If(sink.stb, - sink.ack.eq(0), - NextState("SEND") - ) - ) - self.comb += [ - packetizer.sink.sop.eq(counter.value == 0), - packetizer.sink.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1), - packetizer.sink.hwtype.eq(arp_hwtype_ethernet), - packetizer.sink.proto.eq(arp_proto_ip), - packetizer.sink.hwsize.eq(6), - packetizer.sink.protosize.eq(4), - packetizer.sink.sender_mac.eq(mac_address), - packetizer.sink.sender_ip.eq(ip_address), - If(sink.reply, - packetizer.sink.opcode.eq(arp_opcode_reply), - packetizer.sink.target_mac.eq(sink.mac_address), - packetizer.sink.target_ip.eq(sink.ip_address) - ).Elif(sink.request, + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + sink.ack.eq(1), + counter.reset.eq(1), + If(sink.stb, + sink.ack.eq(0), + NextState("SEND") + ) + ) + self.comb += [ + packetizer.sink.sop.eq(counter.value == 0), + packetizer.sink.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1), + packetizer.sink.hwtype.eq(arp_hwtype_ethernet), + packetizer.sink.proto.eq(arp_proto_ip), + packetizer.sink.hwsize.eq(6), + packetizer.sink.protosize.eq(4), + packetizer.sink.sender_mac.eq(mac_address), + packetizer.sink.sender_ip.eq(ip_address), + If(sink.reply, + packetizer.sink.opcode.eq(arp_opcode_reply), + packetizer.sink.target_mac.eq(sink.mac_address), + packetizer.sink.target_ip.eq(sink.ip_address) + ).Elif(sink.request, - packetizer.sink.opcode.eq(arp_opcode_request), - packetizer.sink.target_mac.eq(0xffffffffffff), - packetizer.sink.target_ip.eq(sink.ip_address) - ) - ] - fsm.act("SEND", - packetizer.sink.stb.eq(1), - Record.connect(packetizer.source, source), - source.target_mac.eq(packetizer.sink.target_mac), - source.sender_mac.eq(mac_address), - source.ethernet_type.eq(ethernet_type_arp), - If(source.stb & source.ack, - counter.ce.eq(1), - If(source.eop, - sink.ack.eq(1), - NextState("IDLE") - ) - ) - ) + packetizer.sink.opcode.eq(arp_opcode_request), + packetizer.sink.target_mac.eq(0xffffffffffff), + packetizer.sink.target_ip.eq(sink.ip_address) + ) + ] + fsm.act("SEND", + packetizer.sink.stb.eq(1), + Record.connect(packetizer.source, source), + source.target_mac.eq(packetizer.sink.target_mac), + source.sender_mac.eq(mac_address), + source.ethernet_type.eq(ethernet_type_arp), + If(source.stb & source.ack, + counter.ce.eq(1), + If(source.eop, + sink.ack.eq(1), + NextState("IDLE") + ) + ) + ) class LiteEthARPDepacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_mac_description(8), - eth_arp_description(8), - arp_header, - arp_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_mac_description(8), + eth_arp_description(8), + arp_header, + arp_header_len) class LiteEthARPRX(Module): - def __init__(self, mac_address, ip_address): - self.sink = sink = Sink(eth_mac_description(8)) - self.source = source = Source(_arp_table_layout) - ### - self.submodules.depacketizer = depacketizer = LiteEthARPDepacketizer() - self.comb += Record.connect(sink, depacketizer.sink) + def __init__(self, mac_address, ip_address): + self.sink = sink = Sink(eth_mac_description(8)) + self.source = source = Source(_arp_table_layout) + ### + self.submodules.depacketizer = depacketizer = LiteEthARPDepacketizer() + self.comb += Record.connect(sink, depacketizer.sink) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") - ) - ) - valid = Signal() - self.sync += valid.eq( - depacketizer.source.stb & - (depacketizer.source.hwtype == arp_hwtype_ethernet) & - (depacketizer.source.proto == arp_proto_ip) & - (depacketizer.source.hwsize == 6) & - (depacketizer.source.protosize == 4) & - (depacketizer.source.target_ip == ip_address) - ) - reply = Signal() - request = Signal() - self.comb += Case(depacketizer.source.opcode, { - arp_opcode_request : [request.eq(1)], - arp_opcode_reply : [reply.eq(1)], - "default" : [] - }) - self.comb += [ - source.ip_address.eq(depacketizer.source.sender_ip), - source.mac_address.eq(depacketizer.source.sender_mac) - ] - fsm.act("CHECK", - If(valid, - source.stb.eq(1), - source.reply.eq(reply), - source.request.eq(request) - ), - NextState("TERMINATE") - ), - fsm.act("TERMINATE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.eop, - NextState("IDLE") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.sop, + depacketizer.source.ack.eq(0), + NextState("CHECK") + ) + ) + valid = Signal() + self.sync += valid.eq( + depacketizer.source.stb & + (depacketizer.source.hwtype == arp_hwtype_ethernet) & + (depacketizer.source.proto == arp_proto_ip) & + (depacketizer.source.hwsize == 6) & + (depacketizer.source.protosize == 4) & + (depacketizer.source.target_ip == ip_address) + ) + reply = Signal() + request = Signal() + self.comb += Case(depacketizer.source.opcode, { + arp_opcode_request : [request.eq(1)], + arp_opcode_reply : [reply.eq(1)], + "default" : [] + }) + self.comb += [ + source.ip_address.eq(depacketizer.source.sender_ip), + source.mac_address.eq(depacketizer.source.sender_mac) + ] + fsm.act("CHECK", + If(valid, + source.stb.eq(1), + source.reply.eq(reply), + source.request.eq(request) + ), + NextState("TERMINATE") + ), + fsm.act("TERMINATE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.eop, + NextState("IDLE") + ) + ) class LiteEthARPTable(Module): - def __init__(self, clk_freq, max_requests=8): - self.sink = sink = Sink(_arp_table_layout) # from arp_rx - self.source = source = Source(_arp_table_layout) # to arp_tx + def __init__(self, clk_freq, max_requests=8): + 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(clk_freq//10) - request_counter = Counter(max=max_requests) - request_pending = FlipFlop() - request_ip_address = FlipFlop(32) - self.submodules += request_timeout, request_counter, 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) - ] + # Request/Response interface + self.request = request = Sink(arp_table_request_layout) + self.response = response = Source(arp_table_response_layout) + ### + request_timeout = Timeout(clk_freq//10) + request_counter = Counter(max=max_requests) + request_pending = FlipFlop() + request_ip_address = FlipFlop(32) + self.submodules += request_timeout, request_counter, 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 1 IP/MAC couple, can be improved with a real - # table in the future to improve performance when packets are - # targeting multiple destinations. - update = Signal() - cached_valid = Signal() - cached_ip_address = Signal(32) - cached_mac_address = Signal(48) - cached_timeout = Timeout(clk_freq*10) - self.submodules += cached_timeout + # Note: Store only 1 IP/MAC couple, can be improved with a real + # table in the future to improve performance when packets are + # targeting multiple destinations. + update = Signal() + cached_valid = Signal() + cached_ip_address = Signal(32) + cached_mac_address = Signal(48) + cached_timeout = Timeout(clk_freq*10) + self.submodules += cached_timeout - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - # Note: for simplicicy, if APR table is busy response from arp_rx - # is lost. This is compensated by the protocol (retries) - If(sink.stb & sink.request, - NextState("SEND_REPLY") - ).Elif(sink.stb & sink.reply & request_pending.q, - NextState("UPDATE_TABLE"), - ).Elif(request_counter.value == max_requests-1, - NextState("PRESENT_RESPONSE") - ).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_valid.eq(1), - cached_ip_address.eq(sink.ip_address), - cached_mac_address.eq(sink.mac_address), - cached_timeout.reset.eq(1) - ).Else( - cached_timeout.ce.eq(1), - If(cached_timeout.reached, - cached_valid.eq(0) - ) - ) - ] - found = Signal() - fsm.act("CHECK_TABLE", - If(cached_valid, - 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(request.stb), - NextState("SEND_REQUEST") - ) - ).Else( - request_ip_address.ce.eq(request.stb), - NextState("SEND_REQUEST") - ) - ) - fsm.act("SEND_REQUEST", - source.stb.eq(1), - source.request.eq(1), - source.ip_address.eq(request_ip_address.q), - If(source.ack, - request_timeout.reset.eq(1), - request_counter.reset.eq(request.stb), - request_counter.ce.eq(1), - request_pending.ce.eq(1), - request.ack.eq(1), - NextState("IDLE") - ) - ) - self.comb += [ - If(request_counter == max_requests-1, - response.failed.eq(1), - request_counter.reset.eq(1), - request_pending.reset.eq(1) - ), - response.mac_address.eq(cached_mac_address) - ] - fsm.act("PRESENT_RESPONSE", - response.stb.eq(1), - If(response.ack, - NextState("IDLE") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + # Note: for simplicicy, if APR table is busy response from arp_rx + # is lost. This is compensated by the protocol (retries) + If(sink.stb & sink.request, + NextState("SEND_REPLY") + ).Elif(sink.stb & sink.reply & request_pending.q, + NextState("UPDATE_TABLE"), + ).Elif(request_counter.value == max_requests-1, + NextState("PRESENT_RESPONSE") + ).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_valid.eq(1), + cached_ip_address.eq(sink.ip_address), + cached_mac_address.eq(sink.mac_address), + cached_timeout.reset.eq(1) + ).Else( + cached_timeout.ce.eq(1), + If(cached_timeout.reached, + cached_valid.eq(0) + ) + ) + ] + found = Signal() + fsm.act("CHECK_TABLE", + If(cached_valid, + 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(request.stb), + NextState("SEND_REQUEST") + ) + ).Else( + request_ip_address.ce.eq(request.stb), + NextState("SEND_REQUEST") + ) + ) + fsm.act("SEND_REQUEST", + source.stb.eq(1), + source.request.eq(1), + source.ip_address.eq(request_ip_address.q), + If(source.ack, + request_timeout.reset.eq(1), + request_counter.reset.eq(request.stb), + request_counter.ce.eq(1), + request_pending.ce.eq(1), + request.ack.eq(1), + NextState("IDLE") + ) + ) + self.comb += [ + If(request_counter == max_requests-1, + response.failed.eq(1), + request_counter.reset.eq(1), + request_pending.reset.eq(1) + ), + response.mac_address.eq(cached_mac_address) + ] + fsm.act("PRESENT_RESPONSE", + response.stb.eq(1), + If(response.ack, + NextState("IDLE") + ) + ) class LiteEthARP(Module): - def __init__(self, mac, mac_address, ip_address, clk_freq): - self.submodules.tx = tx = LiteEthARPTX(mac_address, ip_address) - self.submodules.rx = rx = LiteEthARPRX(mac_address, ip_address) - self.submodules.table = table = LiteEthARPTable(clk_freq) - self.comb += [ - Record.connect(rx.source, table.sink), - Record.connect(table.source, tx.sink) - ] - mac_port = mac.crossbar.get_port(ethernet_type_arp) - self.comb += [ - Record.connect(tx.source, mac_port.sink), - Record.connect(mac_port.source, rx.sink) - ] + def __init__(self, mac, mac_address, ip_address, clk_freq): + self.submodules.tx = tx = LiteEthARPTX(mac_address, ip_address) + self.submodules.rx = rx = LiteEthARPRX(mac_address, ip_address) + self.submodules.table = table = LiteEthARPTable(clk_freq) + self.comb += [ + Record.connect(rx.source, table.sink), + Record.connect(table.source, tx.sink) + ] + mac_port = mac.crossbar.get_port(ethernet_type_arp) + self.comb += [ + Record.connect(tx.source, mac_port.sink), + Record.connect(mac_port.source, rx.sink) + ] diff --git a/misoclib/com/liteeth/core/etherbone/__init__.py b/misoclib/com/liteeth/core/etherbone/__init__.py index c68a8a6f..95285425 100644 --- a/misoclib/com/liteeth/core/etherbone/__init__.py +++ b/misoclib/com/liteeth/core/etherbone/__init__.py @@ -8,24 +8,24 @@ from misoclib.com.liteeth.core.etherbone.record import * from misoclib.com.liteeth.core.etherbone.wishbone import * class LiteEthEtherbone(Module): - def __init__(self, udp, udp_port): - # decode/encode etherbone packets - self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port) + def __init__(self, udp, udp_port): + # decode/encode etherbone packets + self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port) - # packets can be probe (etherbone discovering) or records with - # writes and reads - self.submodules.probe = probe = LiteEthEtherboneProbe() - self.submodules.record = record = LiteEthEtherboneRecord() + # packets can be probe (etherbone discovering) or records with + # writes and reads + self.submodules.probe = probe = LiteEthEtherboneProbe() + self.submodules.record = record = LiteEthEtherboneRecord() - # arbitrate/dispatch probe/records packets - dispatcher = Dispatcher(packet.source, [probe.sink, record.sink]) - self.comb += dispatcher.sel.eq(~packet.source.pf) - arbiter = Arbiter([probe.source, record.source], packet.sink) - self.submodules += dispatcher, arbiter + # arbitrate/dispatch probe/records packets + dispatcher = Dispatcher(packet.source, [probe.sink, record.sink]) + self.comb += dispatcher.sel.eq(~packet.source.pf) + arbiter = Arbiter([probe.source, record.source], packet.sink) + self.submodules += dispatcher, arbiter - # create mmap ŵishbone master - self.submodules.master = master = LiteEthEtherboneWishboneMaster() - self.comb += [ - Record.connect(record.receiver.source, master.sink), - Record.connect(master.source, record.sender.sink) - ] + # create mmap ŵishbone master + self.submodules.master = master = LiteEthEtherboneWishboneMaster() + self.comb += [ + Record.connect(record.receiver.source, master.sink), + Record.connect(master.source, record.sender.sink) + ] diff --git a/misoclib/com/liteeth/core/etherbone/packet.py b/misoclib/com/liteeth/core/etherbone/packet.py index a81a6a75..7db4b5ca 100644 --- a/misoclib/com/liteeth/core/etherbone/packet.py +++ b/misoclib/com/liteeth/core/etherbone/packet.py @@ -4,126 +4,126 @@ from misoclib.com.liteeth.generic.depacketizer import LiteEthDepacketizer from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer class LiteEthEtherbonePacketPacketizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_etherbone_packet_description(32), - eth_udp_user_description(32), - etherbone_packet_header, - etherbone_packet_header_len) + def __init__(self): + LiteEthPacketizer.__init__(self, + eth_etherbone_packet_description(32), + eth_udp_user_description(32), + etherbone_packet_header, + etherbone_packet_header_len) class LiteEthEtherbonePacketTX(Module): - def __init__(self, udp_port): - self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) - self.source = source = Source(eth_udp_user_description(32)) - ### - self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer() - self.comb += [ - packetizer.sink.stb.eq(sink.stb), - packetizer.sink.sop.eq(sink.sop), - packetizer.sink.eop.eq(sink.eop), - sink.ack.eq(packetizer.sink.ack), + def __init__(self, udp_port): + self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) + self.source = source = Source(eth_udp_user_description(32)) + ### + self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer() + self.comb += [ + packetizer.sink.stb.eq(sink.stb), + packetizer.sink.sop.eq(sink.sop), + packetizer.sink.eop.eq(sink.eop), + sink.ack.eq(packetizer.sink.ack), - packetizer.sink.magic.eq(etherbone_magic), - packetizer.sink.port_size.eq(32//8), - packetizer.sink.addr_size.eq(32//8), - packetizer.sink.pf.eq(sink.pf), - packetizer.sink.pr.eq(sink.pr), - packetizer.sink.nr.eq(sink.nr), - packetizer.sink.version.eq(etherbone_version), + packetizer.sink.magic.eq(etherbone_magic), + packetizer.sink.port_size.eq(32//8), + packetizer.sink.addr_size.eq(32//8), + packetizer.sink.pf.eq(sink.pf), + packetizer.sink.pr.eq(sink.pr), + packetizer.sink.nr.eq(sink.nr), + packetizer.sink.version.eq(etherbone_version), - packetizer.sink.data.eq(sink.data) - ] - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.sop, - packetizer.source.ack.eq(0), - NextState("SEND") - ) - ) - fsm.act("SEND", - Record.connect(packetizer.source, source), - source.src_port.eq(udp_port), - source.dst_port.eq(udp_port), - source.ip_address.eq(sink.ip_address), - source.length.eq(sink.length + etherbone_packet_header_len), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) + packetizer.sink.data.eq(sink.data) + ] + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + packetizer.source.ack.eq(1), + If(packetizer.source.stb & packetizer.source.sop, + packetizer.source.ack.eq(0), + NextState("SEND") + ) + ) + fsm.act("SEND", + Record.connect(packetizer.source, source), + source.src_port.eq(udp_port), + source.dst_port.eq(udp_port), + source.ip_address.eq(sink.ip_address), + source.length.eq(sink.length + etherbone_packet_header_len), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) class LiteEthEtherbonePacketDepacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_udp_user_description(32), - eth_etherbone_packet_description(32), - etherbone_packet_header, - etherbone_packet_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_udp_user_description(32), + eth_etherbone_packet_description(32), + etherbone_packet_header, + etherbone_packet_header_len) class LiteEthEtherbonePacketRX(Module): - def __init__(self): - self.sink = sink = Sink(eth_udp_user_description(32)) - self.source = source = Source(eth_etherbone_packet_user_description(32)) - ### - self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer() - self.comb += Record.connect(sink, depacketizer.sink) + def __init__(self): + self.sink = sink = Sink(eth_udp_user_description(32)) + self.source = source = Source(eth_etherbone_packet_user_description(32)) + ### + self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer() + self.comb += Record.connect(sink, depacketizer.sink) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") - ) - ) - valid = Signal() - self.sync += valid.eq( - depacketizer.source.stb & - (depacketizer.source.magic == etherbone_magic) - ) - fsm.act("CHECK", - If(valid, - NextState("PRESENT") - ).Else( - NextState("DROP") - ) - ) - self.comb += [ - source.sop.eq(depacketizer.source.sop), - source.eop.eq(depacketizer.source.eop), + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.sop, + depacketizer.source.ack.eq(0), + NextState("CHECK") + ) + ) + valid = Signal() + self.sync += valid.eq( + depacketizer.source.stb & + (depacketizer.source.magic == etherbone_magic) + ) + fsm.act("CHECK", + If(valid, + NextState("PRESENT") + ).Else( + NextState("DROP") + ) + ) + self.comb += [ + source.sop.eq(depacketizer.source.sop), + source.eop.eq(depacketizer.source.eop), - source.pf.eq(depacketizer.source.pf), - source.pr.eq(depacketizer.source.pr), - source.nr.eq(depacketizer.source.nr), + source.pf.eq(depacketizer.source.pf), + source.pr.eq(depacketizer.source.pr), + source.nr.eq(depacketizer.source.nr), - source.data.eq(depacketizer.source.data), + source.data.eq(depacketizer.source.data), - source.src_port.eq(sink.src_port), - source.dst_port.eq(sink.dst_port), - source.ip_address.eq(sink.ip_address), - source.length.eq(sink.length - etherbone_packet_header_len) - ] - fsm.act("PRESENT", - source.stb.eq(depacketizer.source.stb), - depacketizer.source.ack.eq(source.ack), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - fsm.act("DROP", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, - NextState("IDLE") - ) - ) + source.src_port.eq(sink.src_port), + source.dst_port.eq(sink.dst_port), + source.ip_address.eq(sink.ip_address), + source.length.eq(sink.length - etherbone_packet_header_len) + ] + fsm.act("PRESENT", + source.stb.eq(depacketizer.source.stb), + depacketizer.source.ack.eq(source.ack), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + fsm.act("DROP", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, + NextState("IDLE") + ) + ) class LiteEthEtherbonePacket(Module): - def __init__(self, udp, udp_port): - self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port) - self.submodules.rx = rx = LiteEthEtherbonePacketRX() - udp_port = udp.crossbar.get_port(udp_port, dw=32) - self.comb += [ - Record.connect(tx.source, udp_port.sink), - Record.connect(udp_port.source, rx.sink) - ] - self.sink, self.source = self.tx.sink, self.rx.source + def __init__(self, udp, udp_port): + self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port) + self.submodules.rx = rx = LiteEthEtherbonePacketRX() + udp_port = udp.crossbar.get_port(udp_port, dw=32) + self.comb += [ + Record.connect(tx.source, udp_port.sink), + Record.connect(udp_port.source, rx.sink) + ] + self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/com/liteeth/core/etherbone/probe.py b/misoclib/com/liteeth/core/etherbone/probe.py index 07fc2040..cdc7b7e2 100644 --- a/misoclib/com/liteeth/core/etherbone/probe.py +++ b/misoclib/com/liteeth/core/etherbone/probe.py @@ -2,23 +2,23 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthEtherboneProbe(Module): - def __init__(self): - self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) - self.source = source = Source(eth_etherbone_packet_user_description(32)) - ### - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - sink.ack.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - NextState("PROBE_RESPONSE") - ) - ) - fsm.act("PROBE_RESPONSE", - Record.connect(sink, source), - source.pf.eq(0), - source.pr.eq(1), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) + def __init__(self): + self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) + self.source = source = Source(eth_etherbone_packet_user_description(32)) + ### + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + sink.ack.eq(1), + If(sink.stb & sink.sop, + sink.ack.eq(0), + NextState("PROBE_RESPONSE") + ) + ) + fsm.act("PROBE_RESPONSE", + Record.connect(sink, source), + source.pf.eq(0), + source.pr.eq(1), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) diff --git a/misoclib/com/liteeth/core/etherbone/record.py b/misoclib/com/liteeth/core/etherbone/record.py index 29c01bf5..3e053a52 100644 --- a/misoclib/com/liteeth/core/etherbone/record.py +++ b/misoclib/com/liteeth/core/etherbone/record.py @@ -4,173 +4,173 @@ from misoclib.com.liteeth.generic.depacketizer import LiteEthDepacketizer from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer class LiteEthEtherboneRecordPacketizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_etherbone_record_description(32), - eth_etherbone_packet_user_description(32), - etherbone_record_header, - etherbone_record_header_len) + def __init__(self): + LiteEthPacketizer.__init__(self, + eth_etherbone_record_description(32), + eth_etherbone_packet_user_description(32), + etherbone_record_header, + etherbone_record_header_len) class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_etherbone_packet_user_description(32), - eth_etherbone_record_description(32), - etherbone_record_header, - etherbone_record_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_etherbone_packet_user_description(32), + eth_etherbone_record_description(32), + etherbone_record_header, + etherbone_record_header_len) class LiteEthEtherboneRecordReceiver(Module): - def __init__(self, buffer_depth=256): - self.sink = sink = Sink(eth_etherbone_record_description(32)) - self.source = source = Source(eth_etherbone_mmap_description(32)) - ### - fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, buffered=True) - self.submodules += fifo - self.comb += Record.connect(sink, fifo.sink) + def __init__(self, buffer_depth=256): + self.sink = sink = Sink(eth_etherbone_record_description(32)) + self.source = source = Source(eth_etherbone_mmap_description(32)) + ### + fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, buffered=True) + self.submodules += fifo + self.comb += Record.connect(sink, fifo.sink) - self.submodules.base_addr = base_addr = FlipFlop(32) - self.comb += base_addr.d.eq(fifo.source.data) + self.submodules.base_addr = base_addr = FlipFlop(32) + self.comb += base_addr.d.eq(fifo.source.data) - self.submodules.counter = counter = Counter(max=512) + self.submodules.counter = counter = Counter(max=512) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - fifo.source.ack.eq(1), - counter.reset.eq(1), - If(fifo.source.stb & fifo.source.sop, - base_addr.ce.eq(1), - If(fifo.source.wcount, - NextState("RECEIVE_WRITES") - ).Elif(fifo.source.rcount, - NextState("RECEIVE_READS") - ) - ) - ) - fsm.act("RECEIVE_WRITES", - source.stb.eq(fifo.source.stb), - source.sop.eq(counter.value == 0), - source.eop.eq(counter.value == fifo.source.wcount-1), - source.count.eq(fifo.source.wcount), - source.be.eq(fifo.source.byte_enable), - source.addr.eq(base_addr.q[2:] + counter.value), - source.we.eq(1), - source.data.eq(fifo.source.data), - fifo.source.ack.eq(source.ack), - If(source.stb & source.ack, - counter.ce.eq(1), - If(source.eop, - If(fifo.source.rcount, - NextState("RECEIVE_BASE_RET_ADDR") - ).Else( - NextState("IDLE") - ) - ) - ) - ) - fsm.act("RECEIVE_BASE_RET_ADDR", - counter.reset.eq(1), - If(fifo.source.stb & fifo.source.sop, - base_addr.ce.eq(1), - NextState("RECEIVE_READS") - ) - ) - fsm.act("RECEIVE_READS", - source.stb.eq(fifo.source.stb), - source.sop.eq(counter.value == 0), - source.eop.eq(counter.value == fifo.source.rcount-1), - source.count.eq(fifo.source.rcount), - source.base_addr.eq(base_addr.q), - source.addr.eq(fifo.source.data[2:]), - fifo.source.ack.eq(source.ack), - If(source.stb & source.ack, - counter.ce.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + fifo.source.ack.eq(1), + counter.reset.eq(1), + If(fifo.source.stb & fifo.source.sop, + base_addr.ce.eq(1), + If(fifo.source.wcount, + NextState("RECEIVE_WRITES") + ).Elif(fifo.source.rcount, + NextState("RECEIVE_READS") + ) + ) + ) + fsm.act("RECEIVE_WRITES", + source.stb.eq(fifo.source.stb), + source.sop.eq(counter.value == 0), + source.eop.eq(counter.value == fifo.source.wcount-1), + source.count.eq(fifo.source.wcount), + source.be.eq(fifo.source.byte_enable), + source.addr.eq(base_addr.q[2:] + counter.value), + source.we.eq(1), + source.data.eq(fifo.source.data), + fifo.source.ack.eq(source.ack), + If(source.stb & source.ack, + counter.ce.eq(1), + If(source.eop, + If(fifo.source.rcount, + NextState("RECEIVE_BASE_RET_ADDR") + ).Else( + NextState("IDLE") + ) + ) + ) + ) + fsm.act("RECEIVE_BASE_RET_ADDR", + counter.reset.eq(1), + If(fifo.source.stb & fifo.source.sop, + base_addr.ce.eq(1), + NextState("RECEIVE_READS") + ) + ) + fsm.act("RECEIVE_READS", + source.stb.eq(fifo.source.stb), + source.sop.eq(counter.value == 0), + source.eop.eq(counter.value == fifo.source.rcount-1), + source.count.eq(fifo.source.rcount), + source.base_addr.eq(base_addr.q), + source.addr.eq(fifo.source.data[2:]), + fifo.source.ack.eq(source.ack), + If(source.stb & source.ack, + counter.ce.eq(1), + If(source.eop, + NextState("IDLE") + ) + ) + ) class LiteEthEtherboneRecordSender(Module): - def __init__(self, buffer_depth=256): - self.sink = sink = Sink(eth_etherbone_mmap_description(32)) - self.source = source = Source(eth_etherbone_record_description(32)) - ### - pbuffer = PacketBuffer(eth_etherbone_mmap_description(32), buffer_depth) - self.submodules += pbuffer - self.comb += Record.connect(sink, pbuffer.sink) + def __init__(self, buffer_depth=256): + self.sink = sink = Sink(eth_etherbone_mmap_description(32)) + self.source = source = Source(eth_etherbone_record_description(32)) + ### + pbuffer = PacketBuffer(eth_etherbone_mmap_description(32), buffer_depth) + self.submodules += pbuffer + self.comb += Record.connect(sink, pbuffer.sink) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - pbuffer.source.ack.eq(1), - If(pbuffer.source.stb & pbuffer.source.sop, - pbuffer.source.ack.eq(0), - NextState("SEND_BASE_ADDRESS") - ) - ) - self.comb += [ - source.byte_enable.eq(pbuffer.source.be), - If(pbuffer.source.we, - source.wcount.eq(pbuffer.source.count) - ).Else( - source.rcount.eq(pbuffer.source.count) - ) - ] + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + pbuffer.source.ack.eq(1), + If(pbuffer.source.stb & pbuffer.source.sop, + pbuffer.source.ack.eq(0), + NextState("SEND_BASE_ADDRESS") + ) + ) + self.comb += [ + source.byte_enable.eq(pbuffer.source.be), + If(pbuffer.source.we, + source.wcount.eq(pbuffer.source.count) + ).Else( + source.rcount.eq(pbuffer.source.count) + ) + ] - fsm.act("SEND_BASE_ADDRESS", - source.stb.eq(pbuffer.source.stb), - source.sop.eq(1), - source.eop.eq(0), - source.data.eq(pbuffer.source.base_addr), - If(source.ack, - NextState("SEND_DATA") - ) - ) - fsm.act("SEND_DATA", - source.stb.eq(pbuffer.source.stb), - source.sop.eq(0), - source.eop.eq(pbuffer.source.eop), - source.data.eq(pbuffer.source.data), - If(source.stb & source.ack, - pbuffer.source.ack.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) + fsm.act("SEND_BASE_ADDRESS", + source.stb.eq(pbuffer.source.stb), + source.sop.eq(1), + source.eop.eq(0), + source.data.eq(pbuffer.source.base_addr), + If(source.ack, + NextState("SEND_DATA") + ) + ) + fsm.act("SEND_DATA", + source.stb.eq(pbuffer.source.stb), + source.sop.eq(0), + source.eop.eq(pbuffer.source.eop), + source.data.eq(pbuffer.source.data), + If(source.stb & source.ack, + pbuffer.source.ack.eq(1), + If(source.eop, + NextState("IDLE") + ) + ) + ) # Limitation: For simplicity we only support 1 record per packet class LiteEthEtherboneRecord(Module): - def __init__(self, endianness="big"): - self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) - self.source = source = Sink(eth_etherbone_packet_user_description(32)) - ### + def __init__(self, endianness="big"): + self.sink = sink = Sink(eth_etherbone_packet_user_description(32)) + self.source = source = Sink(eth_etherbone_packet_user_description(32)) + ### - # receive record, decode it and generate mmap stream - self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer() - self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver() - self.comb += [ - Record.connect(sink, depacketizer.sink), - Record.connect(depacketizer.source, receiver.sink) - ] - if endianness is "big": - self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data)) + # receive record, decode it and generate mmap stream + self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer() + self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver() + self.comb += [ + Record.connect(sink, depacketizer.sink), + Record.connect(depacketizer.source, receiver.sink) + ] + if endianness is "big": + self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data)) - # save last ip address - last_ip_address = Signal(32) - self.sync += [ - If(sink.stb & sink.sop & sink.ack, - last_ip_address.eq(sink.ip_address) - ) - ] + # save last ip address + last_ip_address = Signal(32) + self.sync += [ + If(sink.stb & sink.sop & sink.ack, + last_ip_address.eq(sink.ip_address) + ) + ] - # receive mmap stream, encode it and send records - self.submodules.sender = sender = LiteEthEtherboneRecordSender() - self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer() - self.comb += [ - Record.connect(sender.source, packetizer.sink), - Record.connect(packetizer.source, source), - source.length.eq(sender.source.wcount*4 + 4 +etherbone_record_header_len), # XXX improve this - source.ip_address.eq(last_ip_address) - ] - if endianness is "big": - self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data)) + # receive mmap stream, encode it and send records + self.submodules.sender = sender = LiteEthEtherboneRecordSender() + self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer() + self.comb += [ + Record.connect(sender.source, packetizer.sink), + Record.connect(packetizer.source, source), + source.length.eq(sender.source.wcount*4 + 4 +etherbone_record_header_len), # XXX improve this + source.ip_address.eq(last_ip_address) + ] + if endianness is "big": + self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data)) diff --git a/misoclib/com/liteeth/core/etherbone/wishbone.py b/misoclib/com/liteeth/core/etherbone/wishbone.py index 7f1530a8..2cd3ac7a 100644 --- a/misoclib/com/liteeth/core/etherbone/wishbone.py +++ b/misoclib/com/liteeth/core/etherbone/wishbone.py @@ -3,67 +3,67 @@ from misoclib.com.liteeth.generic import * from migen.bus import wishbone class LiteEthEtherboneWishboneMaster(Module): - def __init__(self): - self.sink = sink = Sink(eth_etherbone_mmap_description(32)) - self.source = source = Source(eth_etherbone_mmap_description(32)) - self.bus = bus = wishbone.Interface() - ###s + def __init__(self): + self.sink = sink = Sink(eth_etherbone_mmap_description(32)) + self.source = source = Source(eth_etherbone_mmap_description(32)) + self.bus = bus = wishbone.Interface() + ###s - self.submodules.data = data = FlipFlop(32) - self.comb += data.d.eq(bus.dat_r) + self.submodules.data = data = FlipFlop(32) + self.comb += data.d.eq(bus.dat_r) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - sink.ack.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - If(sink.we, - NextState("WRITE_DATA") - ).Else( - NextState("READ_DATA") - ) - ) - ) - fsm.act("WRITE_DATA", - bus.adr.eq(sink.addr), - bus.dat_w.eq(sink.data), - bus.sel.eq(sink.be), - bus.stb.eq(sink.stb), - bus.we.eq(1), - bus.cyc.eq(1), - If(bus.stb & bus.ack, - sink.ack.eq(1), - If(sink.eop, - NextState("IDLE") - ) - ) - ) - fsm.act("READ_DATA", - bus.adr.eq(sink.addr), - bus.sel.eq(sink.be), - bus.stb.eq(sink.stb), - bus.cyc.eq(1), - If(bus.stb & bus.ack, - data.ce.eq(1), - NextState("SEND_DATA") - ) - ) - fsm.act("SEND_DATA", - source.stb.eq(sink.stb), - source.sop.eq(sink.sop), - source.eop.eq(sink.eop), - source.base_addr.eq(sink.base_addr), - source.addr.eq(sink.addr), - source.count.eq(sink.count), - source.be.eq(sink.be), - source.we.eq(1), - source.data.eq(data.q), - If(source.stb & source.ack, - sink.ack.eq(1), - If(source.eop, - NextState("IDLE") - ).Else( - NextState("READ_DATA") - ) - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + sink.ack.eq(1), + If(sink.stb & sink.sop, + sink.ack.eq(0), + If(sink.we, + NextState("WRITE_DATA") + ).Else( + NextState("READ_DATA") + ) + ) + ) + fsm.act("WRITE_DATA", + bus.adr.eq(sink.addr), + bus.dat_w.eq(sink.data), + bus.sel.eq(sink.be), + bus.stb.eq(sink.stb), + bus.we.eq(1), + bus.cyc.eq(1), + If(bus.stb & bus.ack, + sink.ack.eq(1), + If(sink.eop, + NextState("IDLE") + ) + ) + ) + fsm.act("READ_DATA", + bus.adr.eq(sink.addr), + bus.sel.eq(sink.be), + bus.stb.eq(sink.stb), + bus.cyc.eq(1), + If(bus.stb & bus.ack, + data.ce.eq(1), + NextState("SEND_DATA") + ) + ) + fsm.act("SEND_DATA", + source.stb.eq(sink.stb), + source.sop.eq(sink.sop), + source.eop.eq(sink.eop), + source.base_addr.eq(sink.base_addr), + source.addr.eq(sink.addr), + source.count.eq(sink.count), + source.be.eq(sink.be), + source.we.eq(1), + source.data.eq(data.q), + If(source.stb & source.ack, + sink.ack.eq(1), + If(source.eop, + NextState("IDLE") + ).Else( + NextState("READ_DATA") + ) + ) + ) diff --git a/misoclib/com/liteeth/core/icmp/__init__.py b/misoclib/com/liteeth/core/icmp/__init__.py index c89da79e..66c2f6a4 100644 --- a/misoclib/com/liteeth/core/icmp/__init__.py +++ b/misoclib/com/liteeth/core/icmp/__init__.py @@ -4,135 +4,135 @@ from misoclib.com.liteeth.generic.depacketizer import LiteEthDepacketizer from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer class LiteEthICMPPacketizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_icmp_description(8), - eth_ipv4_user_description(8), - icmp_header, - icmp_header_len) + def __init__(self): + LiteEthPacketizer.__init__(self, + eth_icmp_description(8), + eth_ipv4_user_description(8), + icmp_header, + icmp_header_len) class LiteEthICMPTX(Module): - def __init__(self, ip_address): - self.sink = sink = Sink(eth_icmp_user_description(8)) - self.source = source = Source(eth_ipv4_user_description(8)) - ### - self.submodules.packetizer = packetizer = LiteEthICMPPacketizer() - self.comb += [ - packetizer.sink.stb.eq(sink.stb), - packetizer.sink.sop.eq(sink.sop), - packetizer.sink.eop.eq(sink.eop), - sink.ack.eq(packetizer.sink.ack), - packetizer.sink.msgtype.eq(sink.msgtype), - packetizer.sink.code.eq(sink.code), - packetizer.sink.checksum.eq(sink.checksum), - packetizer.sink.quench.eq(sink.quench), - packetizer.sink.data.eq(sink.data) - ] + def __init__(self, ip_address): + self.sink = sink = Sink(eth_icmp_user_description(8)) + self.source = source = Source(eth_ipv4_user_description(8)) + ### + self.submodules.packetizer = packetizer = LiteEthICMPPacketizer() + self.comb += [ + packetizer.sink.stb.eq(sink.stb), + packetizer.sink.sop.eq(sink.sop), + packetizer.sink.eop.eq(sink.eop), + sink.ack.eq(packetizer.sink.ack), + packetizer.sink.msgtype.eq(sink.msgtype), + packetizer.sink.code.eq(sink.code), + packetizer.sink.checksum.eq(sink.checksum), + packetizer.sink.quench.eq(sink.quench), + packetizer.sink.data.eq(sink.data) + ] - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.sop, - packetizer.source.ack.eq(0), - NextState("SEND") - ) - ) - fsm.act("SEND", - Record.connect(packetizer.source, source), - source.length.eq(sink.length + icmp_header_len), - source.protocol.eq(icmp_protocol), - source.ip_address.eq(sink.ip_address), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + packetizer.source.ack.eq(1), + If(packetizer.source.stb & packetizer.source.sop, + packetizer.source.ack.eq(0), + NextState("SEND") + ) + ) + fsm.act("SEND", + Record.connect(packetizer.source, source), + source.length.eq(sink.length + icmp_header_len), + source.protocol.eq(icmp_protocol), + source.ip_address.eq(sink.ip_address), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) class LiteEthICMPDepacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_ipv4_user_description(8), - eth_icmp_description(8), - icmp_header, - icmp_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_ipv4_user_description(8), + eth_icmp_description(8), + icmp_header, + icmp_header_len) class LiteEthICMPRX(Module): - def __init__(self, ip_address): - self.sink = sink = Sink(eth_ipv4_user_description(8)) - self.source = source = Source(eth_icmp_user_description(8)) - ### - self.submodules.depacketizer = depacketizer = LiteEthICMPDepacketizer() - self.comb += Record.connect(sink, depacketizer.sink) + def __init__(self, ip_address): + self.sink = sink = Sink(eth_ipv4_user_description(8)) + self.source = source = Source(eth_icmp_user_description(8)) + ### + self.submodules.depacketizer = depacketizer = LiteEthICMPDepacketizer() + self.comb += Record.connect(sink, depacketizer.sink) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") - ) - ) - valid = Signal() - self.sync += valid.eq( - depacketizer.source.stb & - (sink.protocol == icmp_protocol) - ) - fsm.act("CHECK", - If(valid, - NextState("PRESENT") - ).Else( - NextState("DROP") - ) - ) - self.comb += [ - source.sop.eq(depacketizer.source.sop), - source.eop.eq(depacketizer.source.eop), - source.msgtype.eq(depacketizer.source.msgtype), - source.code.eq(depacketizer.source.code), - source.checksum.eq(depacketizer.source.checksum), - source.quench.eq(depacketizer.source.quench), - source.ip_address.eq(sink.ip_address), - source.length.eq(sink.length - icmp_header_len), - source.data.eq(depacketizer.source.data), - source.error.eq(depacketizer.source.error) - ] - fsm.act("PRESENT", - source.stb.eq(depacketizer.source.stb), - depacketizer.source.ack.eq(source.ack), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - fsm.act("DROP", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, - NextState("IDLE") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.sop, + depacketizer.source.ack.eq(0), + NextState("CHECK") + ) + ) + valid = Signal() + self.sync += valid.eq( + depacketizer.source.stb & + (sink.protocol == icmp_protocol) + ) + fsm.act("CHECK", + If(valid, + NextState("PRESENT") + ).Else( + NextState("DROP") + ) + ) + self.comb += [ + source.sop.eq(depacketizer.source.sop), + source.eop.eq(depacketizer.source.eop), + source.msgtype.eq(depacketizer.source.msgtype), + source.code.eq(depacketizer.source.code), + source.checksum.eq(depacketizer.source.checksum), + source.quench.eq(depacketizer.source.quench), + source.ip_address.eq(sink.ip_address), + source.length.eq(sink.length - icmp_header_len), + source.data.eq(depacketizer.source.data), + source.error.eq(depacketizer.source.error) + ] + fsm.act("PRESENT", + source.stb.eq(depacketizer.source.stb), + depacketizer.source.ack.eq(source.ack), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + fsm.act("DROP", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, + NextState("IDLE") + ) + ) class LiteEthICMPEcho(Module): - def __init__(self): - self.sink = sink = Sink(eth_icmp_user_description(8)) - self.source = source = Source(eth_icmp_user_description(8)) - ### - self.submodules.buffer = PacketBuffer(eth_icmp_user_description(8), 128, 2) - self.comb += [ - Record.connect(sink, self.buffer.sink), - Record.connect(self.buffer.source, source), - self.source.msgtype.eq(0x0), - self.source.checksum.eq(~((~self.buffer.source.checksum)-0x0800)) - ] + def __init__(self): + self.sink = sink = Sink(eth_icmp_user_description(8)) + self.source = source = Source(eth_icmp_user_description(8)) + ### + self.submodules.buffer = PacketBuffer(eth_icmp_user_description(8), 128, 2) + self.comb += [ + Record.connect(sink, self.buffer.sink), + Record.connect(self.buffer.source, source), + self.source.msgtype.eq(0x0), + self.source.checksum.eq(~((~self.buffer.source.checksum)-0x0800)) + ] class LiteEthICMP(Module): - def __init__(self, ip, ip_address): - self.submodules.tx = tx = LiteEthICMPTX(ip_address) - self.submodules.rx = rx = LiteEthICMPRX(ip_address) - self.submodules.echo = echo = LiteEthICMPEcho() - self.comb += [ - Record.connect(rx.source, echo.sink), - Record.connect(echo.source, tx.sink) - ] - ip_port = ip.crossbar.get_port(icmp_protocol) - self.comb += [ - Record.connect(tx.source, ip_port.sink), - Record.connect(ip_port.source, rx.sink) - ] + def __init__(self, ip, ip_address): + self.submodules.tx = tx = LiteEthICMPTX(ip_address) + self.submodules.rx = rx = LiteEthICMPRX(ip_address) + self.submodules.echo = echo = LiteEthICMPEcho() + self.comb += [ + Record.connect(rx.source, echo.sink), + Record.connect(echo.source, tx.sink) + ] + ip_port = ip.crossbar.get_port(icmp_protocol) + self.comb += [ + Record.connect(tx.source, ip_port.sink), + Record.connect(ip_port.source, rx.sink) + ] diff --git a/misoclib/com/liteeth/core/ip/__init__.py b/misoclib/com/liteeth/core/ip/__init__.py index 5c9edb1f..9fb5a947 100644 --- a/misoclib/com/liteeth/core/ip/__init__.py +++ b/misoclib/com/liteeth/core/ip/__init__.py @@ -6,175 +6,175 @@ from misoclib.com.liteeth.generic.depacketizer import LiteEthDepacketizer from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer class LiteEthIPV4Packetizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_ipv4_description(8), - eth_mac_description(8), - ipv4_header, - ipv4_header_len) + def __init__(self): + LiteEthPacketizer.__init__(self, + eth_ipv4_description(8), + eth_mac_description(8), + ipv4_header, + ipv4_header_len) class LiteEthIPTX(Module): - def __init__(self, mac_address, ip_address, arp_table): - self.sink = sink = Sink(eth_ipv4_user_description(8)) - self.source = source = Source(eth_mac_description(8)) - self.target_unreachable = Signal() - ### - self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=True) - self.comb += [ - checksum.ce.eq(sink.stb & sink.sop), - checksum.reset.eq(source.stb & source.eop & source.ack) - ] + def __init__(self, mac_address, ip_address, arp_table): + self.sink = sink = Sink(eth_ipv4_user_description(8)) + self.source = source = Source(eth_mac_description(8)) + self.target_unreachable = Signal() + ### + self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=True) + self.comb += [ + checksum.ce.eq(sink.stb & sink.sop), + checksum.reset.eq(source.stb & source.eop & source.ack) + ] - self.submodules.packetizer = packetizer = LiteEthIPV4Packetizer() - self.comb += [ - packetizer.sink.stb.eq(sink.stb & checksum.done), - packetizer.sink.sop.eq(sink.sop), - packetizer.sink.eop.eq(sink.eop), - sink.ack.eq(packetizer.sink.ack & checksum.done), - packetizer.sink.target_ip.eq(sink.ip_address), - packetizer.sink.protocol.eq(sink.protocol), - packetizer.sink.total_length.eq(sink.length + (0x5*4)), - packetizer.sink.version.eq(0x4), # ipv4 - packetizer.sink.ihl.eq(0x5), # 20 bytes - packetizer.sink.identification.eq(0), - packetizer.sink.ttl.eq(0x80), - packetizer.sink.sender_ip.eq(ip_address), - packetizer.sink.data.eq(sink.data), - checksum.header.eq(packetizer.header), - packetizer.sink.checksum.eq(checksum.value) - ] + self.submodules.packetizer = packetizer = LiteEthIPV4Packetizer() + self.comb += [ + packetizer.sink.stb.eq(sink.stb & checksum.done), + packetizer.sink.sop.eq(sink.sop), + packetizer.sink.eop.eq(sink.eop), + sink.ack.eq(packetizer.sink.ack & checksum.done), + packetizer.sink.target_ip.eq(sink.ip_address), + packetizer.sink.protocol.eq(sink.protocol), + packetizer.sink.total_length.eq(sink.length + (0x5*4)), + packetizer.sink.version.eq(0x4), # ipv4 + packetizer.sink.ihl.eq(0x5), # 20 bytes + packetizer.sink.identification.eq(0), + packetizer.sink.ttl.eq(0x80), + packetizer.sink.sender_ip.eq(ip_address), + packetizer.sink.data.eq(sink.data), + checksum.header.eq(packetizer.header), + packetizer.sink.checksum.eq(checksum.value) + ] - target_mac = Signal(48) + target_mac = Signal(48) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.sop, - packetizer.source.ack.eq(0), - NextState("SEND_MAC_ADDRESS_REQUEST") - ) - ) - self.comb += arp_table.request.ip_address.eq(sink.ip_address) - fsm.act("SEND_MAC_ADDRESS_REQUEST", - arp_table.request.stb.eq(1), - If(arp_table.request.stb & arp_table.request.ack, - NextState("WAIT_MAC_ADDRESS_RESPONSE") - ) - ) - fsm.act("WAIT_MAC_ADDRESS_RESPONSE", - If(arp_table.response.stb, - arp_table.response.ack.eq(1), - If(arp_table.response.failed, - self.target_unreachable.eq(1), - NextState("DROP"), - ).Else( - NextState("SEND") - ) - ) - ) - self.sync += \ - If(arp_table.response.stb, - target_mac.eq(arp_table.response.mac_address) - ) - fsm.act("SEND", - Record.connect(packetizer.source, source), - source.ethernet_type.eq(ethernet_type_ip), - source.target_mac.eq(target_mac), - source.sender_mac.eq(mac_address), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - fsm.act("DROP", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.eop & packetizer.source.ack, - NextState("IDLE") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + packetizer.source.ack.eq(1), + If(packetizer.source.stb & packetizer.source.sop, + packetizer.source.ack.eq(0), + NextState("SEND_MAC_ADDRESS_REQUEST") + ) + ) + self.comb += arp_table.request.ip_address.eq(sink.ip_address) + fsm.act("SEND_MAC_ADDRESS_REQUEST", + arp_table.request.stb.eq(1), + If(arp_table.request.stb & arp_table.request.ack, + NextState("WAIT_MAC_ADDRESS_RESPONSE") + ) + ) + fsm.act("WAIT_MAC_ADDRESS_RESPONSE", + If(arp_table.response.stb, + arp_table.response.ack.eq(1), + If(arp_table.response.failed, + self.target_unreachable.eq(1), + NextState("DROP"), + ).Else( + NextState("SEND") + ) + ) + ) + self.sync += \ + If(arp_table.response.stb, + target_mac.eq(arp_table.response.mac_address) + ) + fsm.act("SEND", + Record.connect(packetizer.source, source), + source.ethernet_type.eq(ethernet_type_ip), + source.target_mac.eq(target_mac), + source.sender_mac.eq(mac_address), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + fsm.act("DROP", + packetizer.source.ack.eq(1), + If(packetizer.source.stb & packetizer.source.eop & packetizer.source.ack, + NextState("IDLE") + ) + ) class LiteEthIPV4Depacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_mac_description(8), - eth_ipv4_description(8), - ipv4_header, - ipv4_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_mac_description(8), + eth_ipv4_description(8), + ipv4_header, + ipv4_header_len) class LiteEthIPRX(Module): - def __init__(self, mac_address, ip_address): - self.sink = sink = Sink(eth_mac_description(8)) - self.source = source = Source(eth_ipv4_user_description(8)) - ### - self.submodules.depacketizer = depacketizer = LiteEthIPV4Depacketizer() - self.comb += Record.connect(sink, depacketizer.sink) + def __init__(self, mac_address, ip_address): + self.sink = sink = Sink(eth_mac_description(8)) + self.source = source = Source(eth_ipv4_user_description(8)) + ### + self.submodules.depacketizer = depacketizer = LiteEthIPV4Depacketizer() + self.comb += Record.connect(sink, depacketizer.sink) - self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=False) - self.comb += [ - checksum.header.eq(depacketizer.header), - checksum.reset.eq(depacketizer.source.stb & depacketizer.source.eop), - checksum.ce.eq(depacketizer.source.stb & depacketizer.source.sop) - ] + self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=False) + self.comb += [ + checksum.header.eq(depacketizer.header), + checksum.reset.eq(depacketizer.source.stb & depacketizer.source.eop), + checksum.ce.eq(depacketizer.source.stb & depacketizer.source.sop) + ] - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") - ) - ) - valid = Signal() - self.sync += valid.eq( - depacketizer.source.stb & - (depacketizer.source.target_ip == ip_address) & - (depacketizer.source.version == 0x4) & - (depacketizer.source.ihl == 0x5) & - (checksum.value == 0) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.sop, + depacketizer.source.ack.eq(0), + NextState("CHECK") + ) + ) + valid = Signal() + self.sync += valid.eq( + depacketizer.source.stb & + (depacketizer.source.target_ip == ip_address) & + (depacketizer.source.version == 0x4) & + (depacketizer.source.ihl == 0x5) & + (checksum.value == 0) + ) - fsm.act("CHECK", - If(checksum.done, - If(valid, - NextState("PRESENT") - ).Else( - NextState("DROP") - ) - ) - ) - self.comb += [ - source.sop.eq(depacketizer.source.sop), - source.eop.eq(depacketizer.source.eop), - source.length.eq(depacketizer.source.total_length - (0x5*4)), - source.protocol.eq(depacketizer.source.protocol), - source.ip_address.eq(depacketizer.source.sender_ip), - source.data.eq(depacketizer.source.data), - source.error.eq(depacketizer.source.error) - ] - fsm.act("PRESENT", - source.stb.eq(depacketizer.source.stb), - depacketizer.source.ack.eq(source.ack), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - fsm.act("DROP", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, - NextState("IDLE") - ) - ) + fsm.act("CHECK", + If(checksum.done, + If(valid, + NextState("PRESENT") + ).Else( + NextState("DROP") + ) + ) + ) + self.comb += [ + source.sop.eq(depacketizer.source.sop), + source.eop.eq(depacketizer.source.eop), + source.length.eq(depacketizer.source.total_length - (0x5*4)), + source.protocol.eq(depacketizer.source.protocol), + source.ip_address.eq(depacketizer.source.sender_ip), + source.data.eq(depacketizer.source.data), + source.error.eq(depacketizer.source.error) + ] + fsm.act("PRESENT", + source.stb.eq(depacketizer.source.stb), + depacketizer.source.ack.eq(source.ack), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + fsm.act("DROP", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, + NextState("IDLE") + ) + ) class LiteEthIP(Module): - def __init__(self, mac, mac_address, ip_address, arp_table): - self.submodules.tx = tx = LiteEthIPTX(mac_address, ip_address, arp_table) - self.submodules.rx = rx = LiteEthIPRX(mac_address, ip_address) - mac_port = mac.crossbar.get_port(ethernet_type_ip) - self.comb += [ - Record.connect(tx.source, mac_port.sink), - Record.connect(mac_port.source, rx.sink) - ] - self.submodules.crossbar = crossbar = LiteEthIPV4Crossbar() - self.comb += [ - Record.connect(crossbar.master.source, tx.sink), - Record.connect(rx.source, crossbar.master.sink) - ] + def __init__(self, mac, mac_address, ip_address, arp_table): + self.submodules.tx = tx = LiteEthIPTX(mac_address, ip_address, arp_table) + self.submodules.rx = rx = LiteEthIPRX(mac_address, ip_address) + mac_port = mac.crossbar.get_port(ethernet_type_ip) + self.comb += [ + Record.connect(tx.source, mac_port.sink), + Record.connect(mac_port.source, rx.sink) + ] + self.submodules.crossbar = crossbar = LiteEthIPV4Crossbar() + self.comb += [ + Record.connect(crossbar.master.source, tx.sink), + Record.connect(rx.source, crossbar.master.sink) + ] diff --git a/misoclib/com/liteeth/core/ip/checksum.py b/misoclib/com/liteeth/core/ip/checksum.py index a502e02a..ea5e6156 100644 --- a/misoclib/com/liteeth/core/ip/checksum.py +++ b/misoclib/com/liteeth/core/ip/checksum.py @@ -2,42 +2,42 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthIPV4Checksum(Module): - def __init__(self, words_per_clock_cycle=1, skip_checksum=False): - self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog - self.ce = Signal() # XXX FIXME InsertCE generates incorrect verilog - self.header = Signal(ipv4_header_len*8) - self.value = Signal(16) - self.done = Signal() - ### - s = Signal(17) - r = Signal(17) - n_cycles = 0 - for i in range(ipv4_header_len//2): - if skip_checksum and (i == ipv4_header["checksum"].byte//2): - 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 = r_next.eq(Cat(s_next[:16]+s_next[16], Signal())) - if (i%words_per_clock_cycle) != 0: - self.comb += r_next_eq - else: - self.sync += \ - If(self.reset, - r_next.eq(0) - ).Elif(self.ce & ~self.done, - r_next_eq - ) - n_cycles += 1 - s, r = s_next, r_next - self.comb += self.value.eq(~Cat(r[8:16], r[:8])) + def __init__(self, words_per_clock_cycle=1, skip_checksum=False): + self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog + self.ce = Signal() # XXX FIXME InsertCE generates incorrect verilog + self.header = Signal(ipv4_header_len*8) + self.value = Signal(16) + self.done = Signal() + ### + s = Signal(17) + r = Signal(17) + n_cycles = 0 + for i in range(ipv4_header_len//2): + if skip_checksum and (i == ipv4_header["checksum"].byte//2): + 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 = r_next.eq(Cat(s_next[:16]+s_next[16], Signal())) + if (i%words_per_clock_cycle) != 0: + self.comb += r_next_eq + else: + self.sync += \ + If(self.reset, + r_next.eq(0) + ).Elif(self.ce & ~self.done, + r_next_eq + ) + n_cycles += 1 + s, r = s_next, r_next + self.comb += self.value.eq(~Cat(r[8:16], r[:8])) - if not skip_checksum: - n_cycles += 1 - self.submodules.counter = counter = Counter(max=n_cycles+1) - self.comb += [ - counter.reset.eq(self.reset), - counter.ce.eq(self.ce & ~self.done), - self.done.eq(counter.value == n_cycles) - ] + if not skip_checksum: + n_cycles += 1 + self.submodules.counter = counter = Counter(max=n_cycles+1) + self.comb += [ + counter.reset.eq(self.reset), + counter.ce.eq(self.ce & ~self.done), + self.done.eq(counter.value == n_cycles) + ] diff --git a/misoclib/com/liteeth/core/ip/crossbar.py b/misoclib/com/liteeth/core/ip/crossbar.py index f7de9773..7b402e83 100644 --- a/misoclib/com/liteeth/core/ip/crossbar.py +++ b/misoclib/com/liteeth/core/ip/crossbar.py @@ -3,28 +3,28 @@ from misoclib.com.liteeth.generic import * from misoclib.com.liteeth.generic.crossbar import LiteEthCrossbar class LiteEthIPV4MasterPort: - def __init__(self, dw): - self.dw = dw - self.source = Source(eth_ipv4_user_description(dw)) - self.sink = Sink(eth_ipv4_user_description(dw)) + def __init__(self, dw): + self.dw = dw + self.source = Source(eth_ipv4_user_description(dw)) + self.sink = Sink(eth_ipv4_user_description(dw)) class LiteEthIPV4SlavePort: - def __init__(self, dw): - self.dw = dw - self.sink = Sink(eth_ipv4_user_description(dw)) - self.source = Source(eth_ipv4_user_description(dw)) + def __init__(self, dw): + self.dw = dw + self.sink = Sink(eth_ipv4_user_description(dw)) + self.source = Source(eth_ipv4_user_description(dw)) class LiteEthIPV4UserPort(LiteEthIPV4SlavePort): - def __init__(self, dw): - LiteEthIPV4SlavePort.__init__(self, dw) + def __init__(self, dw): + LiteEthIPV4SlavePort.__init__(self, dw) class LiteEthIPV4Crossbar(LiteEthCrossbar): - def __init__(self): - LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol") + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol") - def get_port(self, protocol): - if protocol in self.users.keys(): - raise ValueError("Protocol {0:#x} already assigned".format(protocol)) - port = LiteEthIPV4UserPort(8) - self.users[protocol] = port - return port + def get_port(self, protocol): + if protocol in self.users.keys(): + raise ValueError("Protocol {0:#x} already assigned".format(protocol)) + port = LiteEthIPV4UserPort(8) + self.users[protocol] = port + return port diff --git a/misoclib/com/liteeth/core/tty/__init__.py b/misoclib/com/liteeth/core/tty/__init__.py index 7ead3ef4..828d75b0 100644 --- a/misoclib/com/liteeth/core/tty/__init__.py +++ b/misoclib/com/liteeth/core/tty/__init__.py @@ -2,96 +2,96 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthTTYTX(Module): - def __init__(self, ip_address, udp_port, fifo_depth=None): - self.sink = sink = Sink(eth_tty_description(8)) - self.source = source = Source(eth_udp_user_description(8)) - ### - if fifo_depth is None: - self.comb += [ - source.stb.eq(sink.stb), - source.sop.eq(1), - source.eop.eq(1), - source.length.eq(1), - source.data.eq(sink.data), - sink.ack.eq(source.ack) - ] - else: - self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth) - self.comb += Record.connect(sink, fifo.sink) + def __init__(self, ip_address, udp_port, fifo_depth=None): + self.sink = sink = Sink(eth_tty_description(8)) + self.source = source = Source(eth_udp_user_description(8)) + ### + if fifo_depth is None: + self.comb += [ + source.stb.eq(sink.stb), + source.sop.eq(1), + source.eop.eq(1), + source.length.eq(1), + source.data.eq(sink.data), + sink.ack.eq(source.ack) + ] + else: + self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth) + self.comb += Record.connect(sink, fifo.sink) - self.submodules.level = level = FlipFlop(max=fifo_depth) - self.comb += level.d.eq(fifo.fifo.level) + self.submodules.level = level = FlipFlop(max=fifo_depth) + self.comb += level.d.eq(fifo.fifo.level) - self.submodules.counter = counter = Counter(max=fifo_depth) + self.submodules.counter = counter = Counter(max=fifo_depth) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - If(fifo.source.stb, - level.ce.eq(1), - counter.reset.eq(1), - NextState("SEND") - ) - ) - fsm.act("SEND", - source.stb.eq(fifo.source.stb), - source.sop.eq(counter.value == 0), - If(level.q == 0, - source.eop.eq(1), - ).Else( - source.eop.eq(counter.value == (level.q-1)), - ), - source.src_port.eq(udp_port), - source.dst_port.eq(udp_port), - source.ip_address.eq(ip_address), - If(level.q == 0, - source.length.eq(1), - ).Else( - source.length.eq(level.q), - ), - source.data.eq(fifo.source.data), - fifo.source.ack.eq(source.ack), - If(source.stb & source.ack, - counter.ce.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + If(fifo.source.stb, + level.ce.eq(1), + counter.reset.eq(1), + NextState("SEND") + ) + ) + fsm.act("SEND", + source.stb.eq(fifo.source.stb), + source.sop.eq(counter.value == 0), + If(level.q == 0, + source.eop.eq(1), + ).Else( + source.eop.eq(counter.value == (level.q-1)), + ), + source.src_port.eq(udp_port), + source.dst_port.eq(udp_port), + source.ip_address.eq(ip_address), + If(level.q == 0, + source.length.eq(1), + ).Else( + source.length.eq(level.q), + ), + source.data.eq(fifo.source.data), + fifo.source.ack.eq(source.ack), + If(source.stb & source.ack, + counter.ce.eq(1), + If(source.eop, + NextState("IDLE") + ) + ) + ) class LiteEthTTYRX(Module): - def __init__(self, ip_address, udp_port, fifo_depth=None): - self.sink = sink = Sink(eth_udp_user_description(8)) - self.source = source = Source(eth_tty_description(8)) - ### - valid = Signal() - self.comb += valid.eq( - (sink.ip_address == ip_address) & - (sink.dst_port == udp_port) - ) - if fifo_depth is None: - self.comb += [ - source.stb.eq(sink.stb & valid), - source.data.eq(sink.data), - sink.ack.eq(source.ack) - ] - else: - self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth) - self.comb += [ - fifo.sink.stb.eq(sink.stb & valid), - fifo.sink.data.eq(sink.data), - sink.ack.eq(fifo.sink.ack), - Record.connect(fifo.source, source) - ] + def __init__(self, ip_address, udp_port, fifo_depth=None): + self.sink = sink = Sink(eth_udp_user_description(8)) + self.source = source = Source(eth_tty_description(8)) + ### + valid = Signal() + self.comb += valid.eq( + (sink.ip_address == ip_address) & + (sink.dst_port == udp_port) + ) + if fifo_depth is None: + self.comb += [ + source.stb.eq(sink.stb & valid), + source.data.eq(sink.data), + sink.ack.eq(source.ack) + ] + else: + self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth) + self.comb += [ + fifo.sink.stb.eq(sink.stb & valid), + fifo.sink.data.eq(sink.data), + sink.ack.eq(fifo.sink.ack), + Record.connect(fifo.source, source) + ] class LiteEthTTY(Module): - def __init__(self, udp, ip_address, udp_port, - rx_fifo_depth=64, - tx_fifo_depth=64): - self.submodules.tx = tx = LiteEthTTYTX(ip_address, udp_port, tx_fifo_depth) - self.submodules.rx = rx = LiteEthTTYRX(ip_address, udp_port, rx_fifo_depth) - udp_port = udp.crossbar.get_port(udp_port, dw=8) - self.comb += [ - Record.connect(tx.source, udp_port.sink), - Record.connect(udp_port.source, rx.sink) - ] - self.sink, self.source = self.tx.sink, self.rx.source + def __init__(self, udp, ip_address, udp_port, + rx_fifo_depth=64, + tx_fifo_depth=64): + self.submodules.tx = tx = LiteEthTTYTX(ip_address, udp_port, tx_fifo_depth) + self.submodules.rx = rx = LiteEthTTYRX(ip_address, udp_port, rx_fifo_depth) + udp_port = udp.crossbar.get_port(udp_port, dw=8) + self.comb += [ + Record.connect(tx.source, udp_port.sink), + Record.connect(udp_port.source, rx.sink) + ] + self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/com/liteeth/core/udp/__init__.py b/misoclib/com/liteeth/core/udp/__init__.py index 59f671df..1518dec6 100644 --- a/misoclib/com/liteeth/core/udp/__init__.py +++ b/misoclib/com/liteeth/core/udp/__init__.py @@ -5,121 +5,121 @@ from misoclib.com.liteeth.generic.depacketizer import LiteEthDepacketizer from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer class LiteEthUDPPacketizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_udp_description(8), - eth_ipv4_user_description(8), - udp_header, - udp_header_len) + def __init__(self): + LiteEthPacketizer.__init__(self, + eth_udp_description(8), + eth_ipv4_user_description(8), + udp_header, + udp_header_len) class LiteEthUDPTX(Module): - def __init__(self, ip_address): - self.sink = sink = Sink(eth_udp_user_description(8)) - self.source = source = Source(eth_ipv4_user_description(8)) - ### - self.submodules.packetizer = packetizer = LiteEthUDPPacketizer() - self.comb += [ - packetizer.sink.stb.eq(sink.stb), - packetizer.sink.sop.eq(sink.sop), - packetizer.sink.eop.eq(sink.eop), - sink.ack.eq(packetizer.sink.ack), - packetizer.sink.src_port.eq(sink.src_port), - packetizer.sink.dst_port.eq(sink.dst_port), - packetizer.sink.length.eq(sink.length + udp_header_len), - packetizer.sink.checksum.eq(0), # Disabled (MAC CRC is enough) - packetizer.sink.data.eq(sink.data) - ] + def __init__(self, ip_address): + self.sink = sink = Sink(eth_udp_user_description(8)) + self.source = source = Source(eth_ipv4_user_description(8)) + ### + self.submodules.packetizer = packetizer = LiteEthUDPPacketizer() + self.comb += [ + packetizer.sink.stb.eq(sink.stb), + packetizer.sink.sop.eq(sink.sop), + packetizer.sink.eop.eq(sink.eop), + sink.ack.eq(packetizer.sink.ack), + packetizer.sink.src_port.eq(sink.src_port), + packetizer.sink.dst_port.eq(sink.dst_port), + packetizer.sink.length.eq(sink.length + udp_header_len), + packetizer.sink.checksum.eq(0), # Disabled (MAC CRC is enough) + packetizer.sink.data.eq(sink.data) + ] - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - packetizer.source.ack.eq(1), - If(packetizer.source.stb & packetizer.source.sop, - packetizer.source.ack.eq(0), - NextState("SEND") - ) - ) - fsm.act("SEND", - Record.connect(packetizer.source, source), - source.length.eq(packetizer.sink.length), - source.protocol.eq(udp_protocol), - source.ip_address.eq(sink.ip_address), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + packetizer.source.ack.eq(1), + If(packetizer.source.stb & packetizer.source.sop, + packetizer.source.ack.eq(0), + NextState("SEND") + ) + ) + fsm.act("SEND", + Record.connect(packetizer.source, source), + source.length.eq(packetizer.sink.length), + source.protocol.eq(udp_protocol), + source.ip_address.eq(sink.ip_address), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) class LiteEthUDPDepacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_ipv4_user_description(8), - eth_udp_description(8), - udp_header, - udp_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_ipv4_user_description(8), + eth_udp_description(8), + udp_header, + udp_header_len) class LiteEthUDPRX(Module): - def __init__(self, ip_address): - self.sink = sink = Sink(eth_ipv4_user_description(8)) - self.source = source = Source(eth_udp_user_description(8)) - ### - self.submodules.depacketizer = depacketizer = LiteEthUDPDepacketizer() - self.comb += Record.connect(sink, depacketizer.sink) + def __init__(self, ip_address): + self.sink = sink = Sink(eth_ipv4_user_description(8)) + self.source = source = Source(eth_udp_user_description(8)) + ### + self.submodules.depacketizer = depacketizer = LiteEthUDPDepacketizer() + self.comb += Record.connect(sink, depacketizer.sink) - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.sop, - depacketizer.source.ack.eq(0), - NextState("CHECK") - ) - ) - valid = Signal() - self.sync += valid.eq( - depacketizer.source.stb & - (sink.protocol == udp_protocol) - ) + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.sop, + depacketizer.source.ack.eq(0), + NextState("CHECK") + ) + ) + valid = Signal() + self.sync += valid.eq( + depacketizer.source.stb & + (sink.protocol == udp_protocol) + ) - fsm.act("CHECK", - If(valid, - NextState("PRESENT") - ).Else( - NextState("DROP") - ) - ) - self.comb += [ - source.sop.eq(depacketizer.source.sop), - source.eop.eq(depacketizer.source.eop), - source.src_port.eq(depacketizer.source.src_port), - source.dst_port.eq(depacketizer.source.dst_port), - source.ip_address.eq(sink.ip_address), - source.length.eq(depacketizer.source.length - udp_header_len), - source.data.eq(depacketizer.source.data), - source.error.eq(depacketizer.source.error) - ] - fsm.act("PRESENT", - source.stb.eq(depacketizer.source.stb), - depacketizer.source.ack.eq(source.ack), - If(source.stb & source.eop & source.ack, - NextState("IDLE") - ) - ) - fsm.act("DROP", - depacketizer.source.ack.eq(1), - If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, - NextState("IDLE") - ) - ) + fsm.act("CHECK", + If(valid, + NextState("PRESENT") + ).Else( + NextState("DROP") + ) + ) + self.comb += [ + source.sop.eq(depacketizer.source.sop), + source.eop.eq(depacketizer.source.eop), + source.src_port.eq(depacketizer.source.src_port), + source.dst_port.eq(depacketizer.source.dst_port), + source.ip_address.eq(sink.ip_address), + source.length.eq(depacketizer.source.length - udp_header_len), + source.data.eq(depacketizer.source.data), + source.error.eq(depacketizer.source.error) + ] + fsm.act("PRESENT", + source.stb.eq(depacketizer.source.stb), + depacketizer.source.ack.eq(source.ack), + If(source.stb & source.eop & source.ack, + NextState("IDLE") + ) + ) + fsm.act("DROP", + depacketizer.source.ack.eq(1), + If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack, + NextState("IDLE") + ) + ) class LiteEthUDP(Module): - def __init__(self, ip, ip_address): - self.submodules.tx = tx = LiteEthUDPTX(ip_address) - self.submodules.rx = rx = LiteEthUDPRX(ip_address) - ip_port = ip.crossbar.get_port(udp_protocol) - self.comb += [ - Record.connect(tx.source, ip_port.sink), - Record.connect(ip_port.source, rx.sink) - ] - self.submodules.crossbar = crossbar = LiteEthUDPCrossbar() - self.comb += [ - Record.connect(crossbar.master.source, tx.sink), - Record.connect(rx.source, crossbar.master.sink) - ] + def __init__(self, ip, ip_address): + self.submodules.tx = tx = LiteEthUDPTX(ip_address) + self.submodules.rx = rx = LiteEthUDPRX(ip_address) + ip_port = ip.crossbar.get_port(udp_protocol) + self.comb += [ + Record.connect(tx.source, ip_port.sink), + Record.connect(ip_port.source, rx.sink) + ] + self.submodules.crossbar = crossbar = LiteEthUDPCrossbar() + self.comb += [ + Record.connect(crossbar.master.source, tx.sink), + Record.connect(rx.source, crossbar.master.sink) + ] diff --git a/misoclib/com/liteeth/core/udp/crossbar.py b/misoclib/com/liteeth/core/udp/crossbar.py index a43f3eee..0bb55796 100644 --- a/misoclib/com/liteeth/core/udp/crossbar.py +++ b/misoclib/com/liteeth/core/udp/crossbar.py @@ -4,44 +4,44 @@ from misoclib.com.liteeth.generic import * from misoclib.com.liteeth.generic.crossbar import LiteEthCrossbar class LiteEthUDPMasterPort: - def __init__(self, dw): - self.dw = dw - self.source = Source(eth_udp_user_description(dw)) - self.sink = Sink(eth_udp_user_description(dw)) + def __init__(self, dw): + self.dw = dw + self.source = Source(eth_udp_user_description(dw)) + self.sink = Sink(eth_udp_user_description(dw)) class LiteEthUDPSlavePort: - def __init__(self, dw): - self.dw =dw - self.sink = Sink(eth_udp_user_description(dw)) - self.source = Source(eth_udp_user_description(dw)) + def __init__(self, dw): + self.dw =dw + self.sink = Sink(eth_udp_user_description(dw)) + self.source = Source(eth_udp_user_description(dw)) class LiteEthUDPUserPort(LiteEthUDPSlavePort): - def __init__(self, dw): - LiteEthUDPSlavePort.__init__(self, dw) + def __init__(self, dw): + LiteEthUDPSlavePort.__init__(self, dw) class LiteEthUDPCrossbar(LiteEthCrossbar): - def __init__(self): - LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port") + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port") - def get_port(self, udp_port, dw=8): - if udp_port in self.users.keys(): - raise ValueError("Port {0:#x} already assigned".format(udp_port)) - user_port = LiteEthUDPUserPort(dw) - internal_port = LiteEthUDPUserPort(8) - if dw != 8: - converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8)) - self.submodules += converter - self.comb += [ - Record.connect(user_port.sink, converter.sink), - Record.connect(converter.source, internal_port.sink) - ] - converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw)) - self.submodules += converter - self.comb += [ - Record.connect(internal_port.source, converter.sink), - Record.connect(converter.source, user_port.source) - ] - self.users[udp_port] = internal_port - else: - self.users[udp_port] = user_port - return user_port + def get_port(self, udp_port, dw=8): + if udp_port in self.users.keys(): + raise ValueError("Port {0:#x} already assigned".format(udp_port)) + user_port = LiteEthUDPUserPort(dw) + internal_port = LiteEthUDPUserPort(8) + if dw != 8: + converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8)) + self.submodules += converter + self.comb += [ + Record.connect(user_port.sink, converter.sink), + Record.connect(converter.source, internal_port.sink) + ] + converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw)) + self.submodules += converter + self.comb += [ + Record.connect(internal_port.source, converter.sink), + Record.connect(converter.source, user_port.source) + ] + self.users[udp_port] = internal_port + else: + self.users[udp_port] = user_port + return user_port diff --git a/misoclib/com/liteeth/example_designs/make.py b/misoclib/com/liteeth/example_designs/make.py index 6f504bb2..162ed184 100644 --- a/misoclib/com/liteeth/example_designs/make.py +++ b/misoclib/com/liteeth/example_designs/make.py @@ -14,11 +14,11 @@ from misoclib.soc import cpuif from misoclib.com.liteeth.common import * def _import(default, name): - return importlib.import_module(default + "." + name) + return importlib.import_module(default + "." + name) def _get_args(): - parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, - description="""\ + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, + description="""\ LiteEth - based on Migen. This program builds and/or loads LiteEth components. @@ -34,60 +34,60 @@ load-bitstream load bitstream into volatile storage. all clean, build-csr-csv, build-bitstream, load-bitstream. """) - parser.add_argument("-t", "--target", default="base", help="Core type to build") - parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build") - parser.add_argument("-p", "--platform", default=None, help="platform to build for") - parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option") - parser.add_argument("-Op", "--platform-option", default=[], nargs=2, action="append", help="set platform-specific option") - parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into") + parser.add_argument("-t", "--target", default="base", help="Core type to build") + parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build") + parser.add_argument("-p", "--platform", default=None, help="platform to build for") + parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option") + parser.add_argument("-Op", "--platform-option", default=[], nargs=2, action="append", help="set platform-specific option") + parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into") - parser.add_argument("action", nargs="+", help="specify an action") + parser.add_argument("action", nargs="+", help="specify an action") - return parser.parse_args() + return parser.parse_args() # Note: misoclib need to be installed as a python library if __name__ == "__main__": - args = _get_args() - - # create top-level Core object - target_module = _import("targets", args.target) - if args.sub_target: - top_class = getattr(target_module, args.sub_target) - else: - top_class = target_module.default_subtarget - - if args.platform is None: - if hasattr(top_class, "default_platform"): - platform_name = top_class.default_platform - else: - raise ValueError("Target has no default platform, specify a platform with -p your_platform") - else: - platform_name = args.platform - platform_module = _import("mibuild.platforms", platform_name) - platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option) - platform = platform_module.Platform(**platform_kwargs) - - build_name = top_class.__name__.lower() + "-" + platform_name - top_kwargs = dict((k, autotype(v)) for k, v in args.target_option) - soc = top_class(platform, **top_kwargs) - soc.finalize() - memory_regions = soc.get_memory_regions() - csr_regions = soc.get_csr_regions() - - # decode actions - action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"] - actions = {k: False for k in action_list} - for action in args.action: - if action in actions: - actions[action] = True - else: - print("Unknown action: "+action+". Valid actions are:") - for a in action_list: - print(" "+a) - sys.exit(1) - - print(""" + args = _get_args() + + # create top-level Core object + target_module = _import("targets", args.target) + if args.sub_target: + top_class = getattr(target_module, args.sub_target) + else: + top_class = target_module.default_subtarget + + if args.platform is None: + if hasattr(top_class, "default_platform"): + platform_name = top_class.default_platform + else: + raise ValueError("Target has no default platform, specify a platform with -p your_platform") + else: + platform_name = args.platform + platform_module = _import("mibuild.platforms", platform_name) + platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option) + platform = platform_module.Platform(**platform_kwargs) + + build_name = top_class.__name__.lower() + "-" + platform_name + top_kwargs = dict((k, autotype(v)) for k, v in args.target_option) + soc = top_class(platform, **top_kwargs) + soc.finalize() + memory_regions = soc.get_memory_regions() + csr_regions = soc.get_csr_regions() + + # decode actions + action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"] + actions = {k: False for k in action_list} + for action in args.action: + if action in actions: + actions[action] = True + else: + print("Unknown action: "+action+". Valid actions are:") + for a in action_list: + print(" "+a) + sys.exit(1) + + print(""" __ _ __ ______ __ / / (_) /____ / __/ /_/ / / /__/ / __/ -_) _// __/ _ \\ @@ -101,37 +101,37 @@ Target: {} Subtarget: {} System Clk: {} MHz ===============================""".format( - platform_name, - args.target, - top_class.__name__, - soc.clk_freq/1000000 - ) + platform_name, + args.target, + top_class.__name__, + soc.clk_freq/1000000 + ) ) - # dependencies - if actions["all"]: - actions["build-csr-csv"] = True - actions["build-bitstream"] = True - actions["load-bitstream"] = True - - if actions["build-bitstream"]: - actions["build-csr-csv"] = True - actions["build-bitstream"] = True - actions["load-bitstream"] = True - - if actions["clean"]: - subprocess.call(["rm", "-rf", "build/*"]) - - if actions["build-csr-csv"]: - csr_csv = cpuif.get_csr_csv(csr_regions) - write_to_file(args.csr_csv, csr_csv) - - if actions["build-bitstream"]: - vns = platform.build(soc, build_name=build_name) - if hasattr(soc, "do_exit") and vns is not None: - if hasattr(soc.do_exit, '__call__'): - soc.do_exit(vns) - - if actions["load-bitstream"]: - prog = platform.create_programmer() - prog.load_bitstream("build/" + build_name + platform.bitstream_ext) + # dependencies + if actions["all"]: + actions["build-csr-csv"] = True + actions["build-bitstream"] = True + actions["load-bitstream"] = True + + if actions["build-bitstream"]: + actions["build-csr-csv"] = True + actions["build-bitstream"] = True + actions["load-bitstream"] = True + + if actions["clean"]: + subprocess.call(["rm", "-rf", "build/*"]) + + if actions["build-csr-csv"]: + csr_csv = cpuif.get_csr_csv(csr_regions) + write_to_file(args.csr_csv, csr_csv) + + if actions["build-bitstream"]: + vns = platform.build(soc, build_name=build_name) + if hasattr(soc, "do_exit") and vns is not None: + if hasattr(soc.do_exit, '__call__'): + soc.do_exit(vns) + + if actions["load-bitstream"]: + prog = platform.create_programmer() + prog.load_bitstream("build/" + build_name + platform.bitstream_ext) diff --git a/misoclib/com/liteeth/example_designs/targets/base.py b/misoclib/com/liteeth/example_designs/targets/base.py index f1d95dd7..1b32de0e 100644 --- a/misoclib/com/liteeth/example_designs/targets/base.py +++ b/misoclib/com/liteeth/example_designs/targets/base.py @@ -14,123 +14,123 @@ from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII from misoclib.com.liteeth.core import LiteEthUDPIPCore class BaseSoC(SoC, AutoCSR): - csr_map = { - "phy": 11, - "core": 12 - } - csr_map.update(SoC.csr_map) - def __init__(self, platform, clk_freq=166*1000000, - mac_address=0x10e2d5000000, - ip_address="192.168.0.42"): - clk_freq = int((1/(platform.default_clk_period))*1000000000) - SoC.__init__(self, platform, clk_freq, - cpu_type="none", - with_csr=True, csr_data_width=32, - with_uart=False, - with_identifier=True, - with_timer=False - ) - self.add_cpu_or_bridge(LiteScopeUART2WB(platform.request("serial"), clk_freq, baudrate=115200)) - self.add_wb_master(self.cpu_or_bridge.wishbone) - self.submodules.crg = CRG(platform.request(platform.default_clk_name)) - - # wishbone SRAM (to test Wishbone over UART and Etherbone) - self.submodules.sram = wishbone.SRAM(1024) - self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus) - - # ethernet PHY and UDP/IP stack - self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth")) - self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq) + csr_map = { + "phy": 11, + "core": 12 + } + csr_map.update(SoC.csr_map) + def __init__(self, platform, clk_freq=166*1000000, + mac_address=0x10e2d5000000, + ip_address="192.168.0.42"): + clk_freq = int((1/(platform.default_clk_period))*1000000000) + SoC.__init__(self, platform, clk_freq, + cpu_type="none", + with_csr=True, csr_data_width=32, + with_uart=False, + with_identifier=True, + with_timer=False + ) + self.add_cpu_or_bridge(LiteScopeUART2WB(platform.request("serial"), clk_freq, baudrate=115200)) + self.add_wb_master(self.cpu_or_bridge.wishbone) + self.submodules.crg = CRG(platform.request(platform.default_clk_name)) + + # wishbone SRAM (to test Wishbone over UART and Etherbone) + self.submodules.sram = wishbone.SRAM(1024) + self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus) + + # ethernet PHY and UDP/IP stack + self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth")) + self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq) class BaseSoCDevel(BaseSoC, AutoCSR): - csr_map = { - "la": 20 - } - csr_map.update(BaseSoC.csr_map) - def __init__(self, platform): - BaseSoC.__init__(self, platform) - - self.core_icmp_rx_fsm_state = Signal(4) - self.core_icmp_tx_fsm_state = Signal(4) - self.core_udp_rx_fsm_state = Signal(4) - self.core_udp_tx_fsm_state = Signal(4) - self.core_ip_rx_fsm_state = Signal(4) - self.core_ip_tx_fsm_state = Signal(4) - self.core_arp_rx_fsm_state = Signal(4) - self.core_arp_tx_fsm_state = Signal(4) - self.core_arp_table_fsm_state = Signal(4) - - debug = ( - # MAC interface - self.core.mac.core.sink.stb, - self.core.mac.core.sink.sop, - self.core.mac.core.sink.eop, - self.core.mac.core.sink.ack, - self.core.mac.core.sink.data, - - self.core.mac.core.source.stb, - self.core.mac.core.source.sop, - self.core.mac.core.source.eop, - self.core.mac.core.source.ack, - self.core.mac.core.source.data, - - # ICMP interface - self.core.icmp.echo.sink.stb, - self.core.icmp.echo.sink.sop, - self.core.icmp.echo.sink.eop, - self.core.icmp.echo.sink.ack, - self.core.icmp.echo.sink.data, - - self.core.icmp.echo.source.stb, - self.core.icmp.echo.source.sop, - self.core.icmp.echo.source.eop, - self.core.icmp.echo.source.ack, - self.core.icmp.echo.source.data, - - # IP interface - self.core.ip.crossbar.master.sink.stb, - self.core.ip.crossbar.master.sink.sop, - self.core.ip.crossbar.master.sink.eop, - self.core.ip.crossbar.master.sink.ack, - self.core.ip.crossbar.master.sink.data, - self.core.ip.crossbar.master.sink.ip_address, - self.core.ip.crossbar.master.sink.protocol, - - # State machines - self.core_icmp_rx_fsm_state, - self.core_icmp_tx_fsm_state, - - self.core_arp_rx_fsm_state, - self.core_arp_tx_fsm_state, - self.core_arp_table_fsm_state, - - self.core_ip_rx_fsm_state, - self.core_ip_tx_fsm_state, - - self.core_udp_rx_fsm_state, - self.core_udp_tx_fsm_state - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - - def do_finalize(self): - BaseSoC.do_finalize(self) - self.comb += [ - self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state), - self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state), - - self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state), - self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state), - self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state), - - self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state), - self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state), - - self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state), - self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state) - ] - - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") + csr_map = { + "la": 20 + } + csr_map.update(BaseSoC.csr_map) + def __init__(self, platform): + BaseSoC.__init__(self, platform) + + self.core_icmp_rx_fsm_state = Signal(4) + self.core_icmp_tx_fsm_state = Signal(4) + self.core_udp_rx_fsm_state = Signal(4) + self.core_udp_tx_fsm_state = Signal(4) + self.core_ip_rx_fsm_state = Signal(4) + self.core_ip_tx_fsm_state = Signal(4) + self.core_arp_rx_fsm_state = Signal(4) + self.core_arp_tx_fsm_state = Signal(4) + self.core_arp_table_fsm_state = Signal(4) + + debug = ( + # MAC interface + self.core.mac.core.sink.stb, + self.core.mac.core.sink.sop, + self.core.mac.core.sink.eop, + self.core.mac.core.sink.ack, + self.core.mac.core.sink.data, + + self.core.mac.core.source.stb, + self.core.mac.core.source.sop, + self.core.mac.core.source.eop, + self.core.mac.core.source.ack, + self.core.mac.core.source.data, + + # ICMP interface + self.core.icmp.echo.sink.stb, + self.core.icmp.echo.sink.sop, + self.core.icmp.echo.sink.eop, + self.core.icmp.echo.sink.ack, + self.core.icmp.echo.sink.data, + + self.core.icmp.echo.source.stb, + self.core.icmp.echo.source.sop, + self.core.icmp.echo.source.eop, + self.core.icmp.echo.source.ack, + self.core.icmp.echo.source.data, + + # IP interface + self.core.ip.crossbar.master.sink.stb, + self.core.ip.crossbar.master.sink.sop, + self.core.ip.crossbar.master.sink.eop, + self.core.ip.crossbar.master.sink.ack, + self.core.ip.crossbar.master.sink.data, + self.core.ip.crossbar.master.sink.ip_address, + self.core.ip.crossbar.master.sink.protocol, + + # State machines + self.core_icmp_rx_fsm_state, + self.core_icmp_tx_fsm_state, + + self.core_arp_rx_fsm_state, + self.core_arp_tx_fsm_state, + self.core_arp_table_fsm_state, + + self.core_ip_rx_fsm_state, + self.core_ip_tx_fsm_state, + + self.core_udp_rx_fsm_state, + self.core_udp_tx_fsm_state + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + + def do_finalize(self): + BaseSoC.do_finalize(self) + self.comb += [ + self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state), + self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state), + + self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state), + self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state), + self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state), + + self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state), + self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state), + + self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state), + self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state) + ] + + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") default_subtarget = BaseSoC diff --git a/misoclib/com/liteeth/example_designs/targets/etherbone.py b/misoclib/com/liteeth/example_designs/targets/etherbone.py index 9a9e9c5b..51f9cb9a 100644 --- a/misoclib/com/liteeth/example_designs/targets/etherbone.py +++ b/misoclib/com/liteeth/example_designs/targets/etherbone.py @@ -9,63 +9,63 @@ from targets.base import BaseSoC from misoclib.com.liteeth.core.etherbone import LiteEthEtherbone class EtherboneSoC(BaseSoC): - default_platform = "kc705" - def __init__(self, platform): - BaseSoC.__init__(self, platform, - mac_address=0x10e2d5000000, - ip_address="192.168.0.42") - self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) - self.add_wb_master(self.etherbone.master.bus) + default_platform = "kc705" + def __init__(self, platform): + BaseSoC.__init__(self, platform, + mac_address=0x10e2d5000000, + ip_address="192.168.0.42") + self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) + self.add_wb_master(self.etherbone.master.bus) class EtherboneSoCDevel(EtherboneSoC): - csr_map = { - "la": 20 - } - csr_map.update(EtherboneSoC.csr_map) - def __init__(self, platform): - EtherboneSoC.__init__(self, platform) - debug = ( - # mmap stream from HOST - self.etherbone.master.sink.stb, - self.etherbone.master.sink.sop, - self.etherbone.master.sink.eop, - self.etherbone.master.sink.ack, - self.etherbone.master.sink.we, - self.etherbone.master.sink.count, - self.etherbone.master.sink.base_addr, - self.etherbone.master.sink.be, - self.etherbone.master.sink.addr, - self.etherbone.master.sink.data, + csr_map = { + "la": 20 + } + csr_map.update(EtherboneSoC.csr_map) + def __init__(self, platform): + EtherboneSoC.__init__(self, platform) + debug = ( + # mmap stream from HOST + self.etherbone.master.sink.stb, + self.etherbone.master.sink.sop, + self.etherbone.master.sink.eop, + self.etherbone.master.sink.ack, + self.etherbone.master.sink.we, + self.etherbone.master.sink.count, + self.etherbone.master.sink.base_addr, + self.etherbone.master.sink.be, + self.etherbone.master.sink.addr, + self.etherbone.master.sink.data, - # mmap stream to HOST - self.etherbone.master.source.stb, - self.etherbone.master.source.sop, - self.etherbone.master.source.eop, - self.etherbone.master.source.ack, - self.etherbone.master.source.we, - self.etherbone.master.source.count, - self.etherbone.master.source.base_addr, - self.etherbone.master.source.be, - self.etherbone.master.source.addr, - self.etherbone.master.source.data, + # mmap stream to HOST + self.etherbone.master.source.stb, + self.etherbone.master.source.sop, + self.etherbone.master.source.eop, + self.etherbone.master.source.ack, + self.etherbone.master.source.we, + self.etherbone.master.source.count, + self.etherbone.master.source.base_addr, + self.etherbone.master.source.be, + self.etherbone.master.source.addr, + self.etherbone.master.source.data, - # etherbone wishbone master - self.etherbone.master.bus.dat_w, - self.etherbone.master.bus.dat_r, - self.etherbone.master.bus.adr, - self.etherbone.master.bus.sel, - self.etherbone.master.bus.cyc, - self.etherbone.master.bus.stb, - self.etherbone.master.bus.ack, - self.etherbone.master.bus.we, - self.etherbone.master.bus.cti, - self.etherbone.master.bus.bte, - self.etherbone.master.bus.err - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + # etherbone wishbone master + self.etherbone.master.bus.dat_w, + self.etherbone.master.bus.dat_r, + self.etherbone.master.bus.adr, + self.etherbone.master.bus.sel, + self.etherbone.master.bus.cyc, + self.etherbone.master.bus.stb, + self.etherbone.master.bus.ack, + self.etherbone.master.bus.we, + self.etherbone.master.bus.cti, + self.etherbone.master.bus.bte, + self.etherbone.master.bus.err + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") default_subtarget = EtherboneSoC diff --git a/misoclib/com/liteeth/example_designs/targets/tty.py b/misoclib/com/liteeth/example_designs/targets/tty.py index 2b69f052..a4a6f749 100644 --- a/misoclib/com/liteeth/example_designs/targets/tty.py +++ b/misoclib/com/liteeth/example_designs/targets/tty.py @@ -9,34 +9,34 @@ from targets.base import BaseSoC from misoclib.com.liteeth.core.tty import LiteEthTTY class TTYSoC(BaseSoC): - default_platform = "kc705" - def __init__(self, platform): - BaseSoC.__init__(self, platform, - mac_address=0x10e2d5000000, - ip_address="192.168.0.42") - self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.0.14"), 10000) - self.comb += Record.connect(self.tty.source, self.tty.sink) + default_platform = "kc705" + def __init__(self, platform): + BaseSoC.__init__(self, platform, + mac_address=0x10e2d5000000, + ip_address="192.168.0.42") + self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.0.14"), 10000) + self.comb += Record.connect(self.tty.source, self.tty.sink) class TTYSoCDevel(TTYSoC): - csr_map = { - "la": 20 - } - csr_map.update(TTYSoC.csr_map) - def __init__(self, platform): - TTYSoC.__init__(self, platform) - debug = ( - self.tty.sink.stb, - self.tty.sink.ack, - self.tty.sink.data, + csr_map = { + "la": 20 + } + csr_map.update(TTYSoC.csr_map) + def __init__(self, platform): + TTYSoC.__init__(self, platform) + debug = ( + self.tty.sink.stb, + self.tty.sink.ack, + self.tty.sink.data, - self.tty.source.stb, - self.tty.source.ack, - self.tty.source.data - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + self.tty.source.stb, + self.tty.source.ack, + self.tty.source.data + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") default_subtarget = TTYSoC diff --git a/misoclib/com/liteeth/example_designs/targets/udp.py b/misoclib/com/liteeth/example_designs/targets/udp.py index 46a124de..746f1151 100644 --- a/misoclib/com/liteeth/example_designs/targets/udp.py +++ b/misoclib/com/liteeth/example_designs/targets/udp.py @@ -8,62 +8,62 @@ from misoclib.com.liteeth.generic import * from targets.base import BaseSoC class UDPSoC(BaseSoC): - default_platform = "kc705" - def __init__(self, platform): - BaseSoC.__init__(self, platform, - mac_address=0x10e2d5000000, - ip_address="192.168.0.42") + default_platform = "kc705" + def __init__(self, platform): + BaseSoC.__init__(self, platform, + mac_address=0x10e2d5000000, + ip_address="192.168.0.42") - # add udp loopback on port 6000 with dw=8 - self.add_udp_loopback(6000, 8, 8192, "loopback_8") - # add udp loopback on port 8000 with dw=32 - self.add_udp_loopback(8000, 32, 8192, "loopback_32") + # add udp loopback on port 6000 with dw=8 + self.add_udp_loopback(6000, 8, 8192, "loopback_8") + # add udp loopback on port 8000 with dw=32 + self.add_udp_loopback(8000, 32, 8192, "loopback_32") - def add_udp_loopback(self, port, dw, depth, name=None): - port = self.core.udp.crossbar.get_port(port, dw) - buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8) - if name is None: - self.submodules += buf - else: - setattr(self.submodules, name, buf) - self.comb += Port.connect(port, buf) + def add_udp_loopback(self, port, dw, depth, name=None): + port = self.core.udp.crossbar.get_port(port, dw) + buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8) + if name is None: + self.submodules += buf + else: + setattr(self.submodules, name, buf) + self.comb += Port.connect(port, buf) class UDPSoCDevel(UDPSoC): - csr_map = { - "la": 20 - } - csr_map.update(UDPSoC.csr_map) - def __init__(self, platform): - UDPSoC.__init__(self, platform) - debug = ( - self.loopback_8.sink.stb, - self.loopback_8.sink.sop, - self.loopback_8.sink.eop, - self.loopback_8.sink.ack, - self.loopback_8.sink.data, + csr_map = { + "la": 20 + } + csr_map.update(UDPSoC.csr_map) + def __init__(self, platform): + UDPSoC.__init__(self, platform) + debug = ( + self.loopback_8.sink.stb, + self.loopback_8.sink.sop, + self.loopback_8.sink.eop, + self.loopback_8.sink.ack, + self.loopback_8.sink.data, - self.loopback_8.source.stb, - self.loopback_8.source.sop, - self.loopback_8.source.eop, - self.loopback_8.source.ack, - self.loopback_8.source.data, + self.loopback_8.source.stb, + self.loopback_8.source.sop, + self.loopback_8.source.eop, + self.loopback_8.source.ack, + self.loopback_8.source.data, - self.loopback_32.sink.stb, - self.loopback_32.sink.sop, - self.loopback_32.sink.eop, - self.loopback_32.sink.ack, - self.loopback_32.sink.data, + self.loopback_32.sink.stb, + self.loopback_32.sink.sop, + self.loopback_32.sink.eop, + self.loopback_32.sink.ack, + self.loopback_32.sink.data, - self.loopback_32.source.stb, - self.loopback_32.source.sop, - self.loopback_32.source.eop, - self.loopback_32.source.ack, - self.loopback_32.source.data - ) - self.submodules.la = LiteScopeLA(debug, 4096) - self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) + self.loopback_32.source.stb, + self.loopback_32.source.sop, + self.loopback_32.source.eop, + self.loopback_32.source.ack, + self.loopback_32.source.data + ) + self.submodules.la = LiteScopeLA(debug, 4096) + self.la.trigger.add_port(LiteScopeTerm(self.la.dw)) - def do_exit(self, vns): - self.la.export(vns, "test/la.csv") + def do_exit(self, vns): + self.la.export(vns, "test/la.csv") default_subtarget = UDPSoC diff --git a/misoclib/com/liteeth/example_designs/test/make.py b/misoclib/com/liteeth/example_designs/test/make.py index e0c78b28..1d3f2d9d 100644 --- a/misoclib/com/liteeth/example_designs/test/make.py +++ b/misoclib/com/liteeth/example_designs/test/make.py @@ -2,33 +2,33 @@ import argparse, importlib def _get_args(): - parser = argparse.ArgumentParser() - parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use") - parser.add_argument("--port", default="2", help="UART port") - parser.add_argument("--baudrate", default=115200, help="UART baudrate") - parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address") - parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port") - parser.add_argument("--busword", default=32, help="CSR busword") + parser = argparse.ArgumentParser() + parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use") + parser.add_argument("--port", default="2", help="UART port") + parser.add_argument("--baudrate", default=115200, help="UART baudrate") + parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address") + parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port") + parser.add_argument("--busword", default=32, help="CSR busword") - parser.add_argument("test", nargs="+", help="specify a test") + parser.add_argument("test", nargs="+", help="specify a test") - return parser.parse_args() + return parser.parse_args() if __name__ == "__main__": - args = _get_args() - if args.bridge == "uart": - from misoclib.tools.litescope.host.driver.uart import LiteScopeUARTDriver - port = args.port if not args.port.isdigit() else int(args.port) - wb = LiteScopeUARTDriver(port, args.baudrate, "./csr.csv", int(args.busword), debug=False) - elif args.bridge == "etherbone": - from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver - wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False) - else: - ValueError("Invalid bridge {}".format(args.bridge)) + args = _get_args() + if args.bridge == "uart": + from misoclib.tools.litescope.host.driver.uart import LiteScopeUARTDriver + port = args.port if not args.port.isdigit() else int(args.port) + wb = LiteScopeUARTDriver(port, args.baudrate, "./csr.csv", int(args.busword), debug=False) + elif args.bridge == "etherbone": + from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver + wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False) + else: + ValueError("Invalid bridge {}".format(args.bridge)) - def _import(name): - return importlib.import_module(name) + def _import(name): + return importlib.import_module(name) - for test in args.test: - t = _import(test) - t.main(wb) + for test in args.test: + t = _import(test) + t.main(wb) diff --git a/misoclib/com/liteeth/example_designs/test/test_etherbone.py b/misoclib/com/liteeth/example_designs/test/test_etherbone.py index d11bf496..715de265 100644 --- a/misoclib/com/liteeth/example_designs/test/test_etherbone.py +++ b/misoclib/com/liteeth/example_designs/test/test_etherbone.py @@ -6,55 +6,55 @@ SRAM_BASE = 0x02000000 import socket def main(wb): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - # test probe - packet = EtherbonePacket() - packet.pf = 1 - packet.encode() - sock.sendto(bytes(packet), ("192.168.0.42", 20000)) - time.sleep(0.01) - - # test writes - writes_datas = [j for j in range(16)] - writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas) - record = EtherboneRecord() - record.writes = writes - record.reads = None - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0xf - record.wcount = len(writes_datas) - record.rcount = 0 - - packet = EtherbonePacket() - packet.records = [record] - packet.encode() - sock.sendto(bytes(packet), ("192.168.0.42", 20000)) - time.sleep(0.01) - - # test reads - reads_addrs = [SRAM_BASE+4*j for j in range(16)] - reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs) - record = EtherboneRecord() - record.writes = None - record.reads = reads - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0xf - record.wcount = 0 - record.rcount = len(reads_addrs) - - packet = EtherbonePacket() - packet.records = [record] - packet.encode() - sock.sendto(bytes(packet), ("192.168.0.42", 20000)) - time.sleep(0.01) + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + # test probe + packet = EtherbonePacket() + packet.pf = 1 + packet.encode() + sock.sendto(bytes(packet), ("192.168.0.42", 20000)) + time.sleep(0.01) + + # test writes + writes_datas = [j for j in range(16)] + writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas) + record = EtherboneRecord() + record.writes = writes + record.reads = None + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0xf + record.wcount = len(writes_datas) + record.rcount = 0 + + packet = EtherbonePacket() + packet.records = [record] + packet.encode() + sock.sendto(bytes(packet), ("192.168.0.42", 20000)) + time.sleep(0.01) + + # test reads + reads_addrs = [SRAM_BASE+4*j for j in range(16)] + reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs) + record = EtherboneRecord() + record.writes = None + record.reads = reads + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0xf + record.wcount = 0 + record.rcount = len(reads_addrs) + + packet = EtherbonePacket() + packet.records = [record] + packet.encode() + sock.sendto(bytes(packet), ("192.168.0.42", 20000)) + time.sleep(0.01) diff --git a/misoclib/com/liteeth/example_designs/test/test_la.py b/misoclib/com/liteeth/example_designs/test/test_la.py index 21faec4b..45686bba 100644 --- a/misoclib/com/liteeth/example_designs/test/test_la.py +++ b/misoclib/com/liteeth/example_designs/test/test_la.py @@ -2,23 +2,23 @@ import time from misoclib.tools.litescope.host.driver.la import LiteScopeLADriver def main(wb): - la = LiteScopeLADriver(wb.regs, "la", debug=True) + la = LiteScopeLADriver(wb.regs, "la", debug=True) - wb.open() - regs = wb.regs - ### + wb.open() + regs = wb.regs + ### - conditions = {} - la.configure_term(port=0, cond=conditions) - la.configure_sum("term") - # Run Logic Analyzer - la.run(offset=2048, length=4000) + conditions = {} + la.configure_term(port=0, cond=conditions) + la.configure_sum("term") + # Run Logic Analyzer + la.run(offset=2048, length=4000) - while not la.done(): - pass + while not la.done(): + pass - la.upload() - la.save("dump.vcd") + la.upload() + la.save("dump.vcd") - ### - wb.close() + ### + wb.close() diff --git a/misoclib/com/liteeth/example_designs/test/test_regs.py b/misoclib/com/liteeth/example_designs/test/test_regs.py index ea8767ac..0050fcaa 100644 --- a/misoclib/com/liteeth/example_designs/test/test_regs.py +++ b/misoclib/com/liteeth/example_designs/test/test_regs.py @@ -1,12 +1,12 @@ def main(wb): - wb.open() - regs = wb.regs - ### - print("sysid : 0x{:04x}".format(regs.identifier_sysid.read())) - print("revision : 0x{:04x}".format(regs.identifier_revision.read())) - print("frequency : {}MHz".format(int(regs.identifier_frequency.read()/1000000))) - SRAM_BASE = 0x02000000 - wb.write(SRAM_BASE, [i for i in range(64)]) - print(wb.read(SRAM_BASE, 64)) - ### - wb.close() + wb.open() + regs = wb.regs + ### + print("sysid : 0x{:04x}".format(regs.identifier_sysid.read())) + print("revision : 0x{:04x}".format(regs.identifier_revision.read())) + print("frequency : {}MHz".format(int(regs.identifier_frequency.read()/1000000))) + SRAM_BASE = 0x02000000 + wb.write(SRAM_BASE, [i for i in range(64)]) + print(wb.read(SRAM_BASE, 64)) + ### + wb.close() diff --git a/misoclib/com/liteeth/example_designs/test/test_tty.py b/misoclib/com/liteeth/example_designs/test/test_tty.py index 88f31bdc..a2a7aa92 100644 --- a/misoclib/com/liteeth/example_designs/test/test_tty.py +++ b/misoclib/com/liteeth/example_designs/test/test_tty.py @@ -2,35 +2,35 @@ import socket import threading def test(fpga_ip, udp_port, test_message): - tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock.bind(("", udp_port)) - rx_sock.settimeout(0.5) + tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock.bind(("", udp_port)) + rx_sock.settimeout(0.5) - def receive(): - while True: - try: - msg = rx_sock.recv(8192) - for byte in msg: - print(chr(byte), end="") - except: - break + def receive(): + while True: + try: + msg = rx_sock.recv(8192) + for byte in msg: + print(chr(byte), end="") + except: + break - def send(): - tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port)) + def send(): + tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port)) - receive_thread = threading.Thread(target=receive) - receive_thread.start() + receive_thread = threading.Thread(target=receive) + receive_thread.start() - send_thread = threading.Thread(target=send) - send_thread.start() + send_thread = threading.Thread(target=send) + send_thread.start() - try: - send_thread.join(5) - send_thread.join(5) - except KeyboardInterrupt: - pass + try: + send_thread.join(5) + send_thread.join(5) + except KeyboardInterrupt: + pass def main(wb): - test_message = "LiteEth virtual TTY Hello world\n" - test("192.168.0.42", 10000, test_message) + test_message = "LiteEth virtual TTY Hello world\n" + test("192.168.0.42", 10000, test_message) diff --git a/misoclib/com/liteeth/example_designs/test/test_udp.py b/misoclib/com/liteeth/example_designs/test/test_udp.py index 1f56a275..68e62c07 100644 --- a/misoclib/com/liteeth/example_designs/test/test_udp.py +++ b/misoclib/com/liteeth/example_designs/test/test_udp.py @@ -8,74 +8,74 @@ MB = 1024*KB GB = 1024*MB def seed_to_data(seed, random=True): - if random: - return (seed * 0x31415979 + 1) & 0xffffffff - else: - return seed + if random: + return (seed * 0x31415979 + 1) & 0xffffffff + else: + return seed def check(p1, p2): - p1 = copy.deepcopy(p1) - p2 = copy.deepcopy(p2) - if isinstance(p1, int): - return 0, 1, int(p1 != p2) - else: - if len(p1) >= len(p2): - ref, res = p1, p2 - else: - ref, res = p2, p1 - shift = 0 - while((ref[0] != res[0]) and (len(res)>1)): - res.pop(0) - shift += 1 - length = min(len(ref), len(res)) - errors = 0 - for i in range(length): - if ref.pop(0) != res.pop(0): - errors += 1 - return shift, length, errors + p1 = copy.deepcopy(p1) + p2 = copy.deepcopy(p2) + if isinstance(p1, int): + return 0, 1, int(p1 != p2) + else: + if len(p1) >= len(p2): + ref, res = p1, p2 + else: + ref, res = p2, p1 + shift = 0 + while((ref[0] != res[0]) and (len(res)>1)): + res.pop(0) + shift += 1 + length = min(len(ref), len(res)) + errors = 0 + for i in range(length): + if ref.pop(0) != res.pop(0): + errors += 1 + return shift, length, errors def generate_packet(seed, length): - r = [] - for i in range(length): - r.append(seed_to_data(seed, True)%0xff) # XXX FIXME - seed += 1 - return r, seed + r = [] + for i in range(length): + r.append(seed_to_data(seed, True)%0xff) # XXX FIXME + seed += 1 + return r, seed def test(fpga_ip, udp_port, test_size): - tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - rx_sock.bind(("", udp_port)) + tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + rx_sock.bind(("", udp_port)) - def receive(): - rx_seed = 0 - while rx_seed < test_size: - data, addr = rx_sock.recvfrom(8192) - rx_packet = [] - for byte in data: - rx_packet.append(int(byte)) - rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024) - s, l, e = check(rx_reference_packet, rx_packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + def receive(): + rx_seed = 0 + while rx_seed < test_size: + data, addr = rx_sock.recvfrom(8192) + rx_packet = [] + for byte in data: + rx_packet.append(int(byte)) + rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024) + s, l, e = check(rx_reference_packet, rx_packet) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) - def send(): - tx_seed = 0 - while tx_seed < test_size: - tx_packet, tx_seed = generate_packet(tx_seed, 1024) - tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port)) - time.sleep(0.001) # XXX: FIXME, Python limitation? + def send(): + tx_seed = 0 + while tx_seed < test_size: + tx_packet, tx_seed = generate_packet(tx_seed, 1024) + tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port)) + time.sleep(0.001) # XXX: FIXME, Python limitation? - receive_thread = threading.Thread(target=receive) - receive_thread.start() + receive_thread = threading.Thread(target=receive) + receive_thread.start() - send_thread = threading.Thread(target=send) - send_thread.start() + send_thread = threading.Thread(target=send) + send_thread.start() - try: - send_thread.join(10) - receive_thread.join(0.1) - except KeyboardInterrupt: - pass + try: + send_thread.join(10) + receive_thread.join(0.1) + except KeyboardInterrupt: + pass def main(wb): - test("192.168.0.42", 6000, 128*KB) - test("192.168.0.42", 8000, 128*KB) + test("192.168.0.42", 6000, 128*KB) + test("192.168.0.42", 8000, 128*KB) diff --git a/misoclib/com/liteeth/generic/__init__.py b/misoclib/com/liteeth/generic/__init__.py index d7049a99..cebfe76b 100644 --- a/misoclib/com/liteeth/generic/__init__.py +++ b/misoclib/com/liteeth/generic/__init__.py @@ -3,122 +3,122 @@ from misoclib.com.liteeth.common import * # Generic classes class Port: - def connect(self, port): - r = [ - Record.connect(self.source, port.sink), - Record.connect(port.source, self.sink) - ] - return r + def connect(self, port): + r = [ + Record.connect(self.source, port.sink), + Record.connect(port.source, self.sink) + ] + return r # Generic modules class BufferizeEndpoints(ModuleTransformer): - def __init__(self, *names): - self.names = names + def __init__(self, *names): + self.names = names - def transform_instance(self, submodule): - endpoints = get_endpoints(submodule) - sinks = {} - sources = {} - for name, endpoint in endpoints.items(): - if not self.names or name in self.names: - if isinstance(endpoint, Sink): - sinks.update({name : endpoint}) - elif isinstance(endpoint, Source): - sources.update({name : endpoint}) + def transform_instance(self, submodule): + endpoints = get_endpoints(submodule) + sinks = {} + sources = {} + for name, endpoint in endpoints.items(): + if not self.names or name in self.names: + if isinstance(endpoint, Sink): + sinks.update({name : endpoint}) + elif isinstance(endpoint, Source): + sources.update({name : endpoint}) - # add buffer on sinks - for name, sink in sinks.items(): - buf = Buffer(sink.description) - submodule.submodules += buf - setattr(self, name, buf.d) - submodule.comb += Record.connect(buf.q, sink) + # add buffer on sinks + for name, sink in sinks.items(): + buf = Buffer(sink.description) + submodule.submodules += buf + setattr(self, name, buf.d) + submodule.comb += Record.connect(buf.q, sink) - # add buffer on sources - for name, source in sources.items(): - buf = Buffer(source.description) - submodule.submodules += buf - submodule.comb += Record.connect(source, buf.d) - setattr(self, name, buf.q) + # add buffer on sources + for name, source in sources.items(): + buf = Buffer(source.description) + submodule.submodules += buf + submodule.comb += Record.connect(source, buf.d) + setattr(self, name, buf.q) class EndpointPacketStatus(Module): - def __init__(self, endpoint): - self.start = Signal() - self.done = Signal() - self.ongoing = Signal() + def __init__(self, endpoint): + self.start = Signal() + self.done = Signal() + self.ongoing = Signal() - ongoing = Signal() - self.comb += [ - self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack), - self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack) - ] - self.sync += \ - If(self.start, - ongoing.eq(1) - ).Elif(self.done, - ongoing.eq(0) - ) - self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done) + ongoing = Signal() + self.comb += [ + self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack), + self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack) + ] + self.sync += \ + If(self.start, + ongoing.eq(1) + ).Elif(self.done, + ongoing.eq(0) + ) + self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done) class PacketBuffer(Module): - def __init__(self, description, data_depth, cmd_depth=4, almost_full=None): - self.sink = sink = Sink(description) - self.source = source = Source(description) + def __init__(self, description, data_depth, cmd_depth=4, almost_full=None): + self.sink = sink = Sink(description) + self.source = source = Source(description) - ### - sink_status = EndpointPacketStatus(self.sink) - source_status = EndpointPacketStatus(self.source) - self.submodules += sink_status, source_status + ### + sink_status = EndpointPacketStatus(self.sink) + source_status = EndpointPacketStatus(self.source) + self.submodules += sink_status, source_status - # store incoming packets - # cmds - def cmd_description(): - layout = [("error", 1)] - return EndpointDescription(layout) - cmd_fifo = SyncFIFO(cmd_description(), cmd_depth) - self.submodules += cmd_fifo - self.comb += cmd_fifo.sink.stb.eq(sink_status.done) - if hasattr(sink, "error"): - self.comb += cmd_fifo.sink.error.eq(sink.error) + # store incoming packets + # cmds + def cmd_description(): + layout = [("error", 1)] + return EndpointDescription(layout) + cmd_fifo = SyncFIFO(cmd_description(), cmd_depth) + self.submodules += cmd_fifo + self.comb += cmd_fifo.sink.stb.eq(sink_status.done) + if hasattr(sink, "error"): + self.comb += cmd_fifo.sink.error.eq(sink.error) - # data - data_fifo = SyncFIFO(description, data_depth, buffered=True) - self.submodules += data_fifo - self.comb += [ - Record.connect(self.sink, data_fifo.sink), - data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack), - self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack), - ] + # data + data_fifo = SyncFIFO(description, data_depth, buffered=True) + self.submodules += data_fifo + self.comb += [ + Record.connect(self.sink, data_fifo.sink), + data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack), + self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack), + ] - # output packets - self.fsm = fsm = FSM(reset_state="IDLE") - self.submodules += fsm - fsm.act("IDLE", - If(cmd_fifo.source.stb, - NextState("SEEK_SOP") - ) - ) - fsm.act("SEEK_SOP", - If(~data_fifo.source.sop, - data_fifo.source.ack.eq(1) - ).Else( - NextState("OUTPUT") - ) - ) - if hasattr(source, "error"): - source_error = self.source.error - else: - source_error = Signal() + # output packets + self.fsm = fsm = FSM(reset_state="IDLE") + self.submodules += fsm + fsm.act("IDLE", + If(cmd_fifo.source.stb, + NextState("SEEK_SOP") + ) + ) + fsm.act("SEEK_SOP", + If(~data_fifo.source.sop, + data_fifo.source.ack.eq(1) + ).Else( + NextState("OUTPUT") + ) + ) + if hasattr(source, "error"): + source_error = self.source.error + else: + source_error = Signal() - fsm.act("OUTPUT", - Record.connect(data_fifo.source, self.source), - source_error.eq(cmd_fifo.source.error), - If(source_status.done, - cmd_fifo.source.ack.eq(1), - NextState("IDLE") - ) - ) + fsm.act("OUTPUT", + Record.connect(data_fifo.source, self.source), + source_error.eq(cmd_fifo.source.error), + If(source_status.done, + cmd_fifo.source.ack.eq(1), + NextState("IDLE") + ) + ) - # compute almost full - if almost_full is not None: - self.almost_full = Signal() - self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full) + # compute almost full + if almost_full is not None: + self.almost_full = Signal() + self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full) diff --git a/misoclib/com/liteeth/generic/arbiter.py b/misoclib/com/liteeth/generic/arbiter.py index ca77377e..07200a93 100644 --- a/misoclib/com/liteeth/generic/arbiter.py +++ b/misoclib/com/liteeth/generic/arbiter.py @@ -3,25 +3,25 @@ from migen.genlib.roundrobin import * from migen.genlib.record import * class Arbiter(Module): - def __init__(self, sources, sink): - if len(sources) == 0: - pass - elif len(sources) == 1: - self.grant = Signal() - self.comb += Record.connect(sources.pop(), sink) - else: - self.submodules.rr = RoundRobin(len(sources)) - self.grant = self.rr.grant - cases = {} - for i, source in enumerate(sources): - sop = Signal() - eop = Signal() - ongoing = Signal() - self.comb += [ - sop.eq(source.stb & source.sop), - eop.eq(source.stb & source.eop & source.ack), - ] - self.sync += ongoing.eq((sop | ongoing) & ~eop) - self.comb += self.rr.request[i].eq((sop | ongoing) & ~eop) - cases[i] = [Record.connect(source, sink)] - self.comb += Case(self.grant, cases) + def __init__(self, sources, sink): + if len(sources) == 0: + pass + elif len(sources) == 1: + self.grant = Signal() + self.comb += Record.connect(sources.pop(), sink) + else: + self.submodules.rr = RoundRobin(len(sources)) + self.grant = self.rr.grant + cases = {} + for i, source in enumerate(sources): + sop = Signal() + eop = Signal() + ongoing = Signal() + self.comb += [ + sop.eq(source.stb & source.sop), + eop.eq(source.stb & source.eop & source.ack), + ] + self.sync += ongoing.eq((sop | ongoing) & ~eop) + self.comb += self.rr.request[i].eq((sop | ongoing) & ~eop) + cases[i] = [Record.connect(source, sink)] + self.comb += Case(self.grant, cases) diff --git a/misoclib/com/liteeth/generic/crossbar.py b/misoclib/com/liteeth/generic/crossbar.py index a443eb7f..67268b41 100644 --- a/misoclib/com/liteeth/generic/crossbar.py +++ b/misoclib/com/liteeth/generic/crossbar.py @@ -6,26 +6,26 @@ from misoclib.com.liteeth.generic.arbiter import Arbiter from misoclib.com.liteeth.generic.dispatcher import Dispatcher class LiteEthCrossbar(Module): - def __init__(self, master_port, dispatch_param): - self.users = OrderedDict() - self.master = master_port(8) - self.dispatch_param = dispatch_param + def __init__(self, master_port, dispatch_param): + self.users = OrderedDict() + self.master = master_port(8) + self.dispatch_param = dispatch_param - # overload this in derived classes - def get_port(self, *args, **kwargs): - pass + # overload this in derived classes + def get_port(self, *args, **kwargs): + pass - def do_finalize(self): - # TX arbitrate - sinks = [port.sink for port in self.users.values()] - self.submodules.arbiter = Arbiter(sinks, self.master.source) + def do_finalize(self): + # TX arbitrate + sinks = [port.sink for port in self.users.values()] + self.submodules.arbiter = Arbiter(sinks, self.master.source) - # RX dispatch - sources = [port.source for port in self.users.values()] - self.submodules.dispatcher = Dispatcher(self.master.sink, sources, one_hot=True) - cases = {} - cases["default"] = self.dispatcher.sel.eq(0) - for i, (k, v) in enumerate(self.users.items()): - cases[k] = self.dispatcher.sel.eq(2**i) - self.comb += \ - Case(getattr(self.master.sink, self.dispatch_param), cases) + # RX dispatch + sources = [port.source for port in self.users.values()] + self.submodules.dispatcher = Dispatcher(self.master.sink, sources, one_hot=True) + cases = {} + cases["default"] = self.dispatcher.sel.eq(0) + for i, (k, v) in enumerate(self.users.items()): + cases[k] = self.dispatcher.sel.eq(2**i) + self.comb += \ + Case(getattr(self.master.sink, self.dispatch_param), cases) diff --git a/misoclib/com/liteeth/generic/depacketizer.py b/misoclib/com/liteeth/generic/depacketizer.py index cb7d4430..2a0dc5eb 100644 --- a/misoclib/com/liteeth/generic/depacketizer.py +++ b/misoclib/com/liteeth/generic/depacketizer.py @@ -2,83 +2,83 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * def _decode_header(h_dict, h_signal, obj): - r = [] - for k, v in sorted(h_dict.items()): - start = v.byte*8+v.offset - end = start+v.width - r.append(getattr(obj, k).eq(reverse_bytes(h_signal[start:end]))) - return r + r = [] + for k, v in sorted(h_dict.items()): + start = v.byte*8+v.offset + end = start+v.width + r.append(getattr(obj, k).eq(reverse_bytes(h_signal[start:end]))) + return r class LiteEthDepacketizer(Module): - def __init__(self, sink_description, source_description, header_type, header_length): - self.sink = sink = Sink(sink_description) - self.source = source = Source(source_description) - self.header = Signal(header_length*8) - ### - dw = flen(sink.data) + def __init__(self, sink_description, source_description, header_type, header_length): + self.sink = sink = Sink(sink_description) + self.source = source = Source(source_description) + self.header = Signal(header_length*8) + ### + dw = flen(sink.data) - header_words = (header_length*8)//dw + header_words = (header_length*8)//dw - shift = Signal() - counter = Counter(max=max(header_words, 2)) - self.submodules += counter + shift = Signal() + counter = Counter(max=max(header_words, 2)) + self.submodules += counter - if header_words == 1: - self.sync += \ - If(shift, - self.header.eq(sink.data) - ) - else: - self.sync += \ - If(shift, - self.header.eq(Cat(self.header[dw:], sink.data)) - ) + if header_words == 1: + self.sync += \ + If(shift, + self.header.eq(sink.data) + ) + else: + self.sync += \ + If(shift, + self.header.eq(Cat(self.header[dw:], sink.data)) + ) - fsm = FSM(reset_state="IDLE") - self.submodules += fsm + fsm = FSM(reset_state="IDLE") + self.submodules += fsm - if header_words == 1: - idle_next_state = "COPY" - else: - idle_next_state = "RECEIVE_HEADER" + if header_words == 1: + idle_next_state = "COPY" + else: + idle_next_state = "RECEIVE_HEADER" - fsm.act("IDLE", - sink.ack.eq(1), - counter.reset.eq(1), - If(sink.stb, - shift.eq(1), - NextState(idle_next_state) - ) - ) - if header_words != 1: - fsm.act("RECEIVE_HEADER", - sink.ack.eq(1), - If(sink.stb, - counter.ce.eq(1), - shift.eq(1), - If(counter.value == header_words-2, - NextState("COPY") - ) - ) - ) - no_payload = Signal() - self.sync += \ - If(fsm.before_entering("COPY"), - source.sop.eq(1), - no_payload.eq(sink.eop) - ).Elif(source.stb & source.ack, - source.sop.eq(0) - ) - self.comb += [ - source.eop.eq(sink.eop | no_payload), - source.data.eq(sink.data), - source.error.eq(sink.error), - _decode_header(header_type, self.header, source) - ] - fsm.act("COPY", - sink.ack.eq(source.ack), - source.stb.eq(sink.stb | no_payload), - If(source.stb & source.ack & source.eop, - NextState("IDLE") - ) - ) + fsm.act("IDLE", + sink.ack.eq(1), + counter.reset.eq(1), + If(sink.stb, + shift.eq(1), + NextState(idle_next_state) + ) + ) + if header_words != 1: + fsm.act("RECEIVE_HEADER", + sink.ack.eq(1), + If(sink.stb, + counter.ce.eq(1), + shift.eq(1), + If(counter.value == header_words-2, + NextState("COPY") + ) + ) + ) + no_payload = Signal() + self.sync += \ + If(fsm.before_entering("COPY"), + source.sop.eq(1), + no_payload.eq(sink.eop) + ).Elif(source.stb & source.ack, + source.sop.eq(0) + ) + self.comb += [ + source.eop.eq(sink.eop | no_payload), + source.data.eq(sink.data), + source.error.eq(sink.error), + _decode_header(header_type, self.header, source) + ] + fsm.act("COPY", + sink.ack.eq(source.ack), + source.stb.eq(sink.stb | no_payload), + If(source.stb & source.ack & source.eop, + NextState("IDLE") + ) + ) diff --git a/misoclib/com/liteeth/generic/dispatcher.py b/misoclib/com/liteeth/generic/dispatcher.py index 3acb9f90..a822bded 100644 --- a/misoclib/com/liteeth/generic/dispatcher.py +++ b/misoclib/com/liteeth/generic/dispatcher.py @@ -2,38 +2,38 @@ from migen.fhdl.std import * from migen.genlib.record import * class Dispatcher(Module): - def __init__(self, source, sinks, one_hot=False): - if len(sinks) == 0: - self.sel = Signal() - elif len(sinks) == 1: - self.comb += Record.connect(source, sinks.pop()) - self.sel = Signal() - else: - if one_hot: - self.sel = Signal(len(sinks)) - else: - self.sel = Signal(max=len(sinks)) - ### - sop = Signal() - self.comb += sop.eq(source.stb & source.sop) - sel = Signal(flen(self.sel)) - sel_r = Signal(flen(self.sel)) - self.sync += \ - If(sop, - sel_r.eq(self.sel) - ) - self.comb += \ - If(sop, - sel.eq(self.sel) - ).Else( - sel.eq(sel_r) - ) - cases = {} - for i, sink in enumerate(sinks): - if one_hot: - idx = 2**i - else: - idx = i - cases[idx] = [Record.connect(source, sink)] - cases["default"] = [source.ack.eq(1)] - self.comb += Case(sel, cases) + def __init__(self, source, sinks, one_hot=False): + if len(sinks) == 0: + self.sel = Signal() + elif len(sinks) == 1: + self.comb += Record.connect(source, sinks.pop()) + self.sel = Signal() + else: + if one_hot: + self.sel = Signal(len(sinks)) + else: + self.sel = Signal(max=len(sinks)) + ### + sop = Signal() + self.comb += sop.eq(source.stb & source.sop) + sel = Signal(flen(self.sel)) + sel_r = Signal(flen(self.sel)) + self.sync += \ + If(sop, + sel_r.eq(self.sel) + ) + self.comb += \ + If(sop, + sel.eq(self.sel) + ).Else( + sel.eq(sel_r) + ) + cases = {} + for i, sink in enumerate(sinks): + if one_hot: + idx = 2**i + else: + idx = i + cases[idx] = [Record.connect(source, sink)] + cases["default"] = [source.ack.eq(1)] + self.comb += Case(sel, cases) diff --git a/misoclib/com/liteeth/generic/packetizer.py b/misoclib/com/liteeth/generic/packetizer.py index 91b7202a..7412d965 100644 --- a/misoclib/com/liteeth/generic/packetizer.py +++ b/misoclib/com/liteeth/generic/packetizer.py @@ -2,91 +2,91 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * def _encode_header(h_dict, h_signal, obj): - r = [] - for k, v in sorted(h_dict.items()): - start = v.byte*8+v.offset - end = start+v.width - r.append(h_signal[start:end].eq(reverse_bytes(getattr(obj, k)))) - return r + r = [] + for k, v in sorted(h_dict.items()): + start = v.byte*8+v.offset + end = start+v.width + r.append(h_signal[start:end].eq(reverse_bytes(getattr(obj, k)))) + return r class LiteEthPacketizer(Module): - def __init__(self, sink_description, source_description, header_type, header_length): - self.sink = sink = Sink(sink_description) - self.source = source = Source(source_description) - self.header = Signal(header_length*8) - ### - dw = flen(self.sink.data) + def __init__(self, sink_description, source_description, header_type, header_length): + self.sink = sink = Sink(sink_description) + self.source = source = Source(source_description) + self.header = Signal(header_length*8) + ### + dw = flen(self.sink.data) - header_reg = Signal(header_length*8) - header_words = (header_length*8)//dw - load = Signal() - shift = Signal() - counter = Counter(max=max(header_words, 2)) - self.submodules += counter + header_reg = Signal(header_length*8) + header_words = (header_length*8)//dw + load = Signal() + shift = Signal() + counter = Counter(max=max(header_words, 2)) + self.submodules += counter - self.comb += _encode_header(header_type, self.header, sink) - if header_words == 1: - self.sync += [ - If(load, - header_reg.eq(self.header) - ) - ] - else: - self.sync += [ - If(load, - header_reg.eq(self.header) - ).Elif(shift, - header_reg.eq(Cat(header_reg[dw:], Signal(dw))) - ) - ] + self.comb += _encode_header(header_type, self.header, sink) + if header_words == 1: + self.sync += [ + If(load, + header_reg.eq(self.header) + ) + ] + else: + self.sync += [ + If(load, + header_reg.eq(self.header) + ).Elif(shift, + header_reg.eq(Cat(header_reg[dw:], Signal(dw))) + ) + ] - fsm = FSM(reset_state="IDLE") - self.submodules += fsm + fsm = FSM(reset_state="IDLE") + self.submodules += fsm - if header_words == 1: - idle_next_state = "COPY" - else: - idle_next_state = "SEND_HEADER" + if header_words == 1: + idle_next_state = "COPY" + else: + idle_next_state = "SEND_HEADER" - fsm.act("IDLE", - sink.ack.eq(1), - counter.reset.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - source.stb.eq(1), - source.sop.eq(1), - source.eop.eq(0), - source.data.eq(self.header[:dw]), - If(source.stb & source.ack, - load.eq(1), - NextState(idle_next_state) - ) - ) - ) - if header_words != 1: - fsm.act("SEND_HEADER", - source.stb.eq(1), - source.sop.eq(0), - source.eop.eq(0), - source.data.eq(header_reg[dw:2*dw]), - If(source.stb & source.ack, - shift.eq(1), - counter.ce.eq(1), - If(counter.value == header_words-2, - NextState("COPY") - ) - ) - ) - fsm.act("COPY", - source.stb.eq(sink.stb), - source.sop.eq(0), - source.eop.eq(sink.eop), - source.data.eq(sink.data), - source.error.eq(sink.error), - If(source.stb & source.ack, - sink.ack.eq(1), - If(source.eop, - NextState("IDLE") - ) - ) - ) + fsm.act("IDLE", + sink.ack.eq(1), + counter.reset.eq(1), + If(sink.stb & sink.sop, + sink.ack.eq(0), + source.stb.eq(1), + source.sop.eq(1), + source.eop.eq(0), + source.data.eq(self.header[:dw]), + If(source.stb & source.ack, + load.eq(1), + NextState(idle_next_state) + ) + ) + ) + if header_words != 1: + fsm.act("SEND_HEADER", + source.stb.eq(1), + source.sop.eq(0), + source.eop.eq(0), + source.data.eq(header_reg[dw:2*dw]), + If(source.stb & source.ack, + shift.eq(1), + counter.ce.eq(1), + If(counter.value == header_words-2, + NextState("COPY") + ) + ) + ) + fsm.act("COPY", + source.stb.eq(sink.stb), + source.sop.eq(0), + source.eop.eq(sink.eop), + source.data.eq(sink.data), + source.error.eq(sink.error), + If(source.stb & source.ack, + sink.ack.eq(1), + If(source.eop, + NextState("IDLE") + ) + ) + ) diff --git a/misoclib/com/liteeth/mac/__init__.py b/misoclib/com/liteeth/mac/__init__.py index 0ffe3009..9ac65314 100644 --- a/misoclib/com/liteeth/mac/__init__.py +++ b/misoclib/com/liteeth/mac/__init__.py @@ -5,29 +5,29 @@ from misoclib.com.liteeth.mac.core import LiteEthMACCore from misoclib.com.liteeth.mac.frontend.wishbone import LiteEthMACWishboneInterface class LiteEthMAC(Module, AutoCSR): - def __init__(self, phy, dw, interface="crossbar", endianness="big", - with_hw_preamble_crc=True): - self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_hw_preamble_crc) - self.csrs = [] - if interface == "crossbar": - self.submodules.crossbar = LiteEthMACCrossbar() - self.submodules.packetizer = LiteEthMACPacketizer() - self.submodules.depacketizer = LiteEthMACDepacketizer() - self.comb += [ - Record.connect(self.crossbar.master.source, self.packetizer.sink), - Record.connect(self.packetizer.source, self.core.sink), - Record.connect(self.core.source, self.depacketizer.sink), - Record.connect(self.depacketizer.source, self.crossbar.master.sink) - ] - elif interface == "wishbone": - self.submodules.interface = LiteEthMACWishboneInterface(dw, 2, 2) - self.comb += Port.connect(self.interface, self.core) - self.ev, self.bus = self.interface.sram.ev, self.interface.bus - self.csrs = self.interface.get_csrs() + self.core.get_csrs() - elif interface == "dma": - raise NotImplementedError - else: - raise ValueError(interface + " not supported by LiteEthMac!") + def __init__(self, phy, dw, interface="crossbar", endianness="big", + with_hw_preamble_crc=True): + self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_hw_preamble_crc) + self.csrs = [] + if interface == "crossbar": + self.submodules.crossbar = LiteEthMACCrossbar() + self.submodules.packetizer = LiteEthMACPacketizer() + self.submodules.depacketizer = LiteEthMACDepacketizer() + self.comb += [ + Record.connect(self.crossbar.master.source, self.packetizer.sink), + Record.connect(self.packetizer.source, self.core.sink), + Record.connect(self.core.source, self.depacketizer.sink), + Record.connect(self.depacketizer.source, self.crossbar.master.sink) + ] + elif interface == "wishbone": + self.submodules.interface = LiteEthMACWishboneInterface(dw, 2, 2) + self.comb += Port.connect(self.interface, self.core) + self.ev, self.bus = self.interface.sram.ev, self.interface.bus + self.csrs = self.interface.get_csrs() + self.core.get_csrs() + elif interface == "dma": + raise NotImplementedError + else: + raise ValueError(interface + " not supported by LiteEthMac!") - def get_csrs(self): - return self.csrs + def get_csrs(self): + return self.csrs diff --git a/misoclib/com/liteeth/mac/common.py b/misoclib/com/liteeth/mac/common.py index ba1b0ec2..7e6aadb6 100644 --- a/misoclib/com/liteeth/mac/common.py +++ b/misoclib/com/liteeth/mac/common.py @@ -5,42 +5,42 @@ from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer from misoclib.com.liteeth.generic.crossbar import LiteEthCrossbar class LiteEthMACDepacketizer(LiteEthDepacketizer): - def __init__(self): - LiteEthDepacketizer.__init__(self, - eth_phy_description(8), - eth_mac_description(8), - mac_header, - mac_header_len) + def __init__(self): + LiteEthDepacketizer.__init__(self, + eth_phy_description(8), + eth_mac_description(8), + mac_header, + mac_header_len) class LiteEthMACPacketizer(LiteEthPacketizer): - def __init__(self): - LiteEthPacketizer.__init__(self, - eth_mac_description(8), - eth_phy_description(8), - mac_header, - mac_header_len) + def __init__(self): + LiteEthPacketizer.__init__(self, + eth_mac_description(8), + eth_phy_description(8), + mac_header, + mac_header_len) class LiteEthMACMasterPort: - def __init__(self, dw): - self.source = Source(eth_mac_description(dw)) - self.sink = Sink(eth_mac_description(dw)) + def __init__(self, dw): + self.source = Source(eth_mac_description(dw)) + self.sink = Sink(eth_mac_description(dw)) class LiteEthMACSlavePort: - def __init__(self, dw): - self.sink = Sink(eth_mac_description(dw)) - self.source = Source(eth_mac_description(dw)) + def __init__(self, dw): + self.sink = Sink(eth_mac_description(dw)) + self.source = Source(eth_mac_description(dw)) class LiteEthMACUserPort(LiteEthMACSlavePort): - def __init__(self, dw): - LiteEthMACSlavePort.__init__(self, dw) + def __init__(self, dw): + LiteEthMACSlavePort.__init__(self, dw) class LiteEthMACCrossbar(LiteEthCrossbar): - def __init__(self): - LiteEthCrossbar.__init__(self, LiteEthMACMasterPort, "ethernet_type") + def __init__(self): + LiteEthCrossbar.__init__(self, LiteEthMACMasterPort, "ethernet_type") - def get_port(self, ethernet_type): - port = LiteEthMACUserPort(8) - if ethernet_type in self.users.keys(): - raise ValueError("Ethernet type {0:#x} already assigned".format(ethernet_type)) - self.users[ethernet_type] = port - return port + def get_port(self, ethernet_type): + port = LiteEthMACUserPort(8) + if ethernet_type in self.users.keys(): + raise ValueError("Ethernet type {0:#x} already assigned".format(ethernet_type)) + self.users[ethernet_type] = port + return port diff --git a/misoclib/com/liteeth/mac/core/__init__.py b/misoclib/com/liteeth/mac/core/__init__.py index 50b6e8e3..4aebf81b 100644 --- a/misoclib/com/liteeth/mac/core/__init__.py +++ b/misoclib/com/liteeth/mac/core/__init__.py @@ -4,88 +4,88 @@ from misoclib.com.liteeth.mac.core import gap, preamble, crc, padding, last_be from misoclib.com.liteeth.phy.sim import LiteEthPHYSim class LiteEthMACCore(Module, AutoCSR): - def __init__(self, phy, dw, endianness="big", - with_preamble_crc=True, - with_padding=True): - if dw < phy.dw: - raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw)) - - rx_pipeline = [phy] - tx_pipeline = [phy] - - # Interpacket gap - tx_gap_inserter = gap.LiteEthMACGap(phy.dw) - rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True) - self.submodules += RenameClockDomains(tx_gap_inserter, "eth_tx") - self.submodules += RenameClockDomains(rx_gap_checker, "eth_rx") - - tx_pipeline += [tx_gap_inserter] - rx_pipeline += [rx_gap_checker] - - # Preamble / CRC - if isinstance(phy, LiteEthPHYSim): - # In simulation, avoid CRC/Preamble to enable direct connection - # to the Ethernet tap. - self._preamble_crc = CSRStatus(reset=1) - elif with_preamble_crc: - self._preamble_crc = CSRStatus(reset=1) - # Preamble insert/check - preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw) - preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw) - self.submodules += RenameClockDomains(preamble_inserter, "eth_tx") - self.submodules += RenameClockDomains(preamble_checker, "eth_rx") - - # CRC insert/check - crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw)) - crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw)) - self.submodules += RenameClockDomains(crc32_inserter, "eth_tx") - self.submodules += RenameClockDomains(crc32_checker, "eth_rx") - - tx_pipeline += [preamble_inserter, crc32_inserter] - rx_pipeline += [preamble_checker, crc32_checker] - - # Padding - if with_padding: - padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60) - padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60) - self.submodules += RenameClockDomains(padding_inserter, "eth_tx") - self.submodules += RenameClockDomains(padding_checker, "eth_rx") - - tx_pipeline += [padding_inserter] - rx_pipeline += [padding_checker] - - # Delimiters - if dw != 8: - tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw) - rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw) - self.submodules += RenameClockDomains(tx_last_be, "eth_tx") - self.submodules += RenameClockDomains(rx_last_be, "eth_rx") - - tx_pipeline += [tx_last_be] - rx_pipeline += [rx_last_be] - - # Converters - if dw != phy.dw: - reverse = endianness == "big" - tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse) - rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse) - self.submodules += RenameClockDomains(tx_converter, "eth_tx") - self.submodules += RenameClockDomains(rx_converter, "eth_rx") - - tx_pipeline += [tx_converter] - rx_pipeline += [rx_converter] - - # Cross Domain Crossing - tx_cdc = AsyncFIFO(eth_phy_description(dw), 64) - rx_cdc = AsyncFIFO(eth_phy_description(dw), 64) - self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"}) - self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"}) - - tx_pipeline += [tx_cdc] - rx_pipeline += [rx_cdc] - - # Graph - self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline)) - self.submodules.rx_pipeline = Pipeline(*rx_pipeline) - - self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source + def __init__(self, phy, dw, endianness="big", + with_preamble_crc=True, + with_padding=True): + if dw < phy.dw: + raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw)) + + rx_pipeline = [phy] + tx_pipeline = [phy] + + # Interpacket gap + tx_gap_inserter = gap.LiteEthMACGap(phy.dw) + rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True) + self.submodules += RenameClockDomains(tx_gap_inserter, "eth_tx") + self.submodules += RenameClockDomains(rx_gap_checker, "eth_rx") + + tx_pipeline += [tx_gap_inserter] + rx_pipeline += [rx_gap_checker] + + # Preamble / CRC + if isinstance(phy, LiteEthPHYSim): + # In simulation, avoid CRC/Preamble to enable direct connection + # to the Ethernet tap. + self._preamble_crc = CSRStatus(reset=1) + elif with_preamble_crc: + self._preamble_crc = CSRStatus(reset=1) + # Preamble insert/check + preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw) + preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw) + self.submodules += RenameClockDomains(preamble_inserter, "eth_tx") + self.submodules += RenameClockDomains(preamble_checker, "eth_rx") + + # CRC insert/check + crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw)) + crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw)) + self.submodules += RenameClockDomains(crc32_inserter, "eth_tx") + self.submodules += RenameClockDomains(crc32_checker, "eth_rx") + + tx_pipeline += [preamble_inserter, crc32_inserter] + rx_pipeline += [preamble_checker, crc32_checker] + + # Padding + if with_padding: + padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60) + padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60) + self.submodules += RenameClockDomains(padding_inserter, "eth_tx") + self.submodules += RenameClockDomains(padding_checker, "eth_rx") + + tx_pipeline += [padding_inserter] + rx_pipeline += [padding_checker] + + # Delimiters + if dw != 8: + tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw) + rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw) + self.submodules += RenameClockDomains(tx_last_be, "eth_tx") + self.submodules += RenameClockDomains(rx_last_be, "eth_rx") + + tx_pipeline += [tx_last_be] + rx_pipeline += [rx_last_be] + + # Converters + if dw != phy.dw: + reverse = endianness == "big" + tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse) + rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse) + self.submodules += RenameClockDomains(tx_converter, "eth_tx") + self.submodules += RenameClockDomains(rx_converter, "eth_rx") + + tx_pipeline += [tx_converter] + rx_pipeline += [rx_converter] + + # Cross Domain Crossing + tx_cdc = AsyncFIFO(eth_phy_description(dw), 64) + rx_cdc = AsyncFIFO(eth_phy_description(dw), 64) + self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"}) + self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"}) + + tx_pipeline += [tx_cdc] + rx_pipeline += [rx_cdc] + + # Graph + self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline)) + self.submodules.rx_pipeline = Pipeline(*rx_pipeline) + + self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source diff --git a/misoclib/com/liteeth/mac/core/crc.py b/misoclib/com/liteeth/mac/core/crc.py index 6f1f8ff7..b272ca19 100644 --- a/misoclib/com/liteeth/mac/core/crc.py +++ b/misoclib/com/liteeth/mac/core/crc.py @@ -2,276 +2,276 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthMACCRCEngine(Module): - """Cyclic Redundancy Check Engine - - Compute next CRC value from last CRC value and data input using - an optimized asynchronous LFSR. - - Parameters - ---------- - data_width : int - Width of the data bus. - width : int - Width of the CRC. - polynom : int - Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC) - - Attributes - ---------- - data : in - Data input. - last : in - last CRC value. - next : - next CRC value. - """ - def __init__(self, data_width, width, polynom): - self.data = Signal(data_width) - self.last = Signal(width) - self.next = Signal(width) - - ### - - def _optimize_eq(l): - """ - Replace even numbers of XORs in the equation - with an equivalent XOR - """ - d = OrderedDict() - for e in l: - if e in d: - d[e] += 1 - else: - d[e] = 1 - r = [] - for key, value in d.items(): - if value%2 != 0: - r.append(key) - return r - - # compute and optimize CRC's LFSR - curval = [[("state", i)] for i in range(width)] - for i in range(data_width): - feedback = curval.pop() + [("din", i)] - for j in range(width-1): - if (polynom & (1<<(j+1))): - curval[j] += feedback - curval[j] = _optimize_eq(curval[j]) - curval.insert(0, feedback) - - # implement logic - for i in range(width): - xors = [] - for t, n in curval[i]: - if t == "state": - xors += [self.last[n]] - elif t == "din": - xors += [self.data[n]] - self.comb += self.next[i].eq(optree("^", xors)) + """Cyclic Redundancy Check Engine + + Compute next CRC value from last CRC value and data input using + an optimized asynchronous LFSR. + + Parameters + ---------- + data_width : int + Width of the data bus. + width : int + Width of the CRC. + polynom : int + Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC) + + Attributes + ---------- + data : in + Data input. + last : in + last CRC value. + next : + next CRC value. + """ + def __init__(self, data_width, width, polynom): + self.data = Signal(data_width) + self.last = Signal(width) + self.next = Signal(width) + + ### + + def _optimize_eq(l): + """ + Replace even numbers of XORs in the equation + with an equivalent XOR + """ + d = OrderedDict() + for e in l: + if e in d: + d[e] += 1 + else: + d[e] = 1 + r = [] + for key, value in d.items(): + if value%2 != 0: + r.append(key) + return r + + # compute and optimize CRC's LFSR + curval = [[("state", i)] for i in range(width)] + for i in range(data_width): + feedback = curval.pop() + [("din", i)] + for j in range(width-1): + if (polynom & (1<<(j+1))): + curval[j] += feedback + curval[j] = _optimize_eq(curval[j]) + curval.insert(0, feedback) + + # implement logic + for i in range(width): + xors = [] + for t, n in curval[i]: + if t == "state": + xors += [self.last[n]] + elif t == "din": + xors += [self.data[n]] + self.comb += self.next[i].eq(optree("^", xors)) @DecorateModule(InsertReset) @DecorateModule(InsertCE) class LiteEthMACCRC32(Module): - """IEEE 802.3 CRC - - Implement an IEEE 802.3 CRC generator/checker. - - Parameters - ---------- - data_width : int - Width of the data bus. - - Attributes - ---------- - d : in - Data input. - value : out - CRC value (used for generator). - error : out - CRC error (used for checker). - """ - width = 32 - polynom = 0x04C11DB7 - init = 2**width-1 - check = 0xC704DD7B - def __init__(self, data_width): - self.data = Signal(data_width) - self.value = Signal(self.width) - self.error = Signal() - - ### - - self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom) - reg = Signal(self.width, reset=self.init) - self.sync += reg.eq(self.engine.next) - self.comb += [ - self.engine.data.eq(self.data), - self.engine.last.eq(reg), - - self.value.eq(~reg[::-1]), - self.error.eq(self.engine.next != self.check) - ] + """IEEE 802.3 CRC + + Implement an IEEE 802.3 CRC generator/checker. + + Parameters + ---------- + data_width : int + Width of the data bus. + + Attributes + ---------- + d : in + Data input. + value : out + CRC value (used for generator). + error : out + CRC error (used for checker). + """ + width = 32 + polynom = 0x04C11DB7 + init = 2**width-1 + check = 0xC704DD7B + def __init__(self, data_width): + self.data = Signal(data_width) + self.value = Signal(self.width) + self.error = Signal() + + ### + + self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom) + reg = Signal(self.width, reset=self.init) + self.sync += reg.eq(self.engine.next) + self.comb += [ + self.engine.data.eq(self.data), + self.engine.last.eq(reg), + + self.value.eq(~reg[::-1]), + self.error.eq(self.engine.next != self.check) + ] class LiteEthMACCRCInserter(Module): - """CRC Inserter - - Append a CRC at the end of each packet. - - Parameters - ---------- - description : description - description of the dataflow. - - Attributes - ---------- - sink : in - Packets input without CRC. - source : out - Packets output with CRC. - """ - def __init__(self, crc_class, description): - self.sink = sink = Sink(description) - self.source = source = Source(description) - self.busy = Signal() - - ### - - dw = flen(sink.data) - crc = crc_class(dw) - fsm = FSM(reset_state="IDLE") - self.submodules += crc, fsm - - fsm.act("IDLE", - crc.reset.eq(1), - sink.ack.eq(1), - If(sink.stb & sink.sop, - sink.ack.eq(0), - NextState("COPY"), - ) - ) - fsm.act("COPY", - crc.ce.eq(sink.stb & source.ack), - crc.data.eq(sink.data), - Record.connect(sink, source), - source.eop.eq(0), - If(sink.stb & sink.eop & source.ack, - NextState("INSERT"), - ) - ) - ratio = crc.width//dw - if ratio > 1: - cnt = Signal(max=ratio, reset=ratio-1) - cnt_done = Signal() - fsm.act("INSERT", - source.stb.eq(1), - chooser(crc.value, cnt, source.data, reverse=True), - If(cnt_done, - source.eop.eq(1), - If(source.ack, NextState("IDLE")) - ) - ) - self.comb += cnt_done.eq(cnt == 0) - self.sync += \ - If(fsm.ongoing("IDLE"), - cnt.eq(cnt.reset) - ).Elif(fsm.ongoing("INSERT") & ~cnt_done, - cnt.eq(cnt - source.ack) - ) - else: - fsm.act("INSERT", - source.stb.eq(1), - source.eop.eq(1), - source.data.eq(crc.value), - If(source.ack, NextState("IDLE")) - ) - self.comb += self.busy.eq(~fsm.ongoing("IDLE")) + """CRC Inserter + + Append a CRC at the end of each packet. + + Parameters + ---------- + description : description + description of the dataflow. + + Attributes + ---------- + sink : in + Packets input without CRC. + source : out + Packets output with CRC. + """ + def __init__(self, crc_class, description): + self.sink = sink = Sink(description) + self.source = source = Source(description) + self.busy = Signal() + + ### + + dw = flen(sink.data) + crc = crc_class(dw) + fsm = FSM(reset_state="IDLE") + self.submodules += crc, fsm + + fsm.act("IDLE", + crc.reset.eq(1), + sink.ack.eq(1), + If(sink.stb & sink.sop, + sink.ack.eq(0), + NextState("COPY"), + ) + ) + fsm.act("COPY", + crc.ce.eq(sink.stb & source.ack), + crc.data.eq(sink.data), + Record.connect(sink, source), + source.eop.eq(0), + If(sink.stb & sink.eop & source.ack, + NextState("INSERT"), + ) + ) + ratio = crc.width//dw + if ratio > 1: + cnt = Signal(max=ratio, reset=ratio-1) + cnt_done = Signal() + fsm.act("INSERT", + source.stb.eq(1), + chooser(crc.value, cnt, source.data, reverse=True), + If(cnt_done, + source.eop.eq(1), + If(source.ack, NextState("IDLE")) + ) + ) + self.comb += cnt_done.eq(cnt == 0) + self.sync += \ + If(fsm.ongoing("IDLE"), + cnt.eq(cnt.reset) + ).Elif(fsm.ongoing("INSERT") & ~cnt_done, + cnt.eq(cnt - source.ack) + ) + else: + fsm.act("INSERT", + source.stb.eq(1), + source.eop.eq(1), + source.data.eq(crc.value), + If(source.ack, NextState("IDLE")) + ) + self.comb += self.busy.eq(~fsm.ongoing("IDLE")) class LiteEthMACCRC32Inserter(LiteEthMACCRCInserter): - def __init__(self, description): - LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, description) + def __init__(self, description): + LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, description) class LiteEthMACCRCChecker(Module): - """CRC Checker - - Check CRC at the end of each packet. - - Parameters - ---------- - description : description - description of the dataflow. - - Attributes - ---------- - sink : in - Packets input with CRC. - source : out - Packets output without CRC and "error" set to 0 - on eop when CRC OK / set to 1 when CRC KO. - """ - def __init__(self, crc_class, description): - self.sink = sink = Sink(description) - self.source = source = Source(description) - self.busy = Signal() - - ### - - dw = flen(sink.data) - crc = crc_class(dw) - self.submodules += crc - ratio = crc.width//dw - - error = Signal() - fifo = InsertReset(SyncFIFO(description, ratio + 1)) - self.submodules += fifo - - fsm = FSM(reset_state="RESET") - self.submodules += fsm - - fifo_in = Signal() - fifo_out = Signal() - fifo_full = Signal() - - self.comb += [ - fifo_full.eq(fifo.fifo.level == ratio), - fifo_in.eq(sink.stb & (~fifo_full | fifo_out)), - fifo_out.eq(source.stb & source.ack), - - Record.connect(sink, fifo.sink), - fifo.sink.stb.eq(fifo_in), - self.sink.ack.eq(fifo_in), - - source.stb.eq(sink.stb & fifo_full), - source.sop.eq(fifo.source.sop), - source.eop.eq(sink.eop), - fifo.source.ack.eq(fifo_out), - source.payload.eq(fifo.source.payload), - - source.error.eq(sink.error | crc.error), - ] - - fsm.act("RESET", - crc.reset.eq(1), - fifo.reset.eq(1), - NextState("IDLE"), - ) - fsm.act("IDLE", - crc.data.eq(sink.data), - If(sink.stb & sink.sop & sink.ack, - crc.ce.eq(1), - NextState("COPY") - ) - ) - fsm.act("COPY", - crc.data.eq(sink.data), - If(sink.stb & sink.ack, - crc.ce.eq(1), - If(sink.eop, - NextState("RESET") - ) - ) - ) - self.comb += self.busy.eq(~fsm.ongoing("IDLE")) + """CRC Checker + + Check CRC at the end of each packet. + + Parameters + ---------- + description : description + description of the dataflow. + + Attributes + ---------- + sink : in + Packets input with CRC. + source : out + Packets output without CRC and "error" set to 0 + on eop when CRC OK / set to 1 when CRC KO. + """ + def __init__(self, crc_class, description): + self.sink = sink = Sink(description) + self.source = source = Source(description) + self.busy = Signal() + + ### + + dw = flen(sink.data) + crc = crc_class(dw) + self.submodules += crc + ratio = crc.width//dw + + error = Signal() + fifo = InsertReset(SyncFIFO(description, ratio + 1)) + self.submodules += fifo + + fsm = FSM(reset_state="RESET") + self.submodules += fsm + + fifo_in = Signal() + fifo_out = Signal() + fifo_full = Signal() + + self.comb += [ + fifo_full.eq(fifo.fifo.level == ratio), + fifo_in.eq(sink.stb & (~fifo_full | fifo_out)), + fifo_out.eq(source.stb & source.ack), + + Record.connect(sink, fifo.sink), + fifo.sink.stb.eq(fifo_in), + self.sink.ack.eq(fifo_in), + + source.stb.eq(sink.stb & fifo_full), + source.sop.eq(fifo.source.sop), + source.eop.eq(sink.eop), + fifo.source.ack.eq(fifo_out), + source.payload.eq(fifo.source.payload), + + source.error.eq(sink.error | crc.error), + ] + + fsm.act("RESET", + crc.reset.eq(1), + fifo.reset.eq(1), + NextState("IDLE"), + ) + fsm.act("IDLE", + crc.data.eq(sink.data), + If(sink.stb & sink.sop & sink.ack, + crc.ce.eq(1), + NextState("COPY") + ) + ) + fsm.act("COPY", + crc.data.eq(sink.data), + If(sink.stb & sink.ack, + crc.ce.eq(1), + If(sink.eop, + NextState("RESET") + ) + ) + ) + self.comb += self.busy.eq(~fsm.ongoing("IDLE")) class LiteEthMACCRC32Checker(LiteEthMACCRCChecker): - def __init__(self, description): - LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, description) + def __init__(self, description): + LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, description) diff --git a/misoclib/com/liteeth/mac/core/gap.py b/misoclib/com/liteeth/mac/core/gap.py index 9a350868..b814ed8f 100644 --- a/misoclib/com/liteeth/mac/core/gap.py +++ b/misoclib/com/liteeth/mac/core/gap.py @@ -2,25 +2,25 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthMACGap(Module): - def __init__(self, dw, ack_on_gap=False): - self.sink = sink = Sink(eth_phy_description(dw)) - self.source = source = Source(eth_phy_description(dw)) - ### - gap = math.ceil(eth_interpacket_gap/(dw//8)) - self.submodules.counter = counter = Counter(max=gap) + def __init__(self, dw, ack_on_gap=False): + self.sink = sink = Sink(eth_phy_description(dw)) + self.source = source = Source(eth_phy_description(dw)) + ### + gap = math.ceil(eth_interpacket_gap/(dw//8)) + self.submodules.counter = counter = Counter(max=gap) - self.submodules.fsm = fsm = FSM(reset_state="COPY") - fsm.act("COPY", - counter.reset.eq(1), - Record.connect(sink, source), - If(sink.stb & sink.eop & sink.ack, - NextState("GAP") - ) - ) - fsm.act("GAP", - counter.ce.eq(1), - sink.ack.eq(int(ack_on_gap)), - If(counter.value == (gap-1), - NextState("COPY") - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="COPY") + fsm.act("COPY", + counter.reset.eq(1), + Record.connect(sink, source), + If(sink.stb & sink.eop & sink.ack, + NextState("GAP") + ) + ) + fsm.act("GAP", + counter.ce.eq(1), + sink.ack.eq(int(ack_on_gap)), + If(counter.value == (gap-1), + NextState("COPY") + ) + ) diff --git a/misoclib/com/liteeth/mac/core/last_be.py b/misoclib/com/liteeth/mac/core/last_be.py index bf106eeb..c14177d6 100644 --- a/misoclib/com/liteeth/mac/core/last_be.py +++ b/misoclib/com/liteeth/mac/core/last_be.py @@ -2,37 +2,37 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthMACTXLastBE(Module): - def __init__(self, dw): - self.sink = sink = Sink(eth_phy_description(dw)) - self.source = source = Source(eth_phy_description(dw)) - ### - ongoing = Signal() - self.sync += \ - If(sink.stb & sink.ack, - If(sink.sop, - ongoing.eq(1) - ).Elif(sink.last_be, - ongoing.eq(0) - ) - ) - self.comb += [ - source.stb.eq(sink.stb & (sink.sop | ongoing)), - source.sop.eq(sink.sop), - source.eop.eq(sink.last_be), - source.data.eq(sink.data), - sink.ack.eq(source.ack) - ] + def __init__(self, dw): + self.sink = sink = Sink(eth_phy_description(dw)) + self.source = source = Source(eth_phy_description(dw)) + ### + ongoing = Signal() + self.sync += \ + If(sink.stb & sink.ack, + If(sink.sop, + ongoing.eq(1) + ).Elif(sink.last_be, + ongoing.eq(0) + ) + ) + self.comb += [ + source.stb.eq(sink.stb & (sink.sop | ongoing)), + source.sop.eq(sink.sop), + source.eop.eq(sink.last_be), + source.data.eq(sink.data), + sink.ack.eq(source.ack) + ] class LiteEthMACRXLastBE(Module): - def __init__(self, dw): - self.sink = sink = Sink(eth_phy_description(dw)) - self.source = source = Source(eth_phy_description(dw)) - ### - self.comb += [ - source.stb.eq(sink.stb), - source.sop.eq(sink.sop), - source.eop.eq(sink.eop), - source.data.eq(sink.data), - source.last_be.eq(sink.eop), - sink.ack.eq(source.ack) - ] + def __init__(self, dw): + self.sink = sink = Sink(eth_phy_description(dw)) + self.source = source = Source(eth_phy_description(dw)) + ### + self.comb += [ + source.stb.eq(sink.stb), + source.sop.eq(sink.sop), + source.eop.eq(sink.eop), + source.data.eq(sink.data), + source.last_be.eq(sink.eop), + sink.ack.eq(source.ack) + ] diff --git a/misoclib/com/liteeth/mac/core/padding.py b/misoclib/com/liteeth/mac/core/padding.py index f9ea898e..4bc02cca 100644 --- a/misoclib/com/liteeth/mac/core/padding.py +++ b/misoclib/com/liteeth/mac/core/padding.py @@ -2,46 +2,46 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthMACPaddingInserter(Module): - def __init__(self, dw, packet_min_length): - self.sink = sink = Sink(eth_phy_description(dw)) - self.source = source = Source(eth_phy_description(dw)) - ### - packet_min_data = math.ceil(packet_min_length/(dw/8)) + def __init__(self, dw, packet_min_length): + self.sink = sink = Sink(eth_phy_description(dw)) + self.source = source = Source(eth_phy_description(dw)) + ### + packet_min_data = math.ceil(packet_min_length/(dw/8)) - self.submodules.counter = counter = Counter(max=eth_mtu) + self.submodules.counter = counter = Counter(max=eth_mtu) - self.submodules.fsm = fsm = FSM(reset_state="COPY") - fsm.act("COPY", - counter.reset.eq(sink.stb & sink.sop), - Record.connect(sink, source), - If(sink.stb & sink.ack, - counter.ce.eq(1), - If(sink.eop, - If(counter.value < packet_min_data, - source.eop.eq(0), - NextState("PADDING") - ) - ) - ) - ) - fsm.act("PADDING", - source.stb.eq(1), - source.eop.eq(counter.value == packet_min_data), - source.data.eq(0), - If(source.ack, - counter.ce.eq(1), - If(source.eop, - NextState("COPY") - ) - ) - ) + self.submodules.fsm = fsm = FSM(reset_state="COPY") + fsm.act("COPY", + counter.reset.eq(sink.stb & sink.sop), + Record.connect(sink, source), + If(sink.stb & sink.ack, + counter.ce.eq(1), + If(sink.eop, + If(counter.value < packet_min_data, + source.eop.eq(0), + NextState("PADDING") + ) + ) + ) + ) + fsm.act("PADDING", + source.stb.eq(1), + source.eop.eq(counter.value == packet_min_data), + source.data.eq(0), + If(source.ack, + counter.ce.eq(1), + If(source.eop, + NextState("COPY") + ) + ) + ) class LiteEthMACPaddingChecker(Module): - def __init__(self, dw, packet_min_length): - self.sink = sink = Sink(eth_phy_description(dw)) - self.source = source = Source(eth_phy_description(dw)) - ### - # XXX see if we should drop the packet when - # payload size < minimum ethernet payload size - self.comb += Record.connect(sink, source) + def __init__(self, dw, packet_min_length): + self.sink = sink = Sink(eth_phy_description(dw)) + self.source = source = Source(eth_phy_description(dw)) + ### + # XXX see if we should drop the packet when + # payload size < minimum ethernet payload size + self.comb += Record.connect(sink, source) diff --git a/misoclib/com/liteeth/mac/core/preamble.py b/misoclib/com/liteeth/mac/core/preamble.py index 89527e95..8ddc0e93 100644 --- a/misoclib/com/liteeth/mac/core/preamble.py +++ b/misoclib/com/liteeth/mac/core/preamble.py @@ -2,139 +2,139 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthMACPreambleInserter(Module): - def __init__(self, dw): - self.sink = Sink(eth_phy_description(dw)) - self.source = Source(eth_phy_description(dw)) - - ### - - preamble = Signal(64, reset=eth_preamble) - cnt_max = (64//dw)-1 - cnt = Signal(max=cnt_max+1) - clr_cnt = Signal() - inc_cnt = Signal() - - self.sync += \ - If(clr_cnt, - cnt.eq(0) - ).Elif(inc_cnt, - cnt.eq(cnt+1) - ) - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - fsm.act("IDLE", - self.sink.ack.eq(1), - clr_cnt.eq(1), - If(self.sink.stb & self.sink.sop, - self.sink.ack.eq(0), - NextState("INSERT"), - ) - ) - fsm.act("INSERT", - self.source.stb.eq(1), - self.source.sop.eq(cnt==0), - chooser(preamble, cnt, self.source.data), - If(cnt == cnt_max, - If(self.source.ack, NextState("COPY")) - ).Else( - inc_cnt.eq(self.source.ack) - ) - ) - fsm.act("COPY", - Record.connect(self.sink, self.source), - self.source.sop.eq(0), - - If(self.sink.stb & self.sink.eop & self.source.ack, - NextState("IDLE"), - ) - ) + def __init__(self, dw): + self.sink = Sink(eth_phy_description(dw)) + self.source = Source(eth_phy_description(dw)) + + ### + + preamble = Signal(64, reset=eth_preamble) + cnt_max = (64//dw)-1 + cnt = Signal(max=cnt_max+1) + clr_cnt = Signal() + inc_cnt = Signal() + + self.sync += \ + If(clr_cnt, + cnt.eq(0) + ).Elif(inc_cnt, + cnt.eq(cnt+1) + ) + + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + fsm.act("IDLE", + self.sink.ack.eq(1), + clr_cnt.eq(1), + If(self.sink.stb & self.sink.sop, + self.sink.ack.eq(0), + NextState("INSERT"), + ) + ) + fsm.act("INSERT", + self.source.stb.eq(1), + self.source.sop.eq(cnt==0), + chooser(preamble, cnt, self.source.data), + If(cnt == cnt_max, + If(self.source.ack, NextState("COPY")) + ).Else( + inc_cnt.eq(self.source.ack) + ) + ) + fsm.act("COPY", + Record.connect(self.sink, self.source), + self.source.sop.eq(0), + + If(self.sink.stb & self.sink.eop & self.source.ack, + NextState("IDLE"), + ) + ) class LiteEthMACPreambleChecker(Module): - def __init__(self, dw): - self.sink = Sink(eth_phy_description(dw)) - self.source = Source(eth_phy_description(dw)) - - ### - - preamble = Signal(64, reset=eth_preamble) - cnt_max = (64//dw) - 1 - cnt = Signal(max=cnt_max+1) - clr_cnt = Signal() - inc_cnt = Signal() - - self.sync += \ - If(clr_cnt, - cnt.eq(0) - ).Elif(inc_cnt, - cnt.eq(cnt+1) - ) - - discard = Signal() - clr_discard = Signal() - set_discard = Signal() - - self.sync += \ - If(clr_discard, - discard.eq(0) - ).Elif(set_discard, - discard.eq(1) - ) - - sop = Signal() - clr_sop = Signal() - set_sop = Signal() - self.sync += \ - If(clr_sop, - sop.eq(0) - ).Elif(set_sop, - sop.eq(1) - ) - - ref = Signal(dw) - match = Signal() - self.comb += [ - chooser(preamble, cnt, ref), - match.eq(self.sink.data == ref) - ] - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - self.sink.ack.eq(1), - clr_cnt.eq(1), - clr_discard.eq(1), - If(self.sink.stb & self.sink.sop, - clr_cnt.eq(0), - inc_cnt.eq(1), - clr_discard.eq(0), - set_discard.eq(~match), - NextState("CHECK"), - ) - ) - fsm.act("CHECK", - self.sink.ack.eq(1), - If(self.sink.stb, - set_discard.eq(~match), - If(cnt == cnt_max, - If(discard | (~match), - NextState("IDLE") - ).Else( - set_sop.eq(1), - NextState("COPY") - ) - ).Else( - inc_cnt.eq(1) - ) - ) - ) - fsm.act("COPY", - Record.connect(self.sink, self.source), - self.source.sop.eq(sop), - clr_sop.eq(self.source.stb & self.source.ack), - - If(self.source.stb & self.source.eop & self.source.ack, - NextState("IDLE"), - ) - ) + def __init__(self, dw): + self.sink = Sink(eth_phy_description(dw)) + self.source = Source(eth_phy_description(dw)) + + ### + + preamble = Signal(64, reset=eth_preamble) + cnt_max = (64//dw) - 1 + cnt = Signal(max=cnt_max+1) + clr_cnt = Signal() + inc_cnt = Signal() + + self.sync += \ + If(clr_cnt, + cnt.eq(0) + ).Elif(inc_cnt, + cnt.eq(cnt+1) + ) + + discard = Signal() + clr_discard = Signal() + set_discard = Signal() + + self.sync += \ + If(clr_discard, + discard.eq(0) + ).Elif(set_discard, + discard.eq(1) + ) + + sop = Signal() + clr_sop = Signal() + set_sop = Signal() + self.sync += \ + If(clr_sop, + sop.eq(0) + ).Elif(set_sop, + sop.eq(1) + ) + + ref = Signal(dw) + match = Signal() + self.comb += [ + chooser(preamble, cnt, ref), + match.eq(self.sink.data == ref) + ] + + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + + fsm.act("IDLE", + self.sink.ack.eq(1), + clr_cnt.eq(1), + clr_discard.eq(1), + If(self.sink.stb & self.sink.sop, + clr_cnt.eq(0), + inc_cnt.eq(1), + clr_discard.eq(0), + set_discard.eq(~match), + NextState("CHECK"), + ) + ) + fsm.act("CHECK", + self.sink.ack.eq(1), + If(self.sink.stb, + set_discard.eq(~match), + If(cnt == cnt_max, + If(discard | (~match), + NextState("IDLE") + ).Else( + set_sop.eq(1), + NextState("COPY") + ) + ).Else( + inc_cnt.eq(1) + ) + ) + ) + fsm.act("COPY", + Record.connect(self.sink, self.source), + self.source.sop.eq(sop), + clr_sop.eq(self.source.stb & self.source.ack), + + If(self.source.stb & self.source.eop & self.source.ack, + NextState("IDLE"), + ) + ) diff --git a/misoclib/com/liteeth/mac/frontend/sram.py b/misoclib/com/liteeth/mac/frontend/sram.py index aab94fae..724509cc 100644 --- a/misoclib/com/liteeth/mac/frontend/sram.py +++ b/misoclib/com/liteeth/mac/frontend/sram.py @@ -5,229 +5,229 @@ from migen.bank.description import * from migen.bank.eventmanager import * class LiteEthMACSRAMWriter(Module, AutoCSR): - def __init__(self, dw, depth, nslots=2): - self.sink = sink = Sink(eth_phy_description(dw)) - self.crc_error = Signal() - - slotbits = max(log2_int(nslots), 1) - lengthbits = log2_int(depth*4) # length in bytes - - self._slot = CSRStatus(slotbits) - self._length = CSRStatus(lengthbits) - - self.submodules.ev = EventManager() - self.ev.available = EventSourceLevel() - self.ev.finalize() - - ### - - # packet dropped if no slot available - sink.ack.reset = 1 - - # length computation - increment = Signal(3) - self.comb += \ - If(sink.last_be[3], - increment.eq(1) - ).Elif(sink.last_be[2], - increment.eq(2) - ).Elif(sink.last_be[1], - increment.eq(3) - ).Else( - increment.eq(4) - ) - counter = Counter(lengthbits, increment=increment) - self.submodules += counter - - # slot computation - slot = Counter(slotbits) - self.submodules += slot - - ongoing = Signal() - - # status fifo - fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) - self.submodules += fifo - - # fsm - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - If(sink.stb & sink.sop, - If(fifo.sink.ack, - ongoing.eq(1), - counter.ce.eq(1), - NextState("WRITE") - ) - ) - ) - fsm.act("WRITE", - counter.ce.eq(sink.stb), - ongoing.eq(1), - If(sink.stb & sink.eop, - If((sink.error & sink.last_be) != 0, - NextState("DISCARD") - ).Else( - NextState("TERMINATE") - ) - ) - ) - fsm.act("DISCARD", - counter.reset.eq(1), - NextState("IDLE") - ) - self.comb += [ - fifo.sink.slot.eq(slot.value), - fifo.sink.length.eq(counter.value) - ] - fsm.act("TERMINATE", - counter.reset.eq(1), - slot.ce.eq(1), - fifo.sink.stb.eq(1), - NextState("IDLE") - ) - self.comb += [ - fifo.source.ack.eq(self.ev.available.clear), - self.ev.available.trigger.eq(fifo.source.stb), - self._slot.status.eq(fifo.source.slot), - self._length.status.eq(fifo.source.length), - ] - - # memory - mems = [None]*nslots - ports = [None]*nslots - for n in range(nslots): - mems[n] = Memory(dw, depth) - ports[n] = mems[n].get_port(write_capable=True) - self.specials += ports[n] - self.mems = mems - - cases = {} - for n, port in enumerate(ports): - cases[n] = [ - ports[n].adr.eq(counter.value[2:]), - ports[n].dat_w.eq(sink.data), - If(sink.stb & ongoing, - ports[n].we.eq(0xf) - ) - ] - self.comb += Case(slot.value, cases) + def __init__(self, dw, depth, nslots=2): + self.sink = sink = Sink(eth_phy_description(dw)) + self.crc_error = Signal() + + slotbits = max(log2_int(nslots), 1) + lengthbits = log2_int(depth*4) # length in bytes + + self._slot = CSRStatus(slotbits) + self._length = CSRStatus(lengthbits) + + self.submodules.ev = EventManager() + self.ev.available = EventSourceLevel() + self.ev.finalize() + + ### + + # packet dropped if no slot available + sink.ack.reset = 1 + + # length computation + increment = Signal(3) + self.comb += \ + If(sink.last_be[3], + increment.eq(1) + ).Elif(sink.last_be[2], + increment.eq(2) + ).Elif(sink.last_be[1], + increment.eq(3) + ).Else( + increment.eq(4) + ) + counter = Counter(lengthbits, increment=increment) + self.submodules += counter + + # slot computation + slot = Counter(slotbits) + self.submodules += slot + + ongoing = Signal() + + # status fifo + fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) + self.submodules += fifo + + # fsm + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + + fsm.act("IDLE", + If(sink.stb & sink.sop, + If(fifo.sink.ack, + ongoing.eq(1), + counter.ce.eq(1), + NextState("WRITE") + ) + ) + ) + fsm.act("WRITE", + counter.ce.eq(sink.stb), + ongoing.eq(1), + If(sink.stb & sink.eop, + If((sink.error & sink.last_be) != 0, + NextState("DISCARD") + ).Else( + NextState("TERMINATE") + ) + ) + ) + fsm.act("DISCARD", + counter.reset.eq(1), + NextState("IDLE") + ) + self.comb += [ + fifo.sink.slot.eq(slot.value), + fifo.sink.length.eq(counter.value) + ] + fsm.act("TERMINATE", + counter.reset.eq(1), + slot.ce.eq(1), + fifo.sink.stb.eq(1), + NextState("IDLE") + ) + self.comb += [ + fifo.source.ack.eq(self.ev.available.clear), + self.ev.available.trigger.eq(fifo.source.stb), + self._slot.status.eq(fifo.source.slot), + self._length.status.eq(fifo.source.length), + ] + + # memory + mems = [None]*nslots + ports = [None]*nslots + for n in range(nslots): + mems[n] = Memory(dw, depth) + ports[n] = mems[n].get_port(write_capable=True) + self.specials += ports[n] + self.mems = mems + + cases = {} + for n, port in enumerate(ports): + cases[n] = [ + ports[n].adr.eq(counter.value[2:]), + ports[n].dat_w.eq(sink.data), + If(sink.stb & ongoing, + ports[n].we.eq(0xf) + ) + ] + self.comb += Case(slot.value, cases) class LiteEthMACSRAMReader(Module, AutoCSR): - def __init__(self, dw, depth, nslots=2): - self.source = source = Source(eth_phy_description(dw)) - - slotbits = max(log2_int(nslots), 1) - lengthbits = log2_int(depth*4) # length in bytes - self.lengthbits = lengthbits - - self._start = CSR() - self._ready = CSRStatus() - self._slot = CSRStorage(slotbits) - self._length = CSRStorage(lengthbits) - - self.submodules.ev = EventManager() - self.ev.done = EventSourcePulse() - self.ev.finalize() - - ### - - # command fifo - fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) - self.submodules += fifo - self.comb += [ - fifo.sink.stb.eq(self._start.re), - fifo.sink.slot.eq(self._slot.storage), - fifo.sink.length.eq(self._length.storage), - self._ready.status.eq(fifo.sink.ack) - ] - - # length computation - self.submodules.counter = counter = Counter(lengthbits, increment=4) - - # fsm - first = Signal() - last = Signal() - last_d = Signal() - - fsm = FSM(reset_state="IDLE") - self.submodules += fsm - - fsm.act("IDLE", - counter.reset.eq(1), - If(fifo.source.stb, - NextState("CHECK") - ) - ) - fsm.act("CHECK", - If(~last_d, - NextState("SEND"), - ).Else( - NextState("END"), - ) - ) - length_lsb = fifo.source.length[0:2] - self.comb += [ - If(last, - If(length_lsb == 3, - source.last_be.eq(0b0010) - ).Elif(length_lsb == 2, - source.last_be.eq(0b0100) - ).Elif(length_lsb == 1, - source.last_be.eq(0b1000) - ).Else( - source.last_be.eq(0b0001) - ) - ) - ] - fsm.act("SEND", - source.stb.eq(1), - source.sop.eq(first), - source.eop.eq(last), - If(source.ack, - counter.ce.eq(~last), - NextState("CHECK") - ) - ) - fsm.act("END", - fifo.source.ack.eq(1), - self.ev.done.trigger.eq(1), - NextState("IDLE") - ) - - # first/last computation - self.sync += [ - If(fsm.ongoing("IDLE"), - first.eq(1) - ).Elif(source.stb & source.ack, - first.eq(0) - ) - ] - self.comb += last.eq((counter.value + 4) >= fifo.source.length) - self.sync += last_d.eq(last) - - # memory - rd_slot = fifo.source.slot - - mems = [None]*nslots - ports = [None]*nslots - for n in range(nslots): - mems[n] = Memory(dw, depth) - ports[n] = mems[n].get_port() - self.specials += ports[n] - self.mems = mems - - cases = {} - for n, port in enumerate(ports): - self.comb += ports[n].adr.eq(counter.value[2:]) - cases[n] = [source.data.eq(port.dat_r)] - self.comb += Case(rd_slot, cases) + def __init__(self, dw, depth, nslots=2): + self.source = source = Source(eth_phy_description(dw)) + + slotbits = max(log2_int(nslots), 1) + lengthbits = log2_int(depth*4) # length in bytes + self.lengthbits = lengthbits + + self._start = CSR() + self._ready = CSRStatus() + self._slot = CSRStorage(slotbits) + self._length = CSRStorage(lengthbits) + + self.submodules.ev = EventManager() + self.ev.done = EventSourcePulse() + self.ev.finalize() + + ### + + # command fifo + fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots) + self.submodules += fifo + self.comb += [ + fifo.sink.stb.eq(self._start.re), + fifo.sink.slot.eq(self._slot.storage), + fifo.sink.length.eq(self._length.storage), + self._ready.status.eq(fifo.sink.ack) + ] + + # length computation + self.submodules.counter = counter = Counter(lengthbits, increment=4) + + # fsm + first = Signal() + last = Signal() + last_d = Signal() + + fsm = FSM(reset_state="IDLE") + self.submodules += fsm + + fsm.act("IDLE", + counter.reset.eq(1), + If(fifo.source.stb, + NextState("CHECK") + ) + ) + fsm.act("CHECK", + If(~last_d, + NextState("SEND"), + ).Else( + NextState("END"), + ) + ) + length_lsb = fifo.source.length[0:2] + self.comb += [ + If(last, + If(length_lsb == 3, + source.last_be.eq(0b0010) + ).Elif(length_lsb == 2, + source.last_be.eq(0b0100) + ).Elif(length_lsb == 1, + source.last_be.eq(0b1000) + ).Else( + source.last_be.eq(0b0001) + ) + ) + ] + fsm.act("SEND", + source.stb.eq(1), + source.sop.eq(first), + source.eop.eq(last), + If(source.ack, + counter.ce.eq(~last), + NextState("CHECK") + ) + ) + fsm.act("END", + fifo.source.ack.eq(1), + self.ev.done.trigger.eq(1), + NextState("IDLE") + ) + + # first/last computation + self.sync += [ + If(fsm.ongoing("IDLE"), + first.eq(1) + ).Elif(source.stb & source.ack, + first.eq(0) + ) + ] + self.comb += last.eq((counter.value + 4) >= fifo.source.length) + self.sync += last_d.eq(last) + + # memory + rd_slot = fifo.source.slot + + mems = [None]*nslots + ports = [None]*nslots + for n in range(nslots): + mems[n] = Memory(dw, depth) + ports[n] = mems[n].get_port() + self.specials += ports[n] + self.mems = mems + + cases = {} + for n, port in enumerate(ports): + self.comb += ports[n].adr.eq(counter.value[2:]) + cases[n] = [source.data.eq(port.dat_r)] + self.comb += Case(rd_slot, cases) class LiteEthMACSRAM(Module, AutoCSR): - def __init__(self, dw, depth, nrxslots, ntxslots): - self.submodules.writer = LiteEthMACSRAMWriter(dw, depth, nrxslots) - self.submodules.reader = LiteEthMACSRAMReader(dw, depth, ntxslots) - self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev) - self.sink, self.source = self.writer.sink, self.reader.source + def __init__(self, dw, depth, nrxslots, ntxslots): + self.submodules.writer = LiteEthMACSRAMWriter(dw, depth, nrxslots) + self.submodules.reader = LiteEthMACSRAMReader(dw, depth, ntxslots) + self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev) + self.sink, self.source = self.writer.sink, self.reader.source diff --git a/misoclib/com/liteeth/mac/frontend/wishbone.py b/misoclib/com/liteeth/mac/frontend/wishbone.py index 46e00936..240df40e 100644 --- a/misoclib/com/liteeth/mac/frontend/wishbone.py +++ b/misoclib/com/liteeth/mac/frontend/wishbone.py @@ -6,34 +6,34 @@ from migen.bus import wishbone from migen.fhdl.simplify import FullMemoryWE class LiteEthMACWishboneInterface(Module, AutoCSR): - def __init__(self, dw, nrxslots=2, ntxslots=2): - self.sink = Sink(eth_phy_description(dw)) - self.source = Source(eth_phy_description(dw)) - self.bus = wishbone.Interface() - ### - # storage in SRAM - sram_depth = buffer_depth//(dw//8) - self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots) - self.comb += [ - Record.connect(self.sink, self.sram.sink), - Record.connect(self.sram.source, self.source) - ] + def __init__(self, dw, nrxslots=2, ntxslots=2): + self.sink = Sink(eth_phy_description(dw)) + self.source = Source(eth_phy_description(dw)) + self.bus = wishbone.Interface() + ### + # storage in SRAM + sram_depth = buffer_depth//(dw//8) + self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots) + self.comb += [ + Record.connect(self.sink, self.sram.sink), + Record.connect(self.sram.source, self.source) + ] - # Wishbone interface - wb_rx_sram_ifs = [wishbone.SRAM(self.sram.writer.mems[n], read_only=True) - for n in range(nrxslots)] - # TODO: FullMemoryWE should move to Mibuild - wb_tx_sram_ifs = [FullMemoryWE()(wishbone.SRAM(self.sram.reader.mems[n], read_only=False)) - for n in range(ntxslots)] - wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs + # Wishbone interface + wb_rx_sram_ifs = [wishbone.SRAM(self.sram.writer.mems[n], read_only=True) + for n in range(nrxslots)] + # TODO: FullMemoryWE should move to Mibuild + wb_tx_sram_ifs = [FullMemoryWE()(wishbone.SRAM(self.sram.reader.mems[n], read_only=False)) + for n in range(ntxslots)] + wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs - wb_slaves = [] - decoderoffset = log2_int(sram_depth) - decoderbits = log2_int(len(wb_sram_ifs)) - for n, wb_sram_if in enumerate(wb_sram_ifs): - def slave_filter(a, v=n): - return a[decoderoffset:decoderoffset+decoderbits] == v - wb_slaves.append((slave_filter, wb_sram_if.bus)) - self.submodules += wb_sram_if - wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True) - self.submodules += wb_con + wb_slaves = [] + decoderoffset = log2_int(sram_depth) + decoderbits = log2_int(len(wb_sram_ifs)) + for n, wb_sram_if in enumerate(wb_sram_ifs): + def slave_filter(a, v=n): + return a[decoderoffset:decoderoffset+decoderbits] == v + wb_slaves.append((slave_filter, wb_sram_if.bus)) + self.submodules += wb_sram_if + wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True) + self.submodules += wb_con diff --git a/misoclib/com/liteeth/phy/__init__.py b/misoclib/com/liteeth/phy/__init__.py index 1b1c354f..533fbd05 100644 --- a/misoclib/com/liteeth/phy/__init__.py +++ b/misoclib/com/liteeth/phy/__init__.py @@ -2,23 +2,23 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * def LiteEthPHY(clock_pads, pads, **kwargs): - # Autodetect PHY - if hasattr(pads, "source_stb"): - # This is a simulation PHY - from misoclib.com.liteeth.phy.sim import LiteEthPHYSim - return LiteEthPHYSim(pads) - elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8: - if hasattr(clock_pads, "tx"): - # This is a 10/100/1G PHY - from misoclib.com.liteeth.phy.gmii_mii import LiteEthPHYGMIIMII - return LiteEthPHYGMIIMII(clock_pads, pads, **kwargs) - else: - # This is a pure 1G PHY - from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII - return LiteEthPHYGMII(clock_pads, pads, **kwargs) - elif flen(pads.tx_data) == 4: - # This is a MII PHY - from misoclib.com.liteeth.phy.mii import LiteEthPHYMII - return LiteEthPHYMII(clock_pads, pads, **kwargs) - else: - raise ValueError("Unable to autodetect PHY from platform file, use direct instantiation") + # Autodetect PHY + if hasattr(pads, "source_stb"): + # This is a simulation PHY + from misoclib.com.liteeth.phy.sim import LiteEthPHYSim + return LiteEthPHYSim(pads) + elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8: + if hasattr(clock_pads, "tx"): + # This is a 10/100/1G PHY + from misoclib.com.liteeth.phy.gmii_mii import LiteEthPHYGMIIMII + return LiteEthPHYGMIIMII(clock_pads, pads, **kwargs) + else: + # This is a pure 1G PHY + from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII + return LiteEthPHYGMII(clock_pads, pads, **kwargs) + elif flen(pads.tx_data) == 4: + # This is a MII PHY + from misoclib.com.liteeth.phy.mii import LiteEthPHYMII + return LiteEthPHYMII(clock_pads, pads, **kwargs) + else: + raise ValueError("Unable to autodetect PHY from platform file, use direct instantiation") diff --git a/misoclib/com/liteeth/phy/gmii.py b/misoclib/com/liteeth/phy/gmii.py index 242da110..c1712b97 100644 --- a/misoclib/com/liteeth/phy/gmii.py +++ b/misoclib/com/liteeth/phy/gmii.py @@ -4,82 +4,82 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthPHYGMIITX(Module): - def __init__(self, pads, pads_register): - self.sink = sink = Sink(eth_phy_description(8)) - ### - if hasattr(pads, "tx_er"): - self.sync += pads.tx_er.eq(0) - pads_eq = [ - pads.tx_en.eq(sink.stb), - pads.tx_data.eq(sink.data) - ] - if pads_register: - self.sync += pads_eq - else: - self.comb += pads_eq - self.comb += sink.ack.eq(1) + def __init__(self, pads, pads_register): + self.sink = sink = Sink(eth_phy_description(8)) + ### + if hasattr(pads, "tx_er"): + self.sync += pads.tx_er.eq(0) + pads_eq = [ + pads.tx_en.eq(sink.stb), + pads.tx_data.eq(sink.data) + ] + if pads_register: + self.sync += pads_eq + else: + self.comb += pads_eq + self.comb += sink.ack.eq(1) class LiteEthPHYGMIIRX(Module): - def __init__(self, pads): - self.source = source = Source(eth_phy_description(8)) - ### - dv_d = Signal() - self.sync += dv_d.eq(pads.dv) + def __init__(self, pads): + self.source = source = Source(eth_phy_description(8)) + ### + dv_d = Signal() + self.sync += dv_d.eq(pads.dv) - sop = Signal() - eop = Signal() - self.comb += [ - sop.eq(pads.dv & ~dv_d), - eop.eq(~pads.dv & dv_d) - ] - self.sync += [ - source.stb.eq(pads.dv), - source.sop.eq(sop), - source.data.eq(pads.rx_data) - ] - self.comb += source.eop.eq(eop) + sop = Signal() + eop = Signal() + self.comb += [ + sop.eq(pads.dv & ~dv_d), + eop.eq(~pads.dv & dv_d) + ] + self.sync += [ + source.stb.eq(pads.dv), + source.sop.eq(sop), + source.data.eq(pads.rx_data) + ] + self.comb += source.eop.eq(eop) class LiteEthPHYGMIICRG(Module, AutoCSR): - def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0): - self._reset = CSRStorage() - ### - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() + def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0): + self._reset = CSRStorage() + ### + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() # RX : Let the synthesis tool insert the appropriate clock buffer - self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) + self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) - # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused - # MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx - self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx")) - # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer? - self.specials += Instance("BUFGMUX", - i_I0=self.cd_eth_rx.clk, - i_I1=clock_pads.tx, - i_S=mii_mode, - o_O=self.cd_eth_tx.clk) + # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused + # MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx + self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx")) + # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer? + self.specials += Instance("BUFGMUX", + i_I0=self.cd_eth_rx.clk, + i_I1=clock_pads.tx, + i_S=mii_mode, + o_O=self.cd_eth_tx.clk) - if with_hw_init_reset: - reset = Signal() - counter_done = Signal() - self.submodules.counter = counter = Counter(max=512) - self.comb += [ - counter_done.eq(counter.value == 256), - counter.ce.eq(~counter_done), - reset.eq(~counter_done | self._reset.storage) - ] - else: - reset = self._reset.storage - self.comb += pads.rst_n.eq(~reset) - self.specials += [ - AsyncResetSynchronizer(self.cd_eth_tx, reset), - AsyncResetSynchronizer(self.cd_eth_rx, reset), - ] + if with_hw_init_reset: + reset = Signal() + counter_done = Signal() + self.submodules.counter = counter = Counter(max=512) + self.comb += [ + counter_done.eq(counter.value == 256), + counter.ce.eq(~counter_done), + reset.eq(~counter_done | self._reset.storage) + ] + else: + reset = self._reset.storage + self.comb += pads.rst_n.eq(~reset) + self.specials += [ + AsyncResetSynchronizer(self.cd_eth_tx, reset), + AsyncResetSynchronizer(self.cd_eth_rx, reset), + ] class LiteEthPHYGMII(Module, AutoCSR): - def __init__(self, clock_pads, pads, with_hw_init_reset=True): - self.dw = 8 - self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset) - self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads), "eth_tx") - self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads), "eth_rx") - self.sink, self.source = self.tx.sink, self.rx.source + def __init__(self, clock_pads, pads, with_hw_init_reset=True): + self.dw = 8 + self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset) + self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads), "eth_tx") + self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads), "eth_rx") + self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/com/liteeth/phy/gmii_mii.py b/misoclib/com/liteeth/phy/gmii_mii.py index 32a3ae91..2f5ac7b9 100644 --- a/misoclib/com/liteeth/phy/gmii_mii.py +++ b/misoclib/com/liteeth/phy/gmii_mii.py @@ -10,92 +10,92 @@ from misoclib.com.liteeth.phy.mii import LiteEthPHYMIITX, LiteEthPHYMIIRX from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIITX, LiteEthPHYGMIIRX modes = { - "GMII" : 0, - "MII" : 1 + "GMII" : 0, + "MII" : 1 } tx_pads_layout = [("tx_er", 1), ("tx_en", 1), ("tx_data", 8)] rx_pads_layout = [("rx_er", 1), ("dv", 1), ("rx_data", 8)] class LiteEthPHYGMIIMIITX(Module): - def __init__(self, pads, mode): - self.sink = sink = Sink(eth_phy_description(8)) - ### - gmii_tx_pads = Record(tx_pads_layout) - gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads, pads_register=False) - self.submodules += gmii_tx + def __init__(self, pads, mode): + self.sink = sink = Sink(eth_phy_description(8)) + ### + gmii_tx_pads = Record(tx_pads_layout) + gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads, pads_register=False) + self.submodules += gmii_tx - mii_tx_pads = Record(tx_pads_layout) - mii_tx = LiteEthPHYMIITX(mii_tx_pads, pads_register=False) - self.submodules += mii_tx + mii_tx_pads = Record(tx_pads_layout) + mii_tx = LiteEthPHYMIITX(mii_tx_pads, pads_register=False) + self.submodules += mii_tx - demux = Demultiplexer(eth_phy_description(8), 2) - self.submodules += demux - self.comb += [ - demux.sel.eq(mode==modes["MII"]), - Record.connect(sink, demux.sink), - Record.connect(demux.source0, gmii_tx.sink), - Record.connect(demux.source1, mii_tx.sink), - ] + demux = Demultiplexer(eth_phy_description(8), 2) + self.submodules += demux + self.comb += [ + demux.sel.eq(mode==modes["MII"]), + Record.connect(sink, demux.sink), + Record.connect(demux.source0, gmii_tx.sink), + Record.connect(demux.source1, mii_tx.sink), + ] - if hasattr(pads, "tx_er"): - self.comb += pads.tx_er.eq(0) - self.sync += [ - If(mode==modes["MII"], - pads.tx_en.eq(mii_tx_pads.tx_en), - pads.tx_data.eq(mii_tx_pads.tx_data), - ).Else( - pads.tx_en.eq(gmii_tx_pads.tx_en), - pads.tx_data.eq(gmii_tx_pads.tx_data), - ) - ] + if hasattr(pads, "tx_er"): + self.comb += pads.tx_er.eq(0) + self.sync += [ + If(mode==modes["MII"], + pads.tx_en.eq(mii_tx_pads.tx_en), + pads.tx_data.eq(mii_tx_pads.tx_data), + ).Else( + pads.tx_en.eq(gmii_tx_pads.tx_en), + pads.tx_data.eq(gmii_tx_pads.tx_data), + ) + ] class LiteEthPHYGMIIMIIRX(Module): - def __init__(self, pads, mode): - self.source = source = Source(eth_phy_description(8)) - ### - pads_d = Record(rx_pads_layout) - self.sync += [ - pads_d.dv.eq(pads.dv), - pads_d.rx_data.eq(pads.rx_data) - ] + def __init__(self, pads, mode): + self.source = source = Source(eth_phy_description(8)) + ### + pads_d = Record(rx_pads_layout) + self.sync += [ + pads_d.dv.eq(pads.dv), + pads_d.rx_data.eq(pads.rx_data) + ] - gmii_rx = LiteEthPHYGMIIRX(pads_d) - self.submodules += gmii_rx + gmii_rx = LiteEthPHYGMIIRX(pads_d) + self.submodules += gmii_rx - mii_rx = LiteEthPHYMIIRX(pads_d) - self.submodules += mii_rx + mii_rx = LiteEthPHYMIIRX(pads_d) + self.submodules += mii_rx - mux = Multiplexer(eth_phy_description(8), 2) - self.submodules += mux - self.comb += [ - mux.sel.eq(mode==modes["MII"]), - Record.connect(gmii_rx.source, mux.sink0), - Record.connect(mii_rx.source, mux.sink1), - Record.connect(mux.source, source) - ] + mux = Multiplexer(eth_phy_description(8), 2) + self.submodules += mux + self.comb += [ + mux.sel.eq(mode==modes["MII"]), + Record.connect(gmii_rx.source, mux.sink0), + Record.connect(mii_rx.source, mux.sink1), + Record.connect(mux.source, source) + ] class LiteEthGMIIMIIClockCounter(Module, AutoCSR): - def __init__(self): - self._reset = CSRStorage() - self._value = CSRStatus(32) - ### - counter = RenameClockDomains(Counter(32), "eth_rx") - self.submodules += counter - self.comb += [ - counter.reset.eq(self._reset.storage), #slow, don't need CDC - counter.ce.eq(1), - ] - self.specials += MultiReg(counter.value, self._value.status) + def __init__(self): + self._reset = CSRStorage() + self._value = CSRStatus(32) + ### + counter = RenameClockDomains(Counter(32), "eth_rx") + self.submodules += counter + self.comb += [ + counter.reset.eq(self._reset.storage), #slow, don't need CDC + counter.ce.eq(1), + ] + self.specials += MultiReg(counter.value, self._value.status) class LiteEthPHYGMIIMII(Module, AutoCSR): - def __init__(self, clock_pads, pads, with_hw_init_reset=True): - self.dw = 8 - self._mode = CSRStorage() - mode = self._mode.storage - # Note: we can use GMII CRG since it also handles tx clock pad used for MII - self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode==modes["MII"]) - self.submodules.clock_counter = LiteEthGMIIMIIClockCounter() - self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx") - self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx") - self.sink, self.source = self.tx.sink, self.rx.source + def __init__(self, clock_pads, pads, with_hw_init_reset=True): + self.dw = 8 + self._mode = CSRStorage() + mode = self._mode.storage + # Note: we can use GMII CRG since it also handles tx clock pad used for MII + self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode==modes["MII"]) + self.submodules.clock_counter = LiteEthGMIIMIIClockCounter() + self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx") + self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx") + self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/com/liteeth/phy/loopback.py b/misoclib/com/liteeth/phy/loopback.py index 8fa8ac10..9658c5a5 100644 --- a/misoclib/com/liteeth/phy/loopback.py +++ b/misoclib/com/liteeth/phy/loopback.py @@ -2,26 +2,26 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthPHYLoopbackCRG(Module, AutoCSR): - def __init__(self): - self._reset = CSRStorage() - ### - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()) - ] + def __init__(self): + self._reset = CSRStorage() + ### + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()) + ] - reset = self._reset.storage - self.comb += [ - self.cd_eth_rx.rst.eq(reset), - self.cd_eth_tx.rst.eq(reset) - ] + reset = self._reset.storage + self.comb += [ + self.cd_eth_rx.rst.eq(reset), + self.cd_eth_tx.rst.eq(reset) + ] class LiteEthPHYLoopback(Module, AutoCSR): - def __init__(self): - self.dw = 8 - self.submodules.crg = LiteEthLoopbackPHYCRG() - self.sink = sink = Sink(eth_phy_description(8)) - self.source = source = Source(eth_phy_description(8)) - self.comb += Record.connect(self.sink, self.source) + def __init__(self): + self.dw = 8 + self.submodules.crg = LiteEthLoopbackPHYCRG() + self.sink = sink = Sink(eth_phy_description(8)) + self.source = source = Source(eth_phy_description(8)) + self.comb += Record.connect(self.sink, self.source) diff --git a/misoclib/com/liteeth/phy/mii.py b/misoclib/com/liteeth/phy/mii.py index 3f7b48e3..cd6ba499 100644 --- a/misoclib/com/liteeth/phy/mii.py +++ b/misoclib/com/liteeth/phy/mii.py @@ -2,89 +2,89 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * def converter_description(dw): - payload_layout = [("data", dw)] - return EndpointDescription(payload_layout, packetized=True) + payload_layout = [("data", dw)] + return EndpointDescription(payload_layout, packetized=True) class LiteEthPHYMIITX(Module): - def __init__(self, pads, pads_register=True): - self.sink = sink = Sink(eth_phy_description(8)) - ### - if hasattr(pads, "tx_er"): - self.sync += pads.tx_er.eq(0) - converter = Converter(converter_description(8), converter_description(4)) - self.submodules += converter - self.comb += [ - converter.sink.stb.eq(sink.stb), - converter.sink.data.eq(sink.data), - sink.ack.eq(converter.sink.ack), - converter.source.ack.eq(1) - ] - pads_eq = [ - pads.tx_en.eq(converter.source.stb), - pads.tx_data.eq(converter.source.data) - ] - if pads_register: - self.sync += pads_eq - else: - self.comb += pads_eq + def __init__(self, pads, pads_register=True): + self.sink = sink = Sink(eth_phy_description(8)) + ### + if hasattr(pads, "tx_er"): + self.sync += pads.tx_er.eq(0) + converter = Converter(converter_description(8), converter_description(4)) + self.submodules += converter + self.comb += [ + converter.sink.stb.eq(sink.stb), + converter.sink.data.eq(sink.data), + sink.ack.eq(converter.sink.ack), + converter.source.ack.eq(1) + ] + pads_eq = [ + pads.tx_en.eq(converter.source.stb), + pads.tx_data.eq(converter.source.data) + ] + if pads_register: + self.sync += pads_eq + else: + self.comb += pads_eq class LiteEthPHYMIIRX(Module): - def __init__(self, pads): - self.source = source = Source(eth_phy_description(8)) - ### - sop = FlipFlop(reset=1) - self.submodules += sop + def __init__(self, pads): + self.source = source = Source(eth_phy_description(8)) + ### + sop = FlipFlop(reset=1) + self.submodules += sop - converter = Converter(converter_description(4), converter_description(8)) - converter = InsertReset(converter) - self.submodules += converter + converter = Converter(converter_description(4), converter_description(8)) + converter = InsertReset(converter) + self.submodules += converter - self.sync += [ - converter.reset.eq(~pads.dv), - converter.sink.stb.eq(1), - converter.sink.data.eq(pads.rx_data) - ] - self.comb += [ - sop.reset.eq(~pads.dv), - sop.ce.eq(pads.dv), - converter.sink.sop.eq(sop.q), - converter.sink.eop.eq(~pads.dv) - ] - self.comb += Record.connect(converter.source, source) + self.sync += [ + converter.reset.eq(~pads.dv), + converter.sink.stb.eq(1), + converter.sink.data.eq(pads.rx_data) + ] + self.comb += [ + sop.reset.eq(~pads.dv), + sop.ce.eq(pads.dv), + converter.sink.sop.eq(sop.q), + converter.sink.eop.eq(~pads.dv) + ] + self.comb += Record.connect(converter.source, source) class LiteEthPHYMIICRG(Module, AutoCSR): - def __init__(self, clock_pads, pads, with_hw_init_reset): - self._reset = CSRStorage() - ### - if hasattr(clock_pads, "phy"): - self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy) + def __init__(self, clock_pads, pads, with_hw_init_reset): + self._reset = CSRStorage() + ### + if hasattr(clock_pads, "phy"): + self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy) - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) - self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx) + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) + self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx) - if with_hw_init_reset: - reset = Signal() - counter_done = Signal() - self.submodules.counter = counter = Counter(max=512) - self.comb += [ - counter_done.eq(counter.value == 256), - counter.ce.eq(~counter_done), - reset.eq(~counter_done | self._reset.storage) - ] - else: - reset = self._reset.storage - self.comb += pads.rst_n.eq(~reset) - self.specials += [ - AsyncResetSynchronizer(self.cd_eth_tx, reset), - AsyncResetSynchronizer(self.cd_eth_rx, reset), - ] + if with_hw_init_reset: + reset = Signal() + counter_done = Signal() + self.submodules.counter = counter = Counter(max=512) + self.comb += [ + counter_done.eq(counter.value == 256), + counter.ce.eq(~counter_done), + reset.eq(~counter_done | self._reset.storage) + ] + else: + reset = self._reset.storage + self.comb += pads.rst_n.eq(~reset) + self.specials += [ + AsyncResetSynchronizer(self.cd_eth_tx, reset), + AsyncResetSynchronizer(self.cd_eth_rx, reset), + ] class LiteEthPHYMII(Module, AutoCSR): - def __init__(self, clock_pads, pads, with_hw_init_reset=True): - self.dw = 8 - self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads, with_hw_init_reset) - self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx") - self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx") - self.sink, self.source = self.tx.sink, self.rx.source + def __init__(self, clock_pads, pads, with_hw_init_reset=True): + self.dw = 8 + self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads, with_hw_init_reset) + self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx") + self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx") + self.sink, self.source = self.tx.sink, self.rx.source diff --git a/misoclib/com/liteeth/phy/sim.py b/misoclib/com/liteeth/phy/sim.py index da7124e6..c3f08832 100644 --- a/misoclib/com/liteeth/phy/sim.py +++ b/misoclib/com/liteeth/phy/sim.py @@ -4,54 +4,54 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.generic import * class LiteEthPHYSimCRG(Module, AutoCSR): - def __init__(self): - self._reset = CSRStorage() + def __init__(self): + self._reset = CSRStorage() - ### + ### - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()) - ] + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()) + ] - reset = self._reset.storage - self.comb += [ - self.cd_eth_rx.rst.eq(reset), - self.cd_eth_tx.rst.eq(reset) - ] + reset = self._reset.storage + self.comb += [ + self.cd_eth_rx.rst.eq(reset), + self.cd_eth_tx.rst.eq(reset) + ] class LiteEthPHYSim(Module, AutoCSR): - def __init__(self, pads, tap="tap0", ip_address="192.168.0.14"): - self.dw = 8 - self.submodules.crg = LiteEthPHYSimCRG() - self.sink = sink = Sink(eth_phy_description(8)) - self.source = source = Source(eth_phy_description(8)) - self.tap = tap - self.ip_address = ip_address - - self.comb += [ - pads.source_stb.eq(self.sink.stb), - pads.source_data.eq(self.sink.data), - self.sink.ack.eq(1) - ] - - self.sync += [ - self.source.stb.eq(pads.sink_stb), - self.source.sop.eq(pads.sink_stb & ~self.source.stb), - self.source.data.eq(pads.sink_data), - ] - self.comb += [ - self.source.eop.eq(~pads.sink_stb & self.source.stb), - ] - - # XXX avoid use of os.system - os.system("openvpn --mktun --dev {}".format(self.tap)) - os.system("ifconfig {} {} up".format(self.tap, self.ip_address)) - os.system("mknod /dev/net/{} c 10 200".format(self.tap)) - - def do_exit(self, *args, **kwargs): - # XXX avoid use of os.system - os.system("rm -f /dev/net/{}".format(self.tap)) - os.system("openvpn --rmtun --dev {}".format(self.tap)) + def __init__(self, pads, tap="tap0", ip_address="192.168.0.14"): + self.dw = 8 + self.submodules.crg = LiteEthPHYSimCRG() + self.sink = sink = Sink(eth_phy_description(8)) + self.source = source = Source(eth_phy_description(8)) + self.tap = tap + self.ip_address = ip_address + + self.comb += [ + pads.source_stb.eq(self.sink.stb), + pads.source_data.eq(self.sink.data), + self.sink.ack.eq(1) + ] + + self.sync += [ + self.source.stb.eq(pads.sink_stb), + self.source.sop.eq(pads.sink_stb & ~self.source.stb), + self.source.data.eq(pads.sink_data), + ] + self.comb += [ + self.source.eop.eq(~pads.sink_stb & self.source.stb), + ] + + # XXX avoid use of os.system + os.system("openvpn --mktun --dev {}".format(self.tap)) + os.system("ifconfig {} {} up".format(self.tap, self.ip_address)) + os.system("mknod /dev/net/{} c 10 200".format(self.tap)) + + def do_exit(self, *args, **kwargs): + # XXX avoid use of os.system + os.system("rm -f /dev/net/{}".format(self.tap)) + os.system("openvpn --rmtun --dev {}".format(self.tap)) diff --git a/misoclib/com/liteeth/test/arp_tb.py b/misoclib/com/liteeth/test/arp_tb.py index a6df434d..f2dedfd6 100644 --- a/misoclib/com/liteeth/test/arp_tb.py +++ b/misoclib/com/liteeth/test/arp_tb.py @@ -14,44 +14,44 @@ ip_address = 0x12345678 mac_address = 0x12345678abcd class TB(Module): - def __init__(self): - 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) - - self.submodules.mac = LiteEthMAC(self.phy_model, dw=8, with_hw_preamble_crc=True) - self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, 100000) - - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - for i in range(100): - yield - - while selfp.arp.table.request.ack != 1: - selfp.arp.table.request.stb = 1 - selfp.arp.table.request.ip_address = 0x12345678 - yield - selfp.arp.table.request.stb = 0 - while selfp.arp.table.response.stb != 1: - selfp.arp.table.response.ack = 1 - yield - print("Received MAC : 0x{:12x}".format(selfp.arp.table.response.mac_address)) + def __init__(self): + 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) + + self.submodules.mac = LiteEthMAC(self.phy_model, dw=8, with_hw_preamble_crc=True) + self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, 100000) + + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] + + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 + + for i in range(100): + yield + + while selfp.arp.table.request.ack != 1: + selfp.arp.table.request.stb = 1 + selfp.arp.table.request.ip_address = 0x12345678 + yield + selfp.arp.table.request.stb = 0 + while selfp.arp.table.response.stb != 1: + selfp.arp.table.response.ack = 1 + yield + print("Received MAC : 0x{:12x}".format(selfp.arp.table.response.mac_address)) if __name__ == "__main__": - run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True) diff --git a/misoclib/com/liteeth/test/common.py b/misoclib/com/liteeth/test/common.py index 6519aff2..fb427309 100644 --- a/misoclib/com/liteeth/test/common.py +++ b/misoclib/com/liteeth/test/common.py @@ -7,156 +7,156 @@ from migen.genlib.record import * from misoclib.com.liteeth.common import * def print_with_prefix(s, prefix=""): - if not isinstance(s, str): - s = s.__repr__() - s = s.split("\n") - for l in s: - print(prefix + l) + if not isinstance(s, str): + s = s.__repr__() + s = s.split("\n") + for l in s: + print(prefix + l) def seed_to_data(seed, random=True): - if random: - return (seed * 0x31415979 + 1) & 0xffffffff - else: - return seed + if random: + return (seed * 0x31415979 + 1) & 0xffffffff + else: + return seed def split_bytes(v, n, endianness="big"): - r = [] - r_bytes = v.to_bytes(n, byteorder=endianness) - for byte in r_bytes: - r.append(int(byte)) - return r + r = [] + r_bytes = v.to_bytes(n, byteorder=endianness) + for byte in r_bytes: + r.append(int(byte)) + return r def merge_bytes(b, endianness="big"): - return int.from_bytes(bytes(b), endianness) + return int.from_bytes(bytes(b), endianness) def get_field_data(field, datas): - v = merge_bytes(datas[field.byte:field.byte+math.ceil(field.width/8)]) - return (v >> field.offset) & (2**field.width-1) + v = merge_bytes(datas[field.byte:field.byte+math.ceil(field.width/8)]) + return (v >> field.offset) & (2**field.width-1) def comp(p1, p2): - r = True - for x, y in zip(p1, p2): - if x != y: - r = False - return r + r = True + for x, y in zip(p1, p2): + if x != y: + r = False + return r def check(p1, p2): - p1 = copy.deepcopy(p1) - p2 = copy.deepcopy(p2) - if isinstance(p1, int): - return 0, 1, int(p1 != p2) - else: - if len(p1) >= len(p2): - ref, res = p1, p2 - else: - ref, res = p2, p1 - shift = 0 - while((ref[0] != res[0]) and (len(res)>1)): - res.pop(0) - shift += 1 - length = min(len(ref), len(res)) - errors = 0 - for i in range(length): - if ref.pop(0) != res.pop(0): - errors += 1 - return shift, length, errors + p1 = copy.deepcopy(p1) + p2 = copy.deepcopy(p2) + if isinstance(p1, int): + return 0, 1, int(p1 != p2) + else: + if len(p1) >= len(p2): + ref, res = p1, p2 + else: + ref, res = p2, p1 + shift = 0 + while((ref[0] != res[0]) and (len(res)>1)): + res.pop(0) + shift += 1 + length = min(len(ref), len(res)) + errors = 0 + for i in range(length): + if ref.pop(0) != res.pop(0): + errors += 1 + return shift, length, errors def randn(max_n): - return random.randint(0, max_n-1) + return random.randint(0, max_n-1) class Packet(list): - def __init__(self, init=[]): - self.ongoing = False - self.done = False - for data in init: - self.append(data) + def __init__(self, init=[]): + self.ongoing = False + self.done = False + for data in init: + self.append(data) class PacketStreamer(Module): - def __init__(self, description, last_be=None): - self.source = Source(description) - self.last_be = last_be - ### - self.packets = [] - self.packet = Packet() - self.packet.done = True - - def send(self, packet): - packet = copy.deepcopy(packet) - self.packets.append(packet) - return packet - - def send_blocking(self, packet): - packet = self.send(packet) - while not packet.done: - yield - - def do_simulation(self, selfp): - if len(self.packets) and self.packet.done: - self.packet = self.packets.pop(0) - if not self.packet.ongoing and not self.packet.done: - selfp.source.stb = 1 - selfp.source.sop = 1 - selfp.source.data = self.packet.pop(0) - self.packet.ongoing = True - elif selfp.source.stb == 1 and selfp.source.ack == 1: - selfp.source.sop = 0 - if len(self.packet) == 1: - selfp.source.eop = 1 - if self.last_be is not None: - selfp.source.last_be = self.last_be - else: - selfp.source.eop = 0 - if self.last_be is not None: - selfp.source.last_be = 0 - if len(self.packet) > 0: - selfp.source.stb = 1 - selfp.source.data = self.packet.pop(0) - else: - self.packet.done = True - selfp.source.stb = 0 + def __init__(self, description, last_be=None): + self.source = Source(description) + self.last_be = last_be + ### + self.packets = [] + self.packet = Packet() + self.packet.done = True + + def send(self, packet): + packet = copy.deepcopy(packet) + self.packets.append(packet) + return packet + + def send_blocking(self, packet): + packet = self.send(packet) + while not packet.done: + yield + + def do_simulation(self, selfp): + if len(self.packets) and self.packet.done: + self.packet = self.packets.pop(0) + if not self.packet.ongoing and not self.packet.done: + selfp.source.stb = 1 + selfp.source.sop = 1 + selfp.source.data = self.packet.pop(0) + self.packet.ongoing = True + elif selfp.source.stb == 1 and selfp.source.ack == 1: + selfp.source.sop = 0 + if len(self.packet) == 1: + selfp.source.eop = 1 + if self.last_be is not None: + selfp.source.last_be = self.last_be + else: + selfp.source.eop = 0 + if self.last_be is not None: + selfp.source.last_be = 0 + if len(self.packet) > 0: + selfp.source.stb = 1 + selfp.source.data = self.packet.pop(0) + else: + self.packet.done = True + selfp.source.stb = 0 class PacketLogger(Module): - def __init__(self, description): - self.sink = Sink(description) - ### - self.packet = Packet() - - def receive(self): - self.packet.done = False - while not self.packet.done: - yield - - def do_simulation(self, selfp): - selfp.sink.ack = 1 - if selfp.sink.stb == 1 and selfp.sink.sop == 1: - self.packet = Packet() - self.packet.append(selfp.sink.data) - elif selfp.sink.stb: - self.packet.append(selfp.sink.data) - if selfp.sink.stb == 1 and selfp.sink.eop == 1: - self.packet.done = True + def __init__(self, description): + self.sink = Sink(description) + ### + self.packet = Packet() + + def receive(self): + self.packet.done = False + while not self.packet.done: + yield + + def do_simulation(self, selfp): + selfp.sink.ack = 1 + if selfp.sink.stb == 1 and selfp.sink.sop == 1: + self.packet = Packet() + self.packet.append(selfp.sink.data) + elif selfp.sink.stb: + self.packet.append(selfp.sink.data) + if selfp.sink.stb == 1 and selfp.sink.eop == 1: + self.packet.done = True class AckRandomizer(Module): - def __init__(self, description, level=0): - self.level = level - - self.sink = Sink(description) - self.source = Source(description) - - self.run = Signal() - - self.comb += \ - If(self.run, - Record.connect(self.sink, self.source) - ).Else( - self.source.stb.eq(0), - self.sink.ack.eq(0), - ) - - def do_simulation(self, selfp): - n = randn(100) - if n < self.level: - selfp.run = 0 - else: - selfp.run = 1 + def __init__(self, description, level=0): + self.level = level + + self.sink = Sink(description) + self.source = Source(description) + + self.run = Signal() + + self.comb += \ + If(self.run, + Record.connect(self.sink, self.source) + ).Else( + self.source.stb.eq(0), + self.sink.ack.eq(0), + ) + + def do_simulation(self, selfp): + n = randn(100) + if n < self.level: + selfp.run = 0 + else: + selfp.run = 1 diff --git a/misoclib/com/liteeth/test/etherbone_tb.py b/misoclib/com/liteeth/test/etherbone_tb.py index 5f751b04..97531467 100644 --- a/misoclib/com/liteeth/test/etherbone_tb.py +++ b/misoclib/com/liteeth/test/etherbone_tb.py @@ -14,103 +14,103 @@ ip_address = 0x12345678 mac_address = 0x12345678abcd class TB(Module): - def __init__(self): - 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) - self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False) - self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=False) - self.submodules.etherbone_model = etherbone.Etherbone(self.udp_model, debug=False) - - self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000) - self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) - - self.submodules.sram = wishbone.SRAM(1024) - self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.etherbone.master.bus, self.sram.bus) - - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - for i in range(100): - yield - - test_probe = True - test_writes = True - test_reads = True - - # test probe - if test_probe: - packet = etherbone.EtherbonePacket() - packet.pf = 1 - self.etherbone_model.send(packet) - yield from self.etherbone_model.receive() - print("probe: " + str(bool(self.etherbone_model.rx_packet.pr))) - - for i in range(8): - # test writes - if test_writes: - writes_datas = [j for j in range(16)] - writes = etherbone.EtherboneWrites(base_addr=0x1000, datas=writes_datas) - record = etherbone.EtherboneRecord() - record.writes = writes - record.reads = None - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0xf - record.wcount = len(writes_datas) - record.rcount = 0 - - packet = etherbone.EtherbonePacket() - packet.records = [record] - self.etherbone_model.send(packet) - for i in range(256): - yield - - # test reads - if test_reads: - reads_addrs = [0x1000 + 4*j for j in range(16)] - reads = etherbone.EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs) - record = etherbone.EtherboneRecord() - record.writes = None - record.reads = reads - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0xf - record.wcount = 0 - record.rcount = len(reads_addrs) - - packet = etherbone.EtherbonePacket() - packet.records = [record] - self.etherbone_model.send(packet) - yield from self.etherbone_model.receive() - loopback_writes_datas = [] - loopback_writes_datas = self.etherbone_model.rx_packet.records.pop().writes.get_datas() - - # check results - s, l, e = check(writes_datas, loopback_writes_datas) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + def __init__(self): + 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) + self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False) + self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=False) + self.submodules.etherbone_model = etherbone.Etherbone(self.udp_model, debug=False) + + self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000) + self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000) + + self.submodules.sram = wishbone.SRAM(1024) + self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.etherbone.master.bus, self.sram.bus) + + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] + + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 + + for i in range(100): + yield + + test_probe = True + test_writes = True + test_reads = True + + # test probe + if test_probe: + packet = etherbone.EtherbonePacket() + packet.pf = 1 + self.etherbone_model.send(packet) + yield from self.etherbone_model.receive() + print("probe: " + str(bool(self.etherbone_model.rx_packet.pr))) + + for i in range(8): + # test writes + if test_writes: + writes_datas = [j for j in range(16)] + writes = etherbone.EtherboneWrites(base_addr=0x1000, datas=writes_datas) + record = etherbone.EtherboneRecord() + record.writes = writes + record.reads = None + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0xf + record.wcount = len(writes_datas) + record.rcount = 0 + + packet = etherbone.EtherbonePacket() + packet.records = [record] + self.etherbone_model.send(packet) + for i in range(256): + yield + + # test reads + if test_reads: + reads_addrs = [0x1000 + 4*j for j in range(16)] + reads = etherbone.EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs) + record = etherbone.EtherboneRecord() + record.writes = None + record.reads = reads + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0xf + record.wcount = 0 + record.rcount = len(reads_addrs) + + packet = etherbone.EtherbonePacket() + packet.records = [record] + self.etherbone_model.send(packet) + yield from self.etherbone_model.receive() + loopback_writes_datas = [] + loopback_writes_datas = self.etherbone_model.rx_packet.records.pop().writes.get_datas() + + # check results + s, l, e = check(writes_datas, loopback_writes_datas) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) if __name__ == "__main__": - run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True) \ No newline at end of file + run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True) \ No newline at end of file diff --git a/misoclib/com/liteeth/test/icmp_tb.py b/misoclib/com/liteeth/test/icmp_tb.py index a34e0606..bade68d6 100644 --- a/misoclib/com/liteeth/test/icmp_tb.py +++ b/misoclib/com/liteeth/test/icmp_tb.py @@ -17,42 +17,42 @@ ip_address = 0x12345678 mac_address = 0x12345678abcd class TB(Module): - def __init__(self): - self.submodules.phy_model = phy.PHY(8, debug=True) - self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False) - self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=True) - self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=True, loopback=False) - self.submodules.icmp_model = icmp.ICMP(self.ip_model, ip_address, debug=True) - - self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000) - - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - for i in range(100): - yield - - packet = MACPacket(ping_request) - packet.decode_remove_header() - packet = IPPacket(packet) - packet.decode() - packet = ICMPPacket(packet) - packet.decode() - self.icmp_model.send(packet) + def __init__(self): + self.submodules.phy_model = phy.PHY(8, debug=True) + self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False) + self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=True) + self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=True, loopback=False) + self.submodules.icmp_model = icmp.ICMP(self.ip_model, ip_address, debug=True) + + self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000) + + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] + + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 + + for i in range(100): + yield + + packet = MACPacket(ping_request) + packet.decode_remove_header() + packet = IPPacket(packet) + packet.decode() + packet = ICMPPacket(packet) + packet.decode() + self.icmp_model.send(packet) if __name__ == "__main__": - run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True) diff --git a/misoclib/com/liteeth/test/ip_tb.py b/misoclib/com/liteeth/test/ip_tb.py index 7652a976..7c581dd5 100644 --- a/misoclib/com/liteeth/test/ip_tb.py +++ b/misoclib/com/liteeth/test/ip_tb.py @@ -13,47 +13,47 @@ ip_address = 0x12345678 mac_address = 0x12345678abcd class TB(Module): - def __init__(self): - 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) - self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True) - - self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000) - self.ip_port = self.ip.ip.crossbar.get_port(udp_protocol) - - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - for i in range(100): - yield - - while True: - selfp.ip_port.sink.stb = 1 - selfp.ip_port.sink.sop = 1 - selfp.ip_port.sink.eop = 1 - selfp.ip_port.sink.ip_address = 0x12345678 - selfp.ip_port.sink.protocol = udp_protocol - - selfp.ip_port.source.ack = 1 - if selfp.ip_port.source.stb == 1 and selfp.ip_port.source.sop == 1: - print("packet from IP 0x{:08x}".format(selfp.ip_port.sink.ip_address)) - - yield + def __init__(self): + 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) + self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True) + + self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000) + self.ip_port = self.ip.ip.crossbar.get_port(udp_protocol) + + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] + + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 + + for i in range(100): + yield + + while True: + selfp.ip_port.sink.stb = 1 + selfp.ip_port.sink.sop = 1 + selfp.ip_port.sink.eop = 1 + selfp.ip_port.sink.ip_address = 0x12345678 + selfp.ip_port.sink.protocol = udp_protocol + + selfp.ip_port.source.ack = 1 + if selfp.ip_port.source.stb == 1 and selfp.ip_port.source.sop == 1: + print("packet from IP 0x{:08x}".format(selfp.ip_port.sink.ip_address)) + + yield if __name__ == "__main__": - run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True) diff --git a/misoclib/com/liteeth/test/mac_core_tb.py b/misoclib/com/liteeth/test/mac_core_tb.py index fe6451bd..2f0edb33 100644 --- a/misoclib/com/liteeth/test/mac_core_tb.py +++ b/misoclib/com/liteeth/test/mac_core_tb.py @@ -10,53 +10,53 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import phy, mac class TB(Module): - def __init__(self): - self.submodules.phy_model = phy.PHY(8, debug=False) - self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True) - self.submodules.core = LiteEthMACCore(phy=self.phy_model, dw=8, with_hw_preamble_crc=True) - - self.submodules.streamer = PacketStreamer(eth_phy_description(8), last_be=1) - self.submodules.streamer_randomizer = AckRandomizer(eth_phy_description(8), level=50) - - self.submodules.logger_randomizer = AckRandomizer(eth_phy_description(8), level=50) - self.submodules.logger = PacketLogger(eth_phy_description(8)) - - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - self.comb += [ - Record.connect(self.streamer.source, self.streamer_randomizer.sink), - Record.connect(self.streamer_randomizer.source, self.core.sink), - Record.connect(self.core.source, self.logger_randomizer.sink), - Record.connect(self.logger_randomizer.source, self.logger.sink) - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - for i in range(8): - packet = mac.MACPacket([i for i in range(64)]) - packet.target_mac = 0x010203040506 - packet.sender_mac = 0x090A0B0C0C0D - packet.ethernet_type = 0x0800 - packet.encode_header() - yield from self.streamer.send(packet) - yield from self.logger.receive() - - # check results - s, l, e = check(packet, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + def __init__(self): + self.submodules.phy_model = phy.PHY(8, debug=False) + self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True) + self.submodules.core = LiteEthMACCore(phy=self.phy_model, dw=8, with_hw_preamble_crc=True) + + self.submodules.streamer = PacketStreamer(eth_phy_description(8), last_be=1) + self.submodules.streamer_randomizer = AckRandomizer(eth_phy_description(8), level=50) + + self.submodules.logger_randomizer = AckRandomizer(eth_phy_description(8), level=50) + self.submodules.logger = PacketLogger(eth_phy_description(8)) + + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] + + self.comb += [ + Record.connect(self.streamer.source, self.streamer_randomizer.sink), + Record.connect(self.streamer_randomizer.source, self.core.sink), + Record.connect(self.core.source, self.logger_randomizer.sink), + Record.connect(self.logger_randomizer.source, self.logger.sink) + ] + + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 + + for i in range(8): + packet = mac.MACPacket([i for i in range(64)]) + packet.target_mac = 0x010203040506 + packet.sender_mac = 0x090A0B0C0C0D + packet.ethernet_type = 0x0800 + packet.encode_header() + yield from self.streamer.send(packet) + yield from self.logger.receive() + + # check results + s, l, e = check(packet, self.logger.packet) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) if __name__ == "__main__": - run_simulation(TB(), ncycles=4000, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(), ncycles=4000, vcd_name="my.vcd", keep_files=True) diff --git a/misoclib/com/liteeth/test/mac_wishbone_tb.py b/misoclib/com/liteeth/test/mac_wishbone_tb.py index 2f6d09cf..e11d451b 100644 --- a/misoclib/com/liteeth/test/mac_wishbone_tb.py +++ b/misoclib/com/liteeth/test/mac_wishbone_tb.py @@ -10,136 +10,136 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import phy, mac class WishboneMaster: - def __init__(self, obj): - self.obj = obj - self.dat = 0 - - def write(self, adr, dat): - self.obj.cyc = 1 - self.obj.stb = 1 - self.obj.adr = adr - self.obj.we = 1 - self.obj.sel = 0xF - self.obj.dat_w = dat - while self.obj.ack == 0: - yield - self.obj.cyc = 0 - self.obj.stb = 0 - yield - - def read(self, adr): - self.obj.cyc = 1 - self.obj.stb = 1 - self.obj.adr = adr - self.obj.we = 0 - self.obj.sel = 0xF - self.obj.dat_w = 0 - while self.obj.ack == 0: - yield - self.dat = self.obj.dat_r - self.obj.cyc = 0 - self.obj.stb = 0 - yield + def __init__(self, obj): + self.obj = obj + self.dat = 0 + + def write(self, adr, dat): + self.obj.cyc = 1 + self.obj.stb = 1 + self.obj.adr = adr + self.obj.we = 1 + self.obj.sel = 0xF + self.obj.dat_w = dat + while self.obj.ack == 0: + yield + self.obj.cyc = 0 + self.obj.stb = 0 + yield + + def read(self, adr): + self.obj.cyc = 1 + self.obj.stb = 1 + self.obj.adr = adr + self.obj.we = 0 + self.obj.sel = 0xF + self.obj.dat_w = 0 + while self.obj.ack == 0: + yield + self.dat = self.obj.dat_r + self.obj.cyc = 0 + self.obj.stb = 0 + yield class SRAMReaderDriver: - def __init__(self, obj): - self.obj = obj - - def start(self, slot, length): - self.obj._slot.storage = slot - self.obj._length.storage = length - self.obj._start.re = 1 - yield - self.obj._start.re = 0 - yield - - def wait_done(self): - while self.obj.ev.done.pending == 0: - yield - - def clear_done(self): - self.obj.ev.done.clear = 1 - yield - self.obj.ev.done.clear = 0 - yield + def __init__(self, obj): + self.obj = obj + + def start(self, slot, length): + self.obj._slot.storage = slot + self.obj._length.storage = length + self.obj._start.re = 1 + yield + self.obj._start.re = 0 + yield + + def wait_done(self): + while self.obj.ev.done.pending == 0: + yield + + def clear_done(self): + self.obj.ev.done.clear = 1 + yield + self.obj.ev.done.clear = 0 + yield class SRAMWriterDriver: - def __init__(self, obj): - self.obj = obj + def __init__(self, obj): + self.obj = obj - def wait_available(self): - while self.obj.ev.available.pending == 0: - yield + def wait_available(self): + while self.obj.ev.available.pending == 0: + yield - def clear_available(self): - self.obj.ev.available.clear = 1 - yield - self.obj.ev.available.clear = 0 - yield + def clear_available(self): + self.obj.ev.available.clear = 1 + yield + self.obj.ev.available.clear = 0 + yield class TB(Module): - def __init__(self): - self.submodules.phy_model = phy.PHY(8, debug=False) - self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True) - self.submodules.ethmac = LiteEthMAC(phy=self.phy_model, dw=32, interface="wishbone", with_hw_preamble_crc=True) - - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] - - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 - - wishbone_master = WishboneMaster(selfp.ethmac.bus) - sram_reader_driver = SRAMReaderDriver(selfp.ethmac.interface.sram.reader) - sram_writer_driver = SRAMWriterDriver(selfp.ethmac.interface.sram.writer) - - sram_writer_slots_offset = [0x000, 0x200] - sram_reader_slots_offset = [0x400, 0x600] - - length = 150+2 - - tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0] - - errors = 0 - - while True: - for slot in range(2): - print("slot {}: ".format(slot), end="") - # fill tx memory - for i in range(length//4+1): - dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big") - yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat) - - # send tx payload & wait - yield from sram_reader_driver.start(slot, length) - yield from sram_reader_driver.wait_done() - yield from sram_reader_driver.clear_done() - - # wait rx - yield from sram_writer_driver.wait_available() - yield from sram_writer_driver.clear_available() - - # get rx payload (loopback on PHY Model) - rx_payload = [] - for i in range(length//4+1): - yield from wishbone_master.read(sram_writer_slots_offset[slot]+i) - dat = wishbone_master.dat - rx_payload += list(dat.to_bytes(4, byteorder='big')) - - # check results - s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))]) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + def __init__(self): + self.submodules.phy_model = phy.PHY(8, debug=False) + self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True) + self.submodules.ethmac = LiteEthMAC(phy=self.phy_model, dw=32, interface="wishbone", with_hw_preamble_crc=True) + + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] + + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 + + wishbone_master = WishboneMaster(selfp.ethmac.bus) + sram_reader_driver = SRAMReaderDriver(selfp.ethmac.interface.sram.reader) + sram_writer_driver = SRAMWriterDriver(selfp.ethmac.interface.sram.writer) + + sram_writer_slots_offset = [0x000, 0x200] + sram_reader_slots_offset = [0x400, 0x600] + + length = 150+2 + + tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0] + + errors = 0 + + while True: + for slot in range(2): + print("slot {}: ".format(slot), end="") + # fill tx memory + for i in range(length//4+1): + dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big") + yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat) + + # send tx payload & wait + yield from sram_reader_driver.start(slot, length) + yield from sram_reader_driver.wait_done() + yield from sram_reader_driver.clear_done() + + # wait rx + yield from sram_writer_driver.wait_available() + yield from sram_writer_driver.clear_available() + + # get rx payload (loopback on PHY Model) + rx_payload = [] + for i in range(length//4+1): + yield from wishbone_master.read(sram_writer_slots_offset[slot]+i) + dat = wishbone_master.dat + rx_payload += list(dat.to_bytes(4, byteorder='big')) + + # check results + s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))]) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) if __name__ == "__main__": - run_simulation(TB(), ncycles=3000, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(), ncycles=3000, vcd_name="my.vcd", keep_files=True) diff --git a/misoclib/com/liteeth/test/model/arp.py b/misoclib/com/liteeth/test/model/arp.py index 9ca58d09..52a12dfc 100644 --- a/misoclib/com/liteeth/test/model/arp.py +++ b/misoclib/com/liteeth/test/model/arp.py @@ -6,147 +6,147 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import mac def print_arp(s): - print_with_prefix(s, "[ARP]") + print_with_prefix(s, "[ARP]") preamble = split_bytes(eth_preamble, 8) # ARP model class ARPPacket(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) - - def decode(self): - header = [] - for byte in self[:arp_header_len]: - header.append(self.pop(0)) - for k, v in sorted(arp_header.items()): - setattr(self, k, get_field_data(v, header)) - - def encode(self): - header = 0 - for k, v in sorted(arp_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, arp_header_len): - self.insert(0, d) - - def __repr__(self): - r = "--------\n" - for k in sorted(arp_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - r += "payload: " - for d in self: - r += "{:02x}".format(d) - return r + def __init__(self, init=[]): + Packet.__init__(self, init) + + def decode(self): + header = [] + for byte in self[:arp_header_len]: + header.append(self.pop(0)) + for k, v in sorted(arp_header.items()): + setattr(self, k, get_field_data(v, header)) + + def encode(self): + header = 0 + for k, v in sorted(arp_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, arp_header_len): + self.insert(0, d) + + def __repr__(self): + r = "--------\n" + for k in sorted(arp_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + r += "payload: " + for d in self: + r += "{:02x}".format(d) + return r class ARP(Module): - def __init__(self, mac, mac_address, ip_address, debug=False): - self.mac = mac - self.mac_address = mac_address - self.ip_address = ip_address - self.debug = debug - self.tx_packets = [] - self.tx_packet = ARPPacket() - self.rx_packet = ARPPacket() - self.table = {} - self.request_pending = False - - self.mac.set_arp_callback(self.callback) - - def send(self, packet): - packet.encode() - if self.debug: - print_arp(">>>>>>>>") - print_arp(packet) - mac_packet = mac.MACPacket(packet) - mac_packet.target_mac = packet.target_mac - mac_packet.sender_mac = packet.sender_mac - mac_packet.ethernet_type = ethernet_type_arp - self.mac.send(mac_packet) - - def callback(self, packet): - packet = ARPPacket(packet) - packet.decode() - if self.debug: - print_arp("<<<<<<<<") - print_arp(packet) - self.process(packet) - - def process(self, packet): - if len(packet) != eth_min_len-arp_header_len: - raise ValueError - if packet.hwtype != arp_hwtype_ethernet: - raise ValueError - if packet.proto != arp_proto_ip: - raise ValueError - if packet.hwsize != 6: - raise ValueError - if packet.protosize != 4: - raise ValueError - if packet.opcode == arp_opcode_request: - self.process_request(packet) - elif packet.opcode == arp_opcode_reply: - self.process_reply(packet) - - def process_request(self, request): - if request.target_ip == self.ip_address: - reply = ARPPacket([0]*(eth_min_len-arp_header_len)) - reply.hwtype = arp_hwtype_ethernet - reply.proto = arp_proto_ip - reply.opcode = arp_opcode_reply - reply.hwsize = 6 - reply.protosize = 4 - reply.sender_mac = self.mac_address - reply.sender_ip = self.ip_address - reply.target_mac = request.sender_mac - reply.target_ip = request.sender_ip - self.send(reply) - - def process_reply(self, reply): - self.table[reply.sender_ip] = reply.sender_mac - - def request(self, ip_address): - request = ARPPacket([0]*(eth_min_len-arp_header_len)) - request.hwtype = arp_hwtype_ethernet - request.proto = arp_proto_ip - request.opcode = arp_opcode_request - request.hwsize = 6 - request.protosize = 4 - request.sender_mac = self.mac_address - request.sender_ip = self.ip_address - request.target_mac = 0xffffffffffff - request.target_ip = ip_address + def __init__(self, mac, mac_address, ip_address, debug=False): + self.mac = mac + self.mac_address = mac_address + self.ip_address = ip_address + self.debug = debug + self.tx_packets = [] + self.tx_packet = ARPPacket() + self.rx_packet = ARPPacket() + self.table = {} + self.request_pending = False + + self.mac.set_arp_callback(self.callback) + + def send(self, packet): + packet.encode() + if self.debug: + print_arp(">>>>>>>>") + print_arp(packet) + mac_packet = mac.MACPacket(packet) + mac_packet.target_mac = packet.target_mac + mac_packet.sender_mac = packet.sender_mac + mac_packet.ethernet_type = ethernet_type_arp + self.mac.send(mac_packet) + + def callback(self, packet): + packet = ARPPacket(packet) + packet.decode() + if self.debug: + print_arp("<<<<<<<<") + print_arp(packet) + self.process(packet) + + def process(self, packet): + if len(packet) != eth_min_len-arp_header_len: + raise ValueError + if packet.hwtype != arp_hwtype_ethernet: + raise ValueError + if packet.proto != arp_proto_ip: + raise ValueError + if packet.hwsize != 6: + raise ValueError + if packet.protosize != 4: + raise ValueError + if packet.opcode == arp_opcode_request: + self.process_request(packet) + elif packet.opcode == arp_opcode_reply: + self.process_reply(packet) + + def process_request(self, request): + if request.target_ip == self.ip_address: + reply = ARPPacket([0]*(eth_min_len-arp_header_len)) + reply.hwtype = arp_hwtype_ethernet + reply.proto = arp_proto_ip + reply.opcode = arp_opcode_reply + reply.hwsize = 6 + reply.protosize = 4 + reply.sender_mac = self.mac_address + reply.sender_ip = self.ip_address + reply.target_mac = request.sender_mac + reply.target_ip = request.sender_ip + self.send(reply) + + def process_reply(self, reply): + self.table[reply.sender_ip] = reply.sender_mac + + def request(self, ip_address): + request = ARPPacket([0]*(eth_min_len-arp_header_len)) + request.hwtype = arp_hwtype_ethernet + request.proto = arp_proto_ip + request.opcode = arp_opcode_request + request.hwsize = 6 + request.protosize = 4 + request.sender_mac = self.mac_address + request.sender_ip = self.ip_address + request.target_mac = 0xffffffffffff + request.target_ip = ip_address if __name__ == "__main__": - from misoclib.com.liteeth.test.model.dumps import * - from misoclib.com.liteeth.test.model.mac import * - errors = 0 - # ARP request - packet = MACPacket(arp_request) - packet.decode_remove_header() - packet = ARPPacket(packet) - # check decoding - packet.decode() - #print(packet) - errors += verify_packet(packet, arp_request_infos) - # check encoding - packet.encode() - packet.decode() - #print(packet) - errors += verify_packet(packet, arp_request_infos) - - # ARP Reply - packet = MACPacket(arp_reply) - packet.decode_remove_header() - packet = ARPPacket(packet) - # check decoding - packet.decode() - #print(packet) - errors += verify_packet(packet, arp_reply_infos) - # check encoding - packet.encode() - packet.decode() - #print(packet) - errors += verify_packet(packet, arp_reply_infos) - - print("arp errors " + str(errors)) \ No newline at end of file + from misoclib.com.liteeth.test.model.dumps import * + from misoclib.com.liteeth.test.model.mac import * + errors = 0 + # ARP request + packet = MACPacket(arp_request) + packet.decode_remove_header() + packet = ARPPacket(packet) + # check decoding + packet.decode() + #print(packet) + errors += verify_packet(packet, arp_request_infos) + # check encoding + packet.encode() + packet.decode() + #print(packet) + errors += verify_packet(packet, arp_request_infos) + + # ARP Reply + packet = MACPacket(arp_reply) + packet.decode_remove_header() + packet = ARPPacket(packet) + # check decoding + packet.decode() + #print(packet) + errors += verify_packet(packet, arp_reply_infos) + # check encoding + packet.encode() + packet.decode() + #print(packet) + errors += verify_packet(packet, arp_reply_infos) + + print("arp errors " + str(errors)) \ No newline at end of file diff --git a/misoclib/com/liteeth/test/model/dumps.py b/misoclib/com/liteeth/test/model/dumps.py index ae618e0f..3ae38c26 100644 --- a/misoclib/com/liteeth/test/model/dumps.py +++ b/misoclib/com/liteeth/test/model/dumps.py @@ -1,16 +1,16 @@ import re def format_dump(dump): - return [int(s, 16) for s in re.split(r'[;,\s\n]\s*', dump) if s is not ""] + return [int(s, 16) for s in re.split(r'[;,\s\n]\s*', dump) if s is not ""] def verify_packet(packet, infos): - errors = 0 - for k, v in infos.items(): - if hasattr(packet, k): - if getattr(packet, k) != v: - print("[Error] " + k) - errors += 1 - return errors + errors = 0 + for k, v in infos.items(): + if hasattr(packet, k): + if getattr(packet, k) != v: + print("[Error] " + k) + errors += 1 + return errors arp_request = format_dump(""" 00 22 19 22 54 9e 00 12 3f 97 92 01 08 06 00 01 @@ -18,15 +18,15 @@ arp_request = format_dump(""" 00 22 19 22 54 9e a9 fe 64 62""") arp_request_infos = { - "sender_mac" : 0x00123f979201, - "target_mac" : 0x00221922549e, - "ethernet_type" : 0x806, - "hwtype" : 0x1, - "opcode" : 0x1, - "protosize" : 0x4, - "proto" : 0x800, - "sender_ip" : 0xa9feff42, - "target_ip" : 0xa9fe6462 + "sender_mac" : 0x00123f979201, + "target_mac" : 0x00221922549e, + "ethernet_type" : 0x806, + "hwtype" : 0x1, + "opcode" : 0x1, + "protosize" : 0x4, + "proto" : 0x800, + "sender_ip" : 0xa9feff42, + "target_ip" : 0xa9fe6462 } @@ -37,15 +37,15 @@ arp_reply = format_dump(""" 00 00 00 00 00 00 00 00 00 00 00 00""") arp_reply_infos = { - "sender_mac" : 0x00221922549e, - "target_mac" : 0x00123f979201, - "ethernet_type" : 0x806, - "hwtype" : 0x1, - "opcode" : 0x2, - "protosize" : 0x4, - "proto" : 0x800, - "sender_ip" : 0xa9fe6462, - "target_ip" : 0xa9feff42 + "sender_mac" : 0x00221922549e, + "target_mac" : 0x00123f979201, + "ethernet_type" : 0x806, + "hwtype" : 0x1, + "opcode" : 0x2, + "protosize" : 0x4, + "proto" : 0x800, + "sender_ip" : 0xa9fe6462, + "target_ip" : 0xa9feff42 } udp = format_dump(""" @@ -58,13 +58,13 @@ aa 9b 4e 4d f9 2e 51 52 fe ff 65 31 3a 71 34 3a 34 3a 55 54 7e 62 31 3a 79 31 3a 71 65""") udp_infos = { - "sender_mac" : 0x00140b333327, - "target_mac" : 0xd07ab596cd0a, - "protocol" : 0x11, - "sender_ip" : 0xc0a80165, - "target_ip" : 0xb27b0d78, - "src_port" : 0xa63f, - "dst_port" : 0x690f + "sender_mac" : 0x00140b333327, + "target_mac" : 0xd07ab596cd0a, + "protocol" : 0x11, + "sender_ip" : 0xc0a80165, + "target_ip" : 0xb27b0d78, + "src_port" : 0xa63f, + "dst_port" : 0x690f } ping_request = format_dump(""" @@ -75,9 +75,9 @@ ping_request = format_dump(""" 77 61 62 63 64 65 66 67 68 69""") ping_request_infos = { - "code" : 0x0, - "msgtype" : 0x8, - "quench" : 0x2002100 + "code" : 0x0, + "msgtype" : 0x8, + "quench" : 0x2002100 } ping_reply = format_dump(""" diff --git a/misoclib/com/liteeth/test/model/etherbone.py b/misoclib/com/liteeth/test/model/etherbone.py index 7c3e35a3..c2d875c8 100644 --- a/misoclib/com/liteeth/test/model/etherbone.py +++ b/misoclib/com/liteeth/test/model/etherbone.py @@ -6,349 +6,349 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import udp def print_etherbone(s): - print_with_prefix(s, "[ETHERBONE]") + print_with_prefix(s, "[ETHERBONE]") # Etherbone model class EtherboneWrite: - def __init__(self, data): - self.data = data + def __init__(self, data): + self.data = data - def __repr__(self): - return "WR32 0x{:08x}".format(self.data) + def __repr__(self): + return "WR32 0x{:08x}".format(self.data) class EtherboneRead: - def __init__(self, addr): - self.addr = addr + def __init__(self, addr): + self.addr = addr - def __repr__(self): - return "RD32 @ 0x{:08x}".format(self.addr) + def __repr__(self): + return "RD32 @ 0x{:08x}".format(self.addr) class EtherboneWrites(Packet): - def __init__(self, init=[], base_addr=0, datas=[]): - Packet.__init__(self, init) - self.base_addr = base_addr - self.writes = [] - self.encoded = init != [] - for data in datas: - self.add(EtherboneWrite(data)) - - def add(self, write): - self.writes.append(write) - - def get_datas(self): - datas = [] - for write in self.writes: - datas.append(write.data) - return datas - - def encode(self): - if self.encoded: - raise ValueError - for byte in split_bytes(self.base_addr, 4): - self.append(byte) - for write in self.writes: - for byte in split_bytes(write.data, 4): - self.append(byte) - self.encoded = True - - def decode(self): - if not self.encoded: - raise ValueError - base_addr = [] - for i in range(4): - base_addr.append(self.pop(0)) - self.base_addr = merge_bytes(base_addr) - self.writes = [] - while len(self) != 0: - write = [] - for i in range(4): - write.append(self.pop(0)) - self.writes.append(EtherboneWrite(merge_bytes(write))) - self.encoded = False - - def __repr__(self): - r = "Writes\n" - r += "--------\n" - r += "BaseAddr @ 0x{:08x}\n".format(self.base_addr) - for write in self.writes: - r += write.__repr__() + "\n" - return r + def __init__(self, init=[], base_addr=0, datas=[]): + Packet.__init__(self, init) + self.base_addr = base_addr + self.writes = [] + self.encoded = init != [] + for data in datas: + self.add(EtherboneWrite(data)) + + def add(self, write): + self.writes.append(write) + + def get_datas(self): + datas = [] + for write in self.writes: + datas.append(write.data) + return datas + + def encode(self): + if self.encoded: + raise ValueError + for byte in split_bytes(self.base_addr, 4): + self.append(byte) + for write in self.writes: + for byte in split_bytes(write.data, 4): + self.append(byte) + self.encoded = True + + def decode(self): + if not self.encoded: + raise ValueError + base_addr = [] + for i in range(4): + base_addr.append(self.pop(0)) + self.base_addr = merge_bytes(base_addr) + self.writes = [] + while len(self) != 0: + write = [] + for i in range(4): + write.append(self.pop(0)) + self.writes.append(EtherboneWrite(merge_bytes(write))) + self.encoded = False + + def __repr__(self): + r = "Writes\n" + r += "--------\n" + r += "BaseAddr @ 0x{:08x}\n".format(self.base_addr) + for write in self.writes: + r += write.__repr__() + "\n" + return r class EtherboneReads(Packet): - def __init__(self, init=[], base_ret_addr=0, addrs=[]): - Packet.__init__(self, init) - self.base_ret_addr = base_ret_addr - self.reads = [] - self.encoded = init != [] - for addr in addrs: - self.add(EtherboneRead(addr)) - - def add(self, read): - self.reads.append(read) - - def get_addrs(self): - addrs = [] - for read in self.reads: - addrs.append(read.addr) - return addrs - - def encode(self): - if self.encoded: - raise ValueError - for byte in split_bytes(self.base_ret_addr, 4): - self.append(byte) - for read in self.reads: - for byte in split_bytes(read.addr, 4): - self.append(byte) - self.encoded = True - - def decode(self): - if not self.encoded: - raise ValueError - base_ret_addr = [] - for i in range(4): - base_ret_addr.append(self.pop(0)) - self.base_ret_addr = merge_bytes(base_ret_addr) - self.reads = [] - while len(self) != 0: - read = [] - for i in range(4): - read.append(self.pop(0)) - self.reads.append(EtherboneRead(merge_bytes(read))) - self.encoded = False - - def __repr__(self): - r = "Reads\n" - r += "--------\n" - r += "BaseRetAddr @ 0x{:08x}\n".format(self.base_ret_addr) - for read in self.reads: - r += read.__repr__() + "\n" - return r + def __init__(self, init=[], base_ret_addr=0, addrs=[]): + Packet.__init__(self, init) + self.base_ret_addr = base_ret_addr + self.reads = [] + self.encoded = init != [] + for addr in addrs: + self.add(EtherboneRead(addr)) + + def add(self, read): + self.reads.append(read) + + def get_addrs(self): + addrs = [] + for read in self.reads: + addrs.append(read.addr) + return addrs + + def encode(self): + if self.encoded: + raise ValueError + for byte in split_bytes(self.base_ret_addr, 4): + self.append(byte) + for read in self.reads: + for byte in split_bytes(read.addr, 4): + self.append(byte) + self.encoded = True + + def decode(self): + if not self.encoded: + raise ValueError + base_ret_addr = [] + for i in range(4): + base_ret_addr.append(self.pop(0)) + self.base_ret_addr = merge_bytes(base_ret_addr) + self.reads = [] + while len(self) != 0: + read = [] + for i in range(4): + read.append(self.pop(0)) + self.reads.append(EtherboneRead(merge_bytes(read))) + self.encoded = False + + def __repr__(self): + r = "Reads\n" + r += "--------\n" + r += "BaseRetAddr @ 0x{:08x}\n".format(self.base_ret_addr) + for read in self.reads: + r += read.__repr__() + "\n" + return r class EtherboneRecord(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) - self.writes = None - self.reads = None - self.encoded = init != [] - - def get_writes(self): - if self.wcount == 0: - return None - else: - writes = [] - for i in range((self.wcount+1)*4): - writes.append(self.pop(0)) - return EtherboneWrites(writes) - - def get_reads(self): - if self.rcount == 0: - return None - else: - reads = [] - for i in range((self.rcount+1)*4): - reads.append(self.pop(0)) - return EtherboneReads(reads) - - def decode(self): - if not self.encoded: - raise ValueError - header = [] - for byte in self[:etherbone_record_header_len]: - header.append(self.pop(0)) - for k, v in sorted(etherbone_record_header.items()): - setattr(self, k, get_field_data(v, header)) - self.writes = self.get_writes() - if self.writes is not None: - self.writes.decode() - self.reads = self.get_reads() - if self.reads is not None: - self.reads.decode() - self.encoded = False - - def set_writes(self, writes): - self.wcount = len(writes.writes) - writes.encode() - for byte in writes: - self.append(byte) - - def set_reads(self, reads): - self.rcount = len(reads.reads) - reads.encode() - for byte in reads: - self.append(byte) - - def encode(self): - if self.encoded: - raise ValueError - if self.writes is not None: - self.set_writes(self.writes) - if self.reads is not None: - self.set_reads(self.reads) - header = 0 - for k, v in sorted(etherbone_record_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, etherbone_record_header_len): - self.insert(0, d) - self.encoded = True - - def __repr__(self, n=0): - r = "Record {}\n".format(n) - r += "--------\n" - if self.encoded: - for d in self: - r += "{:02x}".format(d) - else: - for k in sorted(etherbone_record_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - if self.wcount != 0: - r += self.writes.__repr__() - if self.rcount != 0: - r += self.reads.__repr__() - return r + def __init__(self, init=[]): + Packet.__init__(self, init) + self.writes = None + self.reads = None + self.encoded = init != [] + + def get_writes(self): + if self.wcount == 0: + return None + else: + writes = [] + for i in range((self.wcount+1)*4): + writes.append(self.pop(0)) + return EtherboneWrites(writes) + + def get_reads(self): + if self.rcount == 0: + return None + else: + reads = [] + for i in range((self.rcount+1)*4): + reads.append(self.pop(0)) + return EtherboneReads(reads) + + def decode(self): + if not self.encoded: + raise ValueError + header = [] + for byte in self[:etherbone_record_header_len]: + header.append(self.pop(0)) + for k, v in sorted(etherbone_record_header.items()): + setattr(self, k, get_field_data(v, header)) + self.writes = self.get_writes() + if self.writes is not None: + self.writes.decode() + self.reads = self.get_reads() + if self.reads is not None: + self.reads.decode() + self.encoded = False + + def set_writes(self, writes): + self.wcount = len(writes.writes) + writes.encode() + for byte in writes: + self.append(byte) + + def set_reads(self, reads): + self.rcount = len(reads.reads) + reads.encode() + for byte in reads: + self.append(byte) + + def encode(self): + if self.encoded: + raise ValueError + if self.writes is not None: + self.set_writes(self.writes) + if self.reads is not None: + self.set_reads(self.reads) + header = 0 + for k, v in sorted(etherbone_record_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, etherbone_record_header_len): + self.insert(0, d) + self.encoded = True + + def __repr__(self, n=0): + r = "Record {}\n".format(n) + r += "--------\n" + if self.encoded: + for d in self: + r += "{:02x}".format(d) + else: + for k in sorted(etherbone_record_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + if self.wcount != 0: + r += self.writes.__repr__() + if self.rcount != 0: + r += self.reads.__repr__() + return r class EtherbonePacket(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) - self.encoded = init != [] - self.records = [] - - self.magic = etherbone_magic - self.version = etherbone_version - self.addr_size = 32//8 - self.port_size = 32//8 - self.nr = 0 - self.pr = 0 - self.pf = 0 - - def get_records(self): - records = [] - done = False - payload = self - while len(payload) != 0: - record = EtherboneRecord(payload) - record.decode() - records.append(copy.deepcopy(record)) - payload = record - return records - - def decode(self): - if not self.encoded: - raise ValueError - header = [] - for byte in self[:etherbone_packet_header_len]: - header.append(self.pop(0)) - for k, v in sorted(etherbone_packet_header.items()): - setattr(self, k, get_field_data(v, header)) - self.records = self.get_records() - self.encoded = False - - def set_records(self, records): - for record in records: - record.encode() - for byte in record: - self.append(byte) - - def encode(self): - if self.encoded: - raise ValueError - self.set_records(self.records) - header = 0 - for k, v in sorted(etherbone_packet_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, etherbone_packet_header_len): - self.insert(0, d) - self.encoded = True - - def __repr__(self): - r = "Packet\n" - r += "--------\n" - if self.encoded: - for d in self: - r += "{:02x}".format(d) - else: - for k in sorted(etherbone_packet_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - for i, record in enumerate(self.records): - r += record.__repr__(i) - return r + def __init__(self, init=[]): + Packet.__init__(self, init) + self.encoded = init != [] + self.records = [] + + self.magic = etherbone_magic + self.version = etherbone_version + self.addr_size = 32//8 + self.port_size = 32//8 + self.nr = 0 + self.pr = 0 + self.pf = 0 + + def get_records(self): + records = [] + done = False + payload = self + while len(payload) != 0: + record = EtherboneRecord(payload) + record.decode() + records.append(copy.deepcopy(record)) + payload = record + return records + + def decode(self): + if not self.encoded: + raise ValueError + header = [] + for byte in self[:etherbone_packet_header_len]: + header.append(self.pop(0)) + for k, v in sorted(etherbone_packet_header.items()): + setattr(self, k, get_field_data(v, header)) + self.records = self.get_records() + self.encoded = False + + def set_records(self, records): + for record in records: + record.encode() + for byte in record: + self.append(byte) + + def encode(self): + if self.encoded: + raise ValueError + self.set_records(self.records) + header = 0 + for k, v in sorted(etherbone_packet_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, etherbone_packet_header_len): + self.insert(0, d) + self.encoded = True + + def __repr__(self): + r = "Packet\n" + r += "--------\n" + if self.encoded: + for d in self: + r += "{:02x}".format(d) + else: + for k in sorted(etherbone_packet_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + for i, record in enumerate(self.records): + r += record.__repr__(i) + return r class Etherbone(Module): - def __init__(self, udp, debug=False): - self.udp = udp - self.debug = debug - self.tx_packets = [] - self.tx_packet = EtherbonePacket() - self.rx_packet = EtherbonePacket() - - udp.set_etherbone_callback(self.callback) - - def send(self, packet): - packet.encode() - if self.debug: - print_etherbone(">>>>>>>>") - print_etherbone(packet) - udp_packet = udp.UDPPacket(packet) - udp_packet.src_port = 0x1234 # XXX - udp_packet.dst_port = 20000 # XXX - udp_packet.length = len(packet) - udp_packet.checksum = 0 - self.udp.send(udp_packet) - - def receive(self): - self.rx_packet = EtherbonePacket() - while not self.rx_packet.done: - yield - - def callback(self, packet): - packet = EtherbonePacket(packet) - packet.decode() - if self.debug: - print_etherbone("<<<<<<<<") - print_etherbone(packet) - self.rx_packet = packet - self.rx_packet.done = True - self.process(packet) - - def process(self, packet): - pass + def __init__(self, udp, debug=False): + self.udp = udp + self.debug = debug + self.tx_packets = [] + self.tx_packet = EtherbonePacket() + self.rx_packet = EtherbonePacket() + + udp.set_etherbone_callback(self.callback) + + def send(self, packet): + packet.encode() + if self.debug: + print_etherbone(">>>>>>>>") + print_etherbone(packet) + udp_packet = udp.UDPPacket(packet) + udp_packet.src_port = 0x1234 # XXX + udp_packet.dst_port = 20000 # XXX + udp_packet.length = len(packet) + udp_packet.checksum = 0 + self.udp.send(udp_packet) + + def receive(self): + self.rx_packet = EtherbonePacket() + while not self.rx_packet.done: + yield + + def callback(self, packet): + packet = EtherbonePacket(packet) + packet.decode() + if self.debug: + print_etherbone("<<<<<<<<") + print_etherbone(packet) + self.rx_packet = packet + self.rx_packet.done = True + self.process(packet) + + def process(self, packet): + pass if __name__ == "__main__": - # Writes/Reads - writes = EtherboneWrites(base_addr=0x1000, datas=[i for i in range(16)]) - reads = EtherboneReads(base_ret_addr=0x2000, addrs=[i for i in range(16)]) - - # Record - record = EtherboneRecord() - record.writes = writes - record.reads = reads - record.bca = 0 - record.rca = 0 - record.rff = 0 - record.cyc = 0 - record.wca = 0 - record.wff = 0 - record.byte_enable = 0 - record.wcount = len(writes.get_datas()) - record.rcount = len(reads.get_addrs()) - - # Packet - packet = EtherbonePacket() - packet.records = [copy.deepcopy(record) for i in range(8)] - packet.nr = 0 - packet.pr = 0 - packet.pf = 0 - #print(packet) - packet.encode() - #print(packet) - - # Send packet over UDP to check against Wireshark dissector - import socket - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.sendto(bytes(packet), ("192.168.1.1", 20000)) - - packet = EtherbonePacket(packet) - packet.decode() - print(packet) + # Writes/Reads + writes = EtherboneWrites(base_addr=0x1000, datas=[i for i in range(16)]) + reads = EtherboneReads(base_ret_addr=0x2000, addrs=[i for i in range(16)]) + + # Record + record = EtherboneRecord() + record.writes = writes + record.reads = reads + record.bca = 0 + record.rca = 0 + record.rff = 0 + record.cyc = 0 + record.wca = 0 + record.wff = 0 + record.byte_enable = 0 + record.wcount = len(writes.get_datas()) + record.rcount = len(reads.get_addrs()) + + # Packet + packet = EtherbonePacket() + packet.records = [copy.deepcopy(record) for i in range(8)] + packet.nr = 0 + packet.pr = 0 + packet.pf = 0 + #print(packet) + packet.encode() + #print(packet) + + # Send packet over UDP to check against Wireshark dissector + import socket + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.sendto(bytes(packet), ("192.168.1.1", 20000)) + + packet = EtherbonePacket(packet) + packet.decode() + print(packet) diff --git a/misoclib/com/liteeth/test/model/icmp.py b/misoclib/com/liteeth/test/model/icmp.py index e04e5d36..249b9fac 100644 --- a/misoclib/com/liteeth/test/model/icmp.py +++ b/misoclib/com/liteeth/test/model/icmp.py @@ -6,97 +6,97 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import ip def print_icmp(s): - print_with_prefix(s, "[ICMP]") + print_with_prefix(s, "[ICMP]") # ICMP model class ICMPPacket(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) + def __init__(self, init=[]): + Packet.__init__(self, init) - def decode(self): - header = [] - for byte in self[:icmp_header_len]: - header.append(self.pop(0)) - for k, v in sorted(icmp_header.items()): - setattr(self, k, get_field_data(v, header)) + def decode(self): + header = [] + for byte in self[:icmp_header_len]: + header.append(self.pop(0)) + for k, v in sorted(icmp_header.items()): + setattr(self, k, get_field_data(v, header)) - def encode(self): - header = 0 - for k, v in sorted(icmp_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, icmp_header_len): - self.insert(0, d) + def encode(self): + header = 0 + for k, v in sorted(icmp_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, icmp_header_len): + self.insert(0, d) - def __repr__(self): - r = "--------\n" - for k in sorted(icmp_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - r += "payload: " - for d in self: - r += "{:02x}".format(d) - return r + def __repr__(self): + r = "--------\n" + for k in sorted(icmp_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + r += "payload: " + for d in self: + r += "{:02x}".format(d) + return r class ICMP(Module): - def __init__(self, ip, ip_address, debug=False): - self.ip = ip - self.ip_address = ip_address - self.debug = debug - self.tx_packets = [] - self.tx_packet = ICMPPacket() - self.rx_packet = ICMPPacket() + def __init__(self, ip, ip_address, debug=False): + self.ip = ip + self.ip_address = ip_address + self.debug = debug + self.tx_packets = [] + self.tx_packet = ICMPPacket() + self.rx_packet = ICMPPacket() - self.ip.set_icmp_callback(self.callback) + self.ip.set_icmp_callback(self.callback) - def send(self, packet): - packet.encode() - if self.debug: - print_icmp(">>>>>>>>") - print_icmp(packet) - ip_packet = ip.IPPacket(packet) - ip_packet.version = 0x4 - ip_packet.ihl = 0x5 - ip_packet.total_length = len(packet) + ip_packet.ihl - ip_packet.identification = 0 - ip_packet.flags = 0 - ip_packet.fragment_offset = 0 - ip_packet.ttl = 0x80 - ip_packet.sender_ip = self.ip_address - ip_packet.target_ip = 0x12345678 # XXX - ip_packet.checksum = 0 - ip_packet.protocol = icmp_protocol - self.ip.send(ip_packet) + def send(self, packet): + packet.encode() + if self.debug: + print_icmp(">>>>>>>>") + print_icmp(packet) + ip_packet = ip.IPPacket(packet) + ip_packet.version = 0x4 + ip_packet.ihl = 0x5 + ip_packet.total_length = len(packet) + ip_packet.ihl + ip_packet.identification = 0 + ip_packet.flags = 0 + ip_packet.fragment_offset = 0 + ip_packet.ttl = 0x80 + ip_packet.sender_ip = self.ip_address + ip_packet.target_ip = 0x12345678 # XXX + ip_packet.checksum = 0 + ip_packet.protocol = icmp_protocol + self.ip.send(ip_packet) - def callback(self, packet): - packet = ICMPPacket(packet) - packet.decode() - if self.debug: - print_icmp("<<<<<<<<") - print_icmp(packet) - self.process(packet) + def callback(self, packet): + packet = ICMPPacket(packet) + packet.decode() + if self.debug: + print_icmp("<<<<<<<<") + print_icmp(packet) + self.process(packet) - def process(self, packet): - pass + def process(self, packet): + pass if __name__ == "__main__": - from misoclib.com.liteeth.test.model.dumps import * - from misoclib.com.liteeth.test.model.mac import * - from misoclib.com.liteeth.test.model.ip import * - errors = 0 - # ICMP packet - packet = MACPacket(ping_request) - packet.decode_remove_header() - #print(packet) - packet = IPPacket(packet) - packet.decode() - #print(packet) - packet = ICMPPacket(packet) - packet.decode() - #print(packet) - errors += verify_packet(packet, ping_request_infos) - packet.encode() - packet.decode() - #print(packet) - errors += verify_packet(packet, ping_request_infos) + from misoclib.com.liteeth.test.model.dumps import * + from misoclib.com.liteeth.test.model.mac import * + from misoclib.com.liteeth.test.model.ip import * + errors = 0 + # ICMP packet + packet = MACPacket(ping_request) + packet.decode_remove_header() + #print(packet) + packet = IPPacket(packet) + packet.decode() + #print(packet) + packet = ICMPPacket(packet) + packet.decode() + #print(packet) + errors += verify_packet(packet, ping_request_infos) + packet.encode() + packet.decode() + #print(packet) + errors += verify_packet(packet, ping_request_infos) - print("icmp errors " + str(errors)) \ No newline at end of file + print("icmp errors " + str(errors)) \ No newline at end of file diff --git a/misoclib/com/liteeth/test/model/ip.py b/misoclib/com/liteeth/test/model/ip.py index 58e70a93..ee1bdbf6 100644 --- a/misoclib/com/liteeth/test/model/ip.py +++ b/misoclib/com/liteeth/test/model/ip.py @@ -6,7 +6,7 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import mac def print_ip(s): - print_with_prefix(s, "[IP]") + print_with_prefix(s, "[IP]") def carry_around_add(a, b): c = a + b @@ -21,128 +21,128 @@ def checksum(msg): # IP model class IPPacket(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) - - def get_checksum(self): - return self[10] | (self[11] << 8) - - def check_checksum(self): - return checksum(self[:ipv4_header_len]) == 0 - - def decode(self): - header = [] - for byte in self[:ipv4_header_len]: - header.append(self.pop(0)) - for k, v in sorted(ipv4_header.items()): - setattr(self, k, get_field_data(v, header)) - - def encode(self): - header = 0 - for k, v in sorted(ipv4_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, ipv4_header_len): - self.insert(0, d) - - def insert_checksum(self): - self[10] = 0 - self[11] = 0 - c = checksum(self[:ipv4_header_len]) - self[10] = c & 0xff - self[11] = (c >> 8) & 0xff - - def __repr__(self): - r = "--------\n" - for k in sorted(ipv4_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - r += "payload: " - for d in self: - r += "{:02x}".format(d) - return r + def __init__(self, init=[]): + Packet.__init__(self, init) + + def get_checksum(self): + return self[10] | (self[11] << 8) + + def check_checksum(self): + return checksum(self[:ipv4_header_len]) == 0 + + def decode(self): + header = [] + for byte in self[:ipv4_header_len]: + header.append(self.pop(0)) + for k, v in sorted(ipv4_header.items()): + setattr(self, k, get_field_data(v, header)) + + def encode(self): + header = 0 + for k, v in sorted(ipv4_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, ipv4_header_len): + self.insert(0, d) + + def insert_checksum(self): + self[10] = 0 + self[11] = 0 + c = checksum(self[:ipv4_header_len]) + self[10] = c & 0xff + self[11] = (c >> 8) & 0xff + + def __repr__(self): + r = "--------\n" + for k in sorted(ipv4_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + r += "payload: " + for d in self: + r += "{:02x}".format(d) + return r class IP(Module): - def __init__(self, mac, mac_address, ip_address, debug=False, loopback=False): - self.mac = mac - self.mac_address = mac_address - self.ip_address = ip_address - self.debug = debug - self.loopback = loopback - self.rx_packet = IPPacket() - self.table = {} - self.request_pending = False - - self.udp_callback = None - self.icmp_callback = None - - self.mac.set_ip_callback(self.callback) - - def set_udp_callback(self, callback): - self.udp_callback = callback - - def set_icmp_callback(self, callback): - self.icmp_callback = callback - - def send(self, packet): - packet.encode() - packet.insert_checksum() - if self.debug: - print_ip(">>>>>>>>") - print_ip(packet) - mac_packet = mac.MACPacket(packet) - mac_packet.target_mac = 0x12345678abcd # XXX - mac_packet.sender_mac = self.mac_address - mac_packet.ethernet_type = ethernet_type_ip - self.mac.send(mac_packet) - - def callback(self, packet): - packet = IPPacket(packet) - if not packet.check_checksum(): - received = packet.get_checksum() - packet.insert_checksum() - expected = packet.get_checksum() - raise ValueError("Checksum error received {:04x} / expected {:04x}".format(received, expected)) - packet.decode() - if self.debug: - print_ip("<<<<<<<<") - print_ip(packet) - if self.loopback: - self.send(packet) - else: - if packet.version != 0x4: - raise ValueError - if packet.ihl != 0x5: - raise ValueError - self.process(packet) - - def process(self, packet): - if packet.protocol == udp_protocol: - if self.udp_callback is not None: - self.udp_callback(packet) - elif packet.protocol == icmp_protocol: - if self.icmp_callback is not None: - self.icmp_callback(packet) + def __init__(self, mac, mac_address, ip_address, debug=False, loopback=False): + self.mac = mac + self.mac_address = mac_address + self.ip_address = ip_address + self.debug = debug + self.loopback = loopback + self.rx_packet = IPPacket() + self.table = {} + self.request_pending = False + + self.udp_callback = None + self.icmp_callback = None + + self.mac.set_ip_callback(self.callback) + + def set_udp_callback(self, callback): + self.udp_callback = callback + + def set_icmp_callback(self, callback): + self.icmp_callback = callback + + def send(self, packet): + packet.encode() + packet.insert_checksum() + if self.debug: + print_ip(">>>>>>>>") + print_ip(packet) + mac_packet = mac.MACPacket(packet) + mac_packet.target_mac = 0x12345678abcd # XXX + mac_packet.sender_mac = self.mac_address + mac_packet.ethernet_type = ethernet_type_ip + self.mac.send(mac_packet) + + def callback(self, packet): + packet = IPPacket(packet) + if not packet.check_checksum(): + received = packet.get_checksum() + packet.insert_checksum() + expected = packet.get_checksum() + raise ValueError("Checksum error received {:04x} / expected {:04x}".format(received, expected)) + packet.decode() + if self.debug: + print_ip("<<<<<<<<") + print_ip(packet) + if self.loopback: + self.send(packet) + else: + if packet.version != 0x4: + raise ValueError + if packet.ihl != 0x5: + raise ValueError + self.process(packet) + + def process(self, packet): + if packet.protocol == udp_protocol: + if self.udp_callback is not None: + self.udp_callback(packet) + elif packet.protocol == icmp_protocol: + if self.icmp_callback is not None: + self.icmp_callback(packet) if __name__ == "__main__": - from misoclib.com.liteeth.test.model.dumps import * - from misoclib.com.liteeth.test.model.mac import * - errors = 0 - # UDP packet - packet = MACPacket(udp) - packet.decode_remove_header() - #print(packet) - packet = IPPacket(packet) - # check decoding - errors += not packet.check_checksum() - packet.decode() - #print(packet) - errors += verify_packet(packet, {}) - # check encoding - packet.encode() - packet.insert_checksum() - errors += not packet.check_checksum() - packet.decode() - #print(packet) - errors += verify_packet(packet, {}) - - print("ip errors " + str(errors)) \ No newline at end of file + from misoclib.com.liteeth.test.model.dumps import * + from misoclib.com.liteeth.test.model.mac import * + errors = 0 + # UDP packet + packet = MACPacket(udp) + packet.decode_remove_header() + #print(packet) + packet = IPPacket(packet) + # check decoding + errors += not packet.check_checksum() + packet.decode() + #print(packet) + errors += verify_packet(packet, {}) + # check encoding + packet.encode() + packet.insert_checksum() + errors += not packet.check_checksum() + packet.decode() + #print(packet) + errors += verify_packet(packet, {}) + + print("ip errors " + str(errors)) \ No newline at end of file diff --git a/misoclib/com/liteeth/test/model/mac.py b/misoclib/com/liteeth/test/model/mac.py index 33a1d91f..a3a7a8d5 100644 --- a/misoclib/com/liteeth/test/model/mac.py +++ b/misoclib/com/liteeth/test/model/mac.py @@ -4,147 +4,147 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.test.common import * def print_mac(s): - print_with_prefix(s, "[MAC]") + print_with_prefix(s, "[MAC]") preamble = split_bytes(eth_preamble, 8, "little") def crc32(l): - crc = [] - crc_bytes = split_bytes(binascii.crc32(bytes(l)), 4, "little") - for byte in crc_bytes: - crc.append(int(byte)) - return crc + crc = [] + crc_bytes = split_bytes(binascii.crc32(bytes(l)), 4, "little") + for byte in crc_bytes: + crc.append(int(byte)) + return crc # MAC model class MACPacket(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) - self.preamble_error = False - self.crc_error = False - - def check_remove_preamble(self): - if comp(self[0:8], preamble): - for i in range(8): - self.pop(0) - return False - else: - return True - - def check_remove_crc(self): - if comp(self[-4:], crc32(self[:-4])): - for i in range(4): - self.pop() - return False - else: - return True - - def decode_remove_header(self): - header = [] - for byte in self[:mac_header_len]: - header.append(self.pop(0)) - for k, v in sorted(mac_header.items()): - setattr(self, k, get_field_data(v, header)) - - def decode(self): - self.preamble_error = self.check_remove_preamble() - self.crc_error = self.check_remove_crc() - if self.crc_error or self.preamble_error: - raise ValueError # XXX handle this properly - else: - self.decode_remove_header() - - def encode_header(self): - header = 0 - for k, v in sorted(mac_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, mac_header_len): - self.insert(0, d) - - def insert_crc(self): - for d in crc32(self): - self.append(d) - - def insert_preamble(self): - for d in reversed(preamble): - self.insert(0, d) - - def encode(self): - self.encode_header() - self.insert_crc() - self.insert_preamble() - - def __repr__(self): - r = "--------\n" - for k in sorted(mac_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - r += "payload: " - for d in self: - r += "{:02x}".format(d) - return r + def __init__(self, init=[]): + Packet.__init__(self, init) + self.preamble_error = False + self.crc_error = False + + def check_remove_preamble(self): + if comp(self[0:8], preamble): + for i in range(8): + self.pop(0) + return False + else: + return True + + def check_remove_crc(self): + if comp(self[-4:], crc32(self[:-4])): + for i in range(4): + self.pop() + return False + else: + return True + + def decode_remove_header(self): + header = [] + for byte in self[:mac_header_len]: + header.append(self.pop(0)) + for k, v in sorted(mac_header.items()): + setattr(self, k, get_field_data(v, header)) + + def decode(self): + self.preamble_error = self.check_remove_preamble() + self.crc_error = self.check_remove_crc() + if self.crc_error or self.preamble_error: + raise ValueError # XXX handle this properly + else: + self.decode_remove_header() + + def encode_header(self): + header = 0 + for k, v in sorted(mac_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, mac_header_len): + self.insert(0, d) + + def insert_crc(self): + for d in crc32(self): + self.append(d) + + def insert_preamble(self): + for d in reversed(preamble): + self.insert(0, d) + + def encode(self): + self.encode_header() + self.insert_crc() + self.insert_preamble() + + def __repr__(self): + r = "--------\n" + for k in sorted(mac_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + r += "payload: " + for d in self: + r += "{:02x}".format(d) + return r class MAC(Module): - def __init__(self, phy, debug=False, loopback=False): - self.phy = phy - self.debug = debug - self.loopback = loopback - self.rx_packet = MACPacket() - - self.ip_callback = None - self.arp_callback = None - - phy.set_mac_callback(self.callback) - - def set_ip_callback(self, callback): - self.ip_callback = callback - - def set_arp_callback(self, callback): - self.arp_callback = callback - - def send(self, packet): - if self.debug: - print_mac(">>>>>>>>") - print_mac(packet) - packet.encode() - self.phy.send(packet) - - def callback(self, datas): - packet = MACPacket(datas) - packet.decode() - if self.debug: - print_mac("<<<<<<<<") - print_mac(packet) - if self.loopback: - self.send(packet) - else: - if packet.ethernet_type == ethernet_type_ip: - if self.ip_callback is not None: - self.ip_callback(packet) - elif packet.ethernet_type == ethernet_type_arp: - if self.arp_callback is not None: - self.arp_callback(packet) - else: - raise ValueError # XXX handle this properly + def __init__(self, phy, debug=False, loopback=False): + self.phy = phy + self.debug = debug + self.loopback = loopback + self.rx_packet = MACPacket() + + self.ip_callback = None + self.arp_callback = None + + phy.set_mac_callback(self.callback) + + def set_ip_callback(self, callback): + self.ip_callback = callback + + def set_arp_callback(self, callback): + self.arp_callback = callback + + def send(self, packet): + if self.debug: + print_mac(">>>>>>>>") + print_mac(packet) + packet.encode() + self.phy.send(packet) + + def callback(self, datas): + packet = MACPacket(datas) + packet.decode() + if self.debug: + print_mac("<<<<<<<<") + print_mac(packet) + if self.loopback: + self.send(packet) + else: + if packet.ethernet_type == ethernet_type_ip: + if self.ip_callback is not None: + self.ip_callback(packet) + elif packet.ethernet_type == ethernet_type_arp: + if self.arp_callback is not None: + self.arp_callback(packet) + else: + raise ValueError # XXX handle this properly if __name__ == "__main__": - from misoclib.com.liteeth.test.model.dumps import * - errors = 0 - packet = MACPacket(arp_request) - packet.decode_remove_header() - #print(packet) - errors += verify_packet(packet, arp_request_infos) - packet.encode_header() - packet.decode_remove_header() - #print(packet) - errors += verify_packet(packet, arp_request_infos) - - #print(packet) - packet = MACPacket(arp_reply) - packet.decode_remove_header() - errors += verify_packet(packet, arp_reply_infos) - packet.encode_header() - packet.decode_remove_header() - #print(packet) - errors += verify_packet(packet, arp_reply_infos) - - print("mac errors " + str(errors)) + from misoclib.com.liteeth.test.model.dumps import * + errors = 0 + packet = MACPacket(arp_request) + packet.decode_remove_header() + #print(packet) + errors += verify_packet(packet, arp_request_infos) + packet.encode_header() + packet.decode_remove_header() + #print(packet) + errors += verify_packet(packet, arp_request_infos) + + #print(packet) + packet = MACPacket(arp_reply) + packet.decode_remove_header() + errors += verify_packet(packet, arp_reply_infos) + packet.encode_header() + packet.decode_remove_header() + #print(packet) + errors += verify_packet(packet, arp_reply_infos) + + print("mac errors " + str(errors)) diff --git a/misoclib/com/liteeth/test/model/phy.py b/misoclib/com/liteeth/test/model/phy.py index 5b9922f1..5bb69731 100644 --- a/misoclib/com/liteeth/test/model/phy.py +++ b/misoclib/com/liteeth/test/model/phy.py @@ -2,55 +2,55 @@ from misoclib.com.liteeth.common import * from misoclib.com.liteeth.test.common import * def print_phy(s): - print_with_prefix(s, "[PHY]") + print_with_prefix(s, "[PHY]") # PHY model class PHYSource(PacketStreamer): - def __init__(self, dw): - PacketStreamer.__init__(self, eth_phy_description(dw)) + def __init__(self, dw): + PacketStreamer.__init__(self, eth_phy_description(dw)) class PHYSink(PacketLogger): - def __init__(self, dw): - PacketLogger.__init__(self, eth_phy_description(dw)) + def __init__(self, dw): + PacketLogger.__init__(self, eth_phy_description(dw)) class PHY(Module): - def __init__(self, dw, debug=False): - self.dw = dw - self.debug = debug - - self.submodules.phy_source = PHYSource(dw) - self.submodules.phy_sink = PHYSink(dw) - - self.source = self.phy_source.source - self.sink = self.phy_sink.sink - - self.mac_callback = None - - def set_mac_callback(self, callback): - self.mac_callback = callback - - def send(self, datas): - packet = Packet(datas) - if self.debug: - r = ">>>>>>>>\n" - r += "length " + str(len(datas)) + "\n" - for d in datas: - r += "{:02x}".format(d) - print_phy(r) - self.phy_source.send(packet) - - def receive(self): - yield from self.phy_sink.receive() - if self.debug: - r = "<<<<<<<<\n" - r += "length " + str(len(self.phy_sink.packet)) + "\n" - for d in self.phy_sink.packet: - r += "{:02x}".format(d) - print_phy(r) - self.packet = self.phy_sink.packet - - def gen_simulation(self, selfp): - while True: - yield from self.receive() - if self.mac_callback is not None: - self.mac_callback(self.packet) + def __init__(self, dw, debug=False): + self.dw = dw + self.debug = debug + + self.submodules.phy_source = PHYSource(dw) + self.submodules.phy_sink = PHYSink(dw) + + self.source = self.phy_source.source + self.sink = self.phy_sink.sink + + self.mac_callback = None + + def set_mac_callback(self, callback): + self.mac_callback = callback + + def send(self, datas): + packet = Packet(datas) + if self.debug: + r = ">>>>>>>>\n" + r += "length " + str(len(datas)) + "\n" + for d in datas: + r += "{:02x}".format(d) + print_phy(r) + self.phy_source.send(packet) + + def receive(self): + yield from self.phy_sink.receive() + if self.debug: + r = "<<<<<<<<\n" + r += "length " + str(len(self.phy_sink.packet)) + "\n" + for d in self.phy_sink.packet: + r += "{:02x}".format(d) + print_phy(r) + self.packet = self.phy_sink.packet + + def gen_simulation(self, selfp): + while True: + yield from self.receive() + if self.mac_callback is not None: + self.mac_callback(self.packet) diff --git a/misoclib/com/liteeth/test/model/udp.py b/misoclib/com/liteeth/test/model/udp.py index 886cd4b6..f59ab116 100644 --- a/misoclib/com/liteeth/test/model/udp.py +++ b/misoclib/com/liteeth/test/model/udp.py @@ -6,112 +6,112 @@ from misoclib.com.liteeth.test.common import * from misoclib.com.liteeth.test.model import ip def print_udp(s): - print_with_prefix(s, "[UDP]") + print_with_prefix(s, "[UDP]") # UDP model class UDPPacket(Packet): - def __init__(self, init=[]): - Packet.__init__(self, init) - - def decode(self): - header = [] - for byte in self[:udp_header_len]: - header.append(self.pop(0)) - for k, v in sorted(udp_header.items()): - setattr(self, k, get_field_data(v, header)) - - def encode(self): - header = 0 - for k, v in sorted(udp_header.items()): - value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") - header += (value << v.offset+(v.byte*8)) - for d in split_bytes(header, udp_header_len): - self.insert(0, d) - - def __repr__(self): - r = "--------\n" - for k in sorted(udp_header.keys()): - r += k + " : 0x{:0x}\n".format(getattr(self,k)) - r += "payload: " - for d in self: - r += "{:02x}".format(d) - return r + def __init__(self, init=[]): + Packet.__init__(self, init) + + def decode(self): + header = [] + for byte in self[:udp_header_len]: + header.append(self.pop(0)) + for k, v in sorted(udp_header.items()): + setattr(self, k, get_field_data(v, header)) + + def encode(self): + header = 0 + for k, v in sorted(udp_header.items()): + value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little") + header += (value << v.offset+(v.byte*8)) + for d in split_bytes(header, udp_header_len): + self.insert(0, d) + + def __repr__(self): + r = "--------\n" + for k in sorted(udp_header.keys()): + r += k + " : 0x{:0x}\n".format(getattr(self,k)) + r += "payload: " + for d in self: + r += "{:02x}".format(d) + return r class UDP(Module): - def __init__(self, ip, ip_address, debug=False, loopback=False): - self.ip = ip - self.ip_address = ip_address - self.debug = debug - self.loopback = loopback - self.tx_packets = [] - self.tx_packet = UDPPacket() - self.rx_packet = UDPPacket() - - self.etherbone_callback = None - - self.ip.set_udp_callback(self.callback) - - def set_etherbone_callback(self, callback): - self.etherbone_callback = callback - - def send(self, packet): - packet.encode() - if self.debug: - print_udp(">>>>>>>>") - print_udp(packet) - ip_packet = ip.IPPacket(packet) - ip_packet.version = 0x4 - ip_packet.ihl = 0x5 - ip_packet.total_length = len(packet) + ip_packet.ihl - ip_packet.identification = 0 - ip_packet.flags = 0 - ip_packet.fragment_offset = 0 - ip_packet.ttl = 0x80 - ip_packet.sender_ip = self.ip_address - ip_packet.target_ip = 0x12345678 # XXX - ip_packet.checksum = 0 - ip_packet.protocol = udp_protocol - self.ip.send(ip_packet) - - def callback(self, packet): - packet = UDPPacket(packet) - packet.decode() - if self.debug: - print_udp("<<<<<<<<") - print_udp(packet) - if self.loopback: - self.send(packet) - else: - self.process(packet) - - def process(self, packet): - if packet.dst_port == 20000: - if self.etherbone_callback is not None: - self.etherbone_callback(packet) + def __init__(self, ip, ip_address, debug=False, loopback=False): + self.ip = ip + self.ip_address = ip_address + self.debug = debug + self.loopback = loopback + self.tx_packets = [] + self.tx_packet = UDPPacket() + self.rx_packet = UDPPacket() + + self.etherbone_callback = None + + self.ip.set_udp_callback(self.callback) + + def set_etherbone_callback(self, callback): + self.etherbone_callback = callback + + def send(self, packet): + packet.encode() + if self.debug: + print_udp(">>>>>>>>") + print_udp(packet) + ip_packet = ip.IPPacket(packet) + ip_packet.version = 0x4 + ip_packet.ihl = 0x5 + ip_packet.total_length = len(packet) + ip_packet.ihl + ip_packet.identification = 0 + ip_packet.flags = 0 + ip_packet.fragment_offset = 0 + ip_packet.ttl = 0x80 + ip_packet.sender_ip = self.ip_address + ip_packet.target_ip = 0x12345678 # XXX + ip_packet.checksum = 0 + ip_packet.protocol = udp_protocol + self.ip.send(ip_packet) + + def callback(self, packet): + packet = UDPPacket(packet) + packet.decode() + if self.debug: + print_udp("<<<<<<<<") + print_udp(packet) + if self.loopback: + self.send(packet) + else: + self.process(packet) + + def process(self, packet): + if packet.dst_port == 20000: + if self.etherbone_callback is not None: + self.etherbone_callback(packet) if __name__ == "__main__": - from misoclib.com.liteeth.test.model.dumps import * - from misoclib.com.liteeth.test.model.mac import * - from misoclib.com.liteeth.test.model.ip import * - errors = 0 - # UDP packet - packet = MACPacket(udp) - packet.decode_remove_header() - #print(packet) - packet = IPPacket(packet) - packet.decode() - #print(packet) - packet = UDPPacket(packet) - packet.decode() - #print(packet) - if packet.length != (len(packet)+udp_header_len): - errors += 1 - errors += verify_packet(packet, udp_infos) - packet.encode() - packet.decode() - #print(packet) - if packet.length != (len(packet)+udp_header_len): - errors += 1 - errors += verify_packet(packet, udp_infos) - - print("udp errors " + str(errors)) \ No newline at end of file + from misoclib.com.liteeth.test.model.dumps import * + from misoclib.com.liteeth.test.model.mac import * + from misoclib.com.liteeth.test.model.ip import * + errors = 0 + # UDP packet + packet = MACPacket(udp) + packet.decode_remove_header() + #print(packet) + packet = IPPacket(packet) + packet.decode() + #print(packet) + packet = UDPPacket(packet) + packet.decode() + #print(packet) + if packet.length != (len(packet)+udp_header_len): + errors += 1 + errors += verify_packet(packet, udp_infos) + packet.encode() + packet.decode() + #print(packet) + if packet.length != (len(packet)+udp_header_len): + errors += 1 + errors += verify_packet(packet, udp_infos) + + print("udp errors " + str(errors)) \ No newline at end of file diff --git a/misoclib/com/liteeth/test/udp_tb.py b/misoclib/com/liteeth/test/udp_tb.py index 3443fe26..6803571a 100644 --- a/misoclib/com/liteeth/test/udp_tb.py +++ b/misoclib/com/liteeth/test/udp_tb.py @@ -13,58 +13,58 @@ ip_address = 0x12345678 mac_address = 0x12345678abcd class TB(Module): - def __init__(self, dw=8): - self.dw = dw - 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) - self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False) - self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=True) + def __init__(self, dw=8): + self.dw = dw + 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) + self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False) + self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=True) - self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000) - udp_port = self.core.udp.crossbar.get_port(0x5678, dw) - self.submodules.streamer = PacketStreamer(eth_udp_user_description(dw)) - self.submodules.logger = PacketLogger(eth_udp_user_description(dw)) - self.comb += [ - Record.connect(self.streamer.source, udp_port.sink), - udp_port.sink.ip_address.eq(0x12345678), - udp_port.sink.src_port.eq(0x1234), - udp_port.sink.dst_port.eq(0x5678), - udp_port.sink.length.eq(64//(dw//8)), - Record.connect(udp_port.source, self.logger.sink) - ] + self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000) + udp_port = self.core.udp.crossbar.get_port(0x5678, dw) + self.submodules.streamer = PacketStreamer(eth_udp_user_description(dw)) + self.submodules.logger = PacketLogger(eth_udp_user_description(dw)) + self.comb += [ + Record.connect(self.streamer.source, udp_port.sink), + udp_port.sink.ip_address.eq(0x12345678), + udp_port.sink.src_port.eq(0x1234), + udp_port.sink.dst_port.eq(0x5678), + udp_port.sink.length.eq(64//(dw//8)), + Record.connect(udp_port.source, self.logger.sink) + ] - # use sys_clk for each clock_domain - self.clock_domains.cd_eth_rx = ClockDomain() - self.clock_domains.cd_eth_tx = ClockDomain() - self.comb += [ - self.cd_eth_rx.clk.eq(ClockSignal()), - self.cd_eth_rx.rst.eq(ResetSignal()), - self.cd_eth_tx.clk.eq(ClockSignal()), - self.cd_eth_tx.rst.eq(ResetSignal()), - ] + # use sys_clk for each clock_domain + self.clock_domains.cd_eth_rx = ClockDomain() + self.clock_domains.cd_eth_tx = ClockDomain() + self.comb += [ + self.cd_eth_rx.clk.eq(ClockSignal()), + self.cd_eth_rx.rst.eq(ResetSignal()), + self.cd_eth_tx.clk.eq(ClockSignal()), + self.cd_eth_tx.rst.eq(ResetSignal()), + ] - def gen_simulation(self, selfp): - selfp.cd_eth_rx.rst = 1 - selfp.cd_eth_tx.rst = 1 - yield - selfp.cd_eth_rx.rst = 0 - selfp.cd_eth_tx.rst = 0 + def gen_simulation(self, selfp): + selfp.cd_eth_rx.rst = 1 + selfp.cd_eth_tx.rst = 1 + yield + selfp.cd_eth_rx.rst = 0 + selfp.cd_eth_tx.rst = 0 - for i in range(100): - yield + for i in range(100): + yield - while True: - packet = Packet([i for i in range(64//(self.dw//8))]) - yield from self.streamer.send(packet) - yield from self.logger.receive() + while True: + packet = Packet([i for i in range(64//(self.dw//8))]) + yield from self.streamer.send(packet) + yield from self.logger.receive() - # check results - s, l, e = check(packet, self.logger.packet) - print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) + # check results + s, l, e = check(packet, self.logger.packet) + print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e)) if __name__ == "__main__": - run_simulation(TB(8), ncycles=2048, vcd_name="my.vcd", keep_files=True) - run_simulation(TB(16), ncycles=2048, vcd_name="my.vcd", keep_files=True) - run_simulation(TB(32), ncycles=2048, vcd_name="my.vcd", keep_files=True) \ No newline at end of file + run_simulation(TB(8), ncycles=2048, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(16), ncycles=2048, vcd_name="my.vcd", keep_files=True) + run_simulation(TB(32), ncycles=2048, vcd_name="my.vcd", keep_files=True) \ No newline at end of file