Compare commits

..

1 Commits

Author SHA1 Message Date
Astro e138bfb7f7 tecpak: init 2019-10-30 20:10:23 +01:00
88 changed files with 16294 additions and 1732 deletions

125
artiq-fast.nix Normal file
View File

@ -0,0 +1,125 @@
let
pkgs = import <nixpkgs> {};
artiqSrc = <artiqSrc>;
generatedNix = pkgs.runCommand "generated-nix" { buildInputs = [ pkgs.nix pkgs.git ]; }
''
cp --no-preserve=mode,ownership -R ${./artiq-fast} $out
REV=`git --git-dir ${artiqSrc}/.git rev-parse HEAD`
MAJOR_VERSION=`cat ${artiqSrc}/MAJOR_VERSION`
COMMIT_COUNT=`git --git-dir ${artiqSrc}/.git rev-list --count HEAD`
TIMESTAMP=`git --git-dir ${artiqSrc}/.git log -1 --format=%ct`
ARTIQ_SRC_CLEAN=`mktemp -d`
cp -a ${artiqSrc}/. $ARTIQ_SRC_CLEAN
chmod -R 755 $ARTIQ_SRC_CLEAN/.git
chmod 755 $ARTIQ_SRC_CLEAN
rm -rf $ARTIQ_SRC_CLEAN/.git
HASH=`nix-hash --type sha256 --base32 $ARTIQ_SRC_CLEAN`
cat > $out/pkgs/artiq-src.nix << EOF
{ fetchgit }:
fetchgit {
url = "git://github.com/m-labs/artiq.git";
rev = "$REV";
sha256 = "$HASH";
}
EOF
echo "{ stdenv, git, fetchgit }: \"$MAJOR_VERSION.$COMMIT_COUNT.`cut -c1-8 <<< $REV`.beta\"" > $out/pkgs/artiq-version.nix
echo "{ stdenv, git, fetchgit }: \"$TIMESTAMP\"" > $out/pkgs/artiq-timestamp.nix
'';
generateTestOkHash = pkgs.runCommand "generate-test-ok-hash" { buildInputs = [ pkgs.nix ]; }
''
TMPDIR=`mktemp -d`
cp ${generatedNix}/pkgs/artiq-version.nix $TMPDIR/passed
HASH=`nix-hash --type sha256 --base32 $TMPDIR`
echo \"$HASH\" > $out
'';
artiqpkgs = import "${generatedNix}/default.nix" { inherit pkgs; };
artiqVersion = import "${generatedNix}/pkgs/artiq-version.nix" (with pkgs; { inherit stdenv fetchgit git; });
windowsRunner = overrides:
import "${generatedNix}/windows/run-test.nix" ({
inherit pkgs;
artiqPkg = artiqpkgs.conda-artiq;
} // overrides);
jobs = (builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) artiqpkgs);
in
jobs // {
generated-nix = pkgs.lib.hydraJob generatedNix; # used by artiq-full
artiq-fast = pkgs.releaseTools.channel {
name = "artiq-fast";
src = generatedNix;
constituents = builtins.attrValues jobs;
};
windows-no-hardware-tests = pkgs.stdenv.mkDerivation {
name = "windows-no-hardware-tests";
buildInputs = [ (windowsRunner {}) ];
phases = [ "buildPhase" ];
buildPhase = ''
${windowsRunner {}}/bin/run.sh
touch $out
'';
};
# HACK: Abuse fixed-output derivations to escape the sandbox and run the hardware
# unit tests, all integrated in the Hydra interface.
# One major downside of this hack is the tests are only run when generateTestOkHash
# changes, i.e. when the ARTIQ version changes (and not the dependencies).
# Impure derivations, when they land in Nix/Hydra, should improve the situation.
extended-tests = pkgs.stdenv.mkDerivation {
name = "extended-tests";
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = import generateTestOkHash;
__hydraRetry = false;
buildInputs = [
(pkgs.python3.withPackages(ps: [ ps.paramiko artiqpkgs.artiq artiqpkgs.artiq-board-kc705-nist_clock ]))
artiqpkgs.binutils-or1k
artiqpkgs.openocd
pkgs.iputils
pkgs.openssh
];
phases = [ "buildPhase" ];
buildPhase =
''
export HOME=`mktemp -d`
mkdir $HOME/.ssh
cp /opt/hydra_id_rsa $HOME/.ssh/id_rsa
cp /opt/hydra_id_rsa.pub $HOME/.ssh/id_rsa.pub
echo "rpi-1,192.168.1.188 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMc7waNkP2HjL5Eo94evoxJhC8CbYj4i2n1THe5TPIR3" > $HOME/.ssh/known_hosts
chmod 600 $HOME/.ssh/id_rsa
LOCKCTL=$(mktemp -d)
mkfifo $LOCKCTL/lockctl
cat $LOCKCTL/lockctl | ${pkgs.openssh}/bin/ssh \
-i $HOME/.ssh/id_rsa \
-o UserKnownHostsFile=$HOME/.ssh/known_hosts \
sb@rpi-1 \
'flock /tmp/board_lock-kc705-1 -c "echo Ok; cat"' \
| (
# End remote flock via FIFO
atexit_unlock() {
echo > $LOCKCTL/lockctl
}
trap atexit_unlock EXIT
# Read "Ok" line when remote successfully locked
read LOCK_OK
artiq_flash -t kc705 -H rpi-1
sleep 15
# ping: socket: Operation not permitted
#ping kc705-1 -c10 -w30
export ARTIQ_ROOT=`python -c "import artiq; print(artiq.__path__[0])"`/examples/kc705_nist_clock
export ARTIQ_LOW_LATENCY=1
python -m unittest discover -v artiq.test.coredevice
${windowsRunner { testCommand = "set ARTIQ_ROOT=%cd%\\anaconda\\envs\\artiq-env\\Lib\\site-packages\\artiq\\examples\\kc705_nist_clock&&python -m unittest discover -v artiq.test.coredevice"; }}/bin/run.sh
)
mkdir $out
cp ${generatedNix}/pkgs/artiq-version.nix $out/passed
'';
};
}

View File

@ -0,0 +1,97 @@
# Install Vivado in /opt and add to /etc/nixos/configuration.nix:
# nix.sandboxPaths = ["/opt"];
{ pkgs }:
{ target
, variant
, buildCommand ? "python -m artiq.gateware.targets.${target} -V ${variant}"
, extraInstallCommands ? ""}:
let
artiqSrc = import ./pkgs/artiq-src.nix { fetchgit = pkgs.fetchgit; };
fetchcargo = import ./fetchcargo.nix {
inherit (pkgs) stdenv cacert git cargo cargo-vendor;
};
cargoDeps = fetchcargo rec {
name = "artiq-firmware-cargo-deps";
src = "${artiqSrc}/artiq/firmware";
sha256 = "1xzjn9i4rkd9124v2gbdplsgsvp1hlx7czdgc58n316vsnrkbr86";
};
cargoVendored = pkgs.stdenv.mkDerivation {
name = "artiq-firmware-cargo-vendored";
src = cargoDeps;
phases = [ "unpackPhase" "installPhase" ];
installPhase =
''
mkdir -p $out/registry
cat << EOF > $out/config
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = "vendored-sources"
[source."https://github.com/m-labs/libfringe"]
git = "https://github.com/m-labs/libfringe"
rev = "b8a6d8f"
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "$out/registry"
EOF
cp -R * $out/registry
'';
};
vivado = import ./vivado.nix { inherit pkgs; };
artiqpkgs = import ./default.nix { inherit pkgs; };
# Board packages are Python modules so that they get added to the ARTIQ Python
# environment, and artiq_flash finds them.
in pkgs.python3Packages.toPythonModule (pkgs.stdenv.mkDerivation rec {
name = "artiq-board-${target}-${variant}-${version}";
version = import ./pkgs/artiq-version.nix (with pkgs; { inherit stdenv fetchgit git; });
phases = [ "buildPhase" "installCheckPhase" "installPhase" ];
buildInputs = [
vivado
pkgs.gnumake
(pkgs.python3.withPackages(ps: with ps; [ jinja2 numpy artiqpkgs.migen artiqpkgs.microscope artiqpkgs.misoc artiqpkgs.jesd204b artiqpkgs.artiq ]))
pkgs.cargo
artiqpkgs.rustc
artiqpkgs.binutils-or1k
artiqpkgs.llvm-or1k
];
buildPhase =
''
export CARGO_HOME=${cargoVendored}
export TARGET_AR=or1k-linux-ar
${buildCommand}
'';
checkPhase = ''
# Search for PCREs in the Vivado output to check for errors
check_log() {
set +e
grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log
FOUND=$?
set -e
if [ $FOUND != 1 ]; then
exit 1
fi
}
check_log "\d+ constraint not met\."
check_log "Timing constraints are not met\."
'';
installPhase =
''
TARGET_DIR=$out/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant}
mkdir -p $TARGET_DIR
cp artiq_${target}/${variant}/gateware/top.bit $TARGET_DIR
if [ -e artiq_${target}/${variant}/software/bootloader/bootloader.bin ]
then cp artiq_${target}/${variant}/software/bootloader/bootloader.bin $TARGET_DIR
fi
if [ -e artiq_${target}/${variant}/software/runtime ]
then cp artiq_${target}/${variant}/software/runtime/runtime.{elf,fbi} $TARGET_DIR
else cp artiq_${target}/${variant}/software/satman/satman.{elf,fbi} $TARGET_DIR
fi
${extraInstallCommands}
'';
})

View File

@ -0,0 +1,18 @@
[
"python >=3.5.3,<3.6"
"llvmlite-artiq 0.23.0.dev py35_5"
"binutils-or1k-linux >=2.27"
"pythonparser >=1.1"
"openocd 0.10.0 6"
"scipy"
"numpy"
"prettytable"
"h5py 2.8"
"python-dateutil"
"pyqt >=5.5"
"quamash"
"pyqtgraph 0.10.0"
"pygit2"
"aiohttp >=3"
"python-levenshtein"
]

View File

@ -0,0 +1,16 @@
{ pkgs }:
let
version = import ./pkgs/artiq-version.nix (with pkgs; { inherit stdenv fetchgit git; });
fakeCondaSource = import ./conda-fake-source.nix { inherit pkgs; } {
name = "artiq";
inherit version;
src = import ./pkgs/artiq-src.nix { fetchgit = pkgs.fetchgit; };
dependencies = import ./conda-artiq-deps.nix;
};
conda-artiq = import ./conda-build.nix { inherit pkgs; } {
name = "conda-artiq";
src = fakeCondaSource;
};
in
conda-artiq

View File

@ -0,0 +1,20 @@
# We need to pass the whole source to conda for the git variables to work.
# recipe must be a string pointing to a path within the source.
{ pkgs }:
{ name, src, recipe ? "fake-conda"}:
let
condaBuilderEnv = import ./conda-builder-env.nix { inherit pkgs; };
in pkgs.stdenv.mkDerivation {
inherit name src;
buildCommand =
''
HOME=`pwd`
mkdir $out
${condaBuilderEnv}/bin/conda-builder-env -c "PYTHON=python conda build --no-anaconda-upload --no-test --output-folder $out $src/${recipe}"
mkdir -p $out/nix-support
echo file conda $out/noarch/*.tar.bz2 >> $out/nix-support/hydra-build-products
'';
}

View File

@ -0,0 +1,29 @@
{ pkgs }:
with pkgs;
let
condaDeps = [ stdenv.cc xorg.libSM xorg.libICE xorg.libXrender libselinux ];
# Use the full Anaconda distribution, which already contains conda-build and its many dependencies,
# so we don't have to manually deal with them.
condaInstaller = fetchurl {
url = "https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh";
sha256 = "0fmpdd5876ylds98mydmv5klnwlzasa461k0l1f4vhbw96vm3j25";
};
condaSrcChmod = runCommand "conda-src-chmod" { } "mkdir $out; cp ${condaInstaller} $out/conda-installer.sh; chmod +x $out/conda-installer.sh";
condaInstallerEnv = buildFHSUserEnv {
name = "conda-installer-env";
targetPkgs = pkgs: ([ condaSrcChmod ] ++ condaDeps);
};
condaInstalled = runCommand "conda-installed" { }
''
${condaInstallerEnv}/bin/conda-installer-env -c "${condaSrcChmod}/conda-installer.sh -p $out -b"
substituteInPlace $out/lib/python3.7/site-packages/conda/gateways/disk/__init__.py \
--replace "os.chmod(path, 0o2775)" "pass"
'';
in
buildFHSUserEnv {
name = "conda-builder-env";
targetPkgs = pkgs: [ condaInstalled ] ++ condaDeps;
}

View File

@ -0,0 +1,53 @@
{ pkgs }:
{ name, version, src, dependencies ? []}:
pkgs.runCommand "conda-fake-source-${name}" { }
''
mkdir -p $out/fake-conda;
# work around yet more idiotic conda behavior - build breaks if write permissions aren't set on source files.
cp --no-preserve=mode,ownership -R ${src} workaround-conda
pushd workaround-conda
tar cf $out/src.tar .
popd
rm -rf workaround-conda
cat << EOF > $out/fake-conda/meta.yaml
package:
name: ${name}
version: ${version}
source:
url: ../src.tar
{% set data = load_setup_py_data() %}
build:
noarch: python
entry_points:
# NOTE: conda-build cannot distinguish between console and gui scripts
{% for entry_point_type, entry_points in data.get("entry_points", dict()).items() -%}
{% for entry_point in entry_points -%}
- {{ entry_point }}
{% endfor %}
{% endfor %}
ignore_prefix_files: True
requirements:
run:
${pkgs.lib.concatStringsSep "\n" (map (s: " - ${s}") dependencies)}
EOF
cat << EOF > $out/fake-conda/build.sh
#!/bin/bash
set -e
export VERSIONEER_OVERRIDE=${version}
python setup.py install \
--prefix=\$PREFIX \
--single-version-externally-managed \
--record=record.txt \
--no-compile
EOF
chmod 755 $out/fake-conda/build.sh
''

38
artiq-fast/default.nix Normal file
View File

@ -0,0 +1,38 @@
{ pkgs ? import <nixpkgs> {}}:
with pkgs;
let
pythonDeps = import ./pkgs/python-deps.nix { inherit (pkgs) stdenv fetchFromGitHub python3Packages; };
boards = [
{ target = "kasli"; variant = "tester"; }
{ target = "kc705"; variant = "nist_clock"; }
];
boardPackages = pkgs.lib.lists.foldr (board: start:
let
boardBinaries = import ./artiq-board.nix { inherit pkgs; } {
target = board.target;
variant = board.variant;
};
in
start // {
"artiq-board-${board.target}-${board.variant}" = boardBinaries;
}) {} boards;
mainPackages = rec {
inherit (pythonDeps) asyncserial levenshtein pythonparser quamash pyqtgraph-qt5 misoc migen microscope jesd204b migen-axi lit outputcheck;
binutils-or1k = callPackage ./pkgs/binutils.nix { platform = "or1k"; target = "or1k-linux"; };
binutils-arm = callPackage ./pkgs/binutils.nix { platform = "arm"; target = "armv7-unknown-linux-gnueabihf"; };
llvm-or1k = callPackage ./pkgs/llvm-or1k.nix {};
rustc = callPackage ./pkgs/rust
((stdenv.lib.optionalAttrs (stdenv.cc.isGNU && stdenv.hostPlatform.isi686) {
stdenv = overrideCC stdenv gcc6; # with gcc-7: undefined reference to `__divmoddi4'
}) //
{ inherit llvm-or1k; });
llvmlite-artiq = callPackage ./pkgs/llvmlite-artiq.nix { inherit llvm-or1k; };
libartiq-support = callPackage ./pkgs/libartiq-support.nix { inherit rustc; };
artiq = callPackage ./pkgs/artiq.nix { inherit binutils-or1k llvm-or1k llvmlite-artiq libartiq-support lit outputcheck; };
artiq-env = (pkgs.python3.withPackages(ps: [ artiq ])).overrideAttrs (oldAttrs: { name = "${pkgs.python3.name}-artiq-env-${artiq.version}"; });
openocd = callPackage ./pkgs/openocd.nix {};
conda-artiq = import ./conda-artiq.nix { inherit pkgs; };
};
in
mainPackages // boardPackages

35
artiq-fast/fetchcargo.nix Normal file
View File

@ -0,0 +1,35 @@
{ stdenv, cacert, git, cargo, cargo-vendor }:
{ name, src, sha256 }:
stdenv.mkDerivation {
name = "${name}-vendor";
nativeBuildInputs = [ cacert git cargo cargo-vendor ];
inherit src;
phases = "unpackPhase patchPhase installPhase";
installPhase = ''
if [[ ! -f Cargo.lock ]]; then
echo
echo "ERROR: The Cargo.lock file doesn't exist"
echo
echo "Cargo.lock is needed to make sure that cargoSha256 doesn't change"
echo "when the registry is updated."
echo
exit 1
fi
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
cargo vendor
cp -ar vendor $out
'';
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = sha256;
impureEnvVars = stdenv.lib.fetchers.proxyImpureEnvVars;
preferLocalBuild = true;
}

View File

@ -0,0 +1 @@
{ fetchgit }: <artiqSrc>

View File

@ -0,0 +1,14 @@
{ stdenv, git, fetchgit }:
let
artiq-timestamp = stdenv.mkDerivation {
name = "artiq-timestamp";
src = import ./artiq-src.nix { inherit fetchgit; };
buildPhase = ''
TIMESTAMP=`${git}/bin/git log -1 --format=%ct`
'';
installPhase = ''
echo -n $TIMESTAMP > $out
'';
};
in
builtins.readFile artiq-timestamp

View File

@ -0,0 +1,16 @@
{ stdenv, git, fetchgit }:
let
artiq-version = stdenv.mkDerivation {
name = "artiq-version";
src = import ./artiq-src.nix { inherit fetchgit; };
buildPhase = ''
REV=`${git}/bin/git rev-parse HEAD`
MAJOR_VERSION=`cat MAJOR_VERSION`
COMMIT_COUNT=`${git}/bin/git rev-list --count HEAD`
'';
installPhase = ''
echo -n $MAJOR_VERSION.$COMMIT_COUNT.`cut -c1-8 <<< $REV`.beta > $out
'';
};
in
builtins.readFile artiq-version

29
artiq-fast/pkgs/artiq.nix Normal file
View File

@ -0,0 +1,29 @@
{ stdenv, callPackage, fetchgit, git, python3Packages, qt5Full, binutils-or1k, llvm-or1k, llvmlite-artiq, libartiq-support, lit, outputcheck }:
let
pythonDeps = callPackage ./python-deps.nix {};
in
python3Packages.buildPythonPackage rec {
name = "artiq-${version}";
version = import ./artiq-version.nix { inherit stdenv fetchgit git; };
src = import ./artiq-src.nix { inherit fetchgit; };
preBuild = "export VERSIONEER_OVERRIDE=${version}";
propagatedBuildInputs = [ binutils-or1k llvm-or1k llvmlite-artiq qt5Full ]
++ (with pythonDeps; [ levenshtein pyqtgraph-qt5 quamash pythonparser ])
++ (with python3Packages; [ aiohttp pygit2 numpy dateutil scipy prettytable pyserial h5py pyqt5 ]);
checkInputs = [ binutils-or1k outputcheck ];
checkPhase =
''
python -m unittest discover -v artiq.test
TESTDIR=`mktemp -d`
cp --no-preserve=mode,ownership -R ${src}/artiq/test/lit $TESTDIR
LIBARTIQ_SUPPORT=${libartiq-support}/libartiq_support.so ${lit}/bin/lit -v $TESTDIR/lit
'';
meta = with stdenv.lib; {
description = "A leading-edge control system for quantum information experiments";
homepage = https://m-labs/artiq;
license = licenses.lgpl3;
maintainers = [ maintainers.sb0 ];
};
}

View File

@ -0,0 +1,35 @@
{ stdenv, buildPackages
, fetchurl, zlib
, platform, target
}:
stdenv.mkDerivation rec {
basename = "binutils";
inherit platform;
version = "2.30";
name = "${basename}-${platform}-${version}";
src = fetchurl {
url = "https://ftp.gnu.org/gnu/binutils/binutils-${version}.tar.bz2";
sha256 = "028cklfqaab24glva1ks2aqa1zxa6w6xmc8q34zs1sb7h22dxspg";
};
configureFlags =
[ "--enable-shared" "--enable-deterministic-archives" "--target=${target}"];
outputs = [ "out" "info" "man" ];
depsBuildBuild = [ buildPackages.stdenv.cc ];
buildInputs = [ zlib ];
enableParallelBuilding = true;
meta = {
description = "Tools for manipulating binaries (linker, assembler, etc.)";
longDescription = ''
The GNU Binutils are a collection of binary tools. The main
ones are `ld' (the GNU linker) and `as' (the GNU assembler).
They also include the BFD (Binary File Descriptor) library,
`gprof', `nm', `strip', etc.
'';
homepage = http://www.gnu.org/software/binutils/;
license = stdenv.lib.licenses.gpl3Plus;
/* Give binutils a lower priority than gcc-wrapper to prevent a
collision due to the ld/as wrappers/symlinks in the latter. */
priority = "10";
};
}

View File

@ -0,0 +1,13 @@
{ stdenv, fetchgit, git, rustc }:
stdenv.mkDerivation rec {
name = "libartiq-support-${version}";
version = import ./artiq-version.nix { inherit stdenv fetchgit git; };
src = import ./artiq-src.nix { inherit fetchgit; };
phases = [ "buildPhase" ];
# keep in sync with artiq/test/lit/lit.cfg or remove build from the latter once we don't use buildbot/conda anymore
buildPhase =
''
mkdir $out
${rustc}/bin/rustc ${src}/artiq/test/libartiq_support/lib.rs --out-dir $out -Cpanic=unwind -g
'';
}

View File

