forked from M-Labs/artiq
1
0
Fork 0

use device endian for core device protocols (#1591)

This commit is contained in:
pca006132 2021-01-22 16:33:21 +08:00 committed by GitHub
parent 1e443a3aea
commit 8148fdb8a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 22 deletions

View File

@ -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
------- -------

View File

@ -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

View File

@ -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"):

View File

@ -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):

View File

@ -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)

View File

@ -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

View File

@ -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..])?;

View File

@ -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 {

View File

@ -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 {

View File

@ -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();