forked from M-Labs/artiq
Merge branch 'master' into nac3
This commit is contained in:
commit
977543e05a
|
@ -24,6 +24,10 @@ Highlights:
|
||||||
- HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino
|
- HVAMP_8CH 8 channel HV amplifier for Fastino / Zotino
|
||||||
* ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding
|
* ``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"``)
|
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:
|
Breaking changes:
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ streaming DAC.
|
||||||
"""
|
"""
|
||||||
from numpy import int32
|
from numpy import int32
|
||||||
|
|
||||||
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,
|
from artiq.coredevice.rtio import (rtio_output, rtio_output_wide,
|
||||||
rtio_input_data)
|
rtio_input_data)
|
||||||
from artiq.language.units import us
|
from artiq.language.units import us
|
||||||
|
@ -191,3 +191,82 @@ class Fastino:
|
||||||
green LED.
|
green LED.
|
||||||
"""
|
"""
|
||||||
self.write(0x23, leds)
|
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 CIC 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.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
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")
|
||||||
|
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.
|
||||||
|
|
||||||
|
Each Fastino channel includes a fourth order (cubic) CIC interpolator with
|
||||||
|
variable rate change and variable output gain compensation (see
|
||||||
|
:meth:`stage_cic`).
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
@ -203,6 +203,7 @@ class Phaser:
|
||||||
self.measure_frame_timestamp()
|
self.measure_frame_timestamp()
|
||||||
if self.frame_tstamp < 0:
|
if self.frame_tstamp < 0:
|
||||||
raise ValueError("frame timestamp measurement timed out")
|
raise ValueError("frame timestamp measurement timed out")
|
||||||
|
delay(.1*ms)
|
||||||
|
|
||||||
# reset
|
# reset
|
||||||
self.set_cfg(dac_resetb=0, dac_sleep=1, dac_txena=0,
|
self.set_cfg(dac_resetb=0, dac_sleep=1, dac_txena=0,
|
||||||
|
|
|
@ -163,7 +163,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fringe"
|
name = "fringe"
|
||||||
version = "1.2.1"
|
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 = [
|
dependencies = [
|
||||||
"libc 0.2.101",
|
"libc 0.2.101",
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,7 +17,7 @@ use board_misoc::slave_fpga;
|
||||||
#[cfg(has_ethmac)]
|
#[cfg(has_ethmac)]
|
||||||
use board_misoc::{clock, ethmac, net_settings};
|
use board_misoc::{clock, ethmac, net_settings};
|
||||||
use board_misoc::uart_console::Console;
|
use board_misoc::uart_console::Console;
|
||||||
use riscv::register::{mcause, mepc};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
|
|
||||||
fn check_integrity() -> bool {
|
fn check_integrity() -> bool {
|
||||||
extern {
|
extern {
|
||||||
|
@ -522,7 +522,8 @@ pub extern fn main() -> i32 {
|
||||||
pub extern fn exception(_regs: *const u32) {
|
pub extern fn exception(_regs: *const u32) {
|
||||||
let pc = mepc::read();
|
let pc = mepc::read();
|
||||||
let cause = mcause::read().cause();
|
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]
|
#[no_mangle]
|
||||||
|
|
|
@ -23,7 +23,7 @@ use proto_artiq::{kernel_proto, rpc_proto};
|
||||||
use kernel_proto::*;
|
use kernel_proto::*;
|
||||||
#[cfg(has_rtio_dma)]
|
#[cfg(has_rtio_dma)]
|
||||||
use board_misoc::csr;
|
use board_misoc::csr;
|
||||||
use riscv::register::{mcause, mepc};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
|
|
||||||
fn send(request: &Message) {
|
fn send(request: &Message) {
|
||||||
unsafe { mailbox::send(request as *const _ as usize) }
|
unsafe { mailbox::send(request as *const _ as usize) }
|
||||||
|
@ -493,11 +493,13 @@ pub unsafe fn main() {
|
||||||
let _end = library.lookup(b"_end").unwrap();
|
let _end = library.lookup(b"_end").unwrap();
|
||||||
let __modinit__ = library.lookup(b"__modinit__").unwrap();
|
let __modinit__ = library.lookup(b"__modinit__").unwrap();
|
||||||
let typeinfo = library.lookup(b"typeinfo");
|
let typeinfo = library.lookup(b"typeinfo");
|
||||||
|
let _sstack_guard = library.lookup(b"_sstack_guard").unwrap();
|
||||||
|
|
||||||
LIBRARY = Some(library);
|
LIBRARY = Some(library);
|
||||||
|
|
||||||
ptr::write_bytes(__bss_start as *mut u8, 0, (_end - __bss_start) as usize);
|
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_dcache();
|
||||||
board_misoc::cache::flush_cpu_icache();
|
board_misoc::cache::flush_cpu_icache();
|
||||||
|
|
||||||
|
@ -530,7 +532,8 @@ pub unsafe fn main() {
|
||||||
pub extern fn exception(_regs: *const u32) {
|
pub extern fn exception(_regs: *const u32) {
|
||||||
let pc = mepc::read();
|
let pc = mepc::read();
|
||||||
let cause = mcause::read().cause();
|
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]
|
#[no_mangle]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::cache;
|
use super::{cache, pmp};
|
||||||
|
use riscv::register::*;
|
||||||
|
|
||||||
pub unsafe fn reset() -> ! {
|
pub unsafe fn reset() -> ! {
|
||||||
llvm_asm!(r#"
|
llvm_asm!(r#"
|
||||||
|
@ -16,3 +17,14 @@ pub unsafe fn jump(addr: usize) -> ! {
|
||||||
"# : : "r"(addr) : : "volatile");
|
"# : : "r"(addr) : : "volatile");
|
||||||
loop {}
|
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!()
|
||||||
|
}
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
pub mod boot;
|
pub mod boot;
|
||||||
|
pub mod pmp;
|
||||||
|
|
|
@ -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!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,6 @@ riscv = { version = "0.6.0", features = ["inline-asm"] }
|
||||||
|
|
||||||
[dependencies.fringe]
|
[dependencies.fringe]
|
||||||
git = "https://git.m-labs.hk/M-Labs/libfringe.git"
|
git = "https://git.m-labs.hk/M-Labs/libfringe.git"
|
||||||
rev = "9748bb"
|
rev = "3ecbe5"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc"]
|
features = ["alloc"]
|
||||||
|
|
|
@ -29,7 +29,7 @@ use core::cell::RefCell;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use smoltcp::wire::IpCidr;
|
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)]
|
#[cfg(has_ethmac)]
|
||||||
use board_misoc::ethmac;
|
use board_misoc::ethmac;
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
|
@ -40,7 +40,7 @@ use proto_artiq::{mgmt_proto, moninj_proto, rpc_proto, session_proto, kernel_pro
|
||||||
#[cfg(has_rtio_analyzer)]
|
#[cfg(has_rtio_analyzer)]
|
||||||
use proto_artiq::analyzer_proto;
|
use proto_artiq::analyzer_proto;
|
||||||
|
|
||||||
use riscv::register::{mcause, mepc};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
|
|
||||||
mod rtio_clocking;
|
mod rtio_clocking;
|
||||||
mod rtio_mgt;
|
mod rtio_mgt;
|
||||||
|
@ -247,10 +247,15 @@ pub extern fn main() -> i32 {
|
||||||
extern {
|
extern {
|
||||||
static mut _fheap: u8;
|
static mut _fheap: u8;
|
||||||
static mut _eheap: u8;
|
static mut _eheap: u8;
|
||||||
|
static mut _sstack_guard: u8;
|
||||||
}
|
}
|
||||||
ALLOC.add_range(&mut _fheap, &mut _eheap);
|
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
|
0
|
||||||
}
|
}
|
||||||
|
@ -285,6 +290,18 @@ pub extern fn exception(regs: *const TrapFrame) {
|
||||||
mcause::Trap::Interrupt(source) => {
|
mcause::Trap::Interrupt(source) => {
|
||||||
info!("Called interrupt with {:?}", 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) => {
|
mcause::Trap::Exception(e) => {
|
||||||
println!("Trap frame: {:x?}", unsafe { *regs });
|
println!("Trap frame: {:x?}", unsafe { *regs });
|
||||||
|
|
||||||
|
@ -302,7 +319,8 @@ pub extern fn exception(regs: *const TrapFrame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
hexdump(u32::try_from(pc).unwrap());
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,29 +4,66 @@ use board_artiq::si5324;
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use board_misoc::{csr, clock};
|
use board_misoc::{csr, clock};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
pub enum RtioClock {
|
pub enum RtioClock {
|
||||||
Internal = 0,
|
Default,
|
||||||
External = 1
|
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 {
|
fn get_rtio_clock_cfg() -> RtioClock {
|
||||||
config::read("rtio_clock", |result| {
|
config::read_str("rtio_clock", |result| {
|
||||||
match result {
|
let res = match result {
|
||||||
Ok(b"i") => {
|
Ok("int_125") => RtioClock::Int_125,
|
||||||
info!("using internal RTIO clock");
|
Ok("int_100") => RtioClock::Int_100,
|
||||||
RtioClock::Internal
|
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") => {
|
Ok("e") => {
|
||||||
info!("using external RTIO clock");
|
warn!("Using legacy rtio_clock setting ('e'). This will be deprecated.");
|
||||||
RtioClock::External
|
RtioClock::Ext0_Bypass
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
info!("using internal RTIO clock (by default)");
|
warn!("rtio_clock setting not recognised. Falling back to default.");
|
||||||
RtioClock::Internal
|
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)]
|
#[cfg(has_rtio_crg)]
|
||||||
|
@ -41,9 +78,23 @@ pub mod crg {
|
||||||
|
|
||||||
#[cfg(has_rtio_clock_switch)]
|
#[cfg(has_rtio_clock_switch)]
|
||||||
pub fn init(clk: RtioClock) -> bool {
|
pub fn init(clk: RtioClock) -> bool {
|
||||||
|
let clk_sel: u8 = match clk {
|
||||||
|
RtioClock::Ext0_Bypass => {
|
||||||
|
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 {
|
unsafe {
|
||||||
csr::rtio_crg::pll_reset_write(1);
|
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);
|
csr::rtio_crg::pll_reset_write(0);
|
||||||
}
|
}
|
||||||
clock::spin_us(150);
|
clock::spin_us(150);
|
||||||
|
@ -52,6 +103,7 @@ pub mod crg {
|
||||||
|
|
||||||
#[cfg(not(has_rtio_clock_switch))]
|
#[cfg(not(has_rtio_clock_switch))]
|
||||||
pub fn init() -> bool {
|
pub fn init() -> bool {
|
||||||
|
info!("Using internal RTIO clock");
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::rtio_crg::pll_reset_write(0);
|
csr::rtio_crg::pll_reset_write(0);
|
||||||
}
|
}
|
||||||
|
@ -66,11 +118,11 @@ pub mod crg {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(si5324_as_synthesizer)]
|
#[cfg(si5324_as_synthesizer)]
|
||||||
fn setup_si5324_as_synthesizer() {
|
fn setup_si5324_as_synthesizer(cfg: RtioClock) {
|
||||||
// 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW
|
let si5324_settings = match cfg {
|
||||||
#[cfg(all(rtio_frequency = "125.0", si5324_ext_ref, ext_ref_frequency = "10.0"))]
|
RtioClock::Ext0_Synth0_10to125 => { // 125 MHz output from 10 MHz CLKINx reference, 504 Hz BW
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
info!("using 10MHz reference to make 125MHz RTIO clock with PLL");
|
||||||
= si5324::FrequencySettings {
|
si5324::FrequencySettings {
|
||||||
n1_hs : 10,
|
n1_hs : 10,
|
||||||
nc1_ls : 4,
|
nc1_ls : 4,
|
||||||
n2_hs : 10,
|
n2_hs : 10,
|
||||||
|
@ -79,11 +131,11 @@ fn setup_si5324_as_synthesizer() {
|
||||||
n32 : 6,
|
n32 : 6,
|
||||||
bwsel : 4,
|
bwsel : 4,
|
||||||
crystal_ref: false
|
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"))]
|
RtioClock::Ext0_Synth0_100to125 => { // 125MHz output, from 100MHz CLKINx reference, 586 Hz loop bandwidth
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
info!("using 10MHz reference to make 125MHz RTIO clock with PLL");
|
||||||
= si5324::FrequencySettings {
|
si5324::FrequencySettings {
|
||||||
n1_hs : 10,
|
n1_hs : 10,
|
||||||
nc1_ls : 4,
|
nc1_ls : 4,
|
||||||
n2_hs : 10,
|
n2_hs : 10,
|
||||||
|
@ -92,11 +144,11 @@ fn setup_si5324_as_synthesizer() {
|
||||||
n32 : 52,
|
n32 : 52,
|
||||||
bwsel : 4,
|
bwsel : 4,
|
||||||
crystal_ref: false
|
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"))]
|
RtioClock::Ext0_Synth0_125to125 => { // 125MHz output, from 125MHz CLKINx reference, 606 Hz loop bandwidth
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
info!("using 10MHz reference to make 125MHz RTIO clock with PLL");
|
||||||
= si5324::FrequencySettings {
|
si5324::FrequencySettings {
|
||||||
n1_hs : 5,
|
n1_hs : 5,
|
||||||
nc1_ls : 8,
|
nc1_ls : 8,
|
||||||
n2_hs : 7,
|
n2_hs : 7,
|
||||||
|
@ -105,24 +157,11 @@ fn setup_si5324_as_synthesizer() {
|
||||||
n32 : 63,
|
n32 : 63,
|
||||||
bwsel : 4,
|
bwsel : 4,
|
||||||
crystal_ref: false
|
crystal_ref: false
|
||||||
};
|
}
|
||||||
// 125MHz output, from crystal, 7 Hz
|
},
|
||||||
#[cfg(all(rtio_frequency = "125.0", not(si5324_ext_ref)))]
|
RtioClock::Int_150 => { // 150MHz output, from crystal
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
info!("using internal 150MHz RTIO clock");
|
||||||
= 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,
|
n1_hs : 9,
|
||||||
nc1_ls : 4,
|
nc1_ls : 4,
|
||||||
n2_hs : 10,
|
n2_hs : 10,
|
||||||
|
@ -131,11 +170,11 @@ fn setup_si5324_as_synthesizer() {
|
||||||
n32 : 7139,
|
n32 : 7139,
|
||||||
bwsel : 3,
|
bwsel : 3,
|
||||||
crystal_ref: true
|
crystal_ref: true
|
||||||
};
|
}
|
||||||
// 100MHz output, from crystal. Also used as reference for Sayma HMC830.
|
},
|
||||||
#[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))]
|
RtioClock::Int_100 => { // 100MHz output, from crystal. Also used as reference for Sayma HMC830.
|
||||||
const SI5324_SETTINGS: si5324::FrequencySettings
|
info!("using internal 100MHz RTIO clock");
|
||||||
= si5324::FrequencySettings {
|
si5324::FrequencySettings {
|
||||||
n1_hs : 9,
|
n1_hs : 9,
|
||||||
nc1_ls : 6,
|
nc1_ls : 6,
|
||||||
n2_hs : 10,
|
n2_hs : 10,
|
||||||
|
@ -144,6 +183,34 @@ fn setup_si5324_as_synthesizer() {
|
||||||
n32 : 7139,
|
n32 : 7139,
|
||||||
bwsel : 3,
|
bwsel : 3,
|
||||||
crystal_ref: true
|
crystal_ref: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
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)))]
|
#[cfg(all(soc_platform = "kasli", hw_rev = "v2.0", not(si5324_ext_ref)))]
|
||||||
let si5324_ref_input = si5324::Input::Ckin2;
|
let si5324_ref_input = si5324::Input::Ckin2;
|
||||||
|
@ -155,10 +222,11 @@ fn setup_si5324_as_synthesizer() {
|
||||||
let si5324_ref_input = si5324::Input::Ckin2;
|
let si5324_ref_input = si5324::Input::Ckin2;
|
||||||
#[cfg(soc_platform = "kc705")]
|
#[cfg(soc_platform = "kc705")]
|
||||||
let si5324_ref_input = si5324::Input::Ckin2;
|
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() {
|
pub fn init() {
|
||||||
|
let clock_cfg = get_rtio_clock_cfg();
|
||||||
#[cfg(si5324_as_synthesizer)]
|
#[cfg(si5324_as_synthesizer)]
|
||||||
{
|
{
|
||||||
#[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))]
|
#[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))]
|
||||||
|
@ -169,9 +237,12 @@ pub fn init() {
|
||||||
let si5324_ext_input = si5324::Input::Ckin2;
|
let si5324_ext_input = si5324::Input::Ckin2;
|
||||||
#[cfg(soc_platform = "kc705")]
|
#[cfg(soc_platform = "kc705")]
|
||||||
let si5324_ext_input = si5324::Input::Ckin2;
|
let si5324_ext_input = si5324::Input::Ckin2;
|
||||||
match get_rtio_clock_cfg() {
|
match clock_cfg {
|
||||||
RtioClock::Internal => setup_si5324_as_synthesizer(),
|
RtioClock::Ext0_Bypass => {
|
||||||
RtioClock::External => si5324::bypass(si5324_ext_input).expect("cannot bypass Si5324")
|
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 +260,7 @@ pub fn init() {
|
||||||
#[cfg(has_rtio_crg)]
|
#[cfg(has_rtio_crg)]
|
||||||
{
|
{
|
||||||
#[cfg(has_rtio_clock_switch)]
|
#[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))]
|
#[cfg(not(has_rtio_clock_switch))]
|
||||||
let result = crg::init();
|
let result = crg::init();
|
||||||
if !result {
|
if !result {
|
||||||
|
|
|
@ -69,8 +69,11 @@ SECTIONS
|
||||||
_ebss = .;
|
_ebss = .;
|
||||||
} > runtime
|
} > runtime
|
||||||
|
|
||||||
.stack (NOLOAD) : ALIGN(16)
|
.stack (NOLOAD) : ALIGN(0x1000)
|
||||||
{
|
{
|
||||||
|
_sstack_guard = .;
|
||||||
|
. += 0x1000;
|
||||||
|
_estack = .;
|
||||||
. += 0x10000;
|
. += 0x10000;
|
||||||
_fstack = . - 16;
|
_fstack = . - 16;
|
||||||
} > runtime
|
} > runtime
|
||||||
|
|
|
@ -61,7 +61,8 @@ impl Thread {
|
||||||
let spawned = io.spawned.clone();
|
let spawned = io.spawned.clone();
|
||||||
let sockets = io.sockets.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 {
|
ThreadHandle::new(Thread {
|
||||||
generator: Generator::unsafe_new(stack, |yielder, _| {
|
generator: Generator::unsafe_new(stack, |yielder, _| {
|
||||||
f(Io {
|
f(Io {
|
||||||
|
|
|
@ -9,7 +9,7 @@ extern crate board_artiq;
|
||||||
extern crate riscv;
|
extern crate riscv;
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
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)]
|
#[cfg(has_si5324)]
|
||||||
use board_artiq::si5324;
|
use board_artiq::si5324;
|
||||||
#[cfg(has_wrpll)]
|
#[cfg(has_wrpll)]
|
||||||
|
@ -18,7 +18,7 @@ use board_artiq::{spi, drtioaux};
|
||||||
use board_artiq::drtio_routing;
|
use board_artiq::drtio_routing;
|
||||||
#[cfg(has_hmc830_7043)]
|
#[cfg(has_hmc830_7043)]
|
||||||
use board_artiq::hmc830_7043;
|
use board_artiq::hmc830_7043;
|
||||||
use riscv::register::{mcause, mepc};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
|
|
||||||
mod repeater;
|
mod repeater;
|
||||||
#[cfg(has_jdcg)]
|
#[cfg(has_jdcg)]
|
||||||
|
@ -449,6 +449,14 @@ const SI5324_SETTINGS: si5324::FrequencySettings
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn main() -> i32 {
|
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();
|
clock::init();
|
||||||
uart_logger::ConsoleLogger::register();
|
uart_logger::ConsoleLogger::register();
|
||||||
|
|
||||||
|
@ -662,7 +670,8 @@ pub extern fn exception(_regs: *const u32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
hexdump(u32::try_from(pc).unwrap());
|
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]
|
#[no_mangle]
|
||||||
|
|
|
@ -58,8 +58,10 @@ SECTIONS
|
||||||
_ebss = .;
|
_ebss = .;
|
||||||
} > main_ram
|
} > main_ram
|
||||||
|
|
||||||
.stack (NOLOAD) : ALIGN(16)
|
.stack (NOLOAD) : ALIGN(0x1000)
|
||||||
{
|
{
|
||||||
|
_sstack_guard = .;
|
||||||
|
. += 0x1000;
|
||||||
_estack = .;
|
_estack = .;
|
||||||
. += 0x10000;
|
. += 0x10000;
|
||||||
_fstack = . - 16;
|
_fstack = . - 16;
|
||||||
|
|
|
@ -418,8 +418,8 @@ def main():
|
||||||
magic = 0x5352544d # "SRTM", see sayma_rtm target
|
magic = 0x5352544d # "SRTM", see sayma_rtm target
|
||||||
length = bin_file.tell() - 8
|
length = bin_file.tell() - 8
|
||||||
bin_file.seek(0)
|
bin_file.seek(0)
|
||||||
bin_file.write(magic.to_bytes(4, byteorder="big"))
|
bin_file.write(magic.to_bytes(4, byteorder="little"))
|
||||||
bin_file.write(length.to_bytes(4, byteorder="big"))
|
bin_file.write(length.to_bytes(4, byteorder="little"))
|
||||||
atexit.register(lambda: os.unlink(bin_filename))
|
atexit.register(lambda: os.unlink(bin_filename))
|
||||||
return bin_filename
|
return bin_filename
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,10 @@ def get_argparser():
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"-r", "--repository", default="repository",
|
"-r", "--repository", default="repository",
|
||||||
help="path to the repository (default: '%(default)s')")
|
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)
|
log_args(parser)
|
||||||
|
|
||||||
|
@ -104,7 +108,8 @@ def main():
|
||||||
repo_backend = GitBackend(args.repository)
|
repo_backend = GitBackend(args.repository)
|
||||||
else:
|
else:
|
||||||
repo_backend = FilesystemBackend(args.repository)
|
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)
|
atexit.register(experiment_db.close)
|
||||||
|
|
||||||
scheduler = Scheduler(RIDCounter(), worker_handlers, experiment_db)
|
scheduler = Scheduler(RIDCounter(), worker_handlers, experiment_db)
|
||||||
|
|
|
@ -27,16 +27,16 @@ class Fastino(Module):
|
||||||
|
|
||||||
# dac data words
|
# dac data words
|
||||||
dacs = [Signal(16) for i in range(32)]
|
dacs = [Signal(16) for i in range(32)]
|
||||||
|
|
||||||
header = Record([
|
header = Record([
|
||||||
("cfg", 4),
|
("cfg", 4),
|
||||||
("leds", 8),
|
("leds", 8),
|
||||||
("reserved", 8),
|
("typ", 1),
|
||||||
|
("reserved", 7),
|
||||||
("addr", 4),
|
("addr", 4),
|
||||||
("enable", len(dacs)),
|
("enable", len(dacs)),
|
||||||
])
|
])
|
||||||
body = Cat(header.raw_bits(), dacs)
|
assert len(Cat(header.raw_bits(), dacs)) == len(self.serializer.payload)
|
||||||
assert len(body) == len(self.serializer.payload)
|
|
||||||
self.comb += self.serializer.payload.eq(body)
|
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
@ -62,38 +62,61 @@ class Fastino(Module):
|
||||||
# address space is sparse.
|
# address space is sparse.
|
||||||
|
|
||||||
hold = Signal.like(header.enable)
|
hold = Signal.like(header.enable)
|
||||||
|
continuous = Signal.like(header.enable)
|
||||||
|
cic_config = Signal(16)
|
||||||
|
|
||||||
read_regs = Array([Signal.like(self.serializer.readback)
|
read_regs = Array([Signal.like(self.serializer.readback)
|
||||||
for _ in range(1 << len(header.addr))])
|
for _ in range(1 << len(header.addr))])
|
||||||
|
|
||||||
cases = {
|
cases = {
|
||||||
# update
|
# update
|
||||||
0x20: header.enable.eq(header.enable | self.rtlink.o.data),
|
0x20: [
|
||||||
|
header.enable.eq(self.rtlink.o.data),
|
||||||
|
header.typ.eq(0),
|
||||||
|
],
|
||||||
# hold
|
# hold
|
||||||
0x21: hold.eq(self.rtlink.o.data),
|
0x21: hold.eq(self.rtlink.o.data),
|
||||||
# cfg
|
# cfg
|
||||||
0x22: header.cfg.eq(self.rtlink.o.data),
|
0x22: header.cfg.eq(self.rtlink.o.data),
|
||||||
# leds
|
# leds
|
||||||
0x23: header.leds.eq(self.rtlink.o.data),
|
0x23: header.leds.eq(self.rtlink.o.data),
|
||||||
# reserved
|
# reserved bits
|
||||||
0x24: header.reserved.eq(self.rtlink.o.data),
|
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):
|
for i in range(0, len(dacs), width):
|
||||||
cases[i] = [
|
cases[i] = [
|
||||||
Cat(dacs[i:i + width]).eq(self.rtlink.o.data),
|
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),
|
header.enable[i + j].eq(1),
|
||||||
) for j in range(width)]
|
) 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 += [
|
self.sync.rio_phy += [
|
||||||
If(self.serializer.stb,
|
If(self.serializer.stb,
|
||||||
header.enable.eq(0),
|
header.typ.eq(0),
|
||||||
|
header.enable.eq(continuous),
|
||||||
read_regs[header.addr].eq(self.serializer.readback),
|
read_regs[header.addr].eq(self.serializer.readback),
|
||||||
header.addr.eq(header.addr + 1),
|
header.addr.eq(header.addr + 1),
|
||||||
),
|
),
|
||||||
If(self.rtlink.o.stb & ~self.rtlink.o.address[-1],
|
If(self.rtlink.o.stb,
|
||||||
Case(self.rtlink.o.address[:-1], cases),
|
Case(self.rtlink.o.address, cases),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ class SatmanSoCBuilder(Builder):
|
||||||
"satman.bin")
|
"satman.bin")
|
||||||
with open(satman, "rb") as boot_file:
|
with open(satman, "rb") as boot_file:
|
||||||
boot_data = []
|
boot_data = []
|
||||||
unpack_endian = ">I"
|
unpack_endian = "<I"
|
||||||
while True:
|
while True:
|
||||||
w = boot_file.read(4)
|
w = boot_file.read(4)
|
||||||
if not w:
|
if not w:
|
||||||
|
|
|
@ -74,19 +74,20 @@ class _RepoScanner:
|
||||||
entry_dict.update(entries)
|
entry_dict.update(entries)
|
||||||
return entry_dict
|
return entry_dict
|
||||||
|
|
||||||
async def scan(self, root):
|
async def scan(self, root, subdir=""):
|
||||||
self.worker = Worker(self.worker_handlers)
|
self.worker = Worker(self.worker_handlers)
|
||||||
try:
|
try:
|
||||||
r = await self._scan(root)
|
r = await self._scan(root, subdir)
|
||||||
finally:
|
finally:
|
||||||
await self.worker.close()
|
await self.worker.close()
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
class ExperimentDB:
|
class ExperimentDB:
|
||||||
def __init__(self, repo_backend, worker_handlers):
|
def __init__(self, repo_backend, worker_handlers, experiment_subdir=""):
|
||||||
self.repo_backend = repo_backend
|
self.repo_backend = repo_backend
|
||||||
self.worker_handlers = worker_handlers
|
self.worker_handlers = worker_handlers
|
||||||
|
self.experiment_subdir = experiment_subdir
|
||||||
|
|
||||||
self.cur_rev = self.repo_backend.get_head_rev()
|
self.cur_rev = self.repo_backend.get_head_rev()
|
||||||
self.repo_backend.request_rev(self.cur_rev)
|
self.repo_backend.request_rev(self.cur_rev)
|
||||||
|
@ -115,7 +116,8 @@ class ExperimentDB:
|
||||||
self.cur_rev = new_cur_rev
|
self.cur_rev = new_cur_rev
|
||||||
self.status["cur_rev"] = new_cur_rev
|
self.status["cur_rev"] = new_cur_rev
|
||||||
t1 = time.monotonic()
|
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)
|
logger.info("repository scan took %d seconds", time.monotonic()-t1)
|
||||||
update_from_dict(self.explist, new_explist)
|
update_from_dict(self.explist, new_explist)
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -164,6 +164,19 @@ See :mod:`artiq.coredevice.i2c` for more details.
|
||||||
Clocking
|
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.
|
||||||
|
|
|
@ -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)
|
* 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 int_125 # internal 125MHz clock (default)
|
||||||
$ artiq_coremgmt config write -s rtio_clock e # external clock
|
$ 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.
|
20
flake.lock
20
flake.lock
|
@ -18,11 +18,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1633621759,
|
"lastModified": 1634758644,
|
||||||
"narHash": "sha256-Mw29zuYjOozICTWsc9RvjuR7hW5D0H83onQh/WoVrMs=",
|
"narHash": "sha256-H3UW/msC6wadg28lcgZv2Ge/P7dWxesL6i37a0GOeyM=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "6755a884b24038a73dd4c8022dbb05375feef0a7",
|
"rev": "70904d4a9927a4d6e05c72c4aaac4370e05107f3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -44,11 +44,11 @@
|
||||||
"src-migen": {
|
"src-migen": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1633615575,
|
"lastModified": 1634182166,
|
||||||
"narHash": "sha256-frh+WVOkEKMpVEMhdE/GZKSj82XnSC8OF8SWNluk/Yg=",
|
"narHash": "sha256-Iw2d8fCgwuuIevkugSqd8Iplj6N+2nR1pn+or5E38Fk=",
|
||||||
"owner": "m-labs",
|
"owner": "m-labs",
|
||||||
"repo": "migen",
|
"repo": "migen",
|
||||||
"rev": "6e3f8e565704b4293174aedfb15b3470d233f528",
|
"rev": "7507a2bb16dd2cac63535175ce67fb30dfdae1c0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -60,11 +60,11 @@
|
||||||
"src-misoc": {
|
"src-misoc": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1631240866,
|
"lastModified": 1634799783,
|
||||||
"narHash": "sha256-dal999XLFvS8Ol1hZnQjx7q/UfAXkzSMhAWcZKCDPx4=",
|
"narHash": "sha256-CbeXsLTwwYBWb5cfrVVYkcQYV207gi9+CQhzfeZbXGc=",
|
||||||
"ref": "master",
|
"ref": "master",
|
||||||
"rev": "c9572e777febf7abcfbebf624e0323d82600f267",
|
"rev": "855914deace34880c69589022c52a8921f431063",
|
||||||
"revCount": 2371,
|
"revCount": 2375,
|
||||||
"submodules": true,
|
"submodules": true,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/m-labs/misoc.git"
|
"url": "https://github.com/m-labs/misoc.git"
|
||||||
|
|
36
flake.nix
36
flake.nix
|
@ -42,6 +42,8 @@
|
||||||
xorg.libXext
|
xorg.libXext
|
||||||
xorg.libXtst
|
xorg.libXtst
|
||||||
xorg.libXi
|
xorg.libXi
|
||||||
|
freetype
|
||||||
|
fontconfig
|
||||||
];
|
];
|
||||||
|
|
||||||
sipyco = pkgs.python3Packages.buildPythonPackage {
|
sipyco = pkgs.python3Packages.buildPythonPackage {
|
||||||
|
@ -125,6 +127,30 @@
|
||||||
propagatedBuildInputs = with pkgs.python3Packages; [ jinja2 numpy migen pyserial asyncserial ];
|
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 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
cargo-xbuild = rustPlatform.buildRustPackage rec {
|
||||||
pname = "cargo-xbuild";
|
pname = "cargo-xbuild";
|
||||||
version = "0.6.5";
|
version = "0.6.5";
|
||||||
|
@ -147,7 +173,7 @@
|
||||||
vivado = pkgs.buildFHSUserEnv {
|
vivado = pkgs.buildFHSUserEnv {
|
||||||
name = "vivado";
|
name = "vivado";
|
||||||
targetPkgs = vivadoDeps;
|
targetPkgs = vivadoDeps;
|
||||||
profile = "source /opt/Xilinx/Vivado/2020.1/settings64.sh";
|
profile = "source /opt/Xilinx/Vivado/2021.1/settings64.sh";
|
||||||
runScript = "vivado";
|
runScript = "vivado";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,7 +184,7 @@
|
||||||
cargoDeps = rustPlatform.fetchCargoTarball {
|
cargoDeps = rustPlatform.fetchCargoTarball {
|
||||||
name = "artiq-firmware-cargo-deps";
|
name = "artiq-firmware-cargo-deps";
|
||||||
src = "${self}/artiq/firmware";
|
src = "${self}/artiq/firmware";
|
||||||
sha256 = "0hh9x34gs81a8g15abka6a0z1wlankra13rbap5j7ba2r8cz4962";
|
sha256 = "sha256-Lf6M4M/jdRiO5MsWSoqtOSNfRIhbze+qvg4kaiiBWW4=";
|
||||||
};
|
};
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
(pkgs.python3.withPackages(ps: [ migen misoc artiq ]))
|
(pkgs.python3.withPackages(ps: [ migen misoc artiq ]))
|
||||||
|
@ -180,7 +206,9 @@
|
||||||
export TARGET_AR=llvm-ar
|
export TARGET_AR=llvm-ar
|
||||||
${buildCommand}
|
${buildCommand}
|
||||||
'';
|
'';
|
||||||
checkPhase = ''
|
doCheck = true;
|
||||||
|
checkPhase =
|
||||||
|
''
|
||||||
# Search for PCREs in the Vivado output to check for errors
|
# Search for PCREs in the Vivado output to check for errors
|
||||||
check_log() {
|
check_log() {
|
||||||
grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true
|
grep -Pe "$1" artiq_${target}/${variant}/gateware/vivado.log && exit 1 || true
|
||||||
|
@ -277,7 +305,7 @@
|
||||||
devShell.x86_64-linux = pkgs.mkShell {
|
devShell.x86_64-linux = pkgs.mkShell {
|
||||||
name = "artiq-dev-shell";
|
name = "artiq-dev-shell";
|
||||||
buildInputs = [
|
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 microscope ]))
|
||||||
rustPlatform.rust.rustc
|
rustPlatform.rust.rustc
|
||||||
rustPlatform.rust.cargo
|
rustPlatform.rust.cargo
|
||||||
cargo-xbuild
|
cargo-xbuild
|
||||||
|
|
Loading…
Reference in New Issue