@ -0,0 +1,64 @@
{ stdenv
, fetchFromGitHub, runCommand
, perl, groff, cmake, libxml2, python, libffi, valgrind
}:
let
llvm-src = fetchFromGitHub {
rev = "527aa86b578da5dfb9cf4510b71f0f46a11249f7";
owner = "m-labs";
repo = "llvm-or1k";
sha256 = "0lmcg9xj66pf4mb6racipw67vm8kwm84dl861hyqnywd61kvhrwa";
};
clang-src = fetchFromGitHub {
rev = "9e996136d52ed506ed8f57ef8b13b0f0f735e6a3";
owner = "m-labs";
repo = "clang-or1k";
sha256 = "0w5f450i76y162aswi2c7jip8x3arzljaxhbqp8qfdffm0rdbjp4";
};
llvm-clang-src = runCommand "llvm-clang-src" {}
''
mkdir -p $out
mkdir -p $out/tools/clang
cp -r ${llvm-src}/* $out/
cp -r ${clang-src}/* $out/tools/clang
'';
in
stdenv.mkDerivation rec {
name = "llvm-or1k";
src = llvm-clang-src;
buildInputs = [ perl groff cmake libxml2 python libffi ] ++ stdenv.lib.optional stdenv.isLinux valgrind;
preBuild = ''
NIX_BUILD_CORES=4
makeFlagsArray=(-j''$NIX_BUILD_CORES)
mkdir -p $out/
'';
cmakeFlags = with stdenv; [
"-DCMAKE_BUILD_TYPE=Release"
"-DLLVM_BUILD_LLVM_DYLIB=ON"
"-DLLVM_LINK_LLVM_DYLIB=ON"
"-DLLVM_TARGETS_TO_BUILD=X86;ARM"
"-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=OR1K"
"-DLLVM_ENABLE_ASSERTIONS=OFF"
"-DLLVM_INSTALL_UTILS=ON"
"-DLLVM_INCLUDE_TESTS=OFF"
"-DLLVM_INCLUDE_DOCS=OFF"
"-DLLVM_INCLUDE_EXAMPLES=OFF"
"-DCLANG_ENABLE_ARCMT=OFF"
"-DCLANG_ENABLE_STATIC_ANALYZER=OFF"
"-DCLANG_INCLUDE_TESTS=OFF"
"-DCLANG_INCLUDE_DOCS=OFF"
];
enableParallelBuilding = true;
meta = {
description = "Collection of modular and reusable compiler and toolchain technologies";
homepage = http://llvm.org/;
license = stdenv.lib.licenses.bsd3;
maintainers = with stdenv.lib.maintainers; [ sb0 ];
platforms = stdenv.lib.platforms.all;
};
}

View File

@ -0,0 +1,22 @@
{ stdenv, fetchFromGitHub, llvm-or1k, makeWrapper, python3, ncurses, zlib, python3Packages }:
python3Packages.buildPythonPackage rec {
name = "llvmlite-artiq";
src = fetchFromGitHub {
rev = "158f9d3a898dbf055ca513d69505df288c681fea";
owner = "m-labs";
repo = "llvmlite";
sha256 = "1anniwya5jhhr2sxfdnwrsjy17yrk3x61i9hsm1rljsb8zvh68d5";
};
buildInputs = [ makeWrapper python3 ncurses zlib llvm-or1k python3Packages.setuptools ];
preBuild = "export LLVM_CONFIG=${llvm-or1k}/bin/llvm-config";
meta = with stdenv.lib; {
description = "A lightweight LLVM python binding for writing JIT compilers";
homepage = "http://llvmlite.pydata.org/";
maintainers = with maintainers; [ sb0 ];
license = licenses.bsd2;
platforms = platforms.unix;
};
}

View File

@ -0,0 +1,73 @@
{ stdenv, fetchFromGitHub, autoreconfHook, libftdi, libusb1, pkgconfig, hidapi }:
stdenv.mkDerivation rec {
name = "openocd-mlabs-${version}";
version = "0.10.0";
src = fetchFromGitHub {
owner = "m-labs";
repo = "openocd";
fetchSubmodules = true;
rev = "c383a57adcff332b2c5cf8d55a84626285b42c2c";
sha256 = "0xlj9cs72acx3zqagvr7f1c0v6lnqhl8fgrlhgmhmvk5n9knk492";
};
bscan_spi_bitstreams = fetchFromGitHub {
owner = "quartiq";
repo = "bscan_spi_bitstreams";
rev = "01d8f819f15baf9a8cc5d96945a51e4d267ff564";
sha256 = "1zqv47kzgvbn4c8cr019a6wcja7gn5h1z4kvw5bhpc72fyhagal9";
};
nativeBuildInputs = [ pkgconfig ];
buildInputs = [ autoreconfHook libftdi libusb1 hidapi ];
configureFlags = [
"--enable-jtag_vpi"
"--enable-usb_blaster_libftdi"
"--enable-amtjtagaccel"
"--enable-gw16012"
"--enable-presto_libftdi"
"--enable-openjtag_ftdi"
"--enable-oocd_trace"
"--enable-buspirate"
"--enable-sysfsgpio"
"--enable-remote-bitbang"
];
NIX_CFLAGS_COMPILE = [
"-Wno-implicit-fallthrough"
"-Wno-format-truncation"
"-Wno-format-overflow"
"-Wno-error=tautological-compare"
];
postInstall = ''
mkdir -p "$out/etc/udev/rules.d"
rules="$out/share/openocd/contrib/60-openocd.rules"
if [ ! -f "$rules" ]; then
echo "$rules is missing, must update the Nix file."
exit 1
fi
ln -s "$rules" "$out/etc/udev/rules.d/"
mkdir -p "$out/share/bscan-spi-bitstreams"
cp ${bscan_spi_bitstreams}/*.bit "$out/share/bscan-spi-bitstreams"
'';
meta = with stdenv.lib; {
description = "Free and Open On-Chip Debugging, In-System Programming and Boundary-Scan Testing";
longDescription = ''
OpenOCD provides on-chip programming and debugging support with a layered
architecture of JTAG interface and TAP support, debug target support
(e.g. ARM, MIPS), and flash chip drivers (e.g. CFI, NAND, etc.). Several
network interfaces are available for interactiving with OpenOCD: HTTP,
telnet, TCL, and GDB. The GDB server enables OpenOCD to function as a
"remote target" for source-level debugging of embedded systems using the
GNU GDB program.
'';
homepage = http://openocd.sourceforge.net/;
license = licenses.gpl2Plus;
maintainers = with maintainers; [ sb0 ];
platforms = platforms.linux;
};
}

View File

@ -0,0 +1,282 @@
{ stdenv, fetchFromGitHub, python3Packages }:
rec {
# User dependencies
asyncserial = python3Packages.buildPythonPackage rec {
name = "asyncserial";
src = fetchFromGitHub {
owner = "m-labs";
repo = "asyncserial";
rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d";
sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k";
};
propagatedBuildInputs = with python3Packages; [ pyserial ];
doCheck = false;
};
levenshtein = python3Packages.buildPythonPackage rec {
name = "levenshtein";
src = fetchFromGitHub {
owner = "ztane";
repo = "python-Levenshtein";
rev = "854e61a05bb8b750e990add96df412cd5448b75e";
sha256 = "1yf21kg1g2ivm5a4dx1jra9k0c33np54d0hk5ymnfyc4f6pg386q";
};
doCheck = false;
};
pythonparser = python3Packages.buildPythonPackage rec {
name = "pythonparser";
src = fetchFromGitHub {
owner = "m-labs";
repo = "pythonparser";
rev = "5b391fe86f43bb9f4f96c5bc0532e2a112db2936";
sha256 = "1gw1fk4y2l6bwq0fg2a9dfc1rvq8cv492dyil96amjdhsxvnx35b";
};
patches = [ ./python37hack.patch ];
propagatedBuildInputs = with python3Packages; [ regex ];
};
quamash = python3Packages.buildPythonPackage rec {
name = "quamash";
src = fetchFromGitHub {
owner = "harvimt";
repo = "quamash";
rev = "e513b30f137415c5e098602fa383e45debab85e7";
sha256 = "117rp9r4lz0kfz4dmmpa35hp6nhbh6b4xq0jmgvqm68g9hwdxmqa";
};
propagatedBuildInputs = with python3Packages; [ pyqt5 ];
doCheck = false;
};
pyqtgraph-qt5 = python3Packages.buildPythonPackage rec {
name = "pyqtgraph_qt5-${version}";
version = "0.10.0";
doCheck = false;
src = fetchFromGitHub {
owner = "pyqtgraph";
repo = "pyqtgraph";
rev = "1426e334e1d20542400d77c72c132b04c6d17ddb";
sha256 = "1079haxyr316jf0wpirxdj0ry6j8mr16cqr0dyyrd5cnxwl7zssh";
};
propagatedBuildInputs = with python3Packages; [ scipy numpy pyqt5 pyopengl ];
};
# TODO: use python3Packages.pyftdi starting with NixOS 19.09 or later
# Upstream PR: https://github.com/NixOS/nixpkgs/pull/61256
pyftdi = python3Packages.buildPythonPackage rec {
name = "pyftdi";
src = fetchFromGitHub {
owner = "eblot";
repo = "pyftdi";
rev = "8e6f0bab6cff3eb60d2dbe578d0c5a2d1a9e135c";
sha256 = "0mw79fjnvswa0j3bzr0y906rz1vjbr8lwy0albgvsfr0ngwbajqy";
};
propagatedBuildInputs = with python3Packages; [ pyusb pyserial ];
};
# Development/firmware dependencies
misoc = python3Packages.buildPythonPackage rec {
name = "misoc";
src = fetchFromGitHub {
owner = "m-labs";
repo = "misoc";
rev = "e7f76c3ca302d9b1040bb818d7cd07a5c031c63b";
sha256 = "1cdqjgbhgrnds8m0mrgd9phb8gqmhlv8v3ivrz1mvs7cb1bwl0pf";
fetchSubmodules = true;
};
# TODO: fix misoc bitrot and re-enable tests
doCheck = false;
propagatedBuildInputs = with python3Packages; [ pyserial jinja2 numpy asyncserial migen ];
meta = with stdenv.lib; {
description = "A high performance and small footprint system-on-chip based on Migen";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
migen = python3Packages.buildPythonPackage rec {
name = "migen";
src = fetchFromGitHub {
owner = "m-labs";
repo = "migen";
rev = "41922fde2a8c36cd0f99d4b7ebb3ba9c37ce1489";
sha256 = "0srn7lr98sqjss3z2zsk9w7ydl1p6rwskr0r7alss1x720n8hhiw";
};
propagatedBuildInputs = with python3Packages; [ colorama sphinx sphinx_rtd_theme ];
meta = with stdenv.lib; {
description = "A Python toolbox for building complex digital hardware";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
microscope = python3Packages.buildPythonPackage rec {
name = "microscope";
src = fetchFromGitHub {
owner = "m-labs";
repo = "microscope";
rev = "bcbc5346c71ad8f7a1a0b7771a9d126b18fdf558";
sha256 = "1hslm2nn2z1bl84ya4fsab3pvcdmbziwn7zkai0cm3bv525fjxxd";
};
propagatedBuildInputs = with python3Packages; [ pyserial prettytable msgpack migen ];
meta = with stdenv.lib; {
description = "Finding the bacteria in rotting FPGA designs";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
jesd204b = python3Packages.buildPythonPackage rec {
name = "jesd204b";
src = fetchFromGitHub {
owner = "m-labs";
repo = "jesd204b";
rev = "2fd6391c0a9197580d60f7d8a146191dc7337b03";
sha256 = "1lhw8f0dp42xx4g6d7hyhqhrnd6i5ll4a1wcg265rqz3600i4009";
};
propagatedBuildInputs = with python3Packages; [ migen misoc ];
meta = with stdenv.lib; {
description = "JESD204B core for Migen/MiSoC";
homepage = "https://m-labs.hk/migen";
license = licenses.bsd2;
platforms = platforms.unix;
};
};
fastnumbers = python3Packages.buildPythonPackage rec {
pname = "fastnumbers";
version = "2.2.1";
src = python3Packages.fetchPypi {
inherit pname version;
sha256 = "0j15i54p7nri6hkzn1wal9pxri4pgql01wgjccig6ar0v5jjbvsy";
};
meta = with stdenv.lib; {
description = "Super-fast and clean conversions to numbers";
homepage = "https://github.com/SethMMorton/fastnumbers";
license = licenses.mit;
platforms = platforms.unix;
};
};
ramda = python3Packages.buildPythonPackage {
name = "ramda";
src = fetchFromGitHub {
owner = "peteut";
repo = "ramda.py";
rev = "bd58f8e69d0e9a713d9c1f286a1ac5e5603956b1";
sha256 = "0qzd5yp9lbaham8p1wiymdjapzbqsli7lvngv24c3z4ybd9jlq9g";
};
nativeBuildInputs = [ python3Packages.pbr ];
propagatedBuildInputs = [ fastnumbers ];
checkInputs = [ python3Packages.pytest python3Packages.pytest-flake8 ];
checkPhase = "pytest";
preBuild = ''
export PBR_VERSION=0.0.1
'';
meta = with stdenv.lib; {
description = "Ramda, ported to Python";
homepage = "https://github.com/peteut/ramda.py";
license = licenses.mit;
platforms = platforms.unix;
};
};
migen-axi = python3Packages.buildPythonPackage {
name = "migen-axi";
src = fetchFromGitHub {
owner = "peteut";
repo = "migen-axi";
rev = "8526eca769c01e18cc0a6024aacc515ceb8b9bd5";
sha256 = "19gycn7s32j7zzy064qj2yv9g9jk9kn9z3q0fap2dg308g6d1pjs";
};
postPatch = ''
substituteInPlace src/migen_axi/integration/soc_core.py \
--replace "identifier_mem" "identifier"
substituteInPlace tests/test_integration.py \
--replace "zedboard.Platform(name=\"soc\", toolchain=\"vivado\")" "zedboard.Platform()"
'';
nativeBuildInputs = [ python3Packages.pbr ];
propagatedBuildInputs = [ python3Packages.click python3Packages.numpy python3Packages.toolz ramda migen misoc ];
checkInputs = [ python3Packages.pytest python3Packages.pytest-flake8 ];
checkPhase = "pytest";
preBuild = ''
export PBR_VERSION=0.0.1
'';
meta = with stdenv.lib; {
description = "AXI support for Migen/MiSoC";
homepage = "https://github.com/peteut/migen-axi";
license = licenses.mit;
platforms = platforms.unix;
};
};
# not using the nixpkgs version because it is Python 2 and an "application"
lit = python3Packages.buildPythonPackage rec {
pname = "lit";
version = "0.7.1";
src = python3Packages.fetchPypi {
inherit pname version;
sha256 = "ecef2833aef7f411cb923dac109c7c9dcc7dbe7cafce0650c1e8d19c243d955f";
};
# Non-standard test suite. Needs custom checkPhase.
doCheck = false;
meta = with stdenv.lib; {
description = "Portable tool for executing LLVM and Clang style test suites";
homepage = http://llvm.org/docs/CommandGuide/lit.html;
license = licenses.ncsa;
};
};
outputcheck = python3Packages.buildPythonApplication rec {
pname = "outputcheck";
version = "0.4.2";
src = fetchFromGitHub {
owner = "stp";
repo = "OutputCheck";
rev = "e0f533d3c5af2949349856c711bf4bca50022b48";
sha256 = "1y27vz6jq6sywas07kz3v01sqjd0sga9yv9w2cksqac3v7wmf2a0";
};
prePatch = "echo ${version} > RELEASE-VERSION";
meta = with stdenv.lib; {
description = "A tool for checking tool output inspired by LLVM's FileCheck";
homepage = "https://github.com/stp/OutputCheck";
license = licenses.bsd3;
};
};
}

View File

@ -0,0 +1,33 @@
diff --git a/pythonparser/lexer.py b/pythonparser/lexer.py
index a62eaf1..2c48d36 100644
--- a/pythonparser/lexer.py
+++ b/pythonparser/lexer.py
@@ -79,6 +79,7 @@ class Lexer:
(3, 4): _reserved_3_1,
(3, 5): _reserved_3_5,
(3, 6): _reserved_3_5,
+ (3, 7): _reserved_3_5,
}
"""
A map from a tuple (*major*, *minor*) corresponding to Python version to
@@ -102,6 +103,7 @@ class Lexer:
(3, 4): _string_prefixes_3_3,
(3, 5): _string_prefixes_3_3,
(3, 6): _string_prefixes_3_6,
+ (3, 7): _string_prefixes_3_6,
}
"""
A map from a tuple (*major*, *minor*) corresponding to Python version to
diff --git a/pythonparser/parser.py b/pythonparser/parser.py
index 10c741d..f748695 100644
--- a/pythonparser/parser.py
+++ b/pythonparser/parser.py
@@ -419,7 +419,7 @@ class Parser(object):
self.expr_stmt_1 = self.expr_stmt_1__26
self.yield_expr = self.yield_expr__26
return
- elif version in ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6)):
+ elif version in ((3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7)):
if version == (3, 0):
self.with_stmt = self.with_stmt__26 # lol
else:

View File

@ -0,0 +1,117 @@
{ stdenv, makeWrapper, bash, buildRustPackage, curl, darwin
, version
, src
, platform
, versionType
}:
let
inherit (stdenv.lib) optionalString;
inherit (darwin.apple_sdk.frameworks) Security;
bootstrapping = versionType == "bootstrap";
installComponents
= "rustc,rust-std-${platform}"
+ (optionalString bootstrapping ",cargo")
;
in
rec {
inherit buildRustPackage;
rustc = stdenv.mkDerivation rec {
name = "rustc-${versionType}-${version}";
inherit version;
inherit src;
meta = with stdenv.lib; {
homepage = http://www.rust-lang.org/;
description = "A safe, concurrent, practical language";
maintainers = with maintainers; [ sb0 ];
license = [ licenses.mit licenses.asl20 ];
};
buildInputs = [ bash ] ++ stdenv.lib.optional stdenv.isDarwin Security;
postPatch = ''
patchShebangs .
'';
installPhase = ''
./install.sh --prefix=$out \
--components=${installComponents}
${optionalString (stdenv.isLinux && bootstrapping) ''
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/rustc"
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/rustdoc"
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/cargo"
''}
${optionalString (stdenv.isDarwin && bootstrapping) ''
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/rustc"
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/rustdoc"
install_name_tool -change /usr/lib/libiconv.2.dylib '${darwin.libiconv}/lib/libiconv.2.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libcurl.4.dylib '${stdenv.lib.getLib curl}/lib/libcurl.4.dylib' "$out/bin/cargo"
for f in $out/lib/lib*.dylib; do
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$f"
done
''}
# Do NOT, I repeat, DO NOT use `wrapProgram` on $out/bin/rustc
# (or similar) here. It causes strange effects where rustc loads
# the wrong libraries in a bootstrap-build causing failures that
# are very hard to track down. For details, see
# https://github.com/rust-lang/rust/issues/34722#issuecomment-232164943
'';
};
cargo = stdenv.mkDerivation rec {
name = "cargo-${versionType}-${version}";
inherit version;
inherit src;
meta = with stdenv.lib; {
homepage = http://www.rust-lang.org/;
description = "A safe, concurrent, practical language";
maintainers = with maintainers; [ sb0 ];
license = [ licenses.mit licenses.asl20 ];
};
buildInputs = [ makeWrapper bash ] ++ stdenv.lib.optional stdenv.isDarwin Security;
postPatch = ''
patchShebangs .
'';
installPhase = ''
patchShebangs ./install.sh
./install.sh --prefix=$out \
--components=cargo
${optionalString (stdenv.isLinux && bootstrapping) ''
patchelf \
--set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
"$out/bin/cargo"
''}
${optionalString (stdenv.isDarwin && bootstrapping) ''
install_name_tool -change /usr/lib/libiconv.2.dylib '${darwin.libiconv}/lib/libiconv.2.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libresolv.9.dylib '${darwin.libresolv}/lib/libresolv.9.dylib' "$out/bin/cargo"
install_name_tool -change /usr/lib/libcurl.4.dylib '${stdenv.lib.getLib curl}/lib/libcurl.4.dylib' "$out/bin/cargo"
''}
wrapProgram "$out/bin/cargo" \
--suffix PATH : "${rustc}/bin"
'';
};
}

View File

@ -0,0 +1,42 @@
{ stdenv, fetchurl, callPackage }:
let
# Note: the version MUST be one version prior to the version we're
# building
version = "1.28.0";
# fetch hashes by running `print-hashes.sh 1.24.1`
hashes = {
i686-unknown-linux-gnu = "de7cdb4e665e897ea9b10bf6fd545f900683296456d6a11d8510397bb330455f";
x86_64-unknown-linux-gnu = "2a1390340db1d24a9498036884e6b2748e9b4b057fc5219694e298bdaa37b810";
armv7-unknown-linux-gnueabihf = "346558d14050853b87049e5e1fbfae0bf0360a2f7c57433c6985b1a879c349a2";
aarch64-unknown-linux-gnu = "9b6fbcee73070332c811c0ddff399fa31965bec62ef258656c0c90354f6231c1";
i686-apple-darwin = "752e2c9182e057c4a54152d1e0b3949482c225d02bb69d9d9a4127dc2a65fb68";
x86_64-apple-darwin = "5d7a70ed4701fe9410041c1eea025c95cad97e5b3d8acc46426f9ac4f9f02393";
};
platform =
if stdenv.hostPlatform.system == "i686-linux"
then "i686-unknown-linux-gnu"
else if stdenv.hostPlatform.system == "x86_64-linux"
then "x86_64-unknown-linux-gnu"
else if stdenv.hostPlatform.system == "armv7l-linux"
then "armv7-unknown-linux-gnueabihf"
else if stdenv.hostPlatform.system == "aarch64-linux"
then "aarch64-unknown-linux-gnu"
else if stdenv.hostPlatform.system == "i686-darwin"
then "i686-apple-darwin"
else if stdenv.hostPlatform.system == "x86_64-darwin"
then "x86_64-apple-darwin"
else throw "missing bootstrap url for platform ${stdenv.hostPlatform.system}";
src = fetchurl {
url = "https://static.rust-lang.org/dist/rust-${version}-${platform}.tar.gz";
sha256 = hashes."${platform}";
};
in callPackage ./binaryBuild.nix
{ inherit version src platform;
buildRustPackage = null;
versionType = "bootstrap";
}

View File

@ -0,0 +1,91 @@
{ stdenv, callPackage, recurseIntoAttrs, makeRustPlatform, llvm-or1k, fetchurl
, targets ? []
, targetToolchains ? []
, targetPatches ? []
, fetchFromGitHub
, runCommand
}:
let
rustPlatform = recurseIntoAttrs (makeRustPlatform (callPackage ./bootstrap.nix {}));
version = "1.28.0";
src = fetchFromGitHub {
owner = "m-labs";
repo = "rust";
sha256 = "03lfps3xvvv7wv1nnwn3n1ji13z099vx8c3fpbzp9rnasrwzp5jy";
rev = "f305fb024318e96997fbe6e4a105b0cc1052aad4"; # artiq-1.28.0 branch
fetchSubmodules = true;
};
rustc_internal = callPackage ./rustc.nix {
inherit stdenv llvm-or1k targets targetPatches targetToolchains rustPlatform version src;
patches = [
./patches/net-tcp-disable-tests.patch
# Re-evaluate if this we need to disable this one
#./patches/stdsimd-disable-doctest.patch
# Fails on hydra - not locally; the exact reason is unknown.
# Comments in the test suggest that some non-reproducible environment
# variables such $RANDOM can make it fail.
./patches/disable-test-inherit-env.patch
];
#configureFlags = [ "--release-channel=stable" ];
# 1. Upstream is not running tests on aarch64:
# see https://github.com/rust-lang/rust/issues/49807#issuecomment-380860567
# So we do the same.
# 2. Tests run out of memory for i686
#doCheck = !stdenv.isAarch64 && !stdenv.isi686;
# Disabled for now; see https://github.com/NixOS/nixpkgs/pull/42348#issuecomment-402115598.
doCheck = false;
};
or1k-crates = stdenv.mkDerivation {
name = "or1k-crates";
inherit src;
phases = [ "unpackPhase" "buildPhase" ];
buildPhase = ''
destdir=$out
rustc="${rustc_internal}/bin/rustc --out-dir ''${destdir} -L ''${destdir} --target or1k-unknown-none -g -C target-feature=+mul,+div,+ffl1,+cmov,+addc -C opt-level=s --crate-type rlib"
mkdir -p ''${destdir}
''${rustc} --crate-name core src/libcore/lib.rs
''${rustc} --crate-name compiler_builtins src/libcompiler_builtins/src/lib.rs --cfg 'feature="compiler-builtins"' --cfg 'feature="mem"'
''${rustc} --crate-name std_unicode src/libstd_unicode/lib.rs
''${rustc} --crate-name alloc src/liballoc/lib.rs
''${rustc} --crate-name libc src/liblibc_mini/lib.rs
''${rustc} --crate-name unwind src/libunwind/lib.rs
''${rustc} -Cpanic=abort --crate-name panic_abort src/libpanic_abort/lib.rs
''${rustc} -Cpanic=unwind --crate-name panic_unwind src/libpanic_unwind/lib.rs --cfg llvm_libunwind
'';
};
arm-crates = stdenv.mkDerivation {
name = "arm-crates";
inherit src;
phases = [ "unpackPhase" "buildPhase" ];
buildPhase = ''
destdir=$out
rustc="${rustc_internal}/bin/rustc --out-dir ''${destdir} -L ''${destdir} --target armv7-unknown-linux-gnueabihf -g -C target-feature=+dsp,+fp16,+neon,+vfp3 -C opt-level=s --crate-type rlib"
mkdir -p ''${destdir}
''${rustc} --crate-name core src/libcore/lib.rs
''${rustc} --crate-name compiler_builtins src/libcompiler_builtins/src/lib.rs --cfg 'feature="compiler-builtins"' --cfg 'feature="mem"'
''${rustc} --crate-name std_unicode src/libstd_unicode/lib.rs
''${rustc} --crate-name alloc src/liballoc/lib.rs
''${rustc} --crate-name libc src/liblibc_mini/lib.rs
''${rustc} --crate-name unwind src/libunwind/lib.rs
''${rustc} -Cpanic=abort --crate-name panic_abort src/libpanic_abort/lib.rs
''${rustc} -Cpanic=unwind --crate-name panic_unwind src/libpanic_unwind/lib.rs --cfg llvm_libunwind
'';
};
in
runCommand "rustc" {}
''
mkdir -p $out/lib/rustlib/or1k-unknown-none/lib/
cp -r ${or1k-crates}/* $out/lib/rustlib/or1k-unknown-none/lib/
mkdir -p $out/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/
cp -r ${arm-crates}/* $out/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/
cp -r ${rustc_internal}/* $out
''

View File

@ -0,0 +1,10 @@
--- rustc-1.26.2-src.org/src/libstd/process.rs 2018-06-01 21:40:11.000000000 +0100
+++ rustc-1.26.2-src/src/libstd/process.rs 2018-06-08 07:50:23.023828658 +0100
@@ -1745,6 +1745,7 @@
}
#[test]
+ #[ignore]
fn test_inherit_env() {
use env;

View File

@ -0,0 +1,104 @@
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 0f60b5b3e..9b08415e7 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -962,6 +962,7 @@ mod tests {
}
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn listen_localhost() {
let socket_addr = next_test_ip4();
@@ -1020,6 +1021,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn read_eof() {
each_ip(&mut |addr| {
@@ -1039,6 +1041,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn write_close() {
each_ip(&mut |addr| {
@@ -1065,6 +1068,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn multiple_connect_serial() {
each_ip(&mut |addr| {
@@ -1087,6 +1091,7 @@ mod tests {
})
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn multiple_connect_interleaved_greedy_schedule() {
const MAX: usize = 10;
@@ -1123,6 +1128,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(target_os = "macos", ignore)]
fn multiple_connect_interleaved_lazy_schedule() {
const MAX: usize = 10;
each_ip(&mut |addr| {
@@ -1401,6 +1407,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(target_os = "macos", ignore)]
fn clone_while_reading() {
each_ip(&mut |addr| {
let accept = t!(TcpListener::bind(&addr));
@@ -1421,7 +1422,10 @@ mod tests {
// FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
// no longer has rounding errors.
- #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+ #[cfg_attr(any(target_os = "bitrig",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "macos"), ignore)]
#[test]
fn timeouts() {
let addr = next_test_ip4();
@@ -1596,6 +1603,7 @@ mod tests {
drop(listener);
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn nodelay() {
let addr = next_test_ip4();
@@ -1610,6 +1618,7 @@ mod tests {
assert_eq!(false, t!(stream.nodelay()));
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn ttl() {
let ttl = 100;
@@ -1647,6 +1656,7 @@ mod tests {
}
}
+ #[cfg_attr(target_os = "macos", ignore)]
#[test]
fn peek() {
each_ip(&mut |addr| {
@@ -1679,6 +1689,7 @@ mod tests {
}
#[test]
+ #[cfg_attr(any(target_os = "linux", target_os = "macos"), ignore)]
fn connect_timeout_unroutable() {
// this IP is unroutable, so connections should always time out,
// provided the network is reachable to begin with.

View File

@ -0,0 +1,20 @@
diff --git a/src/stdsimd/coresimd/x86/mod.rs b/src/stdsimd/coresimd/x86/mod.rs
index 32915c332..7cb54f31e 100644
--- a/src/stdsimd/coresimd/x86/mod.rs
+++ b/src/stdsimd/coresimd/x86/mod.rs
@@ -279,7 +279,6 @@ types! {
///
/// # Examples
///
- /// ```
/// # #![feature(cfg_target_feature, target_feature, stdsimd)]
/// # #![cfg_attr(not(dox), no_std)]
/// # #[cfg(not(dox))]
@@ -301,7 +300,6 @@ types! {
/// # }
/// # if is_x86_feature_detected!("sse") { unsafe { foo() } }
/// # }
- /// ```
pub struct __m256(f32, f32, f32, f32, f32, f32, f32, f32);
/// 256-bit wide set of four `f64` types, x86-specific

View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
# All rust-related downloads can be found at
# https://static.rust-lang.org/dist/index.html. To find the date on
# which a particular thing was last updated, look for the *-date.txt
# file, e.g.
# https://static.rust-lang.org/dist/channel-rust-beta-date.txt
PLATFORMS=(
i686-unknown-linux-gnu
x86_64-unknown-linux-gnu
armv7-unknown-linux-gnueabihf
aarch64-unknown-linux-gnu
i686-apple-darwin
x86_64-apple-darwin
)
BASEURL=https://static.rust-lang.org/dist
VERSION=${1:-}
DATE=${2:-}
if [[ -z $VERSION ]]
then
echo "No version supplied"
exit -1
fi
if [[ -n $DATE ]]
then
BASEURL=$BASEURL/$DATE
fi
for PLATFORM in "${PLATFORMS[@]}"
do
URL="$BASEURL/rust-$VERSION-$PLATFORM.tar.gz.sha256"
SHA256=$(curl -sSfL $URL | cut -d ' ' -f 1)
echo "$PLATFORM = \"$SHA256\";"
done

View File

@ -0,0 +1,182 @@
{ stdenv, targetPackages
, fetchurl, file, python2, tzdata, ps
, llvm-or1k, ncurses, zlib, darwin, rustPlatform, git, cmake, curl
, which, libffi, gdb
, version
, src
, configureFlags ? []
, patches
, targets
, targetPatches
, targetToolchains
, doCheck ? true
, broken ? false
}:
let
inherit (stdenv.lib) optional optionalString;
inherit (darwin.apple_sdk.frameworks) Security;
target = builtins.replaceStrings [" "] [","] (builtins.toString targets);
src_rustc = fetchurl {
url = "https://static.rust-lang.org/dist/rustc-1.28.0-src.tar.gz";
sha256 = "11k4rn77bca2rikykkk9fmprrgjswd4x4kaq7fia08vgkir82nhx";
};
in
stdenv.mkDerivation {
name = "rustc-${version}";
inherit version;
inherit src;
__darwinAllowLocalNetworking = true;
# rustc complains about modified source files otherwise
dontUpdateAutotoolsGnuConfigScripts = true;
# Running the default `strip -S` command on Darwin corrupts the
# .rlib files in "lib/".
#
# See https://github.com/NixOS/nixpkgs/pull/34227
stripDebugList = if stdenv.isDarwin then [ "bin" ] else null;
NIX_LDFLAGS = optionalString stdenv.isDarwin "-rpath ${llvm-or1k}/lib";
# Enable nightly features in stable compiles (used for
# bootstrapping, see https://github.com/rust-lang/rust/pull/37265).
# This loosens the hard restrictions on bootstrapping-compiler
# versions.
RUSTC_BOOTSTRAP = "1";
# Increase codegen units to introduce parallelism within the compiler.
RUSTFLAGS = "-Ccodegen-units=10";
# We need rust to build rust. If we don't provide it, configure will try to download it.
# Reference: https://github.com/rust-lang/rust/blob/master/src/bootstrap/configure.py
configureFlags = configureFlags
++ [ "--enable-local-rust" "--local-rust-root=${rustPlatform.rust.rustc}" "--enable-rpath" ]
++ [ "--enable-vendor" ]
++ [ "--default-linker=${targetPackages.stdenv.cc}/bin/cc" ]
++ [ "--enable-llvm-link-shared" ]
++ optional (targets != []) "--target=${target}"
++ [ "--llvm-root=${llvm-or1k}" ] ;
# The bootstrap.py will generated a Makefile that then executes the build.
# The BOOTSTRAP_ARGS used by this Makefile must include all flags to pass
# to the bootstrap builder.
postConfigure = ''
substituteInPlace Makefile --replace 'BOOTSTRAP_ARGS :=' 'BOOTSTRAP_ARGS := --jobs $(NIX_BUILD_CORES)'
'';
# FIXME: qknight, readd deleted vendor folder from 1.28 rustc
preConfigure = ''
export HOME=$out
# HACK: we add the vendor folder from rustc 1.28 to make the compiling work
tar xf ${src_rustc}
mv rustc-1.28.0-src/src/vendor/ src/vendor
'';
patches = patches ++ targetPatches;
# the rust build system complains that nix alters the checksums
dontFixLibtool = true;
passthru.target = target;
postPatch = ''
patchShebangs src/etc
# Fix the configure script to not require curl as we won't use it
sed -i configure \
-e '/probe_need CFG_CURL curl/d'
# Disable fragile tests.
rm -vr src/test/run-make/linker-output-non-utf8 || true
rm -vr src/test/run-make/issue-26092 || true
# Remove test targeted at LLVM 3.9 - https://github.com/rust-lang/rust/issues/36835
rm -vr src/test/run-pass/issue-36023.rs || true
# Disable test getting stuck on hydra - possible fix:
# https://reviews.llvm.org/rL281650
rm -vr src/test/run-pass/issue-36474.rs || true
# On Hydra: `TcpListener::bind(&addr)`: Address already in use (os error 98)'
sed '/^ *fn fast_rebind()/i#[ignore]' -i src/libstd/net/tcp.rs
# https://github.com/rust-lang/rust/issues/39522
echo removing gdb-version-sensitive tests...
find src/test/debuginfo -type f -execdir grep -q ignore-gdb-version '{}' \; -print -delete
rm src/test/debuginfo/{borrowed-c-style-enum.rs,c-style-enum-in-composite.rs,gdb-pretty-struct-and-enums-pre-gdb-7-7.rs,generic-enum-with-different-disr-sizes.rs}
# Useful debugging parameter
# export VERBOSE=1
'' + optionalString stdenv.isDarwin ''
# Disable all lldb tests.
# error: Can't run LLDB test because LLDB's python path is not set
rm -vr src/test/debuginfo/*
rm -v src/test/run-pass/backtrace-debuginfo.rs
# error: No such file or directory
rm -v src/test/run-pass/issue-45731.rs
# Disable tests that fail when sandboxing is enabled.
substituteInPlace src/libstd/sys/unix/ext/net.rs \
--replace '#[test]' '#[test] #[ignore]'
substituteInPlace src/test/run-pass/env-home-dir.rs \
--replace 'home_dir().is_some()' true
rm -v src/test/run-pass/fds-are-cloexec.rs # FIXME: pipes?
rm -v src/test/run-pass/sync-send-in-std.rs # FIXME: ???
'';
# rustc unfortunately need cmake for compiling llvm-rt but doesn't
# use it for the normal build. This disables cmake in Nix.
dontUseCmakeConfigure = true;
# ps is needed for one of the test cases
nativeBuildInputs =
[ file python2 ps rustPlatform.rust.rustc git cmake
which libffi
]
# Only needed for the debuginfo tests
++ optional (!stdenv.isDarwin) gdb;
buildInputs = [ ncurses zlib llvm-or1k ] ++ targetToolchains
++ optional stdenv.isDarwin Security;
outputs = [ "out" "man" "doc" ];
setOutputFlags = false;
# Disable codegen units and hardening for the tests.
preCheck = ''
export RUSTFLAGS=
export TZDIR=${tzdata}/share/zoneinfo
export hardeningDisable=all
'' +
# Ensure TMPDIR is set, and disable a test that removing the HOME
# variable from the environment falls back to another home
# directory.
optionalString stdenv.isDarwin ''
export TMPDIR=/tmp
sed -i '28s/home_dir().is_some()/true/' ./src/test/run-pass/env-home-dir.rs
'';
inherit doCheck;
configurePlatforms = [];
# https://github.com/NixOS/nixpkgs/pull/21742#issuecomment-272305764
# https://github.com/rust-lang/rust/issues/30181
# enableParallelBuilding = false;
meta = with stdenv.lib; {
homepage = https://www.rust-lang.org/;
description = "A safe, concurrent, practical language";
maintainers = with maintainers; [ sb0 ];
license = [ licenses.mit licenses.asl20 ];
platforms = platforms.linux ++ platforms.darwin;
broken = broken;
};
}

20
artiq-fast/shell-dev.nix Normal file
View File

@ -0,0 +1,20 @@
{ pkgs ? import <nixpkgs> {}}:
let
artiqpkgs = import ./default.nix { inherit pkgs; };
vivado = import ./vivado.nix { inherit pkgs; };
in
pkgs.mkShell {
buildInputs = [
vivado
pkgs.gnumake
(pkgs.python3.withPackages(ps: (with ps; [ jinja2 numpy paramiko ]) ++ (with artiqpkgs; [ migen microscope misoc jesd204b migen-axi artiq ])))
pkgs.cargo
artiqpkgs.rustc
artiqpkgs.binutils-or1k
artiqpkgs.binutils-arm
artiqpkgs.llvm-or1k
artiqpkgs.openocd
];
TARGET_AR="or1k-linux-ar";
}

8
artiq-fast/shell.nix Normal file
View File

@ -0,0 +1,8 @@
{ pkgs ? import <nixpkgs> {}}:
let
artiqpkgs = import ./default.nix { inherit pkgs; };
in
pkgs.mkShell {
buildInputs = [ (pkgs.python3.withPackages(ps: [artiqpkgs.artiq])) ];
}

24
artiq-fast/vivado.nix Normal file
View File

@ -0,0 +1,24 @@
# Install Vivado in /opt and add to /etc/nixos/configuration.nix:
# nix.sandboxPaths = ["/opt"];
{ pkgs, vivadoPath ? "/opt/Xilinx/Vivado/2019.1" }:
pkgs.buildFHSUserEnv {
name = "vivado";
targetPkgs = pkgs: (
with pkgs; [
ncurses5
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile = "source ${vivadoPath}/settings64.sh";
runScript = "vivado";
}

View File

@ -0,0 +1,25 @@
# Preparation steps
## Install a Windows image
```shell
nix-build install.nix -I artiqSrc=…/artiq
result/bin/windows-installer.sh
```
Follow the instructions.
## Install Anaconda to the image
```shell
result/bin/anaconda-installer.sh
```
Move the image `c.img` to one of Nix' `extra-sandbox-paths` (`nix.sandboxPaths` on NixOS).
# Running the tests manually
```shell
nix-build --pure --arg diskImage "\"…/c.img\"" -I artiqSrc=…/artiq manual-test-run.nix
```

View File

@ -0,0 +1,91 @@
{ pkgs ? import <nixpkgs> {},
diskImageSize ? "22G",
qemuMem ? "4G",
}:
with pkgs;
let
windowsIso = fetchurl {
url = "https://software-download.microsoft.com/download/sg/17763.107.101029-1455.rs5_release_svc_refresh_CLIENT_LTSC_EVAL_x64FRE_en-us.iso";
sha256 = "668fe1af70c2f7416328aee3a0bb066b12dc6bbd2576f40f812b95741e18bc3a";
};
anaconda = fetchurl {
url = "https://repo.anaconda.com/archive/Anaconda3-2019.03-Windows-x86_64.exe";
sha256 = "1f9icm5rwab6l1f23a70dw0qixzrl62wbglimip82h4zhxlh3jfj";
};
escape = builtins.replaceStrings [ "\\" ] [ "\\\\" ];
qemu = import ./qemu.nix {
inherit pkgs qemuMem;
diskImage = "c.img";
};
# Double-escape because we produce a script from a shell heredoc
ssh = cmd: qemu.ssh (escape cmd);
scp = qemu.scp;
sshCondaEnv = cmd: ssh "anaconda\\scripts\\activate && ${cmd}";
condaEnv = "artiq-env";
condaDepSpecs =
builtins.concatStringsSep " "
(map (s: "\"${s}\"")
(import ../conda-artiq-deps.nix));
instructions =
builtins.toFile "install.txt"
(builtins.readFile ./install.txt);
in
stdenv.mkDerivation {
name = "windows-installer";
src = windowsIso;
setSourceRoot = "sourceRoot=`pwd`";
unpackCmd = ''
ln -s $curSrc windows.iso
'';
propagatedBuildInputs = qemu.inputs;
dontBuild = true;
installPhase = ''
mkdir -p $out/bin $out/data
ln -s $(readlink windows.iso) $out/data/windows.iso
cat > $out/bin/windows-installer.sh << EOF
#!/usr/bin/env bash
set -e -m
${qemu.qemu-img} create -f qcow2 c.img ${diskImageSize}
${qemu.runQemu false [] [
"-boot" "order=d"
"-drive" "file=c.img,index=0,media=disk,cache=unsafe"
"-drive" "file=$out/data/windows.iso,index=1,media=cdrom,cache=unsafe"
]} &
cat ${instructions}
wait
EOF
cat > $out/bin/anaconda-installer.sh << EOF
#!/usr/bin/env bash
set -e -m
${qemu.runQemu false [] [
"-boot" "order=c"
"-drive" "file=c.img,index=0,media=disk"
]} &
sleep 10
${ssh "ver"}
${scp anaconda "Anaconda.exe"}
${ssh "start /wait \"\" Anaconda.exe /S /D=%cd%\\anaconda"}
${sshCondaEnv "conda config --add channels conda-forge"}
${sshCondaEnv "conda config --add channels m-labs"}
( ${sshCondaEnv "conda update -y conda"} ) || true
${sshCondaEnv "conda update -y --all"}
${sshCondaEnv "conda create -y -n ${condaEnv}"}
${sshCondaEnv "conda install -y -n ${condaEnv} ${condaDepSpecs}"}
${ssh "shutdown /p /f"}
echo "Waiting for qemu exit"
wait
EOF
chmod a+x $out/bin/*.sh
'';
}

View File

@ -0,0 +1,13 @@
Add user account with expected password [user/user].
Enable the OpenSSH server:
- "Add or remove programs"
- "Manage optional features"
- "Add a feature"
- "OpenSSH Server"
- "Install"
- Open "Services"
- Double-click the "OpenSSH SSH Server" service
- Set "Startup type" to "Automatic"
- "Start"
- "Ok"
Then press ENTER here to proceed with automatic installation

View File

@ -0,0 +1,27 @@
# This runs `run-test.nix` with `nix-build`
{ pkgs ? import <nixpkgs> {},
diskImage ? "/opt/windows/c.img",
qemuMem ? "2G",
testTimeout ? 180,
}:
with pkgs;
let
windowsRunner = overrides:
import ./run-test.nix ({
inherit pkgs diskImage qemuMem testTimeout;
} // overrides);
in
stdenv.mkDerivation {
name = "windows-test";
phases = [ "installPhase" "checkPhase" ];
installPhase = "touch $out";
doCheck = true;
checkPhase = ''
${windowsRunner { testCommand = "set ARTIQ_ROOT=%cd%\\anaconda\\envs\\artiq-env\\Lib\\site-packages\\artiq\\examples\\kc705_nist_clock&&python -m unittest discover -v artiq.test"; }}/bin/run.sh
'';
}

View File

@ -0,0 +1,54 @@
{ pkgs,
diskImage,
qemuMem,
sshUser ? "user",
sshPassword ? "user",
}:
with pkgs;
let
qemu-img = "${qemu_kvm}/bin/qemu-img";
runQemu = isolateNetwork: forwardedPorts: extraArgs:
let
restrict =
if isolateNetwork
then "on"
else "off";
# use socat instead of `tcp:…` to allow multiple connections
guestfwds =
builtins.concatStringsSep ""
(map ({ listenAddr, targetAddr, port }:
",guestfwd=tcp:${listenAddr}:${toString port}-cmd:${socat}/bin/socat\\ -\\ tcp:${targetAddr}:${toString port}"
) forwardedPorts);
args = [
"-enable-kvm"
"-m" qemuMem
"-bios" "${OVMF.fd}/FV/OVMF.fd"
"-netdev" "user,id=n1,net=192.168.1.0/24,restrict=${restrict},hostfwd=tcp::2022-:22${guestfwds}"
"-device" "e1000,netdev=n1"
];
argStr = builtins.concatStringsSep " " (args ++ extraArgs);
in "${qemu_kvm}/bin/qemu-system-x86_64 ${argStr}";
# Pass empty config file to prevent ssh from failing to create ~/.ssh
sshOpts = "-F /dev/null -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=\$TMP/known_hosts";
ssh = cmd: ''
echo ssh windows '${cmd}'
${sshpass}/bin/sshpass -p${sshPassword} -- \
${openssh}/bin/ssh -np 2022 ${sshOpts} \
${sshUser}@localhost \
'${cmd}'
'';
scp = src: target: ''
echo "Copy ${src} to ${target}"
${sshpass}/bin/sshpass -p${sshPassword} -- \
${openssh}/bin/scp -P 2022 ${sshOpts} \
"${src}" "${sshUser}@localhost:${target}"
'';
in
{
inherit qemu-img runQemu ssh scp;
inputs = [ qemu_kvm openssh sshpass ];
}

View File

@ -0,0 +1,80 @@
{ pkgs,
diskImage ? "/opt/windows/c.img",
qemuMem ? "2G",
testTimeout ? 600,
artiqPkg ? import ../conda-artiq.nix { inherit pkgs; },
testCommand ? "python -m unittest discover -v artiq.test",
}:
with pkgs;
let
escape = builtins.replaceStrings [ "\\" ] [ "\\\\" ];
qemu = import ./qemu.nix {
inherit pkgs qemuMem;
diskImage = "c.img";
};
# Double-escape because we produce a script from a shell heredoc
ssh = cmd: qemu.ssh (escape cmd);
scp = qemu.scp;
condaEnv = "artiq-env";
tcpPorts = [ 1380 1381 1382 1383 ];
forwardedPorts =
map (port: {
listenAddr = "192.168.1.50";
targetAddr = "192.168.1.50";
inherit port;
}) tcpPorts;
in
stdenv.mkDerivation {
name = "windows-test-runner";
src = ./.;
propagatedBuildInputs = qemu.inputs;
dontBuild = true;
installPhase = ''
mkdir -p $out/bin
cat > $out/bin/run.sh << EOF
#!/usr/bin/env bash
set -e -m
# +1 day from last modification of the disk image
CLOCK=$(date -Is -d @$(expr $(stat -c %Y ${diskImage}) + 86400))
${qemu.runQemu true forwardedPorts [
"-boot" "order=c"
"-snapshot"
"-drive" "file=${diskImage},index=0,media=disk,cache=unsafe"
"-rtc" "base=\\$CLOCK"
"-display" "none"
]} &
echo "Wait for Windows to boot"
sleep 10
${ssh "ver"}
for pkg in ${artiqPkg}/noarch/artiq*.tar.bz2 ; do
${scp "\\$pkg" "artiq.tar.bz2"}
${ssh "anaconda\\scripts\\activate ${condaEnv} && conda install artiq.tar.bz2"}
done
# Schedule a timed shutdown against hanging test runs
${ssh "shutdown -s -t ${toString testTimeout}"}
FAIL=n
( ${ssh "anaconda\\scripts\\activate ${condaEnv} && ${testCommand}"} ) || FAIL=y
# Abort timeouted shutdown
${ssh "shutdown -a"}
# Power off immediately
${ssh "shutdown -p -f"}
wait
if [ "\$FAIL" = "y" ]; then
exit 1
else
exit 0
fi
EOF
chmod a+x $out/bin/run.sh
'';
}

225
artiq-full.nix Normal file
View File

@ -0,0 +1,225 @@
{ pkgs ? import <nixpkgs> {}}:
let
sinaraSystemsSrc = <sinaraSystemsSrc>;
generatedNix = pkgs.runCommand "generated-nix" { buildInputs = [ pkgs.nix pkgs.git ]; }
''
mkdir $out
cp -a ${<artiq-fast>} $out/fast
cp ${./artiq-full/conda-artiq-board.nix} $out/conda-artiq-board.nix
cp ${./artiq-full/extras.nix} $out/extras.nix
REV=`git --git-dir ${sinaraSystemsSrc}/.git rev-parse HEAD`
SINARA_SRC_CLEAN=`mktemp -d`
cp -a ${sinaraSystemsSrc}/. $SINARA_SRC_CLEAN
chmod -R 755 $SINARA_SRC_CLEAN/.git
chmod 755 $SINARA_SRC_CLEAN
rm -rf $SINARA_SRC_CLEAN/.git
HASH=`nix-hash --type sha256 --base32 $SINARA_SRC_CLEAN`
cat > $out/default.nix << EOF
{ pkgs ? import <nixpkgs> {}}:
let
target = "kasli";
variants = [
"afmaster"
"afsatellite"
"berkeley"
"berkeley2"
"duke"
"duke2"
"duke3"
"hub"
"hustmaster"
"hustsatellite"
"indiana"
"innsbruck"
"ist"
"luh"
"mitll"
"mitll2"
"mpik"
"mpq"
"nrc"
"nudt"
"npl1"
"npl2"
"opticlock"
"oregon"
"ptb"
"ptb2"
"ptb3"
"ptb4"
"ptb5"
"ptb6"
"ptbal"
"ptbin"
"saymamaster"
"siegen"
"su"
"sysu"
"tsinghua"
"tsinghua2"
"ubirmingham"
"ucr"
"unsw"
"unsw2"
"ustc"
"vlbaimaster"
"vlbaisatellite"
"wipm"
"wipm2"
"wipm3"
"wipm4"
"wipm5master"
"wipm5satellite"
];
artiq-fast = import ./fast { inherit pkgs; };
artiq-board = import ./fast/artiq-board.nix { inherit pkgs; };
conda-artiq-board = import ./conda-artiq-board.nix { inherit pkgs; };
src = pkgs.fetchgit {
url = "https://git.m-labs.hk/M-Labs/sinara-systems.git";
rev = "$REV";
sha256 = "$HASH";
};
generic-kasli = pkgs.lib.lists.foldr (variant: start:
let
json = builtins.toPath (src + "/\''${variant}.json");
boardBinaries = artiq-board {
inherit target variant;
buildCommand = "python -m artiq.gateware.targets.kasli_generic \''${json}";
};
in
start // {
"artiq-board-\''${target}-\''${variant}" = boardBinaries;
"conda-artiq-board-\''${target}-\''${variant}" = conda-artiq-board {
boardBinaries = boardBinaries;
inherit target variant;
};
} // (pkgs.lib.optionalAttrs ((builtins.fromJSON (builtins.readFile json)).base == "standalone") {
"device-db-\''${target}-\''${variant}" = pkgs.stdenv.mkDerivation {
name = "device-db-\''${target}-\''${variant}";
buildInputs = [ artiq-fast.artiq ];
phases = [ "buildPhase" ];
buildPhase = "
mkdir \$out
artiq_ddb_template \''${json} -o \$out/device_db.py
mkdir \$out/nix-support
echo file device_db_template \$out/device_db.py >> \$out/nix-support/hydra-build-products
";
};
})) {} variants;
drtio-systems = {
af = {
master = "afmaster";
satellites = {
"1" = "afsatellite";
};
};
hust = {
master = "hustmaster";
satellites = {
"1" = "hustsatellite";
};
};
vlbai = {
master = "vlbaimaster";
satellites = {
"1" = "vlbaisatellite";
};
};
wipm5 = {
master = "wipm5master";
satellites = {
"1" = "wipm5satellite";
};
};
};
drtio-ddbs = pkgs.lib.attrsets.mapAttrs'
(system: crates: pkgs.lib.attrsets.nameValuePair ("device-db-" + system)
(pkgs.stdenv.mkDerivation {
name = "device-db-\''${system}";
buildInputs = [ artiq-fast.artiq ];
phases = [ "buildPhase" ];
buildPhase = "
mkdir \$out
artiq_ddb_template \
\''${pkgs.lib.strings.concatStringsSep " " (pkgs.lib.attrsets.mapAttrsToList (dest: desc: "-s " + dest + " " + src + "/" + desc + ".json") crates.satellites) } \
\''${src}/\''${crates.master}.json -o \$out/device_db.py
mkdir \$out/nix-support
echo file device_db_template \$out/device_db.py >> \$out/nix-support/hydra-build-products
";
})) drtio-systems;
extras = import ./extras.nix { inherit pkgs; inherit (artiq-fast) asyncserial artiq; };
in
artiq-fast // generic-kasli // drtio-ddbs // extras // rec {
artiq-board-sayma-rtm = artiq-board {
target = "sayma";
variant = "rtm";
buildCommand = "python -m artiq.gateware.targets.sayma_rtm";
};
artiq-board-sayma-satellite = artiq-board {
target = "sayma";
variant = "satellite";
buildCommand = "python -m artiq.gateware.targets.sayma_amc";
};
artiq-board-metlino-master = artiq-board {
target = "metlino";
variant = "master";
buildCommand = "python -m artiq.gateware.targets.metlino";
};
artiq-board-kc705-nist_qc2 = artiq-board {
target = "kc705";
variant = "nist_qc2";
};
conda-artiq-board-sayma-rtm = conda-artiq-board {
target = "sayma";
variant = "rtm";
boardBinaries = artiq-board-sayma-rtm;
};
conda-artiq-board-sayma-satellite = conda-artiq-board {
target = "sayma";
variant = "satellite";
boardBinaries = artiq-board-sayma-satellite;
};
conda-artiq-board-metlino-master = conda-artiq-board {
target = "metlino";
variant = "master";
boardBinaries = artiq-board-metlino-master;
};
conda-artiq-board-kc705-nist_clock = conda-artiq-board {
target = "kc705";
variant = "nist_clock";
boardBinaries = artiq-fast.artiq-board-kc705-nist_clock;
};
conda-artiq-board-kc705-nist_qc2 = conda-artiq-board {
target = "kc705";
variant = "nist_qc2";
boardBinaries = artiq-board-kc705-nist_qc2;
};
}
EOF
'';
pythonDeps = import ./artiq-full/python-deps.nix { inherit pkgs; };
manualPackages = import ./artiq-full/manual.nix {
inherit (pkgs) stdenv lib fetchgit git python3Packages texlive texinfo;
inherit (pythonDeps) sphinxcontrib-wavedrom;
};
jobs = (import generatedNix { inherit pkgs; }) // manualPackages // {
# This is in the example in the ARTIQ manual - precompile it to speed up
# installation for users.
matplotlib-qt = pkgs.lib.hydraJob (pkgs.python3Packages.matplotlib.override { enableQt = true; });
};
in
builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) jobs // {
artiq-full = pkgs.releaseTools.channel {
name = "artiq-full";
src = generatedNix;
constituents = builtins.attrValues jobs;
};
conda-channel = import ./artiq-full/conda-channel.nix { inherit pkgs; } { inherit jobs; };
}

View File

@ -0,0 +1,48 @@
{ pkgs }:
{ target, variant, boardBinaries }:
with pkgs;
let
version = import ./fast/pkgs/artiq-version.nix (with pkgs; { inherit stdenv fetchgit git; });
fakeCondaSource = runCommand "fake-condasrc-artiq-board-${target}-${variant}" { }
''
mkdir -p $out/fake-conda;
cat << EOF > $out/fake-conda/meta.yaml
package:
name: artiq-board-${target}-${variant}
version: ${version}
build:
noarch: python
ignore_prefix_files: True
outputs:
- name: artiq-board-${target}-${variant}
noarch: python
files:
- site-packages
ignore_prefix_files: True
about:
home: https://m-labs.hk/artiq
license: LGPL
summary: 'Bitstream, BIOS and firmware for the ${target}-${variant} board variant'
EOF
cat << EOF > $out/fake-conda/build.sh
#!/bin/bash
set -e
SOC_PREFIX=\$PREFIX/site-packages/artiq/board-support/${target}-${variant}
mkdir -p \$SOC_PREFIX
cp ${boardBinaries}/${pkgs.python3Packages.python.sitePackages}/artiq/board-support/${target}-${variant}/* \$SOC_PREFIX
EOF
chmod 755 $out/fake-conda/build.sh
'';
conda-artiq-board = import ./fast/conda-build.nix { inherit pkgs; } {
name = "conda-artiq-board-${target}-${variant}";
src = fakeCondaSource;
};
in
conda-artiq-board

View File

@ -0,0 +1,24 @@
{ pkgs }:
{ jobs }:
let
condaBuilderEnv = import <artiq-fast/conda-builder-env.nix> { inherit pkgs; };
in
pkgs.runCommand "conda-channel" { }
''
mkdir -p $out/noarch
for storepath in ${pkgs.lib.concatMapStringsSep " " builtins.toString (builtins.attrValues jobs)}; do
hydra_build_products=$storepath/nix-support/hydra-build-products
if [ -f $hydra_build_products ]; then
while IFS= read -r line; do
type=`echo $line | cut -f2 -d " "`
if [ $type == "conda" ]; then
path=`echo $line | cut -f3 -d " "`
ln -s $path $out/noarch
fi
done < $hydra_build_products
fi
done
cd $out
${condaBuilderEnv}/bin/conda-builder-env -c "conda index"
''

172
artiq-full/extras.nix Normal file
View File

@ -0,0 +1,172 @@
{ pkgs, asyncserial, artiq }:
let
dualPackage = (
{ name, version, src, pythonOptions ? {}, condaOptions ? {}}:
{
"${name}" = pkgs.python3Packages.buildPythonPackage ({
inherit version;
name = "${name}-${version}";
inherit src;
} // pythonOptions);
"${name}-manual-html" = pkgs.stdenv.mkDerivation {
name = "${name}-manual-html-${version}";
inherit version src;
buildInputs = (with pkgs.python3Packages; [ sphinx sphinx_rtd_theme sphinx-argparse ]) ++ [ artiq ];
preBuild = ''
export SOURCE_DATE_EPOCH=${import ./fast/pkgs/artiq-timestamp.nix { inherit (pkgs) stdenv fetchgit git; }}
cd doc
'';
makeFlags = [ "html" ];
installPhase =
let
dest = "$out/share/doc/${name}-manual";
in
''
mkdir -p ${dest}
cp -r _build/html ${dest}/
mkdir -p $out/nix-support/
echo doc manual ${dest}/html index.html >> $out/nix-support/hydra-build-products
'';
};
"conda-${name}" = import ./fast/conda-build.nix { inherit pkgs; } {
name = "conda-${name}";
src = import ./fast/conda-fake-source.nix { inherit pkgs; } ({
inherit name version src;
} // condaOptions);
};
}
);
# https://github.com/m-labs/artiq/issues/23
hidapi = pkgs.hidapi.overrideAttrs (oa: {
src = pkgs.fetchFromGitHub {
owner = "signal11";
repo = "hidapi";
rev = "a6a622ffb680c55da0de787ff93b80280498330f";
sha256 = "17n7c4v3jjrnzqwxpflggxjn6vkzscb32k4kmxqjbfvjqnx7qp7j";
};
});
in
(dualPackage {
name = "korad_ka3005p";
version = "1.0";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "korad_ka3005p";
rev = "e8c02ade175b842972f76a27919a4aaf8190de90";
sha256 = "1svgnx52amvy9xl0b2wkz0ii4ycjvjv96ac0g07zkxabdqm5ff65";
};
pythonOptions = { propagatedBuildInputs = [ asyncserial artiq ]; };
condaOptions = { dependencies = [ "asyncserial" ]; };
}) // (dualPackage {
name = "novatech409b";
version = "1.0";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "novatech409b";
rev = "442e82e2234c0bf951da2084a77861f8977755c8";
sha256 = "032qgg48dy2k31vj0q8bfni0iy2kcyscd32bq60h701wvass6jv7";
};
pythonOptions = { propagatedBuildInputs = [ asyncserial artiq ]; };
condaOptions = { dependencies = [ "asyncserial" ]; };
}) // (dualPackage {
name = "lda";
version = "1.0";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "lda";
rev = "4329da1497f496839ce20beebce0d79ed453941f";
sha256 = "00c15a03xy9vbca0j2zfy89l3ghbdmmv5wqfksm6pdwy4z036cwa";
};
pythonOptions = {
propagatedBuildInputs = [ artiq ];
postPatch = ''
substituteInPlace lda/hidapi.py \
--replace "hidapi_lib_path = None"\
"hidapi_lib_path = '${hidapi}/lib/libhidapi-libusb.so.0'"
'';
};
}) // (dualPackage {
name = "thorlabs_tcube";
version = "1.0";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "thorlabs_tcube";
rev = "b72e7ba7de8355bd93dd20d53b6f15386dff229d";
sha256 = "1lqwqflwbfdykmhf6g0pwgiq7i2vf67ybj4l8n3jn16vny21b41s";
};
pythonOptions = { propagatedBuildInputs = [ asyncserial artiq ]; };
condaOptions = { dependencies = [ "asyncserial" ]; };
}) // (dualPackage {
name = "newfocus8742";
version = "0.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "newfocus8742";
rev = "31a92595d1cb77d9256b891ec17eed0fbeceb1bc";
sha256 = "1dww0y83d4i6nma1q5hnaagih94c32bxlla5p6a5a8zkc4x2pky9";
};
pythonOptions = {
propagatedBuildInputs = [ pkgs.python3Packages.pyusb artiq ];
# no unit tests so do a simple smoke test
checkPhase = "python -m newfocus8742.aqctl_newfocus8742 --version";
};
}) // (dualPackage {
name = "hut2";
version = "0.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "hut2";
rev = "acfd62dcd60d37250e2d1b691344c6e65b6e83eb";
sha256 = "0dpx3c5aclj7gki6iaybjbx9rqrxnwccpxcvjwp594ccbcswvclr";
};
pythonOptions = {
propagatedBuildInputs = [ artiq ];
# no unit tests without hardware so do a simple smoke test
checkPhase = "python -m hut2.aqctl_hut2 --version";
};
}) // rec {
toptica-lasersdk = pkgs.python3Packages.buildPythonPackage rec {
version = "2.0.0";
name = "toptica-lasersdk-${version}";
format = "wheel";
src = pkgs.fetchurl {
url = "https://files.pythonhosted.org/packages/6b/e2/5c98407215884c2570453a78bc0d6f0bbe619f06593847ccd6a2f1d3fe59/toptica_lasersdk-2.0.0-py3-none-any.whl";
sha256 = "1k5d9ah8qzp75hh63nh9l5dk808v9ybpmzlhrdc3sxmas3ajv8s7";
};
propagatedBuildInputs = [ pkgs.python3Packages.pyserial ];
};
toptica-lasersdk-artiq = pkgs.python3Packages.buildPythonPackage rec {
version = "0.1";
name = "toptica-lasersdk-artiq-${version}";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "lasersdk-artiq";
rev = "d38bb985e7ddffc9ac9d94fe136cac10947bfd72";
sha256 = "03a09lc81l2l787yjm0xjpnjvs5x77ndmks3xxh25yyxdhsdf1fl";
};
postPatch = ''
substituteInPlace lasersdk_artiq/aqctl_laser.py \
--replace "toptica.lasersdk.async.client" \
"toptica.lasersdk.asyncio.client"
substituteInPlace lasersdk_artiq/test.py \
--replace "toptica.lasersdk.async.client" \
"toptica.lasersdk.asyncio.client"
'';
propagatedBuildInputs = [ toptica-lasersdk artiq ];
};
} // (dualPackage {
name = "highfinesse-net";
version = "0.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "highfinesse-net";
rev = "6864ae5da5cbc67953b968010115db951e52a272";
sha256 = "1k8xacgam5xghxvljvdzpsdhhq86fra13hkvdy7y301s9nyp30s4";
};
pythonOptions = {
propagatedBuildInputs = [ artiq ];
# no unit tests without hardware so do a simple smoke test
checkPhase = "python -m highfinesse_net.aqctl_highfinesse_net --version";
};
})

57
artiq-full/manual.nix Normal file
View File

@ -0,0 +1,57 @@
{ stdenv, lib, fetchgit, git, python3Packages, texlive, texinfo, sphinxcontrib-wavedrom }:
let
artiqVersion = import <artiq-fast/pkgs/artiq-version.nix> { inherit stdenv fetchgit git; };
isLatexPdfTarget = target: builtins.match "latexpdf.*" target != null;
latex = texlive.combine {
inherit (texlive)
scheme-basic latexmk cmap collection-fontsrecommended fncychap
titlesec tabulary varwidth framed fancyvrb float wrapfig parskip
upquote capt-of needspace etoolbox;
};
artiq-manual = target: stdenv.mkDerivation rec {
name = "artiq-manual-${target}-${version}";
version = artiqVersion;
src = import <artiq-fast/pkgs/artiq-src.nix> { inherit fetchgit; };
buildInputs = [
python3Packages.sphinx python3Packages.sphinx_rtd_theme
python3Packages.sphinx-argparse sphinxcontrib-wavedrom
] ++
lib.optional (isLatexPdfTarget target) latex ++
lib.optional (target == "texinfo") texinfo;
preBuild = ''
export VERSIONEER_OVERRIDE=${artiqVersion}
export SOURCE_DATE_EPOCH=${import <artiq-fast/pkgs/artiq-timestamp.nix> { inherit stdenv fetchgit git; }}
cd doc/manual
'';
makeFlags = [ target ];
installPhase =
let
dest = "$out/share/doc/artiq-manual";
in
if isLatexPdfTarget target
then ''
mkdir -p ${dest}
cp _build/latex/ARTIQ.pdf ${dest}/
mkdir -p $out/nix-support/
echo doc-pdf manual ${dest} ARTIQ.pdf >> $out/nix-support/hydra-build-products
''
else ''
mkdir -p ${dest}
cp -r _build/${target} ${dest}/
mkdir -p $out/nix-support/
echo doc manual ${dest}/${target} index.html >> $out/nix-support/hydra-build-products
'';
};
targets = [ "html" "latexpdf" ];
in
builtins.listToAttrs (map (target: { name = "artiq-manual-${target}"; value = artiq-manual target; }) targets)

View File

@ -0,0 +1,43 @@
{ pkgs }:
rec {
wavedrom = pkgs.python3Packages.buildPythonPackage rec {
pname = "wavedrom";
version = "0.1";
src = pkgs.python3Packages.fetchPypi {
inherit pname version;
sha256 = "006w683zlmmwcw5xz1n5dwg34ims5jg3gl2700ql4wr0myjz6710";
};
buildInputs = [ pkgs.python3Packages.setuptools_scm ];
propagatedBuildInputs = with pkgs.python3Packages; [ svgwrite attrdict ];
doCheck = false;
meta = with pkgs.stdenv.lib; {
description = "WaveDrom compatible Python module and command line";
homepage = "https://pypi.org/project/wavedrom/";
license = licenses.mit;
};
};
sphinxcontrib-wavedrom = pkgs.python3Packages.buildPythonPackage rec {
pname = "sphinxcontrib-wavedrom";
version = "2.0.0";
src = pkgs.python3Packages.fetchPypi {
inherit pname version;
sha256 = "0nk36zqq5ipxqx9izz2iazb3iraasanv3nm05bjr21gw42zgkz22";
};
buildInputs = [ pkgs.python3Packages.setuptools_scm ];
propagatedBuildInputs = [ wavedrom ] ++ (with pkgs.python3Packages; [ sphinx xcffib cairosvg ]);
doCheck = false;
meta = with pkgs.stdenv.lib; {
description = "A Sphinx extension that allows including WaveDrom diagrams";
homepage = "https://pypi.org/project/sphinxcontrib-wavedrom/";
license = licenses.mit;
};
};
}

View File

@ -1,115 +0,0 @@
{ pkgs ? import <nixpkgs> {} }:
let
ise = import ./ise.nix { inherit pkgs; };
vivado = import ./vivado.nix { inherit pkgs; };
fpgatools = import ./fpgatools.nix { inherit pkgs; };
buildUrukulCpld = {version, src}: pkgs.stdenv.mkDerivation {
pname = "urukul-cpld";
inherit src version;
buildInputs = [(pkgs.python3.withPackages(ps: [fpgatools.migen]))] ++ (builtins.attrValues fpgatools.ise);
phases = ["buildPhase" "installPhase"];
buildPhase = "python $src/urukul_impl.py";
installPhase =
''
mkdir -p $out $out/nix-support
cp build/urukul.jed $out
echo file binary-dist $out/urukul.jed >> $out/nix-support/hydra-build-products
'';
};
buildMirnyCpld = {version, patchPhase ? "", src}: pkgs.stdenv.mkDerivation {
pname = "mirny-cpld";
inherit src version patchPhase;
buildInputs = [(pkgs.python3.withPackages(ps: [fpgatools.migen]))] ++ (builtins.attrValues fpgatools.ise);
phases = ["unpackPhase" "patchPhase" "buildPhase" "installPhase"];
buildPhase = "python $src/mirny_impl.py";
installPhase =
''
mkdir -p $out $out/nix-support
cp build/mirny.jed $out
echo file binary-dist $out/mirny.jed >> $out/nix-support/hydra-build-products
'';
};
in
{
urukul-cpld-master = buildUrukulCpld {
version = "master";
src = <urukulSrc>;
};
urukul-cpld-release = buildUrukulCpld rec {
version = "1.4.0";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "urukul";
rev = "v${version}";
sha256 = "1962jpzqzn22cwkcmfnvwqlj5i89pljhgfk64n6pk73clir9mp0w";
};
};
urukul-cpld-legacy = buildUrukulCpld rec {
version = "1.3.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "urukul";
rev = "v${version}";
sha256 = "1nvarspqbf9f7b27j34jkkh4mj6rwrlmccmfpz5nnzk3h2j6zbqc";
};
};
mirny-cpld-master = buildMirnyCpld {
version = "master";
src = <mirnySrc>;
};
mirny-cpld-release = buildMirnyCpld rec {
version = "0.3.1";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "mirny";
rev = "v${version}";
sha256 = "sha256-FbPUgXcUByEnczbnDCh8wYPO+rpSZSAabG1rtvA7mIs=";
};
};
mirny-cpld-legacy-almazny = buildMirnyCpld rec {
version = "0.2.4";
src = pkgs.fetchFromGitHub {
owner = "quartiq";
repo = "mirny";
rev = "v${version}";
sha256 = "sha256-/O1AE0JOXALC8I7NPhOd8h18oX8Qu7lj+6ToAMMD3zs=";
};
patchPhase = "patch -p1 < ${./mirny-legacy-almazny.diff}";
};
fastino-fpga = pkgs.stdenv.mkDerivation {
name = "fastino-fpga";
src = <fastinoSrc>;
buildInputs = [(pkgs.python3.withPackages(ps: [fpgatools.migen fpgatools.misoc]))] ++ [pkgs.yosys pkgs.nextpnr pkgs.icestorm];
phases = ["buildPhase" "installPhase"];
buildPhase = "python $src/fastino_phy.py";
installPhase =
''
mkdir -p $out $out/nix-support
cp build/fastino.bin $out
echo file binary-dist $out/fastino.bin >> $out/nix-support/hydra-build-products
'';
};
phaser-fpga = pkgs.stdenv.mkDerivation {
name = "phaser-fpga";
src = <phaserSrc>;
patchPhase = ''
substituteInPlace phaser.py \
--replace "source ../load.tcl" \
""
'';
buildInputs = [ (pkgs.python3.withPackages(ps: [ fpgatools.migen fpgatools.misoc ])) ] ++ [ fpgatools.vivado ];
buildPhase = "python phaser.py";
installPhase =
''
mkdir -p $out $out/nix-support
cp build/phaser.bit $out
echo file binary-dist $out/phaser.bit >> $out/nix-support/hydra-build-products
'';
dontFixup = true;
doCheck = true;
checkInputs = [ pkgs.python3Packages.pytest ];
checkPhase = "pytest";
};
}

View File

@ -1,94 +0,0 @@
{ pkgs, isePath ? "/opt/Xilinx/14.7/ISE_DS", vivadoPath ? "/opt/Xilinx/Vivado/2022.2" }:
rec {
ise = let
makeXilinxEnv = name: pkgs.buildFHSUserEnv {
inherit name;
targetPkgs = pkgs: (
with pkgs; [
ncurses5
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile =
''
source ${isePath}/common/.settings64.sh ${isePath}/common
source ${isePath}/ISE/.settings64.sh ${isePath}/ISE
'';
runScript = name;
};
in
pkgs.lib.attrsets.genAttrs ["xst" "ngdbuild" "cpldfit" "taengine" "hprep6"] makeXilinxEnv;
vivado = pkgs.buildFHSUserEnv {
name = "vivado";
targetPkgs = pkgs: (
with pkgs; let
# Apply patch from https://github.com/nix-community/nix-environments/pull/54
# to fix ncurses libtinfo.so's soname issue
ncurses' = ncurses5.overrideAttrs (old: {
configureFlags = old.configureFlags ++ [ "--with-termlib" ];
postFixup = "";
});
in [
libxcrypt-legacy
(ncurses'.override { unicodeSupport = false; })
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile = "source ${vivadoPath}/settings64.sh";
runScript = "vivado";
};
migen = pkgs.python3Packages.buildPythonPackage {
pname = "migen";
version = "unstable-2024-05-02";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "migen";
rev = "4790bb577681a8c3a8d226bc196a4e5deb39e4df";
sha256 = "sha256-4DCHBUBfc/VA+7NW2Hr0+JP4NnKPru2uVJyZjCCk0Ws=";
};
format = "pyproject";
nativeBuildInputs = [ pkgs.python3Packages.setuptools ];
propagatedBuildInputs = with pkgs.python3Packages; [ colorama ];
};
asyncserial = pkgs.python3Packages.buildPythonPackage {
pname = "asyncserial";
version = "0.1";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "asyncserial";
rev = "d95bc1d6c791b0e9785935d2f62f628eb5cdf98d";
sha256 = "0yzkka9jk3612v8gx748x6ziwykq5lr7zmr9wzkcls0v2yilqx9k";
};
propagatedBuildInputs = with pkgs.python3Packages; [ pyserial ];
};
misoc = pkgs.python3Packages.buildPythonPackage {
pname = "misoc";
version = "unstable-2021-10-10";
src = pkgs.fetchFromGitHub {
owner = "m-labs";
repo = "misoc";
rev = "f5203e406520874e15ab5d070058ef642fc57fd9";
sha256 = "sha256-/2XTejqj0Bo81HaTrlTSWwInnWwsuqnq+CURXbpIrkA=";
fetchSubmodules = true;
};
# TODO: fix misoc bitrot and re-enable tests
doCheck = false;
propagatedBuildInputs = with pkgs.python3Packages; [ pyserial jinja2 numpy asyncserial migen ];
};
}

View File

@ -1,313 +0,0 @@
diff --git a/Makefile b/Makefile
index 667b8e7..ed97303 100644
--- a/Makefile
+++ b/Makefile
@@ -8,9 +8,15 @@ test:
.PHONY: build
build: build/mirny.vm6
+.PHONY: legacy_almazny
+legacy_almazny: build/mirny_legacy_almazny.vm6
+
build/mirny.vm6: mirny.py mirny_cpld.py
python mirny_impl.py
+build/mirny_legacy_almazny.vm6: mirny.py mirny_cpld.py
+ python mirny_impl.py --legacy-almazny
+
REV:=$(shell git describe --always --abbrev=8 --dirty)
.PHONY: release
diff --git a/README.md b/README.md
index 1bea35a..5e93809 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,39 @@
-# Mirny CPLD code
+# Mirny CPLD gateware
-[Mirny overview](https://github.com/sinara-hw/mirny/wiki)
+## Hardware
+
+[![Hardware](https://github.com/sinara-hw/mirny/wiki/Mirny_v1.0_top_small.jpg)](https://github.com/sinara-hw/mirny/wiki)
[Mirny Schematics](https://github.com/sinara-hw/mirny/releases)
## Building
-Needs migen and ISE.
+Needs [migen](https://github.com/m-labs/migen) and [Xilinx ISE](https://www.xilinx.com/products/design-tools/ise-design-suite.html). Assumes ISE is installed in ``/opt/Xilinx``.
```
make
-# and then look at/use flash.sh or make flash
-
-# or use fxload and xc3sprog:
-/sbin/fxload -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D /dev/bus/usb/001/*`cat /sys/bus/usb/devices/1-3/devnum` && sleep 10 && \
-xc3sprog -c xpc -m /opt/Xilinx/14.7/ISE_DS/ISE/xbr/data -v build/mirny.jed:w
-# look for "Verify: Success"
```
+## Flashing
+
+With Digilent [JTAG HS2](https://store.digilentinc.com/jtag-hs2-programming-cable/) cable:
+
+ - download firmware to dongle. Manually (adjust USB bus as needed):
+ ```
+ /sbin/fxload -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D /dev/bus/usb/001/*`cat /sys/bus/usb/devices/1-3/devnum`
+ ```
+ or automatically via the ``udev`` rule:
+ ```
+ SUBSYSTEM=="usb", ACTION="add", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", ATTR{manufacturer}=="Digilent", RUN+="/usr/bin/fxload -v -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D $tempnode"
+ ```
+
+ - install [xc3sprog](http://xc3sprog.sourceforge.net/)
+
+ - ``flash_xc3.sh jtaghs2``
+
+ - look for ``Verify: Success``
+
+
# License
GPLv3+
diff --git a/flash_xc3.sh b/flash_xc3.sh
index 4c8a94c..c84b4d6 100755
--- a/flash_xc3.sh
+++ b/flash_xc3.sh
@@ -1,8 +1,9 @@
#!/bin/bash
set -e
-set -x
-/sbin/fxload -t fx2 -I /opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64/xusb_xp2.hex -D /dev/bus/usb/001/*`cat /sys/bus/usb/devices/1-7/devnum`
-sleep 7
-../xc3sprog/build/xc3sprog -c xpc -m /opt/Xilinx/14.7/ISE_DS/ISE/xbr/data -v build/mirny.jed:w
+XC3SPROG=xc3sprog
+CABLE=${1-xpc}
+
+set -x
+$XC3SPROG -c $CABLE -m /opt/Xilinx/14.7/ISE_DS/ISE/xbr/data -v build/mirny.jed:w
diff --git a/mirny.py b/mirny.py
index 82edca2..6dc2612 100644
--- a/mirny.py
+++ b/mirny.py
@@ -153,7 +153,6 @@ class SR(Module):
),
]
-
def intersection(a, b):
(aa, am), (ba, bm) = a, b
# TODO
@@ -182,26 +181,26 @@ class Mirny(Module):
SPI
---
- SPI xfer is ADR(7), WE(1), DAT(REG: 16, ATT: 8, PLL: 32)
-
- | ADR | TARGET |
- |--------+--------|
- | 0 | REG0 |
- | 1 | REG1 |
- | 2 | REG2 |
- | 3 | REG3 |
- | 4 | PLL0 |
- | 5 | PLL1 |
- | 6 | PLL2 |
- | 7 | PLL3 |
- | 8 | ATT0 |
- | 9 | ATT1 |
- | a | ATT2 |
- | b | ATT3 |
- | c | reserved |
- | d | reserved |
- | e | reserved |
- | f | reserved |
+ SPI xfer is ADR(7), WE(1), DAT(REG: 16, ATT: 8, PLL: 32, SR: 8)
+
+ | ADR | TARGET |
+ |-----+----------------------|
+ | 0 | REG0 |
+ | 1 | REG1 |
+ | 2 | REG2 |
+ | 3 | REG3 |
+ | 4 | PLL0 |
+ | 5 | PLL1 |
+ | 6 | PLL2 |
+ | 7 | PLL3 |
+ | 8 | ATT0 |
+ | 9 | ATT1 |
+ | a | ATT2 |
+ | b | ATT3 |
+ | c | (Legacy Almazny) SR1 |
+ | d | (Legacy Almazny) SR2 |
+ | e | (Legacy Almazny) SR3 |
+ | f | (Legacy Almazny) SR4 |
The SPI interface is CPOL=0, CPHA=0, SPI mode 0, 4-wire, full fuplex.
@@ -223,8 +222,8 @@ class Mirny(Module):
| Name | Width | Function |
|-----------+-------+------------------------------------|
| CE_N | 4 | PLL chip enable (bar) |
- | CLK_SEL | 2 | Selects CLK source: 0 OSC, 1 MMCX, |
- | | | 2 reserved, 3 SMA |
+ | CLK_SEL | 2 | Selects CLK source: |
+ | | | 0 OSC, 1 reserved, 2 MMCX, 3 SMA |
| DIV | 2 | Clock divider configuration: |
| | | 0: divide-by-one, |
| | | 1: reserved, |
@@ -234,6 +233,7 @@ class Mirny(Module):
| FSEN_N | 1 | LVDS fail safe, Type 2 (bar) |
| MUXOUT_EEM| 1 | route MUXOUT to EEM[4:8] |
| EEM_MEZZIO| 1 | route EEM[4:8] to MEZZ_IO[0:4] |
+ | ALMAZNY_OE| 1 | Almazny OE in legacy Almazny mode |
| Name | Width | Function |
|-----------+-------+------------------------------------|
@@ -250,7 +250,7 @@ class Mirny(Module):
The test points expose miscellaneous signals for debugging and are not part
of the protocol revision.
"""
- def __init__(self, platform):
+ def __init__(self, platform, legacy_almazny=False):
self.eem = eem = []
for i in range(8):
tsi = TSTriple()
@@ -292,7 +292,7 @@ class Mirny(Module):
self.sr.ext.cs.eq(eem[3].i),
]
- regs = [REG(), REG(width=12), REG(width=4), REG()]
+ regs = [REG(), REG(width=13), REG(width=4), REG()]
self.submodules += regs
for i, reg in enumerate(regs):
self.sr.connect(reg.bus, adr=i, mask=mask)
@@ -310,23 +310,47 @@ class Mirny(Module):
clk = platform.request("clk")
clk_div = TSTriple()
self.specials += clk_div.get_tristate(clk.div)
- # in_sel: 00: XO, 01: MMCX, 10: n/a (SMA+XO), 11: SMA
+ # in_sel: 00: XO, 01: n/a (SMA+XO), 10: MMCX, 11: SMA
# dividers: 00(z): 1, 01(z): 1, 10(low): 2, 11(high) 4
self.comb += [
Cat(clk.in_sel, clk_div.o, clk_div.oe).eq(regs[1].write[4:8]),
platform.request("fsen").eq(~regs[1].write[9]),
]
- for i, m in enumerate(platform.request("mezz_io")):
- tsi = TSTriple()
- self.specials += tsi.get_tristate(m)
+ if legacy_almazny:
+ almazny_io = platform.request("legacy_almazny_common")
+ almazny_adr = 0b1100 # 1100 - and then 1101, 1110, 1111 for sr 1-4
+ ext = Record(ext_layout)
+ self.sr.connect_ext(ext, almazny_adr, almazny_adr)
+ latches = AsyncRst(width=4, reset=0xF)
+ self.submodules += latches
+
self.comb += [
- tsi.o.eq(regs[3].write[i] | (0 if i >= 4 else
- (regs[1].write[11] & eem[i + 4].i))),
- regs[3].read[i].eq(tsi.i),
- tsi.oe.eq(regs[3].write[i + 8]),
- regs[3].read[i + 8].eq(tsi.oe),
+ latches.ce.eq(ext.cs),
+ almazny_io.clk.eq(ext.sck),
+ almazny_io.mosi.eq(ext.sdi),
+ almazny_io.srclr.eq(1)
]
+
+ for i in range(4):
+ almazny = platform.request("legacy_almazny", i)
+ self.sync += latches.i[i].eq(self.sr.bus.adr[:2] != i)
+ self.comb += [
+ almazny.latch.eq(latches.o[i]),
+ almazny.noe.eq(~regs[1].write[12])
+ ]
+
+ else:
+ for i, m in enumerate(platform.request("mezz_io")):
+ tsi = TSTriple()
+ self.specials += tsi.get_tristate(m)
+ self.comb += [
+ tsi.o.eq(regs[3].write[i] | (0 if i >= 4 else
+ (regs[1].write[11] & eem[i + 4].i))),
+ regs[3].read[i].eq(tsi.i),
+ tsi.oe.eq(regs[3].write[i + 8]),
+ regs[3].read[i + 8].eq(tsi.oe),
+ ]
for i in range(4):
rf_sw = platform.request("rf_sw", i)
diff --git a/mirny_cpld.py b/mirny_cpld.py
index 70fc164..a688d89 100644
--- a/mirny_cpld.py
+++ b/mirny_cpld.py
@@ -16,9 +16,33 @@ _io = [
# fail save LVDS enable, LVDS mode selection
# high: type 2 receiver, failsafe low
("fsen", 0, Pins("P80")),
-
+
+ # IO from 0 to 7
("mezz_io", 0, Pins("P57 P58 P59 P60 P61 P64 P68 P69")),
+ # legacy (v1.0-1.1) Almazny pins
+ ("legacy_almazny_common", 0,
+ Subsignal("mosi", Pins("P94")),
+ Subsignal("clk", Pins("P97")),
+ Subsignal("srclr", Pins("P60")),
+ ),
+ ("legacy_almazny", 0,
+ Subsignal("latch", Pins("P96")),
+ Subsignal("noe", Pins("P95")),
+ ),
+ ("legacy_almazny", 1,
+ Subsignal("latch", Pins("P100")),
+ Subsignal("noe", Pins("P98")),
+ ),
+ ("legacy_almazny", 2,
+ Subsignal("latch", Pins("P92")),
+ Subsignal("noe", Pins("P101")),
+ ),
+ ("legacy_almazny", 3,
+ Subsignal("latch", Pins("P57")),
+ Subsignal("noe", Pins("P58")),
+ ),
+
("clk", 0,
Subsignal("div", Pins("P53")),
Subsignal("in_sel", Pins("P54 P56")),
diff --git a/mirny_impl.py b/mirny_impl.py
index 0c42b0b..d7022dc 100644
--- a/mirny_impl.py
+++ b/mirny_impl.py
@@ -1,10 +1,23 @@
+import argparse
+
+def get_argparser():
+ parser = argparse.ArgumentParser(
+ description="Mirny CPLD firmware"
+ )
+ parser.add_argument("--legacy-almazny", action="store_true", default=False)
+
+ return parser
+
def main():
from mirny_cpld import Platform
from mirny import Mirny
+ args = get_argparser().parse_args()
+
p = Platform()
- mirny = Mirny(p)
- p.build(mirny, build_name="mirny", mode="cpld")
+ mirny = Mirny(p, args.legacy_almazny)
+ build_name = "mirny" if not args.legacy_almazny else "mirny_legacy_almazny"
+ p.build(mirny, build_name=build_name, mode="cpld")
if __name__ == "__main__":

View File

@ -1,183 +1,16 @@
{
"main-nac3": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (with NAC3)",
"flake": "git+https://github.com/m-labs/artiq.git?ref=nac3",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"nac3": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Third generation ARTIQ compiler",
"flake": "git+https://git.m-labs.hk/M-Labs/nac3.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"main-beta": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (beta version)",
"flake": "git+https://github.com/m-labs/artiq.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"extra-beta": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Additional ARTIQ packages (beta version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-extrapkg.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq-beta": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "ARTIQ on Zynq-7000 (beta version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-zynq.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"main": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (stable version)",
"flake": "git+https://github.com/m-labs/artiq.git?ref=release-8",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"extra": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Additional ARTIQ packages (stable version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-extrapkg.git?ref=release-8",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "ARTIQ on Zynq-7000 (stable version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-zynq.git?ref=release-8",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"main-legacy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Main ARTIQ packages (legacy version)",
"flake": "git+https://github.com/m-labs/artiq.git?ref=release-7",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"extra-legacy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Additional ARTIQ packages (legacy version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-extrapkg.git?ref=release-7",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq-legacy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "ARTIQ on Zynq-7000 (legacy version)",
"flake": "git+https://git.m-labs.hk/m-labs/artiq-zynq.git?ref=release-7",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"gluelogic": {
"enabled": 1,
"hidden": false,
"description": "Glue logic gateware for Sinara devices",
"nixexprinput": "nixScripts",
"nixexprpath": "gluelogic.nix",
"checkinterval": 172800,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 50,
"inputs": {
"nixpkgs": { "type": "git", "value": "https://github.com/NixOS/nixpkgs.git nixos-24.05", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"urukulSrc": { "type": "git", "value": "https://github.com/quartiq/urukul.git", "emailresponsible": false },
"mirnySrc": { "type": "git", "value": "https://github.com/quartiq/mirny.git", "emailresponsible": false },
"fastinoSrc": { "type": "git", "value": "https://github.com/quartiq/fastino.git", "emailresponsible": false },
"phaserSrc": { "type": "git", "value": "https://github.com/quartiq/phaser.git", "emailresponsible": false }
}
},
"sipyco": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Simple Python Communications",
"flake": "github:m-labs/sipyco",
"checkinterval": 600,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
},
"zynq-rs": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Bare-metal Rust on Zynq-7000",
"flake": "git+https://git.m-labs.hk/m-labs/zynq-rs.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 50
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/artiq.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false }
}
}

62
hydra/artiq.nix Normal file
View File

@ -0,0 +1,62 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"fast": {
"enabled": 1,
"hidden": false,
"description": "Core ARTIQ packages to build fast for CI purposes",
"nixexprinput": "nixScripts",
"nixexprpath": "artiq-fast.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"artiqSrc": { "type": "git", "value": "git://github.com/m-labs/artiq.git master 1", "emailresponsible": false }
}
},
"full": {
"enabled": 1,
"hidden": false,
"description": "Full set of ARTIQ packages",
"nixexprinput": "nixScripts",
"nixexprpath": "artiq-full.nix",
"checkinterval": 86400,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"sinaraSystemsSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/sinara-systems.git master 1", "emailresponsible": false },
"artiq-fast": { "type": "sysbuild", "value": "artiq:fast:generated-nix", "emailresponsible": false }
}
},
"urukul": {
"enabled": 1,
"hidden": false,
"description": "Urukul CPLD gateware",
"nixexprinput": "nixScripts",
"nixexprpath": "urukul.nix",
"checkinterval": 172800,
"schedulingshares": 1,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"urukulSrc": { "type": "git", "value": "git://github.com/quartiq/urukul", "emailresponsible": false }
}
}
}
EOF
'';
}

16
hydra/fpga.json Normal file
View File

@ -0,0 +1,16 @@
{
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/fpga.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.03", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false }
}
}

26
hydra/fpga.nix Normal file
View File

@ -0,0 +1,26 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"heavyx": {
"enabled": 1,
"hidden": false,
"description": "HeavyX SoC toolkit experiment",
"nixexprinput": "heavyx",
"nixexprpath": "release.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.03", "emailresponsible": false },
"heavyx": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/HeavyX.git", "emailresponsible": false }
}
}
}
EOF
'';
}

View File

@ -1,57 +0,0 @@
{
"mcu-contrib": {
"enabled": 1,
"hidden": false,
"description": "Third-party MCU firmware",
"nixexprinput": "nixScripts",
"nixexprpath": "mcu-contrib.nix",
"checkinterval": 7200,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "https://github.com/NixOS/nixpkgs.git nixos-24.05", "emailresponsible": false },
"mozillaOverlay": { "type": "git", "value": "https://github.com/mozilla/nixpkgs-mozilla.git", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"stabilizerSrc": { "type": "git", "value": "https://github.com/quartiq/stabilizer.git main", "emailresponsible": false },
"saymaMmcSrc": { "type": "git", "value": "https://github.com/sinara-hw/openMMC.git sayma-devel", "emailresponsible": false }
}
},
"thermostat": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Firmware for the Sinara 8451 Thermostat",
"flake": "git+https://git.m-labs.hk/M-Labs/thermostat.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10
},
"humpback-dds": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Firmware for Humpback-DDS",
"flake": "git+https://git.m-labs.hk/M-Labs/humpback-dds.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10
},
"kirdy": {
"enabled": 1,
"type": 1,
"hidden": false,
"description": "Firmware for the Sinara 1550 Kirdy laser diode driver",
"flake": "git+https://git.m-labs.hk/M-Labs/kirdy.git",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10
}
}

16
hydra/stm32.json Normal file
View File

@ -0,0 +1,16 @@
{
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/stm32.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false }
}
}

29
hydra/stm32.nix Normal file
View File

@ -0,0 +1,29 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"stm32": {
"enabled": 1,
"hidden": false,
"description": "STM32 firmware",
"nixexprinput": "nixScripts",
"nixexprpath": "stm32.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"mozillaOverlay": { "type": "git", "value": "git://github.com/mozilla/nixpkgs-mozilla.git", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"stabilizerSrc": { "type": "git", "value": "git://github.com/quartiq/stabilizer.git", "emailresponsible": false },
"thermostatSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/thermostat.git", "emailresponsible": false }
}
}
}
EOF
'';
}

16
hydra/tecpak.json Normal file
View File

@ -0,0 +1,16 @@
{
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/tecpak.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git tecpak", "emailresponsible": false }
}
}

28
hydra/tecpak.nix Normal file
View File

@ -0,0 +1,28 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"tecpak": {
"enabled": 1,
"hidden": false,
"description": "tecpak",
"nixexprinput": "nixScripts",
"nixexprpath": "tecpak.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"tecpak": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/ionpak-thermostat.git", "emailresponsible": false },
"mozillaOverlay": { "type": "git", "value": "https://github.com/mozilla/nixpkgs-mozilla.git", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/astro/nix-scripts.git tecpak", "emailresponsible": false }
}
}
}
EOF
'';
}

View File

@ -1,20 +1,16 @@
{
"web": {
"enabled": 1,
"hidden": false,
"description": "Websites",
"nixexprinput": "nixScripts",
"nixexprpath": "web.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "https://github.com/NixOS/nixpkgs.git nixos-24.05", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"webSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/web2019.git", "emailresponsible": false },
"nmigenSrc": { "type": "git", "value": "https://gitlab.com/nmigen/nmigen.git", "emailresponsible": false }
}
"enabled": 1,
"hidden": true,
"description": "js",
"nixexprinput": "nixScripts",
"nixexprpath": "hydra/web.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false }
}
}

27
hydra/web.nix Normal file
View File

@ -0,0 +1,27 @@
{ pkgs ? import <nixpkgs> {}}:
{
jobsets = pkgs.runCommand "spec.json" {}
''
cat > $out << EOF
{
"web": {
"enabled": 1,
"hidden": false,
"description": "M-Labs website",
"nixexprinput": "nixScripts",
"nixexprpath": "web.nix",
"checkinterval": 300,
"schedulingshares": 10,
"enableemail": false,
"emailoverride": "",
"keepnr": 10,
"inputs": {
"nixpkgs": { "type": "git", "value": "git://github.com/NixOS/nixpkgs-channels nixos-19.09", "emailresponsible": false },
"nixScripts": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/nix-scripts.git", "emailresponsible": false },
"webSrc": { "type": "git", "value": "https://git.m-labs.hk/M-Labs/web2019.git", "emailresponsible": false }
}
}
}
EOF
'';
}

View File

@ -1,8 +0,0 @@
{ pkgs ? import <nixpkgs> {} }:
let
jobs = import ./mcu-contrib/default.nix {
mozillaOverlay = import <mozillaOverlay>;
};
in
builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) jobs

View File

@ -1,104 +0,0 @@
{ # Use master branch of the overlay by default
mozillaOverlay ? import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz),
}:
let
pkgs = import <nixpkgs> { overlays = [ mozillaOverlay ]; };
targets = [
"thumbv7em-none-eabihf"
];
rustManifest = pkgs.fetchurl {
url = "https://static.rust-lang.org/dist/2024-06-13/channel-rust-stable.toml";
sha256 = "sha256-Ngiz76YP4HTY75GGdH2P+APE/DEIx2R/Dn+BwwOyzZU=";
};
rustChannelOfTargets = _channel: _date: targets:
(pkgs.lib.rustLib.fromManifestFile rustManifest {
inherit (pkgs) stdenv lib fetchurl patchelf;
}).rust.override {
inherit targets;
extensions = ["rust-src"];
};
rust = rustChannelOfTargets "nightly" null targets;
rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
rustc = rust;
cargo = rust;
});
buildStm32Firmware = { name, src, cargoDepsName ? name, patchPhase ? "", extraNativeBuildInputs ? [], checkPhase ? "", doCheck ? true, binaryName ? name, extraCargoBuildArgs ? "", outputHashes ? {} }:
rustPlatform.buildRustPackage rec {
inherit name cargoDepsName;
version = "0.0.0";
inherit src;
cargoLock = { lockFile = "${src}/Cargo.lock"; inherit outputHashes; };
inherit patchPhase;
nativeBuildInputs = [ pkgs.llvm ] ++ extraNativeBuildInputs;
buildPhase = ''
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
cargo build --release --bin ${binaryName} ${extraCargoBuildArgs}
'';
inherit checkPhase doCheck;
# binaryName defaults to the `name` arg (i.e. the Rust package name);
# it is used as the Cargo binary filename
installPhase = ''
mkdir -p $out $out/nix-support
cp target/thumbv7em-none-eabihf/release/${binaryName} $out/${name}.elf
echo file binary-dist $out/${name}.elf >> $out/nix-support/hydra-build-products
llvm-objcopy -O binary target/thumbv7em-none-eabihf/release/${binaryName} $out/${name}.bin
echo file binary-dist $out/${name}.bin >> $out/nix-support/hydra-build-products
'';
dontFixup = true;
auditable = false;
};
in
pkgs.lib.attrsets.mapAttrs'
(name: value: pkgs.lib.attrsets.nameValuePair ("stabilizer-" + name)
(buildStm32Firmware ({
name = "stabilizer-" + name;
# If binaryName is not specified, use the attribute name as binaryName by default.
binaryName = name;
cargoDepsName = "stabilizer";
src = <stabilizerSrc>;
patchPhase = ''
patch -p1 < ${./pounder-725.diff}
'';
doCheck = false;
outputHashes = {
"menu-0.6.0" = "sha256-Zilj27J4a/T/Je2qJr6igFj2OEw0/4fU4f0t+afm4TY=";
};
} // value))) {
dual-iir = {};
dual-iir-pounder_v1_0 = {
binaryName = "dual-iir";
extraCargoBuildArgs = "--features pounder_v1_0";
};
lockin = {};
} //
{
# openMMC build system breaks if host compiler is not available, so do not use stdenvNoCC here
sayma-mmc = pkgs.stdenv.mkDerivation {
name = "sayma-mmc";
src = <saymaMmcSrc>;
phases = [ "unpackPhase" "buildPhase" "installPhase" ];
nativeBuildInputs = [ pkgs.cmake pkgs.gcc-arm-embedded ];
buildPhase =
''
mkdir build
cd build
cmake .. -DBOARD=sayma -DBOARD_RTM=sayma -DVERSION= -DTARGET_CONTROLLER=LPC1776 -DCMAKE_BUILD_TYPE=Debug
make
'';
installPhase =
''
mkdir $out
cp out/* $out
mkdir -p $out $out/nix-support
echo file binary-dist $out/openMMC.axf >> $out/nix-support/hydra-build-products
echo file binary-dist $out/openMMC.bin >> $out/nix-support/hydra-build-products
'';
};
}

View File

@ -1,811 +0,0 @@
diff --git a/ad9959/src/lib.rs b/ad9959/src/lib.rs
index 025f7d4f..59578cce 100644
--- a/ad9959/src/lib.rs
+++ b/ad9959/src/lib.rs
@@ -2,8 +2,24 @@
use bit_field::BitField;
use bitflags::bitflags;
+use core::ops::Range;
use embedded_hal::{blocking::delay::DelayUs, digital::v2::OutputPin};
+/// The minimum reference clock input frequency with REFCLK multiplier disabled.
+const MIN_REFCLK_FREQUENCY: f32 = 1e6;
+/// The minimum reference clock input frequency with REFCLK multiplier enabled.
+const MIN_MULTIPLIED_REFCLK_FREQUENCY: f32 = 10e6;
+/// The system clock frequency range with high gain configured for the internal VCO.
+const HIGH_GAIN_VCO_RANGE: Range<f32> = Range {
+ start: 255e6,
+ end: 500e6,
+};
+/// The system clock frequency range with low gain configured for the internal VCO.
+const LOW_GAIN_VCO_RANGE: Range<f32> = Range {
+ start: 100e6,
+ end: 160e6,
+};
+
/// A device driver for the AD9959 direct digital synthesis (DDS) chip.
///
/// This chip provides four independently controllable digital-to-analog output sinusoids with
@@ -218,23 +234,17 @@ impl<I: Interface> Ad9959<I> {
reference_clock_frequency: f32,
multiplier: u8,
) -> Result<f32, Error> {
+ let frequency =
+ validate_clocking(reference_clock_frequency, multiplier)?;
self.reference_clock_frequency = reference_clock_frequency;
- if multiplier != 1 && !(4..=20).contains(&multiplier) {
- return Err(Error::Bounds);
- }
-
- let frequency = multiplier as f32 * self.reference_clock_frequency;
- if frequency > 500_000_000.0f32 {
- return Err(Error::Frequency);
- }
-
// TODO: Update / disable any enabled channels?
let mut fr1: [u8; 3] = [0, 0, 0];
self.read(Register::FR1, &mut fr1)?;
fr1[0].set_bits(2..=6, multiplier);
- let vco_range = frequency > 255e6;
+ let vco_range = HIGH_GAIN_VCO_RANGE.contains(&frequency)
+ || frequency == HIGH_GAIN_VCO_RANGE.end;
fr1[0].set_bit(7, vco_range);
self.write(Register::FR1, &fr1)?;
@@ -365,9 +375,7 @@ impl<I: Interface> Ad9959<I> {
channel: Channel,
phase_turns: f32,
) -> Result<f32, Error> {
- let phase_offset: u16 =
- (phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16;
-
+ let phase_offset = phase_to_pow(phase_turns)?;
self.modify_channel(
channel,
Register::CPOW0,
@@ -513,6 +521,108 @@ impl<I: Interface> Ad9959<I> {
}
}
+/// Validate the internal system clock configuration of the chip.
+///
+/// Arguments:
+/// * `reference_clock_frequency` - The reference clock frequency provided to the AD9959 core.
+/// * `multiplier` - The frequency multiplier of the system clock. Must be 1 or 4-20.
+///
+/// Returns:
+/// The system clock frequency to be configured.
+pub fn validate_clocking(
+ reference_clock_frequency: f32,
+ multiplier: u8,
+) -> Result<f32, Error> {
+ // The REFCLK frequency must be at least 1 MHz with REFCLK multiplier disabled.
+ if reference_clock_frequency < MIN_REFCLK_FREQUENCY {
+ return Err(Error::Bounds);
+ }
+ // If the REFCLK multiplier is enabled, the multiplier (FR1[22:18]) must be between 4 to 20.
+ // Alternatively, the clock multiplier can be disabled. The multiplication factor is 1.
+ if multiplier != 1 && !(4..=20).contains(&multiplier) {
+ return Err(Error::Bounds);
+ }
+ // If the REFCLK multiplier is enabled, the REFCLK frequency must be at least 10 MHz.
+ if multiplier != 1
+ && reference_clock_frequency < MIN_MULTIPLIED_REFCLK_FREQUENCY
+ {
+ return Err(Error::Bounds);
+ }
+ let frequency = multiplier as f32 * reference_clock_frequency;
+ // SYSCLK frequency between 255 MHz and 500 MHz (inclusive) is valid with high range VCO
+ if HIGH_GAIN_VCO_RANGE.contains(&frequency)
+ || frequency == HIGH_GAIN_VCO_RANGE.end
+ {
+ return Ok(frequency);
+ }
+
+ // SYSCLK frequency between 100 MHz and 160 MHz (inclusive) is valid with low range VCO
+ if LOW_GAIN_VCO_RANGE.contains(&frequency)
+ || frequency == LOW_GAIN_VCO_RANGE.end
+ {
+ return Ok(frequency);
+ }
+
+ // When the REFCLK multiplier is disabled, SYSCLK frequency can go below 100 MHz
+ if multiplier == 1 && (0.0..=LOW_GAIN_VCO_RANGE.start).contains(&frequency)
+ {
+ return Ok(frequency);
+ }
+
+ Err(Error::Frequency)
+}
+
+/// Convert and validate frequency into frequency tuning word.
+///
+/// Arguments:
+/// * `dds_frequency` - The DDS frequency to be converted and validated.
+/// * `system_clock_frequency` - The system clock frequency of the AD9959 core.
+///
+/// Returns:
+/// The corresponding frequency tuning word.
+pub fn frequency_to_ftw(
+ dds_frequency: f32,
+ system_clock_frequency: f32,
+) -> Result<u32, Error> {
+ // Output frequency should not exceed the Nyquist's frequency.
+ if !(0.0..=(system_clock_frequency / 2.0)).contains(&dds_frequency) {
+ return Err(Error::Bounds);
+ }
+ // The function for channel frequency is `f_out = FTW * f_s / 2^32`, where FTW is the
+ // frequency tuning word and f_s is the system clock rate.
+ Ok(((dds_frequency / system_clock_frequency) * (1u64 << 32) as f32) as u32)
+}
+
+/// Convert phase into phase offset word.
+///
+/// Arguments:
+/// * `phase_turns` - The normalized number of phase turns of a DDS channel.
+///
+/// Returns:
+/// The corresponding phase offset word.
+pub fn phase_to_pow(phase_turns: f32) -> Result<u16, Error> {
+ Ok((phase_turns * (1 << 14) as f32) as u16 & 0x3FFFu16)
+}
+
+/// Convert amplitude into amplitude control register values.
+///
+/// Arguments:
+/// * `amplitude` - The normalized amplitude of a DDS channel.
+///
+/// Returns:
+/// The corresponding value in the amplitude control register.
+pub fn amplitude_to_acr(amplitude: f32) -> Result<u32, Error> {
+ if !(0.0..=1.0).contains(&amplitude) {
+ return Err(Error::Bounds);
+ }
+
+ let acr: u32 = *0u32
+ .set_bits(0..=9, ((amplitude * (1 << 10) as f32) as u32) & 0x3FF)
+ .set_bit(12, amplitude != 1.0);
+
+ Ok(acr as u32)
+}
+
/// Represents a means of serializing a DDS profile for writing to a stream.
pub struct ProfileSerializer {
// heapless::Vec<u8, 32>, especially its extend_from_slice() is slow
@@ -568,6 +678,39 @@ impl ProfileSerializer {
}
}
+ /// Update the system clock configuration.
+ ///
+ /// # Args
+ /// * `reference_clock_frequency` - The reference clock frequency provided to the AD9959 core.
+ /// * `multiplier` - The frequency multiplier of the system clock. Must be 1 or 4-20.
+ ///
+ /// # Limitations
+ /// The correctness of the FR1 register setting code rely on FR1\[0:17\] staying 0.
+ pub fn set_system_clock(
+ &mut self,
+ reference_clock_frequency: f32,
+ multiplier: u8,
+ ) -> Result<f32, Error> {
+ let frequency = reference_clock_frequency * multiplier as f32;
+
+ // The enabled channel will be updated after clock reconfig
+ let mut fr1 = [0u8; 3];
+
+ // The ad9959 crate does not modify FR1[0:17]. These bits keep their default value.
+ // These bits by default are 0.
+ // Reading the register then update is not possible to implement in a serializer, where
+ // many QSPI writes are performed in burst. Switching between read and write requires
+ // breaking the QSPI indirect write mode and switch into the QSPI indirect read mode.
+ fr1[0].set_bits(2..=6, multiplier);
+
+ // Frequencies within the VCO forbidden range (160e6, 255e6) are already rejected.
+ let vco_range = HIGH_GAIN_VCO_RANGE.contains(&frequency);
+ fr1[0].set_bit(7, vco_range);
+
+ self.add_write(Register::FR1, &fr1);
+ Ok(frequency)
+ }
+
/// Add a register write to the serialization data.
fn add_write(&mut self, register: Register, value: &[u8]) {
let data = &mut self.data[self.index..];
diff --git a/src/bin/dual-iir.rs b/src/bin/dual-iir.rs
index ea566e14..84bde34a 100644
--- a/src/bin/dual-iir.rs
+++ b/src/bin/dual-iir.rs
@@ -28,7 +28,7 @@
#![no_std]
#![no_main]
-use core::mem::MaybeUninit;
+use core::mem::{MaybeUninit, size_of};
use core::sync::atomic::{fence, Ordering};
use serde::{Deserialize, Serialize};
@@ -47,6 +47,8 @@ use stabilizer::{
dac::{Dac0Output, Dac1Output, DacCode},
hal,
signal_generator::{self, SignalGenerator},
+ pounder::{ClockConfig, PounderConfig},
+ setup::PounderDevices as Pounder,
timers::SamplingTimer,
DigitalInput0, DigitalInput1, SerialTerminal, SystemTimer, Systick,
UsbDevice, AFE0, AFE1,
@@ -179,6 +181,16 @@ pub struct DualIir {
/// See [signal_generator::BasicConfig#miniconf]
#[tree(depth = 2)]
source: [signal_generator::BasicConfig; 2],
+
+ /// Specifies the config for pounder DDS clock configuration, DDS channels & attenuations
+ ///
+ /// # Path
+ /// `pounder`
+ ///
+ /// # Value
+ /// See [PounderConfig#miniconf]
+ #[tree]
+ pounder: Option<PounderConfig>,
}
impl Default for DualIir {
@@ -206,6 +218,8 @@ impl Default for DualIir {
source: Default::default(),
stream: Default::default(),
+
+ pounder: None.into(),
}
}
}
@@ -222,6 +236,7 @@ mod app {
active_settings: DualIir,
telemetry: TelemetryBuffer,
source: [SignalGenerator; 2],
+ pounder: Option<Pounder>,
}
#[local]
@@ -233,6 +248,7 @@ mod app {
adcs: (Adc0Input, Adc1Input),
dacs: (Dac0Output, Dac1Output),
iir_state: [[[f32; 4]; IIR_CASCADE_LENGTH]; 2],
+ dds_clock_state: Option<ClockConfig>,
generator: FrameGenerator,
cpu_temp_sensor: stabilizer::hardware::cpu_temp_sensor::CpuTempSensor,
}
@@ -242,7 +258,7 @@ mod app {
let clock = SystemTimer::new(|| Systick::now().ticks());
// Configure the microcontroller
- let (stabilizer, _pounder) = hardware::setup::setup::<Settings, 4>(
+ let (mut stabilizer, pounder) = hardware::setup::setup::<Settings, 4>(
c.core,
c.device,
clock,
@@ -261,6 +277,13 @@ mod app {
let generator = network.configure_streaming(StreamFormat::AdcDacData);
+ let dds_clock_state = pounder.as_ref().map(|_| ClockConfig::default());
+ if pounder.is_some() {
+ stabilizer.settings.dual_iir
+ .pounder
+ .replace(PounderConfig::default());
+ }
+
let shared = Shared {
usb: stabilizer.usb,
network,
@@ -279,6 +302,7 @@ mod app {
),
],
settings: stabilizer.settings,
+ pounder
};
let mut local = Local {
@@ -289,6 +313,7 @@ mod app {
adcs: stabilizer.adcs,
dacs: stabilizer.dacs,
iir_state: [[[0.; 4]; IIR_CASCADE_LENGTH]; 2],
+ dds_clock_state,
generator,
cpu_temp_sensor: stabilizer.temperature_sensor,
};
@@ -458,7 +483,7 @@ mod app {
}
}
- #[task(priority = 1, local=[afes], shared=[network, settings, active_settings, source])]
+ #[task(priority = 1, local=[afes, dds_clock_state], shared=[network, settings, active_settings, source, pounder])]
async fn settings_update(mut c: settings_update::Context) {
c.shared.settings.lock(|settings| {
c.local.afes.0.set_gain(settings.dual_iir.afe[0]);
@@ -480,6 +505,17 @@ mod app {
),
}
}
+ // Update Pounder configurations
+ c.shared.pounder.lock(|pounder| {
+ if let Some(pounder) = pounder {
+ let pounder_settings = settings.dual_iir.pounder.as_ref().unwrap();
+ // let mut clocking = c.local.dds_clock_state;
+ pounder.update_dds(
+ *pounder_settings,
+ c.local.dds_clock_state.as_mut().unwrap(),
+ );
+ }
+ });
c.shared
.network
@@ -491,21 +527,30 @@ mod app {
});
}
- #[task(priority = 1, shared=[network, settings, telemetry], local=[cpu_temp_sensor])]
+ #[task(priority = 1, shared=[network, settings, telemetry, pounder], local=[cpu_temp_sensor])]
async fn telemetry(mut c: telemetry::Context) {
loop {
let telemetry = c.shared.telemetry.lock(|telemetry| *telemetry);
- let (gains, telemetry_period) =
+ let (gains, telemetry_period, pounder_config) =
c.shared.settings.lock(|settings| {
- (settings.dual_iir.afe, settings.dual_iir.telemetry_period)
+ (
+ settings.dual_iir.afe,
+ settings.dual_iir.telemetry_period,
+ settings.dual_iir.pounder
+ )
});
+ let pounder_telemetry = c.shared.pounder.lock(|pounder| {
+ pounder.as_mut().map(|pdr| pdr.get_telemetry(pounder_config.unwrap()))
+ });
+
c.shared.network.lock(|net| {
net.telemetry.publish(&telemetry.finalize(
gains[0],
gains[1],
c.local.cpu_temp_sensor.get_temperature().unwrap(),
+ pounder_telemetry,
))
});
diff --git a/src/bin/lockin.rs b/src/bin/lockin.rs
index 3ddecd7c..77a7474b 100644
--- a/src/bin/lockin.rs
+++ b/src/bin/lockin.rs
@@ -29,7 +29,7 @@
use core::{
convert::TryFrom,
- mem::MaybeUninit,
+ mem::{MaybeUninit, size_of},
sync::atomic::{fence, Ordering},
};
@@ -547,6 +547,7 @@ mod app {
gains[0],
gains[1],
c.local.cpu_temp_sensor.get_temperature().unwrap(),
+ None,
))
});
diff --git a/src/hardware/pounder/attenuators.rs b/src/hardware/pounder/attenuators.rs
index cfd08b7f..2570f506 100644
--- a/src/hardware/pounder/attenuators.rs
+++ b/src/hardware/pounder/attenuators.rs
@@ -52,10 +52,9 @@ pub trait AttenuatorInterface {
fn get_attenuation(&mut self, channel: Channel) -> Result<f32, Error> {
let mut channels = [0_u8; 4];
- // Reading the data always shifts data out of the staging registers, so we perform a
- // duplicate write-back to ensure the staging register is always equal to the output
- // register.
- self.transfer_attenuators(&mut channels)?;
+ // Reading the data always shifts data out of the staging registers, so a duplicate
+ // write-back will be performed to ensure the staging register is always equal to the
+ // output register.
self.transfer_attenuators(&mut channels)?;
// The attenuation code is stored in the upper 6 bits of the register, where each LSB
@@ -66,6 +65,9 @@ pub trait AttenuatorInterface {
// care) would contain erroneous data.
let attenuation_code = (!channels[channel as usize]) >> 2;
+ // The write-back transfer is performed. Staging register is now restored.
+ self.transfer_attenuators(&mut channels)?;
+
// Convert the desired channel code into dB of attenuation.
Ok(attenuation_code as f32 / 2.0)
}
diff --git a/src/hardware/pounder/dds_output.rs b/src/hardware/pounder/dds_output.rs
index 3ae1ce90..cd978b01 100644
--- a/src/hardware/pounder/dds_output.rs
+++ b/src/hardware/pounder/dds_output.rs
@@ -55,7 +55,7 @@
use log::warn;
use stm32h7xx_hal as hal;
-use super::{hrtimer::HighResTimerE, QspiInterface};
+use super::{hrtimer::HighResTimerE, Profile, QspiInterface};
use ad9959::{Channel, Mode, ProfileSerializer};
/// The DDS profile update stream.
@@ -157,6 +157,46 @@ impl<'a> ProfileBuilder<'a> {
self
}
+ /// Update a number of channels with fully defined profile settings.
+ ///
+ /// # Args
+ /// * `channels` - A set of channels to apply the configuration to.
+ /// * `profile` - The complete DDS profile, which defines the frequency tuning word,
+ /// amplitude control register & the phase offset word of the channels.
+ /// # Note
+ /// The ACR should be stored in the 3 LSB of the word.
+ /// If amplitude scaling is to be used, the "Amplitude multiplier enable" bit must be set.
+ #[inline]
+ pub fn update_channels_with_profile(
+ &mut self,
+ channels: Channel,
+ profile: Profile,
+ ) -> &mut Self {
+ self.serializer.update_channels(
+ channels,
+ Some(profile.frequency_tuning_word),
+ Some(profile.phase_offset),
+ Some(profile.amplitude_control),
+ );
+ self
+ }
+
+ /// Update the system clock configuration.
+ ///
+ /// # Args
+ /// * `reference_clock_frequency` - The reference clock frequency provided to the AD9959 core.
+ /// * `multiplier` - The frequency multiplier of the system clock. Must be 1 or 4-20.
+ #[inline]
+ pub fn set_system_clock(
+ &mut self,
+ reference_clock_frequency: f32,
+ multiplier: u8,
+ ) -> Result<&mut Self, ad9959::Error> {
+ self.serializer
+ .set_system_clock(reference_clock_frequency, multiplier)?;
+ Ok(self)
+ }
+
/// Write the profile to the DDS asynchronously.
#[allow(dead_code)]
#[inline]
diff --git a/src/hardware/pounder/mod.rs b/src/hardware/pounder/mod.rs
index 5bc7e9ff..5b8d5d30 100644
--- a/src/hardware/pounder/mod.rs
+++ b/src/hardware/pounder/mod.rs
@@ -1,10 +1,17 @@
use self::attenuators::AttenuatorInterface;
use super::hal;
-use crate::hardware::{shared_adc::AdcChannel, I2c1Proxy};
+use crate::hardware::{setup, shared_adc::AdcChannel, I2c1Proxy};
+use crate::net::telemetry::PounderTelemetry;
+use ad9959::{
+ amplitude_to_acr, frequency_to_ftw, phase_to_pow, validate_clocking,
+};
use embedded_hal::blocking::spi::Transfer;
use enum_iterator::Sequence;
+use miniconf::Tree;
+use rf_power::PowerMeasurementInterface;
use serde::{Deserialize, Serialize};
+use stm32h7xx_hal::time::MegaHertz;
pub mod attenuators;
pub mod dds_output;
@@ -120,40 +127,99 @@ impl From<Channel> for GpioPin {
}
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct DdsChannelState {
- pub phase_offset: f32,
+#[derive(Serialize, Deserialize, Copy, Clone, Debug, Tree)]
+pub struct DdsChannelConfig {
pub frequency: f32,
+ pub phase_offset: f32,
pub amplitude: f32,
- pub enabled: bool,
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct ChannelState {
- pub parameters: DdsChannelState,
- pub attenuation: f32,
+impl Default for DdsChannelConfig {
+ fn default() -> Self {
+ Self {
+ frequency: 0.0,
+ phase_offset: 0.0,
+ amplitude: 0.0,
+ }
+ }
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct InputChannelState {
- pub attenuation: f32,
- pub power: f32,
- pub mixer: DdsChannelState,
+/// Represents a fully defined DDS profile, with parameters expressed in machine units
+pub struct Profile {
+ /// A 32-bits representation of DDS frequency in relation to the system clock frequency.
+ /// This value corresponds to the AD9959 CFTW0 register, which specifies the frequency
+ /// of DDS channels.
+ pub frequency_tuning_word: u32,
+ /// The DDS phase offset. It corresponds to the AD9959 CPOW0 register, which specifies
+ /// the phase offset of DDS channels.
+ pub phase_offset: u16,
+ /// Control amplitudes of DDS channels. It corresponds to the AD9959 ACR register, which
+ /// controls the amplitude scaling factor of DDS channels.
+ pub amplitude_control: u32,
+}
+
+impl TryFrom<(ClockConfig, ChannelConfig)> for Profile {
+ type Error = ad9959::Error;
+
+ fn try_from(
+ (clocking, channel): (ClockConfig, ChannelConfig),
+ ) -> Result<Self, Self::Error> {
+ let system_clock_frequency =
+ clocking.reference_clock * clocking.multiplier as f32;
+ Ok(Profile {
+ frequency_tuning_word: frequency_to_ftw(
+ channel.dds.frequency,
+ system_clock_frequency,
+ )?,
+ phase_offset: phase_to_pow(channel.dds.phase_offset)?,
+ amplitude_control: amplitude_to_acr(channel.dds.amplitude)?,
+ })
+ }
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct OutputChannelState {
+#[derive(Serialize, Deserialize, Copy, Clone, Debug, Tree)]
+pub struct ChannelConfig {
+ #[tree]
+ pub dds: DdsChannelConfig,
pub attenuation: f32,
- pub channel: DdsChannelState,
}
-#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
-pub struct DdsClockConfig {
+impl Default for ChannelConfig {
+ fn default() -> Self {
+ ChannelConfig {
+ dds: DdsChannelConfig::default(),
+ attenuation: 31.5,
+ }
+ }
+}
+
+#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Tree)]
+pub struct ClockConfig {
pub multiplier: u8,
pub reference_clock: f32,
pub external_clock: bool,
}
+impl Default for ClockConfig {
+ fn default() -> Self {
+ Self {
+ multiplier: 5,
+ reference_clock: MegaHertz::MHz(100).to_Hz() as f32,
+ external_clock: false,
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, Default, Deserialize, Serialize, Tree)]
+pub struct PounderConfig {
+ #[tree]
+ pub clock: ClockConfig,
+ #[tree(depth = 2)]
+ pub in_channel: [ChannelConfig; 2],
+ #[tree(depth = 2)]
+ pub out_channel: [ChannelConfig; 2],
+}
+
impl From<Channel> for ad9959::Channel {
/// Translate pounder channels to DDS output channels.
fn from(other: Channel) -> Self {
@@ -585,3 +651,78 @@ impl rf_power::PowerMeasurementInterface for PounderDevices {
Ok(adc_scale * 2.048)
}
}
+
+impl setup::PounderDevices {
+ pub fn update_dds(
+ &mut self,
+ settings: PounderConfig,
+ clocking: &mut ClockConfig,
+ ) {
+ if *clocking != settings.clock {
+ match validate_clocking(
+ settings.clock.reference_clock,
+ settings.clock.multiplier,
+ ) {
+ Ok(_frequency) => {
+ self.pounder
+ .set_ext_clk(settings.clock.external_clock)
+ .unwrap();
+
+ self.dds_output
+ .builder()
+ .set_system_clock(
+ settings.clock.reference_clock,
+ settings.clock.multiplier,
+ )
+ .unwrap()
+ .write();
+
+ *clocking = settings.clock;
+ }
+ Err(err) => {
+ log::error!("Invalid AD9959 clocking parameters: {:?}", err)
+ }
+ }
+ }
+
+ for (channel_config, pounder_channel) in settings
+ .in_channel
+ .iter()
+ .chain(settings.out_channel.iter())
+ .zip([Channel::In0, Channel::In1, Channel::Out0, Channel::Out1])
+ {
+ match Profile::try_from((*clocking, *channel_config)) {
+ Ok(dds_profile) => {
+ self.dds_output
+ .builder()
+ .update_channels_with_profile(
+ pounder_channel.into(),
+ dds_profile,
+ )
+ .write();
+
+ if let Err(err) = self.pounder.set_attenuation(
+ pounder_channel,
+ channel_config.attenuation,
+ ) {
+ log::error!("Invalid attenuation settings: {:?}", err)
+ }
+ }
+ Err(err) => {
+ log::error!("Invalid AD9959 profile settings: {:?}", err)
+ }
+ }
+ }
+ }
+
+ pub fn get_telemetry(&mut self, config: PounderConfig) -> PounderTelemetry {
+ PounderTelemetry {
+ temperature: self.pounder.lm75.read_temperature().unwrap(),
+ input_power: [
+ self.pounder.measure_power(Channel::In0).unwrap(),
+ self.pounder.measure_power(Channel::In1).unwrap(),
+ ],
+ config,
+ }
+ }
+}
diff --git a/src/net/data_stream.rs b/src/net/data_stream.rs
index 714ec57f..d442f197 100644
--- a/src/net/data_stream.rs
+++ b/src/net/data_stream.rs
@@ -25,7 +25,7 @@
#![allow(non_camel_case_types)] // https://github.com/rust-embedded/heapless/issues/411
-use core::{fmt::Write, mem::MaybeUninit};
+use core::{fmt::Write, mem::{MaybeUninit, size_of_val}};
use heapless::{
box_pool,
pool::boxed::{Box, BoxBlock},
diff --git a/src/net/mod.rs b/src/net/mod.rs
index 43733fa8..a8b90f86 100644
--- a/src/net/mod.rs
+++ b/src/net/mod.rs
@@ -32,14 +32,14 @@ pub type NetworkReference =
pub struct MqttStorage {
telemetry: [u8; 2048],
- settings: [u8; 1024],
+ settings: [u8; 1536],
}
impl Default for MqttStorage {
fn default() -> Self {
Self {
telemetry: [0u8; 2048],
- settings: [0u8; 1024],
+ settings: [0u8; 1536],
}
}
}
diff --git a/src/net/telemetry.rs b/src/net/telemetry.rs
index c8eb536b..116382a3 100644
--- a/src/net/telemetry.rs
+++ b/src/net/telemetry.rs
@@ -16,7 +16,7 @@ use minimq::{DeferredPublication, Publication};
use serde::Serialize;
use super::NetworkReference;
-use crate::hardware::{adc::AdcCode, afe::Gain, dac::DacCode, SystemTimer};
+use crate::hardware::{adc::AdcCode, afe::Gain, dac::DacCode, SystemTimer, pounder::PounderConfig};
/// Default metadata message if formatting errors occur.
const DEFAULT_METADATA: &str = "{\"message\":\"Truncated: See USB terminal\"}";
@@ -68,6 +68,26 @@ pub struct Telemetry {
/// The CPU temperature in degrees Celsius.
pub cpu_temp: f32,
+
+ /// Measurements related to Pounder
+ pub pounder: Option<PounderTelemetry>,
+}
+
+/// The structure that holds the telemetry related to Pounder.
+///
+/// # Note
+/// This structure should be generated on-demand by the buffer when required to minimize conversion
+/// overhead.
+#[derive(Copy, Clone, Serialize)]
+pub struct PounderTelemetry {
+ /// The Pounder temperature in degrees Celsius
+ pub temperature: f32,
+
+ /// The detected RF power into IN channels
+ pub input_power: [f32; 2],
+
+ /// The configuration of the clock and DDS channels
+ pub config: PounderConfig,
}
impl Default for TelemetryBuffer {
@@ -87,10 +107,17 @@ impl TelemetryBuffer {
/// * `afe0` - The current AFE configuration for channel 0.
/// * `afe1` - The current AFE configuration for channel 1.
/// * `cpu_temp` - The current CPU temperature.
+ /// * `pounder` - The current Pounder telemetry.
///
/// # Returns
/// The finalized telemetry structure that can be serialized and reported.
- pub fn finalize(self, afe0: Gain, afe1: Gain, cpu_temp: f32) -> Telemetry {
+ pub fn finalize(
+ self,
+ afe0: Gain,
+ afe1: Gain,
+ cpu_temp: f32,
+ pounder: Option<PounderTelemetry>,
+ ) -> Telemetry {
let in0_volts = Into::<f32>::into(self.adcs[0]) / afe0.as_multiplier();
let in1_volts = Into::<f32>::into(self.adcs[1]) / afe1.as_multiplier();
@@ -99,6 +126,7 @@ impl TelemetryBuffer {
adcs: [in0_volts, in1_volts],
dacs: [self.dacs[0].into(), self.dacs[1].into()],
digital_inputs: self.digital_inputs,
+ pounder,
}
}
}

View File

@ -0,0 +1,54 @@
{ config, pkgs, lib, ... }:
with lib;
let
makeBackup = pkgs.writeScript "make-backup" ''
#!${pkgs.bash}/bin/bash
set -e
umask 0077
DBDUMPDIR=`mktemp -d`
pushd $DBDUMPDIR
${config.services.mysql.package}/bin/mysqldump --single-transaction flarum > flarum.sql
${pkgs.sudo}/bin/sudo -u mattermost ${config.services.postgresql.package}/bin/pg_dump mattermost > mattermost.sql
${pkgs.gnutar}/bin/tar cf - --exclude "/var/lib/gitea/repositories/*/*.git/archives" /etc/nixos /var/lib/gitea flarum.sql mattermost.sql | \
${pkgs.bzip2}/bin/bzip2 | \
${pkgs.gnupg}/bin/gpg --symmetric --batch --passphrase-file /etc/nixos/secret/backup-passphrase | \
${pkgs.rclone}/bin/rclone rcat --config /etc/nixos/secret/rclone.conf dropbox:backup-`date +%F`.tar.bz2.gpg
popd
rm -rf $DBDUMPDIR
echo Backup done
'';
cfg = config.services.mlabs-backup;
in
{
options.services.mlabs-backup = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable backups";
};
};
config = mkIf cfg.enable {
systemd.services.mlabs-backup = {
description = "M-Labs backup";
serviceConfig = {
Type = "oneshot";
User = "root";
Group = "root";
ExecStart = "${makeBackup}";
};
};
systemd.timers.mlabs-backup = {
description = "M-Labs backup";
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "weekly";
};
};
}

