mirror of https://github.com/m-labs/artiq.git
Merge branch 'master' into nac3
This commit is contained in:
commit
7b56a72da0
|
@ -5,3 +5,4 @@ include versioneer.py
|
||||||
include artiq/_version.py
|
include artiq/_version.py
|
||||||
include artiq/coredevice/coredevice_generic.schema.json
|
include artiq/coredevice/coredevice_generic.schema.json
|
||||||
include artiq/compiler/kernel.ld
|
include artiq/compiler/kernel.ld
|
||||||
|
include artiq/afws.pem
|
||||||
|
|
|
@ -23,7 +23,7 @@ Highlights:
|
||||||
* On Kasli, the number of FIFO lanes in the scalable events dispatcher (SED) can now be configured in
|
* On Kasli, the number of FIFO lanes in the scalable events dispatcher (SED) can now be configured in
|
||||||
the JSON hardware description file.
|
the JSON hardware description file.
|
||||||
* ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding
|
* ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding
|
||||||
TTL device (e.g. ``"ttl_0_counter"`` for the edge counter on TTL device``"ttl_0"``)
|
TTL device (e.g. ``ttl_0_counter`` for the edge counter on TTL device ``ttl_0``).
|
||||||
* ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the
|
* ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the
|
||||||
repository when building the list of experiments.
|
repository when building the list of experiments.
|
||||||
* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage
|
* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIID0zCCArugAwIBAgIUPkNfEUx/uau3z8SD4mgMbCK/DEgwDQYJKoZIhvcNAQEL
|
||||||
|
BQAweTELMAkGA1UEBhMCSEsxEzARBgNVBAgMClNvbWUtU3RhdGUxFzAVBgNVBAoM
|
||||||
|
Dk0tTGFicyBMaW1pdGVkMRkwFwYDVQQDDBBuaXhibGQubS1sYWJzLmhrMSEwHwYJ
|
||||||
|
KoZIhvcNAQkBFhJoZWxwZGVza0BtLWxhYnMuaGswHhcNMjIwMjA2MTA1ODQ0WhcN
|
||||||
|
MjUwMjA1MTA1ODQ0WjB5MQswCQYDVQQGEwJISzETMBEGA1UECAwKU29tZS1TdGF0
|
||||||
|
ZTEXMBUGA1UECgwOTS1MYWJzIExpbWl0ZWQxGTAXBgNVBAMMEG5peGJsZC5tLWxh
|
||||||
|
YnMuaGsxITAfBgkqhkiG9w0BCQEWEmhlbHBkZXNrQG0tbGFicy5oazCCASIwDQYJ
|
||||||
|
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAPWetZhoggPR2ae7waGzv1AQ8NQO3noW
|
||||||
|
8DofVjusNpX5i/YB0waAr1bm1tALLJoHV2r/gTxujlXCe/L/WG1DLseCf6NO9sHg
|
||||||
|
t0FLhDpF9kPMWBgauVVLepd2Y2yU1G8eFuEVGnsiQSu0IzsZP5FQBJSyxvxJ+V/L
|
||||||
|
EW9ox91VGOP9VZR9jqdlYjGhcwClHA/nHe0q1fZq42+9rG466I5yIlNSoa7ilhTU
|
||||||
|
2C2doxy6Sr6VJYnLEMQqoIF65t3MkKi9iaqN7az0OCrj6XR0P5iKBzUhIgMUd2qs
|
||||||
|
7Id0XUdbQvaoaRI67vhGkNr+f4rdAUNCDGcbbokuBnmE7/gva6BAABUCAwEAAaNT
|
||||||
|
MFEwHQYDVR0OBBYEFM2e2FmcytXhKyfC1KEjVJ2mPSy3MB8GA1UdIwQYMBaAFM2e
|
||||||
|
2FmcytXhKyfC1KEjVJ2mPSy3MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
|
||||||
|
BQADggEBAKH0z5vlbfTghjYWwd2yEEFBbZx5XxaLHboFQpFpxu9sZoidVs047tco
|
||||||
|
MOr1py9juiNGGM8G35sw9306f+thDFwqlQfSExUwp5pRQNq+mxglMSF05HWDqBwb
|
||||||
|
wnItKi/WXpkMQXgpQJFVeflz4B4ZFNlH1UQl5bwacXOM9NM9zO7duCjVXmGE0yxi
|
||||||
|
VQyApfPQYu9whCSowDYYaA0toJeikMzGfWxhlAH79/2Qmit8KcSCbX1fK/QoRZLa
|
||||||
|
5NeUi/OlJbBpkgTrfzfMLphmsPWPAVMeUKzqd/vXfG6ZBOZZm6e6sl8RBycBezII
|
||||||
|
15WekikTE5+T54/E0xiu+zIW/Xhhk14=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -119,6 +119,18 @@ class ADF5356:
|
||||||
else:
|
else:
|
||||||
self.sync()
|
self.sync()
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def set_att(self, att: float):
|
||||||
|
"""Set digital step attenuator in SI units.
|
||||||
|
|
||||||
|
This method will write the attenuator settings of the channel.
|
||||||
|
|
||||||
|
.. seealso:: :meth:`artiq.coredevice.mirny.Mirny.set_att`
|
||||||
|
|
||||||
|
:param att: Attenuation in dB.
|
||||||
|
"""
|
||||||
|
self.cpld.set_att(self.channel, att)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att_mu(self, att: int32):
|
def set_att_mu(self, att: int32):
|
||||||
"""Set digital step attenuator in machine units.
|
"""Set digital step attenuator in machine units.
|
||||||
|
|
|
@ -2,7 +2,7 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
import struct
|
import struct
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from .comm import set_keepalive
|
||||||
|
|
||||||
__all__ = ["TTLProbe", "TTLOverride", "CommMonInj"]
|
__all__ = ["TTLProbe", "TTLOverride", "CommMonInj"]
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ class CommMonInj:
|
||||||
|
|
||||||
async def connect(self, host, port=1383):
|
async def connect(self, host, port=1383):
|
||||||
self._reader, self._writer = await asyncio.open_connection(host, port)
|
self._reader, self._writer = await asyncio.open_connection(host, port)
|
||||||
|
set_keepalive(self._writer.transport.get_extra_info('socket'), 1, 1, 3)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._writer.write(b"ARTIQ moninj\n")
|
self._writer.write(b"ARTIQ moninj\n")
|
||||||
# get device endian
|
# get device endian
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""RTIO driver for Mirny (4 channel GHz PLLs)
|
"""RTIO driver for Mirny (4 channel GHz PLLs)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from artiq.language.core import nac3, Kernel, KernelInvariant, kernel
|
from artiq.language.core import nac3, Kernel, KernelInvariant, kernel, portable
|
||||||
from artiq.language.units import us
|
from artiq.language.units import us
|
||||||
|
|
||||||
from numpy import int32
|
from numpy import int32
|
||||||
|
@ -144,6 +144,18 @@ class Mirny:
|
||||||
self.write_reg(1, (self.clk_sel << 4))
|
self.write_reg(1, (self.clk_sel << 4))
|
||||||
self.core.delay(1000. * us)
|
self.core.delay(1000. * us)
|
||||||
|
|
||||||
|
@portable
|
||||||
|
def att_to_mu(self, att: float) -> int32:
|
||||||
|
"""Convert an attenuation setting in dB to machine units.
|
||||||
|
|
||||||
|
:param att: Attenuation setting in dB.
|
||||||
|
:return: Digital attenuation setting.
|
||||||
|
"""
|
||||||
|
code = int32(255) - int32(round(att * 8.))
|
||||||
|
if code < 0 or code > 255:
|
||||||
|
raise ValueError("Invalid Mirny attenuation!")
|
||||||
|
return code
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_att_mu(self, channel: int32, att: int32):
|
def set_att_mu(self, channel: int32, att: int32):
|
||||||
"""Set digital step attenuator in machine units.
|
"""Set digital step attenuator in machine units.
|
||||||
|
@ -153,6 +165,21 @@ class Mirny:
|
||||||
self.bus.set_config_mu(SPI_CONFIG | SPI_END, 16, SPIT_WR, SPI_CS)
|
self.bus.set_config_mu(SPI_CONFIG | SPI_END, 16, SPIT_WR, SPI_CS)
|
||||||
self.bus.write(((channel | 8) << 25) | (att << 16))
|
self.bus.write(((channel | 8) << 25) | (att << 16))
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def set_att(self, channel: int32, att: float):
|
||||||
|
"""Set digital step attenuator in SI units.
|
||||||
|
|
||||||
|
This method will write the attenuator settings of the selected channel.
|
||||||
|
|
||||||
|
.. seealso:: :meth:`set_att_mu`
|
||||||
|
|
||||||
|
:param channel: Attenuator channel (0-3).
|
||||||
|
:param att: Attenuation setting in dB. Higher value is more
|
||||||
|
attenuation. Minimum attenuation is 0*dB, maximum attenuation is
|
||||||
|
31.5*dB.
|
||||||
|
"""
|
||||||
|
self.set_att_mu(channel, self.att_to_mu(att))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def write_ext(self, addr: int32, length: int32, data: int32, ext_div: int32 = SPIT_WR):
|
def write_ext(self, addr: int32, length: int32, data: int32, ext_div: int32 = SPIT_WR):
|
||||||
"""Perform SPI write to a prefixed address"""
|
"""Perform SPI write to a prefixed address"""
|
||||||
|
|
|
@ -65,8 +65,8 @@ fn memory_test(total: &mut usize, wrong: &mut usize) -> bool {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prng32(seed: &mut u32) -> u32 { *seed = 1664525 * *seed + 1013904223; *seed }
|
fn prng32(seed: &mut u32) -> u32 { *seed = u32::wrapping_add(u32::wrapping_mul(1664525, *seed), 1013904223); *seed }
|
||||||
fn prng16(seed: &mut u16) -> u16 { *seed = 25173 * *seed + 13849; *seed }
|
fn prng16(seed: &mut u16) -> u16 { *seed = u16::wrapping_add(u16::wrapping_mul(25173, *seed), 13849); *seed }
|
||||||
|
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
// Test data bus
|
// Test data bus
|
||||||
|
|
|
@ -211,9 +211,10 @@ mod ddr {
|
||||||
|
|
||||||
// Generate pseudo-random sequence
|
// Generate pseudo-random sequence
|
||||||
let mut prs = [0; DFII_NPHASES * DFII_PIX_DATA_SIZE];
|
let mut prs = [0; DFII_NPHASES * DFII_PIX_DATA_SIZE];
|
||||||
let mut prv = 42;
|
let mut prv: u32 = 42;
|
||||||
for b in prs.iter_mut() {
|
for b in prs.iter_mut() {
|
||||||
prv = 1664525 * prv + 1013904223;
|
|
||||||
|
prv = u32::wrapping_add(u32::wrapping_mul(1664525, prv), 1013904223);
|
||||||
*b = prv as u8;
|
*b = prv as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +297,7 @@ mod ddr {
|
||||||
let mut prs = [0; DFII_NPHASES * DFII_PIX_DATA_SIZE];
|
let mut prs = [0; DFII_NPHASES * DFII_PIX_DATA_SIZE];
|
||||||
let mut prv = 42;
|
let mut prv = 42;
|
||||||
for b in prs.iter_mut() {
|
for b in prs.iter_mut() {
|
||||||
prv = 1664525 * prv + 1013904223;
|
prv = u32::wrapping_add(u32::wrapping_mul(1664525, prv), 1013904223);
|
||||||
*b = prv as u8;
|
*b = prv as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,20 @@ use byteorder::{NativeEndian, ByteOrder};
|
||||||
use io::{ProtoRead, Read, Write, ProtoWrite, Error};
|
use io::{ProtoRead, Read, Write, ProtoWrite, Error};
|
||||||
use self::tag::{Tag, TagIterator, split_tag};
|
use self::tag::{Tag, TagIterator, split_tag};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn alignment_offset(alignment: isize, ptr: isize) -> isize {
|
||||||
|
(-ptr).rem_euclid(alignment)
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn align_ptr<T>(ptr: *const ()) -> *const T {
|
unsafe fn align_ptr<T>(ptr: *const ()) -> *const T {
|
||||||
let alignment = core::mem::align_of::<T>() as isize;
|
let alignment = core::mem::align_of::<T>() as isize;
|
||||||
let fix = (alignment - (ptr as isize) % alignment) % alignment;
|
let fix = alignment_offset(alignment as isize, ptr as isize);
|
||||||
((ptr as isize) + fix) as *const T
|
((ptr as isize) + fix) as *const T
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
|
unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
|
||||||
let alignment = core::mem::align_of::<T>() as isize;
|
let alignment = core::mem::align_of::<T>() as isize;
|
||||||
let fix = (alignment - (ptr as isize) % alignment) % alignment;
|
let fix = alignment_offset(alignment as isize, ptr as isize);
|
||||||
((ptr as isize) + fix) as *mut T
|
((ptr as isize) + fix) as *mut T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +59,7 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Tag::Tuple(it, arity) => {
|
Tag::Tuple(it, arity) => {
|
||||||
|
*data = data.offset(alignment_offset(tag.alignment() as isize, *data as isize));
|
||||||
let mut it = it.clone();
|
let mut it = it.clone();
|
||||||
for _ in 0..arity {
|
for _ in 0..arity {
|
||||||
let tag = it.next().expect("truncated tag");
|
let tag = it.next().expect("truncated tag");
|
||||||
|
@ -69,9 +75,12 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
let length = (*ptr).length as usize;
|
let length = (*ptr).length as usize;
|
||||||
|
|
||||||
let tag = it.clone().next().expect("truncated tag");
|
let tag = it.clone().next().expect("truncated tag");
|
||||||
(*ptr).elements = alloc(tag.size() * (*ptr).length as usize)?;
|
let padding = if let Tag::Int64 | Tag::Float64 = tag { 4 } else { 0 };
|
||||||
|
let mut data = alloc(tag.size() * length + padding)?;
|
||||||
|
|
||||||
let mut data = (*ptr).elements;
|
data = data.offset(alignment_offset(tag.alignment() as isize, data as isize));
|
||||||
|
|
||||||
|
(*ptr).elements = data;
|
||||||
match tag {
|
match tag {
|
||||||
Tag::Bool => {
|
Tag::Bool => {
|
||||||
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
||||||
|
@ -109,9 +118,11 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
let length = total_len as usize;
|
let length = total_len as usize;
|
||||||
|
|
||||||
let elt_tag = it.clone().next().expect("truncated tag");
|
let elt_tag = it.clone().next().expect("truncated tag");
|
||||||
*buffer = alloc(elt_tag.size() * total_len as usize)?;
|
let padding = if let Tag::Int64 | Tag::Float64 = tag { 4 } else { 0 };
|
||||||
|
let mut data = alloc(elt_tag.size() * length + padding)?;
|
||||||
|
data = data.offset(alignment_offset(tag.alignment() as isize, data as isize));
|
||||||
|
|
||||||
let mut data = *buffer;
|
*buffer = data;
|
||||||
match elt_tag {
|
match elt_tag {
|
||||||
Tag::Bool => {
|
Tag::Bool => {
|
||||||
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
let dest = slice::from_raw_parts_mut(data as *mut u8, length);
|
||||||
|
@ -139,6 +150,7 @@ unsafe fn recv_value<R, E>(reader: &mut R, tag: Tag, data: &mut *mut (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Tag::Range(it) => {
|
Tag::Range(it) => {
|
||||||
|
*data = data.offset(alignment_offset(tag.alignment() as isize, *data as isize));
|
||||||
let tag = it.clone().next().expect("truncated tag");
|
let tag = it.clone().next().expect("truncated tag");
|
||||||
recv_value(reader, tag, data, alloc)?;
|
recv_value(reader, tag, data, alloc)?;
|
||||||
recv_value(reader, tag, data, alloc)?;
|
recv_value(reader, tag, data, alloc)?;
|
||||||
|
@ -336,6 +348,7 @@ pub fn send_args<W>(writer: &mut W, service: u32, tag_bytes: &[u8], data: *const
|
||||||
|
|
||||||
mod tag {
|
mod tag {
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use super::alignment_offset;
|
||||||
|
|
||||||
pub fn split_tag(tag_bytes: &[u8]) -> (&[u8], &[u8]) {
|
pub fn split_tag(tag_bytes: &[u8]) -> (&[u8], &[u8]) {
|
||||||
let tag_separator =
|
let tag_separator =
|
||||||
|
@ -385,6 +398,33 @@ mod tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn alignment(self) -> usize {
|
||||||
|
use cslice::CSlice;
|
||||||
|
match self {
|
||||||
|
Tag::None => 1,
|
||||||
|
Tag::Bool => core::mem::align_of::<u8>(),
|
||||||
|
Tag::Int32 => core::mem::align_of::<i32>(),
|
||||||
|
Tag::Int64 => core::mem::align_of::<i64>(),
|
||||||
|
Tag::Float64 => core::mem::align_of::<f64>(),
|
||||||
|
// struct type: align to largest element
|
||||||
|
Tag::Tuple(it, arity) => {
|
||||||
|
let it = it.clone();
|
||||||
|
it.take(arity.into()).map(|t| t.alignment()).max().unwrap()
|
||||||
|
},
|
||||||
|
Tag::Range(it) => {
|
||||||
|
let it = it.clone();
|
||||||
|
it.take(3).map(|t| t.alignment()).max().unwrap()
|
||||||
|
}
|
||||||
|
// CSlice basically
|
||||||
|
Tag::Bytes | Tag::String | Tag::ByteArray | Tag::List(_) =>
|
||||||
|
core::mem::align_of::<CSlice<()>>(),
|
||||||
|
// array buffer is allocated, so no need for alignment first
|
||||||
|
Tag::Array(_, _) => 1,
|
||||||
|
// will not be sent from the host
|
||||||
|
_ => unreachable!("unexpected tag from host")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn size(self) -> usize {
|
pub fn size(self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Tag::None => 0,
|
Tag::None => 0,
|
||||||
|
@ -401,6 +441,7 @@ mod tag {
|
||||||
for _ in 0..arity {
|
for _ in 0..arity {
|
||||||
let tag = it.next().expect("truncated tag");
|
let tag = it.next().expect("truncated tag");
|
||||||
size += tag.size();
|
size += tag.size();
|
||||||
|
size += alignment_offset(tag.alignment() as isize, size as isize) as usize;
|
||||||
}
|
}
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
@ -469,6 +510,13 @@ mod tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for TagIterator<'a> {
|
||||||
|
type Item = Tag<'a>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
(self as &mut TagIterator<'a>).next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> fmt::Display for TagIterator<'a> {
|
impl<'a> fmt::Display for TagIterator<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let mut it = self.clone();
|
let mut it = self.clone();
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
import ssl
|
||||||
|
import io
|
||||||
|
import zipfile
|
||||||
|
from getpass import getpass
|
||||||
|
|
||||||
|
|
||||||
|
def get_artiq_cert():
|
||||||
|
try:
|
||||||
|
import artiq
|
||||||
|
except ImportError:
|
||||||
|
return None
|
||||||
|
filename = os.path.join(os.path.dirname(artiq.__file__), "afws.pem")
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
return None
|
||||||
|
return filename
|
||||||
|
|
||||||
|
|
||||||
|
def get_artiq_rev():
|
||||||
|
try:
|
||||||
|
import artiq
|
||||||
|
except ImportError:
|
||||||
|
return None
|
||||||
|
return artiq._version.get_rev()
|
||||||
|
|
||||||
|
|
||||||
|
def zip_unarchive(data, directory):
|
||||||
|
buf = io.BytesIO(data)
|
||||||
|
with zipfile.ZipFile(buf) as archive:
|
||||||
|
archive.extractall(directory)
|
||||||
|
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
def __init__(self, server, port, cafile):
|
||||||
|
self.ssl_context = ssl.create_default_context(cafile=cafile)
|
||||||
|
self.raw_socket = socket.create_connection((server, port))
|
||||||
|
try:
|
||||||
|
self.socket = self.ssl_context.wrap_socket(self.raw_socket, server_hostname=server)
|
||||||
|
except:
|
||||||
|
self.raw_socket.close()
|
||||||
|
raise
|
||||||
|
self.fsocket = self.socket.makefile("rwb")
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.socket.close()
|
||||||
|
self.raw_socket.close()
|
||||||
|
|
||||||
|
def send_command(self, *command):
|
||||||
|
self.fsocket.write((" ".join(command) + "\n").encode())
|
||||||
|
self.fsocket.flush()
|
||||||
|
|
||||||
|
def read_reply(self):
|
||||||
|
return self.fsocket.readline().decode("ascii").split()
|
||||||
|
|
||||||
|
def login(self, username, password):
|
||||||
|
self.send_command("LOGIN", username, password)
|
||||||
|
return self.read_reply() == ["HELLO"]
|
||||||
|
|
||||||
|
def build(self, rev, variant):
|
||||||
|
self.send_command("BUILD", rev, variant)
|
||||||
|
reply = self.read_reply()[0]
|
||||||
|
if reply != "BUILDING":
|
||||||
|
return reply, None
|
||||||
|
print("Build in progress. This may take 10-15 minutes.")
|
||||||
|
reply, status = self.read_reply()
|
||||||
|
if reply != "DONE":
|
||||||
|
raise ValueError("Unexpected server reply: expected 'DONE', got '{}'".format(reply))
|
||||||
|
if status != "done":
|
||||||
|
return status, None
|
||||||
|
print("Build completed. Downloading...")
|
||||||
|
reply, length = self.read_reply()
|
||||||
|
if reply != "PRODUCT":
|
||||||
|
raise ValueError("Unexpected server reply: expected 'PRODUCT', got '{}'".format(reply))
|
||||||
|
contents = self.fsocket.read(int(length))
|
||||||
|
print("Download completed.")
|
||||||
|
return "OK", contents
|
||||||
|
|
||||||
|
def passwd(self, password):
|
||||||
|
self.send_command("PASSWD", password)
|
||||||
|
return self.read_reply() == ["OK"]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--server", default="nixbld.m-labs.hk", help="server to connect to (default: %(default)s)")
|
||||||
|
parser.add_argument("--port", default=7402, type=int, help="port to connect to (default: %(default)d)")
|
||||||
|
parser.add_argument("--cert", default=None, help="SSL certificate file used to authenticate server (default: afws.pem in ARTIQ)")
|
||||||
|
parser.add_argument("username", help="user name for logging into AFWS")
|
||||||
|
action = parser.add_subparsers(dest="action")
|
||||||
|
action.required = True
|
||||||
|
act_build = action.add_parser("build", help="build and download firmware")
|
||||||
|
act_build.add_argument("--rev", default=None, help="revision to build (default: currently installed ARTIQ revision)")
|
||||||
|
act_build.add_argument("variant", help="variant to build")
|
||||||
|
act_build.add_argument("directory", help="output directory")
|
||||||
|
act_passwd = action.add_parser("passwd", help="change password")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
cert = args.cert
|
||||||
|
if cert is None:
|
||||||
|
cert = get_artiq_cert()
|
||||||
|
if cert is None:
|
||||||
|
print("SSL certificate not found in ARTIQ. Specify manually using --cert.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if args.action == "passwd":
|
||||||
|
password = getpass("Current password: ")
|
||||||
|
else:
|
||||||
|
password = getpass()
|
||||||
|
|
||||||
|
client = Client(args.server, args.port, cert)
|
||||||
|
try:
|
||||||
|
if not client.login(args.username, password):
|
||||||
|
print("Login failed")
|
||||||
|
sys.exit(1)
|
||||||
|
print("Logged in successfully.")
|
||||||
|
if args.action == "passwd":
|
||||||
|
print("Password must made of alphanumeric characters (a-z, A-Z, 0-9) and be at least 8 characters long.")
|
||||||
|
password = getpass("New password: ")
|
||||||
|
password_confirm = getpass("New password (again): ")
|
||||||
|
while password != password_confirm:
|
||||||
|
print("Passwords do not match")
|
||||||
|
password = getpass("New password: ")
|
||||||
|
password_confirm = getpass("New password (again): ")
|
||||||
|
if not client.passwd(password):
|
||||||
|
print("Failed to change password")
|
||||||
|
sys.exit(1)
|
||||||
|
elif args.action == "build":
|
||||||
|
try:
|
||||||
|
os.mkdir(args.directory)
|
||||||
|
except FileExistsError:
|
||||||
|
try:
|
||||||
|
if any(os.scandir(args.directory)):
|
||||||
|
print("Output directory already exists and is not empty. Please remove it and try again.")
|
||||||
|
sys.exit(1)
|
||||||
|
except NotADirectoryError:
|
||||||
|
print("A file with the same name as the output directory already exists. Please remove it and try again.")
|
||||||
|
sys.exit(1)
|
||||||
|
rev = args.rev
|
||||||
|
if rev is None:
|
||||||
|
rev = get_artiq_rev()
|
||||||
|
if rev is None:
|
||||||
|
print("Unable to determine currently installed ARTIQ revision. Specify manually using --rev.")
|
||||||
|
sys.exit(1)
|
||||||
|
result, contents = client.build(rev, args.variant)
|
||||||
|
if result != "OK":
|
||||||
|
if result == "UNAUTHORIZED":
|
||||||
|
print("You are not authorized to build this variant. Your firmware subscription may have expired. Contact helpdesk\x40m-labs.hk.")
|
||||||
|
else:
|
||||||
|
print("Build failed: {}".format(result))
|
||||||
|
sys.exit(1)
|
||||||
|
zip_unarchive(contents, args.directory)
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
finally:
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -13,7 +13,6 @@ from collections import defaultdict
|
||||||
from sipyco import common_args
|
from sipyco import common_args
|
||||||
|
|
||||||
from artiq import __version__ as artiq_version
|
from artiq import __version__ as artiq_version
|
||||||
from artiq import __artiq_dir__ as artiq_dir
|
|
||||||
from artiq.remoting import SSHClient, LocalClient
|
from artiq.remoting import SSHClient, LocalClient
|
||||||
from artiq.frontend.bit2bin import bit2bin
|
from artiq.frontend.bit2bin import bit2bin
|
||||||
|
|
||||||
|
@ -63,13 +62,11 @@ Prerequisites:
|
||||||
parser.add_argument("-t", "--target", default="kasli",
|
parser.add_argument("-t", "--target", default="kasli",
|
||||||
help="target board, default: %(default)s, one of: "
|
help="target board, default: %(default)s, one of: "
|
||||||
"kasli sayma metlino kc705")
|
"kasli sayma metlino kc705")
|
||||||
parser.add_argument("-V", "--variant", default=None,
|
|
||||||
help="board variant. Autodetected if only one is installed.")
|
|
||||||
parser.add_argument("-I", "--preinit-command", default=[], action="append",
|
parser.add_argument("-I", "--preinit-command", default=[], action="append",
|
||||||
help="add a pre-initialization OpenOCD command. "
|
help="add a pre-initialization OpenOCD command. "
|
||||||
"Useful for selecting a board when several are connected.")
|
"Useful for selecting a board when several are connected.")
|
||||||
parser.add_argument("-f", "--storage", help="write file to storage area")
|
parser.add_argument("-f", "--storage", help="write file to storage area")
|
||||||
parser.add_argument("-d", "--dir", help="look for board binaries in this directory")
|
parser.add_argument("-d", "--dir", default=None, help="look for board binaries in this directory")
|
||||||
parser.add_argument("--srcbuild", help="board binaries directory is laid out as a source build tree",
|
parser.add_argument("--srcbuild", help="board binaries directory is laid out as a source build tree",
|
||||||
default=False, action="store_true")
|
default=False, action="store_true")
|
||||||
parser.add_argument("--no-rtm-jtag", help="do not attempt JTAG to the RTM",
|
parser.add_argument("--no-rtm-jtag", help="do not attempt JTAG to the RTM",
|
||||||
|
@ -338,56 +335,19 @@ def main():
|
||||||
},
|
},
|
||||||
}[args.target]
|
}[args.target]
|
||||||
|
|
||||||
bin_dir = args.dir
|
|
||||||
if bin_dir is None:
|
|
||||||
bin_dir = os.path.join(artiq_dir, "board-support")
|
|
||||||
|
|
||||||
needs_artifacts = not args.action or any(
|
|
||||||
action in args.action
|
|
||||||
for action in ["gateware", "rtm_gateware", "bootloader", "firmware", "load", "rtm_load"])
|
|
||||||
variant = args.variant
|
|
||||||
if needs_artifacts and variant is None:
|
|
||||||
variants = []
|
|
||||||
if args.srcbuild:
|
|
||||||
for entry in os.scandir(bin_dir):
|
|
||||||
if entry.is_dir():
|
|
||||||
variants.append(entry.name)
|
|
||||||
else:
|
|
||||||
prefix = args.target + "-"
|
|
||||||
for entry in os.scandir(bin_dir):
|
|
||||||
if entry.is_dir() and entry.name.startswith(prefix):
|
|
||||||
variants.append(entry.name[len(prefix):])
|
|
||||||
if args.target == "sayma":
|
|
||||||
try:
|
|
||||||
variants.remove("rtm")
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
if all(action in ["rtm_gateware", "storage", "rtm_load", "erase", "start"]
|
|
||||||
for action in args.action) and args.action:
|
|
||||||
pass
|
|
||||||
elif len(variants) == 0:
|
|
||||||
raise FileNotFoundError("no variants found, did you install a board binary package?")
|
|
||||||
elif len(variants) == 1:
|
|
||||||
variant = variants[0]
|
|
||||||
else:
|
|
||||||
raise ValueError("more than one variant found for selected board, specify -V. "
|
|
||||||
"Found variants: {}".format(" ".join(sorted(variants))))
|
|
||||||
if needs_artifacts:
|
|
||||||
if args.srcbuild:
|
|
||||||
variant_dir = variant
|
|
||||||
else:
|
|
||||||
variant_dir = args.target + "-" + variant
|
|
||||||
if args.target == "sayma":
|
|
||||||
if args.srcbuild:
|
|
||||||
rtm_variant_dir = "rtm"
|
|
||||||
else:
|
|
||||||
rtm_variant_dir = "sayma-rtm"
|
|
||||||
|
|
||||||
if not args.action:
|
if not args.action:
|
||||||
if args.target == "sayma" and variant != "simplesatellite" and variant != "master":
|
if args.target == "sayma":
|
||||||
args.action = "gateware rtm_gateware bootloader firmware start".split()
|
args.action = "gateware rtm_gateware bootloader firmware start".split()
|
||||||
else:
|
else:
|
||||||
args.action = "gateware bootloader firmware start".split()
|
args.action = "gateware bootloader firmware start".split()
|
||||||
|
needs_artifacts = any(
|
||||||
|
action in args.action
|
||||||
|
for action in ["gateware", "rtm_gateware", "bootloader", "firmware", "load", "rtm_load"])
|
||||||
|
if needs_artifacts and args.dir is None:
|
||||||
|
raise ValueError("the directory containing the binaries need to be specified using -d.")
|
||||||
|
|
||||||
|
binary_dir = args.dir
|
||||||
|
rtm_binary_dir = os.path.join(binary_dir, "rtm")
|
||||||
|
|
||||||
if args.host is None:
|
if args.host is None:
|
||||||
client = LocalClient()
|
client = LocalClient()
|
||||||
|
@ -400,14 +360,14 @@ def main():
|
||||||
programmer_cls = config["programmer"]
|
programmer_cls = config["programmer"]
|
||||||
programmer = programmer_cls(client, preinit_script=args.preinit_command)
|
programmer = programmer_cls(client, preinit_script=args.preinit_command)
|
||||||
|
|
||||||
def artifact_path(this_variant_dir, *path_filename):
|
def artifact_path(this_binary_dir, *path_filename):
|
||||||
if args.srcbuild:
|
if args.srcbuild:
|
||||||
# source tree - use path elements to locate file
|
# source tree - use path elements to locate file
|
||||||
return os.path.join(bin_dir, this_variant_dir, *path_filename)
|
return os.path.join(this_binary_dir, *path_filename)
|
||||||
else:
|
else:
|
||||||
# flat tree - all files in the same directory, discard path elements
|
# flat tree - all files in the same directory, discard path elements
|
||||||
*_, filename = path_filename
|
*_, filename = path_filename
|
||||||
return os.path.join(bin_dir, this_variant_dir, filename)
|
return os.path.join(this_binary_dir, filename)
|
||||||
|
|
||||||
def convert_gateware(bit_filename, header=False):
|
def convert_gateware(bit_filename, header=False):
|
||||||
bin_handle, bin_filename = tempfile.mkstemp(
|
bin_handle, bin_filename = tempfile.mkstemp(
|
||||||
|
@ -429,15 +389,15 @@ def main():
|
||||||
for action in args.action:
|
for action in args.action:
|
||||||
if action == "gateware":
|
if action == "gateware":
|
||||||
gateware_bin = convert_gateware(
|
gateware_bin = convert_gateware(
|
||||||
artifact_path(variant_dir, "gateware", "top.bit"))
|
artifact_path(binary_dir, "gateware", "top.bit"))
|
||||||
programmer.write_binary(*config["gateware"], gateware_bin)
|
programmer.write_binary(*config["gateware"], gateware_bin)
|
||||||
elif action == "rtm_gateware":
|
elif action == "rtm_gateware":
|
||||||
rtm_gateware_bin = convert_gateware(
|
rtm_gateware_bin = convert_gateware(
|
||||||
artifact_path(rtm_variant_dir, "gateware", "top.bit"), header=True)
|
artifact_path(rtm_binary_dir, "gateware", "top.bit"), header=True)
|
||||||
programmer.write_binary(*config["rtm_gateware"],
|
programmer.write_binary(*config["rtm_gateware"],
|
||||||
rtm_gateware_bin)
|
rtm_gateware_bin)
|
||||||
elif action == "bootloader":
|
elif action == "bootloader":
|
||||||
bootloader_bin = artifact_path(variant_dir, "software", "bootloader", "bootloader.bin")
|
bootloader_bin = artifact_path(binary_dir, "software", "bootloader", "bootloader.bin")
|
||||||
programmer.write_binary(*config["bootloader"], bootloader_bin)
|
programmer.write_binary(*config["bootloader"], bootloader_bin)
|
||||||
elif action == "storage":
|
elif action == "storage":
|
||||||
storage_img = args.storage
|
storage_img = args.storage
|
||||||
|
@ -445,7 +405,7 @@ def main():
|
||||||
elif action == "firmware":
|
elif action == "firmware":
|
||||||
firmware_fbis = []
|
firmware_fbis = []
|
||||||
for firmware in "satman", "runtime":
|
for firmware in "satman", "runtime":
|
||||||
filename = artifact_path(variant_dir, "software", firmware, firmware + ".fbi")
|
filename = artifact_path(binary_dir, "software", firmware, firmware + ".fbi")
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
firmware_fbis.append(filename)
|
firmware_fbis.append(filename)
|
||||||
if not firmware_fbis:
|
if not firmware_fbis:
|
||||||
|
@ -456,13 +416,13 @@ def main():
|
||||||
programmer.write_binary(*config["firmware"], firmware_fbis[0])
|
programmer.write_binary(*config["firmware"], firmware_fbis[0])
|
||||||
elif action == "load":
|
elif action == "load":
|
||||||
if args.target == "sayma":
|
if args.target == "sayma":
|
||||||
gateware_bit = artifact_path(variant_dir, "gateware", "top.bit")
|
gateware_bit = artifact_path(binary_dir, "gateware", "top.bit")
|
||||||
programmer.load(gateware_bit, 1)
|
programmer.load(gateware_bit, 1)
|
||||||
else:
|
else:
|
||||||
gateware_bit = artifact_path(variant_dir, "gateware", "top.bit")
|
gateware_bit = artifact_path(binary_dir, "gateware", "top.bit")
|
||||||
programmer.load(gateware_bit, 0)
|
programmer.load(gateware_bit, 0)
|
||||||
elif action == "rtm_load":
|
elif action == "rtm_load":
|
||||||
rtm_gateware_bit = artifact_path(rtm_variant_dir, "gateware", "top.bit")
|
rtm_gateware_bit = artifact_path(rtm_binary_dir, "gateware", "top.bit")
|
||||||
programmer.load(rtm_gateware_bit, 0)
|
programmer.load(rtm_gateware_bit, 0)
|
||||||
elif action == "start":
|
elif action == "start":
|
||||||
programmer.start()
|
programmer.start()
|
||||||
|
|
|
@ -331,7 +331,7 @@ class SinaraTester(EnvExperiment):
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
channel.init()
|
channel.init()
|
||||||
|
|
||||||
channel.set_att_mu(160)
|
channel.set_att(11.5*dB)
|
||||||
channel.sw.on()
|
channel.sw.on()
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,17 @@ class NumberEntryInt(QtWidgets.QSpinBox):
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
return procdesc["default"]
|
return procdesc["default"]
|
||||||
else:
|
else:
|
||||||
|
have_max = "max" in procdesc and procdesc["max"] is not None
|
||||||
|
have_min = "min" in procdesc and procdesc["min"] is not None
|
||||||
|
if have_max and have_min:
|
||||||
|
if procdesc["min"] <= 0 < procdesc["max"]:
|
||||||
|
return 0
|
||||||
|
elif have_min and not have_max:
|
||||||
|
if procdesc["min"] >= 0:
|
||||||
|
return procdesc["min"]
|
||||||
|
elif not have_min and have_max:
|
||||||
|
if procdesc["max"] < 0:
|
||||||
|
return procdesc["max"]
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -515,3 +515,26 @@ class NumpyBoolTest(ExperimentCase):
|
||||||
def test_numpy_bool(self):
|
def test_numpy_bool(self):
|
||||||
"""Test NumPy bools decay to ARTIQ compiler builtin bools as expected"""
|
"""Test NumPy bools decay to ARTIQ compiler builtin bools as expected"""
|
||||||
self.create(_NumpyBool).run()
|
self.create(_NumpyBool).run()
|
||||||
|
|
||||||
|
|
||||||
|
class _Alignment(EnvExperiment):
|
||||||
|
def build(self):
|
||||||
|
self.setattr_device("core")
|
||||||
|
|
||||||
|
@rpc
|
||||||
|
def a_tuple(self) -> TList(TTuple([TBool, TFloat, TBool])):
|
||||||
|
return [(True, 1234.5678, True)]
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def run(self):
|
||||||
|
a, b, c = self.a_tuple()[0]
|
||||||
|
d, e, f = self.a_tuple()[0]
|
||||||
|
assert a == d
|
||||||
|
assert b == e
|
||||||
|
assert c == f
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
class AlignmentTest(ExperimentCase):
|
||||||
|
def test_tuple(self):
|
||||||
|
self.create(_Alignment).run()
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
ARTIQ documentation
|
ARTIQ documentation
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Contents:
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
:caption: Contents
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
introduction
|
introduction
|
||||||
|
|
104
flake.lock
104
flake.lock
|
@ -1,5 +1,29 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"artiq-comtools": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nac3",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"sipyco": [
|
||||||
|
"sipyco"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1644743100,
|
||||||
|
"narHash": "sha256-XqxMq2l2DXSovV7r2k/FXjYRM3bvVl3Mjy+C1koVAx4=",
|
||||||
|
"owner": "m-labs",
|
||||||
|
"repo": "artiq-comtools",
|
||||||
|
"rev": "8a126dd7d0a3f2d50ae151ec633cd52587d98796",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "m-labs",
|
||||||
|
"repo": "artiq-comtools",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mozilla-overlay": {
|
"mozilla-overlay": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
|
@ -16,6 +40,24 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nac3": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1644759922,
|
||||||
|
"narHash": "sha256-3hNFahCeHp0seppVONSlAMXIzn0vjCJGrJj6CySLLxw=",
|
||||||
|
"ref": "master",
|
||||||
|
"rev": "21d9182ba2924cf9cc555a201e661d2ea474eed9",
|
||||||
|
"revCount": 594,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.m-labs.hk/M-Labs/nac3.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.m-labs.hk/M-Labs/nac3.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1644472683,
|
"lastModified": 1644472683,
|
||||||
|
@ -34,11 +76,33 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"artiq-comtools": "artiq-comtools",
|
||||||
"mozilla-overlay": "mozilla-overlay",
|
"mozilla-overlay": "mozilla-overlay",
|
||||||
|
"nac3": "nac3",
|
||||||
|
"sipyco": "sipyco",
|
||||||
"src-migen": "src-migen",
|
"src-migen": "src-migen",
|
||||||
"src-misoc": "src-misoc",
|
"src-misoc": "src-misoc"
|
||||||
"src-nac3": "src-nac3",
|
}
|
||||||
"src-sipyco": "src-sipyco"
|
},
|
||||||
|
"sipyco": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nac3",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1644649772,
|
||||||
|
"narHash": "sha256-LE9L5bDSunCPEnuf5Ed8enTAXA2vkTSmjvqPX9ILO0Y=",
|
||||||
|
"owner": "m-labs",
|
||||||
|
"repo": "sipyco",
|
||||||
|
"rev": "8e4382352bc64bd01c9db35d9c9b0ef42b8b9d3b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "m-labs",
|
||||||
|
"repo": "sipyco",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src-migen": {
|
"src-migen": {
|
||||||
|
@ -74,40 +138,6 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/m-labs/misoc.git"
|
"url": "https://github.com/m-labs/misoc.git"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"src-nac3": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1644723702,
|
|
||||||
"narHash": "sha256-2pLJHYvQmoXhdy3WDZpfU7kDMpgH/G7uREZOyql7R10=",
|
|
||||||
"ref": "master",
|
|
||||||
"rev": "4b8e70f7462b139e388f098d42f9f47e4915f431",
|
|
||||||
"revCount": 589,
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.m-labs.hk/M-Labs/nac3.git"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.m-labs.hk/M-Labs/nac3.git"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"src-sipyco": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1644649772,
|
|
||||||
"narHash": "sha256-LE9L5bDSunCPEnuf5Ed8enTAXA2vkTSmjvqPX9ILO0Y=",
|
|
||||||
"owner": "m-labs",
|
|
||||||
"repo": "sipyco",
|
|
||||||
"rev": "8e4382352bc64bd01c9db35d9c9b0ef42b8b9d3b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "m-labs",
|
|
||||||
"repo": "sipyco",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|
122
flake.nix
122
flake.nix
|
@ -2,20 +2,25 @@
|
||||||
description = "A leading-edge control system for quantum information experiments";
|
description = "A leading-edge control system for quantum information experiments";
|
||||||
|
|
||||||
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
||||||
inputs.src-sipyco = { url = github:m-labs/sipyco; flake = false; };
|
inputs.sipyco.url = github:m-labs/sipyco;
|
||||||
inputs.src-nac3 = { type = "git"; url = "https://git.m-labs.hk/M-Labs/nac3.git"; };
|
inputs.sipyco.inputs.nixpkgs.follows = "nac3/nixpkgs";
|
||||||
|
inputs.nac3 = { type = "git"; url = "https://git.m-labs.hk/M-Labs/nac3.git"; };
|
||||||
|
inputs.artiq-comtools.url = github:m-labs/artiq-comtools;
|
||||||
|
inputs.artiq-comtools.inputs.nixpkgs.follows = "nac3/nixpkgs";
|
||||||
|
inputs.artiq-comtools.inputs.sipyco.follows = "sipyco";
|
||||||
|
|
||||||
inputs.src-migen = { url = github:m-labs/migen; flake = false; };
|
inputs.src-migen = { url = github:m-labs/migen; flake = false; };
|
||||||
inputs.src-misoc = { type = "git"; url = "https://github.com/m-labs/misoc.git"; submodules = true; flake = false; };
|
inputs.src-misoc = { type = "git"; url = "https://github.com/m-labs/misoc.git"; submodules = true; flake = false; };
|
||||||
|
|
||||||
outputs = { self, mozilla-overlay, src-sipyco, src-nac3, src-migen, src-misoc }:
|
outputs = { self, mozilla-overlay, sipyco, nac3, artiq-comtools, src-migen, src-misoc }:
|
||||||
let
|
let
|
||||||
pkgs = import src-nac3.inputs.nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; };
|
pkgs = import nac3.inputs.nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; };
|
||||||
|
|
||||||
artiqVersionMajor = 8;
|
artiqVersionMajor = 8;
|
||||||
artiqVersionMinor = self.sourceInfo.revCount or 0;
|
artiqVersionMinor = self.sourceInfo.revCount or 0;
|
||||||
artiqVersionId = self.sourceInfo.shortRev or "unknown";
|
artiqVersionId = self.sourceInfo.shortRev or "unknown";
|
||||||
artiqVersion = (builtins.toString artiqVersionMajor) + "." + (builtins.toString artiqVersionMinor) + "-" + artiqVersionId + "-beta";
|
artiqVersion = (builtins.toString artiqVersionMajor) + "." + (builtins.toString artiqVersionMinor) + "." + artiqVersionId + ".beta";
|
||||||
|
artiqRev = self.sourceInfo.rev or "unknown";
|
||||||
|
|
||||||
rustManifest = pkgs.fetchurl {
|
rustManifest = pkgs.fetchurl {
|
||||||
url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml";
|
url = "https://static.rust-lang.org/dist/2021-01-29/channel-rust-nightly.toml";
|
||||||
|
@ -51,12 +56,6 @@
|
||||||
fontconfig
|
fontconfig
|
||||||
];
|
];
|
||||||
|
|
||||||
sipyco = pkgs.python3Packages.buildPythonPackage {
|
|
||||||
name = "sipyco";
|
|
||||||
src = src-sipyco;
|
|
||||||
propagatedBuildInputs = with pkgs.python3Packages; [ pybase64 numpy ];
|
|
||||||
};
|
|
||||||
|
|
||||||
qasync = pkgs.python3Packages.buildPythonPackage rec {
|
qasync = pkgs.python3Packages.buildPythonPackage rec {
|
||||||
pname = "qasync";
|
pname = "qasync";
|
||||||
version = "0.19.0";
|
version = "0.19.0";
|
||||||
|
@ -78,11 +77,15 @@
|
||||||
version = artiqVersion;
|
version = artiqVersion;
|
||||||
src = self;
|
src = self;
|
||||||
|
|
||||||
preBuild = "export VERSIONEER_OVERRIDE=${version}";
|
preBuild =
|
||||||
|
''
|
||||||
|
export VERSIONEER_OVERRIDE=${version}
|
||||||
|
export VERSIONEER_REV=${artiqRev}
|
||||||
|
'';
|
||||||
|
|
||||||
nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ];
|
nativeBuildInputs = [ pkgs.qt5.wrapQtAppsHook ];
|
||||||
# keep llvm_x and lld_x in sync with nac3
|
# keep llvm_x and lld_x in sync with nac3
|
||||||
propagatedBuildInputs = [ pkgs.llvm_13 pkgs.lld_13 src-nac3.packages.x86_64-linux.nac3artiq sipyco ]
|
propagatedBuildInputs = [ pkgs.llvm_13 pkgs.lld_13 nac3.packages.x86_64-linux.nac3artiq sipyco.packages.x86_64-linux.sipyco artiq-comtools.packages.x86_64-linux.artiq-comtools ]
|
||||||
++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial h5py pyqt5 qasync ]);
|
++ (with pkgs.python3Packages; [ pyqtgraph pygit2 numpy dateutil scipy prettytable pyserial h5py pyqt5 qasync ]);
|
||||||
|
|
||||||
dontWrapQtApps = true;
|
dontWrapQtApps = true;
|
||||||
|
@ -183,7 +186,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }:
|
makeArtiqBoardPackage = { target, variant, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}" }:
|
||||||
pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation {
|
pkgs.stdenv.mkDerivation {
|
||||||
name = "artiq-board-${target}-${variant}";
|
name = "artiq-board-${target}-${variant}";
|
||||||
phases = [ "buildPhase" "checkPhase" "installPhase" ];
|
phases = [ "buildPhase" "checkPhase" "installPhase" ];
|
||||||
cargoDeps = rustPlatform.fetchCargoTarball {
|
cargoDeps = rustPlatform.fetchCargoTarball {
|
||||||
|
@ -192,7 +195,7 @@
|
||||||
sha256 = "sha256-YyycMsDzR+JRcMZJd6A/CRi2J9nKmaWY/KXUnAQaZ00=";
|
sha256 = "sha256-YyycMsDzR+JRcMZJd6A/CRi2J9nKmaWY/KXUnAQaZ00=";
|
||||||
};
|
};
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
(pkgs.python3.withPackages(ps: [ migen misoc artiq ]))
|
(pkgs.python3.withPackages(ps: [ ps.jsonschema migen misoc artiq]))
|
||||||
rustPlatform.rust.rustc
|
rustPlatform.rust.rustc
|
||||||
rustPlatform.rust.cargo
|
rustPlatform.rust.cargo
|
||||||
pkgs.llvmPackages_13.clang-unwrapped
|
pkgs.llvmPackages_13.clang-unwrapped
|
||||||
|
@ -222,7 +225,7 @@
|
||||||
'';
|
'';
|
||||||
installPhase =
|
installPhase =
|
||||||
''
|
''
|
||||||
TARGET_DIR=$out/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant}
|
TARGET_DIR=$out
|
||||||
mkdir -p $TARGET_DIR
|
mkdir -p $TARGET_DIR
|
||||||
cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR
|
cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR
|
||||||
if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ]
|
if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ]
|
||||||
|
@ -235,7 +238,7 @@
|
||||||
'';
|
'';
|
||||||
# don't mangle ELF files as they are not for NixOS
|
# don't mangle ELF files as they are not for NixOS
|
||||||
dontFixup = true;
|
dontFixup = true;
|
||||||
});
|
};
|
||||||
|
|
||||||
openocd-bscanspi = let
|
openocd-bscanspi = let
|
||||||
bscan_spi_bitstreams-pkg = pkgs.stdenv.mkDerivation {
|
bscan_spi_bitstreams-pkg = pkgs.stdenv.mkDerivation {
|
||||||
|
@ -275,36 +278,79 @@
|
||||||
name = "openocd-bscanspi";
|
name = "openocd-bscanspi";
|
||||||
paths = [ openocd-fixed bscan_spi_bitstreams-pkg ];
|
paths = [ openocd-fixed bscan_spi_bitstreams-pkg ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sphinxcontrib-wavedrom = pkgs.python3Packages.buildPythonPackage rec {
|
||||||
|
pname = "sphinxcontrib-wavedrom";
|
||||||
|
version = "3.0.2";
|
||||||
|
src = pkgs.python3Packages.fetchPypi {
|
||||||
|
inherit pname version;
|
||||||
|
sha256 = "sha256-ukZd3ajt0Sx3LByof4R80S31F5t1yo+L8QUADrMMm2A=";
|
||||||
|
};
|
||||||
|
buildInputs = [ pkgs.python3Packages.setuptools_scm ];
|
||||||
|
propagatedBuildInputs = [ pkgs.nodejs pkgs.nodePackages.wavedrom-cli ] ++ (with pkgs.python3Packages; [ wavedrom sphinx xcffib cairosvg ]);
|
||||||
|
};
|
||||||
|
latex-artiq-manual = pkgs.texlive.combine {
|
||||||
|
inherit (pkgs.texlive)
|
||||||
|
scheme-basic latexmk cmap collection-fontsrecommended fncychap
|
||||||
|
titlesec tabulary varwidth framed fancyvrb float wrapfig parskip
|
||||||
|
upquote capt-of needspace etoolbox;
|
||||||
|
};
|
||||||
in rec {
|
in rec {
|
||||||
packages.x86_64-linux = rec {
|
packages.x86_64-linux = rec {
|
||||||
inherit migen misoc vivadoEnv vivado openocd-bscanspi artiq;
|
inherit (nac3.packages.x86_64-linux) python3-mimalloc;
|
||||||
inherit (src-nac3.packages.x86_64-linux) python3-mimalloc;
|
inherit qasync openocd-bscanspi artiq;
|
||||||
|
inherit migen misoc asyncserial microscope vivadoEnv vivado;
|
||||||
artiq-board-kc705-nist_clock = makeArtiqBoardPackage {
|
artiq-board-kc705-nist_clock = makeArtiqBoardPackage {
|
||||||
target = "kc705";
|
target = "kc705";
|
||||||
variant = "nist_clock";
|
variant = "nist_clock";
|
||||||
};
|
};
|
||||||
artiq-board-kc705-nist_qc2 = makeArtiqBoardPackage {
|
inherit sphinxcontrib-wavedrom latex-artiq-manual;
|
||||||
target = "kc705";
|
artiq-manual-html = pkgs.stdenvNoCC.mkDerivation rec {
|
||||||
variant = "nist_qc2";
|
name = "artiq-manual-html-${version}";
|
||||||
|
version = artiqVersion;
|
||||||
|
src = self;
|
||||||
|
buildInputs = [
|
||||||
|
pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme
|
||||||
|
pkgs.python3Packages.sphinx-argparse sphinxcontrib-wavedrom
|
||||||
|
];
|
||||||
|
buildPhase = ''
|
||||||
|
export VERSIONEER_OVERRIDE=${artiqVersion}
|
||||||
|
export SOURCE_DATE_EPOCH=${builtins.toString self.sourceInfo.lastModified}
|
||||||
|
cd doc/manual
|
||||||
|
make html
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
cp -r _build/html $out
|
||||||
|
mkdir $out/nix-support
|
||||||
|
echo doc manual $out index.html >> $out/nix-support/hydra-build-products
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
artiq-board-kc705-nist_clock_master = makeArtiqBoardPackage {
|
artiq-manual-pdf = pkgs.stdenvNoCC.mkDerivation rec {
|
||||||
target = "kc705";
|
name = "artiq-manual-pdf-${version}";
|
||||||
variant = "nist_clock_master";
|
version = artiqVersion;
|
||||||
};
|
src = self;
|
||||||
artiq-board-kc705-nist_qc2_master = makeArtiqBoardPackage {
|
buildInputs = [
|
||||||
target = "kc705";
|
pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme
|
||||||
variant = "nist_qc2_master";
|
pkgs.python3Packages.sphinx-argparse sphinxcontrib-wavedrom
|
||||||
};
|
latex-artiq-manual
|
||||||
artiq-board-kc705-nist_clock_satellite = makeArtiqBoardPackage {
|
];
|
||||||
target = "kc705";
|
buildPhase = ''
|
||||||
variant = "nist_clock";
|
export VERSIONEER_OVERRIDE=${artiq.version}
|
||||||
};
|
export SOURCE_DATE_EPOCH=${builtins.toString self.sourceInfo.lastModified}
|
||||||
artiq-board-kc705-nist_qc2_satellite = makeArtiqBoardPackage {
|
cd doc/manual
|
||||||
target = "kc705";
|
make latexpdf
|
||||||
variant = "nist_qc2";
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
cp _build/latex/ARTIQ.pdf $out
|
||||||
|
mkdir $out/nix-support
|
||||||
|
echo doc-pdf manual $out ARTIQ.pdf >> $out/nix-support/hydra-build-products
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inherit makeArtiqBoardPackage;
|
||||||
|
|
||||||
defaultPackage.x86_64-linux = packages.x86_64-linux.python3-mimalloc.withPackages(ps: [ packages.x86_64-linux.artiq ]);
|
defaultPackage.x86_64-linux = packages.x86_64-linux.python3-mimalloc.withPackages(ps: [ packages.x86_64-linux.artiq ]);
|
||||||
|
|
||||||
devShell.x86_64-linux = pkgs.mkShell {
|
devShell.x86_64-linux = pkgs.mkShell {
|
||||||
|
@ -321,6 +367,8 @@
|
||||||
packages.x86_64-linux.vivadoEnv
|
packages.x86_64-linux.vivadoEnv
|
||||||
packages.x86_64-linux.vivado
|
packages.x86_64-linux.vivado
|
||||||
packages.x86_64-linux.openocd-bscanspi
|
packages.x86_64-linux.openocd-bscanspi
|
||||||
|
pkgs.python3Packages.sphinx pkgs.python3Packages.sphinx_rtd_theme
|
||||||
|
pkgs.python3Packages.sphinx-argparse sphinxcontrib-wavedrom latex-artiq-manual
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -35,6 +35,7 @@ console_scripts = [
|
||||||
"artiq_run = artiq.frontend.artiq_run:main",
|
"artiq_run = artiq.frontend.artiq_run:main",
|
||||||
"artiq_flash = artiq.frontend.artiq_flash:main",
|
"artiq_flash = artiq.frontend.artiq_flash:main",
|
||||||
"aqctl_corelog = artiq.frontend.aqctl_corelog:main",
|
"aqctl_corelog = artiq.frontend.aqctl_corelog:main",
|
||||||
|
"afws_client = artiq.frontend.afws_client:main",
|
||||||
]
|
]
|
||||||
|
|
||||||
gui_scripts = [
|
gui_scripts = [
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
VERSION_FILE = """
|
VERSION_FILE = """
|
||||||
def get_version():
|
def get_version():
|
||||||
return "{version}"
|
return "{version}"
|
||||||
|
|
||||||
|
def get_rev():
|
||||||
|
return "{rev}"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
|
@ -18,10 +22,13 @@ def get_version():
|
||||||
version += ".beta"
|
version += ".beta"
|
||||||
return version
|
return version
|
||||||
|
|
||||||
def write_to_version_file(filename, version):
|
def get_rev():
|
||||||
|
return os.getenv("VERSIONEER_REV", default="unknown")
|
||||||
|
|
||||||
|
def write_to_version_file(filename, version, rev):
|
||||||
os.unlink(filename)
|
os.unlink(filename)
|
||||||
with open(filename, "w") as f:
|
with open(filename, "w") as f:
|
||||||
f.write(VERSION_FILE.format(version=version))
|
f.write(VERSION_FILE.format(version=version, rev=rev))
|
||||||
|
|
||||||
|
|
||||||
def get_cmdclass():
|
def get_cmdclass():
|
||||||
|
@ -36,11 +43,12 @@ def get_cmdclass():
|
||||||
class cmd_build_py(_build_py):
|
class cmd_build_py(_build_py):
|
||||||
def run(self):
|
def run(self):
|
||||||
version = get_version()
|
version = get_version()
|
||||||
|
rev = get_rev()
|
||||||
_build_py.run(self)
|
_build_py.run(self)
|
||||||
target_versionfile = os.path.join(self.build_lib,
|
target_versionfile = os.path.join(self.build_lib,
|
||||||
"artiq", "_version.py")
|
"artiq", "_version.py")
|
||||||
print("UPDATING %s" % target_versionfile)
|
print("UPDATING %s" % target_versionfile)
|
||||||
write_to_version_file(target_versionfile, version)
|
write_to_version_file(target_versionfile, version, rev)
|
||||||
cmds["build_py"] = cmd_build_py
|
cmds["build_py"] = cmd_build_py
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +62,7 @@ def get_cmdclass():
|
||||||
def run(self):
|
def run(self):
|
||||||
version = get_version()
|
version = get_version()
|
||||||
self._versioneer_generated_version = version
|
self._versioneer_generated_version = version
|
||||||
|
self._versioneer_rev = get_rev()
|
||||||
# unless we update this, the command will keep using the old
|
# unless we update this, the command will keep using the old
|
||||||
# version
|
# version
|
||||||
self.distribution.metadata.version = version
|
self.distribution.metadata.version = version
|
||||||
|
@ -64,7 +73,8 @@ def get_cmdclass():
|
||||||
target_versionfile = os.path.join(base_dir, "artiq", "_version.py")
|
target_versionfile = os.path.join(base_dir, "artiq", "_version.py")
|
||||||
print("UPDATING %s" % target_versionfile)
|
print("UPDATING %s" % target_versionfile)
|
||||||
write_to_version_file(target_versionfile,
|
write_to_version_file(target_versionfile,
|
||||||
self._versioneer_generated_version)
|
self._versioneer_generated_version,
|
||||||
|
self._versioneer_rev)
|
||||||
cmds["sdist"] = cmd_sdist
|
cmds["sdist"] = cmd_sdist
|
||||||
|
|
||||||
return cmds
|
return cmds
|
||||||
|
|
Loading…
Reference in New Issue