From 37b474428f09e125d8515cf33e03e6d629d67a3a Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Sat, 16 Feb 2019 23:24:21 +0100 Subject: [PATCH] clk derive and proof improved --- klee-examples/src/clk.rs | 54 +++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/klee-examples/src/clk.rs b/klee-examples/src/clk.rs index e17bff0..d8b689d 100644 --- a/klee-examples/src/clk.rs +++ b/klee-examples/src/clk.rs @@ -30,34 +30,29 @@ pub struct Unknowns { pllq: u32, } -fn pll_derive() -> Unknowns { - // pll input default to HSI - - let pllsrcclk = 8_000_000; - - // desired system clock, default to pll input - let sysclk = 96_000_000; +fn pll_derive(req: Requirements) -> Unknowns { + // assertions on requirements + kassert!(req.pllsrcclk % 1_000_000 == 0); // Multiple of 1MHz + kassert!(4_000_000 <= req.pllsrcclk && req.pllsrcclk <= 26_000_000); // Multiple of 1MHz + kassert!(req.sysclk % 1_000_000 == 0); // Multiple of 1MHz // Sysclk output divisor must be one of 2, 4, 6 or 8 // (&!1 implies even numbers) - let pllp = core::cmp::min(8, (432_000_000 / sysclk) & !1); + let pllp = core::cmp::min(8, (432_000_000 / req.sysclk) & !1); - // Input divisor from PLL source clock, must result to frequency in - // the range from 1 to 2 MHz let mut pllm: u32 = 0; ksymbol!(&mut pllm, "pllm"); - kassume(pllm > 0); + kassume(1 < pllm && pllm < 64); // field constraint - // require multiples of 1 MHz - kassume(1_000_000 <= pllsrcclk / pllm && pllsrcclk / pllm <= 2_000_000); - // only 4Mz..=26Mz allowed - kassume(4 <= pllm && pllm <= 26); + // Oscillator input constraint in the range from 1 to 2 MHz + kassume(1_000_000 <= req.pllsrcclk / pllm && req.pllsrcclk / pllm <= 2_000_000); // Main scaler, - let plln = sysclk * pllp / (pllsrcclk / pllm); - assert!(50 <= plln && plln <= 432); // constraint according to data sheet + let plln = req.sysclk * pllp / (req.pllsrcclk / pllm); + assert!(50 <= plln && plln <= 432); // field constraint - let osc = (pllsrcclk / pllm) * plln; + // Oscillator output constraint + let osc = (req.pllsrcclk / pllm) * plln; // 100MHz <= OSC <= 432MHz kassume(100_000_000 <= osc && osc <= 432_000_000); @@ -65,13 +60,20 @@ fn pll_derive() -> Unknowns { // kassume(192_000_000 <= osc && osc <= 432_000_000); // compute USB clock - // 1-2MHz * plln / pllq = 48Mhz - let pllq = (pllsrcclk / pllm) * plln / 48_000_000; + // OSC / pllq = 48Mhz + let pllq = if req.usbclk { + let pllq = osc / 48_000_000; + kassume(osc / pllq == 48_000_000); // soundness + kassume(1 < pllq && pllq < 16); // field constraint + pllq + } else { + 2 // set a valid value + }; // Calculate real system clock - let sysclk_real = (pllsrcclk / pllm) * plln / pllp; + let sysclk_real = osc / pllp; - kassume(sysclk_real == sysclk); + kassume(sysclk_real == req.sysclk); Unknowns { pllp, @@ -94,7 +96,13 @@ fn main() { ksymbol!(&mut plln, "plln"); ksymbol!(&mut pllq, "pllq"); - let u = pll_derive(); + let req = Requirements { + pllsrcclk: 8_000_000, + sysclk: 96_000_000, + usbclk: true, + }; + + let u = pll_derive(req); kassume(pllp == u.pllp); // kassume(pll_in == u.pll_in); kassume(pllm == u.pllm); -- GitLab