2 from collections
import OrderedDict
4 from migen
.fhdl
.std
import *
5 from migen
.fhdl
.decorators
import ModuleDecorator
6 from migen
.genlib
.resetsync
import AsyncResetSynchronizer
7 from migen
.genlib
.record
import *
8 from migen
.genlib
.fsm
import FSM
, NextState
9 from migen
.genlib
.misc
import chooser
10 from migen
.flow
.actor
import EndpointDescription
11 from migen
.flow
.actor
import Sink
, Source
12 from migen
.actorlib
.structuring
import Converter
, Pipeline
13 from migen
.actorlib
.fifo
import SyncFIFO
, AsyncFIFO
14 from migen
.bank
.description
import *
17 eth_preamble
= 0xD555555555555555
18 buffer_depth
= 2**log2_int(eth_mtu
, need_pow2
=False)
21 def __init__(self
, byte
, offset
, width
):
26 ethernet_type_ip
= 0x800
27 ethernet_type_arp
= 0x806
31 "destination_mac_address": HField(0, 0, 48),
32 "source_mac_address": HField(6, 0, 48),
33 "ethernet_type": HField(12, 0, 16)
36 arp_packet_length
= 60
37 arp_hwtype_ethernet
= 0x0001
39 arp_opcode_request
= 0x0001
40 arp_opcode_reply
= 0x0002
44 "hardware_type": HField( 0, 0, 16),
45 "protocol_type": HField( 2, 0, 16),
46 "hardware_address_length": HField( 4, 0, 8),
47 "protocol_address_length": HField( 5, 0, 8),
48 "operation": HField( 6, 0, 16),
49 "source_mac_address": HField( 8, 0, 48),
50 "source_ip_address": HField(14, 0, 32),
51 "destination_mac_address": HField(18, 0, 48),
52 "destination_ip_address": HField(24, 0, 32)
57 "version": HField(0, 0, 4),
58 "ihl": HField(0, 4, 4),
59 "dscp": HField(1, 0, 6),
60 "ecn": HField(1, 6, 2),
61 "total_length": HField(2, 0, 16),
62 "identification": HField(4, 0, 16),
63 "flags": HField(6, 0, 3),
64 "fragment_offset": HField(6, 3, 13),
65 "time_to_live": HField(8, 0, 8),
66 "protocol": HField(9, 0, 8),
67 "header_checksum": HField(10, 0, 16),
68 "source_ip_address": HField(12, 0, 32),
69 "destination_ip_address": HField(16, 0, 32),
70 "options": HField(20, 0, 32)
74 "source_port": HField( 0, 0, 16),
75 "destination_port": HField( 2, 0, 16),
76 "length": HField( 4, 0, 16),
77 "checksum": HField( 6, 0, 16)
81 n
= math
.ceil(flen(v
)//8)
83 for i
in reversed(range(n
)):
84 r
.append(v
[i
*8:min((i
+1)*8, flen(v
))])
88 def _layout_from_header(header
):
90 for k
, v
in sorted(header
.items()):
91 _layout
.append((k
, v
.width
))
94 def eth_phy_description(dw
):
100 return EndpointDescription(layout
, packetized
=True)
102 def eth_mac_description(dw
):
103 layout
= _layout_from_header(mac_header
) + [
108 return EndpointDescription(layout
, packetized
=True)
110 def eth_arp_description(dw
):
111 layout
= _layout_from_header(arp_header
) + [
115 return EndpointDescription(layout
, packetized
=True)
117 def eth_ipv4_description(dw
):
118 layout
= _layout_from_header(ipv4_header
) + [
122 return EndpointDescription(layout
, packetized
=True)
124 def eth_udp_description(dw
):
125 layout
= _layout_from_header(udp_header
) + [
129 return EndpointDescription(layout
, packetized
=True)
132 @DecorateModule(InsertReset
)
133 @DecorateModule(InsertCE
)
134 class Counter(Module
):
135 def __init__(self
, signal
=None, **kwargs
):
137 self
.value
= Signal(**kwargs
)
140 self
.width
= flen(self
.value
)
141 self
.sync
+= self
.value
.eq(self
.value
+1)
143 @DecorateModule(InsertReset
)
144 @DecorateModule(InsertCE
)
145 class Timeout(Module
):
146 def __init__(self
, length
):
147 self
.reached
= Signal()
149 value
= Signal(max=length
)
150 self
.sync
+= value
.eq(value
+1)
151 self
.comb
+= self
.reached
.eq(value
== length
)
153 class BufferizeEndpoints(ModuleDecorator
):
154 def __init__(self
, submodule
, *args
):
155 ModuleDecorator
.__init
__(self
, submodule
)
157 endpoints
= get_endpoints(submodule
)
160 for name
, endpoint
in endpoints
.items():
161 if name
in args
or len(args
) == 0:
162 if isinstance(endpoint
, Sink
):
163 sinks
.update({name
: endpoint
})
164 elif isinstance(endpoint
, Source
):
165 sources
.update({name
: endpoint
})
167 # add buffer on sinks
168 for name
, sink
in sinks
.items():
169 buf
= Buffer(sink
.description
)
170 self
.submodules
+= buf
171 setattr(self
, name
, buf
.d
)
172 self
.comb
+= Record
.connect(buf
.q
, sink
)
174 # add buffer on sources
175 for name
, source
in sources
.items():
176 buf
= Buffer(source
.description
)
177 self
.submodules
+= buf
178 self
.comb
+= Record
.connect(source
, buf
.d
)
179 setattr(self
, name
, buf
.q
)