From b85e4bc77767f45e976381e679c0f9cafd79e3e0 Mon Sep 17 00:00:00 2001 From: Fischer Moseley <42497969+fischermoseley@users.noreply.github.com> Date: Sun, 19 May 2024 14:07:40 -0700 Subject: [PATCH] mem: quick hack to add user_clock --- src/manta/ethernet/__init__.py | 54 +++++++++++++++++++++++++--------- src/manta/memory_core.py | 7 ++++- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/manta/ethernet/__init__.py b/src/manta/ethernet/__init__.py index 4b8bbb8..7995bee 100644 --- a/src/manta/ethernet/__init__.py +++ b/src/manta/ethernet/__init__.py @@ -83,6 +83,17 @@ class EthernetInterface(Elaboratable): if not 0 <= int(byte) <= 255: raise ValueError(f"Invalid byte in FPGA IP: {byte}") + def _get_socket(self): + """ + Return an open socket if one exists, otherwise, open one and return + it. + """ + + if not hasattr(self, "_socket"): + self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + return self._socket + def get_top_level_ports(self): """ Return the Amaranth signals that should be included as ports in the @@ -261,10 +272,18 @@ class EthernetInterface(Elaboratable): if not all(isinstance(a, int) for a in addrs): raise TypeError("Read address must be an integer or list of integers.") - # Send read requests, and get responses - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + # Send read requests in chunks, such that each chunk of write requests + # is sent as a single UDP packet, and isn't fragmented into multiple + # UDP packets. Right now each read request is 8 bytes on the wire, so + # we can pack ~180 of them into a single packet to fit within the + # Ethernet MTU. We'll only send 128 at a time instead, just to be safe. + + # Listen for incoming packets from FPGA + sock = self._get_socket() sock.bind((self._host_ip_addr, self._udp_port)) - chunk_size = 64 # 128 + + # Send read requests, and get responses + chunk_size = 128 addr_chunks = split_into_chunks(addrs, chunk_size) datas = [] @@ -309,19 +328,26 @@ class EthernetInterface(Elaboratable): if not all(isinstance(d, int) for d in datas): raise TypeError("Write data must all be integers.") - # Since the FPGA doesn't issue any responses to write requests, we - # the host's input buffer isn't written to, and we don't need to - # send the data as chunks as the to avoid overflowing the input buffer. + # Send write requests in chunks, such that each chunk of write requests + # is sent as a single UDP packet, and isn't fragmented into multiple + # UDP packets. Right now each write request is 8 bytes on the wire, so + # we can pack ~180 of them into a single packet to fit within the + # Ethernet MTU. We'll only send 128 at a time instead, just to be safe. - # Encode addrs and datas into write requests - bytes_out = b"" - for addr, data in zip(addrs, datas): - bytes_out += int(1).to_bytes(4, byteorder="little") - bytes_out += int(addr).to_bytes(2, byteorder="little") - bytes_out += int(data).to_bytes(2, byteorder="little") + chunk_size = 128 + addr_chunks = split_into_chunks(addrs, chunk_size) + data_chunks = split_into_chunks(datas, chunk_size) - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.sendto(bytes_out, (self._fpga_ip_addr, self._udp_port)) + for addr_chunk, data_chunk in zip(addr_chunks, data_chunks): + bytes_out = b"" + for addr, data in zip(addr_chunk, data_chunk): + # Encode addrs and datas into write requests + bytes_out += int(1).to_bytes(4, byteorder="little") + bytes_out += int(addr).to_bytes(2, byteorder="little") + bytes_out += int(data).to_bytes(2, byteorder="little") + + sock = self._get_socket() + sock.sendto(bytes_out, (self._fpga_ip_addr, self._udp_port)) def generate_liteeth_core(self): """ diff --git a/src/manta/memory_core.py b/src/manta/memory_core.py index 177cae7..87ee501 100644 --- a/src/manta/memory_core.py +++ b/src/manta/memory_core.py @@ -43,9 +43,11 @@ class MemoryCore(MantaCore): elif self._mode == "host_to_fpga": self.user_addr = Signal(range(self._depth)) self.user_data_out = Signal(self._width) + self.user_clk = Signal() self._top_level_ports = [ self.user_addr, self.user_data_out, + self.user_clk, ] elif self._mode == "bidirectional": @@ -202,7 +204,10 @@ class MemoryCore(MantaCore): if self._mode in ["host_to_fpga", "bidirectional"]: read_datas = [] for i, mem in enumerate(self._mems): - read_port = mem.read_port() + m.domains.user = user_cd = ClockDomain(local=True) + m.d.comb += user_cd.clk.eq(self.user_clk) + + read_port = mem.read_port(domain="user") m.d.comb += read_port.addr.eq(self.user_addr) m.d.comb += read_port.en.eq(1) read_datas.append(read_port.data)