7e547e3b600f2de0232684045e88706c9c256746
[litex.git] / liteeth / test / model / etherbone.py
1 import math, copy
2
3 from liteeth.common import *
4 from liteeth.test.common import *
5
6 from liteeth.test.model import udp
7
8 def print_etherbone(s):
9 print_with_prefix(s, "[ETHERBONE]")
10
11 # Etherbone model
12 class EtherboneWrite:
13 def __init__(self, data):
14 self.data = data
15
16 def __repr__(self):
17 return "Write data : {}".format(self.data)
18
19
20 class EtherboneRead:
21 def __init__(self, addr):
22 self.addr = addr
23
24 def __repr__(self):
25 return "Read addr : {}".format(self.addr)
26
27 class EtherboneWrites(Packet):
28 def __init__(self, init=[], base_addr=0):
29 Packet.__init__(self, init)
30 self.base_addr = base_addr
31 self.writes = []
32
33 def add(self, write):
34 self.writes.append(write)
35
36 def encode(self):
37 for byte in split_bytes(self.base_addr, 4):
38 self.append(byte)
39 for write in self.writes:
40 for byte in split_bytes(write.data, 4):
41 self.append(byte)
42
43 def decode(self):
44 base_addr = []
45 for i in range(4):
46 base_addr.append(self.pop(0))
47 self.base_addr = merge_bytes(base_addr)
48 self.writes = []
49 while len(self) != 0:
50 write = []
51 for i in range(4):
52 write.append(self.pop(0))
53 self.writes.append(EtherboneWrite(merge_bytes(write)))
54
55 class EtherboneReads(Packet):
56 def __init__(self, init=[], base_ret_addr=0):
57 Packet.__init__(self, init)
58 self.base_ret_addr = base_ret_addr
59 self.reads = []
60
61 def add(self, read):
62 self.reads.append(read)
63
64 def encode(self):
65 for byte in split_bytes(self.base_ret_addr, 4):
66 self.append(byte)
67 for read in self.reads:
68 for byte in split_bytes(read.addr, 4):
69 self.append(byte)
70
71 def decode(self):
72 base_ret_addr = []
73 for i in range(4):
74 base_ret_addr.append(self.pop(0))
75 self.base_ret_addr = merge_bytes(base_ret_addr)
76 self.reads = []
77 while len(self) != 0:
78 read = []
79 for i in range(4):
80 read.append(self.pop(0))
81 self.reads.append(EtherboneRead(merge_bytes(read)))
82
83 class EtherboneRecord(Packet):
84 def __init__(self, init=[]):
85 Packet.__init__(self, init)
86 self.writes = None
87 self.reads = None
88
89 def get_writes(self):
90 if self.wcount == 0:
91 return None
92 else:
93 writes = []
94 for i in range((self.wcount+1)*4):
95 writes.append(self.pop(0))
96 return EtherboneWrites(writes)
97
98 def get_reads(self):
99 if self.rcount == 0:
100 return None
101 else:
102 reads = []
103 for i in range((self.rcount+1)*4):
104 reads.append(self.pop(0))
105 return EtherboneReads(reads)
106
107 def decode(self):
108 header = []
109 for byte in self[:etherbone_record_header_len]:
110 header.append(self.pop(0))
111 for k, v in sorted(etherbone_record_header.items()):
112 setattr(self, k, get_field_data(v, header))
113
114 def set_writes(self, writes):
115 self.writes = writes
116 writes.encode()
117 for byte in writes:
118 self.append(byte)
119 self.wcount = len(writes)-4
120
121 def set_reads(self, reads):
122 self.reads = reads
123 reads.encode()
124 for byte in reads:
125 self.append(byte)
126 self.rcount = len(reads)-4
127
128 def encode(self):
129 header = 0
130 for k, v in sorted(etherbone_record_header.items()):
131 value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
132 header += (value << v.offset+(v.byte*8))
133 for d in split_bytes(header, etherbone_record_header_len):
134 self.insert(0, d)
135
136 def __repr__(self):
137 r = "--------\n"
138 for k in sorted(etherbone_record_header.keys()):
139 r += k + " : 0x%x" %getattr(self,k) + "\n"
140 r += "payload: "
141 for d in self:
142 r += "%02x" %d
143 return r
144
145 class EtherbonePacket(Packet):
146 def __init__(self, init=[]):
147 Packet.__init__(self, init)
148
149 def get_records(self):
150 records = []
151 done = False
152 payload = self
153 while len(payload) != 0:
154 record = EtherboneRecord(payload)
155 record.decode()
156 records.append(copy.deepcopy(record))
157 writes = record.get_writes()
158 reads = record.get_reads()
159 payload = record
160 return records
161
162 def decode(self):
163 header = []
164 for byte in self[:etherbone_header_len]:
165 header.append(self.pop(0))
166 for k, v in sorted(etherbone_header.items()):
167 setattr(self, k, get_field_data(v, header))
168
169 def set_records(self, records):
170 self.records = records
171 for record in records:
172 for byte in record:
173 self.append(byte)
174
175 def encode(self):
176 header = 0
177 for k, v in sorted(etherbone_header.items()):
178 value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
179 header += (value << v.offset+(v.byte*8))
180 for d in split_bytes(header, etherbone_header_len):
181 self.insert(0, d)
182
183 def __repr__(self):
184 r = "--------\n"
185 for k in sorted(etherbone_header.keys()):
186 r += k + " : 0x%x" %getattr(self,k) + "\n"
187 r += "payload: "
188 for d in self:
189 r += "%02x" %d
190 return r
191
192 class Etherbone(Module):
193 def __init__(self, udp, debug=False):
194 self.udp = udp
195 self.debug = debug
196 self.tx_packets = []
197 self.tx_packet = EtherbonePacket()
198 self.rx_packet = EtherbonePacket()
199
200 self.udp.set_etherbone_callback(self.callback)
201
202 def send(self, packet):
203 packet.encode()
204 if self.debug:
205 print_etherbone(">>>>>>>>")
206 print_etherbone(packet)
207 udp_packet = udp.UDPPacket(packet)
208 udp_packet.src_port = 0x1234
209 udp_packet.dst_port = 0x5678
210 udp_packet.length = len(packet)
211 udp_packet.checksum = 0
212 self.udp.send(udp_packet)
213
214 def callback(self, packet):
215 packet = Etherbone(packet)
216 packet.decode()
217 if self.debug:
218 print_etherbone("<<<<<<<<")
219 print_etherbone(packet)
220 self.process(packet)
221
222 def process(self, packet):
223 pass
224
225 if __name__ == "__main__":
226 # Writes/Reads
227 writes = EtherboneWrites(base_addr=0x1000)
228 for i in range(16):
229 writes.add(EtherboneWrite(i))
230 reads = EtherboneReads(base_ret_addr=0x2000)
231 for i in range(16):
232 reads.add(EtherboneRead(i))
233
234 # Record
235 record = EtherboneRecord()
236 record.set_writes(writes)
237 record.set_reads(reads)
238 record.bca = 0
239 record.rca = 0
240 record.rff = 0
241 record.cyc = 0
242 record.wca = 0
243 record.wff = 0
244 record.byte_enable = 0
245 record.wcount = 16
246 record.rcount = 16
247 record.encode()
248
249 # Packet
250 packet = EtherbonePacket()
251 packet.set_records([record for i in range(8)])
252 packet.magic = etherbone_magic
253 packet.version = etherbone_version
254 packet.nr = 0
255 packet.pr = 0
256 packet.pf = 0
257 packet.addr_size = 32//8
258 packet.port_size = 32//8
259 #print(packet)
260 packet.encode()
261
262 # Send packet over UDP to check against Wireshark dissector
263 import socket
264 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
265 sock.sendto(bytes(packet), ("192.168.1.1", 20000))
266
267 packet = EtherbonePacket(packet)
268 packet.decode()
269 #print(packet)
270
271 # Record
272 records = packet.get_records()
273 for record in records:
274 writes = record.get_writes()
275 writes.decode()
276 print(writes.base_addr)
277 for e in writes.writes:
278 print(e)
279 reads = record.get_reads()
280 reads.decode()
281 print(reads.base_ret_addr)
282 for e in reads.reads:
283 print(e)