View File

@ -0,0 +1,566 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
let
netifWan = "enp0s31f6";
netifLan = "enp3s0";
netifWifi = "wlp4s0";
netifSit = "henet0";
hydraWwwOutputs = "/var/www/hydra-outputs";
in
{
imports =
[
./hardware-configuration.nix
./homu/nixos-module.nix
./backup-module.nix
(builtins.fetchTarball {
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/v2.2.1/nixos-mailserver-v2.2.1.tar.gz";
sha256 = "03d49v8qnid9g9rha0wg2z6vic06mhp0b049s3whccn1axvs2zzx";
})
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
security.apparmor.enable = true;
security.pam.yubico = {
enable = true;
id = "49094";
control = "required";
};
networking = {
hostName = "nixbld";
firewall = {
allowedTCPPorts = [ 80 443 ];
allowedUDPPorts = [ 53 67 ];
trustedInterfaces = [ netifLan ];
};
interfaces."${netifLan}" = {
ipv4.addresses = [{
address = "192.168.1.1";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "2001:470:f821:1::";
prefixLength = 64;
}];
};
interfaces."${netifWifi}" = {
ipv4.addresses = [{
address = "192.168.12.1";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "2001:470:f821:2::";
prefixLength = 64;
}];
};
nat = {
enable = true;
externalInterface = netifWan;
internalInterfaces = [ netifLan netifWifi ];
extraCommands = ''
iptables -w -N block-lan-from-wifi
iptables -w -A block-lan-from-wifi -i ${netifLan} -o ${netifWifi} -j DROP
iptables -w -A block-lan-from-wifi -i ${netifWifi} -o ${netifLan} -j DROP
iptables -w -A FORWARD -j block-lan-from-wifi
'';
extraStopCommands = ''
iptables -w -D FORWARD -j block-lan-from-wifi 2>/dev/null|| true
iptables -w -F block-lan-from-wifi 2>/dev/null|| true
iptables -w -X block-lan-from-wifi 2>/dev/null|| true
'';
};
sits."${netifSit}" = {
dev = netifWan;
remote = "216.218.221.6";
local = "42.200.147.171";
ttl = 255;
};
interfaces."${netifSit}".ipv6 = {
addresses = [{ address = "2001:470:18:629::2"; prefixLength = 64; }];
routes = [{ address = "::"; prefixLength = 0; }];
};
};
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = "1";
boot.kernel.sysctl."net.ipv6.conf.default.forwarding" = "1";
services.hostapd = {
enable = true;
interface = netifWifi;
hwMode = "g";
ssid = "M-Labs";
wpaPassphrase = (import /etc/nixos/secret/wifi_password.nix);
};
services.dnsmasq = {
enable = true;
extraConfig = ''
interface=${netifLan}
interface=${netifWifi}
bind-interfaces
dhcp-range=interface:${netifLan},192.168.1.81,192.168.1.254,24h
dhcp-range=interface:${netifWifi},192.168.12.10,192.168.12.254,24h
enable-ra
dhcp-range=interface:${netifLan},::,constructor:${netifLan},ra-names
dhcp-range=interface:${netifWifi},::,constructor:${netifWifi},ra-only
# Default IP addresses for ARTIQ boards
address=/thermostat/192.168.1.26
address=/kc705/192.168.1.50
address=/zc706/192.168.1.51
address=/sayma/192.168.1.60
address=/kasli/192.168.1.70
# uTCA MCH from NAT
address=/tschernobyl/192.168.1.80
'';
};
# Select internationalisation properties.
i18n = {
consoleFont = "Lat2-Terminus16";
consoleKeyMap = "de";
defaultLocale = "en_US.UTF-8";
};
# Set your time zone.
time.timeZone = "Asia/Hong_Kong";
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
wget vim git file lm_sensors acpi pciutils psmisc xc3sprog openocd gdb telnet whois zip unzip nixops
irssi tmux adoptopenjdk-openj9-bin-11 tigervnc xorg.xauth icewm xterm xorg.xsetroot usbutils imagemagick jq
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = { enable = true; enableSSHSupport = true; };
# List services that you want to enable:
services.apcupsd.enable = true;
services.apcupsd.configText = ''
UPSTYPE usb
NISIP 127.0.0.1
BATTERYLEVEL 10
MINUTES 5
'';
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.openssh.forwardX11 = true;
programs.mosh.enable = true;
programs.fish.enable = true;
# Enable CUPS to print documents.
services.avahi.enable = true;
services.avahi.interfaces = [ netifLan ];
services.avahi.publish.enable = true;
services.avahi.publish.userServices = true;
nixpkgs.config.allowUnfree = true;
services.printing.enable = true;
services.printing.drivers = [ pkgs.hplipWithPlugin ];
services.printing.browsing = true;
services.printing.listenAddresses = [ "*:631" ];
services.printing.defaultShared = true;
hardware.sane.enable = true;
hardware.sane.extraBackends = [ pkgs.hplipWithPlugin ];
users.extraGroups.plugdev = { };
users.extraUsers.sb = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout" "lp" "scanner"];
shell = pkgs.fish;
};
users.extraUsers.rj = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout"];
};
users.extraUsers.astro = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
};
users.extraUsers.whitequark = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
};
users.extraUsers.nix = {
isNormalUser = true;
};
security.sudo.wheelNeedsPassword = false;
security.hideProcessInformation = true;
boot.kernel.sysctl."kernel.dmesg_restrict" = true;
services.udev.packages = [ pkgs.openocd pkgs.sane-backends ];
services.udev.extraRules = ''
ACTION=="add", SUBSYSTEM=="tty", \
ENV{ID_SERIAL}=="FTDI_Quad_RS232-HS", \
ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:5:1.1", \
SYMLINK+="ttyUSB_sayma-1_0"
ACTION=="add", SUBSYSTEM=="tty", \
ENV{ID_SERIAL}=="FTDI_Quad_RS232-HS", \
ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:5:1.2", \
SYMLINK+="ttyUSB_sayma-1_1"
ACTION=="add", SUBSYSTEM=="tty", \
ENV{ID_SERIAL}=="FTDI_Quad_RS232-HS", \
ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:1:1.2", \
SYMLINK+="ttyUSB_kasli-n1"
'';
nix.distributedBuilds = true;
nix.buildMachines = [
{
hostName = "localhost";
maxJobs = 4;
system = "x86_64-linux";
supportedFeatures = ["big-parallel"];
}
{
hostName = "rpi-3";
sshUser = "nix";
sshKey = "/etc/nixos/secret/nix_id_rsa";
maxJobs = 1;
system = "aarch64-linux";
}
];
services.hydra = {
enable = true;
useSubstitutes = true;
hydraURL = "https://nixbld.m-labs.hk";
notificationSender = "hydra@m-labs.hk";
minimumDiskFree = 15; # in GB
minimumDiskFreeEvaluator = 1;
extraConfig =
''
binary_cache_secret_key_file = /etc/nixos/secret/nixbld.m-labs.hk-1
max_output_size = 10000000000
<runcommand>
job = web:web:web
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/web
</runcommand>
<runcommand>
job = artiq:full:artiq-manual-html
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-html-beta
</runcommand>
<runcommand>
job = artiq:full:artiq-manual-latexpdf
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-manual-latexpdf-beta
</runcommand>
<runcommand>
job = artiq:full:conda-channel
command = [ $(jq '.buildStatus' < $HYDRA_JSON) = 0 ] && ln -sfn $(jq -r '.outputs[0].path' < $HYDRA_JSON) ${hydraWwwOutputs}/artiq-conda-channel-beta
</runcommand>
'';
};
systemd.services.hydra-www-outputs-init = {
description = "Set up a hydra-owned directory for build outputs";
wantedBy = [ "multi-user.target" ];
requiredBy = [ "hydra-queue-runner.service" ];
before = [ "hydra-queue-runner.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = [ "${pkgs.coreutils}/bin/mkdir -p ${hydraWwwOutputs}" "${pkgs.coreutils}/bin/chown hydra-queue-runner:hydra ${hydraWwwOutputs}" ];
};
};
nix.extraOptions = ''
secret-key-files = /etc/nixos/secret/nixbld.m-labs.hk-1
'';
nix.sandboxPaths = ["/opt"];
services.munin-node.enable = true;
services.munin-cron = {
enable = true;
hosts = ''
[${config.networking.hostName}]
address localhost
'';
};
services.mlabs-backup.enable = true;
services.gitea = {
enable = true;
httpPort = 3001;
rootUrl = "https://git.m-labs.hk/";
appName = "M-Labs Git";
cookieSecure = true;
disableRegistration = true;
extraConfig =
''
[attachment]
ALLOWED_TYPES = */*
'';
};
services.mattermost = {
enable = true;
siteUrl = "https://chat.m-labs.hk/";
mutableConfig = true;
};
services.matterbridge = {
enable = true;
configPath = "/etc/nixos/secret/matterbridge.toml";
};
nixpkgs.config.packageOverrides = super: let self = super.pkgs; in {
hydra = super.hydra.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./hydra-conda.patch ./hydra-retry.patch ];
hydraPath = oa.hydraPath + ":" + super.lib.makeBinPath [ super.jq ];
});
matterbridge = super.matterbridge.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./matterbridge-disable-github.patch ];
});
nixops = super.nixops.overrideAttrs(oa: {
patches = oa.patches or [] ++ [ ./nixops-665.patch ];
});
};
security.acme.certs = {
"nixbld.m-labs.hk" = {
webroot = "/var/lib/acme/acme-challenge";
extraDomains = {
"m-labs.hk" = null;
"www.m-labs.hk" = null;
"conda.m-labs.hk" = null;
"lab.m-labs.hk" = null;
"git.m-labs.hk" = null;
"chat.m-labs.hk" = null;
"hooks.m-labs.hk" = null;
"forum.m-labs.hk" = null;
"perso.m-labs.hk" = null;
"openhardware.hk" = null;
"git.openhardware.hk" = null;
};
};
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedGzipSettings = true;
virtualHosts = let
mainWebsite = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "${hydraWwwOutputs}/web";
extraConfig = ''
error_page 404 /404.html;
'';
locations."^~ /fonts/".extraConfig = ''
expires 60d;
'';
locations."^~ /js/".extraConfig = ''
expires 60d;
'';
locations."/MathJax/" = {
alias = "/var/www/MathJax/";
extraConfig = ''
expires 60d;
'';
};
# legacy URLs, redirect to avoid breaking people's bookmarks
locations."/gateware.html".extraConfig = ''
return 301 /gateware/migen/;
'';
locations."/migen".extraConfig = ''
return 301 /gateware/migen/;
'';
locations."/artiq".extraConfig = ''
return 301 /experiment-control/artiq/;
'';
locations."/artiq/resources.html".extraConfig = ''
return 301 /experiment-control/resources/;
'';
# autogenerated ARTIQ manuals
locations."/artiq/manual-beta/" = {
alias = "${hydraWwwOutputs}/artiq-manual-html-beta/share/doc/artiq-manual/html/";
};
locations."=/artiq/manual-beta.pdf" = {
alias = "${hydraWwwOutputs}/artiq-manual-latexpdf-beta/share/doc/artiq-manual/ARTIQ.pdf";
};
# legacy content
locations."/migen/manual/" = {
alias = "/var/www/m-labs.hk.old/migen/manual/";
};
locations."/artiq/manual/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-4/";
};
locations."/artiq/manual-release-4/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-4/";
};
locations."/artiq/manual-release-3/" = {
alias = "/var/www/m-labs.hk.old/artiq/manual-release-3/";
};
};
in {
"m-labs.hk" = mainWebsite;
"www.m-labs.hk" = mainWebsite;
"lab.m-labs.hk" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/munin/".alias = "/var/www/munin/";
locations."/munin".extraConfig = ''
auth_basic "Munin";
auth_basic_user_file /etc/nixos/secret/muninpasswd;
'';
locations."/homu/".proxyPass = "http://127.0.0.1:54856/";
};
"nixbld.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3000";
};
"conda.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/artiq-beta/" = {
alias = "${hydraWwwOutputs}/artiq-conda-channel-beta/";
extraConfig = ''
autoindex on;
index bogus_index_file;
'';
};
};
"git.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3001";
extraConfig = ''
client_max_body_size 300M;
'';
};
"chat.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:8065";
locations."~ /api/v[0-9]+/(users/)?websocket$".proxyPass = "http://127.0.0.1:8065";
locations."~ /api/v[0-9]+/(users/)?websocket$".proxyWebsockets = true;
};
"hooks.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".extraConfig = ''
include ${pkgs.nginx}/conf/uwsgi_params;
uwsgi_pass unix:${config.services.uwsgi.runDir}/uwsgi.sock;
'';
};
"forum.m-labs.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "/var/www/flarum/public";
locations."~ \.php$".extraConfig = ''
fastcgi_pass unix:${config.services.phpfpm.pools.flarum.socket};
fastcgi_index index.php;
'';
extraConfig = ''
index index.php;
include /var/www/flarum/.nginx.conf;
'';
};
"perso.m-labs.hk" = {
addSSL = true;
useACMEHost = "nixbld.m-labs.hk";
root = "/var/www/perso";
};
"git.openhardware.hk" = {
forceSSL = true;
useACMEHost = "nixbld.m-labs.hk";
locations."/".proxyPass = "http://127.0.0.1:3002";
extraConfig = ''
client_max_body_size 300M;
'';
};
};
};
services.uwsgi = {
enable = true;
plugins = [ "python3" ];
instance = {
type = "emperor";
vassals = {
mattermostgithub = import ./mattermost-github-integration/uwsgi-config.nix { inherit config pkgs; };
};
};
};
services.mysql = {
enable = true;
package = pkgs.mariadb;
};
services.phpfpm.pools.flarum = {
user = "nobody";
settings = {
"listen.owner" = "nginx";
"listen.group" = "nginx";
"listen.mode" = "0600";
"pm" = "dynamic";
"pm.max_children" = 5;
"pm.start_servers" = 2;
"pm.min_spare_servers" = 1;
"pm.max_spare_servers" = 3;
"pm.max_requests" = 500;
};
};
services.homu = {
enable = true;
config = "/etc/nixos/secret/homu.toml";
};
mailserver = {
enable = true;
localDnsResolver = false; # conflicts with dnsmasq
# Some mail servers do reverse DNS lookups to filter spam.
# Getting a proper reverse DNS record from ISP is difficult, so use whatever already exists.
fqdn = "42-200-147-171.static.imsbiz.com";
domains = [ "nmigen.org" ];
loginAccounts = (import /etc/nixos/secret/email_accounts.nix);
certificateScheme = 3;
};
security.acme.certs."${config.mailserver.fqdn}".extraDomains = {
"mail.nmigen.org" = null;
};
containers.openhardwarehk = {
autoStart = true;
config =
{ config, pkgs, ... }:
{
services.gitea = {
enable = true;
httpPort = 3002;
rootUrl = "https://git.openhardware.hk/";
appName = "Open Hardware HK";
cookieSecure = true;
disableRegistration = true;
extraConfig =
''
[attachment]
ALLOWED_TYPES = */*
'';
};
};
};
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "18.09"; # Did you read the comment?
}

