From 9b1d7e297d6afb98a8aa36fc18a4d30e97dbfba1 Mon Sep 17 00:00:00 2001 From: Spaqin Date: Thu, 28 Oct 2021 16:21:51 +0800 Subject: [PATCH] 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