forked from M-Labs/artiq-zynq
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
d765b83e36 | |||
62a30bda9b | |||
801d7ac911 | |||
298085b62d | |||
93e26087ee |
45
default.nix
45
default.nix
@ -8,25 +8,23 @@ let
|
||||
vivado = import <artiq-fast/vivado.nix> { inherit pkgs; };
|
||||
# FSBL configuration supplied by Vivado 2020.1 for these boards:
|
||||
fsblTargets = ["zc702" "zc706" "zed"];
|
||||
sat_variants = ["satellite" "acpki_satellite" "nist_clock_satellite" "nist_qc2_satellite"];
|
||||
build = { target, variant, json ? null }: let
|
||||
build = { target, variant }: let
|
||||
szl = (import zynq-rs)."${target}-szl";
|
||||
fsbl = import "${zynq-rs}/nix/fsbl.nix" {
|
||||
inherit pkgs;
|
||||
board = target;
|
||||
};
|
||||
fwtype = if builtins.elem variant sat_variants then "satman" else "runtime";
|
||||
|
||||
firmware = rustPlatform.buildRustPackage rec {
|
||||
# note: due to fetchCargoTarball, cargoSha256 depends on package name
|
||||
name = "firmware";
|
||||
|
||||
src = ./src;
|
||||
cargoSha256 = "0p9d2j7qp00wpxm48phl5rq26simzry6w0m673lyhrlbzqdz4frb";
|
||||
cargoSha256 = "1g1nb8jz1na1v60hq3zrpgrwnw9qz7xrnnr2lkiyhsp72bg52ssl";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.gnumake
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ ps.jsonschema migen migen-axi misoc artiq ])))
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq ])))
|
||||
cargo-xbuild
|
||||
pkgs.llvmPackages_9.llvm
|
||||
pkgs.llvmPackages_9.clang-unwrapped
|
||||
@ -35,15 +33,15 @@ let
|
||||
export XARGO_RUST_SRC="${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library"
|
||||
export CLANG_EXTRA_INCLUDE_DIR="${pkgs.llvmPackages_9.clang-unwrapped.lib}/lib/clang/9.0.1/include"
|
||||
export CARGO_HOME=$(mktemp -d cargo-home.XXX)
|
||||
make TARGET=${target} GWARGS="${if json == null then "-V ${variant}" else json}" ${fwtype}
|
||||
make TARGET=${target} VARIANT=${variant}
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out $out/nix-support
|
||||
cp ../build/${fwtype}.bin $out/${fwtype}.bin
|
||||
cp ../build/firmware/armv7-none-eabihf/release/${fwtype} $out/${fwtype}.elf
|
||||
echo file binary-dist $out/${fwtype}.bin >> $out/nix-support/hydra-build-products
|
||||
echo file binary-dist $out/${fwtype}.elf >> $out/nix-support/hydra-build-products
|
||||
cp ../build/runtime.bin $out/runtime.bin
|
||||
cp ../build/firmware/armv7-none-eabihf/release/runtime $out/runtime.elf
|
||||
echo file binary-dist $out/runtime.bin >> $out/nix-support/hydra-build-products
|
||||
echo file binary-dist $out/runtime.elf >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
doCheck = false;
|
||||
@ -52,12 +50,12 @@ let
|
||||
gateware = pkgs.runCommand "${target}-${variant}-gateware"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ ps.jsonschema migen migen-axi misoc artiq ])))
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq ])))
|
||||
vivado
|
||||
];
|
||||
}
|
||||
''
|
||||
python ${./src/gateware}/${target}.py -g build ${if json == null then "-V ${variant}" else json}
|
||||
python ${./src/gateware}/${target}.py -g build -V ${variant}
|
||||
mkdir -p $out $out/nix-support
|
||||
cp build/top.bit $out
|
||||
echo file binary-dist $out/top.bit >> $out/nix-support/hydra-build-products
|
||||
@ -68,7 +66,7 @@ let
|
||||
''
|
||||
mkdir $out
|
||||
ln -s ${szl}/szl.elf $out
|
||||
ln -s ${firmware}/${fwtype}.bin $out
|
||||
ln -s ${firmware}/runtime.bin $out
|
||||
ln -s ${gateware}/top.bit $out
|
||||
'';
|
||||
sd = pkgs.runCommand "${target}-${variant}-sd"
|
||||
@ -134,25 +132,16 @@ let
|
||||
in
|
||||
(
|
||||
(build { target = "zc706"; variant = "simple"; }) //
|
||||
(build { target = "zc706"; variant = "master"; }) //
|
||||
(build { target = "zc706"; variant = "satellite"; }) //
|
||||
(build { target = "zc706"; variant = "nist_clock"; }) //
|
||||
(build { target = "zc706"; variant = "nist_clock_master"; }) //
|
||||
(build { target = "zc706"; variant = "nist_clock_satellite"; }) //
|
||||
(build { target = "zc706"; variant = "nist_qc2"; }) //
|
||||
(build { target = "zc706"; variant = "nist_qc2_master"; }) //
|
||||
(build { target = "zc706"; variant = "nist_qc2_satellite"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_simple"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_master"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_satellite"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_nist_clock"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_nist_clock_master"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_nist_clock_satellite"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_nist_qc2"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_nist_qc2_master"; }) //
|
||||
(build { target = "zc706"; variant = "acpki_nist_qc2_satellite"; }) //
|
||||
(build { target = "kasli_soc"; variant = "demo"; json = ./demo.json; }) //
|
||||
(build { target = "kasli_soc"; variant = "master"; json = ./kasli-soc-master.json; }) //
|
||||
(build { target = "kasli_soc"; variant = "satellite"; json = ./kasli-soc-satellite.json; }) //
|
||||
(build { target = "coraz7"; variant = "10"; }) //
|
||||
(build { target = "coraz7"; variant = "07s"; }) //
|
||||
(build { target = "coraz7"; variant = "acpki_10"; }) //
|
||||
(build { target = "coraz7"; variant = "acpki_07s"; }) //
|
||||
(build { target = "redpitaya"; variant = "simple"; }) //
|
||||
(build { target = "redpitaya"; variant = "acpki_simple"; }) //
|
||||
{ inherit zynq-rs; }
|
||||
)
|
||||
|
60
demo.json
60
demo.json
@ -1,60 +0,0 @@
|
||||
{
|
||||
"target": "kasli_soc",
|
||||
"variant": "demo",
|
||||
"hw_rev": "v1.0",
|
||||
"base": "standalone",
|
||||
"peripherals": [
|
||||
{
|
||||
"type": "grabber",
|
||||
"ports": [0]
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [1],
|
||||
"bank_direction_low": "input",
|
||||
"bank_direction_high": "output"
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [2],
|
||||
"bank_direction_low": "output",
|
||||
"bank_direction_high": "output"
|
||||
},
|
||||
{
|
||||
"type": "urukul",
|
||||
"dds": "ad9910",
|
||||
"ports": [3, 4],
|
||||
"clk_sel": 2
|
||||
},
|
||||
{
|
||||
"type": "zotino",
|
||||
"ports": [5]
|
||||
},
|
||||
{
|
||||
"type": "sampler",
|
||||
"ports": [6, 7]
|
||||
},
|
||||
{
|
||||
"type": "mirny",
|
||||
"ports": [8],
|
||||
"clk_sel": 1,
|
||||
"refclk": 125e6
|
||||
},
|
||||
{
|
||||
"type": "fastino",
|
||||
"ports": [9]
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [10],
|
||||
"bank_direction_low": "input",
|
||||
"bank_direction_high": "input"
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [11],
|
||||
"bank_direction_low": "output",
|
||||
"bank_direction_high": "input"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
{
|
||||
"target": "kasli_soc",
|
||||
"variant": "master",
|
||||
"hw_rev": "v1.0",
|
||||
"base": "master",
|
||||
"peripherals": [
|
||||
{
|
||||
"type": "grabber",
|
||||
"ports": [0]
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [1],
|
||||
"bank_direction_low": "input",
|
||||
"bank_direction_high": "output"
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [2],
|
||||
"bank_direction_low": "output",
|
||||
"bank_direction_high": "output"
|
||||
},
|
||||
{
|
||||
"type": "urukul",
|
||||
"dds": "ad9910",
|
||||
"ports": [3, 4],
|
||||
"clk_sel": 2
|
||||
},
|
||||
{
|
||||
"type": "zotino",
|
||||
"ports": [5]
|
||||
},
|
||||
{
|
||||
"type": "sampler",
|
||||
"ports": [6, 7]
|
||||
},
|
||||
{
|
||||
"type": "mirny",
|
||||
"ports": [8],
|
||||
"clk_sel": 1,
|
||||
"refclk": 125e6
|
||||
},
|
||||
{
|
||||
"type": "fastino",
|
||||
"ports": [9]
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [10],
|
||||
"bank_direction_low": "input",
|
||||
"bank_direction_high": "input"
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [11],
|
||||
"bank_direction_low": "output",
|
||||
"bank_direction_high": "input"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
{
|
||||
"target": "kasli_soc",
|
||||
"variant": "satellite",
|
||||
"hw_rev": "v1.0",
|
||||
"base": "satellite",
|
||||
"peripherals": [
|
||||
{
|
||||
"type": "grabber",
|
||||
"ports": [0]
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [1],
|
||||
"bank_direction_low": "input",
|
||||
"bank_direction_high": "output"
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [2],
|
||||
"bank_direction_low": "output",
|
||||
"bank_direction_high": "output"
|
||||
},
|
||||
{
|
||||
"type": "urukul",
|
||||
"dds": "ad9910",
|
||||
"ports": [3, 4],
|
||||
"clk_sel": 2
|
||||
},
|
||||
{
|
||||
"type": "zotino",
|
||||
"ports": [5]
|
||||
},
|
||||
{
|
||||
"type": "sampler",
|
||||
"ports": [6, 7]
|
||||
},
|
||||
{
|
||||
"type": "mirny",
|
||||
"ports": [8],
|
||||
"clk_sel": 1,
|
||||
"refclk": 125e6
|
||||
},
|
||||
{
|
||||
"type": "fastino",
|
||||
"ports": [9]
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [10],
|
||||
"bank_direction_low": "input",
|
||||
"bank_direction_high": "input"
|
||||
},
|
||||
{
|
||||
"type": "dio",
|
||||
"ports": [11],
|
||||
"bank_direction_low": "output",
|
||||
"bank_direction_high": "input"
|
||||
}
|
||||
]
|
||||
}
|
23
local_run.sh
23
local_run.sh
@ -13,10 +13,9 @@ fi
|
||||
|
||||
impure=0
|
||||
load_bitstream=1
|
||||
board_type="kasli_soc"
|
||||
fw_type="runtime"
|
||||
board_host="192.168.1.52"
|
||||
|
||||
while getopts "ilb:t:f:" opt; do
|
||||
while getopts "ilb:" opt; do
|
||||
case "$opt" in
|
||||
\?) exit 1
|
||||
;;
|
||||
@ -26,36 +25,24 @@ while getopts "ilb:t:f:" opt; do
|
||||
;;
|
||||
b) board_host=$OPTARG
|
||||
;;
|
||||
t) board_type=$OPTARG
|
||||
;;
|
||||
f) fw_type=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$board_host" ]; then
|
||||
case $board_type in
|
||||
kasli_soc) board_host="192.168.1.56";;
|
||||
zc706) board_host="192.168.1.52";;
|
||||
*) echo "Unknown board type"; exit 1;;
|
||||
esac
|
||||
fi
|
||||
|
||||
load_bitstream_cmd=""
|
||||
|
||||
build_dir=`pwd`/build
|
||||
result_dir=`pwd`/result
|
||||
cd $OPENOCD_ZYNQ
|
||||
openocd -f $board_type.cfg -c "load_image $SZL/szl-$board_type.elf; resume 0; exit"
|
||||
openocd -f zc706.cfg -c "load_image $SZL; resume 0; exit"
|
||||
sleep 5
|
||||
if [ $impure -eq 1 ]; then
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g $build_dir/gateware/top.bit"
|
||||
fi
|
||||
artiq_netboot $load_bitstream_cmd -f $build_dir/$fwtype.bin -b $board_host
|
||||
artiq_netboot $load_bitstream_cmd -f $build_dir/runtime.bin -b $board_host
|
||||
else
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g $result_dir/top.bit"
|
||||
fi
|
||||
artiq_netboot $load_bitstream_cmd -f $result_dir/$fwtype.bin -b $board_host
|
||||
artiq_netboot $load_bitstream_cmd -f $result_dir/runtime.bin -b $board_host
|
||||
fi
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Only ZC706 supported for now.
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$OPENOCD_ZYNQ" ]; then
|
||||
@ -20,9 +18,8 @@ impure_dir="build"
|
||||
sshopts=""
|
||||
load_bitstream=1
|
||||
board_host="192.168.1.52"
|
||||
fw_type="runtime"
|
||||
|
||||
while getopts "h:id:o:lt:" opt; do
|
||||
while getopts "h:id:o:l" opt; do
|
||||
case "$opt" in
|
||||
\?) exit 1
|
||||
;;
|
||||
@ -39,8 +36,6 @@ while getopts "h:id:o:lt:" opt; do
|
||||
;;
|
||||
b) board_host=$OPTARG
|
||||
;;
|
||||
t) fw_type=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
@ -51,17 +46,17 @@ echo "Creating $target_folder..."
|
||||
ssh $sshopts $target_host "mkdir -p $target_folder"
|
||||
echo "Copying files..."
|
||||
rsync -e "ssh $sshopts" -Lc $OPENOCD_ZYNQ/* $target_host:$target_folder
|
||||
rsync -e "ssh $sshopts" -Lc $SZL/szl-zc706.elf $target_host:$target_folder/szl.elf
|
||||
rsync -e "ssh $sshopts" -Lc $SZL $target_host:$target_folder
|
||||
if [ $impure -eq 1 ]; then
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g build/gateware/top.bit"
|
||||
fi
|
||||
firmware="build/$fw_type.bin"
|
||||
firmware="build/runtime.bin"
|
||||
else
|
||||
if [ $load_bitstream -eq 1 ]; then
|
||||
load_bitstream_cmd="-g $pure_dir/top.bit"
|
||||
fi
|
||||
firmware="$pure_dir/$fw_type.bin"
|
||||
firmware="$pure_dir/runtime.bin"
|
||||
fi
|
||||
echo "Programming board..."
|
||||
ssh $sshopts $target_host "cd $target_folder; openocd -f zc706.cfg -c'load_image szl.elf; resume 0; exit'"
|
||||
|
@ -6,6 +6,7 @@ let
|
||||
artiq-fast = <artiq-fast>;
|
||||
artiqpkgs = import "${artiq-fast}/default.nix" { inherit pkgs; };
|
||||
vivado = import "${artiq-fast}/vivado.nix" { inherit pkgs; };
|
||||
zc706-szl = (import zynq-rs).zc706-szl;
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "artiq-zynq-env";
|
||||
@ -21,7 +22,7 @@ in
|
||||
pkgs.openocd
|
||||
pkgs.openssh pkgs.rsync
|
||||
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq artiq-netboot ps.jsonschema ps.pyftdi ])))
|
||||
(pkgs.python3.withPackages(ps: (with artiqpkgs; [ migen migen-axi misoc artiq artiq-netboot ])))
|
||||
vivado
|
||||
artiqpkgs.binutils-arm
|
||||
|
||||
@ -31,5 +32,5 @@ in
|
||||
XARGO_RUST_SRC = "${rustPlatform.rust.rustc}/lib/rustlib/src/rust/library";
|
||||
CLANG_EXTRA_INCLUDE_DIR = "${pkgs.llvmPackages_9.clang-unwrapped.lib}/lib/clang/9.0.1/include";
|
||||
OPENOCD_ZYNQ = "${zynq-rs}/openocd";
|
||||
SZL = "${(import zynq-rs).szl}";
|
||||
SZL = "${zc706-szl}/szl.elf";
|
||||
}
|
||||
|
16
src/Cargo.lock
generated
16
src/Cargo.lock
generated
@ -94,9 +94,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.6"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9"
|
||||
checksum = "db184d3fa27bc7a2344250394c0264144dfe0bc81a4401801dcb964b8dd172ad"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
@ -195,7 +195,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libasync"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
||||
dependencies = [
|
||||
"embedded-hal",
|
||||
"libcortex_a9",
|
||||
@ -207,7 +207,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libboard_zynq"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"embedded-hal",
|
||||
@ -232,7 +232,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libconfig"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
||||
dependencies = [
|
||||
"core_io",
|
||||
"fatfs",
|
||||
@ -243,7 +243,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libcortex_a9"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"libregister",
|
||||
@ -259,7 +259,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
||||
[[package]]
|
||||
name = "libregister"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"vcell",
|
||||
@ -269,7 +269,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "libsupport_zynq"
|
||||
version = "0.0.0"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#57d8d8fbc7087863305721bcb8fdbdd13d65bd65"
|
||||
source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#2c161720fa12f8b7abecaf60f77b062b08ac9bc1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"compiler_builtins",
|
||||
|
@ -3,10 +3,8 @@ members = [
|
||||
"libc",
|
||||
"libdyld",
|
||||
"libdwarf",
|
||||
"libio",
|
||||
"libunwind",
|
||||
"runtime",
|
||||
"satman"
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
20
src/Makefile
20
src/Makefile
@ -1,18 +1,16 @@
|
||||
TARGET := zc706
|
||||
GWARGS := -V simple
|
||||
VARIANT := simple
|
||||
|
||||
all: runtime
|
||||
|
||||
runtime: ../build/runtime.bin
|
||||
all: ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin
|
||||
|
||||
.PHONY: all
|
||||
|
||||
|
||||
../build/pl.rs ../build/rustc-cfg: gateware/*
|
||||
mkdir -p ../build
|
||||
python gateware/$(TARGET).py -r ../build/pl.rs -c ../build/rustc-cfg -m ../build/mem.rs $(GWARGS)
|
||||
python gateware/$(TARGET).py -r ../build/pl.rs -c ../build/rustc-cfg -V $(VARIANT)
|
||||
|
||||
../build/firmware/armv7-none-eabihf/release/runtime: ../build/pl.rs ../build/rustc-cfg
|
||||
../build/firmware/armv7-none-eabihf/release/runtime: ../build/pl.rs ../build/rustc-cfg $(shell find . -print)
|
||||
cd runtime && \
|
||||
XBUILD_SYSROOT_PATH=`pwd`/../../build/sysroot \
|
||||
cargo xbuild --release \
|
||||
@ -21,13 +19,3 @@ runtime: ../build/runtime.bin
|
||||
|
||||
../build/runtime.bin: ../build/firmware/armv7-none-eabihf/release/runtime
|
||||
llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin
|
||||
|
||||
satmanout: ../build/pl.rs ../build/rustc-cfg
|
||||
cd satman && \
|
||||
XBUILD_SYSROOT_PATH=`pwd`/../../build/sysroot \
|
||||
cargo xbuild --release \
|
||||
--target-dir ../../build/firmware \
|
||||
--no-default-features --features=target_$(TARGET)
|
||||
|
||||
satman: satmanout
|
||||
llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/satman ../build/satman.bin
|
@ -8,13 +8,12 @@ from migen.build.generic_platform import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.cdc import MultiReg
|
||||
from migen_axi.integration.soc_core import SoCCore
|
||||
from migen_axi.platforms import kasli_soc
|
||||
from migen_axi.platforms import coraz7
|
||||
from misoc.interconnect.csr import *
|
||||
from misoc.integration import cpu_interface
|
||||
|
||||
from artiq.coredevice import jsondesc
|
||||
from artiq.gateware import rtio, eem_7series
|
||||
from artiq.gateware.rtio.phy import ttl_simple
|
||||
from artiq.gateware import rtio
|
||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
||||
|
||||
import dma
|
||||
import analyzer
|
||||
@ -22,81 +21,55 @@ import acpki
|
||||
|
||||
|
||||
class RTIOCRG(Module, AutoCSR):
|
||||
def __init__(self, platform):
|
||||
def __init__(self, platform, rtio_internal_clk):
|
||||
self.clock_sel = CSRStorage()
|
||||
self.pll_reset = CSRStorage(reset=1)
|
||||
self.pll_locked = CSRStatus()
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
||||
|
||||
clk_synth = platform.request("cdr_clk_clean_fabric")
|
||||
clk_synth_se = Signal()
|
||||
platform.add_period_constraint(clk_synth.p, 8.0)
|
||||
self.specials += [
|
||||
Instance("IBUFGDS",
|
||||
p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="FALSE",
|
||||
i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se),
|
||||
]
|
||||
rtio_external_clk = Signal()
|
||||
# user_sma_clock = platform.request("user_sma_clock")
|
||||
# platform.add_period_constraint(user_sma_clock.p, 8.0)
|
||||
# self.specials += Instance("IBUFDS",
|
||||
# i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
||||
# o_O=rtio_external_clk)
|
||||
|
||||
pll_locked = Signal()
|
||||
rtio_clk = Signal()
|
||||
rtiox4_clk = Signal()
|
||||
fb_clk = Signal()
|
||||
self.specials += [
|
||||
Instance("PLLE2_ADV",
|
||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
||||
p_BANDWIDTH="HIGH",
|
||||
p_REF_JITTER1=0.001,
|
||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
||||
i_CLKIN2=clk_synth_se,
|
||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
||||
i_CLKINSEL=0,
|
||||
|
||||
# VCO @ 1.5GHz when using 125MHz input
|
||||
p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1,
|
||||
i_CLKFBIN=fb_clk,
|
||||
p_REF_JITTER1=0.01,
|
||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
||||
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
|
||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
||||
i_CLKINSEL=~self.clock_sel.storage,
|
||||
|
||||
# VCO @ 1GHz when using 125MHz input
|
||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
||||
i_CLKFBIN=self.cd_rtio.clk,
|
||||
i_RST=self.pll_reset.storage,
|
||||
|
||||
o_CLKFBOUT=fb_clk,
|
||||
o_CLKFBOUT=rtio_clk,
|
||||
|
||||
p_CLKOUT0_DIVIDE=3, p_CLKOUT0_PHASE=0.0,
|
||||
o_CLKOUT0=rtiox4_clk,
|
||||
|
||||
p_CLKOUT1_DIVIDE=12, p_CLKOUT1_PHASE=0.0,
|
||||
o_CLKOUT1=rtio_clk),
|
||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
||||
o_CLKOUT0=rtiox4_clk),
|
||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
||||
|
||||
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
||||
MultiReg(pll_locked, self.pll_locked.status)
|
||||
]
|
||||
|
||||
|
||||
eem_iostandard_dict = {
|
||||
0: "LVDS_25",
|
||||
1: "LVDS_25",
|
||||
2: "LVDS",
|
||||
3: "LVDS",
|
||||
4: "LVDS",
|
||||
5: "LVDS",
|
||||
6: "LVDS",
|
||||
7: "LVDS",
|
||||
8: "LVDS_25",
|
||||
9: "LVDS_25",
|
||||
10: "LVDS",
|
||||
11: "LVDS",
|
||||
}
|
||||
|
||||
|
||||
def eem_iostandard(eem):
|
||||
return IOStandard(eem_iostandard_dict[eem])
|
||||
|
||||
|
||||
class GenericStandalone(SoCCore):
|
||||
def __init__(self, description, acpki=False):
|
||||
class CoraZ7(SoCCore):
|
||||
def __init__(self, device_variant="10", acpki=False):
|
||||
self.acpki = acpki
|
||||
self.rustc_cfg = dict()
|
||||
|
||||
platform = kasli_soc.Platform()
|
||||
platform = coraz7.Platform(device_variant=device_variant)
|
||||
platform.toolchain.bitstream_commands.extend([
|
||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||
])
|
||||
@ -108,33 +81,16 @@ class GenericStandalone(SoCCore):
|
||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||
|
||||
self.rustc_cfg["HAS_SI5324"] = None
|
||||
self.rustc_cfg["SI5324_SOFT_RESET"] = None
|
||||
|
||||
self.crg = self.ps7 # HACK for eem_7series to find the clock
|
||||
self.submodules.rtio_crg = RTIOCRG(self.platform)
|
||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||
self.csr_devices.append("rtio_crg")
|
||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
||||
self.platform.add_false_path_constraints(
|
||||
self.ps7.cd_sys.clk,
|
||||
self.rtio_crg.cd_rtio.clk)
|
||||
|
||||
self.rtio_channels = []
|
||||
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
||||
if has_grabber:
|
||||
self.grabber_csr_group = []
|
||||
eem_7series.add_peripherals(self, description["peripherals"], iostandard=eem_iostandard)
|
||||
for i in (0, 1):
|
||||
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||
user_led = self.platform.request("user_led", i)
|
||||
phy = ttl_simple.Output(user_led)
|
||||
self.submodules += phy
|
||||
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||
self.rtio_channels.append(rtio.LogChannel())
|
||||
|
||||
def add_rtio(self, rtio_channels):
|
||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, self.rtio_channels)
|
||||
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
||||
self.csr_devices.append("rtio_core")
|
||||
|
||||
if self.acpki:
|
||||
@ -157,29 +113,30 @@ class GenericStandalone(SoCCore):
|
||||
[self.rtio_core.cri])
|
||||
self.csr_devices.append("cri_con")
|
||||
|
||||
self.submodules.rtio_moninj = rtio.MonInj(self.rtio_channels)
|
||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||
self.csr_devices.append("rtio_moninj")
|
||||
|
||||
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
||||
self.ps7.s_axi_hp1)
|
||||
self.csr_devices.append("rtio_analyzer")
|
||||
|
||||
if has_grabber:
|
||||
self.rustc_cfg["has_grabber"] = None
|
||||
self.add_csr_group("grabber", self.grabber_csr_group)
|
||||
for grabber in self.grabber_csr_group:
|
||||
self.platform.add_false_path_constraints(
|
||||
self.rtio_crg.cd_rtio.clk, getattr(self, grabber).deserializer.cd_cl.clk)
|
||||
|
||||
class Simple(CoraZ7):
|
||||
def __init__(self, **kwargs):
|
||||
CoraZ7.__init__(self, **kwargs)
|
||||
|
||||
class GenericMaster(SoCCore):
|
||||
def __init__(self, description, **kwargs):
|
||||
raise NotImplementedError
|
||||
platform = self.platform
|
||||
|
||||
rtio_channels = []
|
||||
for i in range(2):
|
||||
phy = ttl_simple.Output(platform.request("user_led", i))
|
||||
self.submodules += phy
|
||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||
|
||||
class GenericSatellite(SoCCore):
|
||||
def __init__(self, description, **kwargs):
|
||||
raise NotImplementedError
|
||||
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
|
||||
rtio_channels.append(rtio.LogChannel())
|
||||
|
||||
self.add_rtio(rtio_channels)
|
||||
|
||||
|
||||
def write_csr_file(soc, filename):
|
||||
@ -199,33 +156,27 @@ def write_rustc_cfg_file(soc, filename):
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="ARTIQ device binary builder for generic Kasli-SoC systems")
|
||||
description="ARTIQ port to the Cora Z7 Zynq development kit")
|
||||
parser.add_argument("-r", default=None,
|
||||
help="build Rust interface into the specified file")
|
||||
parser.add_argument("-c", default=None,
|
||||
help="build Rust compiler configuration into the specified file")
|
||||
parser.add_argument("-g", default=None,
|
||||
help="build gateware into the specified directory")
|
||||
parser.add_argument("--acpki", default=False, action="store_true",
|
||||
help="enable ACPKI")
|
||||
parser.add_argument("description", metavar="DESCRIPTION",
|
||||
help="JSON system description file")
|
||||
parser.add_argument("-V", "--variant", default="10",
|
||||
help="variant: "
|
||||
"[acpki_]10/07s "
|
||||
"(default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
description = jsondesc.load(args.description)
|
||||
|
||||
if description["target"] != "kasli_soc":
|
||||
raise ValueError("Description is for a different target")
|
||||
|
||||
if description["base"] == "standalone":
|
||||
cls = GenericStandalone
|
||||
elif description["base"] == "master":
|
||||
cls = GenericMaster
|
||||
elif description["base"] == "satellite":
|
||||
cls = GenericSatellite
|
||||
else:
|
||||
raise ValueError("Invalid base")
|
||||
|
||||
soc = cls(description, acpki=args.acpki)
|
||||
variant = args.variant.lower()
|
||||
acpki = variant.startswith("acpki_")
|
||||
if acpki:
|
||||
variant = variant[6:]
|
||||
try:
|
||||
soc = Simple(device_variant=variant, acpki=acpki)
|
||||
except KeyError:
|
||||
raise SystemExit("Invalid variant (-V/--variant)")
|
||||
soc.finalize()
|
||||
|
||||
if args.r is not None:
|
191
src/gateware/redpitaya.py
Executable file
191
src/gateware/redpitaya.py
Executable file
@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
from operator import itemgetter
|
||||
|
||||
from migen import *
|
||||
from migen.build.generic_platform import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.cdc import MultiReg
|
||||
from migen_axi.integration.soc_core import SoCCore
|
||||
from migen_axi.platforms import redpitaya
|
||||
from misoc.interconnect.csr import *
|
||||
from misoc.integration import cpu_interface
|
||||
|
||||
from artiq.gateware import rtio
|
||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
||||
|
||||
import dma
|
||||
import analyzer
|
||||
import acpki
|
||||
|
||||
|
||||
class RTIOCRG(Module, AutoCSR):
|
||||
def __init__(self, platform, rtio_internal_clk):
|
||||
self.clock_sel = CSRStorage()
|
||||
self.pll_reset = CSRStorage(reset=1)
|
||||
self.pll_locked = CSRStatus()
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
||||
|
||||
rtio_external_clk = Signal()
|
||||
# user_sma_clock = platform.request("user_sma_clock")
|
||||
# platform.add_period_constraint(user_sma_clock.p, 8.0)
|
||||
# self.specials += Instance("IBUFDS",
|
||||
# i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
||||
# o_O=rtio_external_clk)
|
||||
|
||||
pll_locked = Signal()
|
||||
rtio_clk = Signal()
|
||||
rtiox4_clk = Signal()
|
||||
self.specials += [
|
||||
Instance("PLLE2_ADV",
|
||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
||||
|
||||
p_REF_JITTER1=0.01,
|
||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
||||
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
|
||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
||||
i_CLKINSEL=~self.clock_sel.storage,
|
||||
|
||||
# VCO @ 1GHz when using 125MHz input
|
||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
||||
i_CLKFBIN=self.cd_rtio.clk,
|
||||
i_RST=self.pll_reset.storage,
|
||||
|
||||
o_CLKFBOUT=rtio_clk,
|
||||
|
||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
||||
o_CLKOUT0=rtiox4_clk),
|
||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
||||
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
||||
MultiReg(pll_locked, self.pll_locked.status)
|
||||
]
|
||||
|
||||
|
||||
class Redpitaya(SoCCore):
|
||||
def __init__(self, acpki=False):
|
||||
self.acpki = acpki
|
||||
self.rustc_cfg = dict()
|
||||
|
||||
platform = redpitaya.Platform()
|
||||
platform.toolchain.bitstream_commands.extend([
|
||||
"set_property BITSTREAM.GENERAL.COMPRESS True [current_design]",
|
||||
])
|
||||
ident = self.__class__.__name__
|
||||
if self.acpki:
|
||||
ident = "acpki_" + ident
|
||||
SoCCore.__init__(self, platform=platform, csr_data_width=32, ident=ident)
|
||||
|
||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||
|
||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||
self.csr_devices.append("rtio_crg")
|
||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
||||
self.platform.add_false_path_constraints(
|
||||
self.ps7.cd_sys.clk,
|
||||
self.rtio_crg.cd_rtio.clk)
|
||||
|
||||
def add_rtio(self, rtio_channels):
|
||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||
self.submodules.rtio_core = rtio.Core(self.rtio_tsc, rtio_channels)
|
||||
self.csr_devices.append("rtio_core")
|
||||
|
||||
if self.acpki:
|
||||
self.rustc_cfg["ki_impl"] = "acp"
|
||||
self.submodules.rtio = acpki.KernelInitiator(self.rtio_tsc,
|
||||
bus=self.ps7.s_axi_acp,
|
||||
user=self.ps7.s_axi_acp_user,
|
||||
evento=self.ps7.event.o)
|
||||
self.csr_devices.append("rtio")
|
||||
else:
|
||||
self.rustc_cfg["ki_impl"] = "csr"
|
||||
self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc, now64=True)
|
||||
self.csr_devices.append("rtio")
|
||||
|
||||
self.submodules.rtio_dma = dma.DMA(self.ps7.s_axi_hp0)
|
||||
self.csr_devices.append("rtio_dma")
|
||||
|
||||
self.submodules.cri_con = rtio.CRIInterconnectShared(
|
||||
[self.rtio.cri, self.rtio_dma.cri],
|
||||
[self.rtio_core.cri])
|
||||
self.csr_devices.append("cri_con")
|
||||
|
||||
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)
|
||||
self.csr_devices.append("rtio_moninj")
|
||||
|
||||
self.submodules.rtio_analyzer = analyzer.Analyzer(self.rtio_tsc, self.rtio_core.cri,
|
||||
self.ps7.s_axi_hp1)
|
||||
self.csr_devices.append("rtio_analyzer")
|
||||
|
||||
|
||||
class Simple(Redpitaya):
|
||||
def __init__(self, **kwargs):
|
||||
Redpitaya.__init__(self, **kwargs)
|
||||
|
||||
platform = self.platform
|
||||
|
||||
rtio_channels = []
|
||||
for i in range(2):
|
||||
phy = ttl_simple.Output(platform.request("user_led", i))
|
||||
self.submodules += phy
|
||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||
|
||||
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
|
||||
rtio_channels.append(rtio.LogChannel())
|
||||
|
||||
self.add_rtio(rtio_channels)
|
||||
|
||||
|
||||
VARIANTS = {cls.__name__.lower(): cls for cls in [Simple]}
|
||||
|
||||
|
||||
def write_csr_file(soc, filename):
|
||||
with open(filename, "w") as f:
|
||||
f.write(cpu_interface.get_csr_rust(
|
||||
soc.get_csr_regions(), soc.get_csr_groups(), soc.get_constants()))
|
||||
|
||||
|
||||
def write_rustc_cfg_file(soc, filename):
|
||||
with open(filename, "w") as f:
|
||||
for k, v in sorted(soc.rustc_cfg.items(), key=itemgetter(0)):
|
||||
if v is None:
|
||||
f.write("{}\n".format(k))
|
||||
else:
|
||||
f.write("{}=\"{}\"\n".format(k, v))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="ARTIQ port to the Redpitaya Zynq development kit")
|
||||
parser.add_argument("-r", default=None,
|
||||
help="build Rust interface into the specified file")
|
||||
parser.add_argument("-c", default=None,
|
||||
help="build Rust compiler configuration into the specified file")
|
||||
parser.add_argument("-g", default=None,
|
||||
help="build gateware into the specified directory")
|
||||
parser.add_argument("-V", "--variant", default="10",
|
||||
help="variant: "
|
||||
"[acpki_]simple "
|
||||
"(default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
|
||||
variant = args.variant.lower()
|
||||
acpki = variant.startswith("acpki_")
|
||||
if acpki:
|
||||
variant = variant[6:]
|
||||
soc = Simple(acpki=acpki)
|
||||
soc.finalize()
|
||||
|
||||
if args.r is not None:
|
||||
write_csr_file(soc, args.r)
|
||||
if args.c is not None:
|
||||
write_rustc_cfg_file(soc, args.c)
|
||||
if args.g is not None:
|
||||
soc.build(build_dir=args.g)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -83,7 +83,6 @@ class ZC706(SoCCore):
|
||||
|
||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||
self.csr_devices.append("rtio_crg")
|
||||
self.rustc_cfg["has_rtio_crg_clock_sel"] = None
|
||||
self.platform.add_period_constraint(self.rtio_crg.cd_rtio.clk, 8.)
|
||||
self.platform.add_false_path_constraints(
|
||||
self.ps7.cd_sys.clk,
|
||||
|
@ -7,6 +7,8 @@ edition = "2018"
|
||||
|
||||
[features]
|
||||
target_zc706 = ["libboard_zynq/target_zc706", "libsupport_zynq/target_zc706", "libconfig/target_zc706"]
|
||||
target_coraz7 = ["libboard_zynq/target_coraz7", "libsupport_zynq/target_coraz7", "libconfig/target_coraz7"]
|
||||
target_redpitaya = ["libboard_zynq/target_redpitaya", "libsupport_zynq/target_redpitaya", "libconfig/target_redpitaya"]
|
||||
target_kasli_soc = ["libboard_zynq/target_kasli_soc", "libsupport_zynq/target_kasli_soc", "libconfig/target_kasli_soc"]
|
||||
default = ["target_zc706"]
|
||||
|
||||
|
@ -94,13 +94,13 @@ async fn read_request(stream: &TcpStream, allow_close: bool) -> Result<Option<Re
|
||||
Ok(true) => {}
|
||||
Ok(false) =>
|
||||
return Err(Error::UnexpectedPattern),
|
||||
Err(smoltcp::Error::Finished) => {
|
||||
Err(smoltcp::Error::Illegal) => {
|
||||
if allow_close {
|
||||
info!("peer closed connection");
|
||||
return Ok(None);
|
||||
} else {
|
||||
error!("peer unexpectedly closed connection");
|
||||
return Err(smoltcp::Error::Finished)?;
|
||||
return Err(smoltcp::Error::Illegal)?;
|
||||
}
|
||||
},
|
||||
Err(e) =>
|
||||
@ -313,9 +313,7 @@ async fn load_kernel(buffer: &Vec<u8>, control: &Rc<RefCell<kernel::Control>>, s
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_connection(stream: &mut TcpStream, control: Rc<RefCell<kernel::Control>>) -> Result<()> {
|
||||
stream.set_ack_delay(None);
|
||||
|
||||
async fn handle_connection(stream: &TcpStream, control: Rc<RefCell<kernel::Control>>) -> Result<()> {
|
||||
if !expect(stream, b"ARTIQ coredev\n").await? {
|
||||
return Err(Error::UnexpectedPattern);
|
||||
}
|
||||
@ -409,7 +407,7 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||
let connection = Rc::new(Semaphore::new(1, 1));
|
||||
let terminate = Rc::new(Semaphore::new(0, 1));
|
||||
loop {
|
||||
let mut stream = TcpStream::accept(1381, 0x10_000, 0x10_000).await.unwrap();
|
||||
let stream = TcpStream::accept(1381, 0x10_000, 0x10_000).await.unwrap();
|
||||
|
||||
if connection.try_wait().is_none() {
|
||||
// there is an existing connection
|
||||
@ -427,7 +425,7 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||
task::spawn(async move {
|
||||
select_biased! {
|
||||
_ = (async {
|
||||
let _ = handle_connection(&mut stream, control.clone())
|
||||
let _ = handle_connection(&stream, control.clone())
|
||||
.await
|
||||
.map_err(|e| warn!("connection terminated: {}", e));
|
||||
if let Some(buffer) = &*idle_kernel {
|
||||
|
@ -1,7 +1,9 @@
|
||||
#[cfg(feature = "target_zc706")]
|
||||
mod i2c {
|
||||
use libboard_zynq;
|
||||
use crate::artiq_raise;
|
||||
|
||||
pub static mut I2C_BUS: Option<libboard_zynq::i2c::I2c> = None;
|
||||
static mut I2C_BUS: Option<libboard_zynq::i2c::I2c> = None;
|
||||
|
||||
pub extern fn start(busno: i32) {
|
||||
if busno > 0 {
|
||||
@ -65,3 +67,34 @@ pub fn init() {
|
||||
i2c.init().expect("I2C bus initialization failed");
|
||||
unsafe { I2C_BUS = Some(i2c) };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "target_zc706"))]
|
||||
mod i2c {
|
||||
use crate::artiq_raise;
|
||||
|
||||
pub extern fn start(_busno: i32) {
|
||||
artiq_raise!("I2CError", "No I2C bus");
|
||||
}
|
||||
|
||||
pub extern fn restart(_busno: i32) {
|
||||
artiq_raise!("I2CError", "No I2C bus");
|
||||
}
|
||||
|
||||
pub extern fn stop(_busno: i32) {
|
||||
artiq_raise!("I2CError", "No I2C bus");
|
||||
}
|
||||
|
||||
pub extern fn write(_busno: i32, _data: i32) -> bool {
|
||||
artiq_raise!("I2CError", "No I2C bus");
|
||||
}
|
||||
|
||||
pub extern fn read(_busno: i32, _ack: bool) -> i32 {
|
||||
artiq_raise!("I2CError", "No I2C bus");
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
}
|
||||
}
|
||||
|
||||
pub use i2c::*;
|
||||
|
@ -45,8 +45,6 @@ mod mgmt;
|
||||
mod analyzer;
|
||||
mod irq;
|
||||
mod i2c;
|
||||
#[cfg(has_si5324)]
|
||||
mod si5324;
|
||||
|
||||
fn init_gateware() {
|
||||
// Set up PS->PL clocks
|
||||
@ -110,7 +108,6 @@ fn init_rtio(timer: &mut GlobalTimer, cfg: &Config) {
|
||||
loop {
|
||||
unsafe {
|
||||
pl::csr::rtio_crg::pll_reset_write(1);
|
||||
#[cfg(has_rtio_crg_clock_sel)]
|
||||
pl::csr::rtio_crg::clock_sel_write(clock_sel);
|
||||
pl::csr::rtio_crg::pll_reset_write(0);
|
||||
}
|
||||
@ -162,20 +159,6 @@ async fn report_async_rtio_errors() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_si5324)]
|
||||
// 125MHz output, from crystal, 7 Hz
|
||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
||||
= si5324::FrequencySettings {
|
||||
n1_hs : 10,
|
||||
nc1_ls : 4,
|
||||
n2_hs : 10,
|
||||
n2_ls : 19972,
|
||||
n31 : 4565,
|
||||
n32 : 4565,
|
||||
bwsel : 4,
|
||||
crystal_ref: true
|
||||
};
|
||||
|
||||
static mut LOG_BUFFER: [u8; 1<<17] = [0; 1<<17];
|
||||
|
||||
#[no_mangle]
|
||||
@ -199,9 +182,6 @@ pub fn main_core0() {
|
||||
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
||||
|
||||
i2c::init();
|
||||
#[cfg(has_si5324)]
|
||||
si5324::setup(unsafe { (&mut i2c::I2C_BUS).as_mut().unwrap() },
|
||||
&SI5324_SETTINGS, si5324::Input::Ckin2, timer).expect("cannot initialize Si5324");
|
||||
|
||||
let cfg = match Config::new() {
|
||||
Ok(cfg) => cfg,
|
||||
|
@ -121,7 +121,7 @@ async fn handle_connection(
|
||||
|
||||
loop {
|
||||
let msg = read_i8(stream).await;
|
||||
if let Err(smoltcp::Error::Finished) = msg {
|
||||
if let Err(smoltcp::Error::Illegal) = msg {
|
||||
return Ok(());
|
||||
}
|
||||
let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
|
||||
|
@ -184,7 +184,7 @@ pub fn start(timer: GlobalTimer) {
|
||||
info!("received connection");
|
||||
let result = handle_connection(&stream, timer).await;
|
||||
match result {
|
||||
Err(Error::NetworkError(smoltcp::Error::Finished)) => info!("peer closed connection"),
|
||||
Err(Error::NetworkError(smoltcp::Error::Illegal)) => info!("peer closed connection"),
|
||||
Err(error) => warn!("connection terminated: {}", error),
|
||||
_ => (),
|
||||
}
|
||||
|
@ -1,273 +0,0 @@
|
||||
use core::result;
|
||||
use log::info;
|
||||
use libboard_zynq::{i2c::I2c, timer::GlobalTimer, time::Milliseconds};
|
||||
use embedded_hal::blocking::delay::DelayUs;
|
||||
#[cfg(not(si5324_soft_reset))]
|
||||
use pl::csr;
|
||||
|
||||
type Result<T> = result::Result<T, &'static str>;
|
||||
|
||||
const ADDRESS: u8 = 0x68;
|
||||
|
||||
#[cfg(not(si5324_soft_reset))]
|
||||
fn hard_reset(timer: GlobalTimer) {
|
||||
unsafe { csr::si5324_rst_n::out_write(0); }
|
||||
timer.delay_us(1_000);
|
||||
unsafe { csr::si5324_rst_n::out_write(1); }
|
||||
timer.delay_us(10_000);
|
||||
}
|
||||
|
||||
// NOTE: the logical parameters DO NOT MAP to physical values written
|
||||
// into registers. They have to be mapped; see the datasheet.
|
||||
// DSPLLsim reports the logical parameters in the design summary, not
|
||||
// the physical register values.
|
||||
pub struct FrequencySettings {
|
||||
pub n1_hs: u8,
|
||||
pub nc1_ls: u32,
|
||||
pub n2_hs: u8,
|
||||
pub n2_ls: u32,
|
||||
pub n31: u32,
|
||||
pub n32: u32,
|
||||
pub bwsel: u8,
|
||||
pub crystal_ref: bool
|
||||
}
|
||||
|
||||
pub enum Input {
|
||||
Ckin1,
|
||||
Ckin2,
|
||||
}
|
||||
|
||||
fn map_frequency_settings(settings: &FrequencySettings) -> Result<FrequencySettings> {
|
||||
if settings.nc1_ls != 0 && (settings.nc1_ls % 2) == 1 {
|
||||
return Err("NC1_LS must be 0 or even")
|
||||
}
|
||||
if settings.nc1_ls > (1 << 20) {
|
||||
return Err("NC1_LS is too high")
|
||||
}
|
||||
if (settings.n2_ls % 2) == 1 {
|
||||
return Err("N2_LS must be even")
|
||||
}
|
||||
if settings.n2_ls > (1 << 20) {
|
||||
return Err("N2_LS is too high")
|
||||
}
|
||||
if settings.n31 > (1 << 19) {
|
||||
return Err("N31 is too high")
|
||||
}
|
||||
if settings.n32 > (1 << 19) {
|
||||
return Err("N32 is too high")
|
||||
}
|
||||
let r = FrequencySettings {
|
||||
n1_hs: match settings.n1_hs {
|
||||
4 => 0b000,
|
||||
5 => 0b001,
|
||||
6 => 0b010,
|
||||
7 => 0b011,
|
||||
8 => 0b100,
|
||||
9 => 0b101,
|
||||
10 => 0b110,
|
||||
11 => 0b111,
|
||||
_ => return Err("N1_HS has an invalid value")
|
||||
},
|
||||
nc1_ls: settings.nc1_ls - 1,
|
||||
n2_hs: match settings.n2_hs {
|
||||
4 => 0b000,
|
||||
5 => 0b001,
|
||||
6 => 0b010,
|
||||
7 => 0b011,
|
||||
8 => 0b100,
|
||||
9 => 0b101,
|
||||
10 => 0b110,
|
||||
11 => 0b111,
|
||||
_ => return Err("N2_HS has an invalid value")
|
||||
},
|
||||
n2_ls: settings.n2_ls - 1,
|
||||
n31: settings.n31 - 1,
|
||||
n32: settings.n32 - 1,
|
||||
bwsel: settings.bwsel,
|
||||
crystal_ref: settings.crystal_ref
|
||||
};
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn write(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
|
||||
i2c.start().unwrap();
|
||||
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||
return Err("Si5324 failed to ack write address")
|
||||
}
|
||||
if !i2c.write(reg).unwrap() {
|
||||
return Err("Si5324 failed to ack register")
|
||||
}
|
||||
if !i2c.write(val).unwrap() {
|
||||
return Err("Si5324 failed to ack value")
|
||||
}
|
||||
i2c.stop().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_no_ack_value(i2c: &mut I2c, reg: u8, val: u8) -> Result<()> {
|
||||
i2c.start().unwrap();
|
||||
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||
return Err("Si5324 failed to ack write address")
|
||||
}
|
||||
if !i2c.write(reg).unwrap() {
|
||||
return Err("Si5324 failed to ack register")
|
||||
}
|
||||
i2c.write(val).unwrap();
|
||||
i2c.stop().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read(i2c: &mut I2c, reg: u8) -> Result<u8> {
|
||||
i2c.start().unwrap();
|
||||
if !i2c.write(ADDRESS << 1).unwrap() {
|
||||
return Err("Si5324 failed to ack write address")
|
||||
}
|
||||
if !i2c.write(reg).unwrap() {
|
||||
return Err("Si5324 failed to ack register")
|
||||
}
|
||||
i2c.restart().unwrap();
|
||||
if !i2c.write((ADDRESS << 1) | 1).unwrap() {
|
||||
return Err("Si5324 failed to ack read address")
|
||||
}
|
||||
let val = i2c.read(false).unwrap();
|
||||
i2c.stop().unwrap();
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
fn rmw<F>(i2c: &mut I2c, reg: u8, f: F) -> Result<()> where
|
||||
F: Fn(u8) -> u8 {
|
||||
let value = read(i2c, reg)?;
|
||||
write(i2c, reg, f(value))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ident(i2c: &mut I2c) -> Result<u16> {
|
||||
Ok(((read(i2c, 134)? as u16) << 8) | (read(i2c, 135)? as u16))
|
||||
}
|
||||
|
||||
#[cfg(si5324_soft_reset)]
|
||||
fn soft_reset(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||
write_no_ack_value(i2c, 136, read(i2c, 136)? | 0x80)?;
|
||||
timer.delay_us(10_000);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn has_xtal(i2c: &mut I2c) -> Result<bool> {
|
||||
Ok((read(i2c, 129)? & 0x01) == 0) // LOSX_INT=0
|
||||
}
|
||||
|
||||
fn has_ckin(i2c: &mut I2c, input: Input) -> Result<bool> {
|
||||
match input {
|
||||
Input::Ckin1 => Ok((read(i2c, 129)? & 0x02) == 0), // LOS1_INT=0
|
||||
Input::Ckin2 => Ok((read(i2c, 129)? & 0x04) == 0), // LOS2_INT=0
|
||||
}
|
||||
}
|
||||
|
||||
fn locked(i2c: &mut I2c) -> Result<bool> {
|
||||
Ok((read(i2c, 130)? & 0x01) == 0) // LOL_INT=0
|
||||
}
|
||||
|
||||
fn monitor_lock(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||
info!("waiting for Si5324 lock...");
|
||||
let timeout = timer.get_time() + Milliseconds(20_000);
|
||||
while !locked(i2c)? {
|
||||
// Yes, lock can be really slow.
|
||||
if timer.get_time() > timeout {
|
||||
return Err("Si5324 lock timeout");
|
||||
}
|
||||
}
|
||||
info!(" ...locked");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init(i2c: &mut I2c, timer: GlobalTimer) -> Result<()> {
|
||||
#[cfg(not(si5324_soft_reset))]
|
||||
hard_reset(timer);
|
||||
|
||||
#[cfg(feature = "target_kasli_soc")]
|
||||
{
|
||||
i2c.pca9548_select(0x70, 0)?;
|
||||
i2c.pca9548_select(0x71, 1 << 3)?;
|
||||
}
|
||||
|
||||
if ident(i2c)? != 0x0182 {
|
||||
return Err("Si5324 does not have expected product number");
|
||||
}
|
||||
|
||||
#[cfg(si5324_soft_reset)]
|
||||
soft_reset(i2c, timer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bypass(i2c: &mut I2c, input: Input, timer: GlobalTimer) -> Result<()> {
|
||||
let cksel_reg = match input {
|
||||
Input::Ckin1 => 0b00,
|
||||
Input::Ckin2 => 0b01,
|
||||
};
|
||||
init(i2c, timer)?;
|
||||
rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0
|
||||
rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?; // CKSEL_REG
|
||||
rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00
|
||||
rmw(i2c, 6, |v| (v & 0xc0) | 0b111111)?; // SFOUT2_REG=b111 SFOUT1_REG=b111
|
||||
rmw(i2c, 0, |v| (v & 0xfd) | 0x02)?; // BYPASS_REG=1
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn setup(i2c: &mut I2c, settings: &FrequencySettings, input: Input, timer: GlobalTimer) -> Result<()> {
|
||||
let s = map_frequency_settings(settings)?;
|
||||
let cksel_reg = match input {
|
||||
Input::Ckin1 => 0b00,
|
||||
Input::Ckin2 => 0b01,
|
||||
};
|
||||
|
||||
init(i2c, timer)?;
|
||||
if settings.crystal_ref {
|
||||
rmw(i2c, 0, |v| v | 0x40)?; // FREE_RUN=1
|
||||
}
|
||||
rmw(i2c, 2, |v| (v & 0x0f) | (s.bwsel << 4))?;
|
||||
rmw(i2c, 21, |v| v & 0xfe)?; // CKSEL_PIN=0
|
||||
rmw(i2c, 3, |v| (v & 0x2f) | (cksel_reg << 6) | 0x10)?; // CKSEL_REG, SQ_ICAL=1
|
||||
rmw(i2c, 4, |v| (v & 0x3f) | (0b00 << 6))?; // AUTOSEL_REG=b00
|
||||
rmw(i2c, 6, |v| (v & 0xc0) | 0b111111)?; // SFOUT2_REG=b111 SFOUT1_REG=b111
|
||||
write(i2c, 25, (s.n1_hs << 5 ) as u8)?;
|
||||
write(i2c, 31, (s.nc1_ls >> 16) as u8)?;
|
||||
write(i2c, 32, (s.nc1_ls >> 8 ) as u8)?;
|
||||
write(i2c, 33, (s.nc1_ls) as u8)?;
|
||||
write(i2c, 34, (s.nc1_ls >> 16) as u8)?; // write to NC2_LS as well
|
||||
write(i2c, 35, (s.nc1_ls >> 8 ) as u8)?;
|
||||
write(i2c, 36, (s.nc1_ls) as u8)?;
|
||||
write(i2c, 40, (s.n2_hs << 5 ) as u8 | (s.n2_ls >> 16) as u8)?;
|
||||
write(i2c, 41, (s.n2_ls >> 8 ) as u8)?;
|
||||
write(i2c, 42, (s.n2_ls) as u8)?;
|
||||
write(i2c, 43, (s.n31 >> 16) as u8)?;
|
||||
write(i2c, 44, (s.n31 >> 8) as u8)?;
|
||||
write(i2c, 45, (s.n31) as u8)?;
|
||||
write(i2c, 46, (s.n32 >> 16) as u8)?;
|
||||
write(i2c, 47, (s.n32 >> 8) as u8)?;
|
||||
write(i2c, 48, (s.n32) as u8)?;
|
||||
rmw(i2c, 137, |v| v | 0x01)?; // FASTLOCK=1
|
||||
rmw(i2c, 136, |v| v | 0x40)?; // ICAL=1
|
||||
|
||||
if !has_xtal(i2c)? {
|
||||
return Err("Si5324 misses XA/XB signal");
|
||||
}
|
||||
if !has_ckin(i2c, input)? {
|
||||
return Err("Si5324 misses clock input signal");
|
||||
}
|
||||
|
||||
monitor_lock(i2c, timer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn select_input(i2c: &mut I2c, input: Input, timer: GlobalTimer) -> Result<()> {
|
||||
let cksel_reg = match input {
|
||||
Input::Ckin1 => 0b00,
|
||||
Input::Ckin2 => 0b01,
|
||||
};
|
||||
rmw(i2c, 3, |v| (v & 0x3f) | (cksel_reg << 6))?;
|
||||
if !has_ckin(i2c, input)? {
|
||||
return Err("Si5324 misses clock input signal");
|
||||
}
|
||||
monitor_lock(i2c, timer)?;
|
||||
Ok(())
|
||||
}
|
@ -3,6 +3,6 @@ let
|
||||
in
|
||||
pkgs.fetchgit {
|
||||
url = "https://git.m-labs.hk/M-Labs/zynq-rs.git";
|
||||
rev = "57d8d8fbc7087863305721bcb8fdbdd13d65bd65";
|
||||
sha256 = "0gnbaxgingrxrxi2sjd592r1630ld4ckrz4r8ajx8zp7q3bb43jj";
|
||||
rev = "2c161720fa12f8b7abecaf60f77b062b08ac9bc1";
|
||||
sha256 = "0zpazkicqzps86r7lgqf09y9ary94mjvxw6gc41z9kjjyxar5fhr";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user