2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-25 11:18:27 +08:00

Merge branch 'master' into nac3

This commit is contained in:
Sebastien Bourdeauducq 2021-11-03 21:37:18 +08:00
commit 977543e05a
25 changed files with 495 additions and 154 deletions

View File

@ -24,6 +24,10 @@ 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.
* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage
of compile-time options.
Breaking changes:

View File

@ -3,7 +3,7 @@ streaming DAC.
"""
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,
rtio_input_data)
from artiq.language.units import us
@ -191,3 +191,82 @@ 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 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)

View File

@ -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,

View File

@ -163,7 +163,7 @@ 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",
]

View File

@ -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]

View File

@ -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();
@ -530,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]

View File

@ -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!()
}

View File

@ -1,2 +1,3 @@
pub mod cache;
pub mod boot;
pub mod pmp;

View File

@ -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!()
}
}

View File

@ -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"]

View File

@ -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)]
@ -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;
@ -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
}
@ -285,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 });
@ -302,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)
}
}
}

View File

@ -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,23 @@ 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
},
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 {
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 +103,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 +118,99 @@ 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
}
},
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)))]
let si5324_ref_input = si5324::Input::Ckin2;
@ -155,10 +222,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 +237,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 +260,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 {

View File

@ -69,8 +69,11 @@ SECTIONS
_ebss = .;
} > runtime
.stack (NOLOAD) : ALIGN(16)
.stack (NOLOAD) : ALIGN(0x1000)
{
_sstack_guard = .;
. += 0x1000;
_estack = .;
. += 0x10000;
_fstack = . - 16;
} > runtime

View File

@ -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 {

View File

@ -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)]
@ -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)]
@ -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();
@ -662,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]

View File

@ -58,8 +58,10 @@ SECTIONS
_ebss = .;
} > main_ram
.stack (NOLOAD) : ALIGN(16)
.stack (NOLOAD) : ALIGN(0x1000)
{
_sstack_guard = .;
. += 0x1000;
_estack = .;
. += 0x10000;
_fstack = . - 16;

View File

@ -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

View File

@ -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)

View File

@ -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),
),
]

View File

@ -240,7 +240,7 @@ class SatmanSoCBuilder(Builder):
"satman.bin")
with open(satman, "rb") as boot_file:
boot_data = []
unpack_endian = ">I"
unpack_endian = "<I"
while True:
w = boot_file.read(4)
if not w:

View File

@ -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:

View File

@ -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.

View File

@ -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.

20
flake.lock generated
View File

@ -18,11 +18,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1633621759,
"narHash": "sha256-Mw29zuYjOozICTWsc9RvjuR7hW5D0H83onQh/WoVrMs=",
"lastModified": 1634758644,
"narHash": "sha256-H3UW/msC6wadg28lcgZv2Ge/P7dWxesL6i37a0GOeyM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6755a884b24038a73dd4c8022dbb05375feef0a7",
"rev": "70904d4a9927a4d6e05c72c4aaac4370e05107f3",
"type": "github"
},
"original": {
@ -44,11 +44,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": {
@ -60,11 +60,11 @@
"src-misoc": {
"flake": false,
"locked": {
"lastModified": 1631240866,
"narHash": "sha256-dal999XLFvS8Ol1hZnQjx7q/UfAXkzSMhAWcZKCDPx4=",
"lastModified": 1634799783,
"narHash": "sha256-CbeXsLTwwYBWb5cfrVVYkcQYV207gi9+CQhzfeZbXGc=",
"ref": "master",
"rev": "c9572e777febf7abcfbebf624e0323d82600f267",
"revCount": 2371,
"rev": "855914deace34880c69589022c52a8921f431063",
"revCount": 2375,
"submodules": true,
"type": "git",
"url": "https://github.com/m-labs/misoc.git"

View File

@ -42,6 +42,8 @@
xorg.libXext
xorg.libXtst
xorg.libXi
freetype
fontconfig
];
sipyco = pkgs.python3Packages.buildPythonPackage {
@ -125,6 +127,30 @@
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 {
pname = "cargo-xbuild";
version = "0.6.5";
@ -147,7 +173,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";
};
@ -158,7 +184,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 ]))
@ -180,7 +206,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
@ -277,7 +305,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 microscope ]))
rustPlatform.rust.rustc
rustPlatform.rust.cargo
cargo-xbuild