View File

@ -0,0 +1,13 @@
diff --git a/homu/git_helper.py b/homu/git_helper.py
index 0f70c69..f53fb57 100755
--- a/homu/git_helper.py
+++ b/homu/git_helper.py
@@ -7,7 +7,7 @@ SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), '../cache/key')
def main():
- args = ['ssh', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
+ args = ['ssh', '-o', 'StrictHostKeyChecking=no', '-i', SSH_KEY_FILE, '-S', 'none'] + sys.argv[1:]
os.execvp('ssh', args)

View File

@ -0,0 +1,52 @@
{ config, pkgs, lib, ... }:
with lib;
let
homu = pkgs.callPackage ./pkg.nix {};
cfg = config.services.homu;
in
{
options.services.homu = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the bot";
};
dbDir = mkOption {
type = types.str;
default = "/var/db/homu";
description = "Path to the database file (use the same path in config.toml)";
};
config = mkOption {
description = "Location of config.toml";
type = types.str;
};
};
config = mkIf cfg.enable {
users.users.homu = {
group = "homu";
home = cfg.dbDir;
createHome = true;
};
users.groups.homu = {};
systemd.services.homu = {
description = "Homu bot";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${homu}/bin/homu -c ${cfg.config}";
Restart = "always";
RestartSec = "5sec";
User = "homu";
Group = "homu";
};
};
};
}

