# Path: basil/utils/sim/Protocol.py
# class WriteRequest(ProtocolBase):
#     def __init__(self, address, data):
#         self.address = address
#         self.data = data
# 
#     def __str__(self):
#         return "WriteRequest: 0x%04x <- %s" % (self.address, self.data)
# 
# class ReadRequest(ProtocolBase):
#     def __init__(self, address, size):
#         self.address = address
#         self.size = size
# 
#     def __str__(self):
#         return "ReadRequest: 0x%04x (size %d)" % (self.address, self.size)
# 
# class ReadResponse(ProtocolBase):
#     def __init__(self, data):
#         self.data = data
# 
#     def __str__(self):
#         return "ReadResponse: %s" % str(self.data)
# 
# class PickleInterface(ProtocolBase):
#     def __init__(self, sock):
#         self.sock = sock
# 
#     def send(self, obj):
#         """Prepend a 4-byte length to the string"""
#         assert isinstance(obj, ProtocolBase)
#         string = pickle.dumps(obj)
#         length = len(string)
#         self.sock.sendall(struct.pack("<I", length) + string)
# 
#     def recv(self, blocking=True):
#         """Receive the next object from the socket"""
#         length = struct.unpack("<I", self.sock.recv(4))[0]
#         return self._get_next_obj(length)
# 
#     def try_recv(self):
#         """Return None immediately if nothing is waiting"""
#         try:
#             lenstr = self.sock.recv(4, socket.MSG_DONTWAIT)
#         except socket.error:
#             return None
#         if len(lenstr) < 4:
#             raise EOFError("Socket closed")
#         length = struct.unpack("<I", lenstr)[0]
#         return self._get_next_obj(length)
# 
#     def _get_next_obj(self, length):
#         """Assumes we've already read the object length"""
#         data = b""
#         while len(data) < length:
#             data += self.sock.recv(length - len(data))
# 
#         return pickle.loads(data)


import logging
import os
import socket
import yaml
import cocotb
from cocotb.triggers import Timer
from cocotb.clock import Clock
from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface

    await bus.init()

    while True:
        dut._log.info("Waiting for incoming connection on %s:%d" % (host, int(port)))
        clientsocket, socket_address = s.accept()
        dut._log.info("New connection from %s:%d" % (socket_address[0], socket_address[1]))
        iface = PickleInterface(clientsocket)

        while True:
            # uncomment for constantly advancing clock
            # await RisingEdge(bus.clock)

            try:
                req = iface.try_recv()
            except EOFError:
                dut._log.info("Remote server closed the connection")
                clientsocket.shutdown(socket.SHUT_RDWR)
                clientsocket.close()
                break
            if req is None:
                continue

            dut._log.debug("Received: %s" % str(req))

            # add few clocks
            # for _ in range(10):
            #    await RisingEdge(bus.clock)
            await Timer(bus_transaction_wait)


# Path: basil/utils/sim/Protocol.py
# class WriteRequest(ProtocolBase):
#     def __init__(self, address, data):
#         self.address = address
#         self.data = data
# 
#     def __str__(self):
#         return "WriteRequest: 0x%04x <- %s" % (self.address, self.data)
# 
# class ReadRequest(ProtocolBase):
#     def __init__(self, address, size):
#         self.address = address
#         self.size = size
# 
#     def __str__(self):
#         return "ReadRequest: 0x%04x (size %d)" % (self.address, self.size)
# 
# class ReadResponse(ProtocolBase):
#     def __init__(self, data):
#         self.data = data
# 
#     def __str__(self):
#         return "ReadResponse: %s" % str(self.data)
# 
# class PickleInterface(ProtocolBase):
#     def __init__(self, sock):
#         self.sock = sock
# 
#     def send(self, obj):
#         """Prepend a 4-byte length to the string"""
#         assert isinstance(obj, ProtocolBase)
#         string = pickle.dumps(obj)
#         length = len(string)
#         self.sock.sendall(struct.pack("<I", length) + string)
# 
#     def recv(self, blocking=True):
#         """Receive the next object from the socket"""
#         length = struct.unpack("<I", self.sock.recv(4))[0]
#         return self._get_next_obj(length)
# 
#     def try_recv(self):
#         """Return None immediately if nothing is waiting"""
#         try:
#             lenstr = self.sock.recv(4, socket.MSG_DONTWAIT)
#         except socket.error:
#             return None
#         if len(lenstr) < 4:
#             raise EOFError("Socket closed")
#         length = struct.unpack("<I", lenstr)[0]
#         return self._get_next_obj(length)
# 
#     def _get_next_obj(self, length):
#         """Assumes we've already read the object length"""
#         data = b""
#         while len(data) < length:
#             data += self.sock.recv(length - len(data))
# 
#         return pickle.loads(data)


# Path: basil/utils/sim/Test.py
import logging
import os
import socket
import yaml
import cocotb
from cocotb.triggers import Timer
from cocotb.clock import Clock
from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface


    await bus.init()

    while True:
        dut._log.info("Waiting for incoming connection on %s:%d" % (host, int(port)))
        clientsocket, socket_address = s.accept()
        dut._log.info("New connection from %s:%d" % (socket_address[0], socket_address[1]))
        iface = PickleInterface(clientsocket)

        while True:
            # uncomment for constantly advancing clock
            # await RisingEdge(bus.clock)

            try:
                req = iface.try_recv()
            except EOFError:
                dut._log.info("Remote server closed the connection")
                clientsocket.shutdown(socket.SHUT_RDWR)
                clientsocket.close()
                break
            if req is None:
                continue

            dut._log.debug("Received: %s" % str(req))

            # add few clocks
            # for _ in range(10):
            #    await RisingEdge(bus.clock)
            await Timer(bus_transaction_wait)


            if isinstance(req, WriteRequest):