Merge pull request #1504 from antmicro/msieron/fix-etherbone-timeouts

remote/comm_udp: Fix Etherbone timeout errors
This commit is contained in:
enjoy-digital 2022-11-15 10:10:08 +01:00 committed by GitHub
commit 4afee8535b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 38 additions and 22 deletions

View File

@ -22,13 +22,14 @@ class CommUDP(CSRBuilder):
self.port = port self.port = port
self.debug = debug self.debug = debug
self.timeout= timeout self.timeout= timeout
self.read_counter = 0
def open(self, probe=True): def open(self, probe=True):
if hasattr(self, "socket"): if hasattr(self, "socket"):
return return
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.bind(("", self.port)) self.socket.bind(("", self.port))
self.socket.settimeout(2) self.socket.settimeout(self.timeout)
if probe: if probe:
self.probe(self.server, self.port) self.probe(self.server, self.port)
@ -46,7 +47,6 @@ class CommUDP(CSRBuilder):
packet.bytes += bytes([0x00, 0x00, 0x00, 0x00]) # Add Padding as payload. packet.bytes += bytes([0x00, 0x00, 0x00, 0x00]) # Add Padding as payload.
retries = 10 retries = 10
self.socket.settimeout(self.timeout / retries)
# Send probe request to server and get server's response. # Send probe request to server and get server's response.
for r in range(retries): for r in range(retries):
@ -76,44 +76,60 @@ class CommUDP(CSRBuilder):
def scan(self, ip="192.168.1.x"): def scan(self, ip="192.168.1.x"):
print(f"Etherbone scan on {ip} network:") print(f"Etherbone scan on {ip} network:")
ip = ip.replace("x", "{}") ip = ip.replace("x", "{}")
self.socket.settimeout(0.01)
for i in range(1, 255): for i in range(1, 255):
if self.probe(ip=ip.format(str(i)), port=self.port, loose=True): if self.probe(ip=ip.format(str(i)), port=self.port, loose=True):
print("- {}".format(ip.format(i))) print("- {}".format(ip.format(i)))
self.socket.settimeout(1)
def read(self, addr, length=None, burst="incr"): def read(self, addr, length=None, burst="incr"):
assert burst == "incr" assert burst == "incr"
length_int = 1 if length is None else length length_int = 1 if length is None else length
record = EtherboneRecord()
record.reads = EtherboneReads(addrs=[addr+4*j for j in range(length_int)])
record.rcount = len(record.reads)
packet = EtherbonePacket()
packet.records = [record]
packet.encode()
retries = 10 retries = 10
self.socket.settimeout(self.timeout / retries)
for r in range(retries): for r in range(retries):
self.read_counter += 1
record = EtherboneRecord()
record.reads = EtherboneReads(addrs=[addr+4*j for j in range(length_int)])
record.rcount = len(record.reads)
record.reads.base_ret_addr = self.read_counter
packet = EtherbonePacket()
packet.records = [record]
packet.encode()
self.socket.sendto(packet.bytes, (self.server, self.port)) self.socket.sendto(packet.bytes, (self.server, self.port))
try:
datas, dummy = self.socket.recvfrom(8192) timed_out = False
except socket.timeout: while True:
if self.debug: try:
print("socket timeout, retrying ({}/{})".format(r+1, retries)) datas, dummy = self.socket.recvfrom(8192)
continue except socket.timeout:
break if self.debug:
print("socket timeout, retrying ({}/{})".format(r+1, retries))
timed_out = True
break
packet = EtherbonePacket(datas)
packet.decode()
record = packet.records.pop()
datas = record.writes.get_datas()
if record.writes.base_addr == self.read_counter:
break
else:
if self.debug:
print(f"WARNING: request/response id mismatch: 0x{self.read_counter:08x} != 0x{record.writes.base_addr:08x}")
if not timed_out:
break
else: else:
raise socket.timeout raise socket.timeout
packet = EtherbonePacket(datas)
packet.decode()
datas = packet.records.pop().writes.get_datas()
if self.debug: if self.debug:
for i, value in enumerate(datas): for i, value in enumerate(datas):
print("read 0x{:08x} @ 0x{:08x}".format(value, addr + 4*i)) print("read 0x{:08x} @ 0x{:08x}".format(value, addr + 4*i))
return datas[0] if length is None else datas return datas[0] if length is None else datas
def write(self, addr, datas): def write(self, addr, datas):