View File

@ -0,0 +1,26 @@
diff --git a/homu/git_helper.py b/homu/git_helper.py
index 0f70c69..732230c 100755
--- a/homu/git_helper.py
+++ b/homu/git_helper.py
@@ -3,7 +3,7 @@
import sys
import os
-SSH_KEY_FILE = os.path.join(os.path.dirname(__file__), '../cache/key')
+SSH_KEY_FILE = os.path.expanduser("~/cache/key")
def main():
diff --git a/homu/main.py b/homu/main.py
index 16b60a2..a2e109a 100644
--- a/homu/main.py
+++ b/homu/main.py
@@ -649,7 +649,7 @@ def git_push(git_cmd, branch, state):
def init_local_git_cmds(repo_cfg, git_cfg):
- fpath = 'cache/{}/{}'.format(repo_cfg['owner'], repo_cfg['name'])
+ fpath = '{}/cache/{}/{}'.format(os.path.expanduser("~"), repo_cfg['owner'], repo_cfg['name'])
url = 'git@github.com:{}/{}.git'.format(repo_cfg['owner'], repo_cfg['name']) # noqa
if not os.path.exists(SSH_KEY_FILE):

View File

@ -0,0 +1,34 @@
{ python3Packages, python3, fetchFromGitHub, git, openssh }:
let
uritemplate_0_2_0 = python3Packages.github3_py.overrideAttrs(oa: rec {
version = "0.2.0";
src = python3Packages.fetchPypi {
pname = "uritemplate.py";
inherit version;
sha256 = "1pfk04pmnysz0383lwzgig8zqlwiv2n4pmq51f0mc60zz1jimq4g";
};
});
github3_py_0_9_6 = python3Packages.github3_py.overrideAttrs(oa: rec {
version = "0.9.6";
src = python3Packages.fetchPypi {
pname = "github3.py";
inherit version;
sha256 = "1i8xnh586z4kka7pjl7cy08fmzjs14c8jdp8ykb9jjpzsy2xncdq";
};
propagatedBuildInputs = [ python3Packages.requests uritemplate_0_2_0 ];
});
in
python3Packages.buildPythonApplication {
name = "homu";
src = fetchFromGitHub {
owner = "servo";
repo = "homu";
rev = "2ea53e76ebac3e5fa11bc39054b3cd4c42eff607";
sha256 = "1ih7s8zfbpq0qb9vqbxzr0r4s9ff52l4ipr916kwbck3ygliq3r9";
};
patches = [ ./patch-cache-directory.patch ./disable-ssh-host-keycheck.patch ];
postInstall = "chmod 755 $out/${python3.sitePackages}/homu/git_helper.py";
propagatedBuildInputs = [ github3_py_0_9_6 git openssh ] ++ (with python3Packages; [ toml jinja2 requests bottle waitress retrying ]);
checkPhase = "python -m unittest discover tests -v";
}

