diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index f329d0c8d..83d10d2ac 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -35,6 +35,8 @@ ARTIQ-4 * ``artiq.coredevice.dds`` has been renamed to ``artiq.coredevice.ad9914`` and simplified. DDS batch mode is no longer supported. The ``core_dds`` device is no longer necessary. +* The configuration entry ``startup_clock`` is renamed ``rtio_clock``. Switching + clocks dynamically (i.e. without device restart) is no longer supported. ARTIQ-3 diff --git a/artiq/coredevice/comm_kernel.py b/artiq/coredevice/comm_kernel.py index e79f72f3d..5939fb52d 100644 --- a/artiq/coredevice/comm_kernel.py +++ b/artiq/coredevice/comm_kernel.py @@ -16,7 +16,6 @@ logger = logging.getLogger(__name__) class Request(Enum): SystemInfo = 3 - SwitchClock = 4 LoadKernel = 5 RunKernel = 6 @@ -27,8 +26,6 @@ class Request(Enum): class Reply(Enum): SystemInfo = 2 - ClockSwitchCompleted = 3 - ClockSwitchFailed = 4 LoadCompleted = 5 LoadFailed = 6 @@ -60,9 +57,6 @@ class CommKernelDummy: def __init__(self): pass - def switch_clock(self, external): - pass - def load(self, kernel_library): pass @@ -237,12 +231,6 @@ class CommKernel: if not finished_cleanly: logger.warning("Previous kernel did not cleanly finish") - def switch_clock(self, external): - self._write_header(Request.SwitchClock) - self._write_int8(external) - - self._read_empty(Reply.ClockSwitchCompleted) - def load(self, kernel_library): self._write_header(Request.LoadKernel) self._write_bytes(kernel_library) diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 300085882..9f84efe60 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -62,8 +62,6 @@ class Core: clocked at 125MHz and a SERDES multiplication factor of 8, the reference period is 1ns. The time machine unit is equal to this period. - :param external_clock: whether the core device should switch to its - external RTIO clock input instead of using its internal oscillator. :param ref_multiplier: ratio between the RTIO fine timestamp frequency and the RTIO coarse timestamp frequency (e.g. SERDES multiplication factor). @@ -71,13 +69,10 @@ class Core: kernel_invariants = { "core", "ref_period", "coarse_ref_period", "ref_multiplier", - "external_clock", } - def __init__(self, dmgr, host, ref_period, external_clock=False, - ref_multiplier=8): + def __init__(self, dmgr, host, ref_period, ref_multiplier=8): self.ref_period = ref_period - self.external_clock = external_clock self.ref_multiplier = ref_multiplier self.coarse_ref_period = ref_period*ref_multiplier if host is None: @@ -129,7 +124,6 @@ class Core: if self.first_run: self.comm.check_system_info() - self.comm.switch_clock(self.external_clock) self.first_run = False self.comm.load(kernel_library) diff --git a/artiq/firmware/libproto_artiq/session_proto.rs b/artiq/firmware/libproto_artiq/session_proto.rs index c2867c7d4..cc0012da5 100644 --- a/artiq/firmware/libproto_artiq/session_proto.rs +++ b/artiq/firmware/libproto_artiq/session_proto.rs @@ -64,7 +64,6 @@ fn write_sync(writer: &mut W) -> Result<(), IoError> #[derive(Debug)] pub enum Request { SystemInfo, - SwitchClock(u8), LoadKernel(Vec), RunKernel, @@ -87,8 +86,6 @@ pub enum Reply<'a> { ident: &'a str, finished_cleanly: bool }, - ClockSwitchCompleted, - ClockSwitchFailed, LoadCompleted, LoadFailed(&'a str), @@ -118,10 +115,7 @@ impl Request { { read_sync(reader)?; Ok(match reader.read_u8()? { - // 1-2, 13 were log requests - 3 => Request::SystemInfo, - 4 => Request::SwitchClock(reader.read_u8()?), 5 => Request::LoadKernel(reader.read_bytes()?), 6 => Request::RunKernel, @@ -141,10 +135,6 @@ impl Request { function: reader.read_string()? }, - // 9-12 were flash requests - - // 14 was hotswap request - ty => return Err(Error::UnknownPacket(ty)) }) } @@ -156,20 +146,12 @@ impl<'a> Reply<'a> { { write_sync(writer)?; match *self { - // 1 was log reply - Reply::SystemInfo { ident, finished_cleanly } => { writer.write_u8(2)?; writer.write(b"AROR")?; writer.write_string(ident)?; writer.write_u8(finished_cleanly as u8)?; }, - Reply::ClockSwitchCompleted => { - writer.write_u8(3)?; - }, - Reply::ClockSwitchFailed => { - writer.write_u8(4)?; - }, Reply::LoadCompleted => { writer.write_u8(5)?; @@ -209,16 +191,12 @@ impl<'a> Reply<'a> { writer.write_u8(async as u8)?; }, - // 11-13 were flash requests - Reply::WatchdogExpired => { writer.write_u8(14)?; }, Reply::ClockFailure => { writer.write_u8(15)?; }, - - // 16 was hotswap imminent reply } Ok(()) } diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index 01ba1a4b9..814c021e2 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -1,28 +1,32 @@ -use board_misoc::{csr, config}; +use board_misoc::csr; +#[cfg(has_rtio_clock_switch)] +use board_misoc::config; use sched::Io; #[cfg(has_rtio_crg)] pub mod crg { use board_misoc::{clock, csr}; - pub fn init() { - unsafe { csr::rtio_crg::pll_reset_write(0) } - } - pub fn check() -> bool { unsafe { csr::rtio_crg::pll_locked_read() != 0 } } - pub fn switch_clock(clk: u8) -> bool { + #[cfg(has_rtio_clock_switch)] + pub fn init(clk: u8) -> bool { unsafe { - let cur_clk = csr::rtio_crg::clock_sel_read(); - if clk != cur_clk { - csr::rtio_crg::pll_reset_write(1); - csr::rtio_crg::clock_sel_write(clk); - csr::rtio_crg::pll_reset_write(0); - } + csr::rtio_crg::pll_reset_write(1); + csr::rtio_crg::clock_sel_write(clk); + csr::rtio_crg::pll_reset_write(0); } + clock::spin_us(150); + return check() + } + #[cfg(not(has_rtio_clock_switch))] + pub fn init() -> bool { + unsafe { + csr::rtio_crg::pll_reset_write(0); + } clock::spin_us(150); return check() } @@ -30,9 +34,7 @@ pub mod crg { #[cfg(not(has_rtio_crg))] pub mod crg { - pub fn init() {} pub fn check() -> bool { true } - pub fn switch_clock(_clk: u8) -> bool { true } } #[cfg(has_drtio)] @@ -227,40 +229,43 @@ fn async_error_thread(io: Io) { } pub fn startup(io: &Io) { - crg::init(); + #[cfg(has_rtio_crg)] + { + #[cfg(has_rtio_clock_switch)] + { + #[derive(Debug)] + enum RtioClock { + Internal = 0, + External = 1 + }; - #[derive(Debug)] - enum RtioClock { - Internal = 0, - External = 1 - }; + let clk = config::read("rtio_clock", |result| { + match result { + Ok(b"i") => { + info!("using internal RTIO clock"); + RtioClock::Internal + }, + Ok(b"e") => { + info!("using external RTIO clock"); + RtioClock::External + }, + _ => { + info!("using internal RTIO clock (by default)"); + RtioClock::Internal + }, + } + }); - let clk = config::read("startup_clock", |result| { - match result { - Ok(b"i") => { - info!("using internal startup RTIO clock"); - RtioClock::Internal - }, - Ok(b"e") => { - info!("using external startup RTIO clock"); - RtioClock::External - }, - Err(_) => { - info!("using internal startup RTIO clock (by default)"); - RtioClock::Internal - }, - Ok(_) => { - error!("unrecognized startup_clock configuration entry, \ - using internal RTIO clock"); - RtioClock::Internal + if !crg::init(clk as u8) { + error!("RTIO clock failed"); + } + } + #[cfg(not(has_rtio_clock_switch))] + { + if !crg::init() { + error!("RTIO clock failed"); } } - }); - - if !crg::switch_clock(clk as u8) { - error!("startup RTIO clock failed"); - warn!("this may cause the system initialization to fail"); - warn!("fix clocking and reset the device"); } drtio::startup(io); diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index ca98fdbb6..d9812861b 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -250,24 +250,6 @@ fn process_host_message(io: &Io, session.congress.finished_cleanly.set(true) } - host::Request::SwitchClock(clk) => { - if session.running() { - unexpected!("attempted to switch RTIO clock while a kernel was running") - } - - #[cfg(has_rtio_core)] - { - if rtio_mgt::crg::switch_clock(clk) { - host_write(stream, host::Reply::ClockSwitchCompleted)?; - } else { - host_write(stream, host::Reply::ClockSwitchFailed)?; - } - } - - #[cfg(not(has_rtio_core))] - host_write(stream, host::Reply::ClockSwitchFailed)? - } - host::Request::LoadKernel(kernel) => match unsafe { kern_load(io, session, &kernel) } { Ok(()) => host_write(stream, host::Reply::LoadCompleted)?, diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index b1c85b99b..bdc2b283d 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -29,25 +29,22 @@ from artiq import __version__ as artiq_version class _RTIOCRG(Module, AutoCSR): - def __init__(self, platform, rtio_internal_clk): - self._clock_sel = CSRStorage() + def __init__(self, platform): 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() - clk_synth_se = Signal() clk_synth = platform.request("si5324_clkout_fabric") + clk_synth_se = Signal() + clk_synth_buffered = Signal() platform.add_period_constraint(clk_synth.p, 8.0) self.specials += [ Instance("IBUFGDS", p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="TRUE", i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se), - Instance("BUFG", i_I=clk_synth_se, o_O=rtio_external_clk), + Instance("BUFG", i_I=clk_synth_se, o_O=clk_synth_buffered), ] - platform.add_false_path_constraints( - rtio_external_clk, rtio_internal_clk) pll_locked = Signal() rtio_clk = Signal() @@ -59,9 +56,9 @@ class _RTIOCRG(Module, AutoCSR): 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, + i_CLKIN2=clk_synth_buffered, # Warning: CLKINSEL=0 means CLKIN2 is selected - i_CLKINSEL=~self._clock_sel.storage, + i_CLKINSEL=0, # VCO @ 1GHz when using 125MHz input p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1, @@ -123,7 +120,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): self.config["SI5324_SOFT_RESET"] = None def add_rtio(self, rtio_channels): - self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk) + self.submodules.rtio_crg = _RTIOCRG(self.platform) self.csr_devices.append("rtio_crg") fix_serdes_timing_path(self.platform) self.submodules.rtio_core = rtio.Core(rtio_channels) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index a3eea1949..39f26afa8 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -256,6 +256,7 @@ class _StandaloneBase(MiniSoC, AMPSoC): def add_rtio(self, rtio_channels): self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk) self.csr_devices.append("rtio_crg") + self.config["HAS_RTIO_CLOCK_SWITCH"] = None self.submodules.rtio_core = rtio.Core(rtio_channels) self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator() @@ -502,6 +503,7 @@ class SMA_SPI(_StandaloneBase): self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk, use_sma=False) self.csr_devices.append("rtio_crg") + self.config["HAS_RTIO_CLOCK_SWITCH"] = None self.submodules.rtio_core = rtio.Core(rtio_channels) self.csr_devices.append("rtio_core") self.submodules.rtio = rtio.KernelInitiator() diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index ef269277f..e9dff441c 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -159,6 +159,11 @@ To avoid I/O contention, the startup kernel should first program the TCA6424A ex See :mod:`artiq.coredevice.i2c` for more details. +Clocking +++++++++ + +The KC705 supports an internal 125MHz RTIO clock (based on its crystal oscillator) and an external clock, that can be selected using the ``rtio_clock`` configuration entry. + Kasli ----- diff --git a/doc/manual/installing.rst b/doc/manual/installing.rst index da9affe38..7b726e2ec 100644 --- a/doc/manual/installing.rst +++ b/doc/manual/installing.rst @@ -189,12 +189,12 @@ The startup kernel is executed once when the core device powers up. It should in For DRTIO systems, the startup kernel should wait until the desired links are up, using :meth:`artiq.coredevice.Core.get_drtio_link_status`. -* (optional) Select the startup clock +* (optional) Select the RTIO clock source -The core device may use either an external clock signal or its internal clock. This clock can be switched dynamically after the PC is connected using the ``external_clock`` parameter of the core device driver; however, one may want to select the clock at power-up so that it is used for the startup and idle kernels. Use one of these commands: :: +Some core devices may use either an external clock signal or their internal clock. The clock is selected at power-up. Use one of these commands: :: - $ artiq_coreconfig write -s startup_clock i # internal clock (default) - $ artiq_coreconfig write -s startup_clock e # external clock + $ artiq_coreconfig write -s rtio_clock i # internal clock (default) + $ artiq_coreconfig write -s rtio_clock e # external clock .. rubric:: Footnotes