forked from M-Labs/artiq
use device endian for core device protocols (#1591)
This commit is contained in:
parent
1e443a3aea
commit
8148fdb8a7
|
@ -59,7 +59,8 @@ Breaking changes:
|
||||||
unchanged with the new implementation, but the behavior might differ slightly in some
|
unchanged with the new implementation, but the behavior might differ slightly in some
|
||||||
cases (for instance, non-rectangular arrays are not currently supported).
|
cases (for instance, non-rectangular arrays are not currently supported).
|
||||||
* ``quamash`` has been replaced with ``qasync``.
|
* ``quamash`` has been replaced with ``qasync``.
|
||||||
|
* Protocols are updated to use device endian.
|
||||||
|
* Analyzer dump format includes a byte for device endianness.
|
||||||
|
|
||||||
ARTIQ-5
|
ARTIQ-5
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -90,7 +90,17 @@ DecodedDump = namedtuple(
|
||||||
|
|
||||||
|
|
||||||
def decode_dump(data):
|
def decode_dump(data):
|
||||||
parts = struct.unpack(">IQbbb", data[:15])
|
# extract endian byte
|
||||||
|
if data[0] == ord('E'):
|
||||||
|
endian = '>'
|
||||||
|
elif data[0] == ord('e'):
|
||||||
|
endian = '<'
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
data = data[1:]
|
||||||
|
# only header is device endian
|
||||||
|
# messages are big endian
|
||||||
|
parts = struct.unpack(endian + "IQbbb", data[:15])
|
||||||
(sent_bytes, total_byte_count,
|
(sent_bytes, total_byte_count,
|
||||||
error_occured, log_channel, dds_onehot_sel) = parts
|
error_occured, log_channel, dds_onehot_sel) = parts
|
||||||
|
|
||||||
|
|
|
@ -173,22 +173,13 @@ class CommKernelDummy:
|
||||||
class CommKernel:
|
class CommKernel:
|
||||||
warned_of_mismatch = False
|
warned_of_mismatch = False
|
||||||
|
|
||||||
def __init__(self, host, endian='>', port=1381):
|
def __init__(self, host, port=1381):
|
||||||
self.endian = endian
|
|
||||||
self._read_type = None
|
self._read_type = None
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.read_buffer = bytearray()
|
self.read_buffer = bytearray()
|
||||||
self.write_buffer = bytearray()
|
self.write_buffer = bytearray()
|
||||||
|
|
||||||
self.unpack_int32 = struct.Struct(endian + "l").unpack
|
|
||||||
self.unpack_int64 = struct.Struct(endian + "q").unpack
|
|
||||||
self.unpack_float64 = struct.Struct(endian + "d").unpack
|
|
||||||
|
|
||||||
self.pack_header = struct.Struct(endian + "lB").pack
|
|
||||||
self.pack_int32 = struct.Struct(endian + "l").pack
|
|
||||||
self.pack_int64 = struct.Struct(endian + "q").pack
|
|
||||||
self.pack_float64 = struct.Struct(endian + "d").pack
|
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
if hasattr(self, "socket"):
|
if hasattr(self, "socket"):
|
||||||
|
@ -196,6 +187,21 @@ class CommKernel:
|
||||||
self.socket = socket.create_connection((self.host, self.port))
|
self.socket = socket.create_connection((self.host, self.port))
|
||||||
logger.debug("connected to %s:%d", self.host, self.port)
|
logger.debug("connected to %s:%d", self.host, self.port)
|
||||||
self.socket.sendall(b"ARTIQ coredev\n")
|
self.socket.sendall(b"ARTIQ coredev\n")
|
||||||
|
endian = self._read(1)
|
||||||
|
if endian == b"e":
|
||||||
|
self.endian = "<"
|
||||||
|
elif endian == b"E":
|
||||||
|
self.endian = ">"
|
||||||
|
else:
|
||||||
|
raise IOError("Incorrect reply from device: expected e/E.")
|
||||||
|
self.unpack_int32 = struct.Struct(self.endian + "l").unpack
|
||||||
|
self.unpack_int64 = struct.Struct(self.endian + "q").unpack
|
||||||
|
self.unpack_float64 = struct.Struct(self.endian + "d").unpack
|
||||||
|
|
||||||
|
self.pack_header = struct.Struct(self.endian + "lB").pack
|
||||||
|
self.pack_int32 = struct.Struct(self.endian + "l").pack
|
||||||
|
self.pack_int64 = struct.Struct(self.endian + "q").pack
|
||||||
|
self.pack_float64 = struct.Struct(self.endian + "d").pack
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if not hasattr(self, "socket"):
|
if not hasattr(self, "socket"):
|
||||||
|
|
|
@ -63,6 +63,13 @@ class CommMgmt:
|
||||||
self.socket = socket.create_connection((self.host, self.port))
|
self.socket = socket.create_connection((self.host, self.port))
|
||||||
logger.debug("connected to %s:%d", self.host, self.port)
|
logger.debug("connected to %s:%d", self.host, self.port)
|
||||||
self.socket.sendall(b"ARTIQ management\n")
|
self.socket.sendall(b"ARTIQ management\n")
|
||||||
|
endian = self._read(1)
|
||||||
|
if endian == b"e":
|
||||||
|
self.endian = "<"
|
||||||
|
elif endian == b"E":
|
||||||
|
self.endian = ">"
|
||||||
|
else:
|
||||||
|
raise IOError("Incorrect reply from device: expected e/E.")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if not hasattr(self, "socket"):
|
if not hasattr(self, "socket"):
|
||||||
|
@ -86,7 +93,7 @@ class CommMgmt:
|
||||||
self._write(struct.pack("B", value))
|
self._write(struct.pack("B", value))
|
||||||
|
|
||||||
def _write_int32(self, value):
|
def _write_int32(self, value):
|
||||||
self._write(struct.pack(">l", value))
|
self._write(struct.pack(self.endian + "l", value))
|
||||||
|
|
||||||
def _write_bytes(self, value):
|
def _write_bytes(self, value):
|
||||||
self._write_int32(len(value))
|
self._write_int32(len(value))
|
||||||
|
@ -116,7 +123,7 @@ class CommMgmt:
|
||||||
format(self._read_type, ty))
|
format(self._read_type, ty))
|
||||||
|
|
||||||
def _read_int32(self):
|
def _read_int32(self):
|
||||||
(value, ) = struct.unpack(">l", self._read(4))
|
(value, ) = struct.unpack(self.endian + "l", self._read(4))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _read_bytes(self):
|
def _read_bytes(self):
|
||||||
|
|
|
@ -31,6 +31,14 @@ class CommMonInj:
|
||||||
self._reader, self._writer = await asyncio.open_connection(host, port)
|
self._reader, self._writer = await asyncio.open_connection(host, port)
|
||||||
try:
|
try:
|
||||||
self._writer.write(b"ARTIQ moninj\n")
|
self._writer.write(b"ARTIQ moninj\n")
|
||||||
|
# get device endian
|
||||||
|
endian = await self._reader.read(1)
|
||||||
|
if endian == b"e":
|
||||||
|
self.endian = "<"
|
||||||
|
elif endian == b"E":
|
||||||
|
self.endian = ">"
|
||||||
|
else:
|
||||||
|
raise IOError("Incorrect reply from device: expected e/E.")
|
||||||
self._receive_task = asyncio.ensure_future(self._receive_cr())
|
self._receive_task = asyncio.ensure_future(self._receive_cr())
|
||||||
except:
|
except:
|
||||||
self._writer.close()
|
self._writer.close()
|
||||||
|
@ -52,19 +60,19 @@ class CommMonInj:
|
||||||
del self._writer
|
del self._writer
|
||||||
|
|
||||||
def monitor_probe(self, enable, channel, probe):
|
def monitor_probe(self, enable, channel, probe):
|
||||||
packet = struct.pack(">bblb", 0, enable, channel, probe)
|
packet = struct.pack(self.endian + "bblb", 0, enable, channel, probe)
|
||||||
self._writer.write(packet)
|
self._writer.write(packet)
|
||||||
|
|
||||||
def monitor_injection(self, enable, channel, overrd):
|
def monitor_injection(self, enable, channel, overrd):
|
||||||
packet = struct.pack(">bblb", 3, enable, channel, overrd)
|
packet = struct.pack(self.endian + "bblb", 3, enable, channel, overrd)
|
||||||
self._writer.write(packet)
|
self._writer.write(packet)
|
||||||
|
|
||||||
def inject(self, channel, override, value):
|
def inject(self, channel, override, value):
|
||||||
packet = struct.pack(">blbb", 1, channel, override, value)
|
packet = struct.pack(self.endian + "blbb", 1, channel, override, value)
|
||||||
self._writer.write(packet)
|
self._writer.write(packet)
|
||||||
|
|
||||||
def get_injection_status(self, channel, override):
|
def get_injection_status(self, channel, override):
|
||||||
packet = struct.pack(">blb", 2, channel, override)
|
packet = struct.pack(self.endian + "blb", 2, channel, override)
|
||||||
self._writer.write(packet)
|
self._writer.write(packet)
|
||||||
|
|
||||||
async def _receive_cr(self):
|
async def _receive_cr(self):
|
||||||
|
@ -75,11 +83,13 @@ class CommMonInj:
|
||||||
return
|
return
|
||||||
if ty == b"\x00":
|
if ty == b"\x00":
|
||||||
payload = await self._reader.read(9)
|
payload = await self._reader.read(9)
|
||||||
channel, probe, value = struct.unpack(">lbl", payload)
|
channel, probe, value = struct.unpack(
|
||||||
|
self.endian + "lbl", payload)
|
||||||
self.monitor_cb(channel, probe, value)
|
self.monitor_cb(channel, probe, value)
|
||||||
elif ty == b"\x01":
|
elif ty == b"\x01":
|
||||||
payload = await self._reader.read(6)
|
payload = await self._reader.read(6)
|
||||||
channel, override, value = struct.unpack(">lbb", payload)
|
channel, override, value = struct.unpack(
|
||||||
|
self.endian + "lbb", payload)
|
||||||
self.injection_status_cb(channel, override, value)
|
self.injection_status_cb(channel, override, value)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unknown packet type", ty)
|
raise ValueError("Unknown packet type", ty)
|
||||||
|
|
|
@ -84,8 +84,7 @@ class Core:
|
||||||
if host is None:
|
if host is None:
|
||||||
self.comm = CommKernelDummy()
|
self.comm = CommKernelDummy()
|
||||||
else:
|
else:
|
||||||
endian = "<" if self.target_cls.little_endian else ">"
|
self.comm = CommKernel(host)
|
||||||
self.comm = CommKernel(host, endian)
|
|
||||||
|
|
||||||
self.first_run = True
|
self.first_run = True
|
||||||
self.dmgr = dmgr
|
self.dmgr = dmgr
|
||||||
|
|
|
@ -51,6 +51,7 @@ fn worker(stream: &mut TcpStream) -> Result<(), IoError<SchedError>> {
|
||||||
};
|
};
|
||||||
debug!("{:?}", header);
|
debug!("{:?}", header);
|
||||||
|
|
||||||
|
stream.write_all("E".as_bytes())?;
|
||||||
header.write_to(stream)?;
|
header.write_to(stream)?;
|
||||||
if wraparound {
|
if wraparound {
|
||||||
stream.write_all(&data[pointer..])?;
|
stream.write_all(&data[pointer..])?;
|
||||||
|
|
|
@ -15,6 +15,7 @@ impl From<SchedError> for Error<SchedError> {
|
||||||
|
|
||||||
fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
fn worker(io: &Io, stream: &mut TcpStream) -> Result<(), Error<SchedError>> {
|
||||||
read_magic(stream)?;
|
read_magic(stream)?;
|
||||||
|
Write::write_all(stream, "E".as_bytes())?;
|
||||||
info!("new connection from {}", stream.remote_endpoint());
|
info!("new connection from {}", stream.remote_endpoint());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -2,6 +2,7 @@ use alloc::btree_map::BTreeMap;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use io::Error as IoError;
|
use io::Error as IoError;
|
||||||
|
use io::Write;
|
||||||
use moninj_proto::*;
|
use moninj_proto::*;
|
||||||
use sched::{Io, Mutex, TcpListener, TcpStream, Error as SchedError};
|
use sched::{Io, Mutex, TcpListener, TcpStream, Error as SchedError};
|
||||||
use urc::Urc;
|
use urc::Urc;
|
||||||
|
@ -122,6 +123,7 @@ fn connection_worker(io: &Io, _aux_mutex: &Mutex, _routing_table: &drtio_routing
|
||||||
let mut next_check = 0;
|
let mut next_check = 0;
|
||||||
|
|
||||||
read_magic(&mut stream)?;
|
read_magic(&mut stream)?;
|
||||||
|
stream.write_all("E".as_bytes())?;
|
||||||
info!("new connection from {}", stream.remote_endpoint());
|
info!("new connection from {}", stream.remote_endpoint());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -615,6 +615,14 @@ pub fn thread(io: Io, aux_mutex: &Mutex,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match stream.write_all("E".as_bytes()) {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(_) => {
|
||||||
|
warn!("cannot send endian byte");
|
||||||
|
stream.close().expect("session: cannot close");
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
info!("new connection from {}", stream.remote_endpoint());
|
info!("new connection from {}", stream.remote_endpoint());
|
||||||
|
|
||||||
let aux_mutex = aux_mutex.clone();
|
let aux_mutex = aux_mutex.clone();
|
||||||
|
|
Loading…
Reference in New Issue