View File

@ -0,0 +1,47 @@
commit 5aa5f8d5742883d41d7278a2c8bc2c9a2ddfef45
Author: Sebastien Bourdeauducq <sb@m-labs.hk>
Date: Sun Apr 14 18:25:27 2019 +0800
add SVG icon for conda package
diff --git a/src/root/product-list.tt b/src/root/product-list.tt
index 298d0a66..85914bbd 100644
--- a/src/root/product-list.tt
+++ b/src/root/product-list.tt
@@ -157,6 +157,11 @@
<img src="[% c.uri_for("/static/images/debian.png") %]" alt="DEB" />
</td>
<td>Debian package</td>
+ [% CASE "conda" %]
+ <td>
+ <img src="[% c.uri_for("/static/images/conda.svg") %]" width="32" height="32" alt="Conda" />
+ </td>
+ <td>Conda package</td>
[% CASE "iso" %]
<td>
<img src="[% c.uri_for("/static/images/iso.png") %]" alt="ISO" />
diff --git a/src/root/static/images/conda.svg b/src/root/static/images/conda.svg
new file mode 100644
index 00000000..67859731
--- /dev/null
+++ b/src/root/static/images/conda.svg
@@ -0,0 +1,18 @@
+<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g id="g2">
+ <g>
+ <path d="M118.89,75.13c-1.31-2.72-3.46-5.53-6.97-7.33c-2.37-1.48-4.57-2.24-6.01-2.63 c1.53-5.6-0.64-10.06-3.69-13.39c-4.53-4.88-9.27-5.59-9.27-5.59l-0.01,0c1.56-3.03,2.15-6.54,1.36-9.99 c-1-4.26-3.29-6.94-6.31-8.73c-3.09-1.83-6.91-2.73-10.83-3.43c-1.88-0.34-9.81-1.45-13.1-6c-2.65-3.69-2.73-10.33-3.45-12.32 c-0.77-2.05-3.38-1.15-6.23,0.76c-3.33,2.22-10.23,9.35-12.89,16.49c-2.03,5.47-2.08,10.21-1.28,13.89 c-3.29,0.55-5.76,1.66-6.23,1.88c-0.16,0.05-0.32,0.1-0.49,0.17c-3.01,1.24-9.43,7.02-10.01,15.85c-0.2,3.14,0.21,6.31,1.2,9.26 c-3.94,1.1-6.22,2.54-6.26,2.57c-2,0.75-5.18,2.95-6.15,4.13c-1.97,2.38-3.34,5.21-4.15,8.18C6.35,85.36,7,92.71,10.14,98.67 c1.74,3.31,4.12,6.83,6.74,9.52c8.55,8.79,23.31,12.11,34.96,14.03c14.19,2.34,29.05,1.52,42.33-3.97 c19.92-8.22,25.22-21.44,26-25.17C121.92,84.77,119.8,77,118.89,75.13z" style="fill:#865D53;"/>
+ <g>
+ <g>
+ <ellipse cx="85.95" cy="66.39" rx="16.61" ry="15.5" style="fill:#FFFFFF;" transform="matrix(0.1106 -0.9939 0.9939 0.1106 10.453 144.4706)"/>
+ <path d="M92.63,66.36c-0.23,3.3-3.14,5.82-6.49,5.62c-3.36-0.19-5.9-3.04-5.67-6.34 c0.22-3.31,3.12-5.82,6.48-5.62C90.31,60.21,92.86,63.06,92.63,66.36" style="fill:#2F2F2F;"/>
+ </g>
+ <g>
+ <ellipse cx="42.46" cy="66.4" rx="15.5" ry="16.61" style="fill:#FFFFFF;" transform="matrix(0.9972 -0.0752 0.0752 0.9972 -4.8714 3.3796)"/>
+ <path d="M49.02,65.13c0.38,3.29-2.01,6.3-5.34,6.72c-3.34,0.43-6.36-1.9-6.74-5.18 c-0.4-3.29,1.99-6.3,5.33-6.73C45.6,59.52,48.63,61.85,49.02,65.13" style="fill:#2F2F2F;"/>
+ </g>
+ </g>
+ <path d="M87.35,89.46c-2.22-1.5-5.02-0.51-7.49,0c-6.9,1.42-12.95,1.48-15.86,1.48 c-2.91,0-8.96-0.06-15.86-1.48c-2.47-0.51-5.27-1.5-7.49,0c-2.82,1.9-0.74,8.74,3.7,13.36c2.68,2.79,9.07,8.21,19.66,8.21 c10.58,0,16.97-5.42,19.66-8.21C88.09,98.2,90.17,91.37,87.35,89.46z" style="fill:#ED6D31;"/>
+ </g>
+ </g>
+</svg>
\ No newline at end of file

