Skip to content

Commit 0da4f4b

Browse files
Allow clock control to work independently of links (#1114)
1 parent 3d3071d commit 0da4f4b

8 files changed

Lines changed: 74 additions & 50 deletions

File tree

firmware-binaries/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

firmware-binaries/demos/clock-control/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ riscv-rt = "0.11.0"
1616
bittide-sys = { path = "../../../firmware-support/bittide-sys" }
1717
bittide-hal = { path = "../../../firmware-support/bittide-hal" }
1818
ufmt = "0.2.0"
19+
itertools = { version = "0.14.0", default-features = false }
1920

2021
[build-dependencies]
2122
memmap-generate = { path = "../../../firmware-support/memmap-generate" }

firmware-binaries/demos/clock-control/src/main.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// SPDX-License-Identifier: Apache-2.0
77

88
use core::panic::PanicInfo;
9+
use itertools::izip;
910

1011
use bittide_hal::manual_additions::timer::Duration;
1112
use bittide_hal::manual_additions::timer::Instant;
@@ -37,19 +38,6 @@ fn main() -> ! {
3738
uwriteln!(uart, "Starting sync out generator..").unwrap();
3839
sync_out_generator.set_active(true);
3940

40-
uwriteln!(uart, "Waiting for at least one pulse..").unwrap();
41-
while freeze.number_of_sync_pulses_seen() == 0 {
42-
// TOOD: Memory map sync pulse counter -- no need to involve freeze here
43-
freeze.set_freeze(());
44-
}
45-
46-
// XXX: CPU is booted after all links are available, so we can blindly enable
47-
// all counters.
48-
uwriteln!(uart, "Starting domain diff counters..").unwrap();
49-
for i in 0..DomainDiffCounters::ENABLE_LEN {
50-
domain_diff_counters.set_enable(i, true);
51-
}
52-
5341
uwriteln!(uart, "Starting clock control..").unwrap();
5442
let mut callisto = Callisto::new(cc.config().callisto);
5543

@@ -67,16 +55,34 @@ fn main() -> ! {
6755
let mut prev_all_stable = false;
6856

6957
loop {
70-
// Do clock control on "frozen" counters
58+
// Store frozen elastic buffer counters
7159
freeze.set_freeze(());
72-
cc.set_change_speed(callisto.update(&cc, freeze.eb_counters_volatile_iter()));
60+
61+
// Do clock control update
62+
cc.set_change_speed(
63+
callisto.update(
64+
&cc,
65+
izip!(
66+
0..DomainDiffCounters::ENABLE_LEN,
67+
freeze.eb_counters_volatile_iter()
68+
)
69+
.map(|(i, counter)| {
70+
if domain_diff_counters.enable(i).unwrap_or(false) {
71+
Some(counter)
72+
} else {
73+
None
74+
}
75+
}),
76+
),
77+
);
7378

7479
// Detect stability
7580
let stability = stability_detector.update(&cc, timer.now());
7681

7782
// Store debug information. Stop capturing samples if we are stable to
7883
// reduce plot sizes.
79-
if !prev_all_stable {
84+
let has_sense_of_global_time = freeze.number_of_sync_pulses_seen() != 0;
85+
if !prev_all_stable && has_sense_of_global_time {
8086
sample_store.store(&freeze, stability, callisto.accumulated_speed_requests);
8187
}
8288

@@ -90,6 +96,13 @@ fn main() -> ! {
9096
}
9197
prev_all_stable = all_stable;
9298

99+
// Update active domain difference counters based on which links are
100+
// enabled.
101+
let link_mask_rev = cc.link_mask_rev();
102+
for i in 0..DomainDiffCounters::ENABLE_LEN {
103+
domain_diff_counters.set_enable(i, test_bit(link_mask_rev, i));
104+
}
105+
93106
// Wait for next update
94107
let timer_result = timer.wait_until_stall(next_update);
95108
panic_on_missed_deadline(&mut uart, &timer, next_update, timer_result);
@@ -115,6 +128,11 @@ fn panic_on_missed_deadline(
115128
};
116129
}
117130

131+
/// Test whether the `i`-th bit in `bv` is set.
132+
fn test_bit(bv: u8, i: usize) -> bool {
133+
(bv & (1 << i)) != 0
134+
}
135+
118136
#[panic_handler]
119137
fn panic_handler(_info: &PanicInfo) -> ! {
120138
loop {

firmware-binaries/demos/switch-demo1-boot/src/main.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::panic::PanicInfo;
99
use ufmt::uwriteln;
1010

1111
use bittide_hal::manual_additions::si539x_spi::{Config, WriteError};
12-
use bittide_hal::shared_devices::transceivers::Transceivers;
12+
use bittide_hal::shared_devices::Transceivers;
1313
use bittide_hal::switch_demo_boot::DeviceInstances;
1414
use bittide_macros::load_clock_config_csv;
1515

@@ -49,21 +49,12 @@ fn main() -> ! {
4949

5050
uwriteln!(uart, "Enabling bittide domain..").unwrap();
5151
transceivers.set_transceiver_enable(true);
52-
uwriteln!(uart, "Done.").unwrap();
5352

5453
uwriteln!(uart, "Enabling all transceiver channels..").unwrap();
5554
for channel in 0..Transceivers::CHANNEL_ENABLES_LEN {
5655
transceivers.set_channel_enables(channel, true);
5756
}
5857

59-
for channel in 0..Transceivers::HANDSHAKES_DONE_LEN {
60-
while !transceivers.handshakes_done(channel).unwrap_or(false) {}
61-
uwriteln!(uart, "Channel {} handshake done.", channel).unwrap();
62-
uwriteln!(uart, "{:?}", transceivers.statistics(channel)).unwrap();
63-
}
64-
65-
uwriteln!(uart, "Done.").unwrap();
66-
6758
uwriteln!(uart, "Going into infinite loop..").unwrap();
6859
#[allow(clippy::empty_loop)]
6960
loop {}

firmware-binaries/demos/switch-demo1-mu/src/main.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ fn main() -> ! {
1919
let mut uart = INSTANCES.uart;
2020
let transceivers = &INSTANCES.transceivers;
2121

22-
uwriteln!(uart, "Hello from management unit..").unwrap();
22+
// Channels should be enabled by boot program, so we can simply wait here
23+
uwriteln!(uart, "Waiting for channel negotiations..").unwrap();
24+
for channel in 0..Transceivers::HANDSHAKES_DONE_LEN {
25+
while !transceivers.handshakes_done(channel).unwrap_or(false) {}
26+
uwriteln!(uart, "Channel {} negotiation done.", channel).unwrap();
27+
uwriteln!(uart, "{:?}", transceivers.statistics(channel)).unwrap();
28+
}
2329

2430
uwriteln!(uart, "Centering buffer occupancies").unwrap();
2531
for (i, eb) in [

firmware-binaries/demos/switch-demo2-mu/src/main.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ fn main() -> ! {
1919
let mut uart = INSTANCES.uart;
2020
let transceivers = &INSTANCES.transceivers;
2121

22-
uwriteln!(uart, "Hello from management unit..").unwrap();
22+
// Channels should be enabled by boot program, so we can simply wait here
23+
uwriteln!(uart, "Waiting for channel negotiations..").unwrap();
24+
for channel in 0..Transceivers::HANDSHAKES_DONE_LEN {
25+
while !transceivers.handshakes_done(channel).unwrap_or(false) {}
26+
uwriteln!(uart, "Channel {} negotiation done.", channel).unwrap();
27+
uwriteln!(uart, "{:?}", transceivers.statistics(channel)).unwrap();
28+
}
2329

2430
uwriteln!(uart, "Centering buffer occupancies").unwrap();
2531
for (i, eb) in [

firmware-support/bittide-sys/src/callisto.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,14 @@ impl Callisto {
6060
/// [https://github.com/bittide/Callisto.jl](https://github.com/bittide/Callisto.jl)
6161
pub fn update<I>(self: &mut Callisto, cc: &ClockControl, eb_counters_iter: I) -> SpeedChange
6262
where
63-
I: Iterator<Item = i32>,
63+
I: Iterator<Item = Option<i32>>,
6464
{
6565
// `fStep` should match the step size of the clock boards. For all our HITL
6666
// tests this is set by `HwCcTopologies.commonStepSizeSelect`.
6767
const FSTEP: f32 = 10e-9; // 10 PPB
6868

69-
let link_mask_rev = cc.link_mask_rev();
70-
7169
// Sum the data counts for all active links
72-
let measured_sum: i32 = eb_counters_iter
73-
.enumerate()
74-
.map(|(i, v)| if test_bit(link_mask_rev, i) { v } else { 0 })
75-
.sum();
70+
let measured_sum: i32 = eb_counters_iter.flatten().sum();
7671

7772
let c_des = self.config.gain * (measured_sum as f32) + self.steady_state_target;
7873
let c_est = FSTEP * self.accumulated_speed_requests as f32;
@@ -128,8 +123,3 @@ fn speed_change_to_sign(speed_change: SpeedChange) -> i32 {
128123
SpeedChange::SpeedUp => 1,
129124
}
130125
}
131-
132-
/// Test whether the `i`-th bit in `bv` is set.
133-
fn test_bit(bv: u8, i: usize) -> bool {
134-
(bv & (1 << i)) != 0
135-
}

firmware-support/bittide-sys/src/stability_detector.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ use bittide_hal::{
99
use itertools::izip;
1010
use ufmt::derive::uDebug;
1111

12+
fn test_bit(bv: u8, i: usize) -> bool {
13+
(bv & (1 << i)) != 0
14+
}
15+
1216
pub struct StabilityDetector {
1317
/// Reference data counts -- sampled at some point in time and used to
1418
/// compare against the current data counts to determine stability.
@@ -61,21 +65,28 @@ impl StabilityDetector {
6165
pub fn update(&mut self, cc: &ClockControl, now: Instant) -> Stability {
6266
let mut stables: u32 = 0;
6367
let mut settleds: u32 = 0;
68+
let link_mask_rev = cc.link_mask_rev();
6469

65-
for (data_count_stored, maybe_start, data_count, min_seen, max_seen, prev_stable) in izip!(
66-
self.data_counts.iter_mut(),
67-
self.starts.iter_mut(),
68-
cc.data_counts_volatile_iter(),
69-
cc.min_data_counts_seen_volatile_iter(),
70-
cc.max_data_counts_seen_volatile_iter(),
71-
self.prev_stabilities.iter_mut()
72-
) {
70+
for (i, (data_count_stored, maybe_start, data_count, min_seen, max_seen, prev_stable)) in
71+
izip!(
72+
self.data_counts.iter_mut(),
73+
self.starts.iter_mut(),
74+
cc.data_counts_volatile_iter(),
75+
cc.min_data_counts_seen_volatile_iter(),
76+
cc.max_data_counts_seen_volatile_iter(),
77+
self.prev_stabilities.iter_mut()
78+
)
79+
.enumerate()
80+
{
81+
let active = test_bit(link_mask_rev, i);
7382
let diff0 = data_count_stored.abs_diff(min_seen);
7483
let diff1 = data_count_stored.abs_diff(max_seen);
7584
let height_violated = diff0 > self.margin || diff1 > self.margin;
7685

77-
let (stable, settled) = if height_violated {
78-
// Reset everything, as we violated the window height
86+
let (stable, settled) = if height_violated || !active {
87+
// Reset everything, as we violated the window height or if this
88+
// link is inactive. The latter prevents inactive links from
89+
// being considered stable.
7990
*maybe_start = Some(now);
8091
*data_count_stored = data_count;
8192
cc.set_clear_data_counts_seen(true);

0 commit comments

Comments
 (0)