tools/litex_server/litex_client: Add initial information exchange and improve PCIe case.

Due to the address translation done with the LitePCIe bridge (remapping CSR to 0), RemoteClient
needs to know which bridge is used to also translate CSRs.

This commit adds an initial information exchange between server and client and avoid the PCIe workarounds.
This commit is contained in:
Florent Kermarrec 2022-08-30 18:53:35 +02:00
parent ea8ba57eab
commit 35afd59956
3 changed files with 27 additions and 18 deletions

View File

@ -36,11 +36,19 @@ class RemoteClient(EtherboneIPC, CSRBuilder):
self.debug = debug
self.base_address = base_address if base_address is not None else 0
def _receive_server_info(self):
info = str(self.socket.recv(128))
# With LitePCIe, CSRs are translated to 0 to limit BAR0 size, so also translate base address.
if "CommPCIe" in info:
self.base_address = -self.mems.csr.base
def open(self):
if hasattr(self, "socket"):
return
self.socket = socket.create_connection((self.host, self.port), 5.0)
self.socket.settimeout(5.0)
self._receive_server_info()
def close(self):
if not hasattr(self, "socket"):
@ -99,10 +107,6 @@ def dump_identifier(host, csr_csv, port):
bus = RemoteClient(host=host, csr_csv=csr_csv, port=port)
bus.open()
# On PCIe designs, CSR is remapped to 0 to limit BAR0 size.
if hasattr(bus.bases, "pcie_phy"):
bus.base_address = -bus.mems.csr.base
fpga_identifier = ""
for i in range(256):
@ -119,10 +123,6 @@ def dump_registers(host, csr_csv, port, filter=None):
bus = RemoteClient(host=host, csr_csv=csr_csv, port=port)
bus.open()
# On PCIe designs, CSR is remapped to 0 to limit BAR0 size.
if hasattr(bus.bases, "pcie_phy"):
bus.base_address = -bus.mems.csr.base
for name, register in bus.regs.__dict__.items():
if (filter is None) or filter in name:
print("0x{:08x} : 0x{:08x} {}".format(register.addr, register.read(), name))

View File

@ -96,35 +96,48 @@ class RemoteServer(EtherboneIPC):
self.socket.close()
del self.socket
def _send_server_info(self, client_socket):
# FIXME: Formalize info/improve.
info = []
info.append(f"{self.comm.__class__.__name__}")
info.append(f"{self.bind_ip}")
info.append(f"{self.bind_port}")
info = ":".join(info)
client_socket.sendall(bytes(info, "UTF-8"))
def _serve_thread(self):
while True:
client_socket, addr = self.socket.accept()
self._send_server_info(client_socket)
print("Connected with " + addr[0] + ":" + str(addr[1]))
try:
# Serve Etherbone reads/writes.
while True:
# Receive packet.
try:
packet = self.receive_packet(client_socket)
if packet == 0:
break
except:
break
# Decode Packet.
packet = EtherbonePacket(packet)
packet.decode()
# Get Packet's Record.
record = packet.records.pop()
# Wait for lock
# Hardware lock/reservation.
while self.lock:
time.sleep(0.01)
# Set lock
self.lock = True
# Handle writes:
# Handle Etherbone writes.
if record.writes != None:
self.comm.write(record.writes.base_addr, record.writes.get_datas())
# Handle reads
# Handle Etherbone reads.
if record.reads != None:
max_length = {
"CommUART": 256,
@ -148,7 +161,7 @@ class RemoteServer(EtherboneIPC):
packet.encode()
self.send_packet(client_socket, packet)
# release lock
# Release hardware lock.
self.lock = False
finally:

View File

@ -97,10 +97,6 @@ class CrossoverUART:
if not present:
raise ValueError(f"CrossoverUART {name} not present in design.")
# FIXME: On PCIe designs, CSR is remapped to 0 to limit BAR0 size.
if base_address is None and hasattr(self.bus.bases, "pcie_phy"):
self.bus.base_address = -self.bus.mems.csr.base
def open(self):
self.bus.open()
self.file, self.name = pty.openpty()