View File

@ -0,0 +1,19 @@
commit 86bf81c0b8a51bffa4b4b566e1caaac6f0e041d3
Author: Sebastien Bourdeauducq <sb@m-labs.hk>
Date: Thu Mar 14 17:45:32 2019 +0800
add option to disable retries on transient failures
diff --git a/src/hydra-queue-runner/build-remote.cc b/src/hydra-queue-runner/build-remote.cc
index 69c430eb..bdbc808d 100644
--- a/src/hydra-queue-runner/build-remote.cc
+++ b/src/hydra-queue-runner/build-remote.cc
@@ -344,7 +344,7 @@ void State::buildRemote(ref<Store> destStore,
break;
case BuildResult::TransientFailure:
result.stepStatus = bsFailed;
- result.canRetry = true;
+ result.canRetry = get(step->drv.env, "__hydraRetry", "1") == "1";
result.errorMsg = "";
break;
case BuildResult::TimedOut:

View File

@ -0,0 +1,14 @@
diff -Naur matterbridge-1.11.0.orig/bridge/mattermost/mattermost.go matterbridge-1.11.0/bridge/mattermost/mattermost.go
--- matterbridge-1.11.0.orig/bridge/mattermost/mattermost.go 2018-06-19 06:28:16.000000000 +0800
+++ matterbridge-1.11.0/bridge/mattermost/mattermost.go 2019-04-26 20:40:11.831475087 +0800
@@ -444,6 +444,10 @@
return true
}
+ if message.Username == "github" {
+ return true
+ }
+
// if the message has reactions don't repost it (for now, until we can correlate reaction with message)
if message.Post.HasReactions {
return true

View File

@ -0,0 +1,32 @@
{ fetchFromGitHub, python3Packages }:
with python3Packages;
buildPythonPackage rec {
pname = "mattermost-github-integration";
version = "0.0.0-unstable";
src = fetchFromGitHub {
owner = "softdevteam";
repo = "mattermost-github-integration";
rev = "master";
sha256 = "1hfvjaxjhliy8sv9j3616fkdwd2jqhfsj9ai7ggx88zhxknrfx85";
};
propagatedBuildInputs = [
appdirs
click
flask
itsdangerous
jinja2
markupsafe
olefile
packaging
pillow
pyparsing
requests
six
werkzeug
];
checkInputs = [
pytest
];
doCheck = true;
}

View File

@ -0,0 +1,15 @@
{ config, pkgs }:
let
pkg = pkgs.callPackage ./pkg.nix {};
in {
type = "normal";
pythonPackages = self: [ pkg ];
module = "mattermostgithub:app";
env = [
"MGI_CONFIG_FILE=${./../secret/mattermost-github-integration.py}"
];
socket = "${config.services.uwsgi.runDir}/uwsgi.sock";
# allow access from nginx
chmod-socket = 666;
}

View File

@ -0,0 +1,111 @@
From e2015bbfcbcf7594824755e39f838d7aab258b6e Mon Sep 17 00:00:00 2001
From: Graham Christensen <graham@grahamc.com>
Date: Sat, 13 May 2017 08:53:07 -0400
Subject: [PATCH] Support multiple versions of nixpkgs in one network
Having a machine named foo, described as:
foo = { # ...snipped...
deployment.nix_path.nixpkgs = (builtins.filterSource
(path: type: type != "directory" || baseNameOf path != ".git")
./../nixpkgs);
});
will have the custom nixpkgs set in the `NIX_PATH` as
`nixpkgs=path-to-custom-nixpkgs`.
Note this does not work with foo = { config, ... }: {... machines, but
having a second nix file in the network would work, and also:
let
canary = machine: {
deployment.nix_path.nixpkgs = (builtins.filterSource
(path: type: type != "directory" || baseNameOf path != ".git")
./../nixpkgs);
imports = [machine];
};
machine = { ... }: {
# your machine config
};
in {
machineA = machine;
machineB = canary machine;
}
Note that because this uses scopedImport, the nixops network and
machines may use `import <nixpkgs>` and have a consistent view of
nixpkgs.
---
nix/eval-machine-info.nix | 35 ++++++++++++++++++++++++++++++++---
nix/options.nix | 7 +++++++
2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix
index 503b4c25d..085452cd4 100644
--- a/nix/eval-machine-info.nix
+++ b/nix/eval-machine-info.nix
@@ -39,13 +39,42 @@ rec {
# Get the configuration of this machine from each network
# expression, attaching _file attributes so the NixOS module
# system can give sensible error messages.
+
modules =
concatMap (n: optional (hasAttr machineName n)
{ imports = [(getAttr machineName n)]; inherit (n) _file; })
networks;
- in
- { name = machineName;
- value = import <nixpkgs/nixos/lib/eval-config.nix> {
+
+ machineConfs =
+ concatMap (n: optional (hasAttr machineName n)
+ (getAttr machineName n))
+ networks;
+
+ nameToPath = attrs: name: {
+ prefix = name;
+ path = attrs."${name}";
+ };
+
+ attrsetToPaths = attrset: map (nameToPath attrset)
+ (builtins.attrNames attrset);
+
+ importSources =
+ (concatMap (module:
+ if (!builtins.isFunction module
+ && builtins.hasAttr "deployment" module)
+ && (builtins.hasAttr "nix_path" module.deployment)
+ then attrsetToPaths module.deployment.nix_path
+ else [])
+ machineConfs) ++ builtins.nixPath;
+
+ __nixPath = importSources;
+
+ machineImport = builtins.scopedImport {
+ inherit __nixPath;
+ };
+ in {
+ name = machineName;
+ value = machineImport <nixpkgs/nixos/lib/eval-config.nix> {
modules =
modules ++
defaults ++
diff --git a/nix/options.nix b/nix/options.nix
index 0866c3ab8..117b44a7b 100644
--- a/nix/options.nix
+++ b/nix/options.nix
@@ -103,6 +103,13 @@ in
'';
};
+ deployment.nix_path = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ description = ''
+ '';
+ };
+
deployment.hasFastConnection = mkOption {
default = false;
type = types.bool;

View File

@ -0,0 +1,93 @@
{ config, pkgs, lib, ... }:
with lib;
let
notifico = (pkgs.callPackage ./pkg.nix {})
.overrideAttrs (attrs: {
buildInputs = attrs.buildInputs ++ [ pkgs.makeWrapper ];
# Extend the module path so that local_config.py can be found
postInstall = ''
${attrs.postInstall}
wrapProgram $out/bin/notifico \
--set PYTHONPATH "$${PYTHONPATH}:${cfg.dbDir}"
'';
});
cfg = config.services.notifico;
in
{
options.services.notifico = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the commit notification service";
};
enableLocalRedis = mkOption {
type = types.bool;
default = true;
description = "Enable a local Redis server";
};
dbDir = mkOption {
type = types.str;
default = "/var/db/notifico";
description = "Home directory and location of the database file";
};
config = mkOption {
description = "Path to local_config.py, https://github.com/notifico/notifico/raw/master/notifico/config.py";
type = types.str;
};
};
config = mkIf cfg.enable {
users.users.notifico = {
group = "notifico";
home = cfg.dbDir;
createHome = true;
};
users.groups.notifico = {};
services.redis = mkIf cfg.enableLocalRedis {
enable = true;
bind = "127.0.0.1";
};
systemd.services =
let
User = "notifico";
Group = "notifico";
WorkingDirectory = "${cfg.dbDir}";
ExecStartPre = [
"${pkgs.coreutils}/bin/rm -f local_config.pyc"
"${pkgs.coreutils}/bin/ln -sf ${cfg.config} local_config.py"
];
notifico-init = {
description = "Notifico initialization";
serviceConfig = {
inherit User Group WorkingDirectory ExecStartPre;
Type = "oneshot";
ExecStart = "${notifico}/bin/notifico init";
};
};
notificoService = component: {
description = "Notifico ${component}";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "notifico-init.service" ];
requires = [ "notifico-init.service" ];
serviceConfig = {
inherit User Group WorkingDirectory ExecStartPre;
Type = "simple";
ExecStart = "${notifico}/bin/notifico ${component}";
Restart = "always";
RestartSec = "5sec";
};
};
in {
inherit notifico-init;
notifico-www = notificoService "www";
notifico-worker = notificoService "worker";
notifico-bots = notificoService "bots";
};
};
}

View File

@ -0,0 +1,107 @@
{ python2Packages, python2, fetchFromGitHub, fetchurl }:
let
Flask-Gravatar = python2Packages.buildPythonPackage {
name = "Flask-Gravatar";
src = python2Packages.fetchPypi {
pname = "Flask-Gravatar";
version = "0.5.0";
sha256 = "1qb2ylirjajdqsmldhwfdhf8i86k7vlh3y4gnqfqj4n6q8qmyrk0";
};
propagatedBuildInputs = with python2Packages; [
pytestrunner
flask
];
checkInputs = with python2Packages; [
check-manifest
coverage
isort
pydocstyle
pytestcache
pytestcov
pytestpep8
pytest
pygments
];
};
utopia = python2Packages.buildPythonPackage {
name = "utopia";
src = fetchFromGitHub {
owner = "notifico";
repo = "utopia";
rev = "70293ed5e1ca55232e0fae71061e7e9b9b29be6f";
sha256 = "11cnh9l4d9jlhafnfis9si6kgk9zsdd5439qnhxh6dca3x4a986q";
};
propagatedBuildInputs = with python2Packages; [
gevent
blinker
];
doCheck = false;
};
Flask-WTF = python2Packages.flask_wtf.overrideAttrs(oa: rec {
version = "0.8.4";
src = python2Packages.fetchPypi {
pname = "Flask-WTF";
inherit version;
sha256 = "1khbwmlrcnk9f46f7kf531n06pkyfs6nc8fk273js9mj2igngg2y";
};
});
Flask-XML-RPC = python2Packages.flask_wtf.overrideAttrs(oa: rec {
version = "0.1.2";
src = python2Packages.fetchPypi {
pname = "Flask-XML-RPC";
inherit version;
sha256 = "1dwalj7pc5iid9l1k50q5mllirnn9f5s7jq54a66x48a4j179p2a";
};
});
in
python2Packages.buildPythonApplication {
name = "notifico";
src = fetchFromGitHub {
owner = "notifico";
repo = "notifico";
rev = "6af849e4c75dff4d740051676f5a2093a44efcee";
sha256 = "18jifqdvjy4x5s1bh7vx501pin52g4n3hhw1z4m2c0h512z4spdr";
};
patches = [
(fetchurl {
url = https://github.com/whitequark/notifico/commit/22b582fad6cb97af6f7437e8462d720ddacc42ef.patch;
sha256 = "0w8i8hf1r8b0p1y1zn9vyvnyi20qp120aiyalqymhsxsh17mma52";
})
];
propagatedBuildInputs = with python2Packages; [
flask
Flask-WTF
Flask-Gravatar
flask_sqlalchemy
Flask-XML-RPC
flask_mail
flask-caching
Fabric
sqlalchemy
utopia
gevent
oauth2
redis
gunicorn
requests
PyGithub
xmltodict
unidecode
raven
blinker
docopt
celery
];
postInstall = ''
mkdir $out/bin
cat << EOF > $out/bin/notifico
#!${python2}/bin/python
import sys
from notifico.__main__ import main
sys.exit(main(sys.argv))
EOF
chmod +x $out/bin/notifico
'';
}

View File

@ -0,0 +1,10 @@
-rw------- 1 root root backup-passphrase
-rw------- 1 root root email_accounts.nix
-rw------- 1 homu homu homu.toml
-rw------- 1 matterbridge matterbridge matterbridge.toml
-rw------- 1 uwsgi uwsgi mattermost-github-integration.py
-rw------- 1 nginx nginx muninpasswd
-rw-rw---- 1 hydra hydra nixbld.m-labs.hk-1
-rw-rw---- 1 hydra hydra nix_id_rsa
-rw------- 1 root root rclone.conf
-rw------- 1 root root wifi_password.nix

101
nixops/desktop.nix Normal file
View File

@ -0,0 +1,101 @@
{ host }:
{ config, pkgs, ... }:
{
deployment.targetHost = host;
imports =
[
(./. + "/${host}-hardware-configuration.nix")
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = host;
time.timeZone = "Asia/Hong_Kong";
# List packages installed in system profile. To search, run:
# $ nix search wget
nixpkgs.config.allowUnfree = true;
environment.systemPackages = with pkgs; [
wget vim git firefox thunderbird hexchat usbutils pciutils mplayer vlc youtube-dl file lm_sensors cryptsetup audacious acpi
gwenview okular gimp imagemagick
(python3.withPackages(ps: with ps; [ numpy scipy matplotlib qtconsole pypdf2 reportlab pygments regex ]))
texlive.combined.scheme-full mosh psmisc libreoffice-fresh
xc3sprog gtkwave xournal xsane telnet whois transmission-gtk unzip zip inkscape tigervnc gnupg
wireshark qrencode yosys symbiyosys yices z3 boolector cvc4 pavucontrol keepassx poppler_utils
jq ark sublime3 rink qemu_kvm konsole
];
services.openssh.enable = true;
# Enable CUPS to print documents.
services.printing = {
enable = true;
};
services.avahi = {
enable = true;
nssmdns = true;
};
# Enable sound.
sound.enable = true;
hardware.pulseaudio = {
enable = true;
extraModules = [ pkgs.pulseaudio-modules-bt ];
package = pkgs.pulseaudioFull;
};
i18n.inputMethod = {
enabled = "fcitx";
fcitx.engines = with pkgs.fcitx-engines; [ table-extra m17n ];
};
fonts.fonts = [ pkgs.noto-fonts pkgs.noto-fonts-cjk pkgs.noto-fonts-emoji pkgs.noto-fonts-extra ];
# Enable the X11 windowing system.
services.xserver.enable = true;
services.xserver.layout = "us";
services.xserver.xkbOptions = "eurosign:e";
# Enable touchpad support.
services.xserver.libinput.enable = true;
# Enable the KDE Desktop Environment.
services.xserver.displayManager.sddm.enable = true;
services.xserver.displayManager.sddm.autoLogin.enable = true;
services.xserver.displayManager.sddm.autoLogin.user = "harry";
services.xserver.desktopManager.plasma5.enable = true;
hardware.bluetooth.enable = true;
programs.fish.enable = true;
users.defaultUserShell = pkgs.fish;
users.extraGroups.plugdev = { };
users.extraUsers.sb = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout"];
};
users.extraUsers.harry = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
};
security.sudo.wheelNeedsPassword = false;
services.udev.packages = [ pkgs.openocd pkgs.hackrf ];
services.udev.extraRules = ''
ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple"
ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple"
'';
nix.binaryCachePublicKeys = ["nixbld.m-labs.hk-1:5aSRVA5b320xbNvu30tqxVPXpld73bhtOeH6uAjRyHc="];
nix.binaryCaches = ["https://nixbld.m-labs.hk" "https://cache.nixos.org"];
nix.sandboxPaths = ["/opt"];
# This value determines the NixOS release with which your system is to be
# compatible, in order to avoid breaking some software such as database
# servers. You should change this only after NixOS release notes say you
# should.
system.stateVersion = "19.03"; # Did you read the comment?
}

View File

@ -0,0 +1,30 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }:
{
imports =
[ <nixpkgs/nixos/modules/installer/scan/not-detected.nix>
];
boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/62a38d9c-452c-4648-be12-6131e95b8276";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/88F6-46F2";
fsType = "vfat";
};
swapDevices = [ ];
nix.maxJobs = lib.mkDefault 8;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
}

