# 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 socket
import array
import time
import logging
from threading import Lock
from basil.TL.SiTransferLayer import SiTransferLayer
from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface
    def init(self):
        super(SiSim, self).init()
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        host = 'localhost'
        if 'host' in self._init.keys():
            host = self._init['host']

        port = 12345
        if 'port' in self._init.keys():
            port = self._init['port']

        # try few times for simulator to setup
        try_cnt = 60
        if 'timeout' in self._init.keys():
            try_cnt = self._init['timeout']

        while(self._sock.connect_ex((host, port)) != 0):
            logger.debug("Trying to connect to simulator.")
            time.sleep(1)
            try_cnt -= 1
            if(try_cnt < 1):
                raise IOError("No connection to simulation server.")

        self._iface = PickleInterface(self._sock)  # exeption?

        self._lock = Lock()

    def write(self, addr, data):
        ad = array.array('B', data)

# 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/TL/SiSim.py
import socket
import array
import time
import logging
from threading import Lock
from basil.TL.SiTransferLayer import SiTransferLayer
from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface

    def init(self):
        super(SiSim, self).init()
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        host = 'localhost'
        if 'host' in self._init.keys():
            host = self._init['host']

        port = 12345
        if 'port' in self._init.keys():
            port = self._init['port']

        # try few times for simulator to setup
        try_cnt = 60
        if 'timeout' in self._init.keys():
            try_cnt = self._init['timeout']

        while(self._sock.connect_ex((host, port)) != 0):
            logger.debug("Trying to connect to simulator.")
            time.sleep(1)
            try_cnt -= 1
            if(try_cnt < 1):
                raise IOError("No connection to simulation server.")

        self._iface = PickleInterface(self._sock)  # exeption?

        self._lock = Lock()

    def write(self, addr, data):
        ad = array.array('B', data)

        req = WriteRequest(addr, ad)