{- | Module: Probes Description: Example usage of probes in Atom Copyright: (c) 2015 Chris Hodapp This demonstrates the usage of Atom's probe functionality. In this case, it simply uses @printf@ to log a probe's value. Most POSIX systems should be able to build and run the generated C code. -} module Language.Atom.Example.Probes where import Data.Word import Language.Atom -- | Invoke the Atom compiler main :: IO () main = do let atomCfg = defaults { cCode = prePostCode , cRuleCoverage = False } (sched, _, _, _, _) <- compile "probe_example" atomCfg example putStrLn $ reportSchedule sched -- | Generate a code comment about the given probe. probeStr :: (Name, Type) -> String probeStr (n, t) = "// Probe: " ++ n ++ ", type: " ++ show t -- | Use 'action' to call @PROBE_PRINTF@ on a probe given as (name, value). -- This will work only on integer-valued probes. logProbe :: (String, UE) -> Atom () logProbe (str, ue_) = action probeFn [ue_] where probeFn v = "PROBE_PRINTF(\"%u, " ++ str ++ ": %i\\n\", __global_clock, " ++ head v ++ ")" -- | Top-level rule example :: Atom () example = do -- Include in the once-per-second clock: sec <- tickSecond -- Compute minutes and hours as well (probes take arbitrary expressions): probe "Minutes" $ (value sec) `div_` 60 probe "Hours" $ (value sec) `div_` 3600 -- At 1/200 of our base rate (~ 5 seconds), we call 'logProbe' on all of the -- probes that are in use. period 200 $ atom "monitor" $ do mapM_ logProbe =<< probes prePostCode :: [Name] -> [Name] -> [(Name, Type)] -> (String, String) prePostCode _ _ probeList = ( unlines $ [ "// ---- This source is automatically generated by Atom ----" , "#define PROBE_PRINTF printf" , "#include " , "#include " , "#include " ] ++ map probeStr probeList -- Basic stub to call with a 1 millisecond delay (do not attempt anything like -- this in production - use an interrupt): , unlines [ "int main(void) {" , " while (true) {" , " probe_example();" , " usleep(1000);" , " }" , " return 0;" , "}" , "// ---- End automatically-generated source ----" ]) -- | Count up seconds of runtime, assuming our base rate is 1 millisecond: tickSecond :: Atom (V Word64) tickSecond = do sec <- word64 "seconds" 0 -- Add a probe to the clock: probe "Seconds" $ value sec period 1000 $ exactPhase 0 $ atom "second" $ incr sec return sec