13
nixops/nixops.nix Normal file
View File

@ -0,0 +1,13 @@
{
rpi-1 = import ./rpi.nix { host = "rpi-1"; rpi4 = false; };
rpi-2 = import ./rpi.nix { host = "rpi-2"; rpi4 = false; };
rpi-3 = {
deployment.nix_path.nixpkgs = "https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz";
imports = [(import ./rpi.nix { host = "rpi-3"; rpi4 = true; })];
};
rpi-4 = {
deployment.nix_path.nixpkgs = "https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz";
imports = [(import ./rpi.nix { host = "rpi-4"; rpi4 = true; })];
};
juno = import ./desktop.nix { host = "juno"; };
}

78
nixops/rpi.nix Normal file
View File

@ -0,0 +1,78 @@
{ host, rpi4 }:
{ config, pkgs, ... }:
let
m-labs = import (fetchTarball https://nixbld.m-labs.hk/channel/custom/artiq/full/artiq-full/nixexprs.tar.xz) { inherit pkgs; };
in
{
deployment.targetHost = host;
nixpkgs.system = "aarch64-linux";
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = !rpi4;
boot.loader.raspberryPi = pkgs.lib.mkIf rpi4 {
enable = true;
version = 4;
};
boot.kernelPackages = pkgs.lib.mkIf rpi4 pkgs.linuxPackages_rpi4;
fileSystems = if rpi4 then {
"/boot" = {
device = "/dev/disk/by-label/FIRMWARE";
fsType = "vfat";
};
"/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
};
} else {
"/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
};
};
services.openssh.enable = true;
networking.hostName = host;
time.timeZone = "Asia/Hong_Kong";
users.extraUsers.nix = {
isNormalUser = true;
};
users.extraGroups.plugdev = { };
security.sudo.wheelNeedsPassword = false;
users.extraUsers.sb = {
isNormalUser = true;
extraGroups = ["wheel" "plugdev" "dialout"];
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZGtCJoIRtRadaSBMx+MNX53nvEGUk9q/89ZpEH/jCRS+FRnBOH73C8YGvsJaiL5xUZiLjIW7SRUr40bKgvns1FJ3PNMPqvAh6fC98h5EnWAVtzKpYVXGPVvxGOqRJwvEHr6DGMJbP1lRl78zFt3PQaeEiJ5mCxlY4KenKbkBJpUWBAUa11VrNd+o7AMfF0pbNDxZCd213brbyb8saLnEx28HwdaUn//MMWnfSPDLGlod5dy4/hzj0Yk/o+4yaeIkfk1Z0FqtZif1N+VTqD5r0dfvIi38mmVYzbImy5X/hoPtLTMRb//6KZH5POwMP3ZazIq7Bl0cmGfDEu/p6/zJd sb@sb-ThinkPad-10"];
};
users.extraUsers.astro = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGJJTSJdpDh82486uPiMhhyhnci4tScp5uUe7156MBC8 a"];
};
users.extraUsers.konstantin = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCiyF/90c4286ZeEBFbhpfoRkT+xaXM5QJ+uDXhfQ/015pMfhLTxXaX8xO/PvKjBhGx9DjTL57P3tXWQDOooKoE3cFSYunlVV1wQLXIbxRI8Hq8SQv2HJS3T4QJ9Wt5BCummQpz5XO2Rv/ih0By8ttWXXCoFCBOp1CfydQ/m4R7Nr1l7nFN3t4pBNiu2VFoEcedAj5/9LW+dJccAOHh7Jvr9sF0SB32ZdRYoC+9vUfsjVDx0dbEFNYMzS/TkpYwLYMVwfbxzn7jKMHnjpaM8gS4e9qkyFY2GcQBFebJW0PZbTNb6drHNsJ84tt7RXNikpdO2+ErILWV/MfdXwMCrIebFDOzl7bSufZcwpGSeYkUPneFbyGPH06hCaTUaJcYVk/59PMT33OCZL3E7swNbGn9VLxbpA4z4K4NQdP6n8+EPzi5czz+4FyyN8mIGKZjkNdDmLS61o0oKOWoxrQKNiAe4Ooy4hTB/jc5+UiNoiske/gdFJguV2Mr9de9eDU4QntfSLx0pthmc0rgdzPvyi8bVttL+vl0R5b3RL0FbcyjugOJLw3XrMXLxomZ/CyMncuis/iPYzZRMHEPvH0Uxd8rbnuTENF42pn96RHcHvlGLQ3fPlAgf6wXDA7Ecw0LBw20tPdHwooT/AM46+0OaFZTmq4WvZtAYMRnkUpmouKR7Q== konstantin@MBP.fritz.box"];
};
users.extraUsers.steinb = {
isNormalUser = true;
extraGroups = ["plugdev" "dialout"];
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDAOatwhOkN9YBy8cj2AmNkhlfFd4iW1LF6ImKjBAijfV250YJgOvnzV/lqQxdHYQHNauU7f3kXx1SmrTi/AHsHaoAR0/tYIk57d+UrX9a+qVFSL6ackjzO2vi2nDCy+PBc5Tb3WfCPAICSAk6BZ07yM+SMXiSqwzsaOTMsKuJuwIi+PkmrYG/IvB39IFAi4XLffExyLqD7VxsfJeNp/alZSmw3i4nPJ2nmBX80U9sFw774VIxCRTD5s5uRcp8tDN7ywNot49m3J4wOtRyzLW0QQX7J6RuMsAEQ8bP7VOpWSrOVD+LJDRaN9GPJL6EIASmbRU5t3rKXdAjG0t6pBuR4gqOdOPtj+CUeO465P5A8BgvRE+BeBybVjjc2gFlDShhGxaWfOKWiA/fmbicVWocPWcBjabLMyvewH2JKgUPJ7wvpaAzhvrOktt+Kn2fHqtrvpGYfsPue4F67BmAijlnw2fCBdVlkbIPrFv9eOJI5GX25h6C08ESV3bwv0OqKLJoxP5cODuMrLV04dcOXpy7JLEaf+PcxLa1g65NPML3eL6TQpBVEKN794V/cXETcrwKYG7AYSLbBqqWbreYEJhCE6wntp6/xijBVEBFcf8wBdAzdQKWlAGbpttNwjJ+MYYy9kXc4SN3G33NfTctJeGm+Y7Bov8uh2G7vv6QR3L0/IQ== steinb@QF-stein-laptop"];
};
services.udev.packages = [ m-labs.openocd ];
documentation.enable = false;
environment.systemPackages = with pkgs; [
wget vim git usbutils lm_sensors file mosh tmux xc3sprog m-labs.openocd screen gdb minicom
];
nix.binaryCachePublicKeys = ["nixbld.m-labs.hk-1:5aSRVA5b320xbNvu30tqxVPXpld73bhtOeH6uAjRyHc="];
nix.binaryCaches = ["https://cache.nixos.org" "https://nixbld.m-labs.hk"];
nix.trustedUsers = ["root" "nix"];
}

9
stm32.nix Normal file
View File

@ -0,0 +1,9 @@
{ pkgs ? import <nixpkgs> {}, rustManifest ? ./stm32/channel-rust-nightly.toml }:
let
jobs = import ./stm32/default.nix {
inherit rustManifest;
mozillaOverlay = import <mozillaOverlay>;
};
in
builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) jobs

File diff suppressed because it is too large Load Diff

42
stm32/default.nix Normal file
View File

@ -0,0 +1,42 @@
{ # Use master branch of the overlay by default
mozillaOverlay ? import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz),
rustManifest ? builtins.fetchurl "https://static.rust-lang.org/dist/channel-rust-nightly.toml"
}:
let
pkgs = import <nixpkgs> { overlays = [ mozillaOverlay ]; };
rustPlatform = pkgs.recurseIntoAttrs (pkgs.callPackage ./rustPlatform.nix {
inherit rustManifest;
});
buildStm32Firmware = { name, src, cargoSha256 }:
rustPlatform.buildRustPackage rec {
inherit name;
version = "0.0.0";
inherit src cargoSha256;
buildPhase = ''
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
cargo build --release
'';
doCheck = false;
installPhase = ''
mkdir -p $out $out/nix-support
cp target/thumbv7em-none-eabihf/release/${name} $out/${name}.elf
echo file binary-dist $out/${name}.elf >> $out/nix-support/hydra-build-products
'';
};
in
{
stabilizer = buildStm32Firmware {
name = "stabilizer";
src = <stabilizerSrc>;
cargoSha256 = "00bk0a6f10lyi9cmnc0nxy6zw26byr6cvhzkbr053awvg328qi0k";
};
thermostat = buildStm32Firmware {
name = "thermostat";
src = <thermostatSrc>;
cargoSha256 = "08kk6ja9g4j4apa02n02gxpjm62s27aabx33lg0dmzxgr1v5xlr1";
};
}

23
stm32/rustPlatform.nix Normal file
View File

@ -0,0 +1,23 @@
{ recurseIntoAttrs, stdenv, lib,
makeRustPlatform,
fetchurl, patchelf,
rustManifest ? ./channel-rust-nightly.toml
}:
let
targets = [
"thumbv7em-none-eabihf"
];
rustChannel =
lib.rustLib.fromManifestFile rustManifest {
inherit stdenv fetchurl patchelf;
};
rust =
rustChannel.rust.override {
inherit targets;
};
in
makeRustPlatform {
rustc = rust;
cargo = rust;
}

16
tecpak.nix Normal file
View File

@ -0,0 +1,16 @@
{ pkgs ? import <nixpkgs> {},
tecpak-nix ? import <tecpak> { mozillaOverlay = import <mozillaOverlay>; },
}:
with pkgs;
{ tecpak = lib.hydraJob (tecpak-nix.firmware
.overrideAttrs (oldAttrs: {
installPhase = ''
${oldAttrs.installPhase}
mkdir -p $out/nix-support
for f in $out/*.elf ; do
echo file binary-dist $f >> $out/nix-support/hydra-build-products
done
'';
}));
}

View File

@ -1,6 +1,6 @@
{ pkgs ? import <nixpkgs> {} }:
let
jobs = import ./gluelogic/default.nix { inherit pkgs; };
jobs = import ./urukul/default.nix { inherit pkgs; };
in
builtins.mapAttrs (key: value: pkgs.lib.hydraJob value) jobs

20
urukul/default.nix Normal file
View File

@ -0,0 +1,20 @@
{ pkgs ? import <nixpkgs> {} }:
let
migen = (pkgs.callPackage ../artiq-fast/pkgs/python-deps.nix {}).migen;
ise = import ./ise.nix { inherit pkgs; };
in
{
urukul-cpld = pkgs.stdenv.mkDerivation {
name = "urukul-cpld";
src = <urukulSrc>;
buildInputs = [(pkgs.python3.withPackages(ps: [migen]))] ++ (builtins.attrValues ise);
phases = ["buildPhase" "installPhase"];
buildPhase = "python $src/urukul_impl.py";
installPhase =
''
mkdir -p $out $out/nix-support
cp build/urukul.jed $out
echo file binary-dist $out/urukul.jed >> $out/nix-support/hydra-build-products
'';
};
}

31
urukul/ise.nix Normal file
View File

@ -0,0 +1,31 @@
# Install ISE in /opt and add to /etc/nixos/configuration.nix:
# nix.sandboxPaths = ["/opt"];
{ pkgs, isePath ? "/opt/Xilinx/14.7/ISE_DS" }:
let
makeXilinxEnv = name: pkgs.buildFHSUserEnv {
inherit name;
targetPkgs = pkgs: (
with pkgs; [
ncurses5
zlib
libuuid
xorg.libSM
xorg.libICE
xorg.libXrender
xorg.libX11
xorg.libXext
xorg.libXtst
xorg.libXi
]
);
profile =
''
source ${isePath}/common/.settings64.sh ${isePath}/common
source ${isePath}/ISE/.settings64.sh ${isePath}/ISE
'';
runScript = name;
};
in
pkgs.lib.attrsets.genAttrs ["xst" "ngdbuild" "cpldfit" "taengine" "hprep6"] makeXilinxEnv

35
web.nix
View File

@ -1,36 +1,7 @@
let
pkgs = import <nixpkgs> {};
web-src = <webSrc>;
nmigen-src = <nmigenSrc>;
src = <webSrc>;
in
rec {
web = pkgs.runCommand "web" {} "cd ${web-src}; ${pkgs.zola}/bin/zola build -o $out";
web-intl = pkgs.runCommand "web-intl" {}
''
cd ${web-src}
export DOMAINNAME=m-labs-intl.com
${pkgs.zola}/bin/zola build -o $out -u https://$DOMAINNAME
'';
sphinxcontrib-platformpicker = pkgs.python3Packages.buildPythonPackage rec {
pname = "sphinxcontrib-platformpicker";
version = "1.3";
src = pkgs.fetchFromGitHub {
owner = "whitequark";
repo = "sphinxcontrib-platformpicker";
rev = "v${version}";
sha256 = "sha256-qKhi4QqYhU7CbNSpziFacXc/sWWPSuM3Nc/oWPmBivM=";
};
propagatedBuildInputs = [ pkgs.python3Packages.sphinx ];
};
nmigen-docs = pkgs.stdenvNoCC.mkDerivation {
name = "nmigen-docs";
src = nmigen-src;
buildInputs = [ (pkgs.python3.withPackages(ps: [ ps.sphinx ps.sphinx_rtd_theme sphinxcontrib-platformpicker ])) ];
phases = [ "buildPhase" ];
buildPhase =
''
export PYTHONPATH=$src
sphinx-build -b html $src/docs $out
'';
};
{
web = pkgs.runCommand "web" {} "cd ${src}; ${pkgs.zola}/bin/zola build -o $out";
}