From ea9bc0440753ac22e5d42754b4b54d15ca3a4e20 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Thu, 7 Oct 2021 17:20:44 +0800 Subject: [PATCH 01/29] flake: add jesd204b --- flake.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index e4343766d..0aa09d2b0 100644 --- a/flake.nix +++ b/flake.nix @@ -181,6 +181,18 @@ propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ]; }; + jesd204b = pkgs.python3Packages.buildPythonPackage rec { + pname = "jesd204b"; + version = "unstable-2021-05-05"; + src = pkgs.fetchFromGitHub { + owner = "m-labs"; + repo = "jesd204b"; + rev = "bf1cd9014c8b7a9db67609f653634daaf3bcd39b"; + sha256 = "sha256-wyYOCRIPANReeCl+KaIpiAStsn2mzfMlK+cSrUzVrAw="; + }; + propagatedBuildInputs = with pkgs.python3Packages; [ migen misoc ]; + }; + cargo-xbuild = rustPlatform.buildRustPackage rec { pname = "cargo-xbuild"; version = "0.6.5"; @@ -333,7 +345,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc artiq ps.paramiko ps.jsonschema ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema ])) rustPlatform.rust.rustc rustPlatform.rust.cargo cargo-xbuild From 501eb1fa23faa173a7f4f5c9f87993b840b1aeee Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Fri, 8 Oct 2021 12:13:58 +0800 Subject: [PATCH 02/29] flake: add microscope --- flake.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 0aa09d2b0..4cb3aea77 100644 --- a/flake.nix +++ b/flake.nix @@ -193,6 +193,18 @@ propagatedBuildInputs = with pkgs.python3Packages; [ migen misoc ]; }; + microscope = pkgs.python3Packages.buildPythonPackage rec { + pname = "microscope"; + version = "unstable-2020-12-28"; + src = pkgs.fetchFromGitHub { + owner = "m-labs"; + repo = "microscope"; + rev = "c21afe7a53258f05bde57e5ebf2e2761f3d495e4"; + sha256 = "sha256-jzyiLRuEf7p8LdhmZvOQj/dyQx8eUE8p6uRlwoiT8vg="; + }; + propagatedBuildInputs = with pkgs.python3Packages; [ pyserial prettytable msgpack migen ]; + }; + cargo-xbuild = rustPlatform.buildRustPackage rec { pname = "cargo-xbuild"; version = "0.6.5"; @@ -345,7 +357,7 @@ devShell.x86_64-linux = pkgs.mkShell { name = "artiq-dev-shell"; buildInputs = [ - (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema ])) + (pkgs.python3.withPackages(ps: with packages.x86_64-linux; [ migen misoc jesd204b artiq ps.paramiko ps.jsonschema microscope ])) rustPlatform.rust.rustc rustPlatform.rust.cargo cargo-xbuild From 3f6bf332987c763767952a10630a755927a52978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 7 Oct 2021 13:47:08 +0000 Subject: [PATCH 03/29] fastino: add interpolator support --- artiq/coredevice/fastino.py | 67 +++++++++++++++++++++++++++++- artiq/gateware/rtio/phy/fastino.py | 43 ++++++++++++++----- 2 files changed, 99 insertions(+), 11 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index 73fcfdf38..c60d5d1b1 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -2,7 +2,7 @@ streaming DAC. """ -from artiq.language.core import kernel, portable, delay +from artiq.language.core import kernel, portable, delay, delay_mu from artiq.coredevice.rtio import (rtio_output, rtio_output_wide, rtio_input_data) from artiq.language.units import us @@ -190,3 +190,68 @@ class Fastino: green LED. """ self.write(0x23, leds) + + @kernel + def set_continuous(self, channel_mask): + """Enable continuous DAC updates on channels regardless of new data + being submitted. + """ + self.write(0x25, channel_mask) + + @kernel + def stage_cic_mu(self, rate_mantissa, rate_exponent, gain_exponent): + """Stage machine unit interpolator configuration. + """ + if rate_mantissa < 0 or rate_mantissa >= 1 << 6: + raise ValueError("rate_mantissa out of bounds") + if rate_exponent < 0 or rate_exponent >= 1 << 4: + raise ValueError("rate_exponent out of bounds") + if gain_exponent < 0 or gain_exponent >= 1 << 6: + raise ValueError("gain_exponent out of bounds") + config = rate_mantissa | (rate_exponent << 6) | (gain_exponent << 10) + self.write(0x26, config) + + @kernel + def stage_cic(self, rate) -> TInt32: + """Compute and stage interpolator configuration. + + Approximates rate using 6+4 bit floating point representation, + approximates optimal interpolation gain compensation exponent to avoid + clipping. Gains for rates that are powers of two are accurately + compensated. Other rates lead to overall less than unity gain. + + Returns the actual interpolation rate. + The actual overall interpolation gain including gain compensation is + `actual_rate**order/2**ceil(log2(actual_rate**order))` + where `order = 3`. + """ + if rate <= 0 or rate > 1 << 16: + raise ValueError("rate out of bounds") + rate_mantissa = rate + rate_exponent = 0 + while rate_mantissa > 1 << 6: + rate_exponent += 1 + rate_mantissa >>= 1 + order = 3 + gain = 1 + for i in range(order): + gain *= rate_mantissa + gain_exponent = 0 + while gain > 1 << gain_exponent: + gain_exponent += 1 + gain_exponent += order*rate_exponent + assert gain_exponent <= order*16 + self.stage_cic_mu(rate_mantissa - 1, rate_exponent, gain_exponent) + return rate_mantissa << rate_exponent + + @kernel + def apply_cic(self, channel_mask): + """Apply the staged interpolator configuration on the specified channels. + + Channels using non-unity interpolation rate and variable data should have + continous DAC updates enabled (see :meth:`set_continuous`). + + This resets and settles the interpolators. There will be no output + updates for the next `order = 3` input samples. + """ + self.write(0x27, channel_mask) diff --git a/artiq/gateware/rtio/phy/fastino.py b/artiq/gateware/rtio/phy/fastino.py index ba8a7b5c9..474bab0f3 100644 --- a/artiq/gateware/rtio/phy/fastino.py +++ b/artiq/gateware/rtio/phy/fastino.py @@ -27,16 +27,16 @@ class Fastino(Module): # dac data words dacs = [Signal(16) for i in range(32)] + header = Record([ ("cfg", 4), ("leds", 8), - ("reserved", 8), + ("typ", 1), + ("reserved", 7), ("addr", 4), ("enable", len(dacs)), ]) - body = Cat(header.raw_bits(), dacs) - assert len(body) == len(self.serializer.payload) - self.comb += self.serializer.payload.eq(body) + assert len(Cat(header.raw_bits(), dacs)) == len(self.serializer.payload) # # # @@ -62,38 +62,61 @@ class Fastino(Module): # address space is sparse. hold = Signal.like(header.enable) + continuous = Signal.like(header.enable) + cic_config = Signal(16) read_regs = Array([Signal.like(self.serializer.readback) for _ in range(1 << len(header.addr))]) cases = { # update - 0x20: header.enable.eq(header.enable | self.rtlink.o.data), + 0x20: [ + header.enable.eq(self.rtlink.o.data), + header.typ.eq(0), + ], # hold 0x21: hold.eq(self.rtlink.o.data), # cfg 0x22: header.cfg.eq(self.rtlink.o.data), # leds 0x23: header.leds.eq(self.rtlink.o.data), - # reserved + # reserved bits 0x24: header.reserved.eq(self.rtlink.o.data), + # force continuous DAC updates + 0x25: continuous.eq(self.rtlink.o.data), + # interpolator configuration stage + 0x26: cic_config.eq(self.rtlink.o.data), + # interpolator update flags + 0x27: [ + header.enable.eq(self.rtlink.o.data), + header.typ.eq(1), + ], } for i in range(0, len(dacs), width): cases[i] = [ Cat(dacs[i:i + width]).eq(self.rtlink.o.data), - [If(~hold[i + j], + [If(~hold[i + j] & (header.typ == 0), header.enable[i + j].eq(1), ) for j in range(width)] ] + self.comb += [ + If(header.typ == 0, + self.serializer.payload.eq(Cat(header.raw_bits(), dacs)), + ).Else( + self.serializer.payload.eq(Cat(header.raw_bits(), Replicate(cic_config, len(dacs)))), + ), + ] + self.sync.rio_phy += [ If(self.serializer.stb, - header.enable.eq(0), + header.typ.eq(0), + header.enable.eq(continuous), read_regs[header.addr].eq(self.serializer.readback), header.addr.eq(header.addr + 1), ), - If(self.rtlink.o.stb & ~self.rtlink.o.address[-1], - Case(self.rtlink.o.address[:-1], cases), + If(self.rtlink.o.stb, + Case(self.rtlink.o.address, cases), ), ] From 3c1cbf47d231cf81a2b7526294dbd432c851c689 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 10 Oct 2021 16:18:55 +0800 Subject: [PATCH 04/29] phaser: add more slack during init. Closes #1757 --- artiq/coredevice/phaser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index daaed659d..5f7cd7108 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -203,6 +203,7 @@ class Phaser: self.measure_frame_timestamp() if self.frame_tstamp < 0: raise ValueError("frame timestamp measurement timed out") + delay(.1*ms) # reset self.set_cfg(dac_resetb=0, dac_sleep=1, dac_txena=0, From f5100702f608cf34a24349510d29e7708c74a8d5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 10 Oct 2021 20:40:17 +0800 Subject: [PATCH 05/29] runtime: expose rint from libm --- artiq/firmware/ksupport/api.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 7b219562c..99add22fa 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -101,6 +101,7 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(log10), api!(nextafter), api!(pow), + api!(rint), api!(round), api!(sin), api!(sinh), From 35d21c98d384620f4cc92bb02cf111cb72d60df7 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 11 Oct 2021 08:12:04 +0800 Subject: [PATCH 06/29] Revert "runtime: expose rint from libm" Consistency with NAR3/Zynq where rint is not available. This reverts commit f5100702f608cf34a24349510d29e7708c74a8d5. --- artiq/firmware/ksupport/api.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 99add22fa..7b219562c 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -101,7 +101,6 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(log10), api!(nextafter), api!(pow), - api!(rint), api!(round), api!(sin), api!(sinh), From 178a86bcdafd16eb40281e527ca396087a58488b Mon Sep 17 00:00:00 2001 From: fanmingyu212 Date: Wed, 13 Oct 2021 22:17:52 -0700 Subject: [PATCH 07/29] master: add an argument to set an experiment subdirectory Signed-off-by: Mingyu Fan --- RELEASE_NOTES.rst | 2 ++ artiq/frontend/artiq_master.py | 7 ++++++- artiq/master/experiments.py | 10 ++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 390665643..d9b325382 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -24,6 +24,8 @@ Highlights: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino * ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding TTL device (e.g. ``"ttl_0_counter"`` for the edge counter on TTL device``"ttl_0"``) +* ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the + repository when building the list of experiments. Breaking changes: diff --git a/artiq/frontend/artiq_master.py b/artiq/frontend/artiq_master.py index 1a5073692..ef46fb9bb 100755 --- a/artiq/frontend/artiq_master.py +++ b/artiq/frontend/artiq_master.py @@ -50,6 +50,10 @@ def get_argparser(): group.add_argument( "-r", "--repository", default="repository", help="path to the repository (default: '%(default)s')") + group.add_argument( + "--experiment-subdir", default="", + help=("path to the experiment folder from the repository root " + "(default: '%(default)s')")) log_args(parser) @@ -104,7 +108,8 @@ def main(): repo_backend = GitBackend(args.repository) else: repo_backend = FilesystemBackend(args.repository) - experiment_db = ExperimentDB(repo_backend, worker_handlers) + experiment_db = ExperimentDB( + repo_backend, worker_handlers, args.experiment_subdir) atexit.register(experiment_db.close) scheduler = Scheduler(RIDCounter(), worker_handlers, experiment_db) diff --git a/artiq/master/experiments.py b/artiq/master/experiments.py index b9a46d7ba..918c92dc8 100644 --- a/artiq/master/experiments.py +++ b/artiq/master/experiments.py @@ -74,19 +74,20 @@ class _RepoScanner: entry_dict.update(entries) return entry_dict - async def scan(self, root): + async def scan(self, root, subdir=""): self.worker = Worker(self.worker_handlers) try: - r = await self._scan(root) + r = await self._scan(root, subdir) finally: await self.worker.close() return r class ExperimentDB: - def __init__(self, repo_backend, worker_handlers): + def __init__(self, repo_backend, worker_handlers, experiment_subdir=""): self.repo_backend = repo_backend self.worker_handlers = worker_handlers + self.experiment_subdir = experiment_subdir self.cur_rev = self.repo_backend.get_head_rev() self.repo_backend.request_rev(self.cur_rev) @@ -115,7 +116,8 @@ class ExperimentDB: self.cur_rev = new_cur_rev self.status["cur_rev"] = new_cur_rev t1 = time.monotonic() - new_explist = await _RepoScanner(self.worker_handlers).scan(wd) + new_explist = await _RepoScanner(self.worker_handlers).scan( + wd, self.experiment_subdir) logger.info("repository scan took %d seconds", time.monotonic()-t1) update_from_dict(self.explist, new_explist) finally: From 790a20edf691842d77e9e13dd2291d3f170282e7 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:28:38 +0800 Subject: [PATCH 08/29] linker: generate stack guard + symbol --- artiq/compiler/kernel.ld | 3 +++ artiq/firmware/runtime/runtime.ld | 5 ++++- artiq/firmware/satman/satman.ld | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/artiq/compiler/kernel.ld b/artiq/compiler/kernel.ld index 6523d631a..fafbea2af 100644 --- a/artiq/compiler/kernel.ld +++ b/artiq/compiler/kernel.ld @@ -50,4 +50,7 @@ SECTIONS . = ALIGN(4); _end = .; } + + . = ALIGN(0x1000); + _sstack_guard = .; } diff --git a/artiq/firmware/runtime/runtime.ld b/artiq/firmware/runtime/runtime.ld index 81138fea3..9f60bf3ac 100644 --- a/artiq/firmware/runtime/runtime.ld +++ b/artiq/firmware/runtime/runtime.ld @@ -69,8 +69,11 @@ SECTIONS _ebss = .; } > runtime - .stack (NOLOAD) : ALIGN(16) + .stack (NOLOAD) : ALIGN(0x1000) { + _sstack_guard = .; + . += 0x1000; + _estack = .; . += 0x10000; _fstack = . - 16; } > runtime diff --git a/artiq/firmware/satman/satman.ld b/artiq/firmware/satman/satman.ld index bf7ef51d0..37de797c2 100644 --- a/artiq/firmware/satman/satman.ld +++ b/artiq/firmware/satman/satman.ld @@ -58,8 +58,10 @@ SECTIONS _ebss = .; } > main_ram - .stack (NOLOAD) : ALIGN(16) + .stack (NOLOAD) : ALIGN(0x1000) { + _sstack_guard = .; + . += 0x1000; _estack = .; . += 0x10000; _fstack = . - 16; From a0bf11b465dd62a417c6a80f7890776f538d5f80 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:33:55 +0800 Subject: [PATCH 09/29] riscv: impl pmp --- .../libboard_misoc/riscv32ima/boot.rs | 14 ++++- .../firmware/libboard_misoc/riscv32ima/mod.rs | 1 + .../firmware/libboard_misoc/riscv32ima/pmp.rs | 55 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 artiq/firmware/libboard_misoc/riscv32ima/pmp.rs diff --git a/artiq/firmware/libboard_misoc/riscv32ima/boot.rs b/artiq/firmware/libboard_misoc/riscv32ima/boot.rs index 32e9cfbc3..0d2254da1 100644 --- a/artiq/firmware/libboard_misoc/riscv32ima/boot.rs +++ b/artiq/firmware/libboard_misoc/riscv32ima/boot.rs @@ -1,4 +1,5 @@ -use super::cache; +use super::{cache, pmp}; +use riscv::register::*; pub unsafe fn reset() -> ! { llvm_asm!(r#" @@ -16,3 +17,14 @@ pub unsafe fn jump(addr: usize) -> ! { "# : : "r"(addr) : : "volatile"); loop {} } + +pub unsafe fn start_user(addr: usize) -> ! { + pmp::enable_user_memory(); + mstatus::set_mpp(mstatus::MPP::User); + mepc::write(addr); + llvm_asm!( + "mret" + : : : : "volatile" + ); + unreachable!() +} diff --git a/artiq/firmware/libboard_misoc/riscv32ima/mod.rs b/artiq/firmware/libboard_misoc/riscv32ima/mod.rs index 217ef713f..a8f498adc 100644 --- a/artiq/firmware/libboard_misoc/riscv32ima/mod.rs +++ b/artiq/firmware/libboard_misoc/riscv32ima/mod.rs @@ -1,2 +1,3 @@ pub mod cache; pub mod boot; +pub mod pmp; diff --git a/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs b/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs new file mode 100644 index 000000000..9ac80b9e3 --- /dev/null +++ b/artiq/firmware/libboard_misoc/riscv32ima/pmp.rs @@ -0,0 +1,55 @@ +use riscv::register::{pmpaddr0, pmpaddr1, pmpaddr2, pmpaddr3, pmpcfg0}; + +static mut THREAD_DEPTH: u8 = 0; + +const PMP_L : usize = 0b10000000; +const PMP_NAPOT: usize = 0b00011000; +const PMP_X : usize = 0b00000100; +const PMP_W : usize = 0b00000010; +const PMP_R : usize = 0b00000001; +const PMP_OFF : usize = 0b00000000; + +#[inline(always)] +pub unsafe fn init_stack_guard(guard_base: usize) { + pmpaddr2::write((guard_base >> 2) | ((0x1000 - 1) >> 3)); + pmpcfg0::write((PMP_L | PMP_NAPOT) << 16); +} + +#[inline(always)] +pub fn enable_user_memory() { + pmpaddr3::write((0x80000000 - 1) >> 3); + pmpcfg0::write((PMP_L | PMP_NAPOT | PMP_X | PMP_W | PMP_R) << 24); +} + +#[inline(always)] +pub unsafe fn push_pmp_region(addr: usize) { + let pmp_addr = (addr >> 2) | ((0x1000 - 1) >> 3); + match THREAD_DEPTH { + // Activate PMP0 when switching from main stack to thread + 0 => { + pmpaddr0::write(pmp_addr); + pmpcfg0::write(PMP_NAPOT); + } + + // Temporarily activate PMP1 when spawning a thread from a thread + // The thread should swap back to the main stack very soon after init + 1 => { + pmpaddr1::write(pmp_addr); + pmpcfg0::write(PMP_NAPOT << 8 | PMP_NAPOT); + } + + // Thread *running* another thread should not be possible + _ => unreachable!() + } + THREAD_DEPTH += 1; +} + +#[inline(always)] +pub unsafe fn pop_pmp_region() { + THREAD_DEPTH -= 1; + match THREAD_DEPTH { + 0 => pmpcfg0::write(PMP_OFF), + 1 => pmpcfg0::write(PMP_NAPOT), + _ => unreachable!() + } +} From 27a7a966265293427ca4df73e51816615cf9fccf Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:34:56 +0800 Subject: [PATCH 10/29] runtime: setup pmp + transfer to user --- artiq/firmware/runtime/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index c04ec3a05..45e73d78c 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -29,7 +29,7 @@ use core::cell::RefCell; use core::convert::TryFrom; use smoltcp::wire::IpCidr; -use board_misoc::{csr, ident, clock, spiflash, config, net_settings}; +use board_misoc::{csr, ident, clock, spiflash, config, net_settings, pmp, boot}; #[cfg(has_ethmac)] use board_misoc::ethmac; #[cfg(has_drtio)] @@ -247,10 +247,15 @@ pub extern fn main() -> i32 { extern { static mut _fheap: u8; static mut _eheap: u8; + static mut _sstack_guard: u8; } ALLOC.add_range(&mut _fheap, &mut _eheap); - logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(startup); + pmp::init_stack_guard(&_sstack_guard as *const u8 as usize); + + logger_artiq::BufferLogger::new(&mut LOG_BUFFER[..]).register(|| + boot::start_user(startup as usize) + ); 0 } From 0a59c889de60918d93433b96e5127bf1049613be Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:36:24 +0800 Subject: [PATCH 11/29] satman/kern: init locked PMP on startup --- artiq/firmware/ksupport/lib.rs | 4 +++- artiq/firmware/satman/main.rs | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index aaedbd018..f4a0ec2c7 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -23,7 +23,7 @@ use proto_artiq::{kernel_proto, rpc_proto}; use kernel_proto::*; #[cfg(has_rtio_dma)] use board_misoc::csr; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; fn send(request: &Message) { unsafe { mailbox::send(request as *const _ as usize) } @@ -493,11 +493,13 @@ pub unsafe fn main() { let _end = library.lookup(b"_end").unwrap(); let __modinit__ = library.lookup(b"__modinit__").unwrap(); let typeinfo = library.lookup(b"typeinfo"); + let _sstack_guard = library.lookup(b"_sstack_guard").unwrap(); LIBRARY = Some(library); ptr::write_bytes(__bss_start as *mut u8, 0, (_end - __bss_start) as usize); + board_misoc::pmp::init_stack_guard(_sstack_guard as usize); board_misoc::cache::flush_cpu_dcache(); board_misoc::cache::flush_cpu_icache(); diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index f9e3d9e7c..ef639b7f1 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -9,7 +9,7 @@ extern crate board_artiq; extern crate riscv; use core::convert::TryFrom; -use board_misoc::{csr, ident, clock, uart_logger, i2c}; +use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; #[cfg(has_si5324)] use board_artiq::si5324; #[cfg(has_wrpll)] @@ -449,6 +449,14 @@ const SI5324_SETTINGS: si5324::FrequencySettings #[no_mangle] pub extern fn main() -> i32 { + extern { + static mut _sstack_guard: u8; + } + + unsafe { + pmp::init_stack_guard(&_sstack_guard as *const u8 as usize); + } + clock::init(); uart_logger::ConsoleLogger::register(); From 46326716fd77e58678885773602fb583acfcf489 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:38:30 +0800 Subject: [PATCH 12/29] runtime: bump libfringe, impl ecall abi See libfringe PR: https://git.m-labs.hk/M-Labs/libfringe/pulls/1 --- artiq/firmware/Cargo.lock | 4 ++-- artiq/firmware/runtime/Cargo.toml | 2 +- artiq/firmware/runtime/main.rs | 12 ++++++++++++ artiq/firmware/runtime/sched.rs | 3 ++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index 194952672..dd890c625 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "fringe" version = "1.2.1" -source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=9748bb#9748bb8af86c131d45be1238ea4d5f965a974630" +source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=3ecbe5#3ecbe53f7644b18ee46ebd5b2ca12c9cbceec43a" dependencies = [ - "libc 0.2.101", + "libc 0.2.103", ] [[package]] diff --git a/artiq/firmware/runtime/Cargo.toml b/artiq/firmware/runtime/Cargo.toml index a29acbb86..ee987ad2d 100644 --- a/artiq/firmware/runtime/Cargo.toml +++ b/artiq/firmware/runtime/Cargo.toml @@ -32,6 +32,6 @@ riscv = { version = "0.6.0", features = ["inline-asm"] } [dependencies.fringe] git = "https://git.m-labs.hk/M-Labs/libfringe.git" -rev = "9748bb" +rev = "3ecbe5" default-features = false features = ["alloc"] diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 45e73d78c..04af01be0 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -290,6 +290,18 @@ pub extern fn exception(regs: *const TrapFrame) { mcause::Trap::Interrupt(source) => { info!("Called interrupt with {:?}", source); }, + + mcause::Trap::Exception(mcause::Exception::UserEnvCall) => { + unsafe { + if (*regs).a7 == 0 { + pmp::pop_pmp_region() + } else { + pmp::push_pmp_region((*regs).a7) + } + } + mepc::write(pc + 4); + }, + mcause::Trap::Exception(e) => { println!("Trap frame: {:x?}", unsafe { *regs }); diff --git a/artiq/firmware/runtime/sched.rs b/artiq/firmware/runtime/sched.rs index 7b182a3e4..d6a347269 100644 --- a/artiq/firmware/runtime/sched.rs +++ b/artiq/firmware/runtime/sched.rs @@ -61,7 +61,8 @@ impl Thread { let spawned = io.spawned.clone(); let sockets = io.sockets.clone(); - let stack = OwnedStack::new(stack_size); + // Add a 4k stack guard to the stack of any new threads + let stack = OwnedStack::new(stack_size + 4096); ThreadHandle::new(Thread { generator: Generator::unsafe_new(stack, |yielder, _| { f(Io { From 6d3164a9128d6896777f8e60a250229483b9b2df Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:41:01 +0800 Subject: [PATCH 13/29] riscv: print mtval on panic --- artiq/firmware/bootloader/main.rs | 5 +++-- artiq/firmware/ksupport/lib.rs | 3 ++- artiq/firmware/runtime/main.rs | 5 +++-- artiq/firmware/satman/main.rs | 5 +++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/artiq/firmware/bootloader/main.rs b/artiq/firmware/bootloader/main.rs index 1ef7426a1..9a41bdb4b 100644 --- a/artiq/firmware/bootloader/main.rs +++ b/artiq/firmware/bootloader/main.rs @@ -17,7 +17,7 @@ use board_misoc::slave_fpga; #[cfg(has_ethmac)] use board_misoc::{clock, ethmac, net_settings}; use board_misoc::uart_console::Console; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; fn check_integrity() -> bool { extern { @@ -522,7 +522,8 @@ pub extern fn main() -> i32 { pub extern fn exception(_regs: *const u32) { let pc = mepc::read(); let cause = mcause::read().cause(); - panic!("{:?} at PC {:#08x}", cause, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("{:?} at PC {:#08x}, trap value {:#08x}", cause, u32::try_from(pc).unwrap(), mtval); } #[no_mangle] diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index f4a0ec2c7..d915d7e81 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -532,7 +532,8 @@ pub unsafe fn main() { pub extern fn exception(_regs: *const u32) { let pc = mepc::read(); let cause = mcause::read().cause(); - panic!("{:?} at PC {:#08x}", cause, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("{:?} at PC {:#08x}, trap value {:#08x}", cause, u32::try_from(pc).unwrap(), mtval); } #[no_mangle] diff --git a/artiq/firmware/runtime/main.rs b/artiq/firmware/runtime/main.rs index 04af01be0..45fb76f91 100644 --- a/artiq/firmware/runtime/main.rs +++ b/artiq/firmware/runtime/main.rs @@ -40,7 +40,7 @@ use proto_artiq::{mgmt_proto, moninj_proto, rpc_proto, session_proto, kernel_pro #[cfg(has_rtio_analyzer)] use proto_artiq::analyzer_proto; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; mod rtio_clocking; mod rtio_mgt; @@ -319,7 +319,8 @@ pub extern fn exception(regs: *const TrapFrame) { } hexdump(u32::try_from(pc).unwrap()); - panic!("exception {:?} at PC 0x{:x}", e, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("exception {:?} at PC 0x{:x}, trap value 0x{:x}", e, u32::try_from(pc).unwrap(), mtval) } } } diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index ef639b7f1..e0ec83612 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -18,7 +18,7 @@ use board_artiq::{spi, drtioaux}; use board_artiq::drtio_routing; #[cfg(has_hmc830_7043)] use board_artiq::hmc830_7043; -use riscv::register::{mcause, mepc}; +use riscv::register::{mcause, mepc, mtval}; mod repeater; #[cfg(has_jdcg)] @@ -670,7 +670,8 @@ pub extern fn exception(_regs: *const u32) { } hexdump(u32::try_from(pc).unwrap()); - panic!("exception {:?} at PC 0x{:x}", cause, u32::try_from(pc).unwrap()) + let mtval = mtval::read(); + panic!("exception {:?} at PC 0x{:x}, trap value 0x{:x}", cause, u32::try_from(pc).unwrap(), mtval) } #[no_mangle] From d5fa3d131ac957c3d1fb0eed19bf5773b9bf664c Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 14:52:23 +0800 Subject: [PATCH 14/29] cargo.lock: update libc version for libfringe --- artiq/firmware/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/Cargo.lock b/artiq/firmware/Cargo.lock index dd890c625..77d262538 100644 --- a/artiq/firmware/Cargo.lock +++ b/artiq/firmware/Cargo.lock @@ -165,7 +165,7 @@ name = "fringe" version = "1.2.1" source = "git+https://git.m-labs.hk/M-Labs/libfringe.git?rev=3ecbe5#3ecbe53f7644b18ee46ebd5b2ca12c9cbceec43a" dependencies = [ - "libc 0.2.103", + "libc 0.2.101", ] [[package]] From bf180c168c9276937210eb6326785035335e9a92 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 8 Oct 2021 16:41:58 +0800 Subject: [PATCH 15/29] flake.lock: update dependencies --- flake.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/flake.lock b/flake.lock index e97a38179..e0cc41607 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1631098960, - "narHash": "sha256-6j6G/omHEFAnI2x7UvdrviGDNqiq1Fjd1A58Q6uc4sQ=", + "lastModified": 1633625029, + "narHash": "sha256-Ia3kwnN9DhcskAIElLSKb4u/OK7nZU/P0TkaikAX790=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12eb1d16ae3b6cbf0ea83e9228bca8ffd7cfe347", + "rev": "781b1f8e3a2194e1e233cd62b4f2193e129a07f7", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1628592379, - "narHash": "sha256-TQV6p0+Ri9HVge4qUKOCXe96cmcimNZ3R4sVwNY67DA=", + "lastModified": 1633615575, + "narHash": "sha256-frh+WVOkEKMpVEMhdE/GZKSj82XnSC8OF8SWNluk/Yg=", "owner": "m-labs", "repo": "migen", - "rev": "27dbf03edd75c32dc1706e2a1316950c3a8d452a", + "rev": "6e3f8e565704b4293174aedfb15b3470d233f528", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1631240866, - "narHash": "sha256-dal999XLFvS8Ol1hZnQjx7q/UfAXkzSMhAWcZKCDPx4=", + "lastModified": 1633679103, + "narHash": "sha256-1BPWfwetUZZCCZ+ldNKJvNm7Gls1AkmGYSZapNuM65s=", "ref": "master", - "rev": "c9572e777febf7abcfbebf624e0323d82600f267", - "revCount": 2371, + "rev": "7c1f614ed3ad9ce0fd3291feccb1e5e4ff65adb3", + "revCount": 2372, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" @@ -95,11 +95,11 @@ "src-sipyco": { "flake": false, "locked": { - "lastModified": 1623807309, - "narHash": "sha256-FTRAS4RjqDOygu6+cP8mKbZHu/YZ7YKpEe2gSzJc9rk=", + "lastModified": 1632832039, + "narHash": "sha256-GYXXCCOxNZyy6j7qScB3/QWUUCEVX+4tM4bXXVGXty0=", "owner": "m-labs", "repo": "sipyco", - "rev": "20c946aad78872fe60b78d9b57a624d69f3eea47", + "rev": "b83d8e5d82b25dba9393f0c12bdc5253f8138545", "type": "github" }, "original": { From 92cdfac35a969d851fda610802b96a576b8f9e76 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 16 Oct 2021 18:20:25 +0800 Subject: [PATCH 16/29] flake: fix cargoDeps sha256 --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 4cb3aea77..e44d4af74 100644 --- a/flake.nix +++ b/flake.nix @@ -238,7 +238,7 @@ cargoDeps = rustPlatform.fetchCargoTarball { name = "artiq-firmware-cargo-deps"; src = "${self}/artiq/firmware"; - sha256 = "0hh9x34gs81a8g15abka6a0z1wlankra13rbap5j7ba2r8cz4962"; + sha256 = "sha256-Lf6M4M/jdRiO5MsWSoqtOSNfRIhbze+qvg4kaiiBWW4="; }; nativeBuildInputs = [ (pkgs.python3.withPackages(ps: [ migen misoc artiq ])) From b0cbad530b4d8f28a8496f4aae258c4a30edef77 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 16 Oct 2021 19:10:28 +0800 Subject: [PATCH 17/29] flake: update dependencies --- flake.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index e0cc41607..a8bdf14b9 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1633625029, - "narHash": "sha256-Ia3kwnN9DhcskAIElLSKb4u/OK7nZU/P0TkaikAX790=", + "lastModified": 1634327140, + "narHash": "sha256-d5L7oMjUVC6VU0cQMsF0tceAPkmzuAQ51DWBFNChbEQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "781b1f8e3a2194e1e233cd62b4f2193e129a07f7", + "rev": "83667ff60a88e22b76ef4b0bdf5334670b39c2b6", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "src-migen": { "flake": false, "locked": { - "lastModified": 1633615575, - "narHash": "sha256-frh+WVOkEKMpVEMhdE/GZKSj82XnSC8OF8SWNluk/Yg=", + "lastModified": 1634182166, + "narHash": "sha256-Iw2d8fCgwuuIevkugSqd8Iplj6N+2nR1pn+or5E38Fk=", "owner": "m-labs", "repo": "migen", - "rev": "6e3f8e565704b4293174aedfb15b3470d233f528", + "rev": "7507a2bb16dd2cac63535175ce67fb30dfdae1c0", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1633679103, - "narHash": "sha256-1BPWfwetUZZCCZ+ldNKJvNm7Gls1AkmGYSZapNuM65s=", + "lastModified": 1634382477, + "narHash": "sha256-onIK8GhU6ZbFXsPXEs8IbAnCMZ6q8G9vJawNCWoF6JM=", "ref": "master", - "rev": "7c1f614ed3ad9ce0fd3291feccb1e5e4ff65adb3", - "revCount": 2372, + "rev": "794d29b6c0f10b3764372f89507dd363bb76b5b1", + "revCount": 2373, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From bb61f2dae6ce66edf72393eb49715c896119eaad Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 18 Oct 2021 10:38:28 +0800 Subject: [PATCH 18/29] flake: update dependencies --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index a8bdf14b9..eacc3db64 100644 --- a/flake.lock +++ b/flake.lock @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1634382477, - "narHash": "sha256-onIK8GhU6ZbFXsPXEs8IbAnCMZ6q8G9vJawNCWoF6JM=", + "lastModified": 1634524544, + "narHash": "sha256-/x9CPW0mnUR6hgHWzOSJY//P9k9w+gObNn2uwrxL8dw=", "ref": "master", - "rev": "794d29b6c0f10b3764372f89507dd363bb76b5b1", - "revCount": 2373, + "rev": "2acffae0ee51e569dc217a9f3cea06b33103d623", + "revCount": 2374, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From df6aeb99f6da58dc76deb30f92a32a2bcf1d6589 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 18 Oct 2021 11:09:10 +0800 Subject: [PATCH 19/29] flake: check gateware timing --- flake.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index e44d4af74..5d106f666 100644 --- a/flake.nix +++ b/flake.nix @@ -260,7 +260,9 @@ export TARGET_AR=llvm-ar ${buildCommand} ''; - checkPhase = '' + doCheck = true; + checkPhase = + '' # Search for PCREs in the Vivado output to check for errors check_log() { grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true From cc15a4f5729f28b6a2d3d9bbd1c58a3032e5be21 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 21 Oct 2021 11:24:55 +0800 Subject: [PATCH 20/29] flake: update Vivado --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 5d106f666..1f5e2afef 100644 --- a/flake.nix +++ b/flake.nix @@ -227,7 +227,7 @@ vivado = pkgs.buildFHSUserEnv { name = "vivado"; targetPkgs = vivadoDeps; - profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh"; + profile = "source /opt/Xilinx/Vivado/2021.1/settings64.sh"; runScript = "vivado"; }; From 43eab14f566d7205ea1261151c3078a17df0970a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 21 Oct 2021 15:06:38 +0800 Subject: [PATCH 21/29] flake: update dependencies --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index eacc3db64..e9c80a1ad 100644 --- a/flake.lock +++ b/flake.lock @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1634327140, - "narHash": "sha256-d5L7oMjUVC6VU0cQMsF0tceAPkmzuAQ51DWBFNChbEQ=", + "lastModified": 1634758644, + "narHash": "sha256-H3UW/msC6wadg28lcgZv2Ge/P7dWxesL6i37a0GOeyM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "83667ff60a88e22b76ef4b0bdf5334670b39c2b6", + "rev": "70904d4a9927a4d6e05c72c4aaac4370e05107f3", "type": "github" }, "original": { @@ -61,11 +61,11 @@ "src-misoc": { "flake": false, "locked": { - "lastModified": 1634524544, - "narHash": "sha256-/x9CPW0mnUR6hgHWzOSJY//P9k9w+gObNn2uwrxL8dw=", + "lastModified": 1634799783, + "narHash": "sha256-CbeXsLTwwYBWb5cfrVVYkcQYV207gi9+CQhzfeZbXGc=", "ref": "master", - "rev": "2acffae0ee51e569dc217a9f3cea06b33103d623", - "revCount": 2374, + "rev": "855914deace34880c69589022c52a8921f431063", + "revCount": 2375, "submodules": true, "type": "git", "url": "https://github.com/m-labs/misoc.git" From 0aa8a739aa076c821eb712bb2fb97967dbdb5c9a Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Mon, 25 Oct 2021 09:53:40 +0800 Subject: [PATCH 22/29] sayma_rtm: fix RTM firmware not in little-endian for RISC-V --- artiq/gateware/targets/sayma_rtm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gateware/targets/sayma_rtm.py b/artiq/gateware/targets/sayma_rtm.py index b4401e9e0..7fa740381 100755 --- a/artiq/gateware/targets/sayma_rtm.py +++ b/artiq/gateware/targets/sayma_rtm.py @@ -240,7 +240,7 @@ class SatmanSoCBuilder(Builder): "satman.bin") with open(satman, "rb") as boot_file: boot_data = [] - unpack_endian = ">I" + unpack_endian = " Date: Thu, 21 Oct 2021 15:00:48 +0800 Subject: [PATCH 23/29] artiq_flash: fix gateware header not in little-endian for RISC-V --- artiq/frontend/artiq_flash.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/frontend/artiq_flash.py b/artiq/frontend/artiq_flash.py index d7a5bdb78..1641e31fd 100755 --- a/artiq/frontend/artiq_flash.py +++ b/artiq/frontend/artiq_flash.py @@ -418,8 +418,8 @@ def main(): magic = 0x5352544d # "SRTM", see sayma_rtm target length = bin_file.tell() - 8 bin_file.seek(0) - bin_file.write(magic.to_bytes(4, byteorder="big")) - bin_file.write(length.to_bytes(4, byteorder="big")) + bin_file.write(magic.to_bytes(4, byteorder="little")) + bin_file.write(length.to_bytes(4, byteorder="little")) atexit.register(lambda: os.unlink(bin_filename)) return bin_filename From 10c37b87ecfc8b893bb8e5f8b4acc7e3b674ac54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Wed, 27 Oct 2021 20:24:58 +0000 Subject: [PATCH 24/29] fastino: make driver filter order configurable --- artiq/coredevice/fastino.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index c60d5d1b1..588a3d436 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -39,13 +39,15 @@ class Fastino: :param core_device: Core device name (default: "core") :param log2_width: Width of DAC channel group (logarithm base 2). Value must match the corresponding value in the RTIO PHY (gateware). + :param order: CIC filter interpolation order. """ - kernel_invariants = {"core", "channel", "width"} + kernel_invariants = {"core", "channel", "width", "order"} - def __init__(self, dmgr, channel, core_device="core", log2_width=0): + def __init__(self, dmgr, channel, core_device="core", log2_width=0, order=3): self.channel = channel << 8 self.core = dmgr.get(core_device) self.width = 1 << log2_width + self.order = order @kernel def init(self): @@ -222,8 +224,7 @@ class Fastino: Returns the actual interpolation rate. The actual overall interpolation gain including gain compensation is - `actual_rate**order/2**ceil(log2(actual_rate**order))` - where `order = 3`. + `actual_rate**order/2**ceil(log2(actual_rate**order))`. """ if rate <= 0 or rate > 1 << 16: raise ValueError("rate out of bounds") @@ -232,15 +233,14 @@ class Fastino: while rate_mantissa > 1 << 6: rate_exponent += 1 rate_mantissa >>= 1 - order = 3 gain = 1 - for i in range(order): + for i in range(self.order): gain *= rate_mantissa gain_exponent = 0 while gain > 1 << gain_exponent: gain_exponent += 1 - gain_exponent += order*rate_exponent - assert gain_exponent <= order*16 + gain_exponent += self.order*rate_exponent + assert gain_exponent <= self.order*16 self.stage_cic_mu(rate_mantissa - 1, rate_exponent, gain_exponent) return rate_mantissa << rate_exponent @@ -252,6 +252,6 @@ class Fastino: continous DAC updates enabled (see :meth:`set_continuous`). This resets and settles the interpolators. There will be no output - updates for the next `order = 3` input samples. + updates for the next `order` input samples. """ self.write(0x27, channel_mask) From 1ff474893df1a07399208c8dddbe3dec09879aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 28 Oct 2021 06:29:56 +0000 Subject: [PATCH 25/29] Revert "fastino: make driver filter order configurable" This reverts commit 10c37b87ecfc8b893bb8e5f8b4acc7e3b674ac54. --- artiq/coredevice/fastino.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index 588a3d436..c60d5d1b1 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -39,15 +39,13 @@ class Fastino: :param core_device: Core device name (default: "core") :param log2_width: Width of DAC channel group (logarithm base 2). Value must match the corresponding value in the RTIO PHY (gateware). - :param order: CIC filter interpolation order. """ - kernel_invariants = {"core", "channel", "width", "order"} + kernel_invariants = {"core", "channel", "width"} - def __init__(self, dmgr, channel, core_device="core", log2_width=0, order=3): + def __init__(self, dmgr, channel, core_device="core", log2_width=0): self.channel = channel << 8 self.core = dmgr.get(core_device) self.width = 1 << log2_width - self.order = order @kernel def init(self): @@ -224,7 +222,8 @@ class Fastino: Returns the actual interpolation rate. The actual overall interpolation gain including gain compensation is - `actual_rate**order/2**ceil(log2(actual_rate**order))`. + `actual_rate**order/2**ceil(log2(actual_rate**order))` + where `order = 3`. """ if rate <= 0 or rate > 1 << 16: raise ValueError("rate out of bounds") @@ -233,14 +232,15 @@ class Fastino: while rate_mantissa > 1 << 6: rate_exponent += 1 rate_mantissa >>= 1 + order = 3 gain = 1 - for i in range(self.order): + for i in range(order): gain *= rate_mantissa gain_exponent = 0 while gain > 1 << gain_exponent: gain_exponent += 1 - gain_exponent += self.order*rate_exponent - assert gain_exponent <= self.order*16 + gain_exponent += order*rate_exponent + assert gain_exponent <= order*16 self.stage_cic_mu(rate_mantissa - 1, rate_exponent, gain_exponent) return rate_mantissa << rate_exponent @@ -252,6 +252,6 @@ class Fastino: continous DAC updates enabled (see :meth:`set_continuous`). This resets and settles the interpolators. There will be no output - updates for the next `order` input samples. + updates for the next `order = 3` input samples. """ self.write(0x27, channel_mask) From 21b07dc6673454b74ac9116cad59df65e6d9a467 Mon Sep 17 00:00:00 2001 From: Harry Ho Date: Wed, 27 Oct 2021 17:01:03 +0800 Subject: [PATCH 26/29] flake: fix missing freetype & fontconfig libs for Vivado GUI mode --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 1f5e2afef..a43321d0e 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,8 @@ xorg.libXext xorg.libXtst xorg.libXi + freetype + fontconfig ]; sipyco = pkgs.python3Packages.buildPythonPackage { From 9b1d7e297d6afb98a8aa36fc18a4d30e97dbfba1 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Thu, 28 Oct 2021 16:21:51 +0800 Subject: [PATCH 27/29] runtime: clock input specification improvements closes #1735 --- RELEASE_NOTES.rst | 2 + artiq/firmware/runtime/rtio_clocking.rs | 252 ++++++++++++++---------- doc/manual/core_device.rst | 17 +- doc/manual/installing.rst | 16 +- 4 files changed, 183 insertions(+), 104 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index d9b325382..c743f2005 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -26,6 +26,8 @@ Highlights: TTL device (e.g. ``"ttl_0_counter"`` for the edge counter on TTL device``"ttl_0"``) * ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the repository when building the list of experiments. +* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage + of compile-time options. Breaking changes: diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index b6cf5f395..8f2560ead 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -4,29 +4,66 @@ use board_artiq::si5324; #[cfg(has_drtio)] use board_misoc::{csr, clock}; -#[derive(Debug)] +#[derive(Debug, PartialEq)] +#[allow(non_camel_case_types)] pub enum RtioClock { - Internal = 0, - External = 1 + Default, + Int_125, + Int_100, + Int_150, + Ext0_Bypass, + Ext0_Synth0_10to125, + Ext0_Synth0_100to125, + Ext0_Synth0_125to125, } +#[allow(unreachable_code)] fn get_rtio_clock_cfg() -> RtioClock { - config::read("rtio_clock", |result| { - match result { - Ok(b"i") => { - info!("using internal RTIO clock"); - RtioClock::Internal + config::read_str("rtio_clock", |result| { + let res = match result { + Ok("int_125") => RtioClock::Int_125, + Ok("int_100") => RtioClock::Int_100, + Ok("int_150") => RtioClock::Int_150, + Ok("ext0_bypass") => RtioClock::Ext0_Bypass, + Ok("ext0_bypass_125") => RtioClock::Ext0_Bypass, + Ok("ext0_bypass_100") => RtioClock::Ext0_Bypass, + Ok("ext0_synth0_10to125") => RtioClock::Ext0_Synth0_10to125, + Ok("ext0_synth0_100to125") => RtioClock::Ext0_Synth0_100to125, + Ok("ext0_synth0_125to125") => RtioClock::Ext0_Synth0_125to125, + Ok("i") => { + warn!("Using legacy rtio_clock setting ('i'). Falling back to default. This will be deprecated."); + RtioClock::Default }, - Ok(b"e") => { - info!("using external RTIO clock"); - RtioClock::External + Ok("e") => { + warn!("Using legacy rtio_clock setting ('e'). This will be deprecated."); + RtioClock::Ext0_Bypass }, _ => { - info!("using internal RTIO clock (by default)"); - RtioClock::Internal - }, + warn!("rtio_clock setting not recognised. Falling back to default."); + RtioClock::Default + } + }; + if res == RtioClock::Default { + #[cfg(any(si5324_ext_ref, ext_ref_frequency))] + warn!("si5324_ext_ref and ext_ref_frequency compile-time options are deprecated. Please use the rtio_clock coreconfig settings instead."); + #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "10.0"))] + return RtioClock::Ext0_Synth0_10to125; + #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "100.0"))] + return RtioClock::Ext0_Synth0_100to125; + #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "125.0"))] + return RtioClock::Ext0_Synth0_125to125; + #[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))] + return RtioClock::Int_125; + #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref)))] + return RtioClock::Int_150; + #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))] + return RtioClock::Int_100; + //in case nothing is set + return RtioClock::Int_125; } - }) + res + }) + } #[cfg(has_rtio_crg)] @@ -41,9 +78,19 @@ pub mod crg { #[cfg(has_rtio_clock_switch)] pub fn init(clk: RtioClock) -> bool { + let clk_sel: u8 = match clk { + RtioClock::Ext0_Bypass => { + info!("Using external clock"); + 1 + }, + _ => { + info!("Using internal RTIO clock"); + 0 + } + }; unsafe { csr::rtio_crg::pll_reset_write(1); - csr::rtio_crg::clock_sel_write(clk as u8); + csr::rtio_crg::clock_sel_write(clk_sel); csr::rtio_crg::pll_reset_write(0); } clock::spin_us(150); @@ -52,6 +99,7 @@ pub mod crg { #[cfg(not(has_rtio_clock_switch))] pub fn init() -> bool { + info!("Using internal RTIO clock"); unsafe { csr::rtio_crg::pll_reset_write(0); } @@ -66,84 +114,86 @@ pub mod crg { } #[cfg(si5324_as_synthesizer)] -fn setup_si5324_as_synthesizer() { - // 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW - #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "10.0"))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 10, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 300, - n31 : 6, - n32 : 6, - bwsel : 4, - crystal_ref: false - }; - // 125MHz output, from 100MHz CLKINx reference, 586 Hz loop bandwidth - #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "100.0"))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 10, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 260, - n31 : 52, - n32 : 52, - bwsel : 4, - crystal_ref: false - }; - // 125MHz output, from 125MHz CLKINx reference, 606 Hz loop bandwidth - #[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "125.0"))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 5, - nc1_ls : 8, - n2_hs : 7, - n2_ls : 360, - n31 : 63, - n32 : 63, - bwsel : 4, - crystal_ref: false - }; - // 125MHz output, from crystal, 7 Hz - #[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))] - 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 - }; - // 150MHz output, from crystal - #[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref)))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 9, - nc1_ls : 4, - n2_hs : 10, - n2_ls : 33732, - n31 : 7139, - n32 : 7139, - bwsel : 3, - crystal_ref: true - }; - // 100MHz output, from crystal. Also used as reference for Sayma HMC830. - #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))] - const SI5324_SETTINGS: si5324::FrequencySettings - = si5324::FrequencySettings { - n1_hs : 9, - nc1_ls : 6, - n2_hs : 10, - n2_ls : 33732, - n31 : 7139, - n32 : 7139, - bwsel : 3, - crystal_ref: true +fn setup_si5324_as_synthesizer(cfg: RtioClock) { + let si5324_settings = match cfg { + RtioClock::Ext0_Synth0_10to125 => { // 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW + info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 300, + n31 : 6, + n32 : 6, + bwsel : 4, + crystal_ref: false + } + }, + RtioClock::Ext0_Synth0_100to125 => { // 125MHz output, from 100MHz CLKINx reference, 586 Hz loop bandwidth + info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 260, + n31 : 52, + n32 : 52, + bwsel : 4, + crystal_ref: false + } + }, + RtioClock::Ext0_Synth0_125to125 => { // 125MHz output, from 125MHz CLKINx reference, 606 Hz loop bandwidth + info!("using 10MHz reference to make 125MHz RTIO clock with PLL"); + si5324::FrequencySettings { + n1_hs : 5, + nc1_ls : 8, + n2_hs : 7, + n2_ls : 360, + n31 : 63, + n32 : 63, + bwsel : 4, + crystal_ref: false + } + }, + RtioClock::Int_150 => { // 150MHz output, from crystal + info!("using internal 150MHz RTIO clock"); + si5324::FrequencySettings { + n1_hs : 9, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 33732, + n31 : 7139, + n32 : 7139, + bwsel : 3, + crystal_ref: true + } + }, + RtioClock::Int_100 => { // 100MHz output, from crystal. Also used as reference for Sayma HMC830. + info!("using internal 100MHz RTIO clock"); + si5324::FrequencySettings { + n1_hs : 9, + nc1_ls : 6, + n2_hs : 10, + n2_ls : 33732, + n31 : 7139, + n32 : 7139, + bwsel : 3, + crystal_ref: true + } + }, + _ => { // 125MHz output, from crystal, 7 Hz, default (if chosen option is not supported) + info!("using internal 125MHz RTIO clock"); // covers also RtioClock::Int_125 + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 19972, + n31 : 4565, + n32 : 4565, + bwsel : 4, + crystal_ref: true + } + } }; #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0", not(si5324_ext_ref)))] let si5324_ref_input = si5324::Input::Ckin2; @@ -155,10 +205,11 @@ fn setup_si5324_as_synthesizer() { let si5324_ref_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] let si5324_ref_input = si5324::Input::Ckin2; - si5324::setup(&SI5324_SETTINGS, si5324_ref_input).expect("cannot initialize Si5324"); + si5324::setup(&si5324_settings, si5324_ref_input).expect("cannot initialize Si5324"); } pub fn init() { + let clock_cfg = get_rtio_clock_cfg(); #[cfg(si5324_as_synthesizer)] { #[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))] @@ -169,9 +220,12 @@ pub fn init() { let si5324_ext_input = si5324::Input::Ckin2; #[cfg(soc_platform = "kc705")] let si5324_ext_input = si5324::Input::Ckin2; - match get_rtio_clock_cfg() { - RtioClock::Internal => setup_si5324_as_synthesizer(), - RtioClock::External => si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324") + match clock_cfg { + RtioClock::Ext0_Bypass => { + info!("using external RTIO clock with PLL bypass"); + si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324") + }, + _ => setup_si5324_as_synthesizer(clock_cfg), } } @@ -189,7 +243,7 @@ pub fn init() { #[cfg(has_rtio_crg)] { #[cfg(has_rtio_clock_switch)] - let result = crg::init(get_rtio_clock_cfg()); + let result = crg::init(clock_cfg); #[cfg(not(has_rtio_clock_switch))] let result = crg::init(); if !result { diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index bb38c2b9e..fa3466d32 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -164,6 +164,19 @@ See :mod:`artiq.coredevice.i2c` for more details. Clocking ++++++++ -The KC705 supports an internal 125 MHz RTIO clock (based on its crystal oscillator) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. Valid values are ``i`` and ``e``, and the default is ``i``. The selected option can be observed in the core device boot logs. +The KC705 in standalone variants supports an internal 125 MHz RTIO clock (based on its crystal oscillator, or external reference for PLL for DRTIO variants) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. Valid values are: + * ``int_125`` - internal crystal oscillator, 125 MHz output (default), + * ``ext0_bypass`` - external clock. -On Kasli, ``rtio_clock=i`` is the default and generates the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference (variant-dependent). ``rtio_clock=e`` bypasses that PLL and the user must supply the RTIO clock (typically 125 MHz) at the Kasli front panel SMA input. Bypassing the PLL ensures the skews between input clock, Kasli downstream clock outputs, and RTIO clock are deterministic accross reboots of the system. This is useful when phase determinism is required in situtations where the reference clock fans out to other devices before reaching Kasli. +KC705 in DRTIO variants and Kasli generates the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference. Valid values are: + * ``int_125`` - internal crystal oscillator using PLL, 125 MHz output (default), + * ``int_100`` - internal crystal oscillator using PLL, 100 MHz output, + * ``int_150`` - internal crystal oscillator using PLL, 150 MHz output, + * ``ext0_synth0_10to125`` - external 10 MHz reference using PLL, 125 MHz output, + * ``ext0_synth0_100to125`` - external 100 MHz reference using PLL, 125 MHz output, + * ``ext0_synth0_125to125`` - external 125 MHz reference using PLL, 125 MHz output, + * ``ext0_bypass``, ``ext0_bypass_125``, ``ext0_bypass_100`` - external clock - with explicit aliases available. + +The selected option can be observed in the core device boot logs. + +Options ``rtio_clock=int_XXX`` and ``rtio_clock=ext0_synth0_XXXXX`` generate the RTIO clock using a PLL locked either to an internal crystal or to an external frequency reference (depending on exact option). ``rtio_clock=ext0_bypass`` bypasses that PLL and the user must supply the RTIO clock (typically 125 MHz) at the Kasli front panel SMA input. Bypassing the PLL ensures the skews between input clock, Kasli downstream clock outputs, and RTIO clock are deterministic accross reboots of the system. This is useful when phase determinism is required in situtations where the reference clock fans out to other devices before reaching Kasli. diff --git a/doc/manual/installing.rst b/doc/manual/installing.rst index 41b1ebc82..0b9ac8c18 100644 --- a/doc/manual/installing.rst +++ b/doc/manual/installing.rst @@ -288,7 +288,17 @@ If you are using DRTIO and the default routing table (for a star topology) is no * Select the RTIO clock source (KC705 and Kasli) -The KC705 may use either an external clock signal or its internal clock. The clock is selected at power-up. For Kasli, setting the RTIO clock source to "external" would bypass the Si5324 synthesiser, requiring that an input clock be present. To select the source, use one of these commands: :: +The KC705 may use either an external clock signal, or its internal clock with external frequency or internal crystal reference. The clock is selected at power-up. Setting the RTIO clock source to "ext0_bypass" would bypass the Si5324 synthesiser, requiring that an input clock be present. To select the source, use one of these commands: :: - $ artiq_coremgmt config write -s rtio_clock i # internal clock (default) - $ artiq_coremgmt config write -s rtio_clock e # external clock + $ artiq_coremgmt config write -s rtio_clock int_125 # internal 125MHz clock (default) + $ artiq_coremgmt config write -s rtio_clock ext0_bypass # external clock (bypass) + +Other options include: + - ``ext0_synth0_10to125`` - external 10MHz reference clock used by Si5324 to synthesize a 125MHz RTIO clock, + - ``ext0_synth0_100to125`` - exteral 100MHz reference clock used by Si5324 to synthesize a 125MHz RTIO clock, + - ``ext0_synth0_125to125`` - exteral 125MHz reference clock used by Si5324 to synthesize a 125MHz RTIO clock, + - ``int_100`` - internal crystal reference is used by Si5324 to synthesize a 100MHz RTIO clock, + - ``int_150`` - internal crystal reference is used by Si5324 to synthesize a 150MHz RTIO clock. + - ``ext0_bypass_125`` and ``ext0_bypass_100`` - explicit aliases for ``ext0_bypass``. + +Availability of these options depends on the board and their configuration - specific setting may or may not be supported. \ No newline at end of file From 69cddc6b862a85823d28e6339d3a94415e21eee9 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Thu, 28 Oct 2021 16:34:22 +0800 Subject: [PATCH 28/29] rtio_clocking: add warnings for unsupported rtio_clock settings (#1773) --- artiq/firmware/runtime/rtio_clocking.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/artiq/firmware/runtime/rtio_clocking.rs b/artiq/firmware/runtime/rtio_clocking.rs index 8f2560ead..f0330b4d9 100644 --- a/artiq/firmware/runtime/rtio_clocking.rs +++ b/artiq/firmware/runtime/rtio_clocking.rs @@ -83,9 +83,13 @@ pub mod crg { info!("Using external clock"); 1 }, - _ => { + RtioClock::Int_125 => { info!("Using internal RTIO clock"); 0 + }, + _ => { + warn!("rtio_clock setting '{:?}' is not supported. Using default internal RTIO clock instead", clk); + 0 } }; unsafe { @@ -181,8 +185,21 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) { crystal_ref: true } }, - _ => { // 125MHz output, from crystal, 7 Hz, default (if chosen option is not supported) - info!("using internal 125MHz RTIO clock"); // covers also RtioClock::Int_125 + RtioClock::Int_125 => { // 125MHz output, from crystal, 7 Hz + info!("using internal 125MHz RTIO clock"); + si5324::FrequencySettings { + n1_hs : 10, + nc1_ls : 4, + n2_hs : 10, + n2_ls : 19972, + n31 : 4565, + n32 : 4565, + bwsel : 4, + crystal_ref: true + } + } + _ => { // 125MHz output like above, default (if chosen option is not supported) + warn!("rtio_clock setting '{:?}' is not supported. Falling back to default internal 125MHz RTIO clock.", cfg); si5324::FrequencySettings { n1_hs : 10, nc1_ls : 4, From 5a5b0cc7c0175bf945c04b44f1aacc504e2f26d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Thu, 28 Oct 2021 15:19:48 +0000 Subject: [PATCH 29/29] fastino: expand docs --- artiq/coredevice/fastino.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index c60d5d1b1..193a9d9ba 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -200,7 +200,7 @@ class Fastino: @kernel def stage_cic_mu(self, rate_mantissa, rate_exponent, gain_exponent): - """Stage machine unit interpolator configuration. + """Stage machine unit CIC interpolator configuration. """ if rate_mantissa < 0 or rate_mantissa >= 1 << 6: raise ValueError("rate_mantissa out of bounds") @@ -215,15 +215,18 @@ class Fastino: def stage_cic(self, rate) -> TInt32: """Compute and stage interpolator configuration. - Approximates rate using 6+4 bit floating point representation, - approximates optimal interpolation gain compensation exponent to avoid - clipping. Gains for rates that are powers of two are accurately - compensated. Other rates lead to overall less than unity gain. + This method approximates the desired interpolation rate using a 10 bit + floating point representation (6 bit mantissa, 4 bit exponent) and + then determines an optimal interpolation gain compensation exponent + to avoid clipping. Gains for rates that are powers of two are accurately + compensated. Other rates lead to overall less than unity gain (but more + than 0.5 gain). - Returns the actual interpolation rate. - The actual overall interpolation gain including gain compensation is + The overall gain including gain compensation is `actual_rate**order/2**ceil(log2(actual_rate**order))` where `order = 3`. + + Returns the actual interpolation rate. """ if rate <= 0 or rate > 1 << 16: raise ValueError("rate out of bounds") @@ -248,10 +251,21 @@ class Fastino: def apply_cic(self, channel_mask): """Apply the staged interpolator configuration on the specified channels. - Channels using non-unity interpolation rate and variable data should have - continous DAC updates enabled (see :meth:`set_continuous`). + Each Fastino channel includes a fourth order (cubic) CIC interpolator with + variable rate change and variable output gain compensation (see + :meth:`stage_cic`). - This resets and settles the interpolators. There will be no output - updates for the next `order = 3` input samples. + Channels using non-unity interpolation rate should have + continous DAC updates enabled (see :meth:`set_continuous`) unless + their output is supposed to be constant. + + This method resets and settles the affected interpolators. There will be + no output updates for the next `order = 3` input samples. + Affected channels will only accept one input sample per input sample + period. This method synchronizes the input sample period to the current + frame on the affected channels. + + If application of new interpolator settings results in a change of the + overall gain, there will be a corresponding output step. """ self.write(0x27